Inter-revision diff: patch 5

Comparing v8 (message) to v3 (message)

--- v8
+++ v3
@@ -4,24 +4,6 @@
 
 Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
 ---
-Changelog[v8]:
-	- Update comments (ISA references and some cleanup)
-	- Use 0 or 1 when setting boolean fields with SET_FIELD()
-	- Don't write to spare/unused registers.
-	- Use kernel integer types (u64/u32/s32)
-Changelog[v6]
-	- Add support for FTW windows and drop the fault window id
-	  code since it is not needed for FTW/kernel windows.
-Changelog[v5]
-	- Fix: Copy the FIFO address into LFIFO_BAR register as is (don't
-	  shift address into bits 8:53).
-
-Changelog[v4]
-	- Michael Neuling] Use ilog2(), radix_enabled() helpers;
-	  drop warning when 32-bit app uses VAS (a follow-on patch
-	  will check and return error). Set MSR_PR state to 0 for
-	  kernel (rather than reading from MSR).
-
 Changelog[v3]
 	- Have caller, rather than init_xlate_regs() reset window regs
 	  so we don't reset any settings caller may already have set.
@@ -31,23 +13,106 @@
 	  initialized from the HVWC.
 	- Check winctx->user_win when setting translation registers
 ---
- arch/powerpc/platforms/powernv/vas-window.c | 299 ++++++++++++++++++++++++++++
- arch/powerpc/platforms/powernv/vas.h        |  55 +++++
- 2 files changed, 354 insertions(+)
+ drivers/misc/vas/vas-internal.h |  59 ++++++-
+ drivers/misc/vas/vas-window.c   | 334 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 390 insertions(+), 3 deletions(-)
 
-diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
-index 642814a2..68dfe53 100644
---- a/arch/powerpc/platforms/powernv/vas-window.c
-+++ b/arch/powerpc/platforms/powernv/vas-window.c
-@@ -13,6 +13,7 @@
- #include <linux/mutex.h>
- #include <linux/slab.h>
- #include <linux/io.h>
-+#include <linux/log2.h>
+diff --git a/drivers/misc/vas/vas-internal.h b/drivers/misc/vas/vas-internal.h
+index 15b62e0..8e721df 100644
+--- a/drivers/misc/vas/vas-internal.h
++++ b/drivers/misc/vas/vas-internal.h
+@@ -11,6 +11,7 @@
+ #define VAS_INTERNAL_H
+ #include <linux/atomic.h>
+ #include <linux/idr.h>
++#include <linux/io.h>
+ #include <asm/vas.h>
  
- #include "vas.h"
+ #ifdef CONFIG_PPC_4K_PAGES
+@@ -336,9 +337,6 @@ struct vas_window {
+ 	/* Feilds applicable only to receive windows */
+ 	enum vas_cop_type cop;
+ 	atomic_t num_txwins;
+-
+-	int32_t hwirq;
+-	uint64_t irq_port;
+ };
  
-@@ -186,6 +187,304 @@ int map_winctx_mmio_bars(struct vas_window *window)
+ /*
+@@ -392,4 +390,59 @@ struct vas_winctx {
+ extern int vas_initialized;
+ extern int vas_window_reset(struct vas_instance *vinst, int winid);
+ extern struct vas_instance *find_vas_instance(int vasid);
++
++/*
++ * VREG(x):
++ * Expand a register's short name (eg: LPID) into two parameters:
++ *	- the register's short name in string form ("LPID"), and
++ *	- the name of the macro (eg: VAS_LPID_OFFSET), defining the
++ *	  register's offset in the window context
++ */
++#define VREG_SFX(n, s)	__stringify(n), VAS_##n##s
++#define VREG(r)		VREG_SFX(r, _OFFSET)
++
++#ifndef vas_debug
++static inline void vas_log_write(struct vas_window *win, char *name,
++			void *regptr, uint64_t val)
++{
++	if (val)
++		pr_err("%swin #%d: %s reg %p, val 0x%llx\n",
++				win->tx_win ? "Tx" : "Rx", win->winid, name,
++				regptr, val);
++}
++
++#else	/* vas_debug */
++
++#define vas_log_write(win, name, reg, val)
++
++#endif	/* vas_debug */
++
++static inline void write_uwc_reg(struct vas_window *win, char *name,
++			int32_t reg, uint64_t val)
++{
++	void *regptr;
++
++	regptr = win->uwc_map + reg;
++	vas_log_write(win, name, regptr, val);
++
++	out_be64(regptr, val);
++}
++
++static inline void write_hvwc_reg(struct vas_window *win, char *name,
++			int32_t reg, uint64_t val)
++{
++	void *regptr;
++
++	regptr = win->hvwc_map + reg;
++	vas_log_write(win, name, regptr, val);
++
++	out_be64(regptr, val);
++}
++
++static inline uint64_t read_hvwc_reg(struct vas_window *win,
++			char *name __maybe_unused, int32_t reg)
++{
++	return in_be64(win->hvwc_map+reg);
++}
++
+ #endif
+diff --git a/drivers/misc/vas/vas-window.c b/drivers/misc/vas/vas-window.c
+index 32dd1d0..edf5c9f 100644
+--- a/drivers/misc/vas/vas-window.c
++++ b/drivers/misc/vas/vas-window.c
+@@ -14,6 +14,8 @@
+ #include <asm/vas.h>
+ #include "vas-internal.h"
+ 
++static int fault_winid;
++
+ /*
+  * Compute the paste address region for the window @window using the
+  * ->win_base_addr and ->win_id_shift we got from device tree.
+@@ -138,6 +140,338 @@ int map_wc_mmio_bars(struct vas_window *window)
  	return 0;
  }
  
@@ -58,7 +123,7 @@
 + * NOTE: We cannot really use a for loop to reset window context. Not all
 + *	 offsets in a window context are valid registers and the valid
 + *	 registers are not sequential. And, we can only write to offsets
-+ *	 with valid registers.
++ *	 with valid registers (or is that only in Simics?).
 + */
 +void reset_window_regs(struct vas_window *window)
 +{
@@ -73,6 +138,12 @@
 +	write_hvwc_reg(window, VREG(OSU_INTR_SRC_RA), 0ULL);
 +	write_hvwc_reg(window, VREG(HV_INTR_SRC_RA), 0ULL);
 +	write_hvwc_reg(window, VREG(PSWID), 0ULL);
++	write_hvwc_reg(window, VREG(SPARE1), 0ULL);
++	write_hvwc_reg(window, VREG(SPARE2), 0ULL);
++	write_hvwc_reg(window, VREG(SPARE3), 0ULL);
++	write_hvwc_reg(window, VREG(SPARE4), 0ULL);
++	write_hvwc_reg(window, VREG(SPARE5), 0ULL);
++	write_hvwc_reg(window, VREG(SPARE6), 0ULL);
 +	write_hvwc_reg(window, VREG(LFIFO_BAR), 0ULL);
 +	write_hvwc_reg(window, VREG(LDATA_STAMP_CTL), 0ULL);
 +	write_hvwc_reg(window, VREG(LDMA_CACHE_CTL), 0ULL);
@@ -118,26 +189,35 @@
 + */
 +static void init_xlate_regs(struct vas_window *window, bool user_win)
 +{
-+	u64 lpcr, val;
-+
-+	/*
-+	 * MSR_TA, MSR_US are false for both kernel and user.
-+	 * MSR_DR and MSR_PR are false for kernel.
-+	 */
-+	val = 0ULL;
-+	val = SET_FIELD(VAS_XLATE_MSR_HV, val, 1);
-+	val = SET_FIELD(VAS_XLATE_MSR_SF, val, 1);
++	uint64_t lpcr, msr, val;
++
++	msr = mfmsr();
++	WARN_ON_ONCE(!(msr & MSR_SF));
++	val = 0ULL;
 +	if (user_win) {
-+		val = SET_FIELD(VAS_XLATE_MSR_DR, val, 1);
-+		val = SET_FIELD(VAS_XLATE_MSR_PR, val, 1);
++		val = SET_FIELD(VAS_XLATE_MSR_DR, val, true);
++		val = SET_FIELD(VAS_XLATE_MSR_TA, val, false);
++		val = SET_FIELD(VAS_XLATE_MSR_PR, val, true);
++		val = SET_FIELD(VAS_XLATE_MSR_US, val, false);
++		val = SET_FIELD(VAS_XLATE_MSR_HV, val, true);
++		val = SET_FIELD(VAS_XLATE_MSR_SF, val, true);
++		val = SET_FIELD(VAS_XLATE_MSR_UV, val, false);
++	} else {
++		val = SET_FIELD(VAS_XLATE_MSR_DR, val, false);
++		val = SET_FIELD(VAS_XLATE_MSR_TA, val, false);
++		val = SET_FIELD(VAS_XLATE_MSR_PR, val, msr & MSR_PR);
++		val = SET_FIELD(VAS_XLATE_MSR_US, val, false);
++		val = SET_FIELD(VAS_XLATE_MSR_HV, val, true);
++		val = SET_FIELD(VAS_XLATE_MSR_SF, val, true);
++		val = SET_FIELD(VAS_XLATE_MSR_UV, val, false);
 +	}
 +	write_hvwc_reg(window, VREG(XLATE_MSR), val);
 +
 +	lpcr = mfspr(SPRN_LPCR);
 +	val = 0ULL;
 +	/*
-+	 * NOTE: From Section 5.7.8.1 Segment Lookaside Buffer of the
-+	 *	 Power ISA, v3.0B, Page size encoding is 0 = 4KB, 5 = 64KB.
++	 * NOTE: From Section 5.7.6.1 Segment Lookaside Buffer of the
++	 *	 Power ISA, v2.07, Page size encoding is 0 = 4KB, 5 = 64KB.
 +	 *
 +	 * NOTE: From Section 1.3.1, Address Translation Context of the
 +	 *	 Nest MMU Workbook, LPCR_SC should be 0 for Power9.
@@ -152,11 +232,11 @@
 +	 * Section 1.3.1 (Address translation Context) of NMMU workbook.
 +	 *	0b00	Hashed Page Table mode
 +	 *	0b01	Reserved
-+	 *	0b10	Radix on HPT
-+	 *	0b11	Radix on Radix
-+	 */
-+	val = 0ULL;
-+	val = SET_FIELD(VAS_XLATE_MODE, val, radix_enabled() ? 3 : 2);
++	 *	0b10	Radix on HPT - not supported in P9
++	 *	0b11	Radix on Radix (only mode supported in Linux on P9).
++	 */
++	val = 0ULL;
++	val = SET_FIELD(VAS_XLATE_MODE, val, 0x3);
 +	write_hvwc_reg(window, VREG(XLATE_CTL), val);
 +
 +	/*
@@ -166,6 +246,11 @@
 +	val = SET_FIELD(VAS_AMR, val, mfspr(SPRN_AMR));
 +	write_hvwc_reg(window, VREG(AMR), val);
 +
++	/*
++	 * TODO: Assuming Secure Executable ID Register (SEIDR) is only used
++	 *	 in the ultravisor mode. Since MSR(UV) is 0 for now, set SEIDR
++	 *	 to 0 as well, although we should 'mfspr(SEIDR)' at some point.
++	 */
 +	val = 0ULL;
 +	val = SET_FIELD(VAS_SEIDR, val, 0);
 +	write_hvwc_reg(window, VREG(SEIDR), val);
@@ -185,6 +270,29 @@
 +				struct vas_winctx *winctx)
 +{
 +	write_hvwc_reg(txwin, VREG(TX_RSVD_BUF_COUNT), 0ULL);
++}
++
++/*
++ * Compute the log2() of the FIFO size expressed as kilobytes. It is intended
++ * to be used to initialize the Local FIFO Size Register defined in Section
++ * 3.14.25 of the VAS Workbook.
++ */
++static int map_fifo_size_to_reg(int fifo_size)
++{
++	int kb;
++	int map;
++
++	kb = fifo_size / 1024;
++	if (!kb)
++		kb = 1;
++
++	map = -1;
++	while (kb) {
++		kb >>= 1;
++		map++;
++	}
++
++	return map;
 +}
 +
 +/*
@@ -205,7 +313,7 @@
 + */
 +int init_winctx_regs(struct vas_window *window, struct vas_winctx *winctx)
 +{
-+	u64 val;
++	uint64_t val;
 +	int fifo_size;
 +
 +	reset_window_regs(window);
@@ -221,7 +329,7 @@
 +	init_xlate_regs(window, winctx->user_win);
 +
 +	val = 0ULL;
-+	val = SET_FIELD(VAS_FAULT_TX_WIN, val, 0);
++	val = SET_FIELD(VAS_FAULT_TX_WIN, val, fault_winid);
 +	write_hvwc_reg(window, VREG(FAULT_TX_WIN), val);
 +
 +	/* In PowerNV, interrupts go to HV. */
@@ -239,16 +347,9 @@
 +	write_hvwc_reg(window, VREG(SPARE2), 0ULL);
 +	write_hvwc_reg(window, VREG(SPARE3), 0ULL);
 +
-+	/*
-+	 * NOTE: VAS expects the FIFO address to be copied into the LFIFO_BAR
-+	 *	 register as is - do NOT shift the address into VAS_LFIFO_BAR
-+	 *	 bit fields! Ok to set the page migration select fields -
-+	 *	 VAS ignores the lower 10+ bits in the address anyway, because
-+	 *	 the minimum FIFO size is 1K?
-+	 *
-+	 * See also: Design note in function header.
-+	 */
-+	val = __pa(winctx->rx_fifo);
++	/* See also: Design note in function header */
++	val = 0ULL;
++	val = SET_FIELD(VAS_LFIFO_BAR, val, __pa(winctx->rx_fifo));
 +	val = SET_FIELD(VAS_PAGE_MIGRATION_SELECT, val, 0);
 +	write_hvwc_reg(window, VREG(LFIFO_BAR), val);
 +
@@ -258,7 +359,6 @@
 +
 +	val = 0ULL;
 +	val = SET_FIELD(VAS_LDMA_TYPE, val, winctx->dma_type);
-+	val = SET_FIELD(VAS_LDMA_FIFO_DISABLE, val, winctx->fifo_disable);
 +	write_hvwc_reg(window, VREG(LDMA_CACHE_CTL), val);
 +
 +	write_hvwc_reg(window, VREG(LRFIFO_PUSH), 0ULL);
@@ -276,10 +376,9 @@
 +	write_hvwc_reg(window, VREG(LRX_WCRED_ADDER), 0ULL);
 +	write_hvwc_reg(window, VREG(TX_WCRED_ADDER), 0ULL);
 +
-+	fifo_size = winctx->rx_fifo_size / 1024;
-+
-+	val = 0ULL;
-+	val = SET_FIELD(VAS_LFIFO_SIZE, val, ilog2(fifo_size));
++	val = 0ULL;
++	fifo_size = winctx->rx_fifo_size;
++	val = SET_FIELD(VAS_LFIFO_SIZE, val, map_fifo_size_to_reg(fifo_size));
 +	write_hvwc_reg(window, VREG(LFIFO_SIZE), val);
 +
 +	/* Update window control and caching control registers last so
@@ -350,78 +449,7 @@
 +}
 +
  /* stub for now */
- int vas_win_close(struct vas_window *window)
+ int vas_window_reset(struct vas_instance *vinst, int winid)
  {
-diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
-index 650805d..60a3c3c 100644
---- a/arch/powerpc/platforms/powernv/vas.h
-+++ b/arch/powerpc/platforms/powernv/vas.h
-@@ -12,6 +12,7 @@
- #include <linux/atomic.h>
- #include <linux/idr.h>
- #include <asm/vas.h>
-+#include <linux/io.h>
- 
- /*
-  * Overview of Virtual Accelerator Switchboard (VAS).
-@@ -381,4 +382,58 @@ struct vas_winctx {
- 
- extern struct vas_instance *find_vas_instance(int vasid);
- 
-+/*
-+ * VREG(x):
-+ * Expand a register's short name (eg: LPID) into two parameters:
-+ *	- the register's short name in string form ("LPID"), and
-+ *	- the name of the macro (eg: VAS_LPID_OFFSET), defining the
-+ *	  register's offset in the window context
-+ */
-+#define VREG_SFX(n, s)	__stringify(n), VAS_##n##s
-+#define VREG(r)		VREG_SFX(r, _OFFSET)
-+
-+#ifdef vas_debug
-+static inline void vas_log_write(struct vas_window *win, char *name,
-+			void *regptr, u64 val)
-+{
-+	if (val)
-+		pr_err("%swin #%d: %s reg %p, val 0x%016llx\n",
-+				win->tx_win ? "Tx" : "Rx", win->winid, name,
-+				regptr, val);
-+}
-+
-+#else	/* vas_debug */
-+
-+#define vas_log_write(win, name, reg, val)
-+
-+#endif	/* vas_debug */
-+
-+static inline void write_uwc_reg(struct vas_window *win, char *name,
-+			s32 reg, u64 val)
-+{
-+	void *regptr;
-+
-+	regptr = win->uwc_map + reg;
-+	vas_log_write(win, name, regptr, val);
-+
-+	out_be64(regptr, val);
-+}
-+
-+static inline void write_hvwc_reg(struct vas_window *win, char *name,
-+			s32 reg, u64 val)
-+{
-+	void *regptr;
-+
-+	regptr = win->hvwc_map + reg;
-+	vas_log_write(win, name, regptr, val);
-+
-+	out_be64(regptr, val);
-+}
-+
-+static inline u64 read_hvwc_reg(struct vas_window *win,
-+			char *name __maybe_unused, s32 reg)
-+{
-+	return in_be64(win->hvwc_map+reg);
-+}
-+
- #endif /* _VAS_H */
 -- 
 2.7.4
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help