diff options
Diffstat (limited to 'target-s390x')
-rw-r--r-- | target-s390x/cpu.h | 4 | ||||
-rw-r--r-- | target-s390x/gdbstub.c | 39 | ||||
-rw-r--r-- | target-s390x/kvm.c | 4 | ||||
-rw-r--r-- | target-s390x/mem_helper.c | 50 | ||||
-rw-r--r-- | target-s390x/mmu_helper.c | 28 |
5 files changed, 107 insertions, 18 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 63aebf4846..9aeb0241fb 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; @@ -310,7 +308,7 @@ static inline CPU_DoubleU *get_freg(CPUS390XState *cs, int nr) #define MMU_SECONDARY_IDX 1 #define MMU_HOME_IDX 2 -static inline int cpu_mmu_index (CPUS390XState *env) +static inline int cpu_mmu_index (CPUS390XState *env, bool ifetch) { switch (env->psw.mask & PSW_MASK_ASC) { case PSW_ASC_PRIMARY: diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c index 31f204964f..0c39a3c69f 100644 --- a/target-s390x/gdbstub.c +++ b/target-s390x/gdbstub.c @@ -174,6 +174,39 @@ static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) } } +/* the values represent the positions in s390-cr.xml */ +#define S390_C0_REGNUM 0 +#define S390_C15_REGNUM 15 +/* total number of registers in s390-cr.xml */ +#define S390_NUM_C_REGS 16 + +#ifndef CONFIG_USER_ONLY +static int cpu_read_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case S390_C0_REGNUM ... S390_C15_REGNUM: + return gdb_get_regl(mem_buf, env->cregs[n]); + default: + return 0; + } +} + +static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case S390_C0_REGNUM ... S390_C15_REGNUM: + env->cregs[n] = ldtul_p(mem_buf); + if (tcg_enabled()) { + tlb_flush(ENV_GET_CPU(env), 1); + } + cpu_synchronize_post_init(ENV_GET_CPU(env)); + return 8; + default: + return 0; + } +} +#endif + void s390_cpu_gdb_init(CPUState *cs) { gdb_register_coprocessor(cs, cpu_read_ac_reg, @@ -187,4 +220,10 @@ void s390_cpu_gdb_init(CPUState *cs) gdb_register_coprocessor(cs, cpu_read_vreg, cpu_write_vreg, S390_NUM_VREGS, "s390-vx.xml", 0); + +#ifndef CONFIG_USER_ONLY + gdb_register_coprocessor(cs, cpu_read_c_reg, + cpu_write_c_reg, + S390_NUM_C_REGS, "s390-cr.xml", 0); +#endif } diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index ba1201e93d..5fdee1b20b 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -588,9 +588,9 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) * @addr: the logical start address in guest memory * @ar: the access register number * @hostbuf: buffer in host memory. NULL = do only checks w/o copying - * @len: length that should be transfered + * @len: length that should be transferred * @is_write: true = write, false = read - * Returns: 0 on success, non-zero if an exception or error occured + * Returns: 0 on success, non-zero if an exception or error occurred * * Use KVM ioctl to read/write from/to guest memory. An access exception * is injected into the vCPU in case of translation errors. diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index 6f8bd796ad..90399f1b0b 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 */ @@ -68,7 +69,7 @@ static inline uint64_t adj_len_to_page(uint64_t len, uint64_t addr) static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, uint32_t l) { - int mmu_idx = cpu_mmu_index(env); + int mmu_idx = cpu_mmu_index(env, false); while (l > 0) { void *p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx); @@ -91,7 +92,7 @@ static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src, uint32_t l) { - int mmu_idx = cpu_mmu_index(env); + int mmu_idx = cpu_mmu_index(env, false); while (l > 0) { void *src_p = tlb_vaddr_to_host(env, src, MMU_DATA_LOAD, mmu_idx); @@ -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; } } |