162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * pasid.h - PASID idr, table and entry header 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2018 Intel Corporation 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Lu Baolu <baolu.lu@linux.intel.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifndef __INTEL_PASID_H 1162306a36Sopenharmony_ci#define __INTEL_PASID_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define PASID_MAX 0x100000 1462306a36Sopenharmony_ci#define PASID_PTE_MASK 0x3F 1562306a36Sopenharmony_ci#define PASID_PTE_PRESENT 1 1662306a36Sopenharmony_ci#define PASID_PTE_FPD 2 1762306a36Sopenharmony_ci#define PDE_PFN_MASK PAGE_MASK 1862306a36Sopenharmony_ci#define PASID_PDE_SHIFT 6 1962306a36Sopenharmony_ci#define MAX_NR_PASID_BITS 20 2062306a36Sopenharmony_ci#define PASID_TBL_ENTRIES BIT(PASID_PDE_SHIFT) 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define is_pasid_enabled(entry) (((entry)->lo >> 3) & 0x1) 2362306a36Sopenharmony_ci#define get_pasid_dir_size(entry) (1 << ((((entry)->lo >> 9) & 0x7) + 7)) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Virtual command interface for enlightened pasid management. */ 2662306a36Sopenharmony_ci#define VCMD_CMD_ALLOC 0x1 2762306a36Sopenharmony_ci#define VCMD_CMD_FREE 0x2 2862306a36Sopenharmony_ci#define VCMD_VRSP_IP 0x1 2962306a36Sopenharmony_ci#define VCMD_VRSP_SC(e) (((e) & 0xff) >> 1) 3062306a36Sopenharmony_ci#define VCMD_VRSP_SC_SUCCESS 0 3162306a36Sopenharmony_ci#define VCMD_VRSP_SC_NO_PASID_AVAIL 16 3262306a36Sopenharmony_ci#define VCMD_VRSP_SC_INVALID_PASID 16 3362306a36Sopenharmony_ci#define VCMD_VRSP_RESULT_PASID(e) (((e) >> 16) & 0xfffff) 3462306a36Sopenharmony_ci#define VCMD_CMD_OPERAND(e) ((e) << 16) 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * Domain ID reserved for pasid entries programmed for first-level 3762306a36Sopenharmony_ci * only and pass-through transfer modes. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci#define FLPT_DEFAULT_DID 1 4062306a36Sopenharmony_ci#define NUM_RESERVED_DID 2 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define PASID_FLAG_NESTED BIT(1) 4362306a36Sopenharmony_ci#define PASID_FLAG_PAGE_SNOOP BIT(2) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* 4662306a36Sopenharmony_ci * The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first- 4762306a36Sopenharmony_ci * level translation, otherwise, 4-level paging will be used. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ci#define PASID_FLAG_FL5LP BIT(1) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistruct pasid_dir_entry { 5262306a36Sopenharmony_ci u64 val; 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistruct pasid_entry { 5662306a36Sopenharmony_ci u64 val[8]; 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define PASID_ENTRY_PGTT_FL_ONLY (1) 6062306a36Sopenharmony_ci#define PASID_ENTRY_PGTT_SL_ONLY (2) 6162306a36Sopenharmony_ci#define PASID_ENTRY_PGTT_NESTED (3) 6262306a36Sopenharmony_ci#define PASID_ENTRY_PGTT_PT (4) 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* The representative of a PASID table */ 6562306a36Sopenharmony_cistruct pasid_table { 6662306a36Sopenharmony_ci void *table; /* pasid table pointer */ 6762306a36Sopenharmony_ci int order; /* page order of pasid table */ 6862306a36Sopenharmony_ci u32 max_pasid; /* max pasid */ 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* Get PRESENT bit of a PASID directory entry. */ 7262306a36Sopenharmony_cistatic inline bool pasid_pde_is_present(struct pasid_dir_entry *pde) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci return READ_ONCE(pde->val) & PASID_PTE_PRESENT; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* Get PASID table from a PASID directory entry. */ 7862306a36Sopenharmony_cistatic inline struct pasid_entry * 7962306a36Sopenharmony_ciget_pasid_table_from_pde(struct pasid_dir_entry *pde) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci if (!pasid_pde_is_present(pde)) 8262306a36Sopenharmony_ci return NULL; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return phys_to_virt(READ_ONCE(pde->val) & PDE_PFN_MASK); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* Get PRESENT bit of a PASID table entry. */ 8862306a36Sopenharmony_cistatic inline bool pasid_pte_is_present(struct pasid_entry *pte) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT; 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* Get PGTT field of a PASID table entry */ 9462306a36Sopenharmony_cistatic inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci return (u16)((READ_ONCE(pte->val[0]) >> 6) & 0x7); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciextern unsigned int intel_pasid_max_id; 10062306a36Sopenharmony_ciint intel_pasid_alloc_table(struct device *dev); 10162306a36Sopenharmony_civoid intel_pasid_free_table(struct device *dev); 10262306a36Sopenharmony_cistruct pasid_table *intel_pasid_get_table(struct device *dev); 10362306a36Sopenharmony_ciint intel_pasid_setup_first_level(struct intel_iommu *iommu, 10462306a36Sopenharmony_ci struct device *dev, pgd_t *pgd, 10562306a36Sopenharmony_ci u32 pasid, u16 did, int flags); 10662306a36Sopenharmony_ciint intel_pasid_setup_second_level(struct intel_iommu *iommu, 10762306a36Sopenharmony_ci struct dmar_domain *domain, 10862306a36Sopenharmony_ci struct device *dev, u32 pasid); 10962306a36Sopenharmony_ciint intel_pasid_setup_pass_through(struct intel_iommu *iommu, 11062306a36Sopenharmony_ci struct dmar_domain *domain, 11162306a36Sopenharmony_ci struct device *dev, u32 pasid); 11262306a36Sopenharmony_civoid intel_pasid_tear_down_entry(struct intel_iommu *iommu, 11362306a36Sopenharmony_ci struct device *dev, u32 pasid, 11462306a36Sopenharmony_ci bool fault_ignore); 11562306a36Sopenharmony_ciint vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid); 11662306a36Sopenharmony_civoid vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid); 11762306a36Sopenharmony_civoid intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu, 11862306a36Sopenharmony_ci struct device *dev, u32 pasid); 11962306a36Sopenharmony_ci#endif /* __INTEL_PASID_H */ 120