mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
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:
parent
0efe406cac
commit
0f5f669147
|
@ -19,6 +19,7 @@
|
||||||
#include "virtio-ccw.h"
|
#include "virtio-ccw.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "s390-pci-bus.h"
|
#include "s390-pci-bus.h"
|
||||||
|
#include "hw/s390x/storage-keys.h"
|
||||||
|
|
||||||
#define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
|
#define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
|
||||||
|
|
||||||
|
@ -105,7 +106,6 @@ static void ccw_init(MachineState *machine)
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||||
sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev();
|
sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev();
|
||||||
uint8_t *storage_keys;
|
|
||||||
int ret;
|
int ret;
|
||||||
VirtualCssBus *css_bus;
|
VirtualCssBus *css_bus;
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
|
@ -179,11 +179,11 @@ static void ccw_init(MachineState *machine)
|
||||||
mhd->standby_mem_size = standby_mem_size;
|
mhd->standby_mem_size = standby_mem_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate storage keys */
|
/* Initialize storage key device */
|
||||||
storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
|
s390_skeys_init();
|
||||||
|
|
||||||
/* init CPUs */
|
/* init CPUs */
|
||||||
s390_init_cpus(machine->cpu_model, storage_keys);
|
s390_init_cpus(machine->cpu_model);
|
||||||
|
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
kvm_s390_enable_css_support(s390_cpu_addr2state(0));
|
kvm_s390_enable_css_support(s390_cpu_addr2state(0));
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "hw/s390x/sclp.h"
|
#include "hw/s390x/sclp.h"
|
||||||
#include "hw/s390x/s390_flic.h"
|
#include "hw/s390x/s390_flic.h"
|
||||||
#include "hw/s390x/s390-virtio.h"
|
#include "hw/s390x/s390-virtio.h"
|
||||||
|
#include "hw/s390x/storage-keys.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
//#define DEBUG_S390
|
//#define DEBUG_S390
|
||||||
|
@ -164,7 +165,7 @@ void s390_init_ipl_dev(const char *kernel_filename,
|
||||||
qdev_init_nofail(dev);
|
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;
|
int i;
|
||||||
|
|
||||||
|
@ -184,7 +185,6 @@ void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys)
|
||||||
ipi_states[i] = cpu;
|
ipi_states[i] = cpu;
|
||||||
cs->halted = 1;
|
cs->halted = 1;
|
||||||
cs->exception_index = EXCP_HLT;
|
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 *sysmem = get_system_memory();
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||||
int increment_size = 20;
|
int increment_size = 20;
|
||||||
uint8_t *storage_keys;
|
|
||||||
void *virtio_region;
|
void *virtio_region;
|
||||||
hwaddr virtio_region_len;
|
hwaddr virtio_region_len;
|
||||||
hwaddr virtio_region_start;
|
hwaddr virtio_region_start;
|
||||||
|
@ -306,11 +305,11 @@ static void s390_init(MachineState *machine)
|
||||||
cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1,
|
cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1,
|
||||||
virtio_region_len);
|
virtio_region_len);
|
||||||
|
|
||||||
/* allocate storage keys */
|
/* Initialize storage key device */
|
||||||
storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
|
s390_skeys_init();
|
||||||
|
|
||||||
/* init CPUs */
|
/* init CPUs */
|
||||||
s390_init_cpus(machine->cpu_model, storage_keys);
|
s390_init_cpus(machine->cpu_model);
|
||||||
|
|
||||||
/* Create VirtIO network adapters */
|
/* Create VirtIO network adapters */
|
||||||
s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390");
|
s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390");
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
typedef int (*s390_virtio_fn)(const uint64_t *args);
|
typedef int (*s390_virtio_fn)(const uint64_t *args);
|
||||||
void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
|
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,
|
void s390_init_ipl_dev(const char *kernel_filename,
|
||||||
const char *kernel_cmdline,
|
const char *kernel_cmdline,
|
||||||
const char *initrd_filename,
|
const char *initrd_filename,
|
||||||
|
|
|
@ -143,8 +143,6 @@ typedef struct CPUS390XState {
|
||||||
uint32_t cpu_num;
|
uint32_t cpu_num;
|
||||||
uint32_t machine_type;
|
uint32_t machine_type;
|
||||||
|
|
||||||
uint8_t *storage_keys;
|
|
||||||
|
|
||||||
uint64_t tod_offset;
|
uint64_t tod_offset;
|
||||||
uint64_t tod_basetime;
|
uint64_t tod_basetime;
|
||||||
QEMUTimer *tod_timer;
|
QEMUTimer *tod_timer;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
|
#include "hw/s390x/storage-keys.h"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Softmmu support */
|
/* Softmmu support */
|
||||||
|
@ -937,40 +938,73 @@ uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
|
||||||
/* insert storage key extended */
|
/* insert storage key extended */
|
||||||
uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
|
uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
|
||||||
{
|
{
|
||||||
|
static S390SKeysState *ss;
|
||||||
|
static S390SKeysClass *skeyclass;
|
||||||
uint64_t addr = get_address(env, 0, 0, r2);
|
uint64_t addr = get_address(env, 0, 0, r2);
|
||||||
|
uint8_t key;
|
||||||
|
|
||||||
if (addr > ram_size) {
|
if (addr > ram_size) {
|
||||||
return 0;
|
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 */
|
/* set storage key extended */
|
||||||
void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
|
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);
|
uint64_t addr = get_address(env, 0, 0, r2);
|
||||||
|
uint8_t key;
|
||||||
|
|
||||||
if (addr > ram_size) {
|
if (addr > ram_size) {
|
||||||
return;
|
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 */
|
/* reset reference bit extended */
|
||||||
uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
|
uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
|
||||||
{
|
{
|
||||||
uint8_t re;
|
static S390SKeysState *ss;
|
||||||
uint8_t key;
|
static S390SKeysClass *skeyclass;
|
||||||
|
uint8_t re, key;
|
||||||
|
|
||||||
if (r2 > ram_size) {
|
if (r2 > ram_size) {
|
||||||
return 0;
|
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);
|
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
|
* cc
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
|
#include "trace.h"
|
||||||
|
#include "hw/s390x/storage-keys.h"
|
||||||
|
|
||||||
/* #define DEBUG_S390 */
|
/* #define DEBUG_S390 */
|
||||||
/* #define DEBUG_S390_PTE */
|
/* #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,
|
int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
|
||||||
target_ulong *raddr, int *flags, bool exc)
|
target_ulong *raddr, int *flags, bool exc)
|
||||||
{
|
{
|
||||||
|
static S390SKeysState *ss;
|
||||||
|
static S390SKeysClass *skeyclass;
|
||||||
int r = -1;
|
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;
|
*flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
vaddr &= TARGET_PAGE_MASK;
|
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 */
|
/* Convert real address -> absolute address */
|
||||||
*raddr = mmu_real2abs(env, *raddr);
|
*raddr = mmu_real2abs(env, *raddr);
|
||||||
|
|
||||||
if (*raddr < ram_size) {
|
if (r == 0 && *raddr < ram_size) {
|
||||||
sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE];
|
if (skeyclass->get_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key)) {
|
||||||
|
trace_get_skeys_nonzero(r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (*flags & PAGE_READ) {
|
if (*flags & PAGE_READ) {
|
||||||
*sk |= SK_R;
|
key |= SK_R;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*flags & PAGE_WRITE) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_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
|
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
|
# target-s390x/ioinst.c
|
||||||
ioinst(const char *insn) "IOINST: %s"
|
ioinst(const char *insn) "IOINST: %s"
|
||||||
ioinst_sch_id(const char *insn, int cssid, int ssid, int schid) "IOINST: %s (%x.%x.%04x)"
|
ioinst_sch_id(const char *insn, int cssid, int ssid, int schid) "IOINST: %s (%x.%x.%04x)"
|
||||||
|
|
Loading…
Reference in a new issue