KVM: s390: Add storage key facility interpretation control
Up to now we always expected to have the storage key facility available for our (non-VSIE) KVM guests. For huge page support, we need to be able to disable it, so let's introduce that now. We add the use_skf variable to manage KVM storage key facility usage. Also we rename use_skey in the mm context struct to uses_skeys to make it more clear that it is an indication that the vm actively uses storage keys. Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com> Reviewed-by: Farhan Ali <alifm@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <david@redhat.com> Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:
Родитель
75bc37fefc
Коммит
55531b7431
|
@ -812,6 +812,7 @@ struct kvm_arch{
|
|||
int use_irqchip;
|
||||
int use_cmma;
|
||||
int use_pfmfi;
|
||||
int use_skf;
|
||||
int user_cpu_state_ctrl;
|
||||
int user_sigp;
|
||||
int user_stsi;
|
||||
|
|
|
@ -21,7 +21,7 @@ typedef struct {
|
|||
/* The mmu context uses extended page tables. */
|
||||
unsigned int has_pgste:1;
|
||||
/* The mmu context uses storage keys. */
|
||||
unsigned int use_skey:1;
|
||||
unsigned int uses_skeys:1;
|
||||
/* The mmu context uses CMM. */
|
||||
unsigned int uses_cmm:1;
|
||||
} mm_context_t;
|
||||
|
|
|
@ -30,7 +30,7 @@ static inline int init_new_context(struct task_struct *tsk,
|
|||
test_thread_flag(TIF_PGSTE) ||
|
||||
(current->mm && current->mm->context.alloc_pgste);
|
||||
mm->context.has_pgste = 0;
|
||||
mm->context.use_skey = 0;
|
||||
mm->context.uses_skeys = 0;
|
||||
mm->context.uses_cmm = 0;
|
||||
#endif
|
||||
switch (mm->context.asce_limit) {
|
||||
|
|
|
@ -507,10 +507,10 @@ static inline int mm_alloc_pgste(struct mm_struct *mm)
|
|||
* faults should no longer be backed by zero pages
|
||||
*/
|
||||
#define mm_forbids_zeropage mm_has_pgste
|
||||
static inline int mm_use_skey(struct mm_struct *mm)
|
||||
static inline int mm_uses_skeys(struct mm_struct *mm)
|
||||
{
|
||||
#ifdef CONFIG_PGSTE
|
||||
if (mm->context.use_skey)
|
||||
if (mm->context.uses_skeys)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
|
|
|
@ -1493,7 +1493,7 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
|
|||
return -EINVAL;
|
||||
|
||||
/* Is this guest using storage keys? */
|
||||
if (!mm_use_skey(current->mm))
|
||||
if (!mm_uses_skeys(current->mm))
|
||||
return KVM_S390_GET_SKEYS_NONE;
|
||||
|
||||
/* Enforce sane limit on memory allocation */
|
||||
|
@ -2066,6 +2066,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
|||
kvm->arch.css_support = 0;
|
||||
kvm->arch.use_irqchip = 0;
|
||||
kvm->arch.use_pfmfi = sclp.has_pfmfi;
|
||||
kvm->arch.use_skf = sclp.has_skey;
|
||||
kvm->arch.epoch = 0;
|
||||
|
||||
spin_lock_init(&kvm->arch.start_stop_lock);
|
||||
|
|
|
@ -205,24 +205,28 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
|
|||
|
||||
int kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
|
||||
|
||||
trace_kvm_s390_skey_related_inst(vcpu);
|
||||
if (!(sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE)) &&
|
||||
/* Already enabled? */
|
||||
if (vcpu->kvm->arch.use_skf &&
|
||||
!(sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE)) &&
|
||||
!kvm_s390_test_cpuflags(vcpu, CPUSTAT_KSS))
|
||||
return rc;
|
||||
return 0;
|
||||
|
||||
rc = s390_enable_skey();
|
||||
VCPU_EVENT(vcpu, 3, "enabling storage keys for guest: %d", rc);
|
||||
if (!rc) {
|
||||
if (kvm_s390_test_cpuflags(vcpu, CPUSTAT_KSS))
|
||||
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_KSS);
|
||||
else
|
||||
sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE |
|
||||
ICTL_RRBE);
|
||||
}
|
||||
return rc;
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (kvm_s390_test_cpuflags(vcpu, CPUSTAT_KSS))
|
||||
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_KSS);
|
||||
if (!vcpu->kvm->arch.use_skf)
|
||||
sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
|
||||
else
|
||||
sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int try_handle_skey(struct kvm_vcpu *vcpu)
|
||||
|
@ -232,7 +236,7 @@ static int try_handle_skey(struct kvm_vcpu *vcpu)
|
|||
rc = kvm_s390_skey_check_enable(vcpu);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (sclp.has_skey) {
|
||||
if (vcpu->kvm->arch.use_skf) {
|
||||
/* with storage-key facility, SIE interprets it for us */
|
||||
kvm_s390_retry_instr(vcpu);
|
||||
VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation");
|
||||
|
|
|
@ -2184,14 +2184,14 @@ int s390_enable_skey(void)
|
|||
int rc = 0;
|
||||
|
||||
down_write(&mm->mmap_sem);
|
||||
if (mm_use_skey(mm))
|
||||
if (mm_uses_skeys(mm))
|
||||
goto out_up;
|
||||
|
||||
mm->context.use_skey = 1;
|
||||
mm->context.uses_skeys = 1;
|
||||
for (vma = mm->mmap; vma; vma = vma->vm_next) {
|
||||
if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
|
||||
MADV_UNMERGEABLE, &vma->vm_flags)) {
|
||||
mm->context.use_skey = 0;
|
||||
mm->context.uses_skeys = 0;
|
||||
rc = -ENOMEM;
|
||||
goto out_up;
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ static inline pgste_t pgste_update_all(pte_t pte, pgste_t pgste,
|
|||
#ifdef CONFIG_PGSTE
|
||||
unsigned long address, bits, skey;
|
||||
|
||||
if (!mm_use_skey(mm) || pte_val(pte) & _PAGE_INVALID)
|
||||
if (!mm_uses_skeys(mm) || pte_val(pte) & _PAGE_INVALID)
|
||||
return pgste;
|
||||
address = pte_val(pte) & PAGE_MASK;
|
||||
skey = (unsigned long) page_get_storage_key(address);
|
||||
|
@ -180,7 +180,7 @@ static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry,
|
|||
unsigned long address;
|
||||
unsigned long nkey;
|
||||
|
||||
if (!mm_use_skey(mm) || pte_val(entry) & _PAGE_INVALID)
|
||||
if (!mm_uses_skeys(mm) || pte_val(entry) & _PAGE_INVALID)
|
||||
return;
|
||||
VM_BUG_ON(!(pte_val(*ptep) & _PAGE_INVALID));
|
||||
address = pte_val(entry) & PAGE_MASK;
|
||||
|
|
Загрузка…
Ссылка в новой задаче