@@ -336,9 +336,9 @@ DEF_HELPER_FLAGS_4(stctl, TCG_CALL_NO_WG, void, env, i32, i64, i32)
DEF_HELPER_FLAGS_4(stctg, TCG_CALL_NO_WG, void, env, i32, i64, i32)
DEF_HELPER_FLAGS_2(testblock, TCG_CALL_NO_WG, i32, env, i64)
DEF_HELPER_FLAGS_3(tprot, TCG_CALL_NO_WG, i32, env, i64, i64)
-DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64)
-DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64)
-DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_NO_RWG, i32, env, i64)
+DEF_HELPER_2(iske, i64, env, i64)
+DEF_HELPER_3(sske, void, env, i64, i64)
+DEF_HELPER_2(rrbe, i32, env, i64)
DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
DEF_HELPER_4(mvcp, i32, env, i64, i64, i64)
DEF_HELPER_4(sigp, i32, env, i64, i32, i32)
@@ -94,6 +94,14 @@ target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr)
return raddr;
}
+bool mmu_absolute_addr_valid(target_ulong addr, bool is_write)
+{
+ return address_space_access_valid(&address_space_memory,
+ addr & TARGET_PAGE_MASK,
+ TARGET_PAGE_SIZE, is_write,
+ MEMTXATTRS_UNSPECIFIED);
+}
+
static inline bool read_table_entry(CPUS390XState *env, hwaddr gaddr,
uint64_t *entry)
{
@@ -373,6 +373,7 @@ void probe_write_access(CPUS390XState *env, uint64_t addr, uint64_t len,
/* mmu_helper.c */
+bool mmu_absolute_addr_valid(target_ulong addr, bool is_write);
int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
target_ulong *raddr, int *flags, uint64_t *tec);
int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,
@@ -28,6 +28,7 @@
#include "qemu/int128.h"
#include "qemu/atomic128.h"
#include "tcg/tcg.h"
+#include "trace.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/s390x/storage-keys.h"
@@ -2171,15 +2172,15 @@ uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, uint64_t a2)
/* insert storage key extended */
uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
{
- MachineState *ms = MACHINE(qdev_get_machine());
static S390SKeysState *ss;
static S390SKeysClass *skeyclass;
uint64_t addr = wrap_address(env, r2);
uint8_t key;
+ int rc;
addr = mmu_real2abs(env, addr);
- if (addr > ms->ram_size) {
- return 0;
+ if (!mmu_absolute_addr_valid(addr, false)) {
+ trigger_pgm_exception(env, PGM_ADDRESSING);
}
if (unlikely(!ss)) {
@@ -2187,7 +2188,9 @@ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
skeyclass = S390_SKEYS_GET_CLASS(ss);
}
- if (skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key)) {
+ rc = skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
+ if (rc) {
+ trace_get_skeys_nonzero(rc);
return 0;
}
return key;
@@ -2196,15 +2199,15 @@ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
/* set storage key extended */
void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
{
- MachineState *ms = MACHINE(qdev_get_machine());
static S390SKeysState *ss;
static S390SKeysClass *skeyclass;
uint64_t addr = wrap_address(env, r2);
uint8_t key;
+ int rc;
addr = mmu_real2abs(env, addr);
- if (addr > ms->ram_size) {
- return;
+ if (!mmu_absolute_addr_valid(addr, false)) {
+ trigger_pgm_exception(env, PGM_ADDRESSING);
}
if (unlikely(!ss)) {
@@ -2213,7 +2216,11 @@ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
}
key = r1 & 0xfe;
- skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
+ rc = skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
+ if (rc) {
+ trace_set_skeys_nonzero(rc);
+ return 0;
+ }
/*
* As we can only flush by virtual address and not all the entries
* that point to a physical address we have to flush the whole TLB.
@@ -2224,15 +2231,15 @@ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
/* reset reference bit extended */
uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
{
- MachineState *ms = MACHINE(qdev_get_machine());
uint64_t addr = wrap_address(env, r2);
static S390SKeysState *ss;
static S390SKeysClass *skeyclass;
uint8_t re, key;
+ int rc;
addr = mmu_real2abs(env, addr);
- if (addr > ms->ram_size) {
- return 0;
+ if (!mmu_absolute_addr_valid(addr, false)) {
+ trigger_pgm_exception(env, PGM_ADDRESSING);
}
if (unlikely(!ss)) {
@@ -2240,14 +2247,18 @@ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
skeyclass = S390_SKEYS_GET_CLASS(ss);
}
- if (skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key)) {
+ rc = skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
+ if (rc) {
+ trace_get_skeys_nonzero(rc);
return 0;
}
re = key & (SK_R | SK_C);
key &= ~SK_R;
- if (skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key)) {
+ rc = skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
+ if (rc) {
+ trace_set_skeys_nonzero(rc);
return 0;
}
/*
Let's replace the ram_size check by a proper physical address space check (for example, to prepare for memory hotplug), trigger addressing exceptions and trace the return value of the storage key getter/setter. Provide an helper mmu_absolute_addr_valid() to be used in other context soon. Always test for "read" instead of "write" as we are not actually modifying the page itself. Signed-off-by: David Hildenbrand <david@redhat.com> --- target/s390x/helper.h | 6 +++--- target/s390x/mmu_helper.c | 8 ++++++++ target/s390x/s390x-internal.h | 1 + target/s390x/tcg/mem_helper.c | 37 +++++++++++++++++++++++------------ 4 files changed, 36 insertions(+), 16 deletions(-)