summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/s390x/s390-virtio-ccw.c8
-rw-r--r--hw/s390x/s390-virtio.c11
-rw-r--r--hw/s390x/s390-virtio.h2
-rw-r--r--target-s390x/cpu.h2
-rw-r--r--target-s390x/mem_helper.c46
-rw-r--r--target-s390x/mmu_helper.c28
-rw-r--r--trace-events4
7 files changed, 77 insertions, 24 deletions
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 71df282f5f..0a057aeb90 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -19,6 +19,7 @@
#include "virtio-ccw.h"
#include "qemu/config-file.h"
#include "s390-pci-bus.h"
+#include "hw/s390x/storage-keys.h"
#define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
@@ -105,7 +106,6 @@ static void ccw_init(MachineState *machine)
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev();
- uint8_t *storage_keys;
int ret;
VirtualCssBus *css_bus;
DeviceState *dev;
@@ -179,11 +179,11 @@ static void ccw_init(MachineState *machine)
mhd->standby_mem_size = standby_mem_size;
}
- /* allocate storage keys */
- storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
+ /* Initialize storage key device */
+ s390_skeys_init();
/* init CPUs */
- s390_init_cpus(machine->cpu_model, storage_keys);
+ s390_init_cpus(machine->cpu_model);
if (kvm_enabled()) {
kvm_s390_enable_css_support(s390_cpu_addr2state(0));
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index 1284e77b22..6cc6b5d5c4 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -38,6 +38,7 @@
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/s390-virtio.h"
+#include "hw/s390x/storage-keys.h"
#include "cpu.h"
//#define DEBUG_S390
@@ -164,7 +165,7 @@ void s390_init_ipl_dev(const char *kernel_filename,
qdev_init_nofail(dev);
}
-void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys)
+void s390_init_cpus(const char *cpu_model)
{
int i;
@@ -184,7 +185,6 @@ void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys)
ipi_states[i] = cpu;
cs->halted = 1;
cs->exception_index = EXCP_HLT;
- cpu->env.storage_keys = storage_keys;
}
}
@@ -264,7 +264,6 @@ static void s390_init(MachineState *machine)
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
int increment_size = 20;
- uint8_t *storage_keys;
void *virtio_region;
hwaddr virtio_region_len;
hwaddr virtio_region_start;
@@ -306,11 +305,11 @@ static void s390_init(MachineState *machine)
cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1,
virtio_region_len);
- /* allocate storage keys */
- storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
+ /* Initialize storage key device */
+ s390_skeys_init();
/* init CPUs */
- s390_init_cpus(machine->cpu_model, storage_keys);
+ s390_init_cpus(machine->cpu_model);
/* Create VirtIO network adapters */
s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390");
diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h
index c847853957..cf687968b4 100644
--- a/hw/s390x/s390-virtio.h
+++ b/hw/s390x/s390-virtio.h
@@ -19,7 +19,7 @@
typedef int (*s390_virtio_fn)(const uint64_t *args);
void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
-void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys);
+void s390_init_cpus(const char *cpu_model);
void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 63aebf4846..b650890130 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -143,8 +143,6 @@ typedef struct CPUS390XState {
uint32_t cpu_num;
uint32_t machine_type;
- uint8_t *storage_keys;
-
uint64_t tod_offset;
uint64_t tod_basetime;
QEMUTimer *tod_timer;
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
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 1ea6d812c2..058a37013b 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -19,6 +19,8 @@
#include "exec/address-spaces.h"
#include "cpu.h"
#include "sysemu/kvm.h"
+#include "trace.h"
+#include "hw/s390x/storage-keys.h"
/* #define DEBUG_S390 */
/* #define DEBUG_S390_PTE */
@@ -309,8 +311,15 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
target_ulong *raddr, int *flags, bool exc)
{
+ static S390SKeysState *ss;
+ static S390SKeysClass *skeyclass;
int r = -1;
- uint8_t *sk;
+ uint8_t key;
+
+ if (unlikely(!ss)) {
+ ss = s390_get_skeys_device();
+ skeyclass = S390_SKEYS_GET_CLASS(ss);
+ }
*flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
vaddr &= TARGET_PAGE_MASK;
@@ -358,14 +367,23 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
/* Convert real address -> absolute address */
*raddr = mmu_real2abs(env, *raddr);
- if (*raddr < ram_size) {
- sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE];
+ if (r == 0 && *raddr < ram_size) {
+ if (skeyclass->get_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key)) {
+ trace_get_skeys_nonzero(r);
+ return 0;
+ }
+
if (*flags & PAGE_READ) {
- *sk |= SK_R;
+ key |= SK_R;
}
if (*flags & PAGE_WRITE) {
- *sk |= SK_C;
+ key |= SK_C;
+ }
+
+ if (skeyclass->set_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key)) {
+ trace_set_skeys_nonzero(r);
+ return 0;
}
}
diff --git a/trace-events b/trace-events
index 8f9614adb5..0a82f0c1f2 100644
--- a/trace-events
+++ b/trace-events
@@ -1373,6 +1373,10 @@ hbitmap_iter_skip_words(const void *hb, void *hbi, uint64_t pos, unsigned long c
hbitmap_reset(void *hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) "hb %p items %"PRIu64",%"PRIu64" bits %"PRIu64"..%"PRIu64
hbitmap_set(void *hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) "hb %p items %"PRIu64",%"PRIu64" bits %"PRIu64"..%"PRIu64
+# target-s390x/mmu_helper.c
+get_skeys_nonzero(int rc) "SKEY: Call to get_skeys unexpectedly returned %d"
+set_skeys_nonzero(int rc) "SKEY: Call to set_skeys unexpectedly returned %d"
+
# target-s390x/ioinst.c
ioinst(const char *insn) "IOINST: %s"
ioinst_sch_id(const char *insn, int cssid, int ssid, int schid) "IOINST: %s (%x.%x.%04x)"