Skip to content

Commit

Permalink
s390x: Enable new s390-storage-keys device
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Thomas Huth <[email protected]>
Reviewed-by: David Hildenbrand <[email protected]>
Signed-off-by: Jason J. Herne <[email protected]>
Signed-off-by: Cornelia Huck <[email protected]>
  • Loading branch information
Jason J. Herne authored and cohuck committed Sep 3, 2015
1 parent 0efe406 commit 0f5f669
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 24 deletions.
8 changes: 4 additions & 4 deletions hw/s390x/s390-virtio-ccw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down
11 changes: 5 additions & 6 deletions hw/s390x/s390-virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

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

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion hw/s390x/s390-virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 0 additions & 2 deletions target-s390x/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
46 changes: 40 additions & 6 deletions target-s390x/mem_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down
28 changes: 23 additions & 5 deletions target-s390x/mmu_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}

Expand Down
4 changes: 4 additions & 0 deletions trace-events
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
Expand Down

0 comments on commit 0f5f669

Please sign in to comment.