Commit 0f5f6691 authored by Jason J. Herne's avatar Jason J. Herne Committed by Cornelia Huck
Browse files

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: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: default avatarThomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: default avatarJason J. Herne <jjherne@linux.vnet.ibm.com>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
parent 0efe406c
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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));
+5 −6
Original line number Diff line number Diff line
@@ -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");
+1 −1
Original line number Diff line number Diff line
@@ -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,
+0 −2
Original line number Diff line number Diff line
@@ -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;
+40 −6
Original line number Diff line number Diff line
@@ -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
Loading