summaryrefslogtreecommitdiff
path: root/target-s390x/mem_helper.c
diff options
context:
space:
mode:
authorJason J. Herne <jjherne@linux.vnet.ibm.com>2015-06-26 14:01:00 -0400
committerCornelia Huck <cornelia.huck@de.ibm.com>2015-09-03 12:17:54 +0200
commit0f5f669147b52f89928bdf180165f74c4219210e (patch)
tree80daed9c487d7bdb2bf64bd2867b7305cc701a0c /target-s390x/mem_helper.c
parent0efe406cac8a4d9f0b52eada4c6c2a768fe4b7d2 (diff)
downloadqemu-0f5f669147b52f89928bdf180165f74c4219210e.tar.gz
s390x: Enable new s390-storage-keys device
s390 guest initialization is modified to make use of new s390-storage-keys device. Old code that globally allocated storage key array is removed. The new device enables storage key access for kvm guests. Cache storage key QOM objects in frequently used helper functions to avoid a performance hit every time we use one of these functions. Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Jason J. Herne <jjherne@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'target-s390x/mem_helper.c')
-rw-r--r--target-s390x/mem_helper.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 6f8bd796ad..84bf198e2b 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -21,6 +21,7 @@
#include "cpu.h"
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
+#include "hw/s390x/storage-keys.h"
/*****************************************************************************/
/* Softmmu support */
@@ -937,40 +938,73 @@ uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
/* insert storage key extended */
uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
{
+ static S390SKeysState *ss;
+ static S390SKeysClass *skeyclass;
uint64_t addr = get_address(env, 0, 0, r2);
+ uint8_t key;
if (addr > ram_size) {
return 0;
}
- return env->storage_keys[addr / TARGET_PAGE_SIZE];
+ if (unlikely(!ss)) {
+ ss = s390_get_skeys_device();
+ skeyclass = S390_SKEYS_GET_CLASS(ss);
+ }
+
+ if (skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key)) {
+ return 0;
+ }
+ return key;
}
/* set storage key extended */
void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
{
+ static S390SKeysState *ss;
+ static S390SKeysClass *skeyclass;
uint64_t addr = get_address(env, 0, 0, r2);
+ uint8_t key;
if (addr > ram_size) {
return;
}
- env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
+ if (unlikely(!ss)) {
+ ss = s390_get_skeys_device();
+ skeyclass = S390_SKEYS_GET_CLASS(ss);
+ }
+
+ key = (uint8_t) r1;
+ skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
}
/* reset reference bit extended */
uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
{
- uint8_t re;
- uint8_t key;
+ static S390SKeysState *ss;
+ static S390SKeysClass *skeyclass;
+ uint8_t re, key;
if (r2 > ram_size) {
return 0;
}
- key = env->storage_keys[r2 / TARGET_PAGE_SIZE];
+ if (unlikely(!ss)) {
+ ss = s390_get_skeys_device();
+ skeyclass = S390_SKEYS_GET_CLASS(ss);
+ }
+
+ if (skeyclass->get_skeys(ss, r2 / TARGET_PAGE_SIZE, 1, &key)) {
+ return 0;
+ }
+
re = key & (SK_R | SK_C);
- env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R);
+ key &= ~SK_R;
+
+ if (skeyclass->set_skeys(ss, r2 / TARGET_PAGE_SIZE, 1, &key)) {
+ return 0;
+ }
/*
* cc