Commit 6b33e68a authored by Nico Boehr's avatar Nico Boehr Committed by Janosch Frank

s390/entry: sort out physical vs virtual pointers usage in sie64a

Fix virtual vs physical address confusion (which currently are the
same).

sie_block is accessed in entry.S and passed it to hardware, which is why
both its physical and virtual address are needed. To avoid every caller
having to do the virtual-physical conversion, add a new function sie64a()
which converts the virtual address to physical.
Signed-off-by: default avatarNico Boehr <nrb@linux.ibm.com>
Reviewed-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Reviewed-by: default avatarClaudio Imbrenda <imbrenda@linux.ibm.com>
Link: https://lore.kernel.org/r/20221020143159.294605-3-nrb@linux.ibm.com
Message-Id: <20221020143159.294605-3-nrb@linux.ibm.com>
Signed-off-by: default avatarJanosch Frank <frankja@linux.ibm.com>
parent 079f0c21
...@@ -1017,7 +1017,13 @@ void kvm_arch_crypto_clear_masks(struct kvm *kvm); ...@@ -1017,7 +1017,13 @@ void kvm_arch_crypto_clear_masks(struct kvm *kvm);
void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm, void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm,
unsigned long *aqm, unsigned long *adm); unsigned long *aqm, unsigned long *adm);
extern int sie64a(struct kvm_s390_sie_block *, u64 *); int __sie64a(phys_addr_t sie_block_phys, struct kvm_s390_sie_block *sie_block, u64 *rsa);
static inline int sie64a(struct kvm_s390_sie_block *sie_block, u64 *rsa)
{
return __sie64a(virt_to_phys(sie_block), sie_block, rsa);
}
extern char sie_exit; extern char sie_exit;
extern int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc); extern int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc);
......
...@@ -46,6 +46,7 @@ struct stack_frame { ...@@ -46,6 +46,7 @@ struct stack_frame {
unsigned long sie_savearea; unsigned long sie_savearea;
unsigned long sie_reason; unsigned long sie_reason;
unsigned long sie_flags; unsigned long sie_flags;
unsigned long sie_control_block_phys;
}; };
}; };
unsigned long gprs[10]; unsigned long gprs[10];
......
...@@ -62,6 +62,7 @@ int main(void) ...@@ -62,6 +62,7 @@ int main(void)
OFFSET(__SF_SIE_SAVEAREA, stack_frame, sie_savearea); OFFSET(__SF_SIE_SAVEAREA, stack_frame, sie_savearea);
OFFSET(__SF_SIE_REASON, stack_frame, sie_reason); OFFSET(__SF_SIE_REASON, stack_frame, sie_reason);
OFFSET(__SF_SIE_FLAGS, stack_frame, sie_flags); OFFSET(__SF_SIE_FLAGS, stack_frame, sie_flags);
OFFSET(__SF_SIE_CONTROL_PHYS, stack_frame, sie_control_block_phys);
DEFINE(STACK_FRAME_OVERHEAD, sizeof(struct stack_frame)); DEFINE(STACK_FRAME_OVERHEAD, sizeof(struct stack_frame));
BLANK(); BLANK();
/* idle data offsets */ /* idle data offsets */
......
...@@ -225,18 +225,20 @@ ENDPROC(__switch_to) ...@@ -225,18 +225,20 @@ ENDPROC(__switch_to)
#if IS_ENABLED(CONFIG_KVM) #if IS_ENABLED(CONFIG_KVM)
/* /*
* sie64a calling convention: * __sie64a calling convention:
* %r2 pointer to sie control block * %r2 pointer to sie control block phys
* %r3 guest register save area * %r3 pointer to sie control block virt
* %r4 guest register save area
*/ */
ENTRY(sie64a) ENTRY(__sie64a)
stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers
lg %r12,__LC_CURRENT lg %r12,__LC_CURRENT
stg %r2,__SF_SIE_CONTROL(%r15) # save control block pointer stg %r2,__SF_SIE_CONTROL_PHYS(%r15) # save sie block physical..
stg %r3,__SF_SIE_SAVEAREA(%r15) # save guest register save area stg %r3,__SF_SIE_CONTROL(%r15) # ...and virtual addresses
stg %r4,__SF_SIE_SAVEAREA(%r15) # save guest register save area
xc __SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0 xc __SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0
mvc __SF_SIE_FLAGS(8,%r15),__TI_flags(%r12) # copy thread flags mvc __SF_SIE_FLAGS(8,%r15),__TI_flags(%r12) # copy thread flags
lmg %r0,%r13,0(%r3) # load guest gprs 0-13 lmg %r0,%r13,0(%r4) # load guest gprs 0-13
lg %r14,__LC_GMAP # get gmap pointer lg %r14,__LC_GMAP # get gmap pointer
ltgr %r14,%r14 ltgr %r14,%r14
jz .Lsie_gmap jz .Lsie_gmap
...@@ -248,6 +250,7 @@ ENTRY(sie64a) ...@@ -248,6 +250,7 @@ ENTRY(sie64a)
jnz .Lsie_skip jnz .Lsie_skip
TSTMSK __LC_CPU_FLAGS,_CIF_FPU TSTMSK __LC_CPU_FLAGS,_CIF_FPU
jo .Lsie_skip # exit if fp/vx regs changed jo .Lsie_skip # exit if fp/vx regs changed
lg %r14,__SF_SIE_CONTROL_PHYS(%r15) # get sie block phys addr
BPEXIT __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST) BPEXIT __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
.Lsie_entry: .Lsie_entry:
sie 0(%r14) sie 0(%r14)
...@@ -258,13 +261,14 @@ ENTRY(sie64a) ...@@ -258,13 +261,14 @@ ENTRY(sie64a)
BPOFF BPOFF
BPENTER __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST) BPENTER __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
.Lsie_skip: .Lsie_skip:
lg %r14,__SF_SIE_CONTROL(%r15) # get control block pointer
ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
lctlg %c1,%c1,__LC_KERNEL_ASCE # load primary asce lctlg %c1,%c1,__LC_KERNEL_ASCE # load primary asce
.Lsie_done: .Lsie_done:
# some program checks are suppressing. C code (e.g. do_protection_exception) # some program checks are suppressing. C code (e.g. do_protection_exception)
# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There # will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable. # are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
# Other instructions between sie64a and .Lsie_done should not cause program # Other instructions between __sie64a and .Lsie_done should not cause program
# interrupts. So lets use 3 nops as a landing pad for all possible rewinds. # interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
.Lrewind_pad6: .Lrewind_pad6:
nopr 7 nopr 7
...@@ -293,8 +297,8 @@ sie_exit: ...@@ -293,8 +297,8 @@ sie_exit:
EX_TABLE(.Lrewind_pad4,.Lsie_fault) EX_TABLE(.Lrewind_pad4,.Lsie_fault)
EX_TABLE(.Lrewind_pad2,.Lsie_fault) EX_TABLE(.Lrewind_pad2,.Lsie_fault)
EX_TABLE(sie_exit,.Lsie_fault) EX_TABLE(sie_exit,.Lsie_fault)
ENDPROC(sie64a) ENDPROC(__sie64a)
EXPORT_SYMBOL(sie64a) EXPORT_SYMBOL(__sie64a)
EXPORT_SYMBOL(sie_exit) EXPORT_SYMBOL(sie_exit)
#endif #endif
...@@ -373,7 +377,7 @@ ENTRY(pgm_check_handler) ...@@ -373,7 +377,7 @@ ENTRY(pgm_check_handler)
j 3f # -> fault in user space j 3f # -> fault in user space
.Lpgm_skip_asce: .Lpgm_skip_asce:
#if IS_ENABLED(CONFIG_KVM) #if IS_ENABLED(CONFIG_KVM)
# cleanup critical section for program checks in sie64a # cleanup critical section for program checks in __sie64a
OUTSIDE %r9,.Lsie_gmap,.Lsie_done,1f OUTSIDE %r9,.Lsie_gmap,.Lsie_done,1f
SIEEXIT SIEEXIT
lghi %r10,_PIF_GUEST_FAULT lghi %r10,_PIF_GUEST_FAULT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment