aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2024-04-16 17:39:25 -0700
committerRichard Henderson <richard.henderson@linaro.org>2024-05-15 10:03:44 +0200
commitd8bc1381250b39079d5ed33d2be7eee801ca41c9 (patch)
tree91f5361b4cfa8d59f7ac53fa1f4709a4fd888b51
parent5ae8adbb01cdb0bd2f3c1c444b3e543b38737102 (diff)
downloadqemu-d8bc1381250b39079d5ed33d2be7eee801ca41c9.zip
qemu-d8bc1381250b39079d5ed33d2be7eee801ca41c9.tar.gz
qemu-d8bc1381250b39079d5ed33d2be7eee801ca41c9.tar.bz2
target/hppa: Implement PSW_X
Use PAGE_WRITE_INV to temporarily enable write permission on for a given page, driven by PSW_X being set. Reviewed-by: Helge Deller <deller@gmx.de> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--target/hppa/mem_helper.c42
1 files changed, 25 insertions, 17 deletions
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index d09877a..ca7bbe0 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -296,30 +296,38 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
goto egress;
}
- /* In reverse priority order, check for conditions which raise faults.
- As we go, remove PROT bits that cover the condition we want to check.
- In this way, the resulting PROT will force a re-check of the
- architectural TLB entry for the next access. */
- if (unlikely(!ent->d)) {
+ /*
+ * In priority order, check for conditions which raise faults.
+ * Remove PROT bits that cover the condition we want to check,
+ * so that the resulting PROT will force a re-check of the
+ * architectural TLB entry for the next access.
+ */
+ if (unlikely(ent->t)) {
+ prot &= PAGE_EXEC;
+ if (!(type & PAGE_EXEC)) {
+ /* The T bit is set -- Page Reference Fault. */
+ ret = EXCP_PAGE_REF;
+ }
+ } else if (!ent->d) {
+ prot &= PAGE_READ | PAGE_EXEC;
if (type & PAGE_WRITE) {
/* The D bit is not set -- TLB Dirty Bit Fault. */
ret = EXCP_TLB_DIRTY;
}
+ } else if (unlikely(ent->b)) {
prot &= PAGE_READ | PAGE_EXEC;
- }
- if (unlikely(ent->b)) {
if (type & PAGE_WRITE) {
- /* The B bit is set -- Data Memory Break Fault. */
- ret = EXCP_DMB;
- }
- prot &= PAGE_READ | PAGE_EXEC;
- }
- if (unlikely(ent->t)) {
- if (!(type & PAGE_EXEC)) {
- /* The T bit is set -- Page Reference Fault. */
- ret = EXCP_PAGE_REF;
+ /*
+ * The B bit is set -- Data Memory Break Fault.
+ * Except when PSW_X is set, allow this single access to succeed.
+ * The write bit will be invalidated for subsequent accesses.
+ */
+ if (env->psw_xb & PSW_X) {
+ prot |= PAGE_WRITE_INV;
+ } else {
+ ret = EXCP_DMB;
+ }
}
- prot &= PAGE_EXEC;
}
egress: