Commit fa7431eb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'iommu-fixes-v7.1-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux

Pull iommu fixes from Joerg Roedel:
 "Core:
   - Cache-flushing fix for non-x86 platforms

  AMD-Vi:
   - Security fix when SEV-SNP is enabled
   - Operator precedence fix in DTE setting"

* tag 'iommu-fixes-v7.1-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux:
  iommu/amd: Fix precedence order in set_dte_passthrough()
  iommu/pages: Fix iommu_pages_flush_incoherent() for non-x86
  iommu/amd: Use maximum PPR log buffer size when SNP is enabled on Family 0x19
  iommu/amd: Use maximum Event log buffer size when SNP is enabled on Family 0x19
parents 917719c4 10161b4a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -11,6 +11,9 @@

#include "amd_iommu_types.h"

extern int amd_iommu_evtlog_size;
extern int amd_iommu_pprlog_size;

irqreturn_t amd_iommu_int_thread(int irq, void *data);
irqreturn_t amd_iommu_int_thread_evtlog(int irq, void *data);
irqreturn_t amd_iommu_int_thread_pprlog(int irq, void *data);
+13 −8
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/mutex.h>
#include <linux/msi.h>
#include <linux/list.h>
#include <linux/sizes.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/iommufd.h>
@@ -141,7 +142,6 @@
#define MMIO_STATUS_GALOG_INT_MASK		BIT(10)

/* event logging constants */
#define EVENT_ENTRY_SIZE	0x10
#define EVENT_TYPE_SHIFT	28
#define EVENT_TYPE_MASK		0xf
#define EVENT_TYPE_ILL_DEV	0x1
@@ -259,15 +259,20 @@
#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 */
#define EVT_LEN_MASK		(0x9ULL << 56)
#define EVTLOG_ENTRY_SIZE	0x10
#define EVTLOG_SIZE_SHIFT	56
#define EVTLOG_SIZE_DEF		SZ_8K /* 512 entries */
#define EVTLOG_LEN_MASK_DEF	(0x9ULL << EVTLOG_SIZE_SHIFT)
#define EVTLOG_SIZE_MAX		SZ_512K /* 32K entries */
#define EVTLOG_LEN_MASK_MAX	(0xFULL << EVTLOG_SIZE_SHIFT)

/* Constants for PPR Log handling */
#define PPR_LOG_ENTRIES		512
#define PPR_LOG_SIZE_SHIFT	56
#define PPR_LOG_SIZE_512	(0x9ULL << PPR_LOG_SIZE_SHIFT)
#define PPR_ENTRY_SIZE		16
#define PPR_LOG_SIZE		(PPR_ENTRY_SIZE * PPR_LOG_ENTRIES)
#define PPRLOG_ENTRY_SIZE	0x10
#define PPRLOG_SIZE_SHIFT	56
#define PPRLOG_SIZE_DEF		SZ_8K	/* 512 entries */
#define PPRLOG_LEN_MASK_DEF	(0x9ULL << PPRLOG_SIZE_SHIFT)
#define PPRLOG_SIZE_MAX		SZ_512K	/* 32K entries */
#define PPRLOG_LEN_MASK_MAX	(0xFULL << PPRLOG_SIZE_SHIFT)

/* PAGE_SERVICE_REQUEST PPR Log Buffer Entry flags */
#define PPR_FLAG_EXEC		0x002	/* Execute permission requested */
+88 −35
Original line number Diff line number Diff line
@@ -132,6 +132,9 @@ struct ivhd_entry {
	u8 uid;
} __attribute__((packed));

int amd_iommu_evtlog_size = EVTLOG_SIZE_DEF;
int amd_iommu_pprlog_size = PPRLOG_SIZE_DEF;

/*
 * An AMD IOMMU memory definition structure. It defines things like exclusion
 * ranges for devices and regions that should be unity mapped.
@@ -865,18 +868,26 @@ void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu, gfp_t gfp,
}

/* allocates the memory where the IOMMU will log its events to */
static int __init alloc_event_buffer(struct amd_iommu *iommu)
static int __init alloc_event_buffer(void)
{
	struct amd_iommu *iommu;

	for_each_iommu(iommu) {
		iommu->evt_buf = iommu_alloc_4k_pages(iommu, GFP_KERNEL,
					      EVT_BUFFER_SIZE);
						      amd_iommu_evtlog_size);
		if (!iommu->evt_buf)
			return -ENOMEM;
	}

	return iommu->evt_buf ? 0 : -ENOMEM;
	return 0;
}

static void iommu_enable_event_buffer(struct amd_iommu *iommu)
static void iommu_enable_event_buffer(void)
{
	struct amd_iommu *iommu;
	u64 entry;

	for_each_iommu(iommu) {
		BUG_ON(iommu->evt_buf == NULL);

		if (!is_kdump_kernel()) {
@@ -884,7 +895,10 @@ static void iommu_enable_event_buffer(struct amd_iommu *iommu)
			 * Event buffer is re-used for kdump kernel and setting
			 * of MMIO register is not required.
			 */
		entry = iommu_virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK;
			entry = iommu_virt_to_phys(iommu->evt_buf);
			entry |= (amd_iommu_evtlog_size == EVTLOG_SIZE_DEF) ?
				EVTLOG_LEN_MASK_DEF : EVTLOG_LEN_MASK_MAX;

			memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET,
				    &entry, sizeof(entry));
		}
@@ -895,6 +909,7 @@ static void iommu_enable_event_buffer(struct amd_iommu *iommu)

		iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
	}
}

/*
 * This function disables the event log buffer
@@ -984,15 +999,20 @@ static int __init alloc_cwwb_sem(struct amd_iommu *iommu)
	return 0;
}

static int __init remap_event_buffer(struct amd_iommu *iommu)
static int __init remap_event_buffer(void)
{
	struct amd_iommu *iommu;
	u64 paddr;

	pr_info_once("Re-using event buffer from the previous kernel\n");
	for_each_iommu(iommu) {
		paddr = readq(iommu->mmio_base + MMIO_EVT_BUF_OFFSET) & PM_ADDR_MASK;
	iommu->evt_buf = iommu_memremap(paddr, EVT_BUFFER_SIZE);
		iommu->evt_buf = iommu_memremap(paddr, amd_iommu_evtlog_size);
		if (!iommu->evt_buf)
			return -ENOMEM;
	}

	return iommu->evt_buf ? 0 : -ENOMEM;
	return 0;
}

static int __init remap_command_buffer(struct amd_iommu *iommu)
@@ -1044,10 +1064,6 @@ static int __init alloc_iommu_buffers(struct amd_iommu *iommu)
		ret = remap_command_buffer(iommu);
		if (ret)
			return ret;

		ret = remap_event_buffer(iommu);
		if (ret)
			return ret;
	} else {
		ret = alloc_cwwb_sem(iommu);
		if (ret)
@@ -1056,10 +1072,6 @@ static int __init alloc_iommu_buffers(struct amd_iommu *iommu)
		ret = alloc_command_buffer(iommu);
		if (ret)
			return ret;

		ret = alloc_event_buffer(iommu);
		if (ret)
			return ret;
	}

	return 0;
@@ -2893,7 +2905,6 @@ static void early_enable_iommu(struct amd_iommu *iommu)
	iommu_init_flags(iommu);
	iommu_set_device_table(iommu);
	iommu_enable_command_buffer(iommu);
	iommu_enable_event_buffer(iommu);
	iommu_set_exclusion_range(iommu);
	iommu_enable_gt(iommu);
	iommu_enable_ga(iommu);
@@ -2957,7 +2968,6 @@ static void early_enable_iommus(void)
			iommu_disable_event_buffer(iommu);
			iommu_disable_irtcachedis(iommu);
			iommu_enable_command_buffer(iommu);
			iommu_enable_event_buffer(iommu);
			iommu_enable_ga(iommu);
			iommu_enable_xt(iommu);
			iommu_enable_irtcachedis(iommu);
@@ -3070,6 +3080,7 @@ static void amd_iommu_resume(void *data)
	for_each_iommu(iommu)
		early_enable_iommu(iommu);

	iommu_enable_event_buffer();
	amd_iommu_enable_interrupts();
}

@@ -3399,6 +3410,33 @@ static __init void iommu_snp_enable(void)
#endif
}

static void amd_iommu_apply_erratum_snp(void)
{
#ifdef CONFIG_KVM_AMD_SEV
	if (!amd_iommu_snp_en)
		return;

	/* Errata fix for Family 0x19 */
	if (boot_cpu_data.x86 != 0x19)
		return;

	/* Set event log buffer size to max */
	amd_iommu_evtlog_size = EVTLOG_SIZE_MAX;
	pr_info("Applying erratum: Increase Event log size to 0x%x\n",
		amd_iommu_evtlog_size);

	/*
	 * Set PPR log buffer size to max.
	 * (Family 0x19, model < 0x10 doesn't support PPR when SNP is enabled).
	 */
	if (boot_cpu_data.x86_model >= 0x10) {
		amd_iommu_pprlog_size = PPRLOG_SIZE_MAX;
		pr_info("Applying erratum: Increase PPR log size to 0x%x\n",
			amd_iommu_pprlog_size);
	}
#endif
}

/****************************************************************************
 *
 * AMD IOMMU Initialization State Machine
@@ -3435,6 +3473,21 @@ static int __init state_next(void)
	case IOMMU_ENABLED:
		register_syscore(&amd_iommu_syscore);
		iommu_snp_enable();

		amd_iommu_apply_erratum_snp();

		/* Allocate/enable event log buffer */
		if (is_kdump_kernel())
			ret = remap_event_buffer();
		else
			ret = alloc_event_buffer();

		if (ret) {
			init_state = IOMMU_INIT_ERROR;
			break;
		}
		iommu_enable_event_buffer();

		ret = amd_iommu_init_pci();
		init_state = ret ? IOMMU_INIT_ERROR : IOMMU_PCI_INIT;
		break;
@@ -4037,11 +4090,11 @@ int amd_iommu_snp_disable(void)
		return 0;

	for_each_iommu(iommu) {
		ret = iommu_make_shared(iommu->evt_buf, EVT_BUFFER_SIZE);
		ret = iommu_make_shared(iommu->evt_buf, amd_iommu_evtlog_size);
		if (ret)
			return ret;

		ret = iommu_make_shared(iommu->ppr_log, PPR_LOG_SIZE);
		ret = iommu_make_shared(iommu->ppr_log, amd_iommu_pprlog_size);
		if (ret)
			return ret;

+3 −2
Original line number Diff line number Diff line
@@ -1010,7 +1010,7 @@ static void iommu_poll_events(struct amd_iommu *iommu)
		iommu_print_event(iommu, iommu->evt_buf + head);

		/* Update head pointer of hardware ring-buffer */
		head = (head + EVENT_ENTRY_SIZE) % EVT_BUFFER_SIZE;
		head = (head + EVTLOG_ENTRY_SIZE) % amd_iommu_evtlog_size;
		writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
	}

@@ -2149,7 +2149,8 @@ static void set_dte_passthrough(struct iommu_dev_data *dev_data,
	new->data[0] |= DTE_FLAG_TV | DTE_FLAG_IR | DTE_FLAG_IW;

	new->data[1] |= FIELD_PREP(DTE_DOMID_MASK, domain->id) |
			(dev_data->ats_enabled) ? DTE_FLAG_IOTLB : 0;
			(dev_data->ats_enabled ? DTE_FLAG_IOTLB : 0);

}

static void set_dte_entry(struct amd_iommu *iommu,
+5 −3
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
int __init amd_iommu_alloc_ppr_log(struct amd_iommu *iommu)
{
	iommu->ppr_log = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO,
					      PPR_LOG_SIZE);
					      amd_iommu_pprlog_size);
	return iommu->ppr_log ? 0 : -ENOMEM;
}

@@ -33,7 +33,9 @@ void amd_iommu_enable_ppr_log(struct amd_iommu *iommu)

	iommu_feature_enable(iommu, CONTROL_PPR_EN);

	entry = iommu_virt_to_phys(iommu->ppr_log) | PPR_LOG_SIZE_512;
	entry = iommu_virt_to_phys(iommu->ppr_log);
	entry |= (amd_iommu_pprlog_size == PPRLOG_SIZE_DEF) ?
			PPRLOG_LEN_MASK_DEF : PPRLOG_LEN_MASK_MAX;

	memcpy_toio(iommu->mmio_base + MMIO_PPR_LOG_OFFSET,
		    &entry, sizeof(entry));
@@ -201,7 +203,7 @@ void amd_iommu_poll_ppr_log(struct amd_iommu *iommu)
			raw[0] = raw[1] = 0UL;

		/* Update head pointer of hardware ring-buffer */
		head = (head + PPR_ENTRY_SIZE) % PPR_LOG_SIZE;
		head = (head + PPRLOG_ENTRY_SIZE) % amd_iommu_pprlog_size;
		writel(head, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);

		/* Handle PPR entry */
Loading