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>
This commit is contained in:
Jason J. Herne 2015-06-26 14:01:00 -04:00 committed by Cornelia Huck
parent 0efe406cac
commit 0f5f669147
7 changed files with 77 additions and 24 deletions

View File

@ -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));

View File

@ -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");

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;
}
}

View File

@ -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)"