mirror of
https://github.com/torvalds/linux.git
synced 2026-06-06 05:27:07 +02:00
Merge ac74075e5d ("Merge tag 'x86_pasid_for_5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip") into android-mainline
Steps on the way to 5.10-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I5570b629e4f548b0b625a9b117516d59f569b122
This commit is contained in:
commit
19f3e0e24a
|
|
@ -30,3 +30,4 @@ x86-specific Documentation
|
|||
usb-legacy-support
|
||||
i386/index
|
||||
x86_64/index
|
||||
sva
|
||||
|
|
|
|||
257
Documentation/x86/sva.rst
Normal file
257
Documentation/x86/sva.rst
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===========================================
|
||||
Shared Virtual Addressing (SVA) with ENQCMD
|
||||
===========================================
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
Shared Virtual Addressing (SVA) allows the processor and device to use the
|
||||
same virtual addresses avoiding the need for software to translate virtual
|
||||
addresses to physical addresses. SVA is what PCIe calls Shared Virtual
|
||||
Memory (SVM).
|
||||
|
||||
In addition to the convenience of using application virtual addresses
|
||||
by the device, it also doesn't require pinning pages for DMA.
|
||||
PCIe Address Translation Services (ATS) along with Page Request Interface
|
||||
(PRI) allow devices to function much the same way as the CPU handling
|
||||
application page-faults. For more information please refer to the PCIe
|
||||
specification Chapter 10: ATS Specification.
|
||||
|
||||
Use of SVA requires IOMMU support in the platform. IOMMU is also
|
||||
required to support the PCIe features ATS and PRI. ATS allows devices
|
||||
to cache translations for virtual addresses. The IOMMU driver uses the
|
||||
mmu_notifier() support to keep the device TLB cache and the CPU cache in
|
||||
sync. When an ATS lookup fails for a virtual address, the device should
|
||||
use the PRI in order to request the virtual address to be paged into the
|
||||
CPU page tables. The device must use ATS again in order the fetch the
|
||||
translation before use.
|
||||
|
||||
Shared Hardware Workqueues
|
||||
==========================
|
||||
|
||||
Unlike Single Root I/O Virtualization (SR-IOV), Scalable IOV (SIOV) permits
|
||||
the use of Shared Work Queues (SWQ) by both applications and Virtual
|
||||
Machines (VM's). This allows better hardware utilization vs. hard
|
||||
partitioning resources that could result in under utilization. In order to
|
||||
allow the hardware to distinguish the context for which work is being
|
||||
executed in the hardware by SWQ interface, SIOV uses Process Address Space
|
||||
ID (PASID), which is a 20-bit number defined by the PCIe SIG.
|
||||
|
||||
PASID value is encoded in all transactions from the device. This allows the
|
||||
IOMMU to track I/O on a per-PASID granularity in addition to using the PCIe
|
||||
Resource Identifier (RID) which is the Bus/Device/Function.
|
||||
|
||||
|
||||
ENQCMD
|
||||
======
|
||||
|
||||
ENQCMD is a new instruction on Intel platforms that atomically submits a
|
||||
work descriptor to a device. The descriptor includes the operation to be
|
||||
performed, virtual addresses of all parameters, virtual address of a completion
|
||||
record, and the PASID (process address space ID) of the current process.
|
||||
|
||||
ENQCMD works with non-posted semantics and carries a status back if the
|
||||
command was accepted by hardware. This allows the submitter to know if the
|
||||
submission needs to be retried or other device specific mechanisms to
|
||||
implement fairness or ensure forward progress should be provided.
|
||||
|
||||
ENQCMD is the glue that ensures applications can directly submit commands
|
||||
to the hardware and also permits hardware to be aware of application context
|
||||
to perform I/O operations via use of PASID.
|
||||
|
||||
Process Address Space Tagging
|
||||
=============================
|
||||
|
||||
A new thread-scoped MSR (IA32_PASID) provides the connection between
|
||||
user processes and the rest of the hardware. When an application first
|
||||
accesses an SVA-capable device, this MSR is initialized with a newly
|
||||
allocated PASID. The driver for the device calls an IOMMU-specific API
|
||||
that sets up the routing for DMA and page-requests.
|
||||
|
||||
For example, the Intel Data Streaming Accelerator (DSA) uses
|
||||
iommu_sva_bind_device(), which will do the following:
|
||||
|
||||
- Allocate the PASID, and program the process page-table (%cr3 register) in the
|
||||
PASID context entries.
|
||||
- Register for mmu_notifier() to track any page-table invalidations to keep
|
||||
the device TLB in sync. For example, when a page-table entry is invalidated,
|
||||
the IOMMU propagates the invalidation to the device TLB. This will force any
|
||||
future access by the device to this virtual address to participate in
|
||||
ATS. If the IOMMU responds with proper response that a page is not
|
||||
present, the device would request the page to be paged in via the PCIe PRI
|
||||
protocol before performing I/O.
|
||||
|
||||
This MSR is managed with the XSAVE feature set as "supervisor state" to
|
||||
ensure the MSR is updated during context switch.
|
||||
|
||||
PASID Management
|
||||
================
|
||||
|
||||
The kernel must allocate a PASID on behalf of each process which will use
|
||||
ENQCMD and program it into the new MSR to communicate the process identity to
|
||||
platform hardware. ENQCMD uses the PASID stored in this MSR to tag requests
|
||||
from this process. When a user submits a work descriptor to a device using the
|
||||
ENQCMD instruction, the PASID field in the descriptor is auto-filled with the
|
||||
value from MSR_IA32_PASID. Requests for DMA from the device are also tagged
|
||||
with the same PASID. The platform IOMMU uses the PASID in the transaction to
|
||||
perform address translation. The IOMMU APIs setup the corresponding PASID
|
||||
entry in IOMMU with the process address used by the CPU (e.g. %cr3 register in
|
||||
x86).
|
||||
|
||||
The MSR must be configured on each logical CPU before any application
|
||||
thread can interact with a device. Threads that belong to the same
|
||||
process share the same page tables, thus the same MSR value.
|
||||
|
||||
PASID is cleared when a process is created. The PASID allocation and MSR
|
||||
programming may occur long after a process and its threads have been created.
|
||||
One thread must call iommu_sva_bind_device() to allocate the PASID for the
|
||||
process. If a thread uses ENQCMD without the MSR first being populated, a #GP
|
||||
will be raised. The kernel will update the PASID MSR with the PASID for all
|
||||
threads in the process. A single process PASID can be used simultaneously
|
||||
with multiple devices since they all share the same address space.
|
||||
|
||||
One thread can call iommu_sva_unbind_device() to free the allocated PASID.
|
||||
The kernel will clear the PASID MSR for all threads belonging to the process.
|
||||
|
||||
New threads inherit the MSR value from the parent.
|
||||
|
||||
Relationships
|
||||
=============
|
||||
|
||||
* Each process has many threads, but only one PASID.
|
||||
* Devices have a limited number (~10's to 1000's) of hardware workqueues.
|
||||
The device driver manages allocating hardware workqueues.
|
||||
* A single mmap() maps a single hardware workqueue as a "portal" and
|
||||
each portal maps down to a single workqueue.
|
||||
* For each device with which a process interacts, there must be
|
||||
one or more mmap()'d portals.
|
||||
* Many threads within a process can share a single portal to access
|
||||
a single device.
|
||||
* Multiple processes can separately mmap() the same portal, in
|
||||
which case they still share one device hardware workqueue.
|
||||
* The single process-wide PASID is used by all threads to interact
|
||||
with all devices. There is not, for instance, a PASID for each
|
||||
thread or each thread<->device pair.
|
||||
|
||||
FAQ
|
||||
===
|
||||
|
||||
* What is SVA/SVM?
|
||||
|
||||
Shared Virtual Addressing (SVA) permits I/O hardware and the processor to
|
||||
work in the same address space, i.e., to share it. Some call it Shared
|
||||
Virtual Memory (SVM), but Linux community wanted to avoid confusing it with
|
||||
POSIX Shared Memory and Secure Virtual Machines which were terms already in
|
||||
circulation.
|
||||
|
||||
* What is a PASID?
|
||||
|
||||
A Process Address Space ID (PASID) is a PCIe-defined Transaction Layer Packet
|
||||
(TLP) prefix. A PASID is a 20-bit number allocated and managed by the OS.
|
||||
PASID is included in all transactions between the platform and the device.
|
||||
|
||||
* How are shared workqueues different?
|
||||
|
||||
Traditionally, in order for userspace applications to interact with hardware,
|
||||
there is a separate hardware instance required per process. For example,
|
||||
consider doorbells as a mechanism of informing hardware about work to process.
|
||||
Each doorbell is required to be spaced 4k (or page-size) apart for process
|
||||
isolation. This requires hardware to provision that space and reserve it in
|
||||
MMIO. This doesn't scale as the number of threads becomes quite large. The
|
||||
hardware also manages the queue depth for Shared Work Queues (SWQ), and
|
||||
consumers don't need to track queue depth. If there is no space to accept
|
||||
a command, the device will return an error indicating retry.
|
||||
|
||||
A user should check Deferrable Memory Write (DMWr) capability on the device
|
||||
and only submits ENQCMD when the device supports it. In the new DMWr PCIe
|
||||
terminology, devices need to support DMWr completer capability. In addition,
|
||||
it requires all switch ports to support DMWr routing and must be enabled by
|
||||
the PCIe subsystem, much like how PCIe atomic operations are managed for
|
||||
instance.
|
||||
|
||||
SWQ allows hardware to provision just a single address in the device. When
|
||||
used with ENQCMD to submit work, the device can distinguish the process
|
||||
submitting the work since it will include the PASID assigned to that
|
||||
process. This helps the device scale to a large number of processes.
|
||||
|
||||
* Is this the same as a user space device driver?
|
||||
|
||||
Communicating with the device via the shared workqueue is much simpler
|
||||
than a full blown user space driver. The kernel driver does all the
|
||||
initialization of the hardware. User space only needs to worry about
|
||||
submitting work and processing completions.
|
||||
|
||||
* Is this the same as SR-IOV?
|
||||
|
||||
Single Root I/O Virtualization (SR-IOV) focuses on providing independent
|
||||
hardware interfaces for virtualizing hardware. Hence, it's required to be
|
||||
almost fully functional interface to software supporting the traditional
|
||||
BARs, space for interrupts via MSI-X, its own register layout.
|
||||
Virtual Functions (VFs) are assisted by the Physical Function (PF)
|
||||
driver.
|
||||
|
||||
Scalable I/O Virtualization builds on the PASID concept to create device
|
||||
instances for virtualization. SIOV requires host software to assist in
|
||||
creating virtual devices; each virtual device is represented by a PASID
|
||||
along with the bus/device/function of the device. This allows device
|
||||
hardware to optimize device resource creation and can grow dynamically on
|
||||
demand. SR-IOV creation and management is very static in nature. Consult
|
||||
references below for more details.
|
||||
|
||||
* Why not just create a virtual function for each app?
|
||||
|
||||
Creating PCIe SR-IOV type Virtual Functions (VF) is expensive. VFs require
|
||||
duplicated hardware for PCI config space and interrupts such as MSI-X.
|
||||
Resources such as interrupts have to be hard partitioned between VFs at
|
||||
creation time, and cannot scale dynamically on demand. The VFs are not
|
||||
completely independent from the Physical Function (PF). Most VFs require
|
||||
some communication and assistance from the PF driver. SIOV, in contrast,
|
||||
creates a software-defined device where all the configuration and control
|
||||
aspects are mediated via the slow path. The work submission and completion
|
||||
happen without any mediation.
|
||||
|
||||
* Does this support virtualization?
|
||||
|
||||
ENQCMD can be used from within a guest VM. In these cases, the VMM helps
|
||||
with setting up a translation table to translate from Guest PASID to Host
|
||||
PASID. Please consult the ENQCMD instruction set reference for more
|
||||
details.
|
||||
|
||||
* Does memory need to be pinned?
|
||||
|
||||
When devices support SVA along with platform hardware such as IOMMU
|
||||
supporting such devices, there is no need to pin memory for DMA purposes.
|
||||
Devices that support SVA also support other PCIe features that remove the
|
||||
pinning requirement for memory.
|
||||
|
||||
Device TLB support - Device requests the IOMMU to lookup an address before
|
||||
use via Address Translation Service (ATS) requests. If the mapping exists
|
||||
but there is no page allocated by the OS, IOMMU hardware returns that no
|
||||
mapping exists.
|
||||
|
||||
Device requests the virtual address to be mapped via Page Request
|
||||
Interface (PRI). Once the OS has successfully completed the mapping, it
|
||||
returns the response back to the device. The device requests again for
|
||||
a translation and continues.
|
||||
|
||||
IOMMU works with the OS in managing consistency of page-tables with the
|
||||
device. When removing pages, it interacts with the device to remove any
|
||||
device TLB entry that might have been cached before removing the mappings from
|
||||
the OS.
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
VT-D:
|
||||
https://01.org/blogs/ashokraj/2018/recent-enhancements-intel-virtualization-technology-directed-i/o-intel-vt-d
|
||||
|
||||
SIOV:
|
||||
https://01.org/blogs/2019/assignable-interfaces-intel-scalable-i/o-virtualization-linux
|
||||
|
||||
ENQCMD in ISE:
|
||||
https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf
|
||||
|
||||
DSA spec:
|
||||
https://software.intel.com/sites/default/files/341204-intel-data-streaming-accelerator-spec.pdf
|
||||
|
|
@ -353,6 +353,7 @@
|
|||
#define X86_FEATURE_CLDEMOTE (16*32+25) /* CLDEMOTE instruction */
|
||||
#define X86_FEATURE_MOVDIRI (16*32+27) /* MOVDIRI instruction */
|
||||
#define X86_FEATURE_MOVDIR64B (16*32+28) /* MOVDIR64B instruction */
|
||||
#define X86_FEATURE_ENQCMD (16*32+29) /* ENQCMD and ENQCMDS instructions */
|
||||
|
||||
/* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
|
||||
#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* MCA overflow recovery support */
|
||||
|
|
|
|||
|
|
@ -56,6 +56,12 @@
|
|||
# define DISABLE_PTI (1 << (X86_FEATURE_PTI & 31))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IOMMU_SUPPORT
|
||||
# define DISABLE_ENQCMD 0
|
||||
#else
|
||||
# define DISABLE_ENQCMD (1 << (X86_FEATURE_ENQCMD & 31))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make sure to add features to the correct mask
|
||||
*/
|
||||
|
|
@ -75,7 +81,8 @@
|
|||
#define DISABLED_MASK13 0
|
||||
#define DISABLED_MASK14 0
|
||||
#define DISABLED_MASK15 0
|
||||
#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP)
|
||||
#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP| \
|
||||
DISABLE_ENQCMD)
|
||||
#define DISABLED_MASK17 0
|
||||
#define DISABLED_MASK18 0
|
||||
#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
|
||||
|
|
|
|||
|
|
@ -62,4 +62,16 @@ extern void switch_fpu_return(void);
|
|||
*/
|
||||
extern int cpu_has_xfeatures(u64 xfeatures_mask, const char **feature_name);
|
||||
|
||||
/*
|
||||
* Tasks that are not using SVA have mm->pasid set to zero to note that they
|
||||
* will not have the valid bit set in MSR_IA32_PASID while they are running.
|
||||
*/
|
||||
#define PASID_DISABLED 0
|
||||
|
||||
#ifdef CONFIG_IOMMU_SUPPORT
|
||||
/* Update current's PASID MSR/state by mm's PASID. */
|
||||
void update_pasid(void);
|
||||
#else
|
||||
static inline void update_pasid(void) { }
|
||||
#endif
|
||||
#endif /* _ASM_X86_FPU_API_H */
|
||||
|
|
|
|||
|
|
@ -583,6 +583,13 @@ static inline void switch_fpu_finish(struct fpu *new_fpu)
|
|||
pkru_val = pk->pkru;
|
||||
}
|
||||
__write_pkru(pkru_val);
|
||||
|
||||
/*
|
||||
* Expensive PASID MSR write will be avoided in update_pasid() because
|
||||
* TIF_NEED_FPU_LOAD was set. And the PASID state won't be updated
|
||||
* unless it's different from mm->pasid to reduce overhead.
|
||||
*/
|
||||
update_pasid();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ enum xfeature {
|
|||
XFEATURE_Hi16_ZMM,
|
||||
XFEATURE_PT_UNIMPLEMENTED_SO_FAR,
|
||||
XFEATURE_PKRU,
|
||||
XFEATURE_RSRVD_COMP_10,
|
||||
XFEATURE_PASID,
|
||||
XFEATURE_RSRVD_COMP_11,
|
||||
XFEATURE_RSRVD_COMP_12,
|
||||
XFEATURE_RSRVD_COMP_13,
|
||||
|
|
@ -134,6 +134,7 @@ enum xfeature {
|
|||
#define XFEATURE_MASK_Hi16_ZMM (1 << XFEATURE_Hi16_ZMM)
|
||||
#define XFEATURE_MASK_PT (1 << XFEATURE_PT_UNIMPLEMENTED_SO_FAR)
|
||||
#define XFEATURE_MASK_PKRU (1 << XFEATURE_PKRU)
|
||||
#define XFEATURE_MASK_PASID (1 << XFEATURE_PASID)
|
||||
#define XFEATURE_MASK_LBR (1 << XFEATURE_LBR)
|
||||
|
||||
#define XFEATURE_MASK_FPSSE (XFEATURE_MASK_FP | XFEATURE_MASK_SSE)
|
||||
|
|
@ -256,6 +257,14 @@ struct arch_lbr_state {
|
|||
struct lbr_entry entries[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* State component 10 is supervisor state used for context-switching the
|
||||
* PASID state.
|
||||
*/
|
||||
struct ia32_pasid_state {
|
||||
u64 pasid;
|
||||
} __packed;
|
||||
|
||||
struct xstate_header {
|
||||
u64 xfeatures;
|
||||
u64 xcomp_bv;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
XFEATURE_MASK_BNDCSR)
|
||||
|
||||
/* All currently supported supervisor features */
|
||||
#define XFEATURE_MASK_SUPERVISOR_SUPPORTED (0)
|
||||
#define XFEATURE_MASK_SUPERVISOR_SUPPORTED (XFEATURE_MASK_PASID)
|
||||
|
||||
/*
|
||||
* A supervisor state component may not always contain valuable information,
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ extern bool phys_mem_access_encrypted(unsigned long phys_addr,
|
|||
|
||||
/**
|
||||
* iosubmit_cmds512 - copy data to single MMIO location, in 512-bit units
|
||||
* @__dst: destination, in MMIO space (must be 512-bit aligned)
|
||||
* @dst: destination, in MMIO space (must be 512-bit aligned)
|
||||
* @src: source
|
||||
* @count: number of 512 bits quantities to submit
|
||||
*
|
||||
|
|
@ -412,25 +412,14 @@ extern bool phys_mem_access_encrypted(unsigned long phys_addr,
|
|||
* Warning: Do not use this helper unless your driver has checked that the CPU
|
||||
* instruction is supported on the platform.
|
||||
*/
|
||||
static inline void iosubmit_cmds512(void __iomem *__dst, const void *src,
|
||||
static inline void iosubmit_cmds512(void __iomem *dst, const void *src,
|
||||
size_t count)
|
||||
{
|
||||
/*
|
||||
* Note that this isn't an "on-stack copy", just definition of "dst"
|
||||
* as a pointer to 64-bytes of stuff that is going to be overwritten.
|
||||
* In the MOVDIR64B case that may be needed as you can use the
|
||||
* MOVDIR64B instruction to copy arbitrary memory around. This trick
|
||||
* lets the compiler know how much gets clobbered.
|
||||
*/
|
||||
volatile struct { char _[64]; } *dst = __dst;
|
||||
const u8 *from = src;
|
||||
const u8 *end = from + count * 64;
|
||||
|
||||
while (from < end) {
|
||||
/* MOVDIR64B [rdx], rax */
|
||||
asm volatile(".byte 0x66, 0x0f, 0x38, 0xf8, 0x02"
|
||||
: "=m" (dst)
|
||||
: "d" (from), "a" (dst));
|
||||
movdir64b(dst, from);
|
||||
from += 64;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -257,6 +257,9 @@
|
|||
#define MSR_IA32_LASTINTFROMIP 0x000001dd
|
||||
#define MSR_IA32_LASTINTTOIP 0x000001de
|
||||
|
||||
#define MSR_IA32_PASID 0x00000d93
|
||||
#define MSR_IA32_PASID_VALID BIT_ULL(31)
|
||||
|
||||
/* DEBUGCTLMSR bits (others vary by model): */
|
||||
#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */
|
||||
#define DEBUGCTLMSR_BTF_SHIFT 1
|
||||
|
|
|
|||
|
|
@ -240,6 +240,70 @@ static inline void serialize(void)
|
|||
asm volatile(".byte 0xf, 0x1, 0xe8" ::: "memory");
|
||||
}
|
||||
|
||||
/* The dst parameter must be 64-bytes aligned */
|
||||
static inline void movdir64b(void *dst, const void *src)
|
||||
{
|
||||
const struct { char _[64]; } *__src = src;
|
||||
struct { char _[64]; } *__dst = dst;
|
||||
|
||||
/*
|
||||
* MOVDIR64B %(rdx), rax.
|
||||
*
|
||||
* Both __src and __dst must be memory constraints in order to tell the
|
||||
* compiler that no other memory accesses should be reordered around
|
||||
* this one.
|
||||
*
|
||||
* Also, both must be supplied as lvalues because this tells
|
||||
* the compiler what the object is (its size) the instruction accesses.
|
||||
* I.e., not the pointers but what they point to, thus the deref'ing '*'.
|
||||
*/
|
||||
asm volatile(".byte 0x66, 0x0f, 0x38, 0xf8, 0x02"
|
||||
: "+m" (*__dst)
|
||||
: "m" (*__src), "a" (__dst), "d" (__src));
|
||||
}
|
||||
|
||||
/**
|
||||
* enqcmds - Enqueue a command in supervisor (CPL0) mode
|
||||
* @dst: destination, in MMIO space (must be 512-bit aligned)
|
||||
* @src: 512 bits memory operand
|
||||
*
|
||||
* The ENQCMDS instruction allows software to write a 512-bit command to
|
||||
* a 512-bit-aligned special MMIO region that supports the instruction.
|
||||
* A return status is loaded into the ZF flag in the RFLAGS register.
|
||||
* ZF = 0 equates to success, and ZF = 1 indicates retry or error.
|
||||
*
|
||||
* This function issues the ENQCMDS instruction to submit data from
|
||||
* kernel space to MMIO space, in a unit of 512 bits. Order of data access
|
||||
* is not guaranteed, nor is a memory barrier performed afterwards. It
|
||||
* returns 0 on success and -EAGAIN on failure.
|
||||
*
|
||||
* Warning: Do not use this helper unless your driver has checked that the
|
||||
* ENQCMDS instruction is supported on the platform and the device accepts
|
||||
* ENQCMDS.
|
||||
*/
|
||||
static inline int enqcmds(void __iomem *dst, const void *src)
|
||||
{
|
||||
const struct { char _[64]; } *__src = src;
|
||||
struct { char _[64]; } *__dst = dst;
|
||||
int zf;
|
||||
|
||||
/*
|
||||
* ENQCMDS %(rdx), rax
|
||||
*
|
||||
* See movdir64b()'s comment on operand specification.
|
||||
*/
|
||||
asm volatile(".byte 0xf3, 0x0f, 0x38, 0xf8, 0x02, 0x66, 0x90"
|
||||
CC_SET(z)
|
||||
: CC_OUT(z) (zf), "+m" (*__dst)
|
||||
: "m" (*__src), "a" (__dst), "d" (__src));
|
||||
|
||||
/* Submission failure is indicated via EFLAGS.ZF=1 */
|
||||
if (zf)
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _ASM_X86_SPECIAL_INSNS_H */
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ static const struct cpuid_dep cpuid_deps[] = {
|
|||
{ X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC },
|
||||
{ X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC },
|
||||
{ X86_FEATURE_AVX512_BF16, X86_FEATURE_AVX512VL },
|
||||
{ X86_FEATURE_ENQCMD, X86_FEATURE_XSAVES },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ static const char *xfeature_names[] =
|
|||
"AVX-512 ZMM_Hi256" ,
|
||||
"Processor Trace (unused)" ,
|
||||
"Protection Keys User registers",
|
||||
"PASID state",
|
||||
"unknown xstate feature" ,
|
||||
};
|
||||
|
||||
|
|
@ -51,6 +52,7 @@ static short xsave_cpuid_features[] __initdata = {
|
|||
X86_FEATURE_AVX512F,
|
||||
X86_FEATURE_INTEL_PT,
|
||||
X86_FEATURE_PKU,
|
||||
X86_FEATURE_ENQCMD,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -318,6 +320,7 @@ static void __init print_xstate_features(void)
|
|||
print_xstate_feature(XFEATURE_MASK_ZMM_Hi256);
|
||||
print_xstate_feature(XFEATURE_MASK_Hi16_ZMM);
|
||||
print_xstate_feature(XFEATURE_MASK_PKRU);
|
||||
print_xstate_feature(XFEATURE_MASK_PASID);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -592,6 +595,7 @@ static void check_xstate_against_struct(int nr)
|
|||
XCHECK_SZ(sz, nr, XFEATURE_ZMM_Hi256, struct avx_512_zmm_uppers_state);
|
||||
XCHECK_SZ(sz, nr, XFEATURE_Hi16_ZMM, struct avx_512_hi16_state);
|
||||
XCHECK_SZ(sz, nr, XFEATURE_PKRU, struct pkru_state);
|
||||
XCHECK_SZ(sz, nr, XFEATURE_PASID, struct ia32_pasid_state);
|
||||
|
||||
/*
|
||||
* Make *SURE* to add any feature numbers in below if
|
||||
|
|
@ -601,7 +605,7 @@ static void check_xstate_against_struct(int nr)
|
|||
if ((nr < XFEATURE_YMM) ||
|
||||
(nr >= XFEATURE_MAX) ||
|
||||
(nr == XFEATURE_PT_UNIMPLEMENTED_SO_FAR) ||
|
||||
((nr >= XFEATURE_RSRVD_COMP_10) && (nr <= XFEATURE_LBR))) {
|
||||
((nr >= XFEATURE_RSRVD_COMP_11) && (nr <= XFEATURE_LBR))) {
|
||||
WARN_ONCE(1, "no structure for xstate: %d\n", nr);
|
||||
XSTATE_WARN_ON(1);
|
||||
}
|
||||
|
|
@ -1398,3 +1402,60 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns,
|
|||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PROC_PID_ARCH_STATUS */
|
||||
|
||||
#ifdef CONFIG_IOMMU_SUPPORT
|
||||
void update_pasid(void)
|
||||
{
|
||||
u64 pasid_state;
|
||||
u32 pasid;
|
||||
|
||||
if (!cpu_feature_enabled(X86_FEATURE_ENQCMD))
|
||||
return;
|
||||
|
||||
if (!current->mm)
|
||||
return;
|
||||
|
||||
pasid = READ_ONCE(current->mm->pasid);
|
||||
/* Set the valid bit in the PASID MSR/state only for valid pasid. */
|
||||
pasid_state = pasid == PASID_DISABLED ?
|
||||
pasid : pasid | MSR_IA32_PASID_VALID;
|
||||
|
||||
/*
|
||||
* No need to hold fregs_lock() since the task's fpstate won't
|
||||
* be changed by others (e.g. ptrace) while the task is being
|
||||
* switched to or is in IPI.
|
||||
*/
|
||||
if (!test_thread_flag(TIF_NEED_FPU_LOAD)) {
|
||||
/* The MSR is active and can be directly updated. */
|
||||
wrmsrl(MSR_IA32_PASID, pasid_state);
|
||||
} else {
|
||||
struct fpu *fpu = ¤t->thread.fpu;
|
||||
struct ia32_pasid_state *ppasid_state;
|
||||
struct xregs_state *xsave;
|
||||
|
||||
/*
|
||||
* The CPU's xstate registers are not currently active. Just
|
||||
* update the PASID state in the memory buffer here. The
|
||||
* PASID MSR will be loaded when returning to user mode.
|
||||
*/
|
||||
xsave = &fpu->state.xsave;
|
||||
xsave->header.xfeatures |= XFEATURE_MASK_PASID;
|
||||
ppasid_state = get_xsave_addr(xsave, XFEATURE_PASID);
|
||||
/*
|
||||
* Since XFEATURE_MASK_PASID is set in xfeatures, ppasid_state
|
||||
* won't be NULL and no need to check its value.
|
||||
*
|
||||
* Only update the task's PASID state when it's different
|
||||
* from the mm's pasid.
|
||||
*/
|
||||
if (ppasid_state->pasid != pasid_state) {
|
||||
/*
|
||||
* Invalid fpregs so that state restoring will pick up
|
||||
* the PASID state.
|
||||
*/
|
||||
__fpu_invalidate_fpregs_state(fpu);
|
||||
ppasid_state->pasid = pasid_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IOMMU_SUPPORT */
|
||||
|
|
|
|||
|
|
@ -207,11 +207,11 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *s
|
|||
})
|
||||
|
||||
/* GPUVM API */
|
||||
int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, unsigned int pasid,
|
||||
int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, u32 pasid,
|
||||
void **vm, void **process_info,
|
||||
struct dma_fence **ef);
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
|
||||
struct file *filp, unsigned int pasid,
|
||||
struct file *filp, u32 pasid,
|
||||
void **vm, void **process_info,
|
||||
struct dma_fence **ef);
|
||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
|||
unlock_srbm(kgd);
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
|||
unlock_srbm(kgd);
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
|||
unlock_srbm(kgd);
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ void kgd_gfx_v9_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
|||
unlock_srbm(kgd);
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ void kgd_gfx_v9_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
|||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases);
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
unsigned int vmid);
|
||||
int kgd_gfx_v9_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id);
|
||||
int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
|
|
|
|||
|
|
@ -992,7 +992,7 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, unsigned int pasid,
|
||||
int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, u32 pasid,
|
||||
void **vm, void **process_info,
|
||||
struct dma_fence **ef)
|
||||
{
|
||||
|
|
@ -1028,7 +1028,7 @@ int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, unsigned int pasi
|
|||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
|
||||
struct file *filp, unsigned int pasid,
|
||||
struct file *filp, u32 pasid,
|
||||
void **vm, void **process_info,
|
||||
struct dma_fence **ef)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static DEFINE_IDA(amdgpu_pasid_ida);
|
|||
/* Helper to free pasid from a fence callback */
|
||||
struct amdgpu_pasid_cb {
|
||||
struct dma_fence_cb cb;
|
||||
unsigned int pasid;
|
||||
u32 pasid;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -79,7 +79,7 @@ int amdgpu_pasid_alloc(unsigned int bits)
|
|||
* amdgpu_pasid_free - Free a PASID
|
||||
* @pasid: PASID to free
|
||||
*/
|
||||
void amdgpu_pasid_free(unsigned int pasid)
|
||||
void amdgpu_pasid_free(u32 pasid)
|
||||
{
|
||||
trace_amdgpu_pasid_freed(pasid);
|
||||
ida_simple_remove(&amdgpu_pasid_ida, pasid);
|
||||
|
|
@ -105,7 +105,7 @@ static void amdgpu_pasid_free_cb(struct dma_fence *fence,
|
|||
* Free the pasid only after all the fences in resv are signaled.
|
||||
*/
|
||||
void amdgpu_pasid_free_delayed(struct dma_resv *resv,
|
||||
unsigned int pasid)
|
||||
u32 pasid)
|
||||
{
|
||||
struct dma_fence *fence, **fences;
|
||||
struct amdgpu_pasid_cb *cb;
|
||||
|
|
|
|||
|
|
@ -71,9 +71,9 @@ struct amdgpu_vmid_mgr {
|
|||
};
|
||||
|
||||
int amdgpu_pasid_alloc(unsigned int bits);
|
||||
void amdgpu_pasid_free(unsigned int pasid);
|
||||
void amdgpu_pasid_free(u32 pasid);
|
||||
void amdgpu_pasid_free_delayed(struct dma_resv *resv,
|
||||
unsigned int pasid);
|
||||
u32 pasid);
|
||||
|
||||
bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
|
||||
struct amdgpu_vmid *id);
|
||||
|
|
|
|||
|
|
@ -1084,7 +1084,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
|
|||
struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
|
||||
struct amdgpu_bo_list *list;
|
||||
struct amdgpu_bo *pd;
|
||||
unsigned int pasid;
|
||||
u32 pasid;
|
||||
int handle;
|
||||
|
||||
if (!fpriv)
|
||||
|
|
|
|||
|
|
@ -2785,7 +2785,7 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
|
|||
* 0 for success, error for failure.
|
||||
*/
|
||||
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
int vm_context, unsigned int pasid)
|
||||
int vm_context, u32 pasid)
|
||||
{
|
||||
struct amdgpu_bo_param bp;
|
||||
struct amdgpu_bo *root;
|
||||
|
|
@ -2956,7 +2956,7 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
|
|||
* 0 for success, -errno for errors.
|
||||
*/
|
||||
int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
unsigned int pasid)
|
||||
u32 pasid)
|
||||
{
|
||||
bool pte_support_ats = (adev->asic_type == CHIP_RAVEN);
|
||||
int r;
|
||||
|
|
@ -3254,7 +3254,7 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|||
* @pasid: PASID identifier for VM
|
||||
* @task_info: task_info to fill.
|
||||
*/
|
||||
void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,
|
||||
void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid,
|
||||
struct amdgpu_task_info *task_info)
|
||||
{
|
||||
struct amdgpu_vm *vm;
|
||||
|
|
@ -3298,7 +3298,7 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
|
|||
* Try to gracefully handle a VM fault. Return true if the fault was handled and
|
||||
* shouldn't be reported any more.
|
||||
*/
|
||||
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, unsigned int pasid,
|
||||
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
uint64_t addr)
|
||||
{
|
||||
struct amdgpu_bo *root;
|
||||
|
|
|
|||
|
|
@ -372,8 +372,8 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
|
|||
|
||||
long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
|
||||
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
int vm_context, unsigned int pasid);
|
||||
int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned int pasid);
|
||||
int vm_context, u32 pasid);
|
||||
int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid);
|
||||
void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
|
||||
void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
|
||||
void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
|
||||
|
|
@ -430,9 +430,9 @@ bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
|
|||
struct amdgpu_job *job);
|
||||
void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,
|
||||
void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid,
|
||||
struct amdgpu_task_info *task_info);
|
||||
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, unsigned int pasid,
|
||||
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
uint64_t addr);
|
||||
|
||||
void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev,
|
|||
(const struct cik_ih_ring_entry *)ih_ring_entry;
|
||||
uint32_t context_id = ihre->data & 0xfffffff;
|
||||
unsigned int vmid = (ihre->ring_id & 0x0000ff00) >> 8;
|
||||
unsigned int pasid = (ihre->ring_id & 0xffff0000) >> 16;
|
||||
u32 pasid = (ihre->ring_id & 0xffff0000) >> 16;
|
||||
|
||||
if (pasid == 0)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ static void dbgdev_address_watch_disable_nodiq(struct kfd_dev *dev)
|
|||
}
|
||||
|
||||
static int dbgdev_diq_submit_ib(struct kfd_dbgdev *dbgdev,
|
||||
unsigned int pasid, uint64_t vmid0_address,
|
||||
u32 pasid, uint64_t vmid0_address,
|
||||
uint32_t *packet_buff, size_t size_in_bytes)
|
||||
{
|
||||
struct pm4__release_mem *rm_packet;
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ struct kfd_dbgdev {
|
|||
};
|
||||
|
||||
struct kfd_dbgmgr {
|
||||
unsigned int pasid;
|
||||
u32 pasid;
|
||||
struct kfd_dev *dev;
|
||||
struct kfd_dbgdev *dbgdev;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#define CIK_HPD_EOP_BYTES (1U << CIK_HPD_EOP_BYTES_LOG2)
|
||||
|
||||
static int set_pasid_vmid_mapping(struct device_queue_manager *dqm,
|
||||
unsigned int pasid, unsigned int vmid);
|
||||
u32 pasid, unsigned int vmid);
|
||||
|
||||
static int execute_queues_cpsch(struct device_queue_manager *dqm,
|
||||
enum kfd_unmap_queues_filter filter,
|
||||
|
|
@ -948,7 +948,7 @@ static int unregister_process(struct device_queue_manager *dqm,
|
|||
}
|
||||
|
||||
static int
|
||||
set_pasid_vmid_mapping(struct device_queue_manager *dqm, unsigned int pasid,
|
||||
set_pasid_vmid_mapping(struct device_queue_manager *dqm, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
return dqm->dev->kfd2kgd->set_pasid_vmid_mapping(
|
||||
|
|
@ -1981,8 +1981,7 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm)
|
|||
kfree(dqm);
|
||||
}
|
||||
|
||||
int kfd_process_vm_fault(struct device_queue_manager *dqm,
|
||||
unsigned int pasid)
|
||||
int kfd_process_vm_fault(struct device_queue_manager *dqm, u32 pasid)
|
||||
{
|
||||
struct kfd_process_device *pdd;
|
||||
struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
|
||||
|
|
|
|||
|
|
@ -460,7 +460,7 @@ static void set_event_from_interrupt(struct kfd_process *p,
|
|||
}
|
||||
}
|
||||
|
||||
void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id,
|
||||
void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
|
||||
uint32_t valid_id_bits)
|
||||
{
|
||||
struct kfd_event *ev = NULL;
|
||||
|
|
@ -872,7 +872,7 @@ static void lookup_events_by_type_and_signal(struct kfd_process *p,
|
|||
}
|
||||
|
||||
#ifdef KFD_SUPPORT_IOMMU_V2
|
||||
void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
|
||||
void kfd_signal_iommu_event(struct kfd_dev *dev, u32 pasid,
|
||||
unsigned long address, bool is_write_requested,
|
||||
bool is_execute_requested)
|
||||
{
|
||||
|
|
@ -950,7 +950,7 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
|
|||
}
|
||||
#endif /* KFD_SUPPORT_IOMMU_V2 */
|
||||
|
||||
void kfd_signal_hw_exception_event(unsigned int pasid)
|
||||
void kfd_signal_hw_exception_event(u32 pasid)
|
||||
{
|
||||
/*
|
||||
* Because we are called from arbitrary context (workqueue) as opposed
|
||||
|
|
@ -971,7 +971,7 @@ void kfd_signal_hw_exception_event(unsigned int pasid)
|
|||
kfd_unref_process(p);
|
||||
}
|
||||
|
||||
void kfd_signal_vm_fault_event(struct kfd_dev *dev, unsigned int pasid,
|
||||
void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid,
|
||||
struct kfd_vm_fault_info *info)
|
||||
{
|
||||
struct kfd_event *ev;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ struct kfd_event {
|
|||
#define KFD_EVENT_TYPE_DEBUG 5
|
||||
#define KFD_EVENT_TYPE_MEMORY 8
|
||||
|
||||
extern void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id,
|
||||
uint32_t valid_id_bits);
|
||||
extern void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
|
||||
uint32_t valid_id_bits);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ void kfd_iommu_unbind_process(struct kfd_process *p)
|
|||
}
|
||||
|
||||
/* Callback for process shutdown invoked by the IOMMU driver */
|
||||
static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, int pasid)
|
||||
static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, u32 pasid)
|
||||
{
|
||||
struct kfd_dev *dev = kfd_device_by_pci_dev(pdev);
|
||||
struct kfd_process *p;
|
||||
|
|
@ -185,8 +185,8 @@ static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, int pasid)
|
|||
}
|
||||
|
||||
/* This function called by IOMMU driver on PPR failure */
|
||||
static int iommu_invalid_ppr_cb(struct pci_dev *pdev, int pasid,
|
||||
unsigned long address, u16 flags)
|
||||
static int iommu_invalid_ppr_cb(struct pci_dev *pdev, u32 pasid,
|
||||
unsigned long address, u16 flags)
|
||||
{
|
||||
struct kfd_dev *dev;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ unsigned int kfd_get_pasid_limit(void)
|
|||
return 1U << pasid_bits;
|
||||
}
|
||||
|
||||
unsigned int kfd_pasid_alloc(void)
|
||||
u32 kfd_pasid_alloc(void)
|
||||
{
|
||||
int r = amdgpu_pasid_alloc(pasid_bits);
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ unsigned int kfd_pasid_alloc(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void kfd_pasid_free(unsigned int pasid)
|
||||
void kfd_pasid_free(u32 pasid)
|
||||
{
|
||||
amdgpu_pasid_free(pasid);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -723,7 +723,7 @@ struct kfd_process {
|
|||
/* We want to receive a notification when the mm_struct is destroyed */
|
||||
struct mmu_notifier mmu_notifier;
|
||||
|
||||
uint16_t pasid;
|
||||
u32 pasid;
|
||||
unsigned int doorbell_index;
|
||||
|
||||
/*
|
||||
|
|
@ -800,7 +800,7 @@ int kfd_process_create_wq(void);
|
|||
void kfd_process_destroy_wq(void);
|
||||
struct kfd_process *kfd_create_process(struct file *filep);
|
||||
struct kfd_process *kfd_get_process(const struct task_struct *);
|
||||
struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid);
|
||||
struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid);
|
||||
struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm);
|
||||
void kfd_unref_process(struct kfd_process *p);
|
||||
int kfd_process_evict_queues(struct kfd_process *p);
|
||||
|
|
@ -841,8 +841,8 @@ int kfd_pasid_init(void);
|
|||
void kfd_pasid_exit(void);
|
||||
bool kfd_set_pasid_limit(unsigned int new_limit);
|
||||
unsigned int kfd_get_pasid_limit(void);
|
||||
unsigned int kfd_pasid_alloc(void);
|
||||
void kfd_pasid_free(unsigned int pasid);
|
||||
u32 kfd_pasid_alloc(void);
|
||||
void kfd_pasid_free(u32 pasid);
|
||||
|
||||
/* Doorbells */
|
||||
size_t kfd_doorbell_process_slice(struct kfd_dev *kfd);
|
||||
|
|
@ -927,7 +927,7 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm);
|
|||
struct kernel_queue *kernel_queue_init(struct kfd_dev *dev,
|
||||
enum kfd_queue_type type);
|
||||
void kernel_queue_uninit(struct kernel_queue *kq, bool hanging);
|
||||
int kfd_process_vm_fault(struct device_queue_manager *dqm, unsigned int pasid);
|
||||
int kfd_process_vm_fault(struct device_queue_manager *dqm, u32 pasid);
|
||||
|
||||
/* Process Queue Manager */
|
||||
struct process_queue_node {
|
||||
|
|
@ -1049,12 +1049,12 @@ int kfd_wait_on_events(struct kfd_process *p,
|
|||
uint32_t num_events, void __user *data,
|
||||
bool all, uint32_t user_timeout_ms,
|
||||
uint32_t *wait_result);
|
||||
void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id,
|
||||
void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
|
||||
uint32_t valid_id_bits);
|
||||
void kfd_signal_iommu_event(struct kfd_dev *dev,
|
||||
unsigned int pasid, unsigned long address,
|
||||
bool is_write_requested, bool is_execute_requested);
|
||||
void kfd_signal_hw_exception_event(unsigned int pasid);
|
||||
u32 pasid, unsigned long address,
|
||||
bool is_write_requested, bool is_execute_requested);
|
||||
void kfd_signal_hw_exception_event(u32 pasid);
|
||||
int kfd_set_event(struct kfd_process *p, uint32_t event_id);
|
||||
int kfd_reset_event(struct kfd_process *p, uint32_t event_id);
|
||||
int kfd_event_page_set(struct kfd_process *p, void *kernel_address,
|
||||
|
|
@ -1065,7 +1065,7 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p,
|
|||
uint64_t *event_page_offset, uint32_t *event_slot_index);
|
||||
int kfd_event_destroy(struct kfd_process *p, uint32_t event_id);
|
||||
|
||||
void kfd_signal_vm_fault_event(struct kfd_dev *dev, unsigned int pasid,
|
||||
void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid,
|
||||
struct kfd_vm_fault_info *info);
|
||||
|
||||
void kfd_signal_reset_event(struct kfd_dev *dev);
|
||||
|
|
|
|||
|
|
@ -1306,7 +1306,7 @@ void kfd_process_device_remove_obj_handle(struct kfd_process_device *pdd,
|
|||
}
|
||||
|
||||
/* This increments the process->ref counter. */
|
||||
struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid)
|
||||
struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid)
|
||||
{
|
||||
struct kfd_process *p, *ret_p = NULL;
|
||||
unsigned int temp;
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ struct kfd2kgd_calls {
|
|||
uint32_t sh_mem_config, uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit, uint32_t sh_mem_bases);
|
||||
|
||||
int (*set_pasid_vmid_mapping)(struct kgd_dev *kgd, unsigned int pasid,
|
||||
int (*set_pasid_vmid_mapping)(struct kgd_dev *kgd, u32 pasid,
|
||||
unsigned int vmid);
|
||||
|
||||
int (*init_interrupts)(struct kgd_dev *kgd, uint32_t pipe_id);
|
||||
|
|
|
|||
|
|
@ -45,12 +45,12 @@ extern int amd_iommu_register_ppr_notifier(struct notifier_block *nb);
|
|||
extern int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb);
|
||||
extern void amd_iommu_domain_direct_map(struct iommu_domain *dom);
|
||||
extern int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids);
|
||||
extern int amd_iommu_flush_page(struct iommu_domain *dom, int pasid,
|
||||
extern int amd_iommu_flush_page(struct iommu_domain *dom, u32 pasid,
|
||||
u64 address);
|
||||
extern int amd_iommu_flush_tlb(struct iommu_domain *dom, int pasid);
|
||||
extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid,
|
||||
extern int amd_iommu_flush_tlb(struct iommu_domain *dom, u32 pasid);
|
||||
extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, u32 pasid,
|
||||
unsigned long cr3);
|
||||
extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid);
|
||||
extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, u32 pasid);
|
||||
extern struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev);
|
||||
|
||||
#ifdef CONFIG_IRQ_REMAP
|
||||
|
|
@ -66,7 +66,7 @@ static inline int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
|
|||
#define PPR_INVALID 0x1
|
||||
#define PPR_FAILURE 0xf
|
||||
|
||||
extern int amd_iommu_complete_ppr(struct pci_dev *pdev, int pasid,
|
||||
extern int amd_iommu_complete_ppr(struct pci_dev *pdev, u32 pasid,
|
||||
int status, int tag);
|
||||
|
||||
static inline bool is_rd890_iommu(struct pci_dev *pdev)
|
||||
|
|
|
|||
|
|
@ -513,10 +513,11 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
|
|||
static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
|
||||
{
|
||||
struct device *dev = iommu->iommu.dev;
|
||||
int type, devid, pasid, flags, tag;
|
||||
int type, devid, flags, tag;
|
||||
volatile u32 *event = __evt;
|
||||
int count = 0;
|
||||
u64 address;
|
||||
u32 pasid;
|
||||
|
||||
retry:
|
||||
type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
|
||||
|
|
@ -909,7 +910,7 @@ static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep,
|
|||
cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
|
||||
}
|
||||
|
||||
static void build_inv_iommu_pasid(struct iommu_cmd *cmd, u16 domid, int pasid,
|
||||
static void build_inv_iommu_pasid(struct iommu_cmd *cmd, u16 domid, u32 pasid,
|
||||
u64 address, bool size)
|
||||
{
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
|
@ -927,7 +928,7 @@ static void build_inv_iommu_pasid(struct iommu_cmd *cmd, u16 domid, int pasid,
|
|||
CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
|
||||
}
|
||||
|
||||
static void build_inv_iotlb_pasid(struct iommu_cmd *cmd, u16 devid, int pasid,
|
||||
static void build_inv_iotlb_pasid(struct iommu_cmd *cmd, u16 devid, u32 pasid,
|
||||
int qdep, u64 address, bool size)
|
||||
{
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
|
@ -947,7 +948,7 @@ static void build_inv_iotlb_pasid(struct iommu_cmd *cmd, u16 devid, int pasid,
|
|||
CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES);
|
||||
}
|
||||
|
||||
static void build_complete_ppr(struct iommu_cmd *cmd, u16 devid, int pasid,
|
||||
static void build_complete_ppr(struct iommu_cmd *cmd, u16 devid, u32 pasid,
|
||||
int status, int tag, bool gn)
|
||||
{
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
|
@ -2786,7 +2787,7 @@ int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids)
|
|||
}
|
||||
EXPORT_SYMBOL(amd_iommu_domain_enable_v2);
|
||||
|
||||
static int __flush_pasid(struct protection_domain *domain, int pasid,
|
||||
static int __flush_pasid(struct protection_domain *domain, u32 pasid,
|
||||
u64 address, bool size)
|
||||
{
|
||||
struct iommu_dev_data *dev_data;
|
||||
|
|
@ -2847,13 +2848,13 @@ static int __flush_pasid(struct protection_domain *domain, int pasid,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __amd_iommu_flush_page(struct protection_domain *domain, int pasid,
|
||||
static int __amd_iommu_flush_page(struct protection_domain *domain, u32 pasid,
|
||||
u64 address)
|
||||
{
|
||||
return __flush_pasid(domain, pasid, address, false);
|
||||
}
|
||||
|
||||
int amd_iommu_flush_page(struct iommu_domain *dom, int pasid,
|
||||
int amd_iommu_flush_page(struct iommu_domain *dom, u32 pasid,
|
||||
u64 address)
|
||||
{
|
||||
struct protection_domain *domain = to_pdomain(dom);
|
||||
|
|
@ -2868,13 +2869,13 @@ int amd_iommu_flush_page(struct iommu_domain *dom, int pasid,
|
|||
}
|
||||
EXPORT_SYMBOL(amd_iommu_flush_page);
|
||||
|
||||
static int __amd_iommu_flush_tlb(struct protection_domain *domain, int pasid)
|
||||
static int __amd_iommu_flush_tlb(struct protection_domain *domain, u32 pasid)
|
||||
{
|
||||
return __flush_pasid(domain, pasid, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
|
||||
true);
|
||||
}
|
||||
|
||||
int amd_iommu_flush_tlb(struct iommu_domain *dom, int pasid)
|
||||
int amd_iommu_flush_tlb(struct iommu_domain *dom, u32 pasid)
|
||||
{
|
||||
struct protection_domain *domain = to_pdomain(dom);
|
||||
unsigned long flags;
|
||||
|
|
@ -2888,7 +2889,7 @@ int amd_iommu_flush_tlb(struct iommu_domain *dom, int pasid)
|
|||
}
|
||||
EXPORT_SYMBOL(amd_iommu_flush_tlb);
|
||||
|
||||
static u64 *__get_gcr3_pte(u64 *root, int level, int pasid, bool alloc)
|
||||
static u64 *__get_gcr3_pte(u64 *root, int level, u32 pasid, bool alloc)
|
||||
{
|
||||
int index;
|
||||
u64 *pte;
|
||||
|
|
@ -2920,7 +2921,7 @@ static u64 *__get_gcr3_pte(u64 *root, int level, int pasid, bool alloc)
|
|||
return pte;
|
||||
}
|
||||
|
||||
static int __set_gcr3(struct protection_domain *domain, int pasid,
|
||||
static int __set_gcr3(struct protection_domain *domain, u32 pasid,
|
||||
unsigned long cr3)
|
||||
{
|
||||
struct domain_pgtable pgtable;
|
||||
|
|
@ -2939,7 +2940,7 @@ static int __set_gcr3(struct protection_domain *domain, int pasid,
|
|||
return __amd_iommu_flush_tlb(domain, pasid);
|
||||
}
|
||||
|
||||
static int __clear_gcr3(struct protection_domain *domain, int pasid)
|
||||
static int __clear_gcr3(struct protection_domain *domain, u32 pasid)
|
||||
{
|
||||
struct domain_pgtable pgtable;
|
||||
u64 *pte;
|
||||
|
|
@ -2957,7 +2958,7 @@ static int __clear_gcr3(struct protection_domain *domain, int pasid)
|
|||
return __amd_iommu_flush_tlb(domain, pasid);
|
||||
}
|
||||
|
||||
int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid,
|
||||
int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, u32 pasid,
|
||||
unsigned long cr3)
|
||||
{
|
||||
struct protection_domain *domain = to_pdomain(dom);
|
||||
|
|
@ -2972,7 +2973,7 @@ int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid,
|
|||
}
|
||||
EXPORT_SYMBOL(amd_iommu_domain_set_gcr3);
|
||||
|
||||
int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid)
|
||||
int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, u32 pasid)
|
||||
{
|
||||
struct protection_domain *domain = to_pdomain(dom);
|
||||
unsigned long flags;
|
||||
|
|
@ -2986,7 +2987,7 @@ int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid)
|
|||
}
|
||||
EXPORT_SYMBOL(amd_iommu_domain_clear_gcr3);
|
||||
|
||||
int amd_iommu_complete_ppr(struct pci_dev *pdev, int pasid,
|
||||
int amd_iommu_complete_ppr(struct pci_dev *pdev, u32 pasid,
|
||||
int status, int tag)
|
||||
{
|
||||
struct iommu_dev_data *dev_data;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ struct pasid_state {
|
|||
struct mmu_notifier mn; /* mmu_notifier handle */
|
||||
struct pri_queue pri[PRI_QUEUE_SIZE]; /* PRI tag states */
|
||||
struct device_state *device_state; /* Link to our device_state */
|
||||
int pasid; /* PASID index */
|
||||
u32 pasid; /* PASID index */
|
||||
bool invalid; /* Used during setup and
|
||||
teardown of the pasid */
|
||||
spinlock_t lock; /* Protect pri_queues and
|
||||
|
|
@ -70,7 +70,7 @@ struct fault {
|
|||
struct mm_struct *mm;
|
||||
u64 address;
|
||||
u16 devid;
|
||||
u16 pasid;
|
||||
u32 pasid;
|
||||
u16 tag;
|
||||
u16 finish;
|
||||
u16 flags;
|
||||
|
|
@ -150,7 +150,7 @@ static void put_device_state(struct device_state *dev_state)
|
|||
|
||||
/* Must be called under dev_state->lock */
|
||||
static struct pasid_state **__get_pasid_state_ptr(struct device_state *dev_state,
|
||||
int pasid, bool alloc)
|
||||
u32 pasid, bool alloc)
|
||||
{
|
||||
struct pasid_state **root, **ptr;
|
||||
int level, index;
|
||||
|
|
@ -184,7 +184,7 @@ static struct pasid_state **__get_pasid_state_ptr(struct device_state *dev_state
|
|||
|
||||
static int set_pasid_state(struct device_state *dev_state,
|
||||
struct pasid_state *pasid_state,
|
||||
int pasid)
|
||||
u32 pasid)
|
||||
{
|
||||
struct pasid_state **ptr;
|
||||
unsigned long flags;
|
||||
|
|
@ -211,7 +211,7 @@ static int set_pasid_state(struct device_state *dev_state,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void clear_pasid_state(struct device_state *dev_state, int pasid)
|
||||
static void clear_pasid_state(struct device_state *dev_state, u32 pasid)
|
||||
{
|
||||
struct pasid_state **ptr;
|
||||
unsigned long flags;
|
||||
|
|
@ -229,7 +229,7 @@ static void clear_pasid_state(struct device_state *dev_state, int pasid)
|
|||
}
|
||||
|
||||
static struct pasid_state *get_pasid_state(struct device_state *dev_state,
|
||||
int pasid)
|
||||
u32 pasid)
|
||||
{
|
||||
struct pasid_state **ptr, *ret = NULL;
|
||||
unsigned long flags;
|
||||
|
|
@ -594,7 +594,7 @@ static struct notifier_block ppr_nb = {
|
|||
.notifier_call = ppr_notifier,
|
||||
};
|
||||
|
||||
int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
|
||||
int amd_iommu_bind_pasid(struct pci_dev *pdev, u32 pasid,
|
||||
struct task_struct *task)
|
||||
{
|
||||
struct pasid_state *pasid_state;
|
||||
|
|
@ -615,7 +615,7 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
|
|||
return -EINVAL;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (pasid < 0 || pasid >= dev_state->max_pasids)
|
||||
if (pasid >= dev_state->max_pasids)
|
||||
goto out;
|
||||
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -679,7 +679,7 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
|
|||
}
|
||||
EXPORT_SYMBOL(amd_iommu_bind_pasid);
|
||||
|
||||
void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid)
|
||||
void amd_iommu_unbind_pasid(struct pci_dev *pdev, u32 pasid)
|
||||
{
|
||||
struct pasid_state *pasid_state;
|
||||
struct device_state *dev_state;
|
||||
|
|
@ -695,7 +695,7 @@ void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid)
|
|||
if (dev_state == NULL)
|
||||
return;
|
||||
|
||||
if (pasid < 0 || pasid >= dev_state->max_pasids)
|
||||
if (pasid >= dev_state->max_pasids)
|
||||
goto out;
|
||||
|
||||
pasid_state = get_pasid_state(dev_state, pasid);
|
||||
|
|
|
|||
|
|
@ -1482,7 +1482,7 @@ void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
|
|||
}
|
||||
|
||||
void qi_flush_pasid_cache(struct intel_iommu *iommu, u16 did,
|
||||
u64 granu, int pasid)
|
||||
u64 granu, u32 pasid)
|
||||
{
|
||||
struct qi_desc desc = {.qw1 = 0, .qw2 = 0, .qw3 = 0};
|
||||
|
||||
|
|
@ -1796,7 +1796,7 @@ void dmar_msi_read(int irq, struct msi_msg *msg)
|
|||
}
|
||||
|
||||
static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
|
||||
u8 fault_reason, int pasid, u16 source_id,
|
||||
u8 fault_reason, u32 pasid, u16 source_id,
|
||||
unsigned long long addr)
|
||||
{
|
||||
const char *reason;
|
||||
|
|
@ -1846,7 +1846,8 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
|
|||
u8 fault_reason;
|
||||
u16 source_id;
|
||||
u64 guest_addr;
|
||||
int type, pasid;
|
||||
u32 pasid;
|
||||
int type;
|
||||
u32 data;
|
||||
bool pasid_present;
|
||||
|
||||
|
|
|
|||
|
|
@ -2527,7 +2527,7 @@ dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
|
|||
static int domain_setup_first_level(struct intel_iommu *iommu,
|
||||
struct dmar_domain *domain,
|
||||
struct device *dev,
|
||||
int pasid)
|
||||
u32 pasid)
|
||||
{
|
||||
int flags = PASID_FLAG_SUPERVISOR_MODE;
|
||||
struct dma_pte *pgd = domain->pgd;
|
||||
|
|
@ -5173,7 +5173,7 @@ static int aux_domain_add_dev(struct dmar_domain *domain,
|
|||
return -ENODEV;
|
||||
|
||||
if (domain->default_pasid <= 0) {
|
||||
int pasid;
|
||||
u32 pasid;
|
||||
|
||||
/* No private data needed for the default pasid */
|
||||
pasid = ioasid_alloc(NULL, PASID_MIN,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
static DEFINE_SPINLOCK(pasid_lock);
|
||||
u32 intel_pasid_max_id = PASID_MAX;
|
||||
|
||||
int vcmd_alloc_pasid(struct intel_iommu *iommu, unsigned int *pasid)
|
||||
int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 status_code;
|
||||
|
|
@ -58,7 +58,7 @@ int vcmd_alloc_pasid(struct intel_iommu *iommu, unsigned int *pasid)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void vcmd_free_pasid(struct intel_iommu *iommu, unsigned int pasid)
|
||||
void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 status_code;
|
||||
|
|
@ -146,7 +146,7 @@ int intel_pasid_alloc_table(struct device *dev)
|
|||
struct pasid_table *pasid_table;
|
||||
struct pasid_table_opaque data;
|
||||
struct page *pages;
|
||||
int max_pasid = 0;
|
||||
u32 max_pasid = 0;
|
||||
int ret, order;
|
||||
int size;
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ int intel_pasid_alloc_table(struct device *dev)
|
|||
INIT_LIST_HEAD(&pasid_table->dev);
|
||||
|
||||
if (info->pasid_supported)
|
||||
max_pasid = min_t(int, pci_max_pasids(to_pci_dev(dev)),
|
||||
max_pasid = min_t(u32, pci_max_pasids(to_pci_dev(dev)),
|
||||
intel_pasid_max_id);
|
||||
|
||||
size = max_pasid >> (PASID_PDE_SHIFT - 3);
|
||||
|
|
@ -242,7 +242,7 @@ int intel_pasid_get_dev_max_id(struct device *dev)
|
|||
return info->pasid_table->max_pasid;
|
||||
}
|
||||
|
||||
struct pasid_entry *intel_pasid_get_entry(struct device *dev, int pasid)
|
||||
struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
struct pasid_table *pasid_table;
|
||||
|
|
@ -251,8 +251,7 @@ struct pasid_entry *intel_pasid_get_entry(struct device *dev, int pasid)
|
|||
int dir_index, index;
|
||||
|
||||
pasid_table = intel_pasid_get_table(dev);
|
||||
if (WARN_ON(!pasid_table || pasid < 0 ||
|
||||
pasid >= intel_pasid_get_dev_max_id(dev)))
|
||||
if (WARN_ON(!pasid_table || pasid >= intel_pasid_get_dev_max_id(dev)))
|
||||
return NULL;
|
||||
|
||||
dir = pasid_table->table;
|
||||
|
|
@ -305,7 +304,7 @@ static inline void pasid_clear_entry_with_fpd(struct pasid_entry *pe)
|
|||
}
|
||||
|
||||
static void
|
||||
intel_pasid_clear_entry(struct device *dev, int pasid, bool fault_ignore)
|
||||
intel_pasid_clear_entry(struct device *dev, u32 pasid, bool fault_ignore)
|
||||
{
|
||||
struct pasid_entry *pe;
|
||||
|
||||
|
|
@ -444,7 +443,7 @@ pasid_set_eafe(struct pasid_entry *pe)
|
|||
|
||||
static void
|
||||
pasid_cache_invalidation_with_pasid(struct intel_iommu *iommu,
|
||||
u16 did, int pasid)
|
||||
u16 did, u32 pasid)
|
||||
{
|
||||
struct qi_desc desc;
|
||||
|
||||
|
|
@ -473,7 +472,7 @@ iotlb_invalidation_with_pasid(struct intel_iommu *iommu, u16 did, u32 pasid)
|
|||
|
||||
static void
|
||||
devtlb_invalidation_with_pasid(struct intel_iommu *iommu,
|
||||
struct device *dev, int pasid)
|
||||
struct device *dev, u32 pasid)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
u16 sid, qdep, pfsid;
|
||||
|
|
@ -499,7 +498,7 @@ devtlb_invalidation_with_pasid(struct intel_iommu *iommu,
|
|||
}
|
||||
|
||||
void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
|
||||
int pasid, bool fault_ignore)
|
||||
u32 pasid, bool fault_ignore)
|
||||
{
|
||||
struct pasid_entry *pte;
|
||||
u16 did;
|
||||
|
|
@ -524,7 +523,7 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
|
|||
|
||||
static void pasid_flush_caches(struct intel_iommu *iommu,
|
||||
struct pasid_entry *pte,
|
||||
int pasid, u16 did)
|
||||
u32 pasid, u16 did)
|
||||
{
|
||||
if (!ecap_coherent(iommu->ecap))
|
||||
clflush_cache_range(pte, sizeof(*pte));
|
||||
|
|
@ -543,7 +542,7 @@ static void pasid_flush_caches(struct intel_iommu *iommu,
|
|||
*/
|
||||
int intel_pasid_setup_first_level(struct intel_iommu *iommu,
|
||||
struct device *dev, pgd_t *pgd,
|
||||
int pasid, u16 did, int flags)
|
||||
u32 pasid, u16 did, int flags)
|
||||
{
|
||||
struct pasid_entry *pte;
|
||||
|
||||
|
|
@ -616,7 +615,7 @@ static inline int iommu_skip_agaw(struct dmar_domain *domain,
|
|||
*/
|
||||
int intel_pasid_setup_second_level(struct intel_iommu *iommu,
|
||||
struct dmar_domain *domain,
|
||||
struct device *dev, int pasid)
|
||||
struct device *dev, u32 pasid)
|
||||
{
|
||||
struct pasid_entry *pte;
|
||||
struct dma_pte *pgd;
|
||||
|
|
@ -674,7 +673,7 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
|
|||
*/
|
||||
int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
|
||||
struct dmar_domain *domain,
|
||||
struct device *dev, int pasid)
|
||||
struct device *dev, u32 pasid)
|
||||
{
|
||||
u16 did = FLPT_DEFAULT_DID;
|
||||
struct pasid_entry *pte;
|
||||
|
|
@ -760,7 +759,7 @@ intel_pasid_setup_bind_data(struct intel_iommu *iommu, struct pasid_entry *pte,
|
|||
* @addr_width: Address width of the first level (guest)
|
||||
*/
|
||||
int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
|
||||
pgd_t *gpgd, int pasid,
|
||||
pgd_t *gpgd, u32 pasid,
|
||||
struct iommu_gpasid_bind_data_vtd *pasid_data,
|
||||
struct dmar_domain *domain, int addr_width)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ struct pasid_entry {
|
|||
struct pasid_table {
|
||||
void *table; /* pasid table pointer */
|
||||
int order; /* page order of pasid table */
|
||||
int max_pasid; /* max pasid */
|
||||
u32 max_pasid; /* max pasid */
|
||||
struct list_head dev; /* device list */
|
||||
};
|
||||
|
||||
|
|
@ -98,31 +98,31 @@ static inline bool pasid_pte_is_present(struct pasid_entry *pte)
|
|||
return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
|
||||
}
|
||||
|
||||
extern u32 intel_pasid_max_id;
|
||||
extern unsigned int 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);
|
||||
void intel_pasid_free_id(u32 pasid);
|
||||
void *intel_pasid_lookup_id(u32 pasid);
|
||||
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);
|
||||
struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid);
|
||||
int intel_pasid_setup_first_level(struct intel_iommu *iommu,
|
||||
struct device *dev, pgd_t *pgd,
|
||||
int pasid, u16 did, int flags);
|
||||
u32 pasid, u16 did, int flags);
|
||||
int intel_pasid_setup_second_level(struct intel_iommu *iommu,
|
||||
struct dmar_domain *domain,
|
||||
struct device *dev, int pasid);
|
||||
struct device *dev, u32 pasid);
|
||||
int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
|
||||
struct dmar_domain *domain,
|
||||
struct device *dev, int pasid);
|
||||
struct device *dev, u32 pasid);
|
||||
int intel_pasid_setup_nested(struct intel_iommu *iommu,
|
||||
struct device *dev, pgd_t *pgd, int pasid,
|
||||
struct device *dev, pgd_t *pgd, u32 pasid,
|
||||
struct iommu_gpasid_bind_data_vtd *pasid_data,
|
||||
struct dmar_domain *domain, int addr_width);
|
||||
void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
|
||||
struct device *dev, int pasid,
|
||||
struct device *dev, u32 pasid,
|
||||
bool fault_ignore);
|
||||
int vcmd_alloc_pasid(struct intel_iommu *iommu, unsigned int *pasid);
|
||||
void vcmd_free_pasid(struct intel_iommu *iommu, unsigned int pasid);
|
||||
int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid);
|
||||
void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid);
|
||||
#endif /* __INTEL_PASID_H */
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@
|
|||
#include <linux/mm_types.h>
|
||||
#include <linux/ioasid.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/fpu/api.h>
|
||||
|
||||
#include "pasid.h"
|
||||
|
||||
static irqreturn_t prq_event_thread(int irq, void *d);
|
||||
static void intel_svm_drain_prq(struct device *dev, int pasid);
|
||||
static void intel_svm_drain_prq(struct device *dev, u32 pasid);
|
||||
|
||||
#define PRQ_ORDER 0
|
||||
|
||||
|
|
@ -399,7 +400,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int intel_svm_unbind_gpasid(struct device *dev, int pasid)
|
||||
int intel_svm_unbind_gpasid(struct device *dev, u32 pasid)
|
||||
{
|
||||
struct intel_iommu *iommu = device_to_iommu(dev, NULL, NULL);
|
||||
struct intel_svm_dev *sdev;
|
||||
|
|
@ -444,9 +445,28 @@ int intel_svm_unbind_gpasid(struct device *dev, int pasid)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void _load_pasid(void *unused)
|
||||
{
|
||||
update_pasid();
|
||||
}
|
||||
|
||||
static void load_pasid(struct mm_struct *mm, u32 pasid)
|
||||
{
|
||||
mutex_lock(&mm->context.lock);
|
||||
|
||||
/* Synchronize with READ_ONCE in update_pasid(). */
|
||||
smp_store_release(&mm->pasid, pasid);
|
||||
|
||||
/* Update PASID MSR on all CPUs running the mm's tasks. */
|
||||
on_each_cpu_mask(mm_cpumask(mm), _load_pasid, NULL, true);
|
||||
|
||||
mutex_unlock(&mm->context.lock);
|
||||
}
|
||||
|
||||
/* Caller must hold pasid_mutex, mm reference */
|
||||
static int
|
||||
intel_svm_bind_mm(struct device *dev, int flags, struct svm_dev_ops *ops,
|
||||
intel_svm_bind_mm(struct device *dev, unsigned int flags,
|
||||
struct svm_dev_ops *ops,
|
||||
struct mm_struct *mm, struct intel_svm_dev **sd)
|
||||
{
|
||||
struct intel_iommu *iommu = device_to_iommu(dev, NULL, NULL);
|
||||
|
|
@ -590,6 +610,10 @@ intel_svm_bind_mm(struct device *dev, int flags, struct svm_dev_ops *ops,
|
|||
}
|
||||
|
||||
list_add_tail(&svm->list, &global_svm_list);
|
||||
if (mm) {
|
||||
/* The newly allocated pasid is loaded to the mm. */
|
||||
load_pasid(mm, svm->pasid);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Binding a new device with existing PASID, need to setup
|
||||
|
|
@ -620,7 +644,7 @@ intel_svm_bind_mm(struct device *dev, int flags, struct svm_dev_ops *ops,
|
|||
}
|
||||
|
||||
/* Caller must hold pasid_mutex */
|
||||
static int intel_svm_unbind_mm(struct device *dev, int pasid)
|
||||
static int intel_svm_unbind_mm(struct device *dev, u32 pasid)
|
||||
{
|
||||
struct intel_svm_dev *sdev;
|
||||
struct intel_iommu *iommu;
|
||||
|
|
@ -653,8 +677,11 @@ static int intel_svm_unbind_mm(struct device *dev, int pasid)
|
|||
|
||||
if (list_empty(&svm->devs)) {
|
||||
ioasid_free(svm->pasid);
|
||||
if (svm->mm)
|
||||
if (svm->mm) {
|
||||
mmu_notifier_unregister(&svm->notifier, svm->mm);
|
||||
/* Clear mm's pasid. */
|
||||
load_pasid(svm->mm, PASID_DISABLED);
|
||||
}
|
||||
list_del(&svm->list);
|
||||
/* We mandate that no page faults may be outstanding
|
||||
* for the PASID when intel_svm_unbind_mm() is called.
|
||||
|
|
@ -739,7 +766,7 @@ static bool is_canonical_address(u64 addr)
|
|||
* described in VT-d spec CH7.10 to drain all page requests and page
|
||||
* responses pending in the hardware.
|
||||
*/
|
||||
static void intel_svm_drain_prq(struct device *dev, int pasid)
|
||||
static void intel_svm_drain_prq(struct device *dev, u32 pasid)
|
||||
{
|
||||
struct device_domain_info *info;
|
||||
struct dmar_domain *domain;
|
||||
|
|
@ -1033,7 +1060,7 @@ intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata)
|
|||
{
|
||||
struct iommu_sva *sva = ERR_PTR(-EINVAL);
|
||||
struct intel_svm_dev *sdev = NULL;
|
||||
int flags = 0;
|
||||
unsigned int flags = 0;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
|
@ -1042,7 +1069,7 @@ intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata)
|
|||
* and intel_svm etc.
|
||||
*/
|
||||
if (drvdata)
|
||||
flags = *(int *)drvdata;
|
||||
flags = *(unsigned int *)drvdata;
|
||||
mutex_lock(&pasid_mutex);
|
||||
ret = intel_svm_bind_mm(dev, flags, NULL, mm, &sdev);
|
||||
if (ret)
|
||||
|
|
@ -1067,10 +1094,10 @@ void intel_svm_unbind(struct iommu_sva *sva)
|
|||
mutex_unlock(&pasid_mutex);
|
||||
}
|
||||
|
||||
int intel_svm_get_pasid(struct iommu_sva *sva)
|
||||
u32 intel_svm_get_pasid(struct iommu_sva *sva)
|
||||
{
|
||||
struct intel_svm_dev *sdev;
|
||||
int pasid;
|
||||
u32 pasid;
|
||||
|
||||
mutex_lock(&pasid_mutex);
|
||||
sdev = to_intel_svm_dev(sva);
|
||||
|
|
|
|||
|
|
@ -2839,7 +2839,7 @@ void iommu_sva_unbind_device(struct iommu_sva *handle)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_sva_unbind_device);
|
||||
|
||||
int iommu_sva_get_pasid(struct iommu_sva *handle)
|
||||
u32 iommu_sva_get_pasid(struct iommu_sva *handle)
|
||||
{
|
||||
const struct iommu_ops *ops = handle->dev->bus->iommu_ops;
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ static long uacce_fops_compat_ioctl(struct file *filep,
|
|||
|
||||
static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q)
|
||||
{
|
||||
int pasid;
|
||||
u32 pasid;
|
||||
struct iommu_sva *handle;
|
||||
|
||||
if (!(uacce->flags & UACCE_DEV_SVA))
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ extern void amd_iommu_free_device(struct pci_dev *pdev);
|
|||
*
|
||||
* The function returns 0 on success or a negative value on error.
|
||||
*/
|
||||
extern int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
|
||||
extern int amd_iommu_bind_pasid(struct pci_dev *pdev, u32 pasid,
|
||||
struct task_struct *task);
|
||||
|
||||
/**
|
||||
|
|
@ -88,7 +88,7 @@ extern int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
|
|||
* When this function returns the device is no longer using the PASID
|
||||
* and the PASID is no longer bound to its task.
|
||||
*/
|
||||
extern void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid);
|
||||
extern void amd_iommu_unbind_pasid(struct pci_dev *pdev, u32 pasid);
|
||||
|
||||
/**
|
||||
* amd_iommu_set_invalid_ppr_cb() - Register a call-back for failed
|
||||
|
|
@ -114,7 +114,7 @@ extern void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid);
|
|||
#define AMD_IOMMU_INV_PRI_RSP_FAIL 2
|
||||
|
||||
typedef int (*amd_iommu_invalid_ppr_cb)(struct pci_dev *pdev,
|
||||
int pasid,
|
||||
u32 pasid,
|
||||
unsigned long address,
|
||||
u16);
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ extern int amd_iommu_device_info(struct pci_dev *pdev,
|
|||
* @cb: The call-back function
|
||||
*/
|
||||
|
||||
typedef void (*amd_iommu_invalidate_ctx)(struct pci_dev *pdev, int pasid);
|
||||
typedef void (*amd_iommu_invalidate_ctx)(struct pci_dev *pdev, u32 pasid);
|
||||
|
||||
extern int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev,
|
||||
amd_iommu_invalidate_ctx cb);
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ struct dmar_domain {
|
|||
2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
|
||||
u64 max_addr; /* maximum mapped address */
|
||||
|
||||
int default_pasid; /*
|
||||
u32 default_pasid; /*
|
||||
* The default pasid used for non-SVM
|
||||
* traffic on mediated devices.
|
||||
*/
|
||||
|
|
@ -708,7 +708,7 @@ void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
|
|||
u32 pasid, u16 qdep, u64 addr,
|
||||
unsigned int size_order);
|
||||
void qi_flush_pasid_cache(struct intel_iommu *iommu, u16 did, u64 granu,
|
||||
int pasid);
|
||||
u32 pasid);
|
||||
|
||||
int qi_submit_sync(struct intel_iommu *iommu, struct qi_desc *desc,
|
||||
unsigned int count, unsigned long options);
|
||||
|
|
@ -737,11 +737,11 @@ extern int intel_svm_enable_prq(struct intel_iommu *iommu);
|
|||
extern int intel_svm_finish_prq(struct intel_iommu *iommu);
|
||||
int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev,
|
||||
struct iommu_gpasid_bind_data *data);
|
||||
int intel_svm_unbind_gpasid(struct device *dev, int pasid);
|
||||
int intel_svm_unbind_gpasid(struct device *dev, u32 pasid);
|
||||
struct iommu_sva *intel_svm_bind(struct device *dev, struct mm_struct *mm,
|
||||
void *drvdata);
|
||||
void intel_svm_unbind(struct iommu_sva *handle);
|
||||
int intel_svm_get_pasid(struct iommu_sva *handle);
|
||||
u32 intel_svm_get_pasid(struct iommu_sva *handle);
|
||||
int intel_svm_page_response(struct device *dev, struct iommu_fault_event *evt,
|
||||
struct iommu_page_response *msg);
|
||||
|
||||
|
|
@ -753,7 +753,7 @@ struct intel_svm_dev {
|
|||
struct device *dev;
|
||||
struct svm_dev_ops *ops;
|
||||
struct iommu_sva sva;
|
||||
int pasid;
|
||||
u32 pasid;
|
||||
int users;
|
||||
u16 did;
|
||||
u16 dev_iotlb:1;
|
||||
|
|
@ -765,8 +765,8 @@ struct intel_svm {
|
|||
struct mm_struct *mm;
|
||||
|
||||
struct intel_iommu *iommu;
|
||||
int flags;
|
||||
int pasid;
|
||||
unsigned int flags;
|
||||
u32 pasid;
|
||||
int gpasid; /* In case that guest PASID is different from host PASID */
|
||||
struct list_head devs;
|
||||
struct list_head list;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
struct device;
|
||||
|
||||
struct svm_dev_ops {
|
||||
void (*fault_cb)(struct device *dev, int pasid, u64 address,
|
||||
void (*fault_cb)(struct device *dev, u32 pasid, u64 address,
|
||||
void *private, int rwxp, int response);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ struct iommu_ops {
|
|||
struct iommu_sva *(*sva_bind)(struct device *dev, struct mm_struct *mm,
|
||||
void *drvdata);
|
||||
void (*sva_unbind)(struct iommu_sva *handle);
|
||||
int (*sva_get_pasid)(struct iommu_sva *handle);
|
||||
u32 (*sva_get_pasid)(struct iommu_sva *handle);
|
||||
|
||||
int (*page_response)(struct device *dev,
|
||||
struct iommu_fault_event *evt,
|
||||
|
|
@ -296,7 +296,7 @@ struct iommu_ops {
|
|||
int (*sva_bind_gpasid)(struct iommu_domain *domain,
|
||||
struct device *dev, struct iommu_gpasid_bind_data *data);
|
||||
|
||||
int (*sva_unbind_gpasid)(struct device *dev, int pasid);
|
||||
int (*sva_unbind_gpasid)(struct device *dev, u32 pasid);
|
||||
|
||||
int (*def_domain_type)(struct device *dev);
|
||||
|
||||
|
|
@ -634,7 +634,7 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev,
|
|||
struct mm_struct *mm,
|
||||
void *drvdata);
|
||||
void iommu_sva_unbind_device(struct iommu_sva *handle);
|
||||
int iommu_sva_get_pasid(struct iommu_sva *handle);
|
||||
u32 iommu_sva_get_pasid(struct iommu_sva *handle);
|
||||
|
||||
#else /* CONFIG_IOMMU_API */
|
||||
|
||||
|
|
@ -1027,7 +1027,7 @@ static inline void iommu_sva_unbind_device(struct iommu_sva *handle)
|
|||
{
|
||||
}
|
||||
|
||||
static inline int iommu_sva_get_pasid(struct iommu_sva *handle)
|
||||
static inline u32 iommu_sva_get_pasid(struct iommu_sva *handle)
|
||||
{
|
||||
return IOMMU_PASID_INVALID;
|
||||
}
|
||||
|
|
@ -1046,7 +1046,7 @@ static inline int iommu_sva_bind_gpasid(struct iommu_domain *domain,
|
|||
}
|
||||
|
||||
static inline int iommu_sva_unbind_gpasid(struct iommu_domain *domain,
|
||||
struct device *dev, int pasid)
|
||||
struct device *dev, u32 pasid)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -559,6 +559,10 @@ struct mm_struct {
|
|||
atomic_long_t hugetlb_usage;
|
||||
#endif
|
||||
struct work_struct async_put_work;
|
||||
|
||||
#ifdef CONFIG_IOMMU_SUPPORT
|
||||
u32 pasid;
|
||||
#endif
|
||||
} __randomize_layout;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ struct uacce_queue {
|
|||
struct list_head list;
|
||||
struct uacce_qfile_region *qfrs[UACCE_MAX_REGION];
|
||||
enum uacce_q_state state;
|
||||
int pasid;
|
||||
u32 pasid;
|
||||
struct iommu_sva *handle;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user