s390 Fix address mode switching
PATCH 1/1 s390 Fix address mode switching
Avi,
here is another fix I want to submit for 3.1 (if possible) that repairs KVM for s390. Are you ok to submit this patch via s390 tree - iow can you ACK the kvm specific part (arch/s390/kvm/kvm-s390.c). The biggest chunk is low level SIE handling and memory management. This was already discussed with Martin Schwidefsky.
Christian
----
From: Christian Borntraeger <[email protected]>
598841ca9919d008b520114d8a4378c4ce4e40a1 ([S390] use gmap address spaces for kvm guest images) changed kvm to use a separate address space for kvm guests. This address space was switched in __vcpu_run In some cases (preemption, page fault) there is the possibility that this address space switch is lost.
The typical symptom was a huge amount of validity intercepts or random guest addressing exceptions.
Fix this by doing the switch in sie_loop and sie_exit and saving the address space in the gmap structure itself. Also use the preempt notifier.
arch/s390/include/asm/pgtable.h +2 -0
@@ -658,12 +658,14 @@* struct gmap_struct - guest address space * @mm: pointer to the parent mm_struct * @table: pointer to the page directory +* @asce: address space control element for gmap page table * @crst_list: list of all crst tables used in the guest address space */ struct gmap {struct list_head list;struct mm_struct *mm;unsigned long *table; +unsigned long asce;struct list_head crst_list; };
arch/s390/kernel/asm-offsets.c +3 -0
@@ -10,6 +10,7 @@#include <linux/sched.h> #include <asm/vdso.h> #include <asm/sigp.h> +#include <asm/pgtable.h> /* * Make sure that the compiler is new enough. We want a compiler that
@@ -125,6 +126,7 @@DEFINE (__LC_KERNEL_STACK, offsetof(struct _lowcore , kernel_stack));DEFINE (__LC_ASYNC_STACK, offsetof(struct _lowcore , async_stack));DEFINE (__LC_PANIC_STACK, offsetof(struct _lowcore , panic_stack)); +DEFINE (__LC_USER_ASCE, offsetof(struct _lowcore , user_asce));DEFINE (__LC_INT_CLOCK, offsetof(struct _lowcore , int_clock));DEFINE (__LC_MCCK_CLOCK, offsetof(struct _lowcore , mcck_clock));DEFINE (__LC_MACHINE_FLAGS, offsetof(struct _lowcore , machine_flags));
@@ -149,6 +151,7 @@DEFINE (__LC_VDSO_PER_CPU, offsetof(struct _lowcore , vdso_per_cpu_data));DEFINE (__LC_GMAP, offsetof(struct _lowcore , gmap));DEFINE (__LC_CMF_HPP, offsetof(struct _lowcore , cmf_hpp)); +DEFINE (__GMAP_ASCE, offsetof(struct gmap , asce));#endif /* CONFIG_32BIT */ return 0 ; }
arch/s390/kernel/entry64.S +6 -0
@@ -1073,6 +1073,11 @@ lg %r14,__LC_THREAD_INFO # pointer thread_info struct tm __TI_flags+7(%r14),_TIF_EXIT_SIE jnz sie_exit + lg %r14,__LC_GMAP # get gmap pointer + ltgr %r14,%r14 + jz sie_gmap + lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce +sie_gmap: lg %r14,__SF_EMPTY(%r15) # get control block pointer SPP __SF_EMPTY(%r15) # set guest id sie 0(%r14)
@@ -1080,6 +1085,7 @@ SPP __LC_CMF_HPP # set host id lg %r14,__LC_THREAD_INFO # pointer thread_info struct sie_exit: + lctlg %c1,%c1,__LC_USER_ASCE # load primary asce ni __TI_flags+6(%r14),255-(_TIF_SIE>>8) lg %r14,__SF_EMPTY+8(%r15) # load guest register save area stmg %r0,%r13,0(%r14) # save guest gprs 0-13
arch/s390/kvm/kvm-s390.c +2 -2
@@ -263,10 +263,12 @@ vcpu->arch.guest_fpregs.fpc &=FPC_VALID_MASK ;restore_fp_regs (&vcpu->arch.guest_fpregs);restore_access_regs (vcpu->arch.guest_acrs); +gmap_enable (vcpu->arch.gmap); }void kvm_arch_vcpu_put (struct kvm_vcpu *vcpu) { +gmap_disable (vcpu->arch.gmap);save_fp_regs (&vcpu->arch.guest_fpregs);save_access_regs (vcpu->arch.guest_acrs);restore_fp_regs (&vcpu->arch.host_fpregs);
@@ -461,7 +463,6 @@local_irq_disable ();kvm_guest_enter ();local_irq_enable (); -gmap_enable (vcpu->arch.gmap);VCPU_EVENT (vcpu,6 ,"entering sie flags %x" ,atomic_read (&vcpu->arch.sie_block->cpuflags));if (sie64a (vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
@@ -470,7 +471,6 @@ }VCPU_EVENT (vcpu,6 ,"exit sie icptcode %d" , vcpu->arch.sie_block->icptcode); -gmap_disable (vcpu->arch.gmap);local_irq_disable ();kvm_guest_exit ();local_irq_enable ();
arch/s390/mm/pgtable.c +2 -8
@@ -160,6 +160,8 @@ table = (unsigned long *)page_to_phys (page);crst_table_init (table, _REGION1_ENTRY_EMPTY); gmap->table = table; + gmap->asce = _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH | + _ASCE_USER_BITS |__pa (table);list_add (&gmap->list, &mm->context.gmap_list);return gmap;
@@ -240,10 +242,6 @@*/ void gmap_enable (struct gmap *gmap) { -/* Load primary space page table origin. */ - S390_lowcore.user_asce = _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH | - _ASCE_USER_BITS |__pa (gmap->table); - asmvolatile ("lctlg 1,1,%0\n" : :"m" (S390_lowcore.user_asce) ); S390_lowcore.gmap = (unsigned long ) gmap; }EXPORT_SYMBOL_GPL (gmap_enable);
@@ -254,10 +252,6 @@*/ void gmap_disable (struct gmap *gmap) { -/* Load primary space page table origin. */ - S390_lowcore.user_asce = - gmap->mm->context.asce_bits |__pa (gmap->mm->pgd); - asmvolatile ("lctlg 1,1,%0\n" : :"m" (S390_lowcore.user_asce) ); S390_lowcore.gmap =0UL ; }EXPORT_SYMBOL_GPL (gmap_disable);
Quoted 10 lines · Christian Borntraeger
Avi,
here is another fix I want to submit for 3.1 (if possible) that repairs KVM for s390. Are you ok to submit this patch via s390 tree - iow can you ACK the kvm specific part (
arch/s390/kvm/kvm-s390.c). The biggest chunk is low level SIE handling and memory management. This was already discussed with Martin Schwidefsky.
Sure - ACK.
Signature · 1 line
error compiling committee.c: too many arguments to function