mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'iommu-updates-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux
Pull iommu updates from Joerg Roedel:
- Introduction of the generic IO page-table framework with support for
Intel and AMD IOMMU formats from Jason.
This has good potential for unifying more IO page-table
implementations and making future enhancements more easy. But this
also needed quite some fixes during development. All known issues
have been fixed, but my feeling is that there is a higher potential
than usual that more might be needed.
- Intel VT-d updates:
- Use right invalidation hint in qi_desc_iotlb()
- Reduce the scope of INTEL_IOMMU_FLOPPY_WA
- ARM-SMMU updates:
- Qualcomm device-tree binding updates for Kaanapali and Glymur SoCs
and a new clock for the TBU.
- Fix error handling if level 1 CD table allocation fails.
- Permit more than the architectural maximum number of SMRs for
funky Qualcomm mis-implementations of SMMUv2.
- Mediatek driver:
- MT8189 iommu support
- Move ARM IO-pgtable selftests to kunit
- Device leak fixes for a couple of drivers
- Random smaller fixes and improvements
* tag 'iommu-updates-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux: (81 commits)
iommupt/vtd: Support mgaw's less than a 4 level walk for first stage
iommupt/vtd: Allow VT-d to have a larger table top than the vasz requires
powerpc/pseries/svm: Make mem_encrypt.h self contained
genpt: Make GENERIC_PT invisible
iommupt: Avoid a compiler bug with sw_bit
iommu/arm-smmu-qcom: Enable use of all SMR groups when running bare-metal
iommupt: Fix unlikely flows in increase_top()
iommu/amd: Propagate the error code returned by __modify_irte_ga() in modify_irte_ga()
MAINTAINERS: Update my email address
iommu/arm-smmu-v3: Fix error check in arm_smmu_alloc_cd_tables
dt-bindings: iommu: qcom_iommu: Allow 'tbu' clock
iommu/vt-d: Restore previous domain::aperture_end calculation
iommu/vt-d: Fix unused invalidation hint in qi_desc_iotlb
iommu/vt-d: Set INTEL_IOMMU_FLOPPY_WA depend on BLK_DEV_FD
iommu/tegra: fix device leak on probe_device()
iommu/sun50i: fix device leak on of_xlate()
iommu/omap: simplify probe_device() error handling
iommu/omap: fix device leaks on probe_device()
iommu/mediatek-v1: add missing larb count sanity check
iommu/mediatek-v1: fix device leaks on probe()
...
This commit is contained in:
@@ -415,6 +415,7 @@ ForEachMacros:
|
||||
- 'for_each_prop_dlc_cpus'
|
||||
- 'for_each_prop_dlc_platforms'
|
||||
- 'for_each_property_of_node'
|
||||
- 'for_each_pt_level_entry'
|
||||
- 'for_each_rdt_resource'
|
||||
- 'for_each_reg'
|
||||
- 'for_each_reg_filtered'
|
||||
|
||||
@@ -345,7 +345,8 @@ Jayachandran C <c.jayachandran@gmail.com> <jayachandranc@netlogicmicro.com>
|
||||
Jayachandran C <c.jayachandran@gmail.com> <jchandra@broadcom.com>
|
||||
Jayachandran C <c.jayachandran@gmail.com> <jchandra@digeo.com>
|
||||
Jayachandran C <c.jayachandran@gmail.com> <jnair@caviumnetworks.com>
|
||||
<jean-philippe@linaro.org> <jean-philippe.brucker@arm.com>
|
||||
Jean-Philippe Brucker <jpb@kernel.org> <jean-philippe.brucker@arm.com>
|
||||
Jean-Philippe Brucker <jpb@kernel.org> <jean-philippe@linaro.org>
|
||||
Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> <jeanmichel.hautbois@ideasonboard.com>
|
||||
Jean Tourrilhes <jt@hpl.hp.com>
|
||||
Jeevan Shriram <quic_jshriram@quicinc.com> <jshriram@codeaurora.org>
|
||||
|
||||
@@ -35,6 +35,8 @@ properties:
|
||||
- description: Qcom SoCs implementing "qcom,smmu-500" and "arm,mmu-500"
|
||||
items:
|
||||
- enum:
|
||||
- qcom,glymur-smmu-500
|
||||
- qcom,kaanapali-smmu-500
|
||||
- qcom,milos-smmu-500
|
||||
- qcom,qcm2290-smmu-500
|
||||
- qcom,qcs615-smmu-500
|
||||
|
||||
@@ -82,6 +82,9 @@ properties:
|
||||
- mediatek,mt8188-iommu-vdo # generation two
|
||||
- mediatek,mt8188-iommu-vpp # generation two
|
||||
- mediatek,mt8188-iommu-infra # generation two
|
||||
- mediatek,mt8189-iommu-apu # generation two
|
||||
- mediatek,mt8189-iommu-infra # generation two
|
||||
- mediatek,mt8189-iommu-mm # generation two
|
||||
- mediatek,mt8192-m4u # generation two
|
||||
- mediatek,mt8195-iommu-vdo # generation two
|
||||
- mediatek,mt8195-iommu-vpp # generation two
|
||||
@@ -128,6 +131,7 @@ properties:
|
||||
This is the mtk_m4u_id according to the HW. Specifies the mtk_m4u_id as
|
||||
defined in
|
||||
dt-binding/memory/mediatek,mt8188-memory-port.h for mt8188,
|
||||
dt-binding/memory/mediatek,mt8189-memory-port.h for mt8189,
|
||||
dt-binding/memory/mt2701-larb-port.h for mt2701 and mt7623,
|
||||
dt-binding/memory/mt2712-larb-port.h for mt2712,
|
||||
dt-binding/memory/mt6779-larb-port.h for mt6779,
|
||||
@@ -164,6 +168,7 @@ allOf:
|
||||
- mediatek,mt8186-iommu-mm
|
||||
- mediatek,mt8188-iommu-vdo
|
||||
- mediatek,mt8188-iommu-vpp
|
||||
- mediatek,mt8189-iommu-mm
|
||||
- mediatek,mt8192-m4u
|
||||
- mediatek,mt8195-iommu-vdo
|
||||
- mediatek,mt8195-iommu-vpp
|
||||
@@ -180,6 +185,7 @@ allOf:
|
||||
- mediatek,mt8186-iommu-mm
|
||||
- mediatek,mt8188-iommu-vdo
|
||||
- mediatek,mt8188-iommu-vpp
|
||||
- mediatek,mt8189-iommu-mm
|
||||
- mediatek,mt8192-m4u
|
||||
- mediatek,mt8195-iommu-vdo
|
||||
- mediatek,mt8195-iommu-vpp
|
||||
@@ -208,6 +214,8 @@ allOf:
|
||||
contains:
|
||||
enum:
|
||||
- mediatek,mt8188-iommu-infra
|
||||
- mediatek,mt8189-iommu-apu
|
||||
- mediatek,mt8189-iommu-infra
|
||||
- mediatek,mt8195-iommu-infra
|
||||
|
||||
then:
|
||||
|
||||
@@ -32,14 +32,18 @@ properties:
|
||||
- const: qcom,msm-iommu-v2
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
items:
|
||||
- description: Clock required for IOMMU register group access
|
||||
- description: Clock required for underlying bus access
|
||||
- description: Clock required for Translation Buffer Unit access
|
||||
|
||||
clock-names:
|
||||
minItems: 2
|
||||
items:
|
||||
- const: iface
|
||||
- const: bus
|
||||
- const: tbu
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
========================
|
||||
Generic Radix Page Table
|
||||
========================
|
||||
|
||||
.. kernel-doc:: include/linux/generic_pt/common.h
|
||||
:doc: Generic Radix Page Table
|
||||
|
||||
.. kernel-doc:: drivers/iommu/generic_pt/pt_defs.h
|
||||
:doc: Generic Page Table Language
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Generic PT is structured as a multi-compilation system. Since each format
|
||||
provides an API using a common set of names there can be only one format active
|
||||
within a compilation unit. This design avoids function pointers around the low
|
||||
level API.
|
||||
|
||||
Instead the function pointers can end up at the higher level API (i.e.
|
||||
map/unmap, etc.) and the per-format code can be directly inlined into the
|
||||
per-format compilation unit. For something like IOMMU each format will be
|
||||
compiled into a per-format IOMMU operations kernel module.
|
||||
|
||||
For this to work the .c file for each compilation unit will include both the
|
||||
format headers and the generic code for the implementation. For instance in an
|
||||
implementation compilation unit the headers would normally be included as
|
||||
follows:
|
||||
|
||||
generic_pt/fmt/iommu_amdv1.c::
|
||||
|
||||
#include <linux/generic_pt/common.h>
|
||||
#include "defs_amdv1.h"
|
||||
#include "../pt_defs.h"
|
||||
#include "amdv1.h"
|
||||
#include "../pt_common.h"
|
||||
#include "../pt_iter.h"
|
||||
#include "../iommu_pt.h" /* The IOMMU implementation */
|
||||
|
||||
iommu_pt.h includes definitions that will generate the operations functions for
|
||||
map/unmap/etc. using the definitions provided by AMDv1. The resulting module
|
||||
will have exported symbols named like pt_iommu_amdv1_init().
|
||||
|
||||
Refer to drivers/iommu/generic_pt/fmt/iommu_template.h for an example of how the
|
||||
IOMMU implementation uses multi-compilation to generate per-format ops structs
|
||||
pointers.
|
||||
|
||||
The format code is written so that the common names arise from #defines to
|
||||
distinct format specific names. This is intended to aid debuggability by
|
||||
avoiding symbol clashes across all the different formats.
|
||||
|
||||
Exported symbols and other global names are mangled using a per-format string
|
||||
via the NS() helper macro.
|
||||
|
||||
The format uses struct pt_common as the top-level struct for the table,
|
||||
and each format will have its own struct pt_xxx which embeds it to store
|
||||
format-specific information.
|
||||
|
||||
The implementation will further wrap struct pt_common in its own top-level
|
||||
struct, such as struct pt_iommu_amdv1.
|
||||
|
||||
Format functions at the struct pt_common level
|
||||
----------------------------------------------
|
||||
|
||||
.. kernel-doc:: include/linux/generic_pt/common.h
|
||||
:identifiers:
|
||||
.. kernel-doc:: drivers/iommu/generic_pt/pt_common.h
|
||||
|
||||
Iteration Helpers
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: drivers/iommu/generic_pt/pt_iter.h
|
||||
|
||||
Writing a Format
|
||||
----------------
|
||||
|
||||
It is best to start from a simple format that is similar to the target. x86_64
|
||||
is usually a good reference for something simple, and AMDv1 is something fairly
|
||||
complete.
|
||||
|
||||
The required inline functions need to be implemented in the format header.
|
||||
These should all follow the standard pattern of::
|
||||
|
||||
static inline pt_oaddr_t amdv1pt_entry_oa(const struct pt_state *pts)
|
||||
{
|
||||
[..]
|
||||
}
|
||||
#define pt_entry_oa amdv1pt_entry_oa
|
||||
|
||||
where a uniquely named per-format inline function provides the implementation
|
||||
and a define maps it to the generic name. This is intended to make debug symbols
|
||||
work better. inline functions should always be used as the prototypes in
|
||||
pt_common.h will cause the compiler to validate the function signature to
|
||||
prevent errors.
|
||||
|
||||
Review pt_fmt_defaults.h to understand some of the optional inlines.
|
||||
|
||||
Once the format compiles then it should be run through the generic page table
|
||||
kunit test in kunit_generic_pt.h using kunit. For example::
|
||||
|
||||
$ tools/testing/kunit/kunit.py run --build_dir build_kunit_x86_64 --arch x86_64 --kunitconfig ./drivers/iommu/generic_pt/.kunitconfig amdv1_fmt_test.*
|
||||
[...]
|
||||
[11:15:08] Testing complete. Ran 9 tests: passed: 9
|
||||
[11:15:09] Elapsed time: 3.137s total, 0.001s configuring, 2.368s building, 0.311s running
|
||||
|
||||
The generic tests are intended to prove out the format functions and give
|
||||
clearer failures to speed up finding the problems. Once those pass then the
|
||||
entire kunit suite should be run.
|
||||
|
||||
IOMMU Invalidation Features
|
||||
---------------------------
|
||||
|
||||
Invalidation is how the page table algorithms synchronize with a HW cache of the
|
||||
page table memory, typically called the TLB (or IOTLB for IOMMU cases).
|
||||
|
||||
The TLB can store present PTEs, non-present PTEs and table pointers, depending
|
||||
on its design. Every HW has its own approach on how to describe what has changed
|
||||
to have changed items removed from the TLB.
|
||||
|
||||
PT_FEAT_FLUSH_RANGE
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
PT_FEAT_FLUSH_RANGE is the easiest scheme to understand. It tries to generate a
|
||||
single range invalidation for each operation, over-invalidating if there are
|
||||
gaps of VA that don't need invalidation. This trades off impacted VA for number
|
||||
of invalidation operations. It does not keep track of what is being invalidated;
|
||||
however, if pages have to be freed then page table pointers have to be cleaned
|
||||
from the walk cache. The range can start/end at any page boundary.
|
||||
|
||||
PT_FEAT_FLUSH_RANGE_NO_GAPS
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
PT_FEAT_FLUSH_RANGE_NO_GAPS is similar to PT_FEAT_FLUSH_RANGE; however, it tries
|
||||
to minimize the amount of impacted VA by issuing extra flush operations. This is
|
||||
useful if the cost of processing VA is very high, for instance because a
|
||||
hypervisor is processing the page table with a shadowing algorithm.
|
||||
@@ -93,6 +93,7 @@ Subsystem-specific APIs
|
||||
frame-buffer
|
||||
aperture
|
||||
generic-counter
|
||||
generic_pt
|
||||
gpio/index
|
||||
hsi
|
||||
hte/index
|
||||
|
||||
+3
-3
@@ -388,7 +388,7 @@ B: https://bugzilla.kernel.org
|
||||
F: drivers/acpi/*thermal*
|
||||
|
||||
ACPI VIOT DRIVER
|
||||
M: Jean-Philippe Brucker <jean-philippe@linaro.org>
|
||||
M: Jean-Philippe Brucker <jpb@kernel.org>
|
||||
L: linux-acpi@vger.kernel.org
|
||||
L: iommu@lists.linux.dev
|
||||
S: Maintained
|
||||
@@ -2269,7 +2269,7 @@ F: drivers/iommu/arm/
|
||||
F: drivers/iommu/io-pgtable-arm*
|
||||
|
||||
ARM SMMU SVA SUPPORT
|
||||
R: Jean-Philippe Brucker <jean-philippe@linaro.org>
|
||||
R: Jean-Philippe Brucker <jpb@kernel.org>
|
||||
F: drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
|
||||
|
||||
ARM SUB-ARCHITECTURES
|
||||
@@ -27455,7 +27455,7 @@ F: drivers/virtio/virtio_input.c
|
||||
F: include/uapi/linux/virtio_input.h
|
||||
|
||||
VIRTIO IOMMU DRIVER
|
||||
M: Jean-Philippe Brucker <jean-philippe@linaro.org>
|
||||
M: Jean-Philippe Brucker <jpb@kernel.org>
|
||||
L: virtualization@lists.linux.dev
|
||||
S: Maintained
|
||||
F: drivers/iommu/virtio-iommu.c
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#define _ASM_POWERPC_MEM_ENCRYPT_H
|
||||
|
||||
#include <asm/svm.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct device;
|
||||
|
||||
static inline bool force_dma_unencrypted(struct device *dev)
|
||||
{
|
||||
|
||||
@@ -1156,7 +1156,8 @@ EXPORT_SYMBOL_GPL(iommu_add_device);
|
||||
*/
|
||||
static int
|
||||
spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain,
|
||||
struct device *dev)
|
||||
struct device *dev,
|
||||
struct iommu_domain *old)
|
||||
{
|
||||
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
|
||||
struct iommu_table_group *table_group;
|
||||
@@ -1189,7 +1190,7 @@ static struct iommu_domain spapr_tce_platform_domain = {
|
||||
|
||||
static int
|
||||
spapr_tce_blocked_iommu_attach_dev(struct iommu_domain *platform_domain,
|
||||
struct device *dev)
|
||||
struct device *dev, struct iommu_domain *old)
|
||||
{
|
||||
struct iommu_group *grp = iommu_group_get(dev);
|
||||
struct iommu_table_group *table_group;
|
||||
|
||||
@@ -5,7 +5,7 @@ config ARM_AMBA
|
||||
if ARM_AMBA
|
||||
|
||||
config TEGRA_AHB
|
||||
bool
|
||||
bool "Enable AHB driver for NVIDIA Tegra SoCs" if COMPILE_TEST
|
||||
default y if ARCH_TEGRA
|
||||
help
|
||||
Adds AHB configuration functionality for NVIDIA Tegra SoCs,
|
||||
|
||||
@@ -40,12 +40,13 @@ config IOMMU_IO_PGTABLE_LPAE
|
||||
sizes at both stage-1 and stage-2, as well as address spaces
|
||||
up to 48-bits in size.
|
||||
|
||||
config IOMMU_IO_PGTABLE_LPAE_SELFTEST
|
||||
bool "LPAE selftests"
|
||||
depends on IOMMU_IO_PGTABLE_LPAE
|
||||
config IOMMU_IO_PGTABLE_LPAE_KUNIT_TEST
|
||||
tristate "KUnit tests for LPAE"
|
||||
depends on IOMMU_IO_PGTABLE_LPAE && KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Enable self-tests for LPAE page table allocator. This performs
|
||||
a series of page-table consistency checks during boot.
|
||||
Enable kunit tests for LPAE page table allocator. This performs
|
||||
a series of page-table consistency checks.
|
||||
|
||||
If unsure, say N here.
|
||||
|
||||
@@ -247,7 +248,7 @@ config SUN50I_IOMMU
|
||||
|
||||
config TEGRA_IOMMU_SMMU
|
||||
bool "NVIDIA Tegra SMMU Support"
|
||||
depends on ARCH_TEGRA
|
||||
depends on ARCH_TEGRA || COMPILE_TEST
|
||||
depends on TEGRA_AHB
|
||||
depends on TEGRA_MC
|
||||
select IOMMU_API
|
||||
@@ -384,3 +385,5 @@ config SPRD_IOMMU
|
||||
Say Y here if you want to use the multimedia devices listed above.
|
||||
|
||||
endif # IOMMU_SUPPORT
|
||||
|
||||
source "drivers/iommu/generic_pt/Kconfig"
|
||||
|
||||
@@ -3,6 +3,7 @@ obj-y += arm/ iommufd/
|
||||
obj-$(CONFIG_AMD_IOMMU) += amd/
|
||||
obj-$(CONFIG_INTEL_IOMMU) += intel/
|
||||
obj-$(CONFIG_RISCV_IOMMU) += riscv/
|
||||
obj-$(CONFIG_GENERIC_PT) += generic_pt/fmt/
|
||||
obj-$(CONFIG_IOMMU_API) += iommu.o
|
||||
obj-$(CONFIG_IOMMU_SUPPORT) += iommu-pages.o
|
||||
obj-$(CONFIG_IOMMU_API) += iommu-traces.o
|
||||
@@ -12,6 +13,7 @@ obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
|
||||
obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
|
||||
obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
|
||||
obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
|
||||
obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE_KUNIT_TEST) += io-pgtable-arm-selftests.o
|
||||
obj-$(CONFIG_IOMMU_IO_PGTABLE_DART) += io-pgtable-dart.o
|
||||
obj-$(CONFIG_IOMMU_IOVA) += iova.o
|
||||
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
|
||||
|
||||
@@ -11,10 +11,13 @@ config AMD_IOMMU
|
||||
select MMU_NOTIFIER
|
||||
select IOMMU_API
|
||||
select IOMMU_IOVA
|
||||
select IOMMU_IO_PGTABLE
|
||||
select IOMMU_SVA
|
||||
select IOMMU_IOPF
|
||||
select IOMMUFD_DRIVER if IOMMUFD
|
||||
select GENERIC_PT
|
||||
select IOMMU_PT
|
||||
select IOMMU_PT_AMDV1
|
||||
select IOMMU_PT_X86_64
|
||||
depends on X86_64 && PCI && ACPI && HAVE_CMPXCHG_DOUBLE
|
||||
help
|
||||
With this option you can enable support for AMD IOMMU hardware in
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-y += iommu.o init.o quirks.o io_pgtable.o io_pgtable_v2.o ppr.o pasid.o
|
||||
obj-y += iommu.o init.o quirks.o ppr.o pasid.o
|
||||
obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += debugfs.o
|
||||
|
||||
@@ -88,7 +88,6 @@ int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag);
|
||||
* the IOMMU used by this driver.
|
||||
*/
|
||||
void amd_iommu_flush_all_caches(struct amd_iommu *iommu);
|
||||
void amd_iommu_update_and_flush_device_table(struct protection_domain *domain);
|
||||
void amd_iommu_domain_flush_pages(struct protection_domain *domain,
|
||||
u64 address, size_t size);
|
||||
void amd_iommu_dev_flush_pasid_pages(struct iommu_dev_data *dev_data,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/io-pgtable.h>
|
||||
#include <linux/generic_pt/iommu.h>
|
||||
|
||||
/*
|
||||
* Maximum number of IOMMUs supported
|
||||
@@ -247,6 +247,10 @@
|
||||
#define CMD_BUFFER_ENTRIES 512
|
||||
#define MMIO_CMD_SIZE_SHIFT 56
|
||||
#define MMIO_CMD_SIZE_512 (0x9ULL << MMIO_CMD_SIZE_SHIFT)
|
||||
#define MMIO_CMD_HEAD_MASK GENMASK_ULL(18, 4) /* Command buffer head ptr field [18:4] */
|
||||
#define MMIO_CMD_BUFFER_HEAD(x) FIELD_GET(MMIO_CMD_HEAD_MASK, (x))
|
||||
#define MMIO_CMD_TAIL_MASK GENMASK_ULL(18, 4) /* Command buffer tail ptr field [18:4] */
|
||||
#define MMIO_CMD_BUFFER_TAIL(x) FIELD_GET(MMIO_CMD_TAIL_MASK, (x))
|
||||
|
||||
/* constants for event buffer handling */
|
||||
#define EVT_BUFFER_SIZE 8192 /* 512 entries */
|
||||
@@ -337,76 +341,7 @@
|
||||
#define GUEST_PGTABLE_4_LEVEL 0x00
|
||||
#define GUEST_PGTABLE_5_LEVEL 0x01
|
||||
|
||||
#define PM_LEVEL_SHIFT(x) (12 + ((x) * 9))
|
||||
#define PM_LEVEL_SIZE(x) (((x) < 6) ? \
|
||||
((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
|
||||
(0xffffffffffffffffULL))
|
||||
#define PM_LEVEL_INDEX(x, a) (((a) >> PM_LEVEL_SHIFT((x))) & 0x1ffULL)
|
||||
#define PM_LEVEL_ENC(x) (((x) << 9) & 0xe00ULL)
|
||||
#define PM_LEVEL_PDE(x, a) ((a) | PM_LEVEL_ENC((x)) | \
|
||||
IOMMU_PTE_PR | IOMMU_PTE_IR | IOMMU_PTE_IW)
|
||||
#define PM_PTE_LEVEL(pte) (((pte) >> 9) & 0x7ULL)
|
||||
|
||||
#define PM_MAP_4k 0
|
||||
#define PM_ADDR_MASK 0x000ffffffffff000ULL
|
||||
#define PM_MAP_MASK(lvl) (PM_ADDR_MASK & \
|
||||
(~((1ULL << (12 + ((lvl) * 9))) - 1)))
|
||||
#define PM_ALIGNED(lvl, addr) ((PM_MAP_MASK(lvl) & (addr)) == (addr))
|
||||
|
||||
/*
|
||||
* Returns the page table level to use for a given page size
|
||||
* Pagesize is expected to be a power-of-two
|
||||
*/
|
||||
#define PAGE_SIZE_LEVEL(pagesize) \
|
||||
((__ffs(pagesize) - 12) / 9)
|
||||
/*
|
||||
* Returns the number of ptes to use for a given page size
|
||||
* Pagesize is expected to be a power-of-two
|
||||
*/
|
||||
#define PAGE_SIZE_PTE_COUNT(pagesize) \
|
||||
(1ULL << ((__ffs(pagesize) - 12) % 9))
|
||||
|
||||
/*
|
||||
* Aligns a given io-virtual address to a given page size
|
||||
* Pagesize is expected to be a power-of-two
|
||||
*/
|
||||
#define PAGE_SIZE_ALIGN(address, pagesize) \
|
||||
((address) & ~((pagesize) - 1))
|
||||
/*
|
||||
* Creates an IOMMU PTE for an address and a given pagesize
|
||||
* The PTE has no permission bits set
|
||||
* Pagesize is expected to be a power-of-two larger than 4096
|
||||
*/
|
||||
#define PAGE_SIZE_PTE(address, pagesize) \
|
||||
(((address) | ((pagesize) - 1)) & \
|
||||
(~(pagesize >> 1)) & PM_ADDR_MASK)
|
||||
|
||||
/*
|
||||
* Takes a PTE value with mode=0x07 and returns the page size it maps
|
||||
*/
|
||||
#define PTE_PAGE_SIZE(pte) \
|
||||
(1ULL << (1 + ffz(((pte) | 0xfffULL))))
|
||||
|
||||
/*
|
||||
* Takes a page-table level and returns the default page-size for this level
|
||||
*/
|
||||
#define PTE_LEVEL_PAGE_SIZE(level) \
|
||||
(1ULL << (12 + (9 * (level))))
|
||||
|
||||
/*
|
||||
* The IOPTE dirty bit
|
||||
*/
|
||||
#define IOMMU_PTE_HD_BIT (6)
|
||||
|
||||
/*
|
||||
* Bit value definition for I/O PTE fields
|
||||
*/
|
||||
#define IOMMU_PTE_PR BIT_ULL(0)
|
||||
#define IOMMU_PTE_HD BIT_ULL(IOMMU_PTE_HD_BIT)
|
||||
#define IOMMU_PTE_U BIT_ULL(59)
|
||||
#define IOMMU_PTE_FC BIT_ULL(60)
|
||||
#define IOMMU_PTE_IR BIT_ULL(61)
|
||||
#define IOMMU_PTE_IW BIT_ULL(62)
|
||||
|
||||
/*
|
||||
* Bit value definition for DTE fields
|
||||
@@ -436,12 +371,6 @@
|
||||
/* DTE[128:179] | DTE[184:191] */
|
||||
#define DTE_DATA2_INTR_MASK ~GENMASK_ULL(55, 52)
|
||||
|
||||
#define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
|
||||
#define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_PR)
|
||||
#define IOMMU_PTE_DIRTY(pte) ((pte) & IOMMU_PTE_HD)
|
||||
#define IOMMU_PTE_PAGE(pte) (iommu_phys_to_virt((pte) & IOMMU_PAGE_MASK))
|
||||
#define IOMMU_PTE_MODE(pte) (((pte) >> 9) & 0x07)
|
||||
|
||||
#define IOMMU_PROT_MASK 0x03
|
||||
#define IOMMU_PROT_IR 0x01
|
||||
#define IOMMU_PROT_IW 0x02
|
||||
@@ -534,19 +463,6 @@ struct amd_irte_ops;
|
||||
|
||||
#define AMD_IOMMU_FLAG_TRANS_PRE_ENABLED (1 << 0)
|
||||
|
||||
#define io_pgtable_to_data(x) \
|
||||
container_of((x), struct amd_io_pgtable, pgtbl)
|
||||
|
||||
#define io_pgtable_ops_to_data(x) \
|
||||
io_pgtable_to_data(io_pgtable_ops_to_pgtable(x))
|
||||
|
||||
#define io_pgtable_ops_to_domain(x) \
|
||||
container_of(io_pgtable_ops_to_data(x), \
|
||||
struct protection_domain, iop)
|
||||
|
||||
#define io_pgtable_cfg_to_data(x) \
|
||||
container_of((x), struct amd_io_pgtable, pgtbl.cfg)
|
||||
|
||||
struct gcr3_tbl_info {
|
||||
u64 *gcr3_tbl; /* Guest CR3 table */
|
||||
int glx; /* Number of levels for GCR3 table */
|
||||
@@ -554,14 +470,6 @@ struct gcr3_tbl_info {
|
||||
u16 domid; /* Per device domain ID */
|
||||
};
|
||||
|
||||
struct amd_io_pgtable {
|
||||
seqcount_t seqcount; /* Protects root/mode update */
|
||||
struct io_pgtable pgtbl;
|
||||
int mode;
|
||||
u64 *root;
|
||||
u64 *pgd; /* v2 pgtable pgd pointer */
|
||||
};
|
||||
|
||||
enum protection_domain_mode {
|
||||
PD_MODE_NONE,
|
||||
PD_MODE_V1,
|
||||
@@ -589,10 +497,13 @@ struct pdom_iommu_info {
|
||||
* independent of their use.
|
||||
*/
|
||||
struct protection_domain {
|
||||
union {
|
||||
struct iommu_domain domain;
|
||||
struct pt_iommu iommu;
|
||||
struct pt_iommu_amdv1 amdv1;
|
||||
struct pt_iommu_x86_64 amdv2;
|
||||
};
|
||||
struct list_head dev_list; /* List of all devices in this domain */
|
||||
struct iommu_domain domain; /* generic domain handle used by
|
||||
iommu core code */
|
||||
struct amd_io_pgtable iop;
|
||||
spinlock_t lock; /* mostly used to lock the page table*/
|
||||
u16 id; /* the domain id written to the device table */
|
||||
enum protection_domain_mode pd_mode; /* Track page table type */
|
||||
@@ -602,6 +513,9 @@ struct protection_domain {
|
||||
struct mmu_notifier mn; /* mmu notifier for the SVA domain */
|
||||
struct list_head dev_data_list; /* List of pdom_dev_data */
|
||||
};
|
||||
PT_IOMMU_CHECK_DOMAIN(struct protection_domain, iommu, domain);
|
||||
PT_IOMMU_CHECK_DOMAIN(struct protection_domain, amdv1.iommu, domain);
|
||||
PT_IOMMU_CHECK_DOMAIN(struct protection_domain, amdv2.iommu, domain);
|
||||
|
||||
/*
|
||||
* This structure contains information about one PCI segment in the system.
|
||||
|
||||
@@ -37,7 +37,7 @@ static ssize_t iommu_mmio_write(struct file *filp, const char __user *ubuf,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (iommu->dbg_mmio_offset > iommu->mmio_phys_end - 4) {
|
||||
if (iommu->dbg_mmio_offset > iommu->mmio_phys_end - sizeof(u64)) {
|
||||
iommu->dbg_mmio_offset = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1710,13 +1710,22 @@ static struct amd_iommu_pci_seg *__init alloc_pci_segment(u16 id,
|
||||
list_add_tail(&pci_seg->list, &amd_iommu_pci_seg_list);
|
||||
|
||||
if (alloc_dev_table(pci_seg))
|
||||
return NULL;
|
||||
goto err_free_pci_seg;
|
||||
if (alloc_alias_table(pci_seg))
|
||||
return NULL;
|
||||
goto err_free_dev_table;
|
||||
if (alloc_rlookup_table(pci_seg))
|
||||
return NULL;
|
||||
goto err_free_alias_table;
|
||||
|
||||
return pci_seg;
|
||||
|
||||
err_free_alias_table:
|
||||
free_alias_table(pci_seg);
|
||||
err_free_dev_table:
|
||||
free_dev_table(pci_seg);
|
||||
err_free_pci_seg:
|
||||
list_del(&pci_seg->list);
|
||||
kfree(pci_seg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct amd_iommu_pci_seg *__init get_pci_segment(u16 id,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user