* [PATCH v3 0/3] KVM: s390: Use ESCA instead of BSCA at VM init
@ 2025-05-22 9:31 Christoph Schlameuss
2025-05-22 9:31 ` [PATCH v3 1/3] KVM: s390: Set KVM_MAX_VCPUS to 256 Christoph Schlameuss
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Christoph Schlameuss @ 2025-05-22 9:31 UTC (permalink / raw)
To: kvm
Cc: linux-s390, Christian Borntraeger, Janosch Frank,
Claudio Imbrenda, David Hildenbrand, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Thomas Huth,
Christoph Schlameuss
All modern IBM Z and Linux One machines do offer support for the
Extended System Control Area (ESCA). The ESCA is available since the
z114/z196 released in 2010.
KVM needs to allocate and manage the SCA for guest VMs. Prior to this
change the SCA was setup as Basic SCA only supporting a maximum of 64
vCPUs when initializing the VM. With addition of the 65th vCPU the SCA
was needed to be converted to a ESCA.
Instead we will now allocate the ESCA directly upon VM creation
simplifying the code in multiple places as well as completely removing
the need to convert an existing SCA.
In cases where the ESCA is not supported (z10 and earlier) the use of
the SCA entries and with that SIGP interpretation are disabled for VMs.
This increases the number of exits from the VM in multiprocessor
scenarios and thus decreases performance.
The same is true for VSIE where SIGP is currently disabled and thus no
SCA entries are used.
---
I found a slight problem when testing this to run without sca entries.
Fixed now and tests are successful with and without using the sca
entries (incl. vsie).
Changes in v3:
- do not enable sigp for guests when kvm_s390_use_sca_entries() is false
- consistently use kvm_s390_use_sca_entries() instead of sclp.has_sigpif
- Link to v2: https://lore.kernel.org/r/20250519-rm-bsca-v2-0-e3ea53dd0394@linux.ibm.com
Changes in v2:
- properly apply checkpatch --strict (Thanks Claudio)
- some small comment wording changes
- rebased
- Link to v1: https://lore.kernel.org/r/20250514-rm-bsca-v1-0-6c2b065a8680@linux.ibm.com
---
Christoph Schlameuss (3):
KVM: s390: Set KVM_MAX_VCPUS to 256
KVM: s390: Always allocate esca_block
KVM: s390: Specify kvm->arch.sca as esca_block
arch/s390/include/asm/kvm_host.h | 7 +-
arch/s390/include/asm/kvm_host_types.h | 2 +
arch/s390/kvm/gaccess.c | 10 +-
arch/s390/kvm/interrupt.c | 71 ++++----------
arch/s390/kvm/kvm-s390.c | 163 ++++++---------------------------
arch/s390/kvm/kvm-s390.h | 9 +-
6 files changed, 55 insertions(+), 207 deletions(-)
---
base-commit: a5806cd506af5a7c19bcd596e4708b5c464bfd21
change-id: 20250513-rm-bsca-ab1e8649aca7
Best regards,
--
Christoph Schlameuss <schlameuss@linux.ibm.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 1/3] KVM: s390: Set KVM_MAX_VCPUS to 256
2025-05-22 9:31 [PATCH v3 0/3] KVM: s390: Use ESCA instead of BSCA at VM init Christoph Schlameuss
@ 2025-05-22 9:31 ` Christoph Schlameuss
2025-05-30 7:39 ` Janosch Frank
2025-05-22 9:31 ` [PATCH v3 2/3] KVM: s390: Always allocate esca_block Christoph Schlameuss
2025-05-22 9:31 ` [PATCH v3 3/3] KVM: s390: Specify kvm->arch.sca as esca_block Christoph Schlameuss
2 siblings, 1 reply; 10+ messages in thread
From: Christoph Schlameuss @ 2025-05-22 9:31 UTC (permalink / raw)
To: kvm
Cc: linux-s390, Christian Borntraeger, Janosch Frank,
Claudio Imbrenda, David Hildenbrand, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Thomas Huth,
Christoph Schlameuss
The s390x architecture allows for 256 vCPUs with a max CPUID of 255.
The current KVM implementation limits this to 248 when using the
extended system control area (ESCA). So this correction should not cause
any real world problems but actually correct the values returned by the
ioctls:
* KVM_CAP_NR_VCPUS
* KVM_CAP_MAX_VCPUS
* KVM_CAP_MAX_VCPU_ID
KVM_MAX_VCPUS is also moved to kvm_host_types to allow using this in
future type definitions.
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
---
arch/s390/include/asm/kvm_host.h | 2 --
arch/s390/include/asm/kvm_host_types.h | 2 ++
arch/s390/kvm/kvm-s390.c | 2 ++
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index cb89e54ada257eb4fdfe840ff37b2ea639c2d1cb..f51bac835260f562eaf4bbfd373a24bfdbc43834 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -27,8 +27,6 @@
#include <asm/isc.h>
#include <asm/guarded_storage.h>
-#define KVM_MAX_VCPUS 255
-
#define KVM_INTERNAL_MEM_SLOTS 1
/*
diff --git a/arch/s390/include/asm/kvm_host_types.h b/arch/s390/include/asm/kvm_host_types.h
index 1394d3fb648f1e46dba2c513ed26e5dfd275fad4..9697db9576f6c39a6689251f85b4b974c344769a 100644
--- a/arch/s390/include/asm/kvm_host_types.h
+++ b/arch/s390/include/asm/kvm_host_types.h
@@ -6,6 +6,8 @@
#include <linux/atomic.h>
#include <linux/types.h>
+#define KVM_MAX_VCPUS 256
+
#define KVM_S390_BSCA_CPU_SLOTS 64
#define KVM_S390_ESCA_CPU_SLOTS 248
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 3f3175193fd7a7a26658eb2e2533d8037447a0b4..b65e4cbe67cf70a7d614607ebdd679060e7d31f4 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -638,6 +638,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = KVM_S390_ESCA_CPU_SLOTS;
if (ext == KVM_CAP_NR_VCPUS)
r = min_t(unsigned int, num_online_cpus(), r);
+ else if (ext == KVM_CAP_MAX_VCPU_ID)
+ r -= 1;
break;
case KVM_CAP_S390_COW:
r = machine_has_esop();
--
2.49.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 2/3] KVM: s390: Always allocate esca_block
2025-05-22 9:31 [PATCH v3 0/3] KVM: s390: Use ESCA instead of BSCA at VM init Christoph Schlameuss
2025-05-22 9:31 ` [PATCH v3 1/3] KVM: s390: Set KVM_MAX_VCPUS to 256 Christoph Schlameuss
@ 2025-05-22 9:31 ` Christoph Schlameuss
2025-05-22 10:49 ` Claudio Imbrenda
` (2 more replies)
2025-05-22 9:31 ` [PATCH v3 3/3] KVM: s390: Specify kvm->arch.sca as esca_block Christoph Schlameuss
2 siblings, 3 replies; 10+ messages in thread
From: Christoph Schlameuss @ 2025-05-22 9:31 UTC (permalink / raw)
To: kvm
Cc: linux-s390, Christian Borntraeger, Janosch Frank,
Claudio Imbrenda, David Hildenbrand, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Thomas Huth,
Christoph Schlameuss
Instead of allocating a BSCA and upgrading it for PV or when adding the
65th cpu we can always use the ESCA.
The only downside of the change is that we will always allocate 4 pages
for a 248 cpu ESCA instead of a single page for the BSCA per VM.
In return we can delete a bunch of checks and special handling depending
on the SCA type as well as the whole BSCA to ESCA conversion.
As a fallback we can still run without SCA entries when the SIGP
interpretation facility or ESCA are not available.
Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
---
arch/s390/include/asm/kvm_host.h | 1 -
arch/s390/kvm/interrupt.c | 71 +++++------------
arch/s390/kvm/kvm-s390.c | 161 ++++++---------------------------------
arch/s390/kvm/kvm-s390.h | 4 +-
4 files changed, 45 insertions(+), 192 deletions(-)
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index f51bac835260f562eaf4bbfd373a24bfdbc43834..d03e354a63d9c931522c1a1607eba8685c24527f 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -631,7 +631,6 @@ struct kvm_s390_pv {
struct kvm_arch{
void *sca;
- int use_esca;
rwlock_t sca_lock;
debug_info_t *dbf;
struct kvm_s390_float_interrupt float_int;
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 60c360c18690f6b94e8483dab2c25f016451204b..95a876ff7aca9c632c3e361275da6781ec070c07 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -51,21 +51,11 @@ static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
BUG_ON(!kvm_s390_use_sca_entries());
read_lock(&vcpu->kvm->arch.sca_lock);
- if (vcpu->kvm->arch.use_esca) {
- struct esca_block *sca = vcpu->kvm->arch.sca;
- union esca_sigp_ctrl sigp_ctrl =
- sca->cpu[vcpu->vcpu_id].sigp_ctrl;
+ struct esca_block *sca = vcpu->kvm->arch.sca;
+ union esca_sigp_ctrl sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
- c = sigp_ctrl.c;
- scn = sigp_ctrl.scn;
- } else {
- struct bsca_block *sca = vcpu->kvm->arch.sca;
- union bsca_sigp_ctrl sigp_ctrl =
- sca->cpu[vcpu->vcpu_id].sigp_ctrl;
-
- c = sigp_ctrl.c;
- scn = sigp_ctrl.scn;
- }
+ c = sigp_ctrl.c;
+ scn = sigp_ctrl.scn;
read_unlock(&vcpu->kvm->arch.sca_lock);
if (src_id)
@@ -80,33 +70,17 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
BUG_ON(!kvm_s390_use_sca_entries());
read_lock(&vcpu->kvm->arch.sca_lock);
- if (vcpu->kvm->arch.use_esca) {
- struct esca_block *sca = vcpu->kvm->arch.sca;
- union esca_sigp_ctrl *sigp_ctrl =
- &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
- union esca_sigp_ctrl new_val = {0}, old_val;
-
- old_val = READ_ONCE(*sigp_ctrl);
- new_val.scn = src_id;
- new_val.c = 1;
- old_val.c = 0;
-
- expect = old_val.value;
- rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
- } else {
- struct bsca_block *sca = vcpu->kvm->arch.sca;
- union bsca_sigp_ctrl *sigp_ctrl =
- &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
- union bsca_sigp_ctrl new_val = {0}, old_val;
+ struct esca_block *sca = vcpu->kvm->arch.sca;
+ union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
+ union esca_sigp_ctrl new_val = {0}, old_val;
- old_val = READ_ONCE(*sigp_ctrl);
- new_val.scn = src_id;
- new_val.c = 1;
- old_val.c = 0;
+ old_val = READ_ONCE(*sigp_ctrl);
+ new_val.scn = src_id;
+ new_val.c = 1;
+ old_val.c = 0;
- expect = old_val.value;
- rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
- }
+ expect = old_val.value;
+ rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
read_unlock(&vcpu->kvm->arch.sca_lock);
if (rc != expect) {
@@ -123,19 +97,10 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
return;
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
read_lock(&vcpu->kvm->arch.sca_lock);
- if (vcpu->kvm->arch.use_esca) {
- struct esca_block *sca = vcpu->kvm->arch.sca;
- union esca_sigp_ctrl *sigp_ctrl =
- &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
+ struct esca_block *sca = vcpu->kvm->arch.sca;
+ union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
- WRITE_ONCE(sigp_ctrl->value, 0);
- } else {
- struct bsca_block *sca = vcpu->kvm->arch.sca;
- union bsca_sigp_ctrl *sigp_ctrl =
- &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
-
- WRITE_ONCE(sigp_ctrl->value, 0);
- }
+ WRITE_ONCE(sigp_ctrl->value, 0);
read_unlock(&vcpu->kvm->arch.sca_lock);
}
@@ -1223,7 +1188,7 @@ int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu)
{
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
- if (!sclp.has_sigpif)
+ if (!kvm_s390_use_sca_entries())
return test_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs);
return sca_ext_call_pending(vcpu, NULL);
@@ -1547,7 +1512,7 @@ static int __inject_extcall(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
if (kvm_get_vcpu_by_id(vcpu->kvm, src_id) == NULL)
return -EINVAL;
- if (sclp.has_sigpif && !kvm_s390_pv_cpu_get_handle(vcpu))
+ if (kvm_s390_use_sca_entries() && !kvm_s390_pv_cpu_get_handle(vcpu))
return sca_inject_ext_call(vcpu, src_id);
if (test_and_set_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs))
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index b65e4cbe67cf70a7d614607ebdd679060e7d31f4..473e399056fb31d341d9a00a9295e37a8aa66ab7 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -271,7 +271,6 @@ debug_info_t *kvm_s390_dbf_uv;
/* forward declarations */
static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
unsigned long end);
-static int sca_switch_to_extended(struct kvm *kvm);
static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta)
{
@@ -631,11 +630,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_NR_VCPUS:
case KVM_CAP_MAX_VCPUS:
case KVM_CAP_MAX_VCPU_ID:
- r = KVM_S390_BSCA_CPU_SLOTS;
+ r = KVM_S390_ESCA_CPU_SLOTS;
if (!kvm_s390_use_sca_entries())
r = KVM_MAX_VCPUS;
- else if (sclp.has_esca && sclp.has_64bscao)
- r = KVM_S390_ESCA_CPU_SLOTS;
if (ext == KVM_CAP_NR_VCPUS)
r = min_t(unsigned int, num_online_cpus(), r);
else if (ext == KVM_CAP_MAX_VCPU_ID)
@@ -1932,13 +1929,11 @@ static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
* Updates the Multiprocessor Topology-Change-Report bit to signal
* the guest with a topology change.
* This is only relevant if the topology facility is present.
- *
- * The SCA version, bsca or esca, doesn't matter as offset is the same.
*/
static void kvm_s390_update_topology_change_report(struct kvm *kvm, bool val)
{
union sca_utility new, old;
- struct bsca_block *sca;
+ struct esca_block *sca;
read_lock(&kvm->arch.sca_lock);
sca = kvm->arch.sca;
@@ -1969,7 +1964,7 @@ static int kvm_s390_get_topo_change_indication(struct kvm *kvm,
return -ENXIO;
read_lock(&kvm->arch.sca_lock);
- topo = ((struct bsca_block *)kvm->arch.sca)->utility.mtcr;
+ topo = ((struct esca_block *)kvm->arch.sca)->utility.mtcr;
read_unlock(&kvm->arch.sca_lock);
return put_user(topo, (u8 __user *)attr->addr);
@@ -2668,14 +2663,6 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
if (kvm_s390_pv_is_protected(kvm))
break;
- /*
- * FMT 4 SIE needs esca. As we never switch back to bsca from
- * esca, we need no cleanup in the error cases below
- */
- r = sca_switch_to_extended(kvm);
- if (r)
- break;
-
r = s390_disable_cow_sharing();
if (r)
break;
@@ -3316,10 +3303,7 @@ static void kvm_s390_crypto_init(struct kvm *kvm)
static void sca_dispose(struct kvm *kvm)
{
- if (kvm->arch.use_esca)
- free_pages_exact(kvm->arch.sca, sizeof(struct esca_block));
- else
- free_page((unsigned long)(kvm->arch.sca));
+ free_pages_exact(kvm->arch.sca, sizeof(struct esca_block));
kvm->arch.sca = NULL;
}
@@ -3333,10 +3317,9 @@ void kvm_arch_free_vm(struct kvm *kvm)
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
- gfp_t alloc_flags = GFP_KERNEL_ACCOUNT;
- int i, rc;
+ gfp_t alloc_flags = GFP_KERNEL_ACCOUNT | __GFP_ZERO;
char debug_name[16];
- static unsigned long sca_offset;
+ int i, rc;
rc = -EINVAL;
#ifdef CONFIG_KVM_S390_UCONTROL
@@ -3358,17 +3341,12 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
if (!sclp.has_64bscao)
alloc_flags |= GFP_DMA;
rwlock_init(&kvm->arch.sca_lock);
- /* start with basic SCA */
- kvm->arch.sca = (struct bsca_block *) get_zeroed_page(alloc_flags);
- if (!kvm->arch.sca)
- goto out_err;
mutex_lock(&kvm_lock);
- sca_offset += 16;
- if (sca_offset + sizeof(struct bsca_block) > PAGE_SIZE)
- sca_offset = 0;
- kvm->arch.sca = (struct bsca_block *)
- ((char *) kvm->arch.sca + sca_offset);
+
+ kvm->arch.sca = alloc_pages_exact(sizeof(*kvm->arch.sca), alloc_flags);
mutex_unlock(&kvm_lock);
+ if (!kvm->arch.sca)
+ goto out_err;
sprintf(debug_name, "kvm-%u", current->pid);
@@ -3550,17 +3528,10 @@ static void sca_del_vcpu(struct kvm_vcpu *vcpu)
if (!kvm_s390_use_sca_entries())
return;
read_lock(&vcpu->kvm->arch.sca_lock);
- if (vcpu->kvm->arch.use_esca) {
- struct esca_block *sca = vcpu->kvm->arch.sca;
-
- clear_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn);
- sca->cpu[vcpu->vcpu_id].sda = 0;
- } else {
- struct bsca_block *sca = vcpu->kvm->arch.sca;
+ struct esca_block *sca = vcpu->kvm->arch.sca;
- clear_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn);
- sca->cpu[vcpu->vcpu_id].sda = 0;
- }
+ clear_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
+ sca->cpu[vcpu->vcpu_id].sda = 0;
read_unlock(&vcpu->kvm->arch.sca_lock);
}
@@ -3575,105 +3546,23 @@ static void sca_add_vcpu(struct kvm_vcpu *vcpu)
return;
}
read_lock(&vcpu->kvm->arch.sca_lock);
- if (vcpu->kvm->arch.use_esca) {
- struct esca_block *sca = vcpu->kvm->arch.sca;
- phys_addr_t sca_phys = virt_to_phys(sca);
-
- sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
- vcpu->arch.sie_block->scaoh = sca_phys >> 32;
- vcpu->arch.sie_block->scaol = sca_phys & ESCA_SCAOL_MASK;
- vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
- set_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn);
- } else {
- struct bsca_block *sca = vcpu->kvm->arch.sca;
- phys_addr_t sca_phys = virt_to_phys(sca);
-
- sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
- vcpu->arch.sie_block->scaoh = sca_phys >> 32;
- vcpu->arch.sie_block->scaol = sca_phys;
- set_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn);
- }
+ struct esca_block *sca = vcpu->kvm->arch.sca;
+ phys_addr_t sca_phys = virt_to_phys(sca);
+
+ sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
+ vcpu->arch.sie_block->scaoh = sca_phys >> 32;
+ vcpu->arch.sie_block->scaol = sca_phys & ESCA_SCAOL_MASK;
+ vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
+ set_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
read_unlock(&vcpu->kvm->arch.sca_lock);
}
-/* Basic SCA to Extended SCA data copy routines */
-static inline void sca_copy_entry(struct esca_entry *d, struct bsca_entry *s)
-{
- d->sda = s->sda;
- d->sigp_ctrl.c = s->sigp_ctrl.c;
- d->sigp_ctrl.scn = s->sigp_ctrl.scn;
-}
-
-static void sca_copy_b_to_e(struct esca_block *d, struct bsca_block *s)
-{
- int i;
-
- d->ipte_control = s->ipte_control;
- d->mcn[0] = s->mcn;
- for (i = 0; i < KVM_S390_BSCA_CPU_SLOTS; i++)
- sca_copy_entry(&d->cpu[i], &s->cpu[i]);
-}
-
-static int sca_switch_to_extended(struct kvm *kvm)
-{
- struct bsca_block *old_sca = kvm->arch.sca;
- struct esca_block *new_sca;
- struct kvm_vcpu *vcpu;
- unsigned long vcpu_idx;
- u32 scaol, scaoh;
- phys_addr_t new_sca_phys;
-
- if (kvm->arch.use_esca)
- return 0;
-
- new_sca = alloc_pages_exact(sizeof(*new_sca), GFP_KERNEL_ACCOUNT | __GFP_ZERO);
- if (!new_sca)
- return -ENOMEM;
-
- new_sca_phys = virt_to_phys(new_sca);
- scaoh = new_sca_phys >> 32;
- scaol = new_sca_phys & ESCA_SCAOL_MASK;
-
- kvm_s390_vcpu_block_all(kvm);
- write_lock(&kvm->arch.sca_lock);
-
- sca_copy_b_to_e(new_sca, old_sca);
-
- kvm_for_each_vcpu(vcpu_idx, vcpu, kvm) {
- vcpu->arch.sie_block->scaoh = scaoh;
- vcpu->arch.sie_block->scaol = scaol;
- vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
- }
- kvm->arch.sca = new_sca;
- kvm->arch.use_esca = 1;
-
- write_unlock(&kvm->arch.sca_lock);
- kvm_s390_vcpu_unblock_all(kvm);
-
- free_page((unsigned long)old_sca);
-
- VM_EVENT(kvm, 2, "Switched to ESCA (0x%p -> 0x%p)",
- old_sca, kvm->arch.sca);
- return 0;
-}
-
static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
{
- int rc;
-
- if (!kvm_s390_use_sca_entries()) {
- if (id < KVM_MAX_VCPUS)
- return true;
- return false;
- }
- if (id < KVM_S390_BSCA_CPU_SLOTS)
- return true;
- if (!sclp.has_esca || !sclp.has_64bscao)
- return false;
-
- rc = kvm->arch.use_esca ? 0 : sca_switch_to_extended(kvm);
+ if (!kvm_s390_use_sca_entries())
+ return id < KVM_MAX_VCPUS;
- return rc == 0 && id < KVM_S390_ESCA_CPU_SLOTS;
+ return id < KVM_S390_ESCA_CPU_SLOTS;
}
/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
@@ -3919,7 +3808,7 @@ static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)
vcpu->arch.sie_block->eca |= ECA_IB;
if (sclp.has_siif)
vcpu->arch.sie_block->eca |= ECA_SII;
- if (sclp.has_sigpif)
+ if (kvm_s390_use_sca_entries())
vcpu->arch.sie_block->eca |= ECA_SIGPI;
if (test_kvm_facility(vcpu->kvm, 129)) {
vcpu->arch.sie_block->eca |= ECA_VX;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 8d3bbb2dd8d27802bbde2a7bd1378033ad614b8e..2c8e177e4af8f2dab07fd42a904cefdea80f6855 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -531,7 +531,7 @@ int kvm_s390_handle_per_event(struct kvm_vcpu *vcpu);
/* support for Basic/Extended SCA handling */
static inline union ipte_control *kvm_s390_get_ipte_control(struct kvm *kvm)
{
- struct bsca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
+ struct esca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
return &sca->ipte_control;
}
@@ -542,7 +542,7 @@ static inline int kvm_s390_use_sca_entries(void)
* might use the entries. By not setting the entries and keeping them
* invalid, hardware will not access them but intercept.
*/
- return sclp.has_sigpif;
+ return sclp.has_sigpif && sclp.has_esca;
}
void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
struct mcck_volatile_info *mcck_info);
--
2.49.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 3/3] KVM: s390: Specify kvm->arch.sca as esca_block
2025-05-22 9:31 [PATCH v3 0/3] KVM: s390: Use ESCA instead of BSCA at VM init Christoph Schlameuss
2025-05-22 9:31 ` [PATCH v3 1/3] KVM: s390: Set KVM_MAX_VCPUS to 256 Christoph Schlameuss
2025-05-22 9:31 ` [PATCH v3 2/3] KVM: s390: Always allocate esca_block Christoph Schlameuss
@ 2025-05-22 9:31 ` Christoph Schlameuss
2 siblings, 0 replies; 10+ messages in thread
From: Christoph Schlameuss @ 2025-05-22 9:31 UTC (permalink / raw)
To: kvm
Cc: linux-s390, Christian Borntraeger, Janosch Frank,
Claudio Imbrenda, David Hildenbrand, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Thomas Huth,
Christoph Schlameuss
We are no longer referencing a bsca_block in kvm->arch.sca. This will
always be esca_block instead.
By specifying the type of the sca as esca_block we can simplify access
to the sca and get rid of some helpers while making the code clearer.
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
---
arch/s390/include/asm/kvm_host.h | 4 ++--
arch/s390/kvm/gaccess.c | 10 +++++-----
arch/s390/kvm/kvm-s390.c | 4 ++--
arch/s390/kvm/kvm-s390.h | 7 -------
4 files changed, 9 insertions(+), 16 deletions(-)
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index d03e354a63d9c931522c1a1607eba8685c24527f..2a2b557357c8e40c82022eb338c3e98aa8f03a2b 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -629,8 +629,8 @@ struct kvm_s390_pv {
struct mmu_notifier mmu_notifier;
};
-struct kvm_arch{
- void *sca;
+struct kvm_arch {
+ struct esca_block *sca;
rwlock_t sca_lock;
debug_info_t *dbf;
struct kvm_s390_float_interrupt float_int;
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index f6fded15633ad87f6b02c2c42aea35a3c9164253..ee37d397d9218a4d33c7a33bd877d0b974ca9003 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -112,7 +112,7 @@ int ipte_lock_held(struct kvm *kvm)
int rc;
read_lock(&kvm->arch.sca_lock);
- rc = kvm_s390_get_ipte_control(kvm)->kh != 0;
+ rc = kvm->arch.sca->ipte_control.kh != 0;
read_unlock(&kvm->arch.sca_lock);
return rc;
}
@@ -129,7 +129,7 @@ static void ipte_lock_simple(struct kvm *kvm)
goto out;
retry:
read_lock(&kvm->arch.sca_lock);
- ic = kvm_s390_get_ipte_control(kvm);
+ ic = &kvm->arch.sca->ipte_control;
old = READ_ONCE(*ic);
do {
if (old.k) {
@@ -154,7 +154,7 @@ static void ipte_unlock_simple(struct kvm *kvm)
if (kvm->arch.ipte_lock_count)
goto out;
read_lock(&kvm->arch.sca_lock);
- ic = kvm_s390_get_ipte_control(kvm);
+ ic = &kvm->arch.sca->ipte_control;
old = READ_ONCE(*ic);
do {
new = old;
@@ -172,7 +172,7 @@ static void ipte_lock_siif(struct kvm *kvm)
retry:
read_lock(&kvm->arch.sca_lock);
- ic = kvm_s390_get_ipte_control(kvm);
+ ic = &kvm->arch.sca->ipte_control;
old = READ_ONCE(*ic);
do {
if (old.kg) {
@@ -192,7 +192,7 @@ static void ipte_unlock_siif(struct kvm *kvm)
union ipte_control old, new, *ic;
read_lock(&kvm->arch.sca_lock);
- ic = kvm_s390_get_ipte_control(kvm);
+ ic = &kvm->arch.sca->ipte_control;
old = READ_ONCE(*ic);
do {
new = old;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 473e399056fb31d341d9a00a9295e37a8aa66ab7..f228d0a187ce2a349c1ea76f3d6dd7dc8e3283d8 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1964,7 +1964,7 @@ static int kvm_s390_get_topo_change_indication(struct kvm *kvm,
return -ENXIO;
read_lock(&kvm->arch.sca_lock);
- topo = ((struct esca_block *)kvm->arch.sca)->utility.mtcr;
+ topo = kvm->arch.sca->utility.mtcr;
read_unlock(&kvm->arch.sca_lock);
return put_user(topo, (u8 __user *)attr->addr);
@@ -3303,7 +3303,7 @@ static void kvm_s390_crypto_init(struct kvm *kvm)
static void sca_dispose(struct kvm *kvm)
{
- free_pages_exact(kvm->arch.sca, sizeof(struct esca_block));
+ free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca));
kvm->arch.sca = NULL;
}
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 2c8e177e4af8f2dab07fd42a904cefdea80f6855..0c5e8ae07b77648d554668cc0536607545636a68 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -528,13 +528,6 @@ void kvm_s390_prepare_debug_exit(struct kvm_vcpu *vcpu);
int kvm_s390_handle_per_ifetch_icpt(struct kvm_vcpu *vcpu);
int kvm_s390_handle_per_event(struct kvm_vcpu *vcpu);
-/* support for Basic/Extended SCA handling */
-static inline union ipte_control *kvm_s390_get_ipte_control(struct kvm *kvm)
-{
- struct esca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
-
- return &sca->ipte_control;
-}
static inline int kvm_s390_use_sca_entries(void)
{
/*
--
2.49.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/3] KVM: s390: Always allocate esca_block
2025-05-22 9:31 ` [PATCH v3 2/3] KVM: s390: Always allocate esca_block Christoph Schlameuss
@ 2025-05-22 10:49 ` Claudio Imbrenda
2025-05-26 8:22 ` Janosch Frank
2025-05-26 10:36 ` Janosch Frank
2 siblings, 0 replies; 10+ messages in thread
From: Claudio Imbrenda @ 2025-05-22 10:49 UTC (permalink / raw)
To: Christoph Schlameuss
Cc: kvm, linux-s390, Christian Borntraeger, Janosch Frank,
David Hildenbrand, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Sven Schnelle, Thomas Huth
On Thu, 22 May 2025 11:31:58 +0200
Christoph Schlameuss <schlameuss@linux.ibm.com> wrote:
> Instead of allocating a BSCA and upgrading it for PV or when adding the
> 65th cpu we can always use the ESCA.
>
> The only downside of the change is that we will always allocate 4 pages
> for a 248 cpu ESCA instead of a single page for the BSCA per VM.
> In return we can delete a bunch of checks and special handling depending
> on the SCA type as well as the whole BSCA to ESCA conversion.
>
> As a fallback we can still run without SCA entries when the SIGP
> interpretation facility or ESCA are not available.
>
> Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
I think you could have kept the R-bs for such a small change.
anyway, here it is again:
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> ---
> arch/s390/include/asm/kvm_host.h | 1 -
> arch/s390/kvm/interrupt.c | 71 +++++------------
> arch/s390/kvm/kvm-s390.c | 161 ++++++---------------------------------
> arch/s390/kvm/kvm-s390.h | 4 +-
> 4 files changed, 45 insertions(+), 192 deletions(-)
>
> diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
> index f51bac835260f562eaf4bbfd373a24bfdbc43834..d03e354a63d9c931522c1a1607eba8685c24527f 100644
> --- a/arch/s390/include/asm/kvm_host.h
> +++ b/arch/s390/include/asm/kvm_host.h
> @@ -631,7 +631,6 @@ struct kvm_s390_pv {
>
> struct kvm_arch{
> void *sca;
> - int use_esca;
> rwlock_t sca_lock;
> debug_info_t *dbf;
> struct kvm_s390_float_interrupt float_int;
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index 60c360c18690f6b94e8483dab2c25f016451204b..95a876ff7aca9c632c3e361275da6781ec070c07 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
> @@ -51,21 +51,11 @@ static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
>
> BUG_ON(!kvm_s390_use_sca_entries());
> read_lock(&vcpu->kvm->arch.sca_lock);
> - if (vcpu->kvm->arch.use_esca) {
> - struct esca_block *sca = vcpu->kvm->arch.sca;
> - union esca_sigp_ctrl sigp_ctrl =
> - sca->cpu[vcpu->vcpu_id].sigp_ctrl;
> + struct esca_block *sca = vcpu->kvm->arch.sca;
> + union esca_sigp_ctrl sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
>
> - c = sigp_ctrl.c;
> - scn = sigp_ctrl.scn;
> - } else {
> - struct bsca_block *sca = vcpu->kvm->arch.sca;
> - union bsca_sigp_ctrl sigp_ctrl =
> - sca->cpu[vcpu->vcpu_id].sigp_ctrl;
> -
> - c = sigp_ctrl.c;
> - scn = sigp_ctrl.scn;
> - }
> + c = sigp_ctrl.c;
> + scn = sigp_ctrl.scn;
> read_unlock(&vcpu->kvm->arch.sca_lock);
>
> if (src_id)
> @@ -80,33 +70,17 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
>
> BUG_ON(!kvm_s390_use_sca_entries());
> read_lock(&vcpu->kvm->arch.sca_lock);
> - if (vcpu->kvm->arch.use_esca) {
> - struct esca_block *sca = vcpu->kvm->arch.sca;
> - union esca_sigp_ctrl *sigp_ctrl =
> - &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
> - union esca_sigp_ctrl new_val = {0}, old_val;
> -
> - old_val = READ_ONCE(*sigp_ctrl);
> - new_val.scn = src_id;
> - new_val.c = 1;
> - old_val.c = 0;
> -
> - expect = old_val.value;
> - rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
> - } else {
> - struct bsca_block *sca = vcpu->kvm->arch.sca;
> - union bsca_sigp_ctrl *sigp_ctrl =
> - &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
> - union bsca_sigp_ctrl new_val = {0}, old_val;
> + struct esca_block *sca = vcpu->kvm->arch.sca;
> + union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
> + union esca_sigp_ctrl new_val = {0}, old_val;
>
> - old_val = READ_ONCE(*sigp_ctrl);
> - new_val.scn = src_id;
> - new_val.c = 1;
> - old_val.c = 0;
> + old_val = READ_ONCE(*sigp_ctrl);
> + new_val.scn = src_id;
> + new_val.c = 1;
> + old_val.c = 0;
>
> - expect = old_val.value;
> - rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
> - }
> + expect = old_val.value;
> + rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
> read_unlock(&vcpu->kvm->arch.sca_lock);
>
> if (rc != expect) {
> @@ -123,19 +97,10 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
> return;
> kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
> read_lock(&vcpu->kvm->arch.sca_lock);
> - if (vcpu->kvm->arch.use_esca) {
> - struct esca_block *sca = vcpu->kvm->arch.sca;
> - union esca_sigp_ctrl *sigp_ctrl =
> - &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
> + struct esca_block *sca = vcpu->kvm->arch.sca;
> + union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
>
> - WRITE_ONCE(sigp_ctrl->value, 0);
> - } else {
> - struct bsca_block *sca = vcpu->kvm->arch.sca;
> - union bsca_sigp_ctrl *sigp_ctrl =
> - &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
> -
> - WRITE_ONCE(sigp_ctrl->value, 0);
> - }
> + WRITE_ONCE(sigp_ctrl->value, 0);
> read_unlock(&vcpu->kvm->arch.sca_lock);
> }
>
> @@ -1223,7 +1188,7 @@ int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu)
> {
> struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
>
> - if (!sclp.has_sigpif)
> + if (!kvm_s390_use_sca_entries())
> return test_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs);
>
> return sca_ext_call_pending(vcpu, NULL);
> @@ -1547,7 +1512,7 @@ static int __inject_extcall(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
> if (kvm_get_vcpu_by_id(vcpu->kvm, src_id) == NULL)
> return -EINVAL;
>
> - if (sclp.has_sigpif && !kvm_s390_pv_cpu_get_handle(vcpu))
> + if (kvm_s390_use_sca_entries() && !kvm_s390_pv_cpu_get_handle(vcpu))
> return sca_inject_ext_call(vcpu, src_id);
>
> if (test_and_set_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs))
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index b65e4cbe67cf70a7d614607ebdd679060e7d31f4..473e399056fb31d341d9a00a9295e37a8aa66ab7 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -271,7 +271,6 @@ debug_info_t *kvm_s390_dbf_uv;
> /* forward declarations */
> static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
> unsigned long end);
> -static int sca_switch_to_extended(struct kvm *kvm);
>
> static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta)
> {
> @@ -631,11 +630,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> case KVM_CAP_NR_VCPUS:
> case KVM_CAP_MAX_VCPUS:
> case KVM_CAP_MAX_VCPU_ID:
> - r = KVM_S390_BSCA_CPU_SLOTS;
> + r = KVM_S390_ESCA_CPU_SLOTS;
> if (!kvm_s390_use_sca_entries())
> r = KVM_MAX_VCPUS;
> - else if (sclp.has_esca && sclp.has_64bscao)
> - r = KVM_S390_ESCA_CPU_SLOTS;
> if (ext == KVM_CAP_NR_VCPUS)
> r = min_t(unsigned int, num_online_cpus(), r);
> else if (ext == KVM_CAP_MAX_VCPU_ID)
> @@ -1932,13 +1929,11 @@ static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
> * Updates the Multiprocessor Topology-Change-Report bit to signal
> * the guest with a topology change.
> * This is only relevant if the topology facility is present.
> - *
> - * The SCA version, bsca or esca, doesn't matter as offset is the same.
> */
> static void kvm_s390_update_topology_change_report(struct kvm *kvm, bool val)
> {
> union sca_utility new, old;
> - struct bsca_block *sca;
> + struct esca_block *sca;
>
> read_lock(&kvm->arch.sca_lock);
> sca = kvm->arch.sca;
> @@ -1969,7 +1964,7 @@ static int kvm_s390_get_topo_change_indication(struct kvm *kvm,
> return -ENXIO;
>
> read_lock(&kvm->arch.sca_lock);
> - topo = ((struct bsca_block *)kvm->arch.sca)->utility.mtcr;
> + topo = ((struct esca_block *)kvm->arch.sca)->utility.mtcr;
> read_unlock(&kvm->arch.sca_lock);
>
> return put_user(topo, (u8 __user *)attr->addr);
> @@ -2668,14 +2663,6 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
> if (kvm_s390_pv_is_protected(kvm))
> break;
>
> - /*
> - * FMT 4 SIE needs esca. As we never switch back to bsca from
> - * esca, we need no cleanup in the error cases below
> - */
> - r = sca_switch_to_extended(kvm);
> - if (r)
> - break;
> -
> r = s390_disable_cow_sharing();
> if (r)
> break;
> @@ -3316,10 +3303,7 @@ static void kvm_s390_crypto_init(struct kvm *kvm)
>
> static void sca_dispose(struct kvm *kvm)
> {
> - if (kvm->arch.use_esca)
> - free_pages_exact(kvm->arch.sca, sizeof(struct esca_block));
> - else
> - free_page((unsigned long)(kvm->arch.sca));
> + free_pages_exact(kvm->arch.sca, sizeof(struct esca_block));
> kvm->arch.sca = NULL;
> }
>
> @@ -3333,10 +3317,9 @@ void kvm_arch_free_vm(struct kvm *kvm)
>
> int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
> {
> - gfp_t alloc_flags = GFP_KERNEL_ACCOUNT;
> - int i, rc;
> + gfp_t alloc_flags = GFP_KERNEL_ACCOUNT | __GFP_ZERO;
> char debug_name[16];
> - static unsigned long sca_offset;
> + int i, rc;
>
> rc = -EINVAL;
> #ifdef CONFIG_KVM_S390_UCONTROL
> @@ -3358,17 +3341,12 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
> if (!sclp.has_64bscao)
> alloc_flags |= GFP_DMA;
> rwlock_init(&kvm->arch.sca_lock);
> - /* start with basic SCA */
> - kvm->arch.sca = (struct bsca_block *) get_zeroed_page(alloc_flags);
> - if (!kvm->arch.sca)
> - goto out_err;
> mutex_lock(&kvm_lock);
> - sca_offset += 16;
> - if (sca_offset + sizeof(struct bsca_block) > PAGE_SIZE)
> - sca_offset = 0;
> - kvm->arch.sca = (struct bsca_block *)
> - ((char *) kvm->arch.sca + sca_offset);
> +
> + kvm->arch.sca = alloc_pages_exact(sizeof(*kvm->arch.sca), alloc_flags);
> mutex_unlock(&kvm_lock);
> + if (!kvm->arch.sca)
> + goto out_err;
>
> sprintf(debug_name, "kvm-%u", current->pid);
>
> @@ -3550,17 +3528,10 @@ static void sca_del_vcpu(struct kvm_vcpu *vcpu)
> if (!kvm_s390_use_sca_entries())
> return;
> read_lock(&vcpu->kvm->arch.sca_lock);
> - if (vcpu->kvm->arch.use_esca) {
> - struct esca_block *sca = vcpu->kvm->arch.sca;
> -
> - clear_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn);
> - sca->cpu[vcpu->vcpu_id].sda = 0;
> - } else {
> - struct bsca_block *sca = vcpu->kvm->arch.sca;
> + struct esca_block *sca = vcpu->kvm->arch.sca;
>
> - clear_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn);
> - sca->cpu[vcpu->vcpu_id].sda = 0;
> - }
> + clear_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
> + sca->cpu[vcpu->vcpu_id].sda = 0;
> read_unlock(&vcpu->kvm->arch.sca_lock);
> }
>
> @@ -3575,105 +3546,23 @@ static void sca_add_vcpu(struct kvm_vcpu *vcpu)
> return;
> }
> read_lock(&vcpu->kvm->arch.sca_lock);
> - if (vcpu->kvm->arch.use_esca) {
> - struct esca_block *sca = vcpu->kvm->arch.sca;
> - phys_addr_t sca_phys = virt_to_phys(sca);
> -
> - sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
> - vcpu->arch.sie_block->scaoh = sca_phys >> 32;
> - vcpu->arch.sie_block->scaol = sca_phys & ESCA_SCAOL_MASK;
> - vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
> - set_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn);
> - } else {
> - struct bsca_block *sca = vcpu->kvm->arch.sca;
> - phys_addr_t sca_phys = virt_to_phys(sca);
> -
> - sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
> - vcpu->arch.sie_block->scaoh = sca_phys >> 32;
> - vcpu->arch.sie_block->scaol = sca_phys;
> - set_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn);
> - }
> + struct esca_block *sca = vcpu->kvm->arch.sca;
> + phys_addr_t sca_phys = virt_to_phys(sca);
> +
> + sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
> + vcpu->arch.sie_block->scaoh = sca_phys >> 32;
> + vcpu->arch.sie_block->scaol = sca_phys & ESCA_SCAOL_MASK;
> + vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
> + set_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
> read_unlock(&vcpu->kvm->arch.sca_lock);
> }
>
> -/* Basic SCA to Extended SCA data copy routines */
> -static inline void sca_copy_entry(struct esca_entry *d, struct bsca_entry *s)
> -{
> - d->sda = s->sda;
> - d->sigp_ctrl.c = s->sigp_ctrl.c;
> - d->sigp_ctrl.scn = s->sigp_ctrl.scn;
> -}
> -
> -static void sca_copy_b_to_e(struct esca_block *d, struct bsca_block *s)
> -{
> - int i;
> -
> - d->ipte_control = s->ipte_control;
> - d->mcn[0] = s->mcn;
> - for (i = 0; i < KVM_S390_BSCA_CPU_SLOTS; i++)
> - sca_copy_entry(&d->cpu[i], &s->cpu[i]);
> -}
> -
> -static int sca_switch_to_extended(struct kvm *kvm)
> -{
> - struct bsca_block *old_sca = kvm->arch.sca;
> - struct esca_block *new_sca;
> - struct kvm_vcpu *vcpu;
> - unsigned long vcpu_idx;
> - u32 scaol, scaoh;
> - phys_addr_t new_sca_phys;
> -
> - if (kvm->arch.use_esca)
> - return 0;
> -
> - new_sca = alloc_pages_exact(sizeof(*new_sca), GFP_KERNEL_ACCOUNT | __GFP_ZERO);
> - if (!new_sca)
> - return -ENOMEM;
> -
> - new_sca_phys = virt_to_phys(new_sca);
> - scaoh = new_sca_phys >> 32;
> - scaol = new_sca_phys & ESCA_SCAOL_MASK;
> -
> - kvm_s390_vcpu_block_all(kvm);
> - write_lock(&kvm->arch.sca_lock);
> -
> - sca_copy_b_to_e(new_sca, old_sca);
> -
> - kvm_for_each_vcpu(vcpu_idx, vcpu, kvm) {
> - vcpu->arch.sie_block->scaoh = scaoh;
> - vcpu->arch.sie_block->scaol = scaol;
> - vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
> - }
> - kvm->arch.sca = new_sca;
> - kvm->arch.use_esca = 1;
> -
> - write_unlock(&kvm->arch.sca_lock);
> - kvm_s390_vcpu_unblock_all(kvm);
> -
> - free_page((unsigned long)old_sca);
> -
> - VM_EVENT(kvm, 2, "Switched to ESCA (0x%p -> 0x%p)",
> - old_sca, kvm->arch.sca);
> - return 0;
> -}
> -
> static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
> {
> - int rc;
> -
> - if (!kvm_s390_use_sca_entries()) {
> - if (id < KVM_MAX_VCPUS)
> - return true;
> - return false;
> - }
> - if (id < KVM_S390_BSCA_CPU_SLOTS)
> - return true;
> - if (!sclp.has_esca || !sclp.has_64bscao)
> - return false;
> -
> - rc = kvm->arch.use_esca ? 0 : sca_switch_to_extended(kvm);
> + if (!kvm_s390_use_sca_entries())
> + return id < KVM_MAX_VCPUS;
>
> - return rc == 0 && id < KVM_S390_ESCA_CPU_SLOTS;
> + return id < KVM_S390_ESCA_CPU_SLOTS;
> }
>
> /* needs disabled preemption to protect from TOD sync and vcpu_load/put */
> @@ -3919,7 +3808,7 @@ static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)
> vcpu->arch.sie_block->eca |= ECA_IB;
> if (sclp.has_siif)
> vcpu->arch.sie_block->eca |= ECA_SII;
> - if (sclp.has_sigpif)
> + if (kvm_s390_use_sca_entries())
> vcpu->arch.sie_block->eca |= ECA_SIGPI;
> if (test_kvm_facility(vcpu->kvm, 129)) {
> vcpu->arch.sie_block->eca |= ECA_VX;
> diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
> index 8d3bbb2dd8d27802bbde2a7bd1378033ad614b8e..2c8e177e4af8f2dab07fd42a904cefdea80f6855 100644
> --- a/arch/s390/kvm/kvm-s390.h
> +++ b/arch/s390/kvm/kvm-s390.h
> @@ -531,7 +531,7 @@ int kvm_s390_handle_per_event(struct kvm_vcpu *vcpu);
> /* support for Basic/Extended SCA handling */
> static inline union ipte_control *kvm_s390_get_ipte_control(struct kvm *kvm)
> {
> - struct bsca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
> + struct esca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
>
> return &sca->ipte_control;
> }
> @@ -542,7 +542,7 @@ static inline int kvm_s390_use_sca_entries(void)
> * might use the entries. By not setting the entries and keeping them
> * invalid, hardware will not access them but intercept.
> */
> - return sclp.has_sigpif;
> + return sclp.has_sigpif && sclp.has_esca;
> }
> void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
> struct mcck_volatile_info *mcck_info);
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/3] KVM: s390: Always allocate esca_block
2025-05-22 9:31 ` [PATCH v3 2/3] KVM: s390: Always allocate esca_block Christoph Schlameuss
2025-05-22 10:49 ` Claudio Imbrenda
@ 2025-05-26 8:22 ` Janosch Frank
2025-06-02 10:01 ` Christoph Schlameuss
2025-05-26 10:36 ` Janosch Frank
2 siblings, 1 reply; 10+ messages in thread
From: Janosch Frank @ 2025-05-26 8:22 UTC (permalink / raw)
To: Christoph Schlameuss, kvm
Cc: linux-s390, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Sven Schnelle, Thomas Huth
On 5/22/25 11:31 AM, Christoph Schlameuss wrote:
> Instead of allocating a BSCA and upgrading it for PV or when adding the
> 65th cpu we can always use the ESCA.
>
> The only downside of the change is that we will always allocate 4 pages
> for a 248 cpu ESCA instead of a single page for the BSCA per VM.
> In return we can delete a bunch of checks and special handling depending
> on the SCA type as well as the whole BSCA to ESCA conversion.
>
> As a fallback we can still run without SCA entries when the SIGP
> interpretation facility or ESCA are not available.
>
> Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
> ---
> arch/s390/include/asm/kvm_host.h | 1 -
> arch/s390/kvm/interrupt.c | 71 +++++------------
> arch/s390/kvm/kvm-s390.c | 161 ++++++---------------------------------
> arch/s390/kvm/kvm-s390.h | 4 +-
> 4 files changed, 45 insertions(+), 192 deletions(-)
[...]
> @@ -80,33 +70,17 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
>
> BUG_ON(!kvm_s390_use_sca_entries());
> read_lock(&vcpu->kvm->arch.sca_lock);
> - if (vcpu->kvm->arch.use_esca) {
> - struct esca_block *sca = vcpu->kvm->arch.sca;
> - union esca_sigp_ctrl *sigp_ctrl =
> - &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
> - union esca_sigp_ctrl new_val = {0}, old_val;
> -
> - old_val = READ_ONCE(*sigp_ctrl);
> - new_val.scn = src_id;
> - new_val.c = 1;
> - old_val.c = 0;
> -
> - expect = old_val.value;
> - rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
> - } else {
> - struct bsca_block *sca = vcpu->kvm->arch.sca;
> - union bsca_sigp_ctrl *sigp_ctrl =
> - &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
> - union bsca_sigp_ctrl new_val = {0}, old_val;
> + struct esca_block *sca = vcpu->kvm->arch.sca;
> + union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
> + union esca_sigp_ctrl new_val = {0}, old_val;
Since we don't have a need for inline declarations anymore, could you
move those to the beginning of the function?
@Christian @Claudio:
Another interesting question is locking.
The SCA RW lock protected against the bsca->esca switch which never
happens after this patch.
Can't we rip out that lock and maybe get a bit of performance and even
less code? (In another patch set to limit the destructive potential)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/3] KVM: s390: Always allocate esca_block
2025-05-22 9:31 ` [PATCH v3 2/3] KVM: s390: Always allocate esca_block Christoph Schlameuss
2025-05-22 10:49 ` Claudio Imbrenda
2025-05-26 8:22 ` Janosch Frank
@ 2025-05-26 10:36 ` Janosch Frank
2025-06-02 9:24 ` Christoph Schlameuss
2 siblings, 1 reply; 10+ messages in thread
From: Janosch Frank @ 2025-05-26 10:36 UTC (permalink / raw)
To: Christoph Schlameuss, kvm
Cc: linux-s390, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Sven Schnelle, Thomas Huth
On 5/22/25 11:31 AM, Christoph Schlameuss wrote:
> Instead of allocating a BSCA and upgrading it for PV or when adding the
> 65th cpu we can always use the ESCA.
>
> The only downside of the change is that we will always allocate 4 pages
> for a 248 cpu ESCA instead of a single page for the BSCA per VM.
> In return we can delete a bunch of checks and special handling depending
> on the SCA type as well as the whole BSCA to ESCA conversion.
>
> As a fallback we can still run without SCA entries when the SIGP
> interpretation facility or ESCA are not available.
>
> Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
> ---
> arch/s390/include/asm/kvm_host.h | 1 -
> arch/s390/kvm/interrupt.c | 71 +++++------------
> arch/s390/kvm/kvm-s390.c | 161 ++++++---------------------------------
> arch/s390/kvm/kvm-s390.h | 4 +-
> 4 files changed, 45 insertions(+), 192 deletions(-)
>
> diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
> index f51bac835260f562eaf4bbfd373a24bfdbc43834..d03e354a63d9c931522c1a1607eba8685c24527f 100644
> --- a/arch/s390/include/asm/kvm_host.h
> +++ b/arch/s390/include/asm/kvm_host.h
> @@ -631,7 +631,6 @@ struct kvm_s390_pv {
>
[...]
> int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
> {
> - gfp_t alloc_flags = GFP_KERNEL_ACCOUNT;
> - int i, rc;
> + gfp_t alloc_flags = GFP_KERNEL_ACCOUNT | __GFP_ZERO;
> char debug_name[16];
> - static unsigned long sca_offset;
> + int i, rc;
>
> rc = -EINVAL;
> #ifdef CONFIG_KVM_S390_UCONTROL
> @@ -3358,17 +3341,12 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
> if (!sclp.has_64bscao)
> alloc_flags |= GFP_DMA;
> rwlock_init(&kvm->arch.sca_lock);
> - /* start with basic SCA */
> - kvm->arch.sca = (struct bsca_block *) get_zeroed_page(alloc_flags);
> - if (!kvm->arch.sca)
> - goto out_err;
> mutex_lock(&kvm_lock);
> - sca_offset += 16;
> - if (sca_offset + sizeof(struct bsca_block) > PAGE_SIZE)
> - sca_offset = 0;
> - kvm->arch.sca = (struct bsca_block *)
> - ((char *) kvm->arch.sca + sca_offset);
> +
> + kvm->arch.sca = alloc_pages_exact(sizeof(*kvm->arch.sca), alloc_flags);
kvm->arch.sca is (void *) at the point of this patch, which makes this a
very bad idea. Granted, you fix that up in the next patch but this is
still wrong.
Any reason why you have patch #3 at all?
We could just squash it and avoid this problem?
> mutex_unlock(&kvm_lock);
> + if (!kvm->arch.sca)
> + goto out_err;
>
> sprintf(debug_name, "kvm-%u", current->pid);
>
[...]
> /* needs disabled preemption to protect from TOD sync and vcpu_load/put */
> @@ -3919,7 +3808,7 @@ static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)
> vcpu->arch.sie_block->eca |= ECA_IB;
> if (sclp.has_siif)
> vcpu->arch.sie_block->eca |= ECA_SII;
> - if (sclp.has_sigpif)
> + if (kvm_s390_use_sca_entries())
> vcpu->arch.sie_block->eca |= ECA_SIGPI;
> if (test_kvm_facility(vcpu->kvm, 129)) {
> vcpu->arch.sie_block->eca |= ECA_VX;
> diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
> index 8d3bbb2dd8d27802bbde2a7bd1378033ad614b8e..2c8e177e4af8f2dab07fd42a904cefdea80f6855 100644
> --- a/arch/s390/kvm/kvm-s390.h
> +++ b/arch/s390/kvm/kvm-s390.h
> @@ -531,7 +531,7 @@ int kvm_s390_handle_per_event(struct kvm_vcpu *vcpu);
> /* support for Basic/Extended SCA handling */
> static inline union ipte_control *kvm_s390_get_ipte_control(struct kvm *kvm)
> {
> - struct bsca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
> + struct esca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
Remove the comment as well please
>
> return &sca->ipte_control;
> }
> @@ -542,7 +542,7 @@ static inline int kvm_s390_use_sca_entries(void)
> * might use the entries. By not setting the entries and keeping them
> * invalid, hardware will not access them but intercept.
> */
> - return sclp.has_sigpif;
> + return sclp.has_sigpif && sclp.has_esca;
> }
> void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
> struct mcck_volatile_info *mcck_info);
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 1/3] KVM: s390: Set KVM_MAX_VCPUS to 256
2025-05-22 9:31 ` [PATCH v3 1/3] KVM: s390: Set KVM_MAX_VCPUS to 256 Christoph Schlameuss
@ 2025-05-30 7:39 ` Janosch Frank
0 siblings, 0 replies; 10+ messages in thread
From: Janosch Frank @ 2025-05-30 7:39 UTC (permalink / raw)
To: Christoph Schlameuss, kvm
Cc: linux-s390, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Sven Schnelle, Thomas Huth
On 5/22/25 11:31 AM, Christoph Schlameuss wrote:
> The s390x architecture allows for 256 vCPUs with a max CPUID of 255.
> The current KVM implementation limits this to 248 when using the
> extended system control area (ESCA). So this correction should not cause
> any real world problems but actually correct the values returned by the
> ioctls:
>
> * KVM_CAP_NR_VCPUS
> * KVM_CAP_MAX_VCPUS
> * KVM_CAP_MAX_VCPU_ID
>
> KVM_MAX_VCPUS is also moved to kvm_host_types to allow using this in
> future type definitions.
>
> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
> ---
> arch/s390/include/asm/kvm_host.h | 2 --
> arch/s390/include/asm/kvm_host_types.h | 2 ++
> arch/s390/kvm/kvm-s390.c | 2 ++
> 3 files changed, 4 insertions(+), 2 deletions(-)
[...]
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 3f3175193fd7a7a26658eb2e2533d8037447a0b4..b65e4cbe67cf70a7d614607ebdd679060e7d31f4 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -638,6 +638,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> r = KVM_S390_ESCA_CPU_SLOTS;
> if (ext == KVM_CAP_NR_VCPUS)
> r = min_t(unsigned int, num_online_cpus(), r);
> + else if (ext == KVM_CAP_MAX_VCPU_ID)
> + r -= 1;
I went on a wild goose chase since this change broke the max vcpu
selftest. Turns out that KVM_CAP_MAX_VCPU_ID is actually
KVM_CAP_MAX_VCPU_ID_S_ but we can't rename it since it's part of the API
(sigh). Have a look at the KVM changes and it will make a bit more sense.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/3] KVM: s390: Always allocate esca_block
2025-05-26 10:36 ` Janosch Frank
@ 2025-06-02 9:24 ` Christoph Schlameuss
0 siblings, 0 replies; 10+ messages in thread
From: Christoph Schlameuss @ 2025-06-02 9:24 UTC (permalink / raw)
To: Janosch Frank, kvm
Cc: linux-s390, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Sven Schnelle, Thomas Huth
On Mon May 26, 2025 at 12:36 PM CEST, Janosch Frank wrote:
> On 5/22/25 11:31 AM, Christoph Schlameuss wrote:
>> Instead of allocating a BSCA and upgrading it for PV or when adding the
>> 65th cpu we can always use the ESCA.
>>
>> The only downside of the change is that we will always allocate 4 pages
>> for a 248 cpu ESCA instead of a single page for the BSCA per VM.
>> In return we can delete a bunch of checks and special handling depending
>> on the SCA type as well as the whole BSCA to ESCA conversion.
>>
>> As a fallback we can still run without SCA entries when the SIGP
>> interpretation facility or ESCA are not available.
>>
>> Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
>> ---
>> arch/s390/include/asm/kvm_host.h | 1 -
>> arch/s390/kvm/interrupt.c | 71 +++++------------
>> arch/s390/kvm/kvm-s390.c | 161 ++++++---------------------------------
>> arch/s390/kvm/kvm-s390.h | 4 +-
>> 4 files changed, 45 insertions(+), 192 deletions(-)
>>
>> diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
>> index f51bac835260f562eaf4bbfd373a24bfdbc43834..d03e354a63d9c931522c1a1607eba8685c24527f 100644
>> --- a/arch/s390/include/asm/kvm_host.h
>> +++ b/arch/s390/include/asm/kvm_host.h
>> @@ -631,7 +631,6 @@ struct kvm_s390_pv {
>>
>
> [...]
>
>> int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
>> {
>> - gfp_t alloc_flags = GFP_KERNEL_ACCOUNT;
>> - int i, rc;
>> + gfp_t alloc_flags = GFP_KERNEL_ACCOUNT | __GFP_ZERO;
>> char debug_name[16];
>> - static unsigned long sca_offset;
>> + int i, rc;
>>
>> rc = -EINVAL;
>> #ifdef CONFIG_KVM_S390_UCONTROL
>> @@ -3358,17 +3341,12 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
>> if (!sclp.has_64bscao)
>> alloc_flags |= GFP_DMA;
>> rwlock_init(&kvm->arch.sca_lock);
>> - /* start with basic SCA */
>> - kvm->arch.sca = (struct bsca_block *) get_zeroed_page(alloc_flags);
>> - if (!kvm->arch.sca)
>> - goto out_err;
>> mutex_lock(&kvm_lock);
>> - sca_offset += 16;
>> - if (sca_offset + sizeof(struct bsca_block) > PAGE_SIZE)
>> - sca_offset = 0;
>> - kvm->arch.sca = (struct bsca_block *)
>> - ((char *) kvm->arch.sca + sca_offset);
>> +
>> + kvm->arch.sca = alloc_pages_exact(sizeof(*kvm->arch.sca), alloc_flags);
>
> kvm->arch.sca is (void *) at the point of this patch, which makes this a
> very bad idea. Granted, you fix that up in the next patch but this is
> still wrong.
>
> Any reason why you have patch #3 at all?
> We could just squash it and avoid this problem?
>
Yes, I can just roll that up into a single patch. Just thought it would be a bit
easier to review this way.
>> mutex_unlock(&kvm_lock);
>> + if (!kvm->arch.sca)
>> + goto out_err;
>>
>> sprintf(debug_name, "kvm-%u", current->pid);
>>
>
> [...]
>
>> /* needs disabled preemption to protect from TOD sync and vcpu_load/put */
>> @@ -3919,7 +3808,7 @@ static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)
>> vcpu->arch.sie_block->eca |= ECA_IB;
>> if (sclp.has_siif)
>> vcpu->arch.sie_block->eca |= ECA_SII;
>> - if (sclp.has_sigpif)
>> + if (kvm_s390_use_sca_entries())
>> vcpu->arch.sie_block->eca |= ECA_SIGPI;
>> if (test_kvm_facility(vcpu->kvm, 129)) {
>> vcpu->arch.sie_block->eca |= ECA_VX;
>> diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
>> index 8d3bbb2dd8d27802bbde2a7bd1378033ad614b8e..2c8e177e4af8f2dab07fd42a904cefdea80f6855 100644
>> --- a/arch/s390/kvm/kvm-s390.h
>> +++ b/arch/s390/kvm/kvm-s390.h
>> @@ -531,7 +531,7 @@ int kvm_s390_handle_per_event(struct kvm_vcpu *vcpu);
>> /* support for Basic/Extended SCA handling */
>> static inline union ipte_control *kvm_s390_get_ipte_control(struct kvm *kvm)
>> {
>> - struct bsca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
>> + struct esca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
>
> Remove the comment as well please
>
That's also fully removed in patch 3 along with he whole method.
>>
>> return &sca->ipte_control;
>> }
>> @@ -542,7 +542,7 @@ static inline int kvm_s390_use_sca_entries(void)
>> * might use the entries. By not setting the entries and keeping them
>> * invalid, hardware will not access them but intercept.
>> */
>> - return sclp.has_sigpif;
>> + return sclp.has_sigpif && sclp.has_esca;
>> }
>> void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
>> struct mcck_volatile_info *mcck_info);
>>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/3] KVM: s390: Always allocate esca_block
2025-05-26 8:22 ` Janosch Frank
@ 2025-06-02 10:01 ` Christoph Schlameuss
0 siblings, 0 replies; 10+ messages in thread
From: Christoph Schlameuss @ 2025-06-02 10:01 UTC (permalink / raw)
To: Janosch Frank, kvm
Cc: linux-s390, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Sven Schnelle, Thomas Huth
On Mon May 26, 2025 at 10:22 AM CEST, Janosch Frank wrote:
> On 5/22/25 11:31 AM, Christoph Schlameuss wrote:
>> Instead of allocating a BSCA and upgrading it for PV or when adding the
>> 65th cpu we can always use the ESCA.
>>
>> The only downside of the change is that we will always allocate 4 pages
>> for a 248 cpu ESCA instead of a single page for the BSCA per VM.
>> In return we can delete a bunch of checks and special handling depending
>> on the SCA type as well as the whole BSCA to ESCA conversion.
>>
>> As a fallback we can still run without SCA entries when the SIGP
>> interpretation facility or ESCA are not available.
>>
>> Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
>> ---
>> arch/s390/include/asm/kvm_host.h | 1 -
>> arch/s390/kvm/interrupt.c | 71 +++++------------
>> arch/s390/kvm/kvm-s390.c | 161 ++++++---------------------------------
>> arch/s390/kvm/kvm-s390.h | 4 +-
>> 4 files changed, 45 insertions(+), 192 deletions(-)
>
> [...]
>
>> @@ -80,33 +70,17 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
>>
>> BUG_ON(!kvm_s390_use_sca_entries());
>> read_lock(&vcpu->kvm->arch.sca_lock);
>> - if (vcpu->kvm->arch.use_esca) {
>> - struct esca_block *sca = vcpu->kvm->arch.sca;
>> - union esca_sigp_ctrl *sigp_ctrl =
>> - &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
>> - union esca_sigp_ctrl new_val = {0}, old_val;
>> -
>> - old_val = READ_ONCE(*sigp_ctrl);
>> - new_val.scn = src_id;
>> - new_val.c = 1;
>> - old_val.c = 0;
>> -
>> - expect = old_val.value;
>> - rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
>> - } else {
>> - struct bsca_block *sca = vcpu->kvm->arch.sca;
>> - union bsca_sigp_ctrl *sigp_ctrl =
>> - &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
>> - union bsca_sigp_ctrl new_val = {0}, old_val;
>> + struct esca_block *sca = vcpu->kvm->arch.sca;
>> + union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
>> + union esca_sigp_ctrl new_val = {0}, old_val;
>
>
> Since we don't have a need for inline declarations anymore, could you
> move those to the beginning of the function?
That would mean moving the sca access here out of the read lock. So I would
rather include that in a patch removing the sca_lock completely.
>
> @Christian @Claudio:
> Another interesting question is locking.
> The SCA RW lock protected against the bsca->esca switch which never
> happens after this patch.
>
> Can't we rip out that lock and maybe get a bit of performance and even
> less code? (In another patch set to limit the destructive potential)
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-06-02 10:02 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-22 9:31 [PATCH v3 0/3] KVM: s390: Use ESCA instead of BSCA at VM init Christoph Schlameuss
2025-05-22 9:31 ` [PATCH v3 1/3] KVM: s390: Set KVM_MAX_VCPUS to 256 Christoph Schlameuss
2025-05-30 7:39 ` Janosch Frank
2025-05-22 9:31 ` [PATCH v3 2/3] KVM: s390: Always allocate esca_block Christoph Schlameuss
2025-05-22 10:49 ` Claudio Imbrenda
2025-05-26 8:22 ` Janosch Frank
2025-06-02 10:01 ` Christoph Schlameuss
2025-05-26 10:36 ` Janosch Frank
2025-06-02 9:24 ` Christoph Schlameuss
2025-05-22 9:31 ` [PATCH v3 3/3] KVM: s390: Specify kvm->arch.sca as esca_block Christoph Schlameuss
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).