forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'kvm-s390-next-4.15-1' of git://git.kernel.org/pub/scm/linu…
…x/kernel/git/kvms390/linux KVM: s390: fixes and improvements for 4.15 - Some initial preparation patches for exitless interrupts and crypto - New capability for AIS migration - Fixes - merge of the sthyi tree from the base s390 team, which moves the sthyi out of KVM into a shared function also for non-KVM
- Loading branch information
Showing
20 changed files
with
262 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef _UAPI_ASM_STHYI_H | ||
#define _UAPI_ASM_STHYI_H | ||
|
||
#define STHYI_FC_CP_IFL_CAP 0 | ||
|
||
#endif /* _UAPI_ASM_STHYI_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,22 +8,19 @@ | |
* Copyright IBM Corp. 2016 | ||
* Author(s): Janosch Frank <[email protected]> | ||
*/ | ||
#include <linux/kvm_host.h> | ||
#include <linux/errno.h> | ||
#include <linux/pagemap.h> | ||
#include <linux/vmalloc.h> | ||
#include <linux/ratelimit.h> | ||
|
||
#include <asm/kvm_host.h> | ||
#include <linux/syscalls.h> | ||
#include <linux/mutex.h> | ||
#include <asm/asm-offsets.h> | ||
#include <asm/sclp.h> | ||
#include <asm/diag.h> | ||
#include <asm/sysinfo.h> | ||
#include <asm/ebcdic.h> | ||
|
||
#include "kvm-s390.h" | ||
#include "gaccess.h" | ||
#include "trace.h" | ||
#include <asm/facility.h> | ||
#include <asm/sthyi.h> | ||
#include "entry.h" | ||
|
||
#define DED_WEIGHT 0xffff | ||
/* | ||
|
@@ -144,6 +141,21 @@ struct lpar_cpu_inf { | |
struct cpu_inf ifl; | ||
}; | ||
|
||
/* | ||
* STHYI requires extensive locking in the higher hypervisors | ||
* and is very computational/memory expensive. Therefore we | ||
* cache the retrieved data whose valid period is 1s. | ||
*/ | ||
#define CACHE_VALID_JIFFIES HZ | ||
|
||
struct sthyi_info { | ||
void *info; | ||
unsigned long end; | ||
}; | ||
|
||
static DEFINE_MUTEX(sthyi_mutex); | ||
static struct sthyi_info sthyi_cache; | ||
|
||
static inline u64 cpu_id(u8 ctidx, void *diag224_buf) | ||
{ | ||
return *((u64 *)(diag224_buf + (ctidx + 1) * DIAG204_CPU_NAME_LEN)); | ||
|
@@ -382,88 +394,124 @@ static void fill_diag(struct sthyi_sctns *sctns) | |
vfree(diag204_buf); | ||
} | ||
|
||
static int sthyi(u64 vaddr) | ||
static int sthyi(u64 vaddr, u64 *rc) | ||
{ | ||
register u64 code asm("0") = 0; | ||
register u64 addr asm("2") = vaddr; | ||
register u64 rcode asm("3"); | ||
int cc; | ||
|
||
asm volatile( | ||
".insn rre,0xB2560000,%[code],%[addr]\n" | ||
"ipm %[cc]\n" | ||
"srl %[cc],28\n" | ||
: [cc] "=d" (cc) | ||
: [cc] "=d" (cc), "=d" (rcode) | ||
: [code] "d" (code), [addr] "a" (addr) | ||
: "3", "memory", "cc"); | ||
: "memory", "cc"); | ||
*rc = rcode; | ||
return cc; | ||
} | ||
|
||
int handle_sthyi(struct kvm_vcpu *vcpu) | ||
static int fill_dst(void *dst, u64 *rc) | ||
{ | ||
int reg1, reg2, r = 0; | ||
u64 code, addr, cc = 0; | ||
struct sthyi_sctns *sctns = NULL; | ||
|
||
if (!test_kvm_facility(vcpu->kvm, 74)) | ||
return kvm_s390_inject_program_int(vcpu, PGM_OPERATION); | ||
struct sthyi_sctns *sctns = (struct sthyi_sctns *)dst; | ||
|
||
/* | ||
* STHYI requires extensive locking in the higher hypervisors | ||
* and is very computational/memory expensive. Therefore we | ||
* ratelimit the executions per VM. | ||
* If the facility is on, we don't want to emulate the instruction. | ||
* We ask the hypervisor to provide the data. | ||
*/ | ||
if (!__ratelimit(&vcpu->kvm->arch.sthyi_limit)) { | ||
kvm_s390_retry_instr(vcpu); | ||
if (test_facility(74)) | ||
return sthyi((u64)dst, rc); | ||
|
||
fill_hdr(sctns); | ||
fill_stsi(sctns); | ||
fill_diag(sctns); | ||
*rc = 0; | ||
return 0; | ||
} | ||
|
||
static int sthyi_init_cache(void) | ||
{ | ||
if (sthyi_cache.info) | ||
return 0; | ||
} | ||
sthyi_cache.info = (void *)get_zeroed_page(GFP_KERNEL); | ||
if (!sthyi_cache.info) | ||
return -ENOMEM; | ||
sthyi_cache.end = jiffies - 1; /* expired */ | ||
return 0; | ||
} | ||
|
||
kvm_s390_get_regs_rre(vcpu, ®1, ®2); | ||
code = vcpu->run->s.regs.gprs[reg1]; | ||
addr = vcpu->run->s.regs.gprs[reg2]; | ||
static int sthyi_update_cache(u64 *rc) | ||
{ | ||
int r; | ||
|
||
vcpu->stat.instruction_sthyi++; | ||
VCPU_EVENT(vcpu, 3, "STHYI: fc: %llu addr: 0x%016llx", code, addr); | ||
trace_kvm_s390_handle_sthyi(vcpu, code, addr); | ||
memset(sthyi_cache.info, 0, PAGE_SIZE); | ||
r = fill_dst(sthyi_cache.info, rc); | ||
if (r) | ||
return r; | ||
sthyi_cache.end = jiffies + CACHE_VALID_JIFFIES; | ||
return r; | ||
} | ||
|
||
if (reg1 == reg2 || reg1 & 1 || reg2 & 1) | ||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
/* | ||
* sthyi_fill - Fill page with data returned by the STHYI instruction | ||
* | ||
* @dst: Pointer to zeroed page | ||
* @rc: Pointer for storing the return code of the instruction | ||
* | ||
* Fills the destination with system information returned by the STHYI | ||
* instruction. The data is generated by emulation or execution of STHYI, | ||
* if available. The return value is the condition code that would be | ||
* returned, the rc parameter is the return code which is passed in | ||
* register R2 + 1. | ||
*/ | ||
int sthyi_fill(void *dst, u64 *rc) | ||
{ | ||
int r; | ||
|
||
if (code & 0xffff) { | ||
cc = 3; | ||
mutex_lock(&sthyi_mutex); | ||
r = sthyi_init_cache(); | ||
if (r) | ||
goto out; | ||
} | ||
|
||
if (addr & ~PAGE_MASK) | ||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
if (time_is_before_jiffies(sthyi_cache.end)) { | ||
/* cache expired */ | ||
r = sthyi_update_cache(rc); | ||
if (r) | ||
goto out; | ||
} | ||
*rc = 0; | ||
memcpy(dst, sthyi_cache.info, PAGE_SIZE); | ||
out: | ||
mutex_unlock(&sthyi_mutex); | ||
return r; | ||
} | ||
EXPORT_SYMBOL_GPL(sthyi_fill); | ||
|
||
sctns = (void *)get_zeroed_page(GFP_KERNEL); | ||
if (!sctns) | ||
SYSCALL_DEFINE4(s390_sthyi, unsigned long, function_code, void __user *, buffer, | ||
u64 __user *, return_code, unsigned long, flags) | ||
{ | ||
u64 sthyi_rc; | ||
void *info; | ||
int r; | ||
|
||
if (flags) | ||
return -EINVAL; | ||
if (function_code != STHYI_FC_CP_IFL_CAP) | ||
return -EOPNOTSUPP; | ||
info = (void *)get_zeroed_page(GFP_KERNEL); | ||
if (!info) | ||
return -ENOMEM; | ||
|
||
/* | ||
* If we are a guest, we don't want to emulate an emulated | ||
* instruction. We ask the hypervisor to provide the data. | ||
*/ | ||
if (test_facility(74)) { | ||
cc = sthyi((u64)sctns); | ||
r = sthyi_fill(info, &sthyi_rc); | ||
if (r < 0) | ||
goto out; | ||
if (return_code && put_user(sthyi_rc, return_code)) { | ||
r = -EFAULT; | ||
goto out; | ||
} | ||
|
||
fill_hdr(sctns); | ||
fill_stsi(sctns); | ||
fill_diag(sctns); | ||
|
||
if (copy_to_user(buffer, info, PAGE_SIZE)) | ||
r = -EFAULT; | ||
out: | ||
if (!cc) { | ||
r = write_guest(vcpu, addr, reg2, sctns, PAGE_SIZE); | ||
if (r) { | ||
free_page((unsigned long)sctns); | ||
return kvm_s390_inject_prog_cond(vcpu, r); | ||
} | ||
} | ||
|
||
free_page((unsigned long)sctns); | ||
vcpu->run->s.regs.gprs[reg2 + 1] = cc ? 4 : 0; | ||
kvm_s390_set_psw_cc(vcpu, cc); | ||
free_page((unsigned long)info); | ||
return r; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.