提交 fb66944d 编写于 作者: D David Hildenbrand 提交者: Cornelia Huck

s390x/tcg: add MMU for real addresses

This makes it easy to access real addresses (prefix) and in addition
checks for valid memory addresses, which is missing when using e.g.
stl_phys().

We can later reuse it to implement low address protection checks (then
we might even decide to introduce yet another MMU for absolute
addresses, just for handling storage keys and low address protection).
Signed-off-by: NDavid Hildenbrand <david@redhat.com>
Message-Id: <20170926183318.12995-3-david@redhat.com>
Reviewed-by: NRichard Henderson <richard.henderson@linaro.org>
Reviewed-by: NThomas Huth <thuth@redhat.com>
Signed-off-by: NCornelia Huck <cohuck@redhat.com>
上级 0bd695a9
...@@ -43,12 +43,13 @@ ...@@ -43,12 +43,13 @@
#include "fpu/softfloat.h" #include "fpu/softfloat.h"
#define NB_MMU_MODES 3 #define NB_MMU_MODES 4
#define TARGET_INSN_START_EXTRA_WORDS 1 #define TARGET_INSN_START_EXTRA_WORDS 1
#define MMU_MODE0_SUFFIX _primary #define MMU_MODE0_SUFFIX _primary
#define MMU_MODE1_SUFFIX _secondary #define MMU_MODE1_SUFFIX _secondary
#define MMU_MODE2_SUFFIX _home #define MMU_MODE2_SUFFIX _home
#define MMU_MODE3_SUFFIX _real
#define MMU_USER_IDX 0 #define MMU_USER_IDX 0
...@@ -351,6 +352,7 @@ extern const struct VMStateDescription vmstate_s390_cpu; ...@@ -351,6 +352,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;
#define MMU_PRIMARY_IDX 0 #define MMU_PRIMARY_IDX 0
#define MMU_SECONDARY_IDX 1 #define MMU_SECONDARY_IDX 1
#define MMU_HOME_IDX 2 #define MMU_HOME_IDX 2
#define MMU_REAL_IDX 3
static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch) static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
{ {
......
...@@ -88,8 +88,8 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, ...@@ -88,8 +88,8 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
{ {
S390CPU *cpu = S390_CPU(cs); S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env; CPUS390XState *env = &cpu->env;
uint64_t asc = cpu_mmu_idx_to_asc(mmu_idx);
target_ulong vaddr, raddr; target_ulong vaddr, raddr;
uint64_t asc;
int prot; int prot;
DPRINTF("%s: address 0x%" VADDR_PRIx " rw %d mmu_idx %d\n", DPRINTF("%s: address 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
...@@ -98,14 +98,21 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, ...@@ -98,14 +98,21 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
orig_vaddr &= TARGET_PAGE_MASK; orig_vaddr &= TARGET_PAGE_MASK;
vaddr = orig_vaddr; vaddr = orig_vaddr;
/* 31-Bit mode */ if (mmu_idx < MMU_REAL_IDX) {
if (!(env->psw.mask & PSW_MASK_64)) { asc = cpu_mmu_idx_to_asc(mmu_idx);
vaddr &= 0x7fffffff; /* 31-Bit mode */
} if (!(env->psw.mask & PSW_MASK_64)) {
vaddr &= 0x7fffffff;
if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) { }
/* Translation ended in exception */ if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) {
return 1; return 1;
}
} else if (mmu_idx == MMU_REAL_IDX) {
if (mmu_translate_real(env, vaddr, rw, &raddr, &prot)) {
return 1;
}
} else {
abort();
} }
/* check out of RAM access */ /* check out of RAM access */
......
...@@ -389,6 +389,8 @@ target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr); ...@@ -389,6 +389,8 @@ target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
/* mmu_helper.c */ /* mmu_helper.c */
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);
int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,
target_ulong *addr, int *flags);
/* misc_helper.c */ /* misc_helper.c */
......
...@@ -497,3 +497,22 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf, ...@@ -497,3 +497,22 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
g_free(pages); g_free(pages);
return ret; return ret;
} }
/**
* Translate a real address into a physical (absolute) address.
* @param raddr the real address
* @param rw 0 = read, 1 = write, 2 = code fetch
* @param addr the translated address is stored to this pointer
* @param flags the PAGE_READ/WRITE/EXEC flags are stored to this pointer
* @return 0 if the translation was successful, < 0 if a fault occurred
*/
int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,
target_ulong *addr, int *flags)
{
/* TODO: low address protection once we flush the tlb on cr changes */
*flags = PAGE_READ | PAGE_WRITE;
*addr = mmu_real2abs(env, raddr);
/* TODO: storage key handling */
return 0;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册