Commit e4f79000 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull powerpc fixes from Michael Ellerman:

 - Fix IOMMU table initialisation when doing kdump over SR-IOV

 - Fix incorrect RTAS function name for resetting TCE tables

 - Fix fpu_signal selftest failures since a recent change

Thanks to Gaurav Batra and Nathan Lynch.

* tag 'powerpc-6.8-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  selftests/powerpc: Fix fpu_signal failures
  powerpc/rtas: use correct function name for resetting TCE tables
  powerpc/pseries/iommu: IOMMU table is not initialized for kdump over SR-IOV
parents 73d35f83 380cb2f4
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ enum rtas_function_index {
	RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE,
	RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE2,
	RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW,
	RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOWS,
	RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOW,
	RTAS_FNIDX__IBM_SCAN_LOG_DUMP,
	RTAS_FNIDX__IBM_SET_DYNAMIC_INDICATOR,
	RTAS_FNIDX__IBM_SET_EEH_OPTION,
@@ -164,7 +164,7 @@ typedef struct {
#define RTAS_FN_IBM_READ_SLOT_RESET_STATE         rtas_fn_handle(RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE)
#define RTAS_FN_IBM_READ_SLOT_RESET_STATE2        rtas_fn_handle(RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE2)
#define RTAS_FN_IBM_REMOVE_PE_DMA_WINDOW          rtas_fn_handle(RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW)
#define RTAS_FN_IBM_RESET_PE_DMA_WINDOWS          rtas_fn_handle(RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOWS)
#define RTAS_FN_IBM_RESET_PE_DMA_WINDOW           rtas_fn_handle(RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOW)
#define RTAS_FN_IBM_SCAN_LOG_DUMP                 rtas_fn_handle(RTAS_FNIDX__IBM_SCAN_LOG_DUMP)
#define RTAS_FN_IBM_SET_DYNAMIC_INDICATOR         rtas_fn_handle(RTAS_FNIDX__IBM_SET_DYNAMIC_INDICATOR)
#define RTAS_FN_IBM_SET_EEH_OPTION                rtas_fn_handle(RTAS_FNIDX__IBM_SET_EEH_OPTION)
+7 −2
Original line number Diff line number Diff line
@@ -375,8 +375,13 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
	[RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW] = {
		.name = "ibm,remove-pe-dma-window",
	},
	[RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOWS] = {
		.name = "ibm,reset-pe-dma-windows",
	[RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOW] = {
		/*
		 * Note: PAPR+ v2.13 7.3.31.4.1 spells this as
		 * "ibm,reset-pe-dma-windows" (plural), but RTAS
		 * implementations use the singular form in practice.
		 */
		.name = "ibm,reset-pe-dma-window",
	},
	[RTAS_FNIDX__IBM_SCAN_LOG_DUMP] = {
		.name = "ibm,scan-log-dump",
+105 −51
Original line number Diff line number Diff line
@@ -574,29 +574,6 @@ static void iommu_table_setparms(struct pci_controller *phb,

struct iommu_table_ops iommu_table_lpar_multi_ops;

/*
 * iommu_table_setparms_lpar
 *
 * Function: On pSeries LPAR systems, return TCE table info, given a pci bus.
 */
static void iommu_table_setparms_lpar(struct pci_controller *phb,
				      struct device_node *dn,
				      struct iommu_table *tbl,
				      struct iommu_table_group *table_group,
				      const __be32 *dma_window)
{
	unsigned long offset, size, liobn;

	of_parse_dma_window(dn, dma_window, &liobn, &offset, &size);

	iommu_table_setparms_common(tbl, phb->bus->number, liobn, offset, size, IOMMU_PAGE_SHIFT_4K, NULL,
				    &iommu_table_lpar_multi_ops);


	table_group->tce32_start = offset;
	table_group->tce32_size = size;
}

struct iommu_table_ops iommu_table_pseries_ops = {
	.set = tce_build_pSeries,
	.clear = tce_free_pSeries,
@@ -724,26 +701,71 @@ struct iommu_table_ops iommu_table_lpar_multi_ops = {
 * dynamic 64bit DMA window, walking up the device tree.
 */
static struct device_node *pci_dma_find(struct device_node *dn,
					const __be32 **dma_window)
					struct dynamic_dma_window_prop *prop)
{
	const __be32 *dw = NULL;
	const __be32 *default_prop = NULL;
	const __be32 *ddw_prop = NULL;
	struct device_node *rdn = NULL;
	bool default_win = false, ddw_win = false;

	for ( ; dn && PCI_DN(dn); dn = dn->parent) {
		dw = of_get_property(dn, "ibm,dma-window", NULL);
		if (dw) {
			if (dma_window)
				*dma_window = dw;
			return dn;
		default_prop = of_get_property(dn, "ibm,dma-window", NULL);
		if (default_prop) {
			rdn = dn;
			default_win = true;
		}
		ddw_prop = of_get_property(dn, DIRECT64_PROPNAME, NULL);
		if (ddw_prop) {
			rdn = dn;
			ddw_win = true;
			break;
		}
		ddw_prop = of_get_property(dn, DMA64_PROPNAME, NULL);
		if (ddw_prop) {
			rdn = dn;
			ddw_win = true;
			break;
		}
		dw = of_get_property(dn, DIRECT64_PROPNAME, NULL);
		if (dw)
			return dn;
		dw = of_get_property(dn, DMA64_PROPNAME, NULL);
		if (dw)
			return dn;

		/* At least found default window, which is the case for normal boot */
		if (default_win)
			break;
	}

	return NULL;
	/* For PCI devices there will always be a DMA window, either on the device
	 * or parent bus
	 */
	WARN_ON(!(default_win | ddw_win));

	/* caller doesn't want to get DMA window property */
	if (!prop)
		return rdn;

	/* parse DMA window property. During normal system boot, only default
	 * DMA window is passed in OF. But, for kdump, a dedicated adapter might
	 * have both default and DDW in FDT. In this scenario, DDW takes precedence
	 * over default window.
	 */
	if (ddw_win) {
		struct dynamic_dma_window_prop *p;

		p = (struct dynamic_dma_window_prop *)ddw_prop;
		prop->liobn = p->liobn;
		prop->dma_base = p->dma_base;
		prop->tce_shift = p->tce_shift;
		prop->window_shift = p->window_shift;
	} else if (default_win) {
		unsigned long offset, size, liobn;

		of_parse_dma_window(rdn, default_prop, &liobn, &offset, &size);

		prop->liobn = cpu_to_be32((u32)liobn);
		prop->dma_base = cpu_to_be64(offset);
		prop->tce_shift = cpu_to_be32(IOMMU_PAGE_SHIFT_4K);
		prop->window_shift = cpu_to_be32(order_base_2(size));
	}

	return rdn;
}

static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
@@ -751,17 +773,20 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
	struct iommu_table *tbl;
	struct device_node *dn, *pdn;
	struct pci_dn *ppci;
	const __be32 *dma_window = NULL;
	struct dynamic_dma_window_prop prop;

	dn = pci_bus_to_OF_node(bus);

	pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %pOF\n",
		 dn);

	pdn = pci_dma_find(dn, &dma_window);
	pdn = pci_dma_find(dn, &prop);

	if (dma_window == NULL)
		pr_debug("  no ibm,dma-window property !\n");
	/* In PPC architecture, there will always be DMA window on bus or one of the
	 * parent bus. During reboot, there will be ibm,dma-window property to
	 * define DMA window. For kdump, there will at least be default window or DDW
	 * or both.
	 */

	ppci = PCI_DN(pdn);

@@ -771,13 +796,24 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
	if (!ppci->table_group) {
		ppci->table_group = iommu_pseries_alloc_group(ppci->phb->node);
		tbl = ppci->table_group->tables[0];
		if (dma_window) {
			iommu_table_setparms_lpar(ppci->phb, pdn, tbl,
						  ppci->table_group, dma_window);

		iommu_table_setparms_common(tbl, ppci->phb->bus->number,
				be32_to_cpu(prop.liobn),
				be64_to_cpu(prop.dma_base),
				1ULL << be32_to_cpu(prop.window_shift),
				be32_to_cpu(prop.tce_shift), NULL,
				&iommu_table_lpar_multi_ops);

		/* Only for normal boot with default window. Doesn't matter even
		 * if we set these with DDW which is 64bit during kdump, since
		 * these will not be used during kdump.
		 */
		ppci->table_group->tce32_start = be64_to_cpu(prop.dma_base);
		ppci->table_group->tce32_size = 1 << be32_to_cpu(prop.window_shift);

		if (!iommu_init_table(tbl, ppci->phb->node, 0, 0))
			panic("Failed to initialize iommu table");
		}

		iommu_register_group(ppci->table_group,
				pci_domain_nr(bus), 0);
		pr_debug("  created table: %p\n", ppci->table_group);
@@ -968,6 +1004,12 @@ static void find_existing_ddw_windows_named(const char *name)
			continue;
		}

		/* If at the time of system initialization, there are DDWs in OF,
		 * it means this is during kexec. DDW could be direct or dynamic.
		 * We will just mark DDWs as "dynamic" since this is kdump path,
		 * no need to worry about perforance. ddw_list_new_entry() will
		 * set window->direct = false.
		 */
		window = ddw_list_new_entry(pdn, dma64);
		if (!window) {
			of_node_put(pdn);
@@ -1524,8 +1566,8 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
{
	struct device_node *pdn, *dn;
	struct iommu_table *tbl;
	const __be32 *dma_window = NULL;
	struct pci_dn *pci;
	struct dynamic_dma_window_prop prop;

	pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));

@@ -1538,7 +1580,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
	dn = pci_device_to_OF_node(dev);
	pr_debug("  node is %pOF\n", dn);

	pdn = pci_dma_find(dn, &dma_window);
	pdn = pci_dma_find(dn, &prop);
	if (!pdn || !PCI_DN(pdn)) {
		printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
		       "no DMA window found for pci dev=%s dn=%pOF\n",
@@ -1551,8 +1593,20 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
	if (!pci->table_group) {
		pci->table_group = iommu_pseries_alloc_group(pci->phb->node);
		tbl = pci->table_group->tables[0];
		iommu_table_setparms_lpar(pci->phb, pdn, tbl,
				pci->table_group, dma_window);

		iommu_table_setparms_common(tbl, pci->phb->bus->number,
				be32_to_cpu(prop.liobn),
				be64_to_cpu(prop.dma_base),
				1ULL << be32_to_cpu(prop.window_shift),
				be32_to_cpu(prop.tce_shift), NULL,
				&iommu_table_lpar_multi_ops);

		/* Only for normal boot with default window. Doesn't matter even
		 * if we set these with DDW which is 64bit during kdump, since
		 * these will not be used during kdump.
		 */
		pci->table_group->tce32_start = be64_to_cpu(prop.dma_base);
		pci->table_group->tce32_size = 1 << be32_to_cpu(prop.window_shift);

		iommu_init_table(tbl, pci->phb->node, 0, 0);
		iommu_register_group(pci->table_group,
+6 −10
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <pthread.h>

#include "utils.h"
#include "fpu.h"

/* Number of times each thread should receive the signal */
#define ITERATIONS 10
@@ -27,9 +28,7 @@
 */
#define THREAD_FACTOR 8

__thread double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
		     1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
		     2.1};
__thread double darray[32];

bool bad_context;
int threads_starting;
@@ -43,9 +42,9 @@ void signal_fpu_sig(int sig, siginfo_t *info, void *context)
	ucontext_t *uc = context;
	mcontext_t *mc = &uc->uc_mcontext;

	/* Only the non volatiles were loaded up */
	for (i = 14; i < 32; i++) {
		if (mc->fp_regs[i] != darray[i - 14]) {
	// Don't check f30/f31, they're used as scratches in check_all_fprs()
	for (i = 0; i < 30; i++) {
		if (mc->fp_regs[i] != darray[i]) {
			bad_context = true;
			break;
		}
@@ -54,7 +53,6 @@ void signal_fpu_sig(int sig, siginfo_t *info, void *context)

void *signal_fpu_c(void *p)
{
	int i;
	long rc;
	struct sigaction act;
	act.sa_sigaction = signal_fpu_sig;
@@ -64,9 +62,7 @@ void *signal_fpu_c(void *p)
		return p;

	srand(pthread_self());
	for (i = 0; i < 21; i++)
		darray[i] = rand();

	randomise_darray(darray, ARRAY_SIZE(darray));
	rc = preempt_fpu(darray, &threads_starting, &running);

	return (void *) rc;