linux-headers/arch/e2k/include/asm/mmu-regs-types-v2.h

162 lines
5.3 KiB
C

/*
* E2K ISET V2-V5 MMU structure and common definitions.
*
* Copyright 2018 (c) MCST, Salavat S. Guiliazov (atic@mcst.ru)
*/
#ifndef _ASM_E2K_MMU_REGS_TYPES_V2_H
#define _ASM_E2K_MMU_REGS_TYPES_V2_H
/* Avoid header dependency loop of probe_entry_t and DTLB_ENTRY_PH_BOUND_V2 */
#ifndef _E2K_TLB_REGS_TYPES_H_
# error Do not include <asm/mmu-regs-types-v2.h> directly, use <asm/tlb_regs_types.h> instead
#endif
/*
* This file contains the functions and defines necessary to modify and
* use the E2K ISET V2-V5 page tables.
* NOTE: E2K has four levels of page tables.
*/
#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <linux/bug.h>
#include <asm/mmu_types.h>
/*
* DTLB entry probe format
*/
#define DTLB_ENTRY_ERROR_MASK_V2 0xbe00000000000000ULL
#define DTLB_ENTRY_PH_BOUND_V2 0x8000000000000000ULL
#define DTLB_ENTRY_ILLEGAL_PAGE_V2 0x4000000000000000ULL
#define DTLB_ENTRY_PAGE_MISS_V2 0x2000000000000000ULL
#define DTLB_ENTRY_PROBE_DISABLED_V2 0x0400000000000000ULL
#define DTLB_ENTRY_RES_BITS_V2 0x0200000000000000ULL
#define DTLB_ENTRY_MISS_LEVEL_MASK_V2 0x1800000000000000ULL
#define DTLB_ENTRY_WR_V2 0x0000000000000002ULL
#define DTLB_ENTRY_NON_EX_U_S_V2 0x0000000000000004ULL
#define DTLB_ENTRY_PWT_V2 0x0000000000000008ULL
#define DTLB_ENTRY_PCD1_V2 0x0000000000000010ULL
#define DTLB_ENTRY_D_V2 0x0000000000000040ULL
#define DTLB_ENTRY_G_V2 0x0000000000000100ULL
#define DTLB_ENTRY_PCD2_V2 0x0000000000000200ULL
#define DTLB_ENTRY_NWA_V2 0x0000000000000400ULL
#define DTLB_ENTRY_PHA_V2 0x000000fffffff000ULL /* phys address */
#define DTLB_ENTRY_VVA_V2 0x0000010000000000ULL /* VVA bit */
#define DTLB_ENTRY_PV_V2 0x0000020000000000ULL
#define DTLB_ENTRY_INT_PR_NON_EX_V2 0x0000040000000000ULL
#define DTLB_ENTRY_INTL_RD_V2 0x0000200000000000ULL
#define DTLB_ENTRY_INTL_WR_V2 0x0000400000000000ULL
#define DTLB_ENTRY_WP_V2 0x0000800000000000ULL
#define DTLB_ENTRY_UC_V2 0x0001000000000000ULL
/* MPT flags for 2/4Mb & 1Gb pages [46:45] */
#define DTLB_ENTRY_MPT_FLAGS_V2 0x0000600000000000ULL
#define DTLB_EP_RES_V2 0x0001ffffffffffffULL
#define DTLB_EP_FAULT_RES_V2 (~DTLB_EP_RES_V2)
/*
* DTLB address probe result format
*/
#define PH_ADDR_AP_RES_V2 0x000000ffffffffffULL /* Physical address */
/* normal result of */
/* AP [39: 0] */
#define DISABLE_AP_RES_V2 DISABLE_EP_RES_V2 /* AP diasble result */
/* [62] */
#define ILLEGAL_PAGE_AP_RES_V2 ILLEGAL_PAGE_EP_RES_V2 /* illegal page */
/* [58] */
/* convert physical address to page frame number for DTLB */
#define PA_TO_DTLB_ENTRY_PHA_V2(phys_addr) \
(((e2k_addr_t)phys_addr) & DTLB_ENTRY_PHA_V2)
/* convert the page frame number from DTLB entry to physical address */
#define DTLB_ENTRY_PHA_TO_PA_V2(dtlb_entry) \
((e2k_addr_t)(dtlb_entry) & DTLB_ENTRY_PHA_V2)
static inline probe_entry_t
covert_uni_dtlb_flags_to_dtlb_val_v2(const uni_dtlb_t uni_flags)
{
probe_entry_t dtlb_flags = 0;
if (uni_flags & UNI_PAGE_WRITE)
dtlb_flags |= (DTLB_ENTRY_WR_V2);
if (uni_flags & UNI_PAGE_PRIV)
dtlb_flags |= (DTLB_ENTRY_PV_V2);
if (uni_flags & UNI_PAGE_VALID)
dtlb_flags |= (DTLB_ENTRY_VVA_V2);
if (uni_flags & UNI_PAGE_PROTECT)
dtlb_flags |= (DTLB_ENTRY_INT_PR_NON_EX_V2);
if (uni_flags & UNI_PAGE_GLOBAL)
dtlb_flags |= (DTLB_ENTRY_G_V2);
if (uni_flags & UNI_PAGE_DIRTY)
dtlb_flags |= (DTLB_ENTRY_D_V2);
if (uni_flags & UNI_PAGE_NWA)
dtlb_flags |= (DTLB_ENTRY_NWA_V2);
if (uni_flags & UNI_PAGE_MEM_TYPE)
dtlb_flags |= (DTLB_ENTRY_PCD1_V2 | DTLB_ENTRY_PCD2_V2 |
DTLB_ENTRY_PWT_V2);
if (uni_flags & UNI_PAGE_NON_EX)
dtlb_flags |= (DTLB_ENTRY_NON_EX_U_S_V2);
if (uni_flags & UNI_PAGE_PFN)
dtlb_flags |= (DTLB_ENTRY_PHA_V2);
if (uni_flags & UNI_PAGE_MEM_TYPE_MA)
dtlb_flags |= (DTLB_ENTRY_PCD1_V2 | DTLB_ENTRY_PCD2_V2 |
DTLB_ENTRY_PWT_V2);
if (uni_flags & UNI_PAGE_WRITE_INT)
dtlb_flags |= (DTLB_ENTRY_WP_V2);
if (uni_flags & UNI_PAGE_INTL_RD)
dtlb_flags |= (DTLB_ENTRY_INTL_RD_V2);
if (uni_flags & UNI_PAGE_INTL_WR)
dtlb_flags |= (DTLB_ENTRY_INTL_WR_V2);
if (uni_flags & UNI_DTLB_EP_RES)
dtlb_flags |= (DTLB_EP_RES_V2);
if (uni_flags & UNI_DTLB_PH_ADDR_AP_RES)
dtlb_flags |= (PH_ADDR_AP_RES_V2);
if (uni_flags & UNI_DTLB_ERROR_MASK)
dtlb_flags |= (DTLB_ENTRY_ERROR_MASK_V2);
if (uni_flags & UNI_DTLB_MISS_LEVEL)
dtlb_flags |= (DTLB_ENTRY_MISS_LEVEL_MASK_V2);
if (uni_flags & UNI_DTLB_SUCCESSFUL)
dtlb_flags |= (DTLB_ENTRY_PROBE_DISABLED_V2);
if (uni_flags & UNI_DTLB_RES_BITS)
dtlb_flags |= (DTLB_ENTRY_RES_BITS_V2);
BUILD_BUG_ON(dtlb_flags == 0);
return dtlb_flags;
}
static inline probe_entry_t
fill_dtlb_val_v2_flags(const uni_dtlb_t uni_flags)
{
return covert_uni_dtlb_flags_to_dtlb_val_v2(uni_flags);
}
static inline probe_entry_t
get_dtlb_val_v2_flags(probe_entry_t dtlb_val, const uni_dtlb_t uni_flags)
{
return dtlb_val & covert_uni_dtlb_flags_to_dtlb_val_v2(uni_flags);
}
static inline bool
test_dtlb_val_v2_flags(probe_entry_t dtlb_val, const uni_dtlb_t uni_flags)
{
return get_dtlb_val_v2_flags(dtlb_val, uni_flags) != 0;
}
static inline probe_entry_t
set_dtlb_val_v2_flags(probe_entry_t dtlb_val, const uni_dtlb_t uni_flags)
{
return dtlb_val | covert_uni_dtlb_flags_to_dtlb_val_v2(uni_flags);
}
static inline probe_entry_t
clear_dtlb_val_v2_flags(probe_entry_t dtlb_val, const uni_dtlb_t uni_flags)
{
return dtlb_val & ~covert_uni_dtlb_flags_to_dtlb_val_v2(uni_flags);
}
#endif /* ! __ASSEMBLY__ */
#endif /* ! _ASM_E2K_MMU_REGS_TYPES_V2_H */