mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 00:05:36 +00:00
target/riscv: Change the TLB page size depends on PMP entries.
The minimum granularity of PMP is 4 bytes, it is small than 4KB page size, therefore, the pmp checking would be ignored if its range doesn't start from the alignment of one page. This patch detects the pmp entries and sets the small page size to TLB if there is a PMP entry which cover the page size. Backports af3fc195e3c8e98b62eca3e4ee927f1965381dc3
This commit is contained in:
parent
2edba8fcfe
commit
9792907bcf
|
@ -7300,6 +7300,7 @@ riscv_symbols = (
|
||||||
'helper_vcompress_vm_w',
|
'helper_vcompress_vm_w',
|
||||||
'helper_vcompress_vm_d',
|
'helper_vcompress_vm_d',
|
||||||
'pmp_hart_has_privs',
|
'pmp_hart_has_privs',
|
||||||
|
'pmp_is_range_in_tlb',
|
||||||
'pmpaddr_csr_read',
|
'pmpaddr_csr_read',
|
||||||
'pmpaddr_csr_write',
|
'pmpaddr_csr_write',
|
||||||
'pmpcfg_csr_read',
|
'pmpcfg_csr_read',
|
||||||
|
|
|
@ -4736,6 +4736,7 @@
|
||||||
#define helper_vcompress_vm_w helper_vcompress_vm_w_riscv32
|
#define helper_vcompress_vm_w helper_vcompress_vm_w_riscv32
|
||||||
#define helper_vcompress_vm_d helper_vcompress_vm_d_riscv32
|
#define helper_vcompress_vm_d helper_vcompress_vm_d_riscv32
|
||||||
#define pmp_hart_has_privs pmp_hart_has_privs_riscv32
|
#define pmp_hart_has_privs pmp_hart_has_privs_riscv32
|
||||||
|
#define pmp_is_range_in_tlb pmp_is_range_in_tlb_riscv32
|
||||||
#define pmpaddr_csr_read pmpaddr_csr_read_riscv32
|
#define pmpaddr_csr_read pmpaddr_csr_read_riscv32
|
||||||
#define pmpaddr_csr_write pmpaddr_csr_write_riscv32
|
#define pmpaddr_csr_write pmpaddr_csr_write_riscv32
|
||||||
#define pmpcfg_csr_read pmpcfg_csr_read_riscv32
|
#define pmpcfg_csr_read pmpcfg_csr_read_riscv32
|
||||||
|
|
|
@ -4736,6 +4736,7 @@
|
||||||
#define helper_vcompress_vm_w helper_vcompress_vm_w_riscv64
|
#define helper_vcompress_vm_w helper_vcompress_vm_w_riscv64
|
||||||
#define helper_vcompress_vm_d helper_vcompress_vm_d_riscv64
|
#define helper_vcompress_vm_d helper_vcompress_vm_d_riscv64
|
||||||
#define pmp_hart_has_privs pmp_hart_has_privs_riscv64
|
#define pmp_hart_has_privs pmp_hart_has_privs_riscv64
|
||||||
|
#define pmp_is_range_in_tlb pmp_is_range_in_tlb_riscv64
|
||||||
#define pmpaddr_csr_read pmpaddr_csr_read_riscv64
|
#define pmpaddr_csr_read pmpaddr_csr_read_riscv64
|
||||||
#define pmpaddr_csr_write pmpaddr_csr_write_riscv64
|
#define pmpaddr_csr_write pmpaddr_csr_write_riscv64
|
||||||
#define pmpcfg_csr_read pmpcfg_csr_read_riscv64
|
#define pmpcfg_csr_read pmpcfg_csr_read_riscv64
|
||||||
|
|
|
@ -684,6 +684,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||||
bool first_stage_error = true;
|
bool first_stage_error = true;
|
||||||
int ret = TRANSLATE_FAIL;
|
int ret = TRANSLATE_FAIL;
|
||||||
int mode = mmu_idx;
|
int mode = mmu_idx;
|
||||||
|
target_ulong tlb_size = 0;
|
||||||
|
|
||||||
env->guest_phys_fault_addr = 0;
|
env->guest_phys_fault_addr = 0;
|
||||||
|
|
||||||
|
@ -775,8 +776,13 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == TRANSLATE_SUCCESS) {
|
if (ret == TRANSLATE_SUCCESS) {
|
||||||
tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK,
|
if (pmp_is_range_in_tlb(env, pa & TARGET_PAGE_MASK, &tlb_size)) {
|
||||||
prot, mmu_idx, TARGET_PAGE_SIZE);
|
tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
|
||||||
|
prot, mmu_idx, tlb_size);
|
||||||
|
} else {
|
||||||
|
tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK,
|
||||||
|
prot, mmu_idx, TARGET_PAGE_SIZE);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (probe) {
|
} else if (probe) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -383,4 +383,56 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the TLB size if the start address or the end address of
|
||||||
|
* PMP entry is presented in thie TLB page.
|
||||||
|
*/
|
||||||
|
static target_ulong pmp_get_tlb_size(CPURISCVState *env, int pmp_index,
|
||||||
|
target_ulong tlb_sa, target_ulong tlb_ea)
|
||||||
|
{
|
||||||
|
target_ulong pmp_sa = env->pmp_state.addr[pmp_index].sa;
|
||||||
|
target_ulong pmp_ea = env->pmp_state.addr[pmp_index].ea;
|
||||||
|
|
||||||
|
if (pmp_sa >= tlb_sa && pmp_ea <= tlb_ea) {
|
||||||
|
return pmp_ea - pmp_sa + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pmp_sa >= tlb_sa && pmp_sa <= tlb_ea && pmp_ea >= tlb_ea) {
|
||||||
|
return tlb_ea - pmp_sa + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pmp_ea <= tlb_ea && pmp_ea >= tlb_sa && pmp_sa <= tlb_sa) {
|
||||||
|
return pmp_ea - tlb_sa + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check is there a PMP entry which range covers this page. If so,
|
||||||
|
* try to find the minimum granularity for the TLB size.
|
||||||
|
*/
|
||||||
|
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
|
||||||
|
target_ulong *tlb_size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
target_ulong val;
|
||||||
|
target_ulong tlb_ea = (tlb_sa + TARGET_PAGE_SIZE - 1);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_RISCV_PMPS; i++) {
|
||||||
|
val = pmp_get_tlb_size(env, i, tlb_sa, tlb_ea);
|
||||||
|
if (val) {
|
||||||
|
if (*tlb_size == 0 || *tlb_size > val) {
|
||||||
|
*tlb_size = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*tlb_size != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -60,5 +60,7 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
|
||||||
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
|
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
|
||||||
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
|
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
|
||||||
target_ulong size, pmp_priv_t priv, target_ulong mode);
|
target_ulong size, pmp_priv_t priv, target_ulong mode);
|
||||||
|
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
|
||||||
|
target_ulong *tlb_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue