mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
KVM: S390: Remove sca_lock
Since we are no longer switching from a BSCA to a ESCA we can completely get rid of the sca_lock. The write lock was only taken for that conversion. After removal of the lock some local code cleanups are possible. Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com> Suggested-by: Janosch Frank <frankja@linux.ibm.com> [frankja@linux.ibm.com: Added suggested-by tag as discussed on list] Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
This commit is contained in:
parent
e72753ed12
commit
14542a0a54
|
|
@ -633,7 +633,6 @@ struct kvm_s390_pv {
|
||||||
|
|
||||||
struct kvm_arch {
|
struct kvm_arch {
|
||||||
struct esca_block *sca;
|
struct esca_block *sca;
|
||||||
rwlock_t sca_lock;
|
|
||||||
debug_info_t *dbf;
|
debug_info_t *dbf;
|
||||||
struct kvm_s390_float_interrupt float_int;
|
struct kvm_s390_float_interrupt float_int;
|
||||||
struct kvm_device *flic;
|
struct kvm_device *flic;
|
||||||
|
|
|
||||||
|
|
@ -109,14 +109,9 @@ struct aste {
|
||||||
|
|
||||||
int ipte_lock_held(struct kvm *kvm)
|
int ipte_lock_held(struct kvm *kvm)
|
||||||
{
|
{
|
||||||
if (sclp.has_siif) {
|
if (sclp.has_siif)
|
||||||
int rc;
|
return kvm->arch.sca->ipte_control.kh != 0;
|
||||||
|
|
||||||
read_lock(&kvm->arch.sca_lock);
|
|
||||||
rc = kvm->arch.sca->ipte_control.kh != 0;
|
|
||||||
read_unlock(&kvm->arch.sca_lock);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
return kvm->arch.ipte_lock_count != 0;
|
return kvm->arch.ipte_lock_count != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,19 +124,16 @@ static void ipte_lock_simple(struct kvm *kvm)
|
||||||
if (kvm->arch.ipte_lock_count > 1)
|
if (kvm->arch.ipte_lock_count > 1)
|
||||||
goto out;
|
goto out;
|
||||||
retry:
|
retry:
|
||||||
read_lock(&kvm->arch.sca_lock);
|
|
||||||
ic = &kvm->arch.sca->ipte_control;
|
ic = &kvm->arch.sca->ipte_control;
|
||||||
old = READ_ONCE(*ic);
|
old = READ_ONCE(*ic);
|
||||||
do {
|
do {
|
||||||
if (old.k) {
|
if (old.k) {
|
||||||
read_unlock(&kvm->arch.sca_lock);
|
|
||||||
cond_resched();
|
cond_resched();
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
new = old;
|
new = old;
|
||||||
new.k = 1;
|
new.k = 1;
|
||||||
} while (!try_cmpxchg(&ic->val, &old.val, new.val));
|
} while (!try_cmpxchg(&ic->val, &old.val, new.val));
|
||||||
read_unlock(&kvm->arch.sca_lock);
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&kvm->arch.ipte_mutex);
|
mutex_unlock(&kvm->arch.ipte_mutex);
|
||||||
}
|
}
|
||||||
|
|
@ -154,14 +146,12 @@ static void ipte_unlock_simple(struct kvm *kvm)
|
||||||
kvm->arch.ipte_lock_count--;
|
kvm->arch.ipte_lock_count--;
|
||||||
if (kvm->arch.ipte_lock_count)
|
if (kvm->arch.ipte_lock_count)
|
||||||
goto out;
|
goto out;
|
||||||
read_lock(&kvm->arch.sca_lock);
|
|
||||||
ic = &kvm->arch.sca->ipte_control;
|
ic = &kvm->arch.sca->ipte_control;
|
||||||
old = READ_ONCE(*ic);
|
old = READ_ONCE(*ic);
|
||||||
do {
|
do {
|
||||||
new = old;
|
new = old;
|
||||||
new.k = 0;
|
new.k = 0;
|
||||||
} while (!try_cmpxchg(&ic->val, &old.val, new.val));
|
} while (!try_cmpxchg(&ic->val, &old.val, new.val));
|
||||||
read_unlock(&kvm->arch.sca_lock);
|
|
||||||
wake_up(&kvm->arch.ipte_wq);
|
wake_up(&kvm->arch.ipte_wq);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&kvm->arch.ipte_mutex);
|
mutex_unlock(&kvm->arch.ipte_mutex);
|
||||||
|
|
@ -172,12 +162,10 @@ static void ipte_lock_siif(struct kvm *kvm)
|
||||||
union ipte_control old, new, *ic;
|
union ipte_control old, new, *ic;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
read_lock(&kvm->arch.sca_lock);
|
|
||||||
ic = &kvm->arch.sca->ipte_control;
|
ic = &kvm->arch.sca->ipte_control;
|
||||||
old = READ_ONCE(*ic);
|
old = READ_ONCE(*ic);
|
||||||
do {
|
do {
|
||||||
if (old.kg) {
|
if (old.kg) {
|
||||||
read_unlock(&kvm->arch.sca_lock);
|
|
||||||
cond_resched();
|
cond_resched();
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
@ -185,14 +173,12 @@ static void ipte_lock_siif(struct kvm *kvm)
|
||||||
new.k = 1;
|
new.k = 1;
|
||||||
new.kh++;
|
new.kh++;
|
||||||
} while (!try_cmpxchg(&ic->val, &old.val, new.val));
|
} while (!try_cmpxchg(&ic->val, &old.val, new.val));
|
||||||
read_unlock(&kvm->arch.sca_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ipte_unlock_siif(struct kvm *kvm)
|
static void ipte_unlock_siif(struct kvm *kvm)
|
||||||
{
|
{
|
||||||
union ipte_control old, new, *ic;
|
union ipte_control old, new, *ic;
|
||||||
|
|
||||||
read_lock(&kvm->arch.sca_lock);
|
|
||||||
ic = &kvm->arch.sca->ipte_control;
|
ic = &kvm->arch.sca->ipte_control;
|
||||||
old = READ_ONCE(*ic);
|
old = READ_ONCE(*ic);
|
||||||
do {
|
do {
|
||||||
|
|
@ -201,7 +187,6 @@ static void ipte_unlock_siif(struct kvm *kvm)
|
||||||
if (!new.kh)
|
if (!new.kh)
|
||||||
new.k = 0;
|
new.k = 0;
|
||||||
} while (!try_cmpxchg(&ic->val, &old.val, new.val));
|
} while (!try_cmpxchg(&ic->val, &old.val, new.val));
|
||||||
read_unlock(&kvm->arch.sca_lock);
|
|
||||||
if (!new.kh)
|
if (!new.kh)
|
||||||
wake_up(&kvm->arch.ipte_wq);
|
wake_up(&kvm->arch.ipte_wq);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,48 +45,34 @@ static struct kvm_s390_gib *gib;
|
||||||
/* handle external calls via sigp interpretation facility */
|
/* handle external calls via sigp interpretation facility */
|
||||||
static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
|
static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
|
||||||
{
|
{
|
||||||
union esca_sigp_ctrl sigp_ctrl;
|
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||||
struct esca_block *sca;
|
union esca_sigp_ctrl sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||||
int c, scn;
|
|
||||||
|
|
||||||
if (!kvm_s390_test_cpuflags(vcpu, CPUSTAT_ECALL_PEND))
|
if (!kvm_s390_test_cpuflags(vcpu, CPUSTAT_ECALL_PEND))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
BUG_ON(!kvm_s390_use_sca_entries());
|
BUG_ON(!kvm_s390_use_sca_entries());
|
||||||
read_lock(&vcpu->kvm->arch.sca_lock);
|
|
||||||
sca = vcpu->kvm->arch.sca;
|
|
||||||
sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
|
||||||
|
|
||||||
c = sigp_ctrl.c;
|
|
||||||
scn = sigp_ctrl.scn;
|
|
||||||
read_unlock(&vcpu->kvm->arch.sca_lock);
|
|
||||||
|
|
||||||
if (src_id)
|
if (src_id)
|
||||||
*src_id = scn;
|
*src_id = sigp_ctrl.scn;
|
||||||
|
|
||||||
return c;
|
return sigp_ctrl.c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
|
static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
|
||||||
{
|
{
|
||||||
union esca_sigp_ctrl old_val, new_val = {0};
|
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||||
union esca_sigp_ctrl *sigp_ctrl;
|
union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||||
struct esca_block *sca;
|
union esca_sigp_ctrl old_val, new_val = {.scn = src_id, .c = 1};
|
||||||
int expect, rc;
|
int expect, rc;
|
||||||
|
|
||||||
BUG_ON(!kvm_s390_use_sca_entries());
|
BUG_ON(!kvm_s390_use_sca_entries());
|
||||||
read_lock(&vcpu->kvm->arch.sca_lock);
|
|
||||||
sca = vcpu->kvm->arch.sca;
|
|
||||||
sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
|
||||||
|
|
||||||
old_val = READ_ONCE(*sigp_ctrl);
|
old_val = READ_ONCE(*sigp_ctrl);
|
||||||
new_val.scn = src_id;
|
|
||||||
new_val.c = 1;
|
|
||||||
old_val.c = 0;
|
old_val.c = 0;
|
||||||
|
|
||||||
expect = old_val.value;
|
expect = old_val.value;
|
||||||
rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
|
rc = cmpxchg(&sigp_ctrl->value, old_val.value, new_val.value);
|
||||||
read_unlock(&vcpu->kvm->arch.sca_lock);
|
|
||||||
|
|
||||||
if (rc != expect) {
|
if (rc != expect) {
|
||||||
/* another external call is pending */
|
/* another external call is pending */
|
||||||
|
|
@ -98,18 +84,14 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
|
||||||
|
|
||||||
static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
|
static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
union esca_sigp_ctrl *sigp_ctrl;
|
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||||
struct esca_block *sca;
|
union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||||
|
|
||||||
if (!kvm_s390_use_sca_entries())
|
if (!kvm_s390_use_sca_entries())
|
||||||
return;
|
return;
|
||||||
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
|
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
|
||||||
read_lock(&vcpu->kvm->arch.sca_lock);
|
|
||||||
sca = vcpu->kvm->arch.sca;
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int psw_extint_disabled(struct kvm_vcpu *vcpu)
|
int psw_extint_disabled(struct kvm_vcpu *vcpu)
|
||||||
|
|
|
||||||
|
|
@ -1938,14 +1938,12 @@ static void kvm_s390_update_topology_change_report(struct kvm *kvm, bool val)
|
||||||
union sca_utility new, old;
|
union sca_utility new, old;
|
||||||
struct esca_block *sca;
|
struct esca_block *sca;
|
||||||
|
|
||||||
read_lock(&kvm->arch.sca_lock);
|
|
||||||
sca = kvm->arch.sca;
|
sca = kvm->arch.sca;
|
||||||
old = READ_ONCE(sca->utility);
|
old = READ_ONCE(sca->utility);
|
||||||
do {
|
do {
|
||||||
new = old;
|
new = old;
|
||||||
new.mtcr = val;
|
new.mtcr = val;
|
||||||
} while (!try_cmpxchg(&sca->utility.val, &old.val, new.val));
|
} while (!try_cmpxchg(&sca->utility.val, &old.val, new.val));
|
||||||
read_unlock(&kvm->arch.sca_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kvm_s390_set_topo_change_indication(struct kvm *kvm,
|
static int kvm_s390_set_topo_change_indication(struct kvm *kvm,
|
||||||
|
|
@ -1966,9 +1964,7 @@ static int kvm_s390_get_topo_change_indication(struct kvm *kvm,
|
||||||
if (!test_kvm_facility(kvm, 11))
|
if (!test_kvm_facility(kvm, 11))
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
read_lock(&kvm->arch.sca_lock);
|
|
||||||
topo = 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);
|
return put_user(topo, (u8 __user *)attr->addr);
|
||||||
}
|
}
|
||||||
|
|
@ -3345,7 +3341,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||||
|
|
||||||
if (!sclp.has_64bscao)
|
if (!sclp.has_64bscao)
|
||||||
alloc_flags |= GFP_DMA;
|
alloc_flags |= GFP_DMA;
|
||||||
rwlock_init(&kvm->arch.sca_lock);
|
|
||||||
mutex_lock(&kvm_lock);
|
mutex_lock(&kvm_lock);
|
||||||
|
|
||||||
kvm->arch.sca = alloc_pages_exact(sizeof(*kvm->arch.sca), alloc_flags);
|
kvm->arch.sca = alloc_pages_exact(sizeof(*kvm->arch.sca), alloc_flags);
|
||||||
|
|
@ -3530,41 +3525,30 @@ static int __kvm_ucontrol_vcpu_init(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
static void sca_del_vcpu(struct kvm_vcpu *vcpu)
|
static void sca_del_vcpu(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct esca_block *sca;
|
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||||
|
|
||||||
if (!kvm_s390_use_sca_entries())
|
if (!kvm_s390_use_sca_entries())
|
||||||
return;
|
return;
|
||||||
read_lock(&vcpu->kvm->arch.sca_lock);
|
|
||||||
sca = vcpu->kvm->arch.sca;
|
|
||||||
|
|
||||||
clear_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
|
clear_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
|
||||||
sca->cpu[vcpu->vcpu_id].sda = 0;
|
sca->cpu[vcpu->vcpu_id].sda = 0;
|
||||||
read_unlock(&vcpu->kvm->arch.sca_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sca_add_vcpu(struct kvm_vcpu *vcpu)
|
static void sca_add_vcpu(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct esca_block *sca;
|
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||||
phys_addr_t sca_phys;
|
phys_addr_t sca_phys = virt_to_phys(sca);
|
||||||
|
|
||||||
if (!kvm_s390_use_sca_entries()) {
|
/* we still need the sca header for the ipte control */
|
||||||
sca_phys = virt_to_phys(vcpu->kvm->arch.sca);
|
|
||||||
|
|
||||||
/* we still need the basic sca for the ipte control */
|
|
||||||
vcpu->arch.sie_block->scaoh = sca_phys >> 32;
|
|
||||||
vcpu->arch.sie_block->scaol = sca_phys;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
read_lock(&vcpu->kvm->arch.sca_lock);
|
|
||||||
sca = vcpu->kvm->arch.sca;
|
|
||||||
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->scaoh = sca_phys >> 32;
|
||||||
vcpu->arch.sie_block->scaol = sca_phys & ESCA_SCAOL_MASK;
|
vcpu->arch.sie_block->scaol = sca_phys & ESCA_SCAOL_MASK;
|
||||||
vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
|
vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
|
||||||
|
|
||||||
|
if (!kvm_s390_use_sca_entries())
|
||||||
|
return;
|
||||||
|
|
||||||
set_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
|
set_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
|
||||||
read_unlock(&vcpu->kvm->arch.sca_lock);
|
sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
|
static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user