aboutsummaryrefslogtreecommitdiff
path: root/target/s390x/mmu_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/s390x/mmu_helper.c')
-rw-r--r--target/s390x/mmu_helper.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c
index d8f4838..3b1e75f 100644
--- a/target/s390x/mmu_helper.c
+++ b/target/s390x/mmu_helper.c
@@ -17,14 +17,15 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
-#include "exec/address-spaces.h"
+#include "system/address-spaces.h"
#include "cpu.h"
#include "s390x-internal.h"
#include "kvm/kvm_s390x.h"
#include "system/kvm.h"
#include "system/tcg.h"
-#include "exec/exec-all.h"
+#include "system/memory.h"
#include "exec/page-protection.h"
+#include "exec/target_page.h"
#include "hw/hw.h"
#include "hw/s390x/storage-keys.h"
#include "hw/boards.h"
@@ -522,6 +523,7 @@ int s390_cpu_pv_mem_rw(S390CPU *cpu, unsigned int offset, void *hostbuf,
int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
int len, bool is_write)
{
+ const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
int currlen, nr_pages, i;
target_ulong *pages;
uint64_t tec;
@@ -539,19 +541,28 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
pages = g_malloc(nr_pages * sizeof(*pages));
ret = translate_pages(cpu, laddr, nr_pages, pages, is_write, &tec);
- if (ret) {
- trigger_access_exception(&cpu->env, ret, tec);
- } else if (hostbuf != NULL) {
+ if (ret == 0 && hostbuf != NULL) {
+ AddressSpace *as = CPU(cpu)->as;
+
/* Copy data by stepping through the area page by page */
for (i = 0; i < nr_pages; i++) {
+ MemTxResult res;
+
currlen = MIN(len, TARGET_PAGE_SIZE - (laddr % TARGET_PAGE_SIZE));
- cpu_physical_memory_rw(pages[i] | (laddr & ~TARGET_PAGE_MASK),
- hostbuf, currlen, is_write);
+ res = address_space_rw(as, pages[i] | (laddr & ~TARGET_PAGE_MASK),
+ attrs, hostbuf, currlen, is_write);
+ if (res != MEMTX_OK) {
+ ret = PGM_ADDRESSING;
+ break;
+ }
laddr += currlen;
hostbuf += currlen;
len -= currlen;
}
}
+ if (ret) {
+ trigger_access_exception(&cpu->env, ret, tec);
+ }
g_free(pages);
return ret;