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>
This commit is contained in:
Richard Henderson 2024-04-16 17:39:25 -07:00
parent 5ae8adbb01
commit d8bc138125

View File

@ -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)) {
if (type & PAGE_WRITE) {
/* The D bit is not set -- TLB Dirty Bit Fault. */
ret = EXCP_TLB_DIRTY;
}
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;
}
/*
* 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;
}
prot &= PAGE_EXEC;
} 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 (type & PAGE_WRITE) {
/*
* 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;
}
}
}
egress: