QEMU main repository: Please see https://www.qemu.org/docs/master/devel/submitting-a-patch.html for how to submit changes to QEMU. Pull Requests are ignored. Please only use release tarballs from the QEMU website. http://www.qemu.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

103 lines
2.7 KiB

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* LoongArch CPU parameters for QEMU.
*
* Copyright (c) 2025 Loongson Technology Corporation Limited
*/
#ifndef LOONGARCH_CPU_MMU_H
#define LOONGARCH_CPU_MMU_H
typedef enum TLBRet {
TLBRET_MATCH,
TLBRET_BADADDR,
TLBRET_NOMATCH,
TLBRET_INVALID,
TLBRET_DIRTY,
TLBRET_RI,
TLBRET_XI,
TLBRET_PE,
} TLBRet;
typedef struct MMUContext {
vaddr addr;
uint64_t pte;
hwaddr physical;
int ps; /* page size shift */
int prot;
int tlb_index;
int mmu_index;
uint64_t pte_buddy[2];
} MMUContext;
static inline bool cpu_has_ptw(CPULoongArchState *env)
{
return !!FIELD_EX64(env->CSR_PWCH, CSR_PWCH, HPTW_EN);
}
static inline bool pte_present(CPULoongArchState *env, uint64_t entry)
{
uint8_t present;
if (cpu_has_ptw(env)) {
present = FIELD_EX64(entry, TLBENTRY, P);
} else {
present = FIELD_EX64(entry, TLBENTRY, V);
}
return !!present;
}
static inline bool pte_write(CPULoongArchState *env, uint64_t entry)
{
uint8_t writable;
if (cpu_has_ptw(env)) {
writable = FIELD_EX64(entry, TLBENTRY, W);
} else {
writable = FIELD_EX64(entry, TLBENTRY, D);
}
return !!writable;
}
/*
* The folloing functions should be called with PTW enable checked
* With hardware PTW enabled
* Bit D will be set by hardware with write access
* Bit A will be set by hardware with read/intruction fetch access
*/
static inline uint64_t pte_mkaccess(uint64_t entry)
{
return FIELD_DP64(entry, TLBENTRY, V, 1);
}
static inline uint64_t pte_mkdirty(uint64_t entry)
{
return FIELD_DP64(entry, TLBENTRY, D, 1);
}
static inline bool pte_access(uint64_t entry)
{
return !!FIELD_EX64(entry, TLBENTRY, V);
}
static inline bool pte_dirty(uint64_t entry)
{
return !!FIELD_EX64(entry, TLBENTRY, D);
}
bool check_ps(CPULoongArchState *ent, uint8_t ps);
TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context,
MMUAccessType access_type, int mmu_idx);
TLBRet get_physical_address(CPULoongArchState *env, MMUContext *context,
MMUAccessType access_type, int mmu_idx,
int is_debug);
TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context,
int access_type, int mmu_idx, int debug);
void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
uint64_t *dir_width, unsigned int level);
hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
uint64_t loongarch_palen_mask(CPULoongArchState *env);
#endif /* LOONGARCH_CPU_MMU_H */