2018-07-14 10:46:54 +03:00
/* SPDX-License-Identifier: GPL-2.0 */
/*
* intel - pasid . h - PASID idr , table and entry header
*
* Copyright ( C ) 2018 Intel Corporation
*
* Author : Lu Baolu < baolu . lu @ linux . intel . com >
*/
# ifndef __INTEL_PASID_H
# define __INTEL_PASID_H
2018-12-10 04:59:01 +03:00
# define PASID_RID2PASID 0x0
2018-07-14 10:46:54 +03:00
# define PASID_MIN 0x1
2018-12-10 04:58:56 +03:00
# define PASID_MAX 0x100000
# define PASID_PTE_MASK 0x3F
# define PASID_PTE_PRESENT 1
# define PDE_PFN_MASK PAGE_MASK
# define PASID_PDE_SHIFT 6
2018-12-10 04:59:03 +03:00
# define MAX_NR_PASID_BITS 20
2019-05-25 02:40:16 +03:00
# define PASID_TBL_ENTRIES BIT(PASID_PDE_SHIFT)
# define is_pasid_enabled(entry) (((entry)->lo >> 3) & 0x1)
# define get_pasid_dir_size(entry) (1 << ((((entry)->lo >> 9) & 0x7) + 7))
2018-07-14 10:46:54 +03:00
2018-12-10 04:58:59 +03:00
/*
* Domain ID reserved for pasid entries programmed for first - level
* only and pass - through transfer modes .
*/
# define FLPT_DEFAULT_DID 1
2018-12-10 04:59:04 +03:00
/*
* The SUPERVISOR_MODE flag indicates a first level translation which
* can be used for access to kernel addresses . It is valid only for
* access to the kernel ' s static 1 : 1 mapping of physical memory — not
* to vmalloc or even module mappings .
*/
# define PASID_FLAG_SUPERVISOR_MODE BIT(0)
2018-12-10 04:58:56 +03:00
struct pasid_dir_entry {
2018-07-14 10:46:59 +03:00
u64 val ;
} ;
2018-12-10 04:58:56 +03:00
struct pasid_entry {
u64 val [ 8 ] ;
} ;
2018-07-14 10:46:59 +03:00
/* The representative of a PASID table */
struct pasid_table {
void * table ; /* pasid table pointer */
int order ; /* page order of pasid table */
int max_pasid ; /* max pasid */
struct list_head dev ; /* device list */
} ;
2019-05-25 02:40:16 +03:00
/* Get PRESENT bit of a PASID directory entry. */
static inline bool pasid_pde_is_present ( struct pasid_dir_entry * pde )
{
return READ_ONCE ( pde - > val ) & PASID_PTE_PRESENT ;
}
/* Get PASID table from a PASID directory entry. */
static inline struct pasid_entry *
get_pasid_table_from_pde ( struct pasid_dir_entry * pde )
{
if ( ! pasid_pde_is_present ( pde ) )
return NULL ;
return phys_to_virt ( READ_ONCE ( pde - > val ) & PDE_PFN_MASK ) ;
}
/* Get PRESENT bit of a PASID table entry. */
static inline bool pasid_pte_is_present ( struct pasid_entry * pte )
{
return READ_ONCE ( pte - > val [ 0 ] ) & PASID_PTE_PRESENT ;
}
2018-07-14 10:46:54 +03:00
extern u32 intel_pasid_max_id ;
int intel_pasid_alloc_id ( void * ptr , int start , int end , gfp_t gfp ) ;
void intel_pasid_free_id ( int pasid ) ;
void * intel_pasid_lookup_id ( int pasid ) ;
2018-07-14 10:46:59 +03:00
int intel_pasid_alloc_table ( struct device * dev ) ;
void intel_pasid_free_table ( struct device * dev ) ;
struct pasid_table * intel_pasid_get_table ( struct device * dev ) ;
int intel_pasid_get_dev_max_id ( struct device * dev ) ;
struct pasid_entry * intel_pasid_get_entry ( struct device * dev , int pasid ) ;
2018-12-10 04:59:04 +03:00
int intel_pasid_setup_first_level ( struct intel_iommu * iommu ,
struct device * dev , pgd_t * pgd ,
int pasid , u16 did , int flags ) ;
2018-12-10 04:59:00 +03:00
int intel_pasid_setup_second_level ( struct intel_iommu * iommu ,
struct dmar_domain * domain ,
struct device * dev , int pasid ) ;
int intel_pasid_setup_pass_through ( struct intel_iommu * iommu ,
struct dmar_domain * domain ,
struct device * dev , int pasid ) ;
void intel_pasid_tear_down_entry ( struct intel_iommu * iommu ,
struct device * dev , int pasid ) ;
2018-07-14 10:46:54 +03:00
# endif /* __INTEL_PASID_H */