KVM: PPC: Book3S HV: Rename hpte_setup_done to mmu_ready
This renames the kvm->arch.hpte_setup_done field to mmu_ready because we will want to use it for radix guests too -- both for setting things up before vcpu execution, and for excluding vcpus from executing while MMU-related things get changed, such as in future switching the MMU from radix to HPT mode or vice-versa. This also moves the call to kvmppc_setup_partition_table() that was done in kvmppc_hv_setup_htab_rma() for HPT guests, and the setting of mmu_ready, into the caller in kvmppc_vcpu_run_hv(). Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
8dc6cca556
commit
1b151ce466
|
@ -276,7 +276,7 @@ struct kvm_arch {
|
|||
int tlbie_lock;
|
||||
unsigned long lpcr;
|
||||
unsigned long vrma_slb_v;
|
||||
int hpte_setup_done;
|
||||
int mmu_ready;
|
||||
atomic_t vcpus_running;
|
||||
u32 online_vcores;
|
||||
atomic_t hpte_mod_interest;
|
||||
|
|
|
@ -140,12 +140,12 @@ long kvmppc_alloc_reset_hpt(struct kvm *kvm, int order)
|
|||
return -EINVAL;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
if (kvm->arch.hpte_setup_done) {
|
||||
kvm->arch.hpte_setup_done = 0;
|
||||
/* order hpte_setup_done vs. vcpus_running */
|
||||
if (kvm->arch.mmu_ready) {
|
||||
kvm->arch.mmu_ready = 0;
|
||||
/* order mmu_ready vs. vcpus_running */
|
||||
smp_mb();
|
||||
if (atomic_read(&kvm->arch.vcpus_running)) {
|
||||
kvm->arch.hpte_setup_done = 1;
|
||||
kvm->arch.mmu_ready = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -1533,15 +1533,15 @@ long kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm,
|
|||
|
||||
/* This shouldn't be possible */
|
||||
ret = -EIO;
|
||||
if (WARN_ON(!kvm->arch.hpte_setup_done))
|
||||
if (WARN_ON(!kvm->arch.mmu_ready))
|
||||
goto out_no_hpt;
|
||||
|
||||
/* Stop VCPUs from running while we mess with the HPT */
|
||||
kvm->arch.hpte_setup_done = 0;
|
||||
kvm->arch.mmu_ready = 0;
|
||||
smp_mb();
|
||||
|
||||
/* Boot all CPUs out of the guest so they re-read
|
||||
* hpte_setup_done */
|
||||
* mmu_ready */
|
||||
on_each_cpu(resize_hpt_boot_vcpu, NULL, 1);
|
||||
|
||||
ret = -ENXIO;
|
||||
|
@ -1564,7 +1564,7 @@ long kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm,
|
|||
|
||||
out:
|
||||
/* Let VCPUs run again */
|
||||
kvm->arch.hpte_setup_done = 1;
|
||||
kvm->arch.mmu_ready = 1;
|
||||
smp_mb();
|
||||
out_no_hpt:
|
||||
resize_hpt_release(kvm, resize);
|
||||
|
@ -1802,7 +1802,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
|
|||
unsigned long tmp[2];
|
||||
ssize_t nb;
|
||||
long int err, ret;
|
||||
int hpte_setup;
|
||||
int mmu_ready;
|
||||
|
||||
if (!access_ok(VERIFY_READ, buf, count))
|
||||
return -EFAULT;
|
||||
|
@ -1811,13 +1811,13 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
|
|||
|
||||
/* lock out vcpus from running while we're doing this */
|
||||
mutex_lock(&kvm->lock);
|
||||
hpte_setup = kvm->arch.hpte_setup_done;
|
||||
if (hpte_setup) {
|
||||
kvm->arch.hpte_setup_done = 0; /* temporarily */
|
||||
/* order hpte_setup_done vs. vcpus_running */
|
||||
mmu_ready = kvm->arch.mmu_ready;
|
||||
if (mmu_ready) {
|
||||
kvm->arch.mmu_ready = 0; /* temporarily */
|
||||
/* order mmu_ready vs. vcpus_running */
|
||||
smp_mb();
|
||||
if (atomic_read(&kvm->arch.vcpus_running)) {
|
||||
kvm->arch.hpte_setup_done = 1;
|
||||
kvm->arch.mmu_ready = 1;
|
||||
mutex_unlock(&kvm->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -1870,7 +1870,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
|
|||
"r=%lx\n", ret, i, v, r);
|
||||
goto out;
|
||||
}
|
||||
if (!hpte_setup && is_vrma_hpte(v)) {
|
||||
if (!mmu_ready && is_vrma_hpte(v)) {
|
||||
unsigned long psize = hpte_base_page_size(v, r);
|
||||
unsigned long senc = slb_pgsize_encoding(psize);
|
||||
unsigned long lpcr;
|
||||
|
@ -1879,7 +1879,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
|
|||
(VRMA_VSID << SLB_VSID_SHIFT_1T);
|
||||
lpcr = senc << (LPCR_VRMASD_SH - 4);
|
||||
kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD);
|
||||
hpte_setup = 1;
|
||||
mmu_ready = 1;
|
||||
}
|
||||
++i;
|
||||
hptp += 2;
|
||||
|
@ -1895,9 +1895,9 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
|
|||
}
|
||||
|
||||
out:
|
||||
/* Order HPTE updates vs. hpte_setup_done */
|
||||
/* Order HPTE updates vs. mmu_ready */
|
||||
smp_wmb();
|
||||
kvm->arch.hpte_setup_done = hpte_setup;
|
||||
kvm->arch.mmu_ready = mmu_ready;
|
||||
mutex_unlock(&kvm->lock);
|
||||
|
||||
if (err)
|
||||
|
|
|
@ -115,6 +115,7 @@ MODULE_PARM_DESC(h_ipi_redirect, "Redirect H_IPI wakeup to a free host core");
|
|||
|
||||
static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
|
||||
static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
|
||||
static void kvmppc_setup_partition_table(struct kvm *kvm);
|
||||
|
||||
static inline struct kvm_vcpu *next_runnable_thread(struct kvmppc_vcore *vc,
|
||||
int *ip)
|
||||
|
@ -3198,6 +3199,7 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
|
|||
unsigned long ebb_regs[3] = {}; /* shut up GCC */
|
||||
unsigned long user_tar = 0;
|
||||
unsigned int user_vrsave;
|
||||
struct kvm *kvm;
|
||||
|
||||
if (!vcpu->arch.sane) {
|
||||
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
||||
|
@ -3235,13 +3237,25 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
|
|||
return -EINTR;
|
||||
}
|
||||
|
||||
atomic_inc(&vcpu->kvm->arch.vcpus_running);
|
||||
/* Order vcpus_running vs. hpte_setup_done, see kvmppc_alloc_reset_hpt */
|
||||
kvm = vcpu->kvm;
|
||||
atomic_inc(&kvm->arch.vcpus_running);
|
||||
/* Order vcpus_running vs. mmu_ready, see kvmppc_alloc_reset_hpt */
|
||||
smp_mb();
|
||||
|
||||
/* On the first time here, set up HTAB and VRMA */
|
||||
if (!kvm_is_radix(vcpu->kvm) && !vcpu->kvm->arch.hpte_setup_done) {
|
||||
r = kvmppc_hv_setup_htab_rma(vcpu);
|
||||
/* On the first time here, set up MMU if necessary */
|
||||
if (!vcpu->kvm->arch.mmu_ready) {
|
||||
mutex_lock(&kvm->lock);
|
||||
r = 0;
|
||||
if (!kvm->arch.mmu_ready) {
|
||||
if (!kvm_is_radix(vcpu->kvm))
|
||||
r = kvmppc_hv_setup_htab_rma(vcpu);
|
||||
if (!r) {
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300))
|
||||
kvmppc_setup_partition_table(kvm);
|
||||
kvm->arch.mmu_ready = 1;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&kvm->lock);
|
||||
if (r)
|
||||
goto out;
|
||||
}
|
||||
|
@ -3530,6 +3544,10 @@ static void kvmppc_setup_partition_table(struct kvm *kvm)
|
|||
mmu_partition_table_set_entry(kvm->arch.lpid, dw0, dw1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up HPT (hashed page table) and RMA (real-mode area).
|
||||
* Must be called with kvm->lock held.
|
||||
*/
|
||||
static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int err = 0;
|
||||
|
@ -3541,10 +3559,6 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
|
|||
unsigned long psize, porder;
|
||||
int srcu_idx;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
if (kvm->arch.hpte_setup_done)
|
||||
goto out; /* another vcpu beat us to it */
|
||||
|
||||
/* Allocate hashed page table (if not done already) and reset it */
|
||||
if (!kvm->arch.hpt.virt) {
|
||||
int order = KVM_DEFAULT_HPT_ORDER;
|
||||
|
@ -3603,18 +3617,14 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
|
|||
/* the -4 is to account for senc values starting at 0x10 */
|
||||
lpcr = senc << (LPCR_VRMASD_SH - 4);
|
||||
kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD);
|
||||
} else {
|
||||
kvmppc_setup_partition_table(kvm);
|
||||
}
|
||||
|
||||
/* Order updates to kvm->arch.lpcr etc. vs. hpte_setup_done */
|
||||
/* Order updates to kvm->arch.lpcr etc. vs. mmu_ready */
|
||||
smp_wmb();
|
||||
kvm->arch.hpte_setup_done = 1;
|
||||
err = 0;
|
||||
out_srcu:
|
||||
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
||||
out:
|
||||
mutex_unlock(&kvm->lock);
|
||||
return err;
|
||||
|
||||
up_out:
|
||||
|
@ -3769,6 +3779,7 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
|
|||
*/
|
||||
if (radix_enabled()) {
|
||||
kvm->arch.radix = 1;
|
||||
kvm->arch.mmu_ready = 1;
|
||||
lpcr &= ~LPCR_VPM1;
|
||||
lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR;
|
||||
ret = kvmppc_init_vm_radix(kvm);
|
||||
|
|
Loading…
Reference in New Issue