mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
target/hppa: add TLB protection id check
Signed-off-by: Sven Schnelle <svens@stackframe.org> Message-Id: <20190311191602.25796-10-svens@stackframe.org> [rth: Add required tlb flushing when prot id registers change.] Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
38188fd216
commit
d5de20bd84
6 changed files with 70 additions and 9 deletions
|
@ -143,6 +143,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CR_RC 0
|
#define CR_RC 0
|
||||||
|
#define CR_PID1 8
|
||||||
|
#define CR_PID2 9
|
||||||
|
#define CR_PID3 12
|
||||||
|
#define CR_PID4 13
|
||||||
#define CR_SCRCCR 10
|
#define CR_SCRCCR 10
|
||||||
#define CR_SAR 11
|
#define CR_SAR 11
|
||||||
#define CR_IVA 14
|
#define CR_IVA 14
|
||||||
|
@ -341,6 +345,12 @@ target_ureg cpu_hppa_get_psw(CPUHPPAState *env);
|
||||||
void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg);
|
void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg);
|
||||||
void cpu_hppa_loaded_fr0(CPUHPPAState *env);
|
void cpu_hppa_loaded_fr0(CPUHPPAState *env);
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
static inline void cpu_hppa_change_prot_id(CPUHPPAState *env) { }
|
||||||
|
#else
|
||||||
|
void cpu_hppa_change_prot_id(CPUHPPAState *env);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define cpu_signal_handler cpu_hppa_signal_handler
|
#define cpu_signal_handler cpu_hppa_signal_handler
|
||||||
|
|
||||||
int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
|
int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||||
|
|
|
@ -93,19 +93,19 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||||
val = env->cr[CR_RC];
|
val = env->cr[CR_RC];
|
||||||
break;
|
break;
|
||||||
case 52:
|
case 52:
|
||||||
val = env->cr[8];
|
val = env->cr[CR_PID1];
|
||||||
break;
|
break;
|
||||||
case 53:
|
case 53:
|
||||||
val = env->cr[9];
|
val = env->cr[CR_PID2];
|
||||||
break;
|
break;
|
||||||
case 54:
|
case 54:
|
||||||
val = env->cr[CR_SCRCCR];
|
val = env->cr[CR_SCRCCR];
|
||||||
break;
|
break;
|
||||||
case 55:
|
case 55:
|
||||||
val = env->cr[12];
|
val = env->cr[CR_PID3];
|
||||||
break;
|
break;
|
||||||
case 56:
|
case 56:
|
||||||
val = env->cr[13];
|
val = env->cr[CR_PID4];
|
||||||
break;
|
break;
|
||||||
case 57:
|
case 57:
|
||||||
val = env->cr[24];
|
val = env->cr[24];
|
||||||
|
@ -224,19 +224,23 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||||
env->cr[CR_RC] = val;
|
env->cr[CR_RC] = val;
|
||||||
break;
|
break;
|
||||||
case 52:
|
case 52:
|
||||||
env->cr[8] = val;
|
env->cr[CR_PID1] = val;
|
||||||
|
cpu_hppa_change_prot_id(env);
|
||||||
break;
|
break;
|
||||||
case 53:
|
case 53:
|
||||||
env->cr[9] = val;
|
env->cr[CR_PID2] = val;
|
||||||
|
cpu_hppa_change_prot_id(env);
|
||||||
break;
|
break;
|
||||||
case 54:
|
case 54:
|
||||||
env->cr[CR_SCRCCR] = val;
|
env->cr[CR_SCRCCR] = val;
|
||||||
break;
|
break;
|
||||||
case 55:
|
case 55:
|
||||||
env->cr[12] = val;
|
env->cr[CR_PID3] = val;
|
||||||
|
cpu_hppa_change_prot_id(env);
|
||||||
break;
|
break;
|
||||||
case 56:
|
case 56:
|
||||||
env->cr[13] = val;
|
env->cr[CR_PID4] = val;
|
||||||
|
cpu_hppa_change_prot_id(env);
|
||||||
break;
|
break;
|
||||||
case 57:
|
case 57:
|
||||||
env->cr[24] = val;
|
env->cr[24] = val;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "fpu/softfloat.h"
|
#include "fpu/softfloat.h"
|
||||||
|
#include "exec/exec-all.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
|
|
||||||
target_ureg cpu_hppa_get_psw(CPUHPPAState *env)
|
target_ureg cpu_hppa_get_psw(CPUHPPAState *env)
|
||||||
|
@ -49,6 +50,7 @@ target_ureg cpu_hppa_get_psw(CPUHPPAState *env)
|
||||||
|
|
||||||
void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw)
|
void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw)
|
||||||
{
|
{
|
||||||
|
target_ureg old_psw = env->psw;
|
||||||
target_ureg cb = 0;
|
target_ureg cb = 0;
|
||||||
|
|
||||||
env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
|
env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
|
||||||
|
@ -64,6 +66,14 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw)
|
||||||
cb |= ((psw >> 9) & 1) << 8;
|
cb |= ((psw >> 9) & 1) << 8;
|
||||||
cb |= ((psw >> 8) & 1) << 4;
|
cb |= ((psw >> 8) & 1) << 4;
|
||||||
env->psw_cb = cb;
|
env->psw_cb = cb;
|
||||||
|
|
||||||
|
/* If PSW_P changes, it affects how we translate addresses. */
|
||||||
|
if ((psw ^ old_psw) & PSW_P) {
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
CPUState *src = CPU(hppa_env_get_cpu(env));
|
||||||
|
tlb_flush_by_mmuidx(src, 0xf);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hppa_cpu_dump_state(CPUState *cs, FILE *f,
|
void hppa_cpu_dump_state(CPUState *cs, FILE *f,
|
||||||
|
|
|
@ -92,4 +92,5 @@ DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr)
|
||||||
DEF_HELPER_FLAGS_2(ptlb, TCG_CALL_NO_RWG, void, env, tl)
|
DEF_HELPER_FLAGS_2(ptlb, TCG_CALL_NO_RWG, void, env, tl)
|
||||||
DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env)
|
DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env)
|
||||||
DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tr, env, tl)
|
DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tr, env, tl)
|
||||||
|
DEF_HELPER_FLAGS_1(change_prot_id, TCG_CALL_NO_RWG, void, env)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -131,7 +131,20 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ??? Check PSW_P and ent->access_prot. This can remove PAGE_WRITE. */
|
/* access_id == 0 means public page and no check is performed */
|
||||||
|
if ((env->psw & PSW_P) && ent->access_id) {
|
||||||
|
/* If bits [31:1] match, and bit 0 is set, suppress write. */
|
||||||
|
int match = ent->access_id * 2 + 1;
|
||||||
|
|
||||||
|
if (match == env->cr[CR_PID1] || match == env->cr[CR_PID2] ||
|
||||||
|
match == env->cr[CR_PID3] || match == env->cr[CR_PID4]) {
|
||||||
|
prot &= PAGE_READ | PAGE_EXEC;
|
||||||
|
if (type == PAGE_WRITE) {
|
||||||
|
ret = EXCP_DMPI;
|
||||||
|
goto egress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* No guest access type indicates a non-architectural access from
|
/* No guest access type indicates a non-architectural access from
|
||||||
within QEMU. Bypass checks for access, D, B and T bits. */
|
within QEMU. Bypass checks for access, D, B and T bits. */
|
||||||
|
@ -334,6 +347,19 @@ void HELPER(ptlbe)(CPUHPPAState *env)
|
||||||
tlb_flush_by_mmuidx(src, 0xf);
|
tlb_flush_by_mmuidx(src, 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cpu_hppa_change_prot_id(CPUHPPAState *env)
|
||||||
|
{
|
||||||
|
if (env->psw & PSW_P) {
|
||||||
|
CPUState *src = CPU(hppa_env_get_cpu(env));
|
||||||
|
tlb_flush_by_mmuidx(src, 0xf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HELPER(change_prot_id)(CPUHPPAState *env)
|
||||||
|
{
|
||||||
|
cpu_hppa_change_prot_id(env);
|
||||||
|
}
|
||||||
|
|
||||||
target_ureg HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
|
target_ureg HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
|
||||||
{
|
{
|
||||||
hwaddr phys;
|
hwaddr phys;
|
||||||
|
|
|
@ -2256,6 +2256,16 @@ static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
|
||||||
offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
|
offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CR_PID1:
|
||||||
|
case CR_PID2:
|
||||||
|
case CR_PID3:
|
||||||
|
case CR_PID4:
|
||||||
|
tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
gen_helper_change_prot_id(cpu_env);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
|
tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue