102f3effdSLu Baolu /* SPDX-License-Identifier: GPL-2.0 */
202f3effdSLu Baolu /*
302f3effdSLu Baolu * pasid.h - PASID idr, table and entry header
402f3effdSLu Baolu *
502f3effdSLu Baolu * Copyright (C) 2018 Intel Corporation
602f3effdSLu Baolu *
702f3effdSLu Baolu * Author: Lu Baolu <baolu.lu@linux.intel.com>
802f3effdSLu Baolu */
902f3effdSLu Baolu
1002f3effdSLu Baolu #ifndef __INTEL_PASID_H
1102f3effdSLu Baolu #define __INTEL_PASID_H
1202f3effdSLu Baolu
1302f3effdSLu Baolu #define PASID_MAX 0x100000
1402f3effdSLu Baolu #define PASID_PTE_MASK 0x3F
1502f3effdSLu Baolu #define PASID_PTE_PRESENT 1
1602f3effdSLu Baolu #define PASID_PTE_FPD 2
1702f3effdSLu Baolu #define PDE_PFN_MASK PAGE_MASK
1802f3effdSLu Baolu #define PASID_PDE_SHIFT 6
1902f3effdSLu Baolu #define MAX_NR_PASID_BITS 20
2002f3effdSLu Baolu #define PASID_TBL_ENTRIES BIT(PASID_PDE_SHIFT)
2102f3effdSLu Baolu
2202f3effdSLu Baolu #define is_pasid_enabled(entry) (((entry)->lo >> 3) & 0x1)
2302f3effdSLu Baolu #define get_pasid_dir_size(entry) (1 << ((((entry)->lo >> 9) & 0x7) + 7))
2402f3effdSLu Baolu
2502f3effdSLu Baolu /* Virtual command interface for enlightened pasid management. */
2602f3effdSLu Baolu #define VCMD_CMD_ALLOC 0x1
2702f3effdSLu Baolu #define VCMD_CMD_FREE 0x2
2802f3effdSLu Baolu #define VCMD_VRSP_IP 0x1
294d99efb2SLu Baolu #define VCMD_VRSP_SC(e) (((e) & 0xff) >> 1)
3002f3effdSLu Baolu #define VCMD_VRSP_SC_SUCCESS 0
314d99efb2SLu Baolu #define VCMD_VRSP_SC_NO_PASID_AVAIL 16
324d99efb2SLu Baolu #define VCMD_VRSP_SC_INVALID_PASID 16
334d99efb2SLu Baolu #define VCMD_VRSP_RESULT_PASID(e) (((e) >> 16) & 0xfffff)
344d99efb2SLu Baolu #define VCMD_CMD_OPERAND(e) ((e) << 16)
3502f3effdSLu Baolu /*
3602f3effdSLu Baolu * Domain ID reserved for pasid entries programmed for first-level
3702f3effdSLu Baolu * only and pass-through transfer modes.
3802f3effdSLu Baolu */
3902f3effdSLu Baolu #define FLPT_DEFAULT_DID 1
40*98f7b0dbSLu Baolu #define NUM_RESERVED_DID 2
4102f3effdSLu Baolu
4202f3effdSLu Baolu #define PASID_FLAG_NESTED BIT(1)
436c00612dSLu Baolu #define PASID_FLAG_PAGE_SNOOP BIT(2)
4402f3effdSLu Baolu
4502f3effdSLu Baolu /*
4602f3effdSLu Baolu * The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first-
4702f3effdSLu Baolu * level translation, otherwise, 4-level paging will be used.
4802f3effdSLu Baolu */
4902f3effdSLu Baolu #define PASID_FLAG_FL5LP BIT(1)
5002f3effdSLu Baolu
5102f3effdSLu Baolu struct pasid_dir_entry {
5202f3effdSLu Baolu u64 val;
5302f3effdSLu Baolu };
5402f3effdSLu Baolu
5502f3effdSLu Baolu struct pasid_entry {
5602f3effdSLu Baolu u64 val[8];
5702f3effdSLu Baolu };
5802f3effdSLu Baolu
5902f3effdSLu Baolu #define PASID_ENTRY_PGTT_FL_ONLY (1)
6002f3effdSLu Baolu #define PASID_ENTRY_PGTT_SL_ONLY (2)
6102f3effdSLu Baolu #define PASID_ENTRY_PGTT_NESTED (3)
6202f3effdSLu Baolu #define PASID_ENTRY_PGTT_PT (4)
6302f3effdSLu Baolu
6402f3effdSLu Baolu /* The representative of a PASID table */
6502f3effdSLu Baolu struct pasid_table {
6602f3effdSLu Baolu void *table; /* pasid table pointer */
6702f3effdSLu Baolu int order; /* page order of pasid table */
68c7b6bac9SFenghua Yu u32 max_pasid; /* max pasid */
6902f3effdSLu Baolu };
7002f3effdSLu Baolu
7102f3effdSLu Baolu /* Get PRESENT bit of a PASID directory entry. */
pasid_pde_is_present(struct pasid_dir_entry * pde)7202f3effdSLu Baolu static inline bool pasid_pde_is_present(struct pasid_dir_entry *pde)
7302f3effdSLu Baolu {
7402f3effdSLu Baolu return READ_ONCE(pde->val) & PASID_PTE_PRESENT;
7502f3effdSLu Baolu }
7602f3effdSLu Baolu
7702f3effdSLu Baolu /* Get PASID table from a PASID directory entry. */
7802f3effdSLu Baolu static inline struct pasid_entry *
get_pasid_table_from_pde(struct pasid_dir_entry * pde)7902f3effdSLu Baolu get_pasid_table_from_pde(struct pasid_dir_entry *pde)
8002f3effdSLu Baolu {
8102f3effdSLu Baolu if (!pasid_pde_is_present(pde))
8202f3effdSLu Baolu return NULL;
8302f3effdSLu Baolu
8402f3effdSLu Baolu return phys_to_virt(READ_ONCE(pde->val) & PDE_PFN_MASK);
8502f3effdSLu Baolu }
8602f3effdSLu Baolu
8702f3effdSLu Baolu /* Get PRESENT bit of a PASID table entry. */
pasid_pte_is_present(struct pasid_entry * pte)8802f3effdSLu Baolu static inline bool pasid_pte_is_present(struct pasid_entry *pte)
8902f3effdSLu Baolu {
9002f3effdSLu Baolu return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
9102f3effdSLu Baolu }
9202f3effdSLu Baolu
938798d364SLiu Yi L /* Get PGTT field of a PASID table entry */
pasid_pte_get_pgtt(struct pasid_entry * pte)948798d364SLiu Yi L static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
958798d364SLiu Yi L {
968798d364SLiu Yi L return (u16)((READ_ONCE(pte->val[0]) >> 6) & 0x7);
978798d364SLiu Yi L }
988798d364SLiu Yi L
99c7b6bac9SFenghua Yu extern unsigned int intel_pasid_max_id;
10002f3effdSLu Baolu int intel_pasid_alloc_table(struct device *dev);
10102f3effdSLu Baolu void intel_pasid_free_table(struct device *dev);
10202f3effdSLu Baolu struct pasid_table *intel_pasid_get_table(struct device *dev);
10302f3effdSLu Baolu int intel_pasid_setup_first_level(struct intel_iommu *iommu,
10402f3effdSLu Baolu struct device *dev, pgd_t *pgd,
105c7b6bac9SFenghua Yu u32 pasid, u16 did, int flags);
10602f3effdSLu Baolu int intel_pasid_setup_second_level(struct intel_iommu *iommu,
10702f3effdSLu Baolu struct dmar_domain *domain,
108c7b6bac9SFenghua Yu struct device *dev, u32 pasid);
10902f3effdSLu Baolu int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
11002f3effdSLu Baolu struct dmar_domain *domain,
111c7b6bac9SFenghua Yu struct device *dev, u32 pasid);
11202f3effdSLu Baolu void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
113c7b6bac9SFenghua Yu struct device *dev, u32 pasid,
11402f3effdSLu Baolu bool fault_ignore);
115c7b6bac9SFenghua Yu int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid);
116c7b6bac9SFenghua Yu void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid);
117fc0051cbSLu Baolu void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
118fc0051cbSLu Baolu struct device *dev, u32 pasid);
11902f3effdSLu Baolu #endif /* __INTEL_PASID_H */
120