target/hppa: Implement IDTLBT, IITLBT
Rename the existing insert tlb helpers to emphasize that they are for pa1.1 cpus. Implement a combined i/d tlb for pa2.0. Still missing is the new 'P' tlb bit. Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
25460fc5a7
commit
8577f35479
@ -94,8 +94,10 @@ DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr)
|
||||
DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tr)
|
||||
DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr)
|
||||
DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr)
|
||||
DEF_HELPER_FLAGS_3(itlba, TCG_CALL_NO_RWG, void, env, tl, tr)
|
||||
DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr)
|
||||
DEF_HELPER_FLAGS_3(itlba_pa11, TCG_CALL_NO_RWG, void, env, tl, tr)
|
||||
DEF_HELPER_FLAGS_3(itlbp_pa11, TCG_CALL_NO_RWG, void, env, tl, tr)
|
||||
DEF_HELPER_FLAGS_3(idtlbt_pa20, TCG_CALL_NO_RWG, void, env, tr, tr)
|
||||
DEF_HELPER_FLAGS_3(iitlbt_pa20, TCG_CALL_NO_RWG, void, env, tr, tr)
|
||||
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_2(lpa, TCG_CALL_NO_WG, tr, env, tl)
|
||||
|
@ -145,6 +145,7 @@ nop_addrx 000001 ..... ..... -- 01001110 . 00000 @addrx # pdc
|
||||
|
||||
probe 000001 b:5 ri:5 sp:2 imm:1 100011 write:1 0 t:5
|
||||
|
||||
# pa1.x tlb insert instructions
|
||||
ixtlbx 000001 b:5 r:5 sp:2 0100000 addr:1 0 00000 data=1
|
||||
ixtlbx 000001 b:5 r:5 ... 000000 addr:1 0 00000 \
|
||||
sp=%assemble_sr3x data=0
|
||||
@ -152,6 +153,9 @@ ixtlbx 000001 b:5 r:5 ... 000000 addr:1 0 00000 \
|
||||
# pcxl and pcxl2 Fast TLB Insert instructions
|
||||
ixtlbxf 000001 00000 r:5 00 0 data:1 01000 addr:1 0 00000
|
||||
|
||||
# pa2.0 tlb insert idtlbt and iitlbt instructions
|
||||
ixtlbt 000001 r2:5 r1:5 000 data:1 100000 0 00000 # idtlbt
|
||||
|
||||
pxtlbx 000001 b:5 x:5 sp:2 0100100 local:1 m:1 ----- data=1
|
||||
pxtlbx 000001 b:5 x:5 ... 000100 local:1 m:1 ----- \
|
||||
sp=%assemble_sr3x data=0
|
||||
|
@ -344,7 +344,7 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
|
||||
}
|
||||
|
||||
/* Insert (Insn/Data) TLB Address. Note this is PA 1.1 only. */
|
||||
void HELPER(itlba)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
||||
void HELPER(itlba_pa11)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
||||
{
|
||||
HPPATLBEntry *ent;
|
||||
|
||||
@ -365,7 +365,8 @@ void HELPER(itlba)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
||||
trace_hppa_tlb_itlba(env, ent, ent->itree.start, ent->itree.last, ent->pa);
|
||||
}
|
||||
|
||||
static void set_access_bits(CPUHPPAState *env, HPPATLBEntry *ent, target_ureg reg)
|
||||
static void set_access_bits_pa11(CPUHPPAState *env, HPPATLBEntry *ent,
|
||||
target_ureg reg)
|
||||
{
|
||||
ent->access_id = extract32(reg, 1, 18);
|
||||
ent->u = extract32(reg, 19, 1);
|
||||
@ -383,20 +384,70 @@ static void set_access_bits(CPUHPPAState *env, HPPATLBEntry *ent, target_ureg re
|
||||
}
|
||||
|
||||
/* Insert (Insn/Data) TLB Protection. Note this is PA 1.1 only. */
|
||||
void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
||||
void HELPER(itlbp_pa11)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
||||
{
|
||||
HPPATLBEntry *ent = env->tlb_partial;
|
||||
|
||||
if (ent) {
|
||||
env->tlb_partial = NULL;
|
||||
if (ent->itree.start <= addr && addr <= ent->itree.last) {
|
||||
set_access_bits(env, ent, reg);
|
||||
set_access_bits_pa11(env, ent, reg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "ITLBP not following ITLBA\n");
|
||||
}
|
||||
|
||||
static void itlbt_pa20(CPUHPPAState *env, target_ureg r1,
|
||||
target_ureg r2, vaddr va_b)
|
||||
{
|
||||
HPPATLBEntry *ent;
|
||||
vaddr va_e;
|
||||
uint64_t va_size;
|
||||
int mask_shift;
|
||||
|
||||
mask_shift = 2 * (r1 & 0xf);
|
||||
va_size = TARGET_PAGE_SIZE << mask_shift;
|
||||
va_b &= -va_size;
|
||||
va_e = va_b + va_size - 1;
|
||||
|
||||
hppa_flush_tlb_range(env, va_b, va_e);
|
||||
ent = hppa_alloc_tlb_ent(env);
|
||||
|
||||
ent->itree.start = va_b;
|
||||
ent->itree.last = va_e;
|
||||
ent->pa = (r1 << 7) & (TARGET_PAGE_MASK << mask_shift);
|
||||
ent->t = extract64(r2, 61, 1);
|
||||
ent->d = extract64(r2, 60, 1);
|
||||
ent->b = extract64(r2, 59, 1);
|
||||
ent->ar_type = extract64(r2, 56, 3);
|
||||
ent->ar_pl1 = extract64(r2, 54, 2);
|
||||
ent->ar_pl2 = extract64(r2, 52, 2);
|
||||
ent->u = extract64(r2, 51, 1);
|
||||
/* o = bit 50 */
|
||||
/* p = bit 49 */
|
||||
ent->access_id = extract64(r2, 1, 31);
|
||||
ent->entry_valid = 1;
|
||||
|
||||
interval_tree_insert(&ent->itree, &env->tlb_root);
|
||||
trace_hppa_tlb_itlba(env, ent, ent->itree.start, ent->itree.last, ent->pa);
|
||||
trace_hppa_tlb_itlbp(env, ent, ent->access_id, ent->u,
|
||||
ent->ar_pl2, ent->ar_pl1, ent->ar_type,
|
||||
ent->b, ent->d, ent->t);
|
||||
}
|
||||
|
||||
void HELPER(idtlbt_pa20)(CPUHPPAState *env, target_ureg r1, target_ureg r2)
|
||||
{
|
||||
vaddr va_b = deposit64(env->cr[CR_IOR], 32, 32, env->cr[CR_ISR]);
|
||||
itlbt_pa20(env, r1, r2, va_b);
|
||||
}
|
||||
|
||||
void HELPER(iitlbt_pa20)(CPUHPPAState *env, target_ureg r1, target_ureg r2)
|
||||
{
|
||||
vaddr va_b = deposit64(env->cr[CR_IIAOQ], 32, 32, env->cr[CR_IIASQ]);
|
||||
itlbt_pa20(env, r1, r2, va_b);
|
||||
}
|
||||
|
||||
/* Purge (Insn/Data) TLB. This is explicitly page-based, and is
|
||||
synchronous across all processors. */
|
||||
static void ptlb_work(CPUState *cpu, run_on_cpu_data data)
|
||||
@ -563,7 +614,7 @@ void HELPER(diag_btlb)(CPUHPPAState *env)
|
||||
btlb->itree.start = virt_page << TARGET_PAGE_BITS;
|
||||
btlb->itree.last = btlb->itree.start + len * TARGET_PAGE_SIZE - 1;
|
||||
btlb->pa = phys_page << TARGET_PAGE_BITS;
|
||||
set_access_bits(env, btlb, env->gr[20]);
|
||||
set_access_bits_pa11(env, btlb, env->gr[20]);
|
||||
btlb->t = 0;
|
||||
btlb->d = 1;
|
||||
} else {
|
||||
|
@ -2514,6 +2514,9 @@ static bool trans_probe(DisasContext *ctx, arg_probe *a)
|
||||
|
||||
static bool trans_ixtlbx(DisasContext *ctx, arg_ixtlbx *a)
|
||||
{
|
||||
if (ctx->is_pa20) {
|
||||
return false;
|
||||
}
|
||||
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
TCGv_tl addr;
|
||||
@ -2524,9 +2527,9 @@ static bool trans_ixtlbx(DisasContext *ctx, arg_ixtlbx *a)
|
||||
form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
|
||||
reg = load_gpr(ctx, a->r);
|
||||
if (a->addr) {
|
||||
gen_helper_itlba(tcg_env, addr, reg);
|
||||
gen_helper_itlba_pa11(tcg_env, addr, reg);
|
||||
} else {
|
||||
gen_helper_itlbp(tcg_env, addr, reg);
|
||||
gen_helper_itlbp_pa11(tcg_env, addr, reg);
|
||||
}
|
||||
|
||||
/* Exit TB for TLB change if mmu is enabled. */
|
||||
@ -2572,6 +2575,9 @@ static bool trans_pxtlbx(DisasContext *ctx, arg_pxtlbx *a)
|
||||
*/
|
||||
static bool trans_ixtlbxf(DisasContext *ctx, arg_ixtlbxf *a)
|
||||
{
|
||||
if (ctx->is_pa20) {
|
||||
return false;
|
||||
}
|
||||
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
TCGv_tl addr, atl, stl;
|
||||
@ -2583,8 +2589,6 @@ static bool trans_ixtlbxf(DisasContext *ctx, arg_ixtlbxf *a)
|
||||
* FIXME:
|
||||
* if (not (pcxl or pcxl2))
|
||||
* return gen_illegal(ctx);
|
||||
*
|
||||
* Note for future: these are 32-bit systems; no hppa64.
|
||||
*/
|
||||
|
||||
atl = tcg_temp_new_tl();
|
||||
@ -2602,9 +2606,9 @@ static bool trans_ixtlbxf(DisasContext *ctx, arg_ixtlbxf *a)
|
||||
|
||||
reg = load_gpr(ctx, a->r);
|
||||
if (a->addr) {
|
||||
gen_helper_itlba(tcg_env, addr, reg);
|
||||
gen_helper_itlba_pa11(tcg_env, addr, reg);
|
||||
} else {
|
||||
gen_helper_itlbp(tcg_env, addr, reg);
|
||||
gen_helper_itlbp_pa11(tcg_env, addr, reg);
|
||||
}
|
||||
|
||||
/* Exit TB for TLB change if mmu is enabled. */
|
||||
@ -2615,6 +2619,32 @@ static bool trans_ixtlbxf(DisasContext *ctx, arg_ixtlbxf *a)
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool trans_ixtlbt(DisasContext *ctx, arg_ixtlbt *a)
|
||||
{
|
||||
if (!ctx->is_pa20) {
|
||||
return false;
|
||||
}
|
||||
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
nullify_over(ctx);
|
||||
{
|
||||
TCGv_i64 src1 = load_gpr(ctx, a->r1);
|
||||
TCGv_i64 src2 = load_gpr(ctx, a->r2);
|
||||
|
||||
if (a->data) {
|
||||
gen_helper_idtlbt_pa20(tcg_env, src1, src2);
|
||||
} else {
|
||||
gen_helper_iitlbt_pa20(tcg_env, src1, src2);
|
||||
}
|
||||
}
|
||||
/* Exit TB for TLB change if mmu is enabled. */
|
||||
if (ctx->tb_flags & PSW_C) {
|
||||
ctx->base.is_jmp = DISAS_IAQ_N_STALE;
|
||||
}
|
||||
return nullify_end(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool trans_lpa(DisasContext *ctx, arg_ldst *a)
|
||||
{
|
||||
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||
|
Loading…
Reference in New Issue
Block a user