mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
target/hppa: Wire up diag instruction to support BTLB
Wire up the hppa diag instruction to support Block-TLBs when called with the 0x100 value. The diag_btlb() helper function does all necessary steps to emulate the PDC BTLB firmware function, which includes providing BTLB info, adding a new BTLB, deleting a BTLB and removing all BTLBs. Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
parent
a64b8842f1
commit
cf6b28d41b
3 changed files with 105 additions and 3 deletions
|
@ -95,4 +95,5 @@ 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)
|
DEF_HELPER_FLAGS_1(change_prot_id, TCG_CALL_NO_RWG, void, env)
|
||||||
|
DEF_HELPER_1(diag_btlb, void, env)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -412,3 +412,95 @@ int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr)
|
||||||
hppa_tlb_entry *ent = hppa_find_tlb(env, vaddr);
|
hppa_tlb_entry *ent = hppa_find_tlb(env, vaddr);
|
||||||
return ent ? ent->ar_type : -1;
|
return ent ? ent->ar_type : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* diag_btlb() emulates the PDC PDC_BLOCK_TLB firmware call to
|
||||||
|
* allow operating systems to modify the Block TLB (BTLB) entries.
|
||||||
|
* For implementation details see page 1-13 in
|
||||||
|
* https://parisc.wiki.kernel.org/images-parisc/e/ef/Pdc11-v0.96-Ch1-procs.pdf
|
||||||
|
*/
|
||||||
|
void HELPER(diag_btlb)(CPUHPPAState *env)
|
||||||
|
{
|
||||||
|
unsigned int phys_page, len, slot;
|
||||||
|
int mmu_idx = cpu_mmu_index(env, 0);
|
||||||
|
uintptr_t ra = GETPC();
|
||||||
|
hppa_tlb_entry *btlb;
|
||||||
|
uint64_t virt_page;
|
||||||
|
uint32_t *vaddr;
|
||||||
|
|
||||||
|
#ifdef TARGET_HPPA64
|
||||||
|
/* BTLBs are not supported on 64-bit CPUs */
|
||||||
|
env->gr[28] = -1; /* nonexistent procedure */
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
env->gr[28] = 0; /* PDC_OK */
|
||||||
|
|
||||||
|
switch (env->gr[25]) {
|
||||||
|
case 0:
|
||||||
|
/* return BTLB parameters */
|
||||||
|
qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_INFO\n");
|
||||||
|
vaddr = probe_access(env, env->gr[24], 4 * sizeof(target_ulong),
|
||||||
|
MMU_DATA_STORE, mmu_idx, ra);
|
||||||
|
if (vaddr == NULL) {
|
||||||
|
env->gr[28] = -10; /* invalid argument */
|
||||||
|
} else {
|
||||||
|
vaddr[0] = cpu_to_be32(1);
|
||||||
|
vaddr[1] = cpu_to_be32(16 * 1024);
|
||||||
|
vaddr[2] = cpu_to_be32(HPPA_BTLB_FIXED);
|
||||||
|
vaddr[3] = cpu_to_be32(HPPA_BTLB_VARIABLE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* insert BTLB entry */
|
||||||
|
virt_page = env->gr[24]; /* upper 32 bits */
|
||||||
|
virt_page <<= 32;
|
||||||
|
virt_page |= env->gr[23]; /* lower 32 bits */
|
||||||
|
phys_page = env->gr[22];
|
||||||
|
len = env->gr[21];
|
||||||
|
slot = env->gr[19];
|
||||||
|
qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_INSERT "
|
||||||
|
"0x%08llx-0x%08llx: vpage 0x%llx for phys page 0x%04x len %d "
|
||||||
|
"into slot %d\n",
|
||||||
|
(long long) virt_page << TARGET_PAGE_BITS,
|
||||||
|
(long long) (virt_page + len) << TARGET_PAGE_BITS,
|
||||||
|
(long long) virt_page, phys_page, len, slot);
|
||||||
|
if (slot < HPPA_BTLB_ENTRIES) {
|
||||||
|
btlb = &env->tlb[slot];
|
||||||
|
/* force flush of possibly existing BTLB entry */
|
||||||
|
hppa_flush_tlb_ent(env, btlb, true);
|
||||||
|
/* create new BTLB entry */
|
||||||
|
btlb->va_b = virt_page << TARGET_PAGE_BITS;
|
||||||
|
btlb->va_e = btlb->va_b + len * TARGET_PAGE_SIZE - 1;
|
||||||
|
btlb->pa = phys_page << TARGET_PAGE_BITS;
|
||||||
|
set_access_bits(env, btlb, env->gr[20]);
|
||||||
|
btlb->t = 0;
|
||||||
|
btlb->d = 1;
|
||||||
|
} else {
|
||||||
|
env->gr[28] = -10; /* invalid argument */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* Purge BTLB entry */
|
||||||
|
slot = env->gr[22];
|
||||||
|
qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_PURGE slot %d\n",
|
||||||
|
slot);
|
||||||
|
if (slot < HPPA_BTLB_ENTRIES) {
|
||||||
|
btlb = &env->tlb[slot];
|
||||||
|
hppa_flush_tlb_ent(env, btlb, true);
|
||||||
|
} else {
|
||||||
|
env->gr[28] = -10; /* invalid argument */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
/* Purge all BTLB entries */
|
||||||
|
qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_PURGE_ALL\n");
|
||||||
|
for (slot = 0; slot < HPPA_BTLB_ENTRIES; slot++) {
|
||||||
|
btlb = &env->tlb[slot];
|
||||||
|
hppa_flush_tlb_ent(env, btlb, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
env->gr[28] = -2; /* nonexistent option */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4042,9 +4042,18 @@ static bool trans_fmpyfadd_d(DisasContext *ctx, arg_fmpyfadd_d *a)
|
||||||
|
|
||||||
static bool trans_diag(DisasContext *ctx, arg_diag *a)
|
static bool trans_diag(DisasContext *ctx, arg_diag *a)
|
||||||
{
|
{
|
||||||
qemu_log_mask(LOG_UNIMP, "DIAG opcode ignored\n");
|
nullify_over(ctx);
|
||||||
cond_free(&ctx->null_cond);
|
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||||
return true;
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
if (a->i == 0x100) {
|
||||||
|
/* emulate PDC BTLB, called by SeaBIOS-hppa */
|
||||||
|
gen_helper_diag_btlb(cpu_env);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
qemu_log_mask(LOG_UNIMP, "DIAG opcode 0x%04x ignored\n", a->i);
|
||||||
|
}
|
||||||
|
return nullify_end(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue