Inter-revision diff: patch 10

Comparing v8 (message) to rfc (message)

--- v8
+++ vrfc
@@ -1,231 +1,237 @@
-Define interfaces (wrappers) to the 'copy' and 'paste' instructions
-(which are new in PowerISA 3.0). These are intended to be used to
-by NX driver(s) to submit Coprocessor Request Blocks (CRBs) to the
-NX hardware engines.
+The VAS hardware requires kernel to setup a "fault window" to which
+the hardware will paste a CRB in case of address translation faults.
+
+Create a fault window (which is basically a special receive window)
+and a kernel thread that processes the CRBs that arrive at the fault
+window.  A follow-on patch will implement IRQ handling and the
+interrupt handler will wake up the fault thread.
+
+The fault window and thread will be used when we support user-space
+access to the VAS/NX hardware. For now the fault window thread simply
+dumps/logs the CRB and the fault isolation registers. Including these
+in this RFC patchset for review/comments.
 
 Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
-
 ---
-Changelog[v8]:
-	- [Michael Ellerman] Drop vas_initialized() check; cleanup asm code,
-	  reuse existing macros, fix old references; add cr0 to clobbers
-
-Changelog[v4]
-	- Export symbols
-Changelog[v3]
-	- Map raw CR value from paste instruction into an error code.
-
-Conflicts:
-	arch/powerpc/platforms/powernv/vas.h
----
- MAINTAINERS                                 |  1 +
- arch/powerpc/include/asm/ppc-opcode.h       |  2 ++
- arch/powerpc/include/asm/vas.h              | 12 ++++++++
- arch/powerpc/platforms/powernv/copy-paste.h | 46 ++++++++++++++++++++++++++++
- arch/powerpc/platforms/powernv/vas-window.c | 47 +++++++++++++++++++++++++++++
- arch/powerpc/platforms/powernv/vas.h        | 18 +++++++++--
- 6 files changed, 124 insertions(+), 2 deletions(-)
- create mode 100644 arch/powerpc/platforms/powernv/copy-paste.h
-
-diff --git a/MAINTAINERS b/MAINTAINERS
-index ec68732..624c67a 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -6442,6 +6442,7 @@ M:	Sukadev Bhattiprolu
- L:	linuxppc-dev@lists.ozlabs.org
- S:	Supported
- F:	arch/powerpc/platforms/powernv/vas*
-+F:	arch/powerpc/platforms/powernv/copy-paste.h
- F:	arch/powerpc/include/asm/vas.h
- F:	arch/powerpc/include/uapi/asm/vas.h
- 
-diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
-index fa9ebae..749336d 100644
---- a/arch/powerpc/include/asm/ppc-opcode.h
-+++ b/arch/powerpc/include/asm/ppc-opcode.h
-@@ -414,6 +414,8 @@
- 					___PPC_RB(b))
- #define PPC_MSGCLRP(b)		stringify_in_c(.long PPC_INST_MSGCLRP | \
- 					___PPC_RB(b))
-+#define PPC_PASTE(a, b)		stringify_in_c(.long PPC_INST_PASTE | \
-+					___PPC_RA(a) | ___PPC_RB(b))
- #define PPC_POPCNTB(a, s)	stringify_in_c(.long PPC_INST_POPCNTB | \
- 					__PPC_RA(a) | __PPC_RS(s))
- #define PPC_POPCNTD(a, s)	stringify_in_c(.long PPC_INST_POPCNTD | \
-diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
-index efbdde5..dfc97f5 100644
---- a/arch/powerpc/include/asm/vas.h
-+++ b/arch/powerpc/include/asm/vas.h
-@@ -145,4 +145,16 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
+ drivers/misc/vas/vas-internal.h |   1 +
+ drivers/misc/vas/vas.c          | 157 +++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 157 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/misc/vas/vas-internal.h b/drivers/misc/vas/vas-internal.h
+index a58ffb2..e3ceb74 100644
+--- a/drivers/misc/vas/vas-internal.h
++++ b/drivers/misc/vas/vas-internal.h
+@@ -366,6 +366,7 @@ extern int vas_initialized;
+ 
+ extern int vas_window_reset(struct vas_instance *vinst, int winid);
+ extern struct vas_instance *find_vas_instance(int node, int chip);
++extern void vas_wakeup_fault_win_thread(void);
+ 
+ /*
+  * VREG(x):
+diff --git a/drivers/misc/vas/vas.c b/drivers/misc/vas/vas.c
+index 785e7a1..448d7f9 100644
+--- a/drivers/misc/vas/vas.c
++++ b/drivers/misc/vas/vas.c
+@@ -12,15 +12,29 @@
+ #include <linux/export.h>
+ #include <linux/types.h>
+ #include <linux/slab.h>
++#include <linux/kthread.h>
+ #include <linux/io.h>
+ #include <asm/vas.h>
+ #include "vas-internal.h"
+ #include <asm/opal-api.h>
+ #include <asm/opal.h>
+ 
++#define VAS_FAULT_WIN_FIFO_SIZE		(64 << 10)
++#define VAS_FAULT_WIN_WCREDS		64
++
+ int vas_initialized;
+ struct vas_instance *vas_instances;
+ 
++struct fault_win_thread_arg {
++	int notified;
++	wait_queue_head_t wq;
++	void *rx_fifo;
++	int rx_fifo_size;
++} fwta;
++
++struct task_struct *fwt_thr;		/* Fault window thread */
++struct vas_window *fault_win;
++
+ /*
+  * Read the Fault Isolation Registers (FIR) from skiboot into @fir.
   */
- int vas_win_close(struct vas_window *win);
- 
+@@ -56,6 +70,135 @@ void vas_print_regs(int chip)
+ 	}
+ }
+ 
++void vas_wakeup_fault_win_thread(void)
++{
++	fwta.notified = 1;
++	wake_up(&fwta.wq);
++}
++
 +/*
-+ * Copy the co-processor request block (CRB) @crb into the local L2 cache.
++ * Process a CRB that we receive on the fault window.
++ *
++ * TODO: Since we only support in-kernel compression requests for now,
++ *	 we should not get a fault. If we do, dump the CRB and the FIR
++ *	 and return - VAS may enter a checkstop :-(
 + */
-+extern int vas_copy_crb(void *crb, int offset);
-+
-+/*
-+ * Paste a previously copied CRB (see vas_copy_crb()) from the L2 cache to
-+ * the hardware address associated with the window @win. @re is expected/
-+ * assumed to be true for NX windows.
-+ */
-+extern int vas_paste_crb(struct vas_window *win, int offset, bool re);
-+
- #endif /* _MISC_VAS_H */
-diff --git a/arch/powerpc/platforms/powernv/copy-paste.h b/arch/powerpc/platforms/powernv/copy-paste.h
-new file mode 100644
-index 0000000..c9a5036
---- /dev/null
-+++ b/arch/powerpc/platforms/powernv/copy-paste.h
-@@ -0,0 +1,46 @@
-+/*
-+ * Copyright 2016-17 IBM Corp.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+#include <asm/ppc-opcode.h>
-+
-+#define CR0_SHIFT	28
-+#define CR0_MASK	0xF
-+/*
-+ * Copy/paste instructions:
-+ *
-+ *	copy RA,RB
-+ *		Copy contents of address (RA) + effective_address(RB)
-+ *		to internal copy-buffer.
-+ *
-+ *	paste RA,RB
-+ *		Paste contents of internal copy-buffer to the address
-+ *		(RA) + effective_address(RB)
-+ */
-+static inline int vas_copy(void *crb, int offset)
-+{
-+	asm volatile(PPC_COPY(%0, %1)";"
-+		:
-+		: "b" (offset), "b" (crb)
-+		: "memory");
++static void process_fault_crb(struct fault_win_thread_arg *fwt)
++{
++	u64 buf[16];
++
++	/* TODO: Dump FIRs for all chips for now. We should detect the
++	 *	 current chip id and dump only for that chip?
++	 */
++	vas_print_regs(-1);
++
++	memcpy(buf, fwt->rx_fifo, sizeof(buf));
++	memset(fwt->rx_fifo, 0, sizeof(buf));
++	pr_debug("VAS: FaultWin Rx-fifo: 0x%llx 0x%llx 0x%llx 0x%llx\n",
++				buf[0], buf[1], buf[2], buf[3]);
++}
++
++static int fault_win_thread(void *arg)
++{
++	struct fault_win_thread_arg *fwta = arg;
++
++	do {
++		if (signal_pending(current))
++			flush_signals(current);
++
++		fwta->notified = 0;
++		wait_event_interruptible(fwta->wq, fwta->notified ||
++				kthread_should_stop());
++
++		process_fault_crb(fwta);
++
++	} while (!kthread_should_stop());
 +
 +	return 0;
 +}
 +
-+static inline int vas_paste(void *paste_address, int offset)
-+{
-+	u32 cr;
-+
-+	cr = 0;
-+	asm volatile(PPC_PASTE(%1, %2)";"
-+		"mfocrf %0, 0x80;"
-+		: "=r" (cr)
-+		: "b" (offset), "b" (paste_address)
-+		: "memory", "cr0");
-+
-+	return (cr >> CR0_SHIFT) & CR0_MASK;
-+}
-diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
-index cd12e44..b02f26d 100644
---- a/arch/powerpc/platforms/powernv/vas-window.c
-+++ b/arch/powerpc/platforms/powernv/vas-window.c
-@@ -18,6 +18,7 @@
- #include <linux/cred.h>
- 
- #include "vas.h"
-+#include "copy-paste.h"
- 
- /*
-  * Compute the paste address region for the window @window using the
-@@ -997,6 +998,52 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
++static int create_fault_win(void)
++{
++	char *name = "VAS-FaultWin-Thread";
++	struct vas_rx_win_attr attr;
++
++	init_waitqueue_head(&fwta.wq);
++	fwta.notified = 0;
++	fwta.rx_fifo_size = VAS_FAULT_WIN_FIFO_SIZE;
++	fwta.rx_fifo = kmalloc(fwta.rx_fifo_size, GFP_KERNEL);
++	if (!fwta.rx_fifo) {
++		pr_err("VAS: Unable to alloc %d bytes for rx_fifo\n",
++				fwta.rx_fifo_size);
++		return -1;
++	}
++
++	/*
++	 * Create a worker thread that processes the fault CRBs.
++	 */
++	fwt_thr = kthread_create_on_node(fault_win_thread, &fwta, 0, name, 0);
++	if (IS_ERR(fwt_thr))
++		goto free_mem;
++
++	memset(&attr, 0, sizeof(attr));
++	attr.rx_fifo_size = fwta.rx_fifo_size;
++	attr.rx_fifo = fwta.rx_fifo;
++
++	attr.wcreds_max = VAS_FAULT_WIN_WCREDS;
++	attr.tc_mode = VAS_THRESH_DISABLED;
++	attr.pin_win = true;
++	attr.tx_win_ord_mode = true;
++	attr.rx_win_ord_mode = true;
++	attr.fault_win = true;
++
++	/*
++	 * 3.1.4.32: Local Notification Control Register. notify_disable is
++	 * true and interrupt disable is false for Fault windows
++	 */
++	attr.notify_disable = true;
++
++	attr.lnotify_lpid = 0;
++	attr.lnotify_pid = task_pid_nr(fwt_thr);
++	attr.lnotify_tid = task_pid_nr(fwt_thr);
++
++	fault_win = vas_rx_win_open(0, 0, VAS_COP_TYPE_FAULT, &attr);
++	if (IS_ERR(fault_win)) {
++		pr_err("VAS: Error %ld opening fault window\n",
++					PTR_ERR(fault_win));
++		goto stop_thread;
++	}
++
++	/*
++	 * Wakeup fault thread after fault rx window is opened.
++	 */
++	wake_up_process(fwt_thr);
++
++	pr_err("VAS: Created fault window, %d, LPID/PID/TID [%d/%d/%d]\n",
++			fault_win->winid, attr.lnotify_lpid, attr.lnotify_pid,
++			attr.lnotify_tid);
++
++	return 0;
++
++stop_thread:
++	kthread_stop(fwt_thr);
++
++free_mem:
++	kfree(attr.rx_fifo);
++	return -1;
++}
++
++static void destroy_fault_win(void)
++{
++	if (vas_win_close(fault_win) < 0)
++		pr_err("VAS: error closing fault window\n");
++
++	/*
++	 * TODO: fault_win_thread() does not exit unless stopped
++	 *	 but check if there can be any race here.
++	 */
++	kthread_stop(fwt_thr);
++	kfree(fwta.rx_fifo);
++	pr_err("VAS: Fault thread stopped\n");
++}
+ 
+ static void init_vas_chip(struct vas_instance *vinst)
+ {
+@@ -93,7 +236,7 @@ static void init_vas_instance(int node, int chip)
+ 
+ int vas_init(void)
+ {
+-	int n, c;
++	int n, c, rc;
+ 
+ 	vas_instances = kmalloc_array(VAS_MAX_NODES * VAS_MAX_CHIPS_PER_NODE,
+ 				sizeof(struct vas_instance), GFP_KERNEL);
+@@ -110,12 +253,24 @@ int vas_init(void)
+ 
+ 	vas_initialized = 1;
+ 
++	/*
++	 * Create fault handler thread and window.
++	 */
++	rc = create_fault_win();
++	if (rc < 0)
++		goto cleanup;
++
+ 	return 0;
++
++cleanup:
++	kfree(vas_instances);
++	return rc;
  }
- EXPORT_SYMBOL_GPL(vas_tx_win_open);
- 
-+int vas_copy_crb(void *crb, int offset)
-+{
-+	return vas_copy(crb, offset);
-+}
-+EXPORT_SYMBOL_GPL(vas_copy_crb);
-+
-+#define RMA_LSMP_REPORT_ENABLE PPC_BIT(53)
-+int vas_paste_crb(struct vas_window *txwin, int offset, bool re)
-+{
-+	int rc;
-+	void *addr;
-+	uint64_t val;
-+
-+	/*
-+	 * Only NX windows are supported for now and hardware assumes
-+	 * report-enable flag is set for NX windows. Ensure software
-+	 * complies too.
-+	 */
-+	WARN_ON_ONCE(txwin->nx_win && !re);
-+
-+	addr = txwin->paste_kaddr;
-+	if (re) {
-+		/*
-+		 * Set the REPORT_ENABLE bit (equivalent to writing
-+		 * to 1K offset of the paste address)
-+		 */
-+		val = SET_FIELD(RMA_LSMP_REPORT_ENABLE, 0ULL, 1);
-+		addr += val;
-+	}
-+
-+	/*
-+	 * Map the raw CR value from vas_paste() to an error code (there
-+	 * is just pass or fail for now though).
-+	 */
-+	rc = vas_paste(addr, offset);
-+	if (rc == 2)
-+		rc = 0;
-+	else
-+		rc = -EINVAL;
-+
-+	print_fifo_msg_count(txwin);
-+
-+	return rc;
-+}
-+EXPORT_SYMBOL_GPL(vas_paste_crb);
-+
- static void poll_window_busy_state(struct vas_window *window)
+ 
+ void vas_exit(void)
  {
- 	int busy;
-diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
-index d3e4f55..38dee5d 100644
---- a/arch/powerpc/platforms/powernv/vas.h
-+++ b/arch/powerpc/platforms/powernv/vas.h
-@@ -398,11 +398,11 @@ extern struct vas_instance *find_vas_instance(int vasid);
- #ifdef vas_debug
- static inline void dump_rx_win_attr(struct vas_rx_win_attr *attr)
- {
--	pr_err("VAS: fault %d, notify %d, intr %d early %d\n",
-+	pr_err("fault %d, notify %d, intr %d early %d\n",
- 			attr->fault_win, attr->notify_disable,
- 			attr->intr_disable, attr->notify_early);
- 
--	pr_err("VAS: rx_fifo_size %d, max value %d\n",
-+	pr_err("rx_fifo_size %d, max value %d\n",
- 				attr->rx_fifo_size, VAS_RX_FIFO_SIZE_MAX);
+ 	vas_initialized = 0;
++	destroy_fault_win();
+ 	kfree(vas_instances);
  }
  
-@@ -450,4 +450,18 @@ static inline u64 read_hvwc_reg(struct vas_window *win,
- 	return in_be64(win->hvwc_map+reg);
- }
- 
-+#ifdef vas_debug
-+
-+static void print_fifo_msg_count(struct vas_window *txwin)
-+{
-+	uint64_t read_hvwc_reg(struct vas_window *w, char *n, uint64_t o);
-+	pr_devel("Winid %d, Msg count %llu\n", txwin->winid,
-+			(uint64_t)read_hvwc_reg(txwin, VREG(LRFIFO_PUSH)));
-+}
-+#else	/* vas_debug */
-+
-+#define print_fifo_msg_count(window)
-+
-+#endif	/* vas_debug */
-+
- #endif /* _VAS_H */
 -- 
-2.7.4
+1.8.3.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help