From: Brian Cain <bcain@quicinc.com>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
linux-user/hexagon/cpu_loop.c | 7 +++++
target/hexagon/hex_mmu.c | 54 ++++++++++++++++++++++++++++++++++-
2 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
index 28ad8073f6..7853819f77 100644
--- a/linux-user/hexagon/cpu_loop.c
+++ b/linux-user/hexagon/cpu_loop.c
@@ -63,6 +63,13 @@ void cpu_loop(CPUHexagonState *env)
break;
case HEX_EVENT_PRECISE:
switch (env->cause_code) {
+ case HEX_CAUSE_FETCH_NO_UPAGE:
+ case HEX_CAUSE_PRIV_NO_UREAD:
+ case HEX_CAUSE_PRIV_NO_UWRITE:
+ force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
+ env->gpr[HEX_REG_PC]);
+
+ break;
case HEX_CAUSE_PRIV_USER_NO_GINSN:
case HEX_CAUSE_PRIV_USER_NO_SINSN:
case HEX_CAUSE_INVALID_PACKET:
diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c
index 332e7f4029..8f9f16158f 100644
--- a/target/hexagon/hex_mmu.c
+++ b/target/hexagon/hex_mmu.c
@@ -264,7 +264,59 @@ static inline void hex_tlb_entry_get_perm(CPUHexagonState *env, uint64_t entry,
int mmu_idx, int *prot,
int32_t *excp)
{
- g_assert_not_reached();
+ bool perm_x = GET_TLB_FIELD(entry, PTE_X);
+ bool perm_w = GET_TLB_FIELD(entry, PTE_W);
+ bool perm_r = GET_TLB_FIELD(entry, PTE_R);
+ bool perm_u = GET_TLB_FIELD(entry, PTE_U);
+ bool user_idx = mmu_idx == MMU_USER_IDX;
+
+ if (mmu_idx == MMU_KERNEL_IDX) {
+ *prot = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ return;
+ }
+
+ *prot = PAGE_VALID;
+ switch (access_type) {
+ case MMU_INST_FETCH:
+ if (user_idx && !perm_u) {
+ *excp = HEX_EVENT_PRECISE;
+ env->cause_code = HEX_CAUSE_FETCH_NO_UPAGE;
+ } else if (!perm_x) {
+ *excp = HEX_EVENT_PRECISE;
+ env->cause_code = HEX_CAUSE_FETCH_NO_XPAGE;
+ }
+ break;
+ case MMU_DATA_LOAD:
+ if (user_idx && !perm_u) {
+ *excp = HEX_EVENT_PRECISE;
+ env->cause_code = HEX_CAUSE_PRIV_NO_UREAD;
+ } else if (!perm_r) {
+ *excp = HEX_EVENT_PRECISE;
+ env->cause_code = HEX_CAUSE_PRIV_NO_READ;
+ }
+ break;
+ case MMU_DATA_STORE:
+ if (user_idx && !perm_u) {
+ *excp = HEX_EVENT_PRECISE;
+ env->cause_code = HEX_CAUSE_PRIV_NO_UWRITE;
+ } else if (!perm_w) {
+ *excp = HEX_EVENT_PRECISE;
+ env->cause_code = HEX_CAUSE_PRIV_NO_WRITE;
+ }
+ break;
+ }
+
+ if (!user_idx || perm_u) {
+ if (perm_x) {
+ *prot |= PAGE_EXEC;
+ }
+ if (perm_r) {
+ *prot |= PAGE_READ;
+ }
+ if (perm_w) {
+ *prot |= PAGE_WRITE;
+ }
+ }
}
static inline bool hex_tlb_entry_match(CPUHexagonState *env, uint64_t entry,
--
2.34.1