aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile')
-rw-r--r--arch/tile/Kconfig43
-rw-r--r--arch/tile/Makefile7
-rw-r--r--arch/tile/include/arch/spr_def_32.h56
-rw-r--r--arch/tile/include/arch/spr_def_64.h43
-rw-r--r--arch/tile/include/asm/Kbuild2
-rw-r--r--arch/tile/include/asm/atomic_32.h10
-rw-r--r--arch/tile/include/asm/bitops.h12
-rw-r--r--arch/tile/include/asm/byteorder.h20
-rw-r--r--arch/tile/include/asm/cachectl.h42
-rw-r--r--arch/tile/include/asm/compat.h3
-rw-r--r--arch/tile/include/asm/elf.h5
-rw-r--r--arch/tile/include/asm/futex.h143
-rw-r--r--arch/tile/include/asm/hardwall.h18
-rw-r--r--arch/tile/include/asm/hugetlb.h21
-rw-r--r--arch/tile/include/asm/irqflags.h34
-rw-r--r--arch/tile/include/asm/kexec.h12
-rw-r--r--arch/tile/include/asm/kvm_para.h1
-rw-r--r--arch/tile/include/asm/mmu.h2
-rw-r--r--arch/tile/include/asm/mmu_context.h8
-rw-r--r--arch/tile/include/asm/module.h40
-rw-r--r--arch/tile/include/asm/page.h18
-rw-r--r--arch/tile/include/asm/pgalloc.h92
-rw-r--r--arch/tile/include/asm/pgtable.h111
-rw-r--r--arch/tile/include/asm/pgtable_32.h40
-rw-r--r--arch/tile/include/asm/pgtable_64.h57
-rw-r--r--arch/tile/include/asm/processor.h17
-rw-r--r--arch/tile/include/asm/setup.h10
-rw-r--r--arch/tile/include/asm/syscalls.h3
-rw-r--r--arch/tile/include/asm/tlbflush.h17
-rw-r--r--arch/tile/include/asm/uaccess.h222
-rw-r--r--arch/tile/include/asm/unistd.h4
-rw-r--r--arch/tile/include/hv/drv_xgbe_intf.h2
-rw-r--r--arch/tile/include/hv/hypervisor.h325
-rw-r--r--arch/tile/kernel/Makefile3
-rw-r--r--arch/tile/kernel/entry.S3
-rw-r--r--arch/tile/kernel/hardwall.c754
-rw-r--r--arch/tile/kernel/head_32.S8
-rw-r--r--arch/tile/kernel/head_64.S22
-rw-r--r--arch/tile/kernel/hvglue.lds3
-rw-r--r--arch/tile/kernel/intvec_64.S80
-rw-r--r--arch/tile/kernel/machine_kexec.c42
-rw-r--r--arch/tile/kernel/module.c12
-rw-r--r--arch/tile/kernel/proc.c1
-rw-r--r--arch/tile/kernel/process.c16
-rw-r--r--arch/tile/kernel/relocate_kernel_32.S (renamed from arch/tile/kernel/relocate_kernel.S)0
-rw-r--r--arch/tile/kernel/relocate_kernel_64.S260
-rw-r--r--arch/tile/kernel/setup.c169
-rw-r--r--arch/tile/kernel/single_step.c16
-rw-r--r--arch/tile/kernel/smp.c2
-rw-r--r--arch/tile/kernel/sys.c10
-rw-r--r--arch/tile/kernel/sysfs.c8
-rw-r--r--arch/tile/kernel/tlb.c11
-rw-r--r--arch/tile/kernel/traps.c30
-rw-r--r--arch/tile/lib/atomic_32.c47
-rw-r--r--arch/tile/lib/exports.c8
-rw-r--r--arch/tile/lib/memchr_64.c8
-rw-r--r--arch/tile/lib/memcpy_64.c23
-rw-r--r--arch/tile/lib/memcpy_tile64.c8
-rw-r--r--arch/tile/lib/strchr_64.c15
-rw-r--r--arch/tile/lib/string-endian.h33
-rw-r--r--arch/tile/lib/strlen_64.c11
-rw-r--r--arch/tile/lib/usercopy_32.S76
-rw-r--r--arch/tile/lib/usercopy_64.S49
-rw-r--r--arch/tile/mm/fault.c34
-rw-r--r--arch/tile/mm/homecache.c1
-rw-r--r--arch/tile/mm/hugetlbpage.c285
-rw-r--r--arch/tile/mm/init.c19
-rw-r--r--arch/tile/mm/migrate.h6
-rw-r--r--arch/tile/mm/migrate_32.S36
-rw-r--r--arch/tile/mm/migrate_64.S34
-rw-r--r--arch/tile/mm/pgtable.c40
71 files changed, 2459 insertions, 1164 deletions
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 6ad6219fc47e..fe128816c448 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -48,6 +48,14 @@ config NEED_PER_CPU_PAGE_FIRST_CHUNK
48config SYS_SUPPORTS_HUGETLBFS 48config SYS_SUPPORTS_HUGETLBFS
49 def_bool y 49 def_bool y
50 50
51# Support for additional huge page sizes besides HPAGE_SIZE.
52# The software support is currently only present in the TILE-Gx
53# hypervisor. TILEPro in any case does not support page sizes
54# larger than the default HPAGE_SIZE.
55config HUGETLB_SUPER_PAGES
56 depends on HUGETLB_PAGE && TILEGX
57 def_bool y
58
51# FIXME: tilegx can implement a more efficient rwsem. 59# FIXME: tilegx can implement a more efficient rwsem.
52config RWSEM_GENERIC_SPINLOCK 60config RWSEM_GENERIC_SPINLOCK
53 def_bool y 61 def_bool y
@@ -107,16 +115,14 @@ config HVC_TILE
107 select HVC_DRIVER 115 select HVC_DRIVER
108 def_bool y 116 def_bool y
109 117
110# Please note: TILE-Gx support is not yet finalized; this is
111# the preliminary support. TILE-Gx drivers are only provided
112# with the alpha or beta test versions for Tilera customers.
113config TILEGX 118config TILEGX
114 depends on EXPERIMENTAL
115 bool "Building with TILE-Gx (64-bit) compiler and toolchain" 119 bool "Building with TILE-Gx (64-bit) compiler and toolchain"
116 120
121config TILEPRO
122 def_bool !TILEGX
123
117config 64BIT 124config 64BIT
118 depends on TILEGX 125 def_bool TILEGX
119 def_bool y
120 126
121config ARCH_DEFCONFIG 127config ARCH_DEFCONFIG
122 string 128 string
@@ -137,6 +143,31 @@ config NR_CPUS
137 smaller kernel memory footprint results from using a smaller 143 smaller kernel memory footprint results from using a smaller
138 value on chips with fewer tiles. 144 value on chips with fewer tiles.
139 145
146if TILEGX
147
148choice
149 prompt "Kernel page size"
150 default PAGE_SIZE_64KB
151 help
152 This lets you select the page size of the kernel. For best
153 performance on memory-intensive applications, a page size of 64KB
154 is recommended. For workloads involving many small files, many
155 connections, etc., it may be better to select 16KB, which uses
156 memory more efficiently at some cost in TLB performance.
157
158 Note that this option is TILE-Gx specific; currently
159 TILEPro page size is set by rebuilding the hypervisor.
160
161config PAGE_SIZE_16KB
162 bool "16KB"
163
164config PAGE_SIZE_64KB
165 bool "64KB"
166
167endchoice
168
169endif
170
140source "kernel/Kconfig.hz" 171source "kernel/Kconfig.hz"
141 172
142config KEXEC 173config KEXEC
diff --git a/arch/tile/Makefile b/arch/tile/Makefile
index 9520bc5a4b7f..e20b0a0b64a1 100644
--- a/arch/tile/Makefile
+++ b/arch/tile/Makefile
@@ -34,7 +34,12 @@ LIBGCC_PATH := \
34 $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name) 34 $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
35 35
36# Provide the path to use for "make defconfig". 36# Provide the path to use for "make defconfig".
37KBUILD_DEFCONFIG := $(ARCH)_defconfig 37# We default to the newer TILE-Gx architecture if only "tile" is given.
38ifeq ($(ARCH),tile)
39 KBUILD_DEFCONFIG := tilegx_defconfig
40else
41 KBUILD_DEFCONFIG := $(ARCH)_defconfig
42endif
38 43
39# Used as a file extension when useful, e.g. head_$(BITS).o 44# Used as a file extension when useful, e.g. head_$(BITS).o
40# Not needed for (e.g.) "$(CC) -m32" since the compiler automatically 45# Not needed for (e.g.) "$(CC) -m32" since the compiler automatically
diff --git a/arch/tile/include/arch/spr_def_32.h b/arch/tile/include/arch/spr_def_32.h
index bbc1f4c924ee..78bbce2fb19a 100644
--- a/arch/tile/include/arch/spr_def_32.h
+++ b/arch/tile/include/arch/spr_def_32.h
@@ -65,6 +65,31 @@
65#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1 65#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1
66#define SPR_EX_CONTEXT_2_1__ICS_MASK 0x4 66#define SPR_EX_CONTEXT_2_1__ICS_MASK 0x4
67#define SPR_FAIL 0x4e09 67#define SPR_FAIL 0x4e09
68#define SPR_IDN_AVAIL_EN 0x3e05
69#define SPR_IDN_CA_DATA 0x0b00
70#define SPR_IDN_DATA_AVAIL 0x0b03
71#define SPR_IDN_DEADLOCK_TIMEOUT 0x3406
72#define SPR_IDN_DEMUX_CA_COUNT 0x0a05
73#define SPR_IDN_DEMUX_COUNT_0 0x0a06
74#define SPR_IDN_DEMUX_COUNT_1 0x0a07
75#define SPR_IDN_DEMUX_CTL 0x0a08
76#define SPR_IDN_DEMUX_QUEUE_SEL 0x0a0a
77#define SPR_IDN_DEMUX_STATUS 0x0a0b
78#define SPR_IDN_DEMUX_WRITE_FIFO 0x0a0c
79#define SPR_IDN_DIRECTION_PROTECT 0x2e05
80#define SPR_IDN_PENDING 0x0a0e
81#define SPR_IDN_REFILL_EN 0x0e05
82#define SPR_IDN_SP_FIFO_DATA 0x0a0f
83#define SPR_IDN_SP_FIFO_SEL 0x0a10
84#define SPR_IDN_SP_FREEZE 0x0a11
85#define SPR_IDN_SP_FREEZE__SP_FRZ_MASK 0x1
86#define SPR_IDN_SP_FREEZE__DEMUX_FRZ_MASK 0x2
87#define SPR_IDN_SP_FREEZE__NON_DEST_EXT_MASK 0x4
88#define SPR_IDN_SP_STATE 0x0a12
89#define SPR_IDN_TAG_0 0x0a13
90#define SPR_IDN_TAG_1 0x0a14
91#define SPR_IDN_TAG_VALID 0x0a15
92#define SPR_IDN_TILE_COORD 0x0a16
68#define SPR_INTCTRL_0_STATUS 0x4a07 93#define SPR_INTCTRL_0_STATUS 0x4a07
69#define SPR_INTCTRL_1_STATUS 0x4807 94#define SPR_INTCTRL_1_STATUS 0x4807
70#define SPR_INTCTRL_2_STATUS 0x4607 95#define SPR_INTCTRL_2_STATUS 0x4607
@@ -87,12 +112,36 @@
87#define SPR_INTERRUPT_MASK_SET_1_1 0x480e 112#define SPR_INTERRUPT_MASK_SET_1_1 0x480e
88#define SPR_INTERRUPT_MASK_SET_2_0 0x460c 113#define SPR_INTERRUPT_MASK_SET_2_0 0x460c
89#define SPR_INTERRUPT_MASK_SET_2_1 0x460d 114#define SPR_INTERRUPT_MASK_SET_2_1 0x460d
115#define SPR_MPL_AUX_PERF_COUNT_SET_0 0x6000
116#define SPR_MPL_AUX_PERF_COUNT_SET_1 0x6001
117#define SPR_MPL_AUX_PERF_COUNT_SET_2 0x6002
90#define SPR_MPL_DMA_CPL_SET_0 0x5800 118#define SPR_MPL_DMA_CPL_SET_0 0x5800
91#define SPR_MPL_DMA_CPL_SET_1 0x5801 119#define SPR_MPL_DMA_CPL_SET_1 0x5801
92#define SPR_MPL_DMA_CPL_SET_2 0x5802 120#define SPR_MPL_DMA_CPL_SET_2 0x5802
93#define SPR_MPL_DMA_NOTIFY_SET_0 0x3800 121#define SPR_MPL_DMA_NOTIFY_SET_0 0x3800
94#define SPR_MPL_DMA_NOTIFY_SET_1 0x3801 122#define SPR_MPL_DMA_NOTIFY_SET_1 0x3801
95#define SPR_MPL_DMA_NOTIFY_SET_2 0x3802 123#define SPR_MPL_DMA_NOTIFY_SET_2 0x3802
124#define SPR_MPL_IDN_ACCESS_SET_0 0x0a00
125#define SPR_MPL_IDN_ACCESS_SET_1 0x0a01
126#define SPR_MPL_IDN_ACCESS_SET_2 0x0a02
127#define SPR_MPL_IDN_AVAIL_SET_0 0x3e00
128#define SPR_MPL_IDN_AVAIL_SET_1 0x3e01
129#define SPR_MPL_IDN_AVAIL_SET_2 0x3e02
130#define SPR_MPL_IDN_CA_SET_0 0x3a00
131#define SPR_MPL_IDN_CA_SET_1 0x3a01
132#define SPR_MPL_IDN_CA_SET_2 0x3a02
133#define SPR_MPL_IDN_COMPLETE_SET_0 0x1200
134#define SPR_MPL_IDN_COMPLETE_SET_1 0x1201
135#define SPR_MPL_IDN_COMPLETE_SET_2 0x1202
136#define SPR_MPL_IDN_FIREWALL_SET_0 0x2e00
137#define SPR_MPL_IDN_FIREWALL_SET_1 0x2e01
138#define SPR_MPL_IDN_FIREWALL_SET_2 0x2e02
139#define SPR_MPL_IDN_REFILL_SET_0 0x0e00
140#define SPR_MPL_IDN_REFILL_SET_1 0x0e01
141#define SPR_MPL_IDN_REFILL_SET_2 0x0e02
142#define SPR_MPL_IDN_TIMER_SET_0 0x3400
143#define SPR_MPL_IDN_TIMER_SET_1 0x3401
144#define SPR_MPL_IDN_TIMER_SET_2 0x3402
96#define SPR_MPL_INTCTRL_0_SET_0 0x4a00 145#define SPR_MPL_INTCTRL_0_SET_0 0x4a00
97#define SPR_MPL_INTCTRL_0_SET_1 0x4a01 146#define SPR_MPL_INTCTRL_0_SET_1 0x4a01
98#define SPR_MPL_INTCTRL_0_SET_2 0x4a02 147#define SPR_MPL_INTCTRL_0_SET_2 0x4a02
@@ -102,6 +151,9 @@
102#define SPR_MPL_INTCTRL_2_SET_0 0x4600 151#define SPR_MPL_INTCTRL_2_SET_0 0x4600
103#define SPR_MPL_INTCTRL_2_SET_1 0x4601 152#define SPR_MPL_INTCTRL_2_SET_1 0x4601
104#define SPR_MPL_INTCTRL_2_SET_2 0x4602 153#define SPR_MPL_INTCTRL_2_SET_2 0x4602
154#define SPR_MPL_PERF_COUNT_SET_0 0x4200
155#define SPR_MPL_PERF_COUNT_SET_1 0x4201
156#define SPR_MPL_PERF_COUNT_SET_2 0x4202
105#define SPR_MPL_SN_ACCESS_SET_0 0x0800 157#define SPR_MPL_SN_ACCESS_SET_0 0x0800
106#define SPR_MPL_SN_ACCESS_SET_1 0x0801 158#define SPR_MPL_SN_ACCESS_SET_1 0x0801
107#define SPR_MPL_SN_ACCESS_SET_2 0x0802 159#define SPR_MPL_SN_ACCESS_SET_2 0x0802
@@ -181,6 +233,7 @@
181#define SPR_UDN_DEMUX_STATUS 0x0c0d 233#define SPR_UDN_DEMUX_STATUS 0x0c0d
182#define SPR_UDN_DEMUX_WRITE_FIFO 0x0c0e 234#define SPR_UDN_DEMUX_WRITE_FIFO 0x0c0e
183#define SPR_UDN_DIRECTION_PROTECT 0x3005 235#define SPR_UDN_DIRECTION_PROTECT 0x3005
236#define SPR_UDN_PENDING 0x0c10
184#define SPR_UDN_REFILL_EN 0x1005 237#define SPR_UDN_REFILL_EN 0x1005
185#define SPR_UDN_SP_FIFO_DATA 0x0c11 238#define SPR_UDN_SP_FIFO_DATA 0x0c11
186#define SPR_UDN_SP_FIFO_SEL 0x0c12 239#define SPR_UDN_SP_FIFO_SEL 0x0c12
@@ -195,6 +248,9 @@
195#define SPR_UDN_TAG_3 0x0c18 248#define SPR_UDN_TAG_3 0x0c18
196#define SPR_UDN_TAG_VALID 0x0c19 249#define SPR_UDN_TAG_VALID 0x0c19
197#define SPR_UDN_TILE_COORD 0x0c1a 250#define SPR_UDN_TILE_COORD 0x0c1a
251#define SPR_WATCH_CTL 0x4209
252#define SPR_WATCH_MASK 0x420a
253#define SPR_WATCH_VAL 0x420b
198 254
199#endif /* !defined(__ARCH_SPR_DEF_H__) */ 255#endif /* !defined(__ARCH_SPR_DEF_H__) */
200 256
diff --git a/arch/tile/include/arch/spr_def_64.h b/arch/tile/include/arch/spr_def_64.h
index cd3e5f95d5fd..0da86faa3370 100644
--- a/arch/tile/include/arch/spr_def_64.h
+++ b/arch/tile/include/arch/spr_def_64.h
@@ -52,6 +52,13 @@
52#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1 52#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1
53#define SPR_EX_CONTEXT_2_1__ICS_MASK 0x4 53#define SPR_EX_CONTEXT_2_1__ICS_MASK 0x4
54#define SPR_FAIL 0x2707 54#define SPR_FAIL 0x2707
55#define SPR_IDN_AVAIL_EN 0x1a05
56#define SPR_IDN_DATA_AVAIL 0x0a80
57#define SPR_IDN_DEADLOCK_TIMEOUT 0x1806
58#define SPR_IDN_DEMUX_COUNT_0 0x0a05
59#define SPR_IDN_DEMUX_COUNT_1 0x0a06
60#define SPR_IDN_DIRECTION_PROTECT 0x1405
61#define SPR_IDN_PENDING 0x0a08
55#define SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK 0x1 62#define SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK 0x1
56#define SPR_INTCTRL_0_STATUS 0x2505 63#define SPR_INTCTRL_0_STATUS 0x2505
57#define SPR_INTCTRL_1_STATUS 0x2405 64#define SPR_INTCTRL_1_STATUS 0x2405
@@ -88,9 +95,27 @@
88#define SPR_IPI_MASK_SET_0 0x1f0a 95#define SPR_IPI_MASK_SET_0 0x1f0a
89#define SPR_IPI_MASK_SET_1 0x1e0a 96#define SPR_IPI_MASK_SET_1 0x1e0a
90#define SPR_IPI_MASK_SET_2 0x1d0a 97#define SPR_IPI_MASK_SET_2 0x1d0a
98#define SPR_MPL_AUX_PERF_COUNT_SET_0 0x2100
99#define SPR_MPL_AUX_PERF_COUNT_SET_1 0x2101
100#define SPR_MPL_AUX_PERF_COUNT_SET_2 0x2102
91#define SPR_MPL_AUX_TILE_TIMER_SET_0 0x1700 101#define SPR_MPL_AUX_TILE_TIMER_SET_0 0x1700
92#define SPR_MPL_AUX_TILE_TIMER_SET_1 0x1701 102#define SPR_MPL_AUX_TILE_TIMER_SET_1 0x1701
93#define SPR_MPL_AUX_TILE_TIMER_SET_2 0x1702 103#define SPR_MPL_AUX_TILE_TIMER_SET_2 0x1702
104#define SPR_MPL_IDN_ACCESS_SET_0 0x0a00
105#define SPR_MPL_IDN_ACCESS_SET_1 0x0a01
106#define SPR_MPL_IDN_ACCESS_SET_2 0x0a02
107#define SPR_MPL_IDN_AVAIL_SET_0 0x1a00
108#define SPR_MPL_IDN_AVAIL_SET_1 0x1a01
109#define SPR_MPL_IDN_AVAIL_SET_2 0x1a02
110#define SPR_MPL_IDN_COMPLETE_SET_0 0x0500
111#define SPR_MPL_IDN_COMPLETE_SET_1 0x0501
112#define SPR_MPL_IDN_COMPLETE_SET_2 0x0502
113#define SPR_MPL_IDN_FIREWALL_SET_0 0x1400
114#define SPR_MPL_IDN_FIREWALL_SET_1 0x1401
115#define SPR_MPL_IDN_FIREWALL_SET_2 0x1402
116#define SPR_MPL_IDN_TIMER_SET_0 0x1800
117#define SPR_MPL_IDN_TIMER_SET_1 0x1801
118#define SPR_MPL_IDN_TIMER_SET_2 0x1802
94#define SPR_MPL_INTCTRL_0_SET_0 0x2500 119#define SPR_MPL_INTCTRL_0_SET_0 0x2500
95#define SPR_MPL_INTCTRL_0_SET_1 0x2501 120#define SPR_MPL_INTCTRL_0_SET_1 0x2501
96#define SPR_MPL_INTCTRL_0_SET_2 0x2502 121#define SPR_MPL_INTCTRL_0_SET_2 0x2502
@@ -100,6 +125,21 @@
100#define SPR_MPL_INTCTRL_2_SET_0 0x2300 125#define SPR_MPL_INTCTRL_2_SET_0 0x2300
101#define SPR_MPL_INTCTRL_2_SET_1 0x2301 126#define SPR_MPL_INTCTRL_2_SET_1 0x2301
102#define SPR_MPL_INTCTRL_2_SET_2 0x2302 127#define SPR_MPL_INTCTRL_2_SET_2 0x2302
128#define SPR_MPL_IPI_0 0x1f04
129#define SPR_MPL_IPI_0_SET_0 0x1f00
130#define SPR_MPL_IPI_0_SET_1 0x1f01
131#define SPR_MPL_IPI_0_SET_2 0x1f02
132#define SPR_MPL_IPI_1 0x1e04
133#define SPR_MPL_IPI_1_SET_0 0x1e00
134#define SPR_MPL_IPI_1_SET_1 0x1e01
135#define SPR_MPL_IPI_1_SET_2 0x1e02
136#define SPR_MPL_IPI_2 0x1d04
137#define SPR_MPL_IPI_2_SET_0 0x1d00
138#define SPR_MPL_IPI_2_SET_1 0x1d01
139#define SPR_MPL_IPI_2_SET_2 0x1d02
140#define SPR_MPL_PERF_COUNT_SET_0 0x2000
141#define SPR_MPL_PERF_COUNT_SET_1 0x2001
142#define SPR_MPL_PERF_COUNT_SET_2 0x2002
103#define SPR_MPL_UDN_ACCESS_SET_0 0x0b00 143#define SPR_MPL_UDN_ACCESS_SET_0 0x0b00
104#define SPR_MPL_UDN_ACCESS_SET_1 0x0b01 144#define SPR_MPL_UDN_ACCESS_SET_1 0x0b01
105#define SPR_MPL_UDN_ACCESS_SET_2 0x0b02 145#define SPR_MPL_UDN_ACCESS_SET_2 0x0b02
@@ -167,6 +207,9 @@
167#define SPR_UDN_DEMUX_COUNT_2 0x0b07 207#define SPR_UDN_DEMUX_COUNT_2 0x0b07
168#define SPR_UDN_DEMUX_COUNT_3 0x0b08 208#define SPR_UDN_DEMUX_COUNT_3 0x0b08
169#define SPR_UDN_DIRECTION_PROTECT 0x1505 209#define SPR_UDN_DIRECTION_PROTECT 0x1505
210#define SPR_UDN_PENDING 0x0b0a
211#define SPR_WATCH_MASK 0x200a
212#define SPR_WATCH_VAL 0x200b
170 213
171#endif /* !defined(__ARCH_SPR_DEF_H__) */ 214#endif /* !defined(__ARCH_SPR_DEF_H__) */
172 215
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 0bb42642343a..143473e3a0bb 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -2,6 +2,7 @@ include include/asm-generic/Kbuild.asm
2 2
3header-y += ../arch/ 3header-y += ../arch/
4 4
5header-y += cachectl.h
5header-y += ucontext.h 6header-y += ucontext.h
6header-y += hardwall.h 7header-y += hardwall.h
7 8
@@ -21,7 +22,6 @@ generic-y += ipcbuf.h
21generic-y += irq_regs.h 22generic-y += irq_regs.h
22generic-y += kdebug.h 23generic-y += kdebug.h
23generic-y += local.h 24generic-y += local.h
24generic-y += module.h
25generic-y += msgbuf.h 25generic-y += msgbuf.h
26generic-y += mutex.h 26generic-y += mutex.h
27generic-y += param.h 27generic-y += param.h
diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h
index 54d1da826f93..e7fb5cfb9597 100644
--- a/arch/tile/include/asm/atomic_32.h
+++ b/arch/tile/include/asm/atomic_32.h
@@ -303,7 +303,14 @@ void __init_atomic_per_cpu(void);
303void __atomic_fault_unlock(int *lock_ptr); 303void __atomic_fault_unlock(int *lock_ptr);
304#endif 304#endif
305 305
306/* Return a pointer to the lock for the given address. */
307int *__atomic_hashed_lock(volatile void *v);
308
306/* Private helper routines in lib/atomic_asm_32.S */ 309/* Private helper routines in lib/atomic_asm_32.S */
310struct __get_user {
311 unsigned long val;
312 int err;
313};
307extern struct __get_user __atomic_cmpxchg(volatile int *p, 314extern struct __get_user __atomic_cmpxchg(volatile int *p,
308 int *lock, int o, int n); 315 int *lock, int o, int n);
309extern struct __get_user __atomic_xchg(volatile int *p, int *lock, int n); 316extern struct __get_user __atomic_xchg(volatile int *p, int *lock, int n);
@@ -319,6 +326,9 @@ extern u64 __atomic64_xchg_add(volatile u64 *p, int *lock, u64 n);
319extern u64 __atomic64_xchg_add_unless(volatile u64 *p, 326extern u64 __atomic64_xchg_add_unless(volatile u64 *p,
320 int *lock, u64 o, u64 n); 327 int *lock, u64 o, u64 n);
321 328
329/* Return failure from the atomic wrappers. */
330struct __get_user __atomic_bad_address(int __user *addr);
331
322#endif /* !__ASSEMBLY__ */ 332#endif /* !__ASSEMBLY__ */
323 333
324#endif /* _ASM_TILE_ATOMIC_32_H */ 334#endif /* _ASM_TILE_ATOMIC_32_H */
diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h
index 16f1fa51fea1..bd186c4eaa50 100644
--- a/arch/tile/include/asm/bitops.h
+++ b/arch/tile/include/asm/bitops.h
@@ -77,6 +77,11 @@ static inline int ffs(int x)
77 return __builtin_ffs(x); 77 return __builtin_ffs(x);
78} 78}
79 79
80static inline int fls64(__u64 w)
81{
82 return (sizeof(__u64) * 8) - __builtin_clzll(w);
83}
84
80/** 85/**
81 * fls - find last set bit in word 86 * fls - find last set bit in word
82 * @x: the word to search 87 * @x: the word to search
@@ -90,12 +95,7 @@ static inline int ffs(int x)
90 */ 95 */
91static inline int fls(int x) 96static inline int fls(int x)
92{ 97{
93 return (sizeof(int) * 8) - __builtin_clz(x); 98 return fls64((unsigned int) x);
94}
95
96static inline int fls64(__u64 w)
97{
98 return (sizeof(__u64) * 8) - __builtin_clzll(w);
99} 99}
100 100
101static inline unsigned int __arch_hweight32(unsigned int w) 101static inline unsigned int __arch_hweight32(unsigned int w)
diff --git a/arch/tile/include/asm/byteorder.h b/arch/tile/include/asm/byteorder.h
index 9558416d578b..fb72ecf49218 100644
--- a/arch/tile/include/asm/byteorder.h
+++ b/arch/tile/include/asm/byteorder.h
@@ -1 +1,21 @@
1/*
2 * Copyright 2011 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#if defined (__BIG_ENDIAN__)
16#include <linux/byteorder/big_endian.h>
17#elif defined (__LITTLE_ENDIAN__)
1#include <linux/byteorder/little_endian.h> 18#include <linux/byteorder/little_endian.h>
19#else
20#error "__BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be defined."
21#endif
diff --git a/arch/tile/include/asm/cachectl.h b/arch/tile/include/asm/cachectl.h
new file mode 100644
index 000000000000..af4c9f9154d1
--- /dev/null
+++ b/arch/tile/include/asm/cachectl.h
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2011 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#ifndef _ASM_TILE_CACHECTL_H
16#define _ASM_TILE_CACHECTL_H
17
18/*
19 * Options for cacheflush system call.
20 *
21 * The ICACHE flush is performed on all cores currently running the
22 * current process's address space. The intent is for user
23 * applications to be able to modify code, invoke the system call,
24 * then allow arbitrary other threads in the same address space to see
25 * the newly-modified code. Passing a length of CHIP_L1I_CACHE_SIZE()
26 * or more invalidates the entire icache on all cores in the address
27 * spaces. (Note: currently this option invalidates the entire icache
28 * regardless of the requested address and length, but we may choose
29 * to honor the arguments at some point.)
30 *
31 * Flush and invalidation of memory can normally be performed with the
32 * __insn_flush(), __insn_inv(), and __insn_finv() instructions from
33 * userspace. The DCACHE option to the system call allows userspace
34 * to flush the entire L1+L2 data cache from the core. In this case,
35 * the address and length arguments are not used. The DCACHE flush is
36 * restricted to the current core, not all cores in the address space.
37 */
38#define ICACHE (1<<0) /* invalidate L1 instruction cache */
39#define DCACHE (1<<1) /* flush and invalidate data cache */
40#define BCACHE (ICACHE|DCACHE) /* flush both caches */
41
42#endif /* _ASM_TILE_CACHECTL_H */
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index 4b4b28969a65..69adc08d36a5 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -242,9 +242,6 @@ long compat_sys_fallocate(int fd, int mode,
242long compat_sys_sched_rr_get_interval(compat_pid_t pid, 242long compat_sys_sched_rr_get_interval(compat_pid_t pid,
243 struct compat_timespec __user *interval); 243 struct compat_timespec __user *interval);
244 244
245/* Tilera Linux syscalls that don't have "compat" versions. */
246#define compat_sys_flush_cache sys_flush_cache
247
248/* These are the intvec_64.S trampolines. */ 245/* These are the intvec_64.S trampolines. */
249long _compat_sys_execve(const char __user *path, 246long _compat_sys_execve(const char __user *path,
250 const compat_uptr_t __user *argv, 247 const compat_uptr_t __user *argv,
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h
index 623a6bb741c1..d16d006d660e 100644
--- a/arch/tile/include/asm/elf.h
+++ b/arch/tile/include/asm/elf.h
@@ -44,7 +44,11 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
44#else 44#else
45#define ELF_CLASS ELFCLASS32 45#define ELF_CLASS ELFCLASS32
46#endif 46#endif
47#ifdef __BIG_ENDIAN__
48#define ELF_DATA ELFDATA2MSB
49#else
47#define ELF_DATA ELFDATA2LSB 50#define ELF_DATA ELFDATA2LSB
51#endif
48 52
49/* 53/*
50 * There seems to be a bug in how compat_binfmt_elf.c works: it 54 * There seems to be a bug in how compat_binfmt_elf.c works: it
@@ -59,6 +63,7 @@ enum { ELF_ARCH = CHIP_ELF_TYPE() };
59 */ 63 */
60#define elf_check_arch(x) \ 64#define elf_check_arch(x) \
61 ((x)->e_ident[EI_CLASS] == ELF_CLASS && \ 65 ((x)->e_ident[EI_CLASS] == ELF_CLASS && \
66 (x)->e_ident[EI_DATA] == ELF_DATA && \
62 (x)->e_machine == CHIP_ELF_TYPE()) 67 (x)->e_machine == CHIP_ELF_TYPE())
63 68
64/* The module loader only handles a few relocation types. */ 69/* The module loader only handles a few relocation types. */
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index d03ec124a598..5909ac3d7218 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -28,29 +28,81 @@
28#include <linux/futex.h> 28#include <linux/futex.h>
29#include <linux/uaccess.h> 29#include <linux/uaccess.h>
30#include <linux/errno.h> 30#include <linux/errno.h>
31#include <asm/atomic.h>
31 32
32extern struct __get_user futex_set(u32 __user *v, int i); 33/*
33extern struct __get_user futex_add(u32 __user *v, int n); 34 * Support macros for futex operations. Do not use these macros directly.
34extern struct __get_user futex_or(u32 __user *v, int n); 35 * They assume "ret", "val", "oparg", and "uaddr" in the lexical context.
35extern struct __get_user futex_andn(u32 __user *v, int n); 36 * __futex_cmpxchg() additionally assumes "oldval".
36extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n); 37 */
38
39#ifdef __tilegx__
40
41#define __futex_asm(OP) \
42 asm("1: {" #OP " %1, %3, %4; movei %0, 0 }\n" \
43 ".pushsection .fixup,\"ax\"\n" \
44 "0: { movei %0, %5; j 9f }\n" \
45 ".section __ex_table,\"a\"\n" \
46 ".quad 1b, 0b\n" \
47 ".popsection\n" \
48 "9:" \
49 : "=r" (ret), "=r" (val), "+m" (*(uaddr)) \
50 : "r" (uaddr), "r" (oparg), "i" (-EFAULT))
51
52#define __futex_set() __futex_asm(exch4)
53#define __futex_add() __futex_asm(fetchadd4)
54#define __futex_or() __futex_asm(fetchor4)
55#define __futex_andn() ({ oparg = ~oparg; __futex_asm(fetchand4); })
56#define __futex_cmpxchg() \
57 ({ __insn_mtspr(SPR_CMPEXCH_VALUE, oldval); __futex_asm(cmpexch4); })
58
59#define __futex_xor() \
60 ({ \
61 u32 oldval, n = oparg; \
62 if ((ret = __get_user(oldval, uaddr)) == 0) { \
63 do { \
64 oparg = oldval ^ n; \
65 __futex_cmpxchg(); \
66 } while (ret == 0 && oldval != val); \
67 } \
68 })
69
70/* No need to prefetch, since the atomic ops go to the home cache anyway. */
71#define __futex_prolog()
37 72
38#ifndef __tilegx__
39extern struct __get_user futex_xor(u32 __user *v, int n);
40#else 73#else
41static inline struct __get_user futex_xor(u32 __user *uaddr, int n) 74
42{ 75#define __futex_call(FN) \
43 struct __get_user asm_ret = __get_user_4(uaddr); 76 { \
44 if (!asm_ret.err) { 77 struct __get_user gu = FN((u32 __force *)uaddr, lock, oparg); \
45 int oldval, newval; 78 val = gu.val; \
46 do { 79 ret = gu.err; \
47 oldval = asm_ret.val;
48 newval = oldval ^ n;
49 asm_ret = futex_cmpxchg(uaddr, oldval, newval);
50 } while (asm_ret.err == 0 && oldval != asm_ret.val);
51 } 80 }
52 return asm_ret; 81
53} 82#define __futex_set() __futex_call(__atomic_xchg)
83#define __futex_add() __futex_call(__atomic_xchg_add)
84#define __futex_or() __futex_call(__atomic_or)
85#define __futex_andn() __futex_call(__atomic_andn)
86#define __futex_xor() __futex_call(__atomic_xor)
87
88#define __futex_cmpxchg() \
89 { \
90 struct __get_user gu = __atomic_cmpxchg((u32 __force *)uaddr, \
91 lock, oldval, oparg); \
92 val = gu.val; \
93 ret = gu.err; \
94 }
95
96/*
97 * Find the lock pointer for the atomic calls to use, and issue a
98 * prefetch to the user address to bring it into cache. Similar to
99 * __atomic_setup(), but we can't do a read into the L1 since it might
100 * fault; instead we do a prefetch into the L2.
101 */
102#define __futex_prolog() \
103 int *lock; \
104 __insn_prefetch(uaddr); \
105 lock = __atomic_hashed_lock((int __force *)uaddr)
54#endif 106#endif
55 107
56static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 108static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
@@ -59,8 +111,12 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
59 int cmp = (encoded_op >> 24) & 15; 111 int cmp = (encoded_op >> 24) & 15;
60 int oparg = (encoded_op << 8) >> 20; 112 int oparg = (encoded_op << 8) >> 20;
61 int cmparg = (encoded_op << 20) >> 20; 113 int cmparg = (encoded_op << 20) >> 20;
62 int ret; 114 int uninitialized_var(val), ret;
63 struct __get_user asm_ret; 115
116 __futex_prolog();
117
118 /* The 32-bit futex code makes this assumption, so validate it here. */
119 BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
64 120
65 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 121 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
66 oparg = 1 << oparg; 122 oparg = 1 << oparg;
@@ -71,46 +127,45 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
71 pagefault_disable(); 127 pagefault_disable();
72 switch (op) { 128 switch (op) {
73 case FUTEX_OP_SET: 129 case FUTEX_OP_SET:
74 asm_ret = futex_set(uaddr, oparg); 130 __futex_set();
75 break; 131 break;
76 case FUTEX_OP_ADD: 132 case FUTEX_OP_ADD:
77 asm_ret = futex_add(uaddr, oparg); 133 __futex_add();
78 break; 134 break;
79 case FUTEX_OP_OR: 135 case FUTEX_OP_OR:
80 asm_ret = futex_or(uaddr, oparg); 136 __futex_or();
81 break; 137 break;
82 case FUTEX_OP_ANDN: 138 case FUTEX_OP_ANDN:
83 asm_ret = futex_andn(uaddr, oparg); 139 __futex_andn();
84 break; 140 break;
85 case FUTEX_OP_XOR: 141 case FUTEX_OP_XOR:
86 asm_ret = futex_xor(uaddr, oparg); 142 __futex_xor();
87 break; 143 break;
88 default: 144 default:
89 asm_ret.err = -ENOSYS; 145 ret = -ENOSYS;
146 break;
90 } 147 }
91 pagefault_enable(); 148 pagefault_enable();
92 149
93 ret = asm_ret.err;
94
95 if (!ret) { 150 if (!ret) {
96 switch (cmp) { 151 switch (cmp) {
97 case FUTEX_OP_CMP_EQ: 152 case FUTEX_OP_CMP_EQ:
98 ret = (asm_ret.val == cmparg); 153 ret = (val == cmparg);
99 break; 154 break;
100 case FUTEX_OP_CMP_NE: 155 case FUTEX_OP_CMP_NE:
101 ret = (asm_ret.val != cmparg); 156 ret = (val != cmparg);
102 break; 157 break;
103 case FUTEX_OP_CMP_LT: 158 case FUTEX_OP_CMP_LT:
104 ret = (asm_ret.val < cmparg); 159 ret = (val < cmparg);
105 break; 160 break;
106 case FUTEX_OP_CMP_GE: 161 case FUTEX_OP_CMP_GE:
107 ret = (asm_ret.val >= cmparg); 162 ret = (val >= cmparg);
108 break; 163 break;
109 case FUTEX_OP_CMP_LE: 164 case FUTEX_OP_CMP_LE:
110 ret = (asm_ret.val <= cmparg); 165 ret = (val <= cmparg);
111 break; 166 break;
112 case FUTEX_OP_CMP_GT: 167 case FUTEX_OP_CMP_GT:
113 ret = (asm_ret.val > cmparg); 168 ret = (val > cmparg);
114 break; 169 break;
115 default: 170 default:
116 ret = -ENOSYS; 171 ret = -ENOSYS;
@@ -120,22 +175,20 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
120} 175}
121 176
122static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 177static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
123 u32 oldval, u32 newval) 178 u32 oldval, u32 oparg)
124{ 179{
125 struct __get_user asm_ret; 180 int ret, val;
181
182 __futex_prolog();
126 183
127 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 184 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
128 return -EFAULT; 185 return -EFAULT;
129 186
130 asm_ret = futex_cmpxchg(uaddr, oldval, newval); 187 __futex_cmpxchg();
131 *uval = asm_ret.val;
132 return asm_ret.err;
133}
134 188
135#ifndef __tilegx__ 189 *uval = val;
136/* Return failure from the atomic wrappers. */ 190 return ret;
137struct __get_user __atomic_bad_address(int __user *addr); 191}
138#endif
139 192
140#endif /* !__ASSEMBLY__ */ 193#endif /* !__ASSEMBLY__ */
141 194
diff --git a/arch/tile/include/asm/hardwall.h b/arch/tile/include/asm/hardwall.h
index 2ac422848c7d..47514a58d685 100644
--- a/arch/tile/include/asm/hardwall.h
+++ b/arch/tile/include/asm/hardwall.h
@@ -11,12 +11,14 @@
11 * NON INFRINGEMENT. See the GNU General Public License for 11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details. 12 * more details.
13 * 13 *
14 * Provide methods for the HARDWALL_FILE for accessing the UDN. 14 * Provide methods for access control of per-cpu resources like
15 * UDN, IDN, or IPI.
15 */ 16 */
16 17
17#ifndef _ASM_TILE_HARDWALL_H 18#ifndef _ASM_TILE_HARDWALL_H
18#define _ASM_TILE_HARDWALL_H 19#define _ASM_TILE_HARDWALL_H
19 20
21#include <arch/chip.h>
20#include <linux/ioctl.h> 22#include <linux/ioctl.h>
21 23
22#define HARDWALL_IOCTL_BASE 0xa2 24#define HARDWALL_IOCTL_BASE 0xa2
@@ -24,8 +26,9 @@
24/* 26/*
25 * The HARDWALL_CREATE() ioctl is a macro with a "size" argument. 27 * The HARDWALL_CREATE() ioctl is a macro with a "size" argument.
26 * The resulting ioctl value is passed to the kernel in conjunction 28 * The resulting ioctl value is passed to the kernel in conjunction
27 * with a pointer to a little-endian bitmask of cpus, which must be 29 * with a pointer to a standard kernel bitmask of cpus.
28 * physically in a rectangular configuration on the chip. 30 * For network resources (UDN or IDN) the bitmask must physically
31 * represent a rectangular configuration on the chip.
29 * The "size" is the number of bytes of cpu mask data. 32 * The "size" is the number of bytes of cpu mask data.
30 */ 33 */
31#define _HARDWALL_CREATE 1 34#define _HARDWALL_CREATE 1
@@ -44,13 +47,7 @@
44#define HARDWALL_GET_ID \ 47#define HARDWALL_GET_ID \
45 _IO(HARDWALL_IOCTL_BASE, _HARDWALL_GET_ID) 48 _IO(HARDWALL_IOCTL_BASE, _HARDWALL_GET_ID)
46 49
47#ifndef __KERNEL__ 50#ifdef __KERNEL__
48
49/* This is the canonical name expected by userspace. */
50#define HARDWALL_FILE "/dev/hardwall"
51
52#else
53
54/* /proc hooks for hardwall. */ 51/* /proc hooks for hardwall. */
55struct proc_dir_entry; 52struct proc_dir_entry;
56#ifdef CONFIG_HARDWALL 53#ifdef CONFIG_HARDWALL
@@ -59,7 +56,6 @@ int proc_pid_hardwall(struct task_struct *task, char *buffer);
59#else 56#else
60static inline void proc_tile_hardwall_init(struct proc_dir_entry *root) {} 57static inline void proc_tile_hardwall_init(struct proc_dir_entry *root) {}
61#endif 58#endif
62
63#endif 59#endif
64 60
65#endif /* _ASM_TILE_HARDWALL_H */ 61#endif /* _ASM_TILE_HARDWALL_H */
diff --git a/arch/tile/include/asm/hugetlb.h b/arch/tile/include/asm/hugetlb.h
index d396d1805163..b2042380a5aa 100644
--- a/arch/tile/include/asm/hugetlb.h
+++ b/arch/tile/include/asm/hugetlb.h
@@ -106,4 +106,25 @@ static inline void arch_release_hugepage(struct page *page)
106{ 106{
107} 107}
108 108
109#ifdef CONFIG_HUGETLB_SUPER_PAGES
110static inline pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
111 struct page *page, int writable)
112{
113 size_t pagesize = huge_page_size(hstate_vma(vma));
114 if (pagesize != PUD_SIZE && pagesize != PMD_SIZE)
115 entry = pte_mksuper(entry);
116 return entry;
117}
118#define arch_make_huge_pte arch_make_huge_pte
119
120/* Sizes to scale up page size for PTEs with HV_PTE_SUPER bit. */
121enum {
122 HUGE_SHIFT_PGDIR = 0,
123 HUGE_SHIFT_PMD = 1,
124 HUGE_SHIFT_PAGE = 2,
125 HUGE_SHIFT_ENTRIES
126};
127extern int huge_shift[HUGE_SHIFT_ENTRIES];
128#endif
129
109#endif /* _ASM_TILE_HUGETLB_H */ 130#endif /* _ASM_TILE_HUGETLB_H */
diff --git a/arch/tile/include/asm/irqflags.h b/arch/tile/include/asm/irqflags.h
index 5db0ce54284d..b4e96fef2cf8 100644
--- a/arch/tile/include/asm/irqflags.h
+++ b/arch/tile/include/asm/irqflags.h
@@ -28,10 +28,10 @@
28 */ 28 */
29#if CHIP_HAS_AUX_PERF_COUNTERS() 29#if CHIP_HAS_AUX_PERF_COUNTERS()
30#define LINUX_MASKABLE_INTERRUPTS_HI \ 30#define LINUX_MASKABLE_INTERRUPTS_HI \
31 (~(INT_MASK_HI(INT_PERF_COUNT) | INT_MASK_HI(INT_AUX_PERF_COUNT))) 31 (~(INT_MASK_HI(INT_PERF_COUNT) | INT_MASK_HI(INT_AUX_PERF_COUNT)))
32#else 32#else
33#define LINUX_MASKABLE_INTERRUPTS_HI \ 33#define LINUX_MASKABLE_INTERRUPTS_HI \
34 (~(INT_MASK_HI(INT_PERF_COUNT))) 34 (~(INT_MASK_HI(INT_PERF_COUNT)))
35#endif 35#endif
36 36
37#else 37#else
@@ -90,6 +90,14 @@
90 __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_0, (unsigned long)(__m)); \ 90 __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_0, (unsigned long)(__m)); \
91 __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_1, (unsigned long)(__m>>32)); \ 91 __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_1, (unsigned long)(__m>>32)); \
92} while (0) 92} while (0)
93#define interrupt_mask_save_mask() \
94 (__insn_mfspr(SPR_INTERRUPT_MASK_SET_K_0) | \
95 (((unsigned long long)__insn_mfspr(SPR_INTERRUPT_MASK_SET_K_1))<<32))
96#define interrupt_mask_restore_mask(mask) do { \
97 unsigned long long __m = (mask); \
98 __insn_mtspr(SPR_INTERRUPT_MASK_K_0, (unsigned long)(__m)); \
99 __insn_mtspr(SPR_INTERRUPT_MASK_K_1, (unsigned long)(__m>>32)); \
100} while (0)
93#else 101#else
94#define interrupt_mask_set(n) \ 102#define interrupt_mask_set(n) \
95 __insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (1UL << (n))) 103 __insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (1UL << (n)))
@@ -101,6 +109,10 @@
101 __insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (mask)) 109 __insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (mask))
102#define interrupt_mask_reset_mask(mask) \ 110#define interrupt_mask_reset_mask(mask) \
103 __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (mask)) 111 __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (mask))
112#define interrupt_mask_save_mask() \
113 __insn_mfspr(SPR_INTERRUPT_MASK_K)
114#define interrupt_mask_restore_mask(mask) \
115 __insn_mtspr(SPR_INTERRUPT_MASK_K, (mask))
104#endif 116#endif
105 117
106/* 118/*
@@ -122,7 +134,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
122 134
123/* Disable all interrupts, including NMIs. */ 135/* Disable all interrupts, including NMIs. */
124#define arch_local_irq_disable_all() \ 136#define arch_local_irq_disable_all() \
125 interrupt_mask_set_mask(-1UL) 137 interrupt_mask_set_mask(-1ULL)
126 138
127/* Re-enable all maskable interrupts. */ 139/* Re-enable all maskable interrupts. */
128#define arch_local_irq_enable() \ 140#define arch_local_irq_enable() \
@@ -179,7 +191,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
179#ifdef __tilegx__ 191#ifdef __tilegx__
180 192
181#if INT_MEM_ERROR != 0 193#if INT_MEM_ERROR != 0
182# error Fix IRQ_DISABLED() macro 194# error Fix IRQS_DISABLED() macro
183#endif 195#endif
184 196
185/* Return 0 or 1 to indicate whether interrupts are currently disabled. */ 197/* Return 0 or 1 to indicate whether interrupts are currently disabled. */
@@ -207,9 +219,10 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
207 mtspr SPR_INTERRUPT_MASK_SET_K, tmp 219 mtspr SPR_INTERRUPT_MASK_SET_K, tmp
208 220
209/* Enable interrupts. */ 221/* Enable interrupts. */
210#define IRQ_ENABLE(tmp0, tmp1) \ 222#define IRQ_ENABLE_LOAD(tmp0, tmp1) \
211 GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \ 223 GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \
212 ld tmp0, tmp0; \ 224 ld tmp0, tmp0
225#define IRQ_ENABLE_APPLY(tmp0, tmp1) \
213 mtspr SPR_INTERRUPT_MASK_RESET_K, tmp0 226 mtspr SPR_INTERRUPT_MASK_RESET_K, tmp0
214 227
215#else /* !__tilegx__ */ 228#else /* !__tilegx__ */
@@ -253,17 +266,22 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
253 mtspr SPR_INTERRUPT_MASK_SET_K_1, tmp 266 mtspr SPR_INTERRUPT_MASK_SET_K_1, tmp
254 267
255/* Enable interrupts. */ 268/* Enable interrupts. */
256#define IRQ_ENABLE(tmp0, tmp1) \ 269#define IRQ_ENABLE_LOAD(tmp0, tmp1) \
257 GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \ 270 GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \
258 { \ 271 { \
259 lw tmp0, tmp0; \ 272 lw tmp0, tmp0; \
260 addi tmp1, tmp0, 4 \ 273 addi tmp1, tmp0, 4 \
261 }; \ 274 }; \
262 lw tmp1, tmp1; \ 275 lw tmp1, tmp1
276#define IRQ_ENABLE_APPLY(tmp0, tmp1) \
263 mtspr SPR_INTERRUPT_MASK_RESET_K_0, tmp0; \ 277 mtspr SPR_INTERRUPT_MASK_RESET_K_0, tmp0; \
264 mtspr SPR_INTERRUPT_MASK_RESET_K_1, tmp1 278 mtspr SPR_INTERRUPT_MASK_RESET_K_1, tmp1
265#endif 279#endif
266 280
281#define IRQ_ENABLE(tmp0, tmp1) \
282 IRQ_ENABLE_LOAD(tmp0, tmp1); \
283 IRQ_ENABLE_APPLY(tmp0, tmp1)
284
267/* 285/*
268 * Do the CPU's IRQ-state tracing from assembly code. We call a 286 * Do the CPU's IRQ-state tracing from assembly code. We call a
269 * C function, but almost everywhere we do, we don't mind clobbering 287 * C function, but almost everywhere we do, we don't mind clobbering
diff --git a/arch/tile/include/asm/kexec.h b/arch/tile/include/asm/kexec.h
index c11a6cc73bb8..fc98ccfc98ac 100644
--- a/arch/tile/include/asm/kexec.h
+++ b/arch/tile/include/asm/kexec.h
@@ -19,12 +19,24 @@
19 19
20#include <asm/page.h> 20#include <asm/page.h>
21 21
22#ifndef __tilegx__
22/* Maximum physical address we can use pages from. */ 23/* Maximum physical address we can use pages from. */
23#define KEXEC_SOURCE_MEMORY_LIMIT TASK_SIZE 24#define KEXEC_SOURCE_MEMORY_LIMIT TASK_SIZE
24/* Maximum address we can reach in physical address mode. */ 25/* Maximum address we can reach in physical address mode. */
25#define KEXEC_DESTINATION_MEMORY_LIMIT TASK_SIZE 26#define KEXEC_DESTINATION_MEMORY_LIMIT TASK_SIZE
26/* Maximum address we can use for the control code buffer. */ 27/* Maximum address we can use for the control code buffer. */
27#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE 28#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
29#else
30/* We need to limit the memory below PGDIR_SIZE since
31 * we only setup page table for [0, PGDIR_SIZE) before final kexec.
32 */
33/* Maximum physical address we can use pages from. */
34#define KEXEC_SOURCE_MEMORY_LIMIT PGDIR_SIZE
35/* Maximum address we can reach in physical address mode. */
36#define KEXEC_DESTINATION_MEMORY_LIMIT PGDIR_SIZE
37/* Maximum address we can use for the control code buffer. */
38#define KEXEC_CONTROL_MEMORY_LIMIT PGDIR_SIZE
39#endif
28 40
29#define KEXEC_CONTROL_PAGE_SIZE PAGE_SIZE 41#define KEXEC_CONTROL_PAGE_SIZE PAGE_SIZE
30 42
diff --git a/arch/tile/include/asm/kvm_para.h b/arch/tile/include/asm/kvm_para.h
new file mode 100644
index 000000000000..14fab8f0b957
--- /dev/null
+++ b/arch/tile/include/asm/kvm_para.h
@@ -0,0 +1 @@
#include <asm-generic/kvm_para.h>
diff --git a/arch/tile/include/asm/mmu.h b/arch/tile/include/asm/mmu.h
index 92f94c77b6e4..e2c789096795 100644
--- a/arch/tile/include/asm/mmu.h
+++ b/arch/tile/include/asm/mmu.h
@@ -21,7 +21,7 @@ struct mm_context {
21 * Written under the mmap_sem semaphore; read without the 21 * Written under the mmap_sem semaphore; read without the
22 * semaphore but atomically, but it is conservatively set. 22 * semaphore but atomically, but it is conservatively set.
23 */ 23 */
24 unsigned int priority_cached; 24 unsigned long priority_cached;
25}; 25};
26 26
27typedef struct mm_context mm_context_t; 27typedef struct mm_context mm_context_t;
diff --git a/arch/tile/include/asm/mmu_context.h b/arch/tile/include/asm/mmu_context.h
index 15fb24641120..37f0b741dee7 100644
--- a/arch/tile/include/asm/mmu_context.h
+++ b/arch/tile/include/asm/mmu_context.h
@@ -30,11 +30,15 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
30 return 0; 30 return 0;
31} 31}
32 32
33/* Note that arch/tile/kernel/head.S also calls hv_install_context() */ 33/*
34 * Note that arch/tile/kernel/head_NN.S and arch/tile/mm/migrate_NN.S
35 * also call hv_install_context().
36 */
34static inline void __install_page_table(pgd_t *pgdir, int asid, pgprot_t prot) 37static inline void __install_page_table(pgd_t *pgdir, int asid, pgprot_t prot)
35{ 38{
36 /* FIXME: DIRECTIO should not always be set. FIXME. */ 39 /* FIXME: DIRECTIO should not always be set. FIXME. */
37 int rc = hv_install_context(__pa(pgdir), prot, asid, HV_CTX_DIRECTIO); 40 int rc = hv_install_context(__pa(pgdir), prot, asid,
41 HV_CTX_DIRECTIO | CTX_PAGE_FLAG);
38 if (rc < 0) 42 if (rc < 0)
39 panic("hv_install_context failed: %d", rc); 43 panic("hv_install_context failed: %d", rc);
40} 44}
diff --git a/arch/tile/include/asm/module.h b/arch/tile/include/asm/module.h
new file mode 100644
index 000000000000..44ed07ccd3d2
--- /dev/null
+++ b/arch/tile/include/asm/module.h
@@ -0,0 +1,40 @@
1/*
2 * Copyright 2011 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#ifndef _ASM_TILE_MODULE_H
16#define _ASM_TILE_MODULE_H
17
18#include <arch/chip.h>
19
20#include <asm-generic/module.h>
21
22/* We can't use modules built with different page sizes. */
23#if defined(CONFIG_PAGE_SIZE_16KB)
24# define MODULE_PGSZ " 16KB"
25#elif defined(CONFIG_PAGE_SIZE_64KB)
26# define MODULE_PGSZ " 64KB"
27#else
28# define MODULE_PGSZ ""
29#endif
30
31/* We don't really support no-SMP so tag if someone tries. */
32#ifdef CONFIG_SMP
33#define MODULE_NOSMP ""
34#else
35#define MODULE_NOSMP " nosmp"
36#endif
37
38#define MODULE_ARCH_VERMAGIC CHIP_ARCH_NAME MODULE_PGSZ MODULE_NOSMP
39
40#endif /* _ASM_TILE_MODULE_H */
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h
index db93518fac03..9d9131e5c552 100644
--- a/arch/tile/include/asm/page.h
+++ b/arch/tile/include/asm/page.h
@@ -20,8 +20,17 @@
20#include <arch/chip.h> 20#include <arch/chip.h>
21 21
22/* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */ 22/* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */
23#define PAGE_SHIFT HV_LOG2_PAGE_SIZE_SMALL 23#if defined(CONFIG_PAGE_SIZE_16KB)
24#define HPAGE_SHIFT HV_LOG2_PAGE_SIZE_LARGE 24#define PAGE_SHIFT 14
25#define CTX_PAGE_FLAG HV_CTX_PG_SM_16K
26#elif defined(CONFIG_PAGE_SIZE_64KB)
27#define PAGE_SHIFT 16
28#define CTX_PAGE_FLAG HV_CTX_PG_SM_64K
29#else
30#define PAGE_SHIFT HV_LOG2_DEFAULT_PAGE_SIZE_SMALL
31#define CTX_PAGE_FLAG 0
32#endif
33#define HPAGE_SHIFT HV_LOG2_DEFAULT_PAGE_SIZE_LARGE
25 34
26#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) 35#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
27#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT) 36#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
@@ -78,8 +87,7 @@ typedef HV_PTE pgprot_t;
78/* 87/*
79 * User L2 page tables are managed as one L2 page table per page, 88 * User L2 page tables are managed as one L2 page table per page,
80 * because we use the page allocator for them. This keeps the allocation 89 * because we use the page allocator for them. This keeps the allocation
81 * simple and makes it potentially useful to implement HIGHPTE at some point. 90 * simple, but it's also inefficient, since L2 page tables are much smaller
82 * However, it's also inefficient, since L2 page tables are much smaller
83 * than pages (currently 2KB vs 64KB). So we should revisit this. 91 * than pages (currently 2KB vs 64KB). So we should revisit this.
84 */ 92 */
85typedef struct page *pgtable_t; 93typedef struct page *pgtable_t;
@@ -128,7 +136,7 @@ static inline __attribute_const__ int get_order(unsigned long size)
128 136
129#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) 137#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
130 138
131#define HUGE_MAX_HSTATE 2 139#define HUGE_MAX_HSTATE 6
132 140
133#ifdef CONFIG_HUGETLB_PAGE 141#ifdef CONFIG_HUGETLB_PAGE
134#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA 142#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
diff --git a/arch/tile/include/asm/pgalloc.h b/arch/tile/include/asm/pgalloc.h
index e919c0bdc22d..1b902508b664 100644
--- a/arch/tile/include/asm/pgalloc.h
+++ b/arch/tile/include/asm/pgalloc.h
@@ -19,24 +19,24 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/mmzone.h> 20#include <linux/mmzone.h>
21#include <asm/fixmap.h> 21#include <asm/fixmap.h>
22#include <asm/page.h>
22#include <hv/hypervisor.h> 23#include <hv/hypervisor.h>
23 24
24/* Bits for the size of the second-level page table. */ 25/* Bits for the size of the second-level page table. */
25#define L2_KERNEL_PGTABLE_SHIFT \ 26#define L2_KERNEL_PGTABLE_SHIFT _HV_LOG2_L2_SIZE(HPAGE_SHIFT, PAGE_SHIFT)
26 (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL + HV_LOG2_PTE_SIZE) 27
28/* How big is a kernel L2 page table? */
29#define L2_KERNEL_PGTABLE_SIZE (1UL << L2_KERNEL_PGTABLE_SHIFT)
27 30
28/* We currently allocate user L2 page tables by page (unlike kernel L2s). */ 31/* We currently allocate user L2 page tables by page (unlike kernel L2s). */
29#if L2_KERNEL_PGTABLE_SHIFT < HV_LOG2_PAGE_SIZE_SMALL 32#if L2_KERNEL_PGTABLE_SHIFT < PAGE_SHIFT
30#define L2_USER_PGTABLE_SHIFT HV_LOG2_PAGE_SIZE_SMALL 33#define L2_USER_PGTABLE_SHIFT PAGE_SHIFT
31#else 34#else
32#define L2_USER_PGTABLE_SHIFT L2_KERNEL_PGTABLE_SHIFT 35#define L2_USER_PGTABLE_SHIFT L2_KERNEL_PGTABLE_SHIFT
33#endif 36#endif
34 37
35/* How many pages do we need, as an "order", for a user L2 page table? */ 38/* How many pages do we need, as an "order", for a user L2 page table? */
36#define L2_USER_PGTABLE_ORDER (L2_USER_PGTABLE_SHIFT - HV_LOG2_PAGE_SIZE_SMALL) 39#define L2_USER_PGTABLE_ORDER (L2_USER_PGTABLE_SHIFT - PAGE_SHIFT)
37
38/* How big is a kernel L2 page table? */
39#define L2_KERNEL_PGTABLE_SIZE (1 << L2_KERNEL_PGTABLE_SHIFT)
40 40
41static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) 41static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
42{ 42{
@@ -50,14 +50,14 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
50static inline void pmd_populate_kernel(struct mm_struct *mm, 50static inline void pmd_populate_kernel(struct mm_struct *mm,
51 pmd_t *pmd, pte_t *ptep) 51 pmd_t *pmd, pte_t *ptep)
52{ 52{
53 set_pmd(pmd, ptfn_pmd(__pa(ptep) >> HV_LOG2_PAGE_TABLE_ALIGN, 53 set_pmd(pmd, ptfn_pmd(HV_CPA_TO_PTFN(__pa(ptep)),
54 __pgprot(_PAGE_PRESENT))); 54 __pgprot(_PAGE_PRESENT)));
55} 55}
56 56
57static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, 57static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
58 pgtable_t page) 58 pgtable_t page)
59{ 59{
60 set_pmd(pmd, ptfn_pmd(HV_PFN_TO_PTFN(page_to_pfn(page)), 60 set_pmd(pmd, ptfn_pmd(HV_CPA_TO_PTFN(PFN_PHYS(page_to_pfn(page))),
61 __pgprot(_PAGE_PRESENT))); 61 __pgprot(_PAGE_PRESENT)));
62} 62}
63 63
@@ -68,8 +68,20 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
68extern pgd_t *pgd_alloc(struct mm_struct *mm); 68extern pgd_t *pgd_alloc(struct mm_struct *mm);
69extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); 69extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
70 70
71extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address); 71extern pgtable_t pgtable_alloc_one(struct mm_struct *mm, unsigned long address,
72extern void pte_free(struct mm_struct *mm, struct page *pte); 72 int order);
73extern void pgtable_free(struct mm_struct *mm, struct page *pte, int order);
74
75static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
76 unsigned long address)
77{
78 return pgtable_alloc_one(mm, address, L2_USER_PGTABLE_ORDER);
79}
80
81static inline void pte_free(struct mm_struct *mm, struct page *pte)
82{
83 pgtable_free(mm, pte, L2_USER_PGTABLE_ORDER);
84}
73 85
74#define pmd_pgtable(pmd) pmd_page(pmd) 86#define pmd_pgtable(pmd) pmd_page(pmd)
75 87
@@ -85,8 +97,13 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
85 pte_free(mm, virt_to_page(pte)); 97 pte_free(mm, virt_to_page(pte));
86} 98}
87 99
88extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, 100extern void __pgtable_free_tlb(struct mmu_gather *tlb, struct page *pte,
89 unsigned long address); 101 unsigned long address, int order);
102static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
103 unsigned long address)
104{
105 __pgtable_free_tlb(tlb, pte, address, L2_USER_PGTABLE_ORDER);
106}
90 107
91#define check_pgt_cache() do { } while (0) 108#define check_pgt_cache() do { } while (0)
92 109
@@ -104,19 +121,44 @@ void shatter_pmd(pmd_t *pmd);
104void shatter_huge_page(unsigned long addr); 121void shatter_huge_page(unsigned long addr);
105 122
106#ifdef __tilegx__ 123#ifdef __tilegx__
107/* We share a single page allocator for both L1 and L2 page tables. */ 124
108#if HV_L1_SIZE != HV_L2_SIZE
109# error Rework assumption that L1 and L2 page tables are same size.
110#endif
111#define L1_USER_PGTABLE_ORDER L2_USER_PGTABLE_ORDER
112#define pud_populate(mm, pud, pmd) \ 125#define pud_populate(mm, pud, pmd) \
113 pmd_populate_kernel((mm), (pmd_t *)(pud), (pte_t *)(pmd)) 126 pmd_populate_kernel((mm), (pmd_t *)(pud), (pte_t *)(pmd))
114#define pmd_alloc_one(mm, addr) \ 127
115 ((pmd_t *)page_to_virt(pte_alloc_one((mm), (addr)))) 128/* Bits for the size of the L1 (intermediate) page table. */
116#define pmd_free(mm, pmdp) \ 129#define L1_KERNEL_PGTABLE_SHIFT _HV_LOG2_L1_SIZE(HPAGE_SHIFT)
117 pte_free((mm), virt_to_page(pmdp)) 130
118#define __pmd_free_tlb(tlb, pmdp, address) \ 131/* How big is a kernel L2 page table? */
119 __pte_free_tlb((tlb), virt_to_page(pmdp), (address)) 132#define L1_KERNEL_PGTABLE_SIZE (1UL << L1_KERNEL_PGTABLE_SHIFT)
133
134/* We currently allocate L1 page tables by page. */
135#if L1_KERNEL_PGTABLE_SHIFT < PAGE_SHIFT
136#define L1_USER_PGTABLE_SHIFT PAGE_SHIFT
137#else
138#define L1_USER_PGTABLE_SHIFT L1_KERNEL_PGTABLE_SHIFT
120#endif 139#endif
121 140
141/* How many pages do we need, as an "order", for an L1 page table? */
142#define L1_USER_PGTABLE_ORDER (L1_USER_PGTABLE_SHIFT - PAGE_SHIFT)
143
144static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
145{
146 struct page *p = pgtable_alloc_one(mm, address, L1_USER_PGTABLE_ORDER);
147 return (pmd_t *)page_to_virt(p);
148}
149
150static inline void pmd_free(struct mm_struct *mm, pmd_t *pmdp)
151{
152 pgtable_free(mm, virt_to_page(pmdp), L1_USER_PGTABLE_ORDER);
153}
154
155static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
156 unsigned long address)
157{
158 __pgtable_free_tlb(tlb, virt_to_page(pmdp), address,
159 L1_USER_PGTABLE_ORDER);
160}
161
162#endif /* __tilegx__ */
163
122#endif /* _ASM_TILE_PGALLOC_H */ 164#endif /* _ASM_TILE_PGALLOC_H */
diff --git a/arch/tile/include/asm/pgtable.h b/arch/tile/include/asm/pgtable.h
index 67490910774d..73b1a4c9ad03 100644
--- a/arch/tile/include/asm/pgtable.h
+++ b/arch/tile/include/asm/pgtable.h
@@ -27,8 +27,10 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/list.h> 28#include <linux/list.h>
29#include <linux/spinlock.h> 29#include <linux/spinlock.h>
30#include <linux/pfn.h>
30#include <asm/processor.h> 31#include <asm/processor.h>
31#include <asm/fixmap.h> 32#include <asm/fixmap.h>
33#include <asm/page.h>
32 34
33struct mm_struct; 35struct mm_struct;
34struct vm_area_struct; 36struct vm_area_struct;
@@ -69,6 +71,7 @@ extern void set_page_homes(void);
69 71
70#define _PAGE_PRESENT HV_PTE_PRESENT 72#define _PAGE_PRESENT HV_PTE_PRESENT
71#define _PAGE_HUGE_PAGE HV_PTE_PAGE 73#define _PAGE_HUGE_PAGE HV_PTE_PAGE
74#define _PAGE_SUPER_PAGE HV_PTE_SUPER
72#define _PAGE_READABLE HV_PTE_READABLE 75#define _PAGE_READABLE HV_PTE_READABLE
73#define _PAGE_WRITABLE HV_PTE_WRITABLE 76#define _PAGE_WRITABLE HV_PTE_WRITABLE
74#define _PAGE_EXECUTABLE HV_PTE_EXECUTABLE 77#define _PAGE_EXECUTABLE HV_PTE_EXECUTABLE
@@ -85,6 +88,7 @@ extern void set_page_homes(void);
85#define _PAGE_ALL (\ 88#define _PAGE_ALL (\
86 _PAGE_PRESENT | \ 89 _PAGE_PRESENT | \
87 _PAGE_HUGE_PAGE | \ 90 _PAGE_HUGE_PAGE | \
91 _PAGE_SUPER_PAGE | \
88 _PAGE_READABLE | \ 92 _PAGE_READABLE | \
89 _PAGE_WRITABLE | \ 93 _PAGE_WRITABLE | \
90 _PAGE_EXECUTABLE | \ 94 _PAGE_EXECUTABLE | \
@@ -162,7 +166,7 @@ extern void set_page_homes(void);
162 (pgprot_t) { ((oldprot).val & ~_PAGE_ALL) | (newprot).val } 166 (pgprot_t) { ((oldprot).val & ~_PAGE_ALL) | (newprot).val }
163 167
164/* Just setting the PFN to zero suffices. */ 168/* Just setting the PFN to zero suffices. */
165#define pte_pgprot(x) hv_pte_set_pfn((x), 0) 169#define pte_pgprot(x) hv_pte_set_pa((x), 0)
166 170
167/* 171/*
168 * For PTEs and PDEs, we must clear the Present bit first when 172 * For PTEs and PDEs, we must clear the Present bit first when
@@ -187,6 +191,7 @@ static inline void __pte_clear(pte_t *ptep)
187 * Undefined behaviour if not.. 191 * Undefined behaviour if not..
188 */ 192 */
189#define pte_present hv_pte_get_present 193#define pte_present hv_pte_get_present
194#define pte_mknotpresent hv_pte_clear_present
190#define pte_user hv_pte_get_user 195#define pte_user hv_pte_get_user
191#define pte_read hv_pte_get_readable 196#define pte_read hv_pte_get_readable
192#define pte_dirty hv_pte_get_dirty 197#define pte_dirty hv_pte_get_dirty
@@ -194,6 +199,7 @@ static inline void __pte_clear(pte_t *ptep)
194#define pte_write hv_pte_get_writable 199#define pte_write hv_pte_get_writable
195#define pte_exec hv_pte_get_executable 200#define pte_exec hv_pte_get_executable
196#define pte_huge hv_pte_get_page 201#define pte_huge hv_pte_get_page
202#define pte_super hv_pte_get_super
197#define pte_rdprotect hv_pte_clear_readable 203#define pte_rdprotect hv_pte_clear_readable
198#define pte_exprotect hv_pte_clear_executable 204#define pte_exprotect hv_pte_clear_executable
199#define pte_mkclean hv_pte_clear_dirty 205#define pte_mkclean hv_pte_clear_dirty
@@ -206,6 +212,7 @@ static inline void __pte_clear(pte_t *ptep)
206#define pte_mkyoung hv_pte_set_accessed 212#define pte_mkyoung hv_pte_set_accessed
207#define pte_mkwrite hv_pte_set_writable 213#define pte_mkwrite hv_pte_set_writable
208#define pte_mkhuge hv_pte_set_page 214#define pte_mkhuge hv_pte_set_page
215#define pte_mksuper hv_pte_set_super
209 216
210#define pte_special(pte) 0 217#define pte_special(pte) 0
211#define pte_mkspecial(pte) (pte) 218#define pte_mkspecial(pte) (pte)
@@ -261,7 +268,7 @@ static inline int pte_none(pte_t pte)
261 268
262static inline unsigned long pte_pfn(pte_t pte) 269static inline unsigned long pte_pfn(pte_t pte)
263{ 270{
264 return hv_pte_get_pfn(pte); 271 return PFN_DOWN(hv_pte_get_pa(pte));
265} 272}
266 273
267/* Set or get the remote cache cpu in a pgprot with remote caching. */ 274/* Set or get the remote cache cpu in a pgprot with remote caching. */
@@ -270,7 +277,7 @@ extern int get_remote_cache_cpu(pgprot_t prot);
270 277
271static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) 278static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
272{ 279{
273 return hv_pte_set_pfn(prot, pfn); 280 return hv_pte_set_pa(prot, PFN_PHYS(pfn));
274} 281}
275 282
276/* Support for priority mappings. */ 283/* Support for priority mappings. */
@@ -312,7 +319,7 @@ extern void check_mm_caching(struct mm_struct *prev, struct mm_struct *next);
312 */ 319 */
313static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 320static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
314{ 321{
315 return pfn_pte(hv_pte_get_pfn(pte), newprot); 322 return pfn_pte(pte_pfn(pte), newprot);
316} 323}
317 324
318/* 325/*
@@ -335,13 +342,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
335 */ 342 */
336#define pgd_offset_k(address) pgd_offset(&init_mm, address) 343#define pgd_offset_k(address) pgd_offset(&init_mm, address)
337 344
338#if defined(CONFIG_HIGHPTE)
339extern pte_t *pte_offset_map(pmd_t *, unsigned long address);
340#define pte_unmap(pte) kunmap_atomic(pte)
341#else
342#define pte_offset_map(dir, address) pte_offset_kernel(dir, address) 345#define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
343#define pte_unmap(pte) do { } while (0) 346#define pte_unmap(pte) do { } while (0)
344#endif
345 347
346/* Clear a non-executable kernel PTE and flush it from the TLB. */ 348/* Clear a non-executable kernel PTE and flush it from the TLB. */
347#define kpte_clear_flush(ptep, vaddr) \ 349#define kpte_clear_flush(ptep, vaddr) \
@@ -410,6 +412,46 @@ static inline unsigned long pmd_index(unsigned long address)
410 return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); 412 return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
411} 413}
412 414
415#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
416static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
417 unsigned long address,
418 pmd_t *pmdp)
419{
420 return ptep_test_and_clear_young(vma, address, pmdp_ptep(pmdp));
421}
422
423#define __HAVE_ARCH_PMDP_SET_WRPROTECT
424static inline void pmdp_set_wrprotect(struct mm_struct *mm,
425 unsigned long address, pmd_t *pmdp)
426{
427 ptep_set_wrprotect(mm, address, pmdp_ptep(pmdp));
428}
429
430
431#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
432static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
433 unsigned long address,
434 pmd_t *pmdp)
435{
436 return pte_pmd(ptep_get_and_clear(mm, address, pmdp_ptep(pmdp)));
437}
438
439static inline void __set_pmd(pmd_t *pmdp, pmd_t pmdval)
440{
441 set_pte(pmdp_ptep(pmdp), pmd_pte(pmdval));
442}
443
444#define set_pmd_at(mm, addr, pmdp, pmdval) __set_pmd(pmdp, pmdval)
445
446/* Create a pmd from a PTFN. */
447static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot)
448{
449 return pte_pmd(hv_pte_set_ptfn(prot, ptfn));
450}
451
452/* Return the page-table frame number (ptfn) that a pmd_t points at. */
453#define pmd_ptfn(pmd) hv_pte_get_ptfn(pmd_pte(pmd))
454
413/* 455/*
414 * A given kernel pmd_t maps to a specific virtual address (either a 456 * A given kernel pmd_t maps to a specific virtual address (either a
415 * kernel huge page or a kernel pte_t table). Since kernel pte_t 457 * kernel huge page or a kernel pte_t table). Since kernel pte_t
@@ -430,7 +472,48 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
430 * OK for pte_lockptr(), since we just end up with potentially one 472 * OK for pte_lockptr(), since we just end up with potentially one
431 * lock being used for several pte_t arrays. 473 * lock being used for several pte_t arrays.
432 */ 474 */
433#define pmd_page(pmd) pfn_to_page(HV_PTFN_TO_PFN(pmd_ptfn(pmd))) 475#define pmd_page(pmd) pfn_to_page(PFN_DOWN(HV_PTFN_TO_CPA(pmd_ptfn(pmd))))
476
477static inline void pmd_clear(pmd_t *pmdp)
478{
479 __pte_clear(pmdp_ptep(pmdp));
480}
481
482#define pmd_mknotpresent(pmd) pte_pmd(pte_mknotpresent(pmd_pte(pmd)))
483#define pmd_young(pmd) pte_young(pmd_pte(pmd))
484#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
485#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
486#define pmd_mkwrite(pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd)))
487#define pmd_write(pmd) pte_write(pmd_pte(pmd))
488#define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
489#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd)))
490#define pmd_huge_page(pmd) pte_huge(pmd_pte(pmd))
491#define pmd_mkhuge(pmd) pte_pmd(pte_mkhuge(pmd_pte(pmd)))
492#define __HAVE_ARCH_PMD_WRITE
493
494#define pfn_pmd(pfn, pgprot) pte_pmd(pfn_pte((pfn), (pgprot)))
495#define pmd_pfn(pmd) pte_pfn(pmd_pte(pmd))
496#define mk_pmd(page, pgprot) pfn_pmd(page_to_pfn(page), (pgprot))
497
498static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
499{
500 return pfn_pmd(pmd_pfn(pmd), newprot);
501}
502
503#ifdef CONFIG_TRANSPARENT_HUGEPAGE
504#define has_transparent_hugepage() 1
505#define pmd_trans_huge pmd_huge_page
506
507static inline pmd_t pmd_mksplitting(pmd_t pmd)
508{
509 return pte_pmd(hv_pte_set_client2(pmd_pte(pmd)));
510}
511
512static inline int pmd_trans_splitting(pmd_t pmd)
513{
514 return hv_pte_get_client2(pmd_pte(pmd));
515}
516#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
434 517
435/* 518/*
436 * The pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] 519 * The pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
@@ -448,17 +531,13 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address)
448 return (pte_t *)pmd_page_vaddr(*pmd) + pte_index(address); 531 return (pte_t *)pmd_page_vaddr(*pmd) + pte_index(address);
449} 532}
450 533
451static inline int pmd_huge_page(pmd_t pmd)
452{
453 return pmd_val(pmd) & _PAGE_HUGE_PAGE;
454}
455
456#include <asm-generic/pgtable.h> 534#include <asm-generic/pgtable.h>
457 535
458/* Support /proc/NN/pgtable API. */ 536/* Support /proc/NN/pgtable API. */
459struct seq_file; 537struct seq_file;
460int arch_proc_pgtable_show(struct seq_file *m, struct mm_struct *mm, 538int arch_proc_pgtable_show(struct seq_file *m, struct mm_struct *mm,
461 unsigned long vaddr, pte_t *ptep, void **datap); 539 unsigned long vaddr, unsigned long pagesize,
540 pte_t *ptep, void **datap);
462 541
463#endif /* !__ASSEMBLY__ */ 542#endif /* !__ASSEMBLY__ */
464 543
diff --git a/arch/tile/include/asm/pgtable_32.h b/arch/tile/include/asm/pgtable_32.h
index 9f98529761fd..4ce4a7a99c24 100644
--- a/arch/tile/include/asm/pgtable_32.h
+++ b/arch/tile/include/asm/pgtable_32.h
@@ -20,11 +20,12 @@
20 * The level-1 index is defined by the huge page size. A PGD is composed 20 * The level-1 index is defined by the huge page size. A PGD is composed
21 * of PTRS_PER_PGD pgd_t's and is the top level of the page table. 21 * of PTRS_PER_PGD pgd_t's and is the top level of the page table.
22 */ 22 */
23#define PGDIR_SHIFT HV_LOG2_PAGE_SIZE_LARGE 23#define PGDIR_SHIFT HPAGE_SHIFT
24#define PGDIR_SIZE HV_PAGE_SIZE_LARGE 24#define PGDIR_SIZE HPAGE_SIZE
25#define PGDIR_MASK (~(PGDIR_SIZE-1)) 25#define PGDIR_MASK (~(PGDIR_SIZE-1))
26#define PTRS_PER_PGD (1 << (32 - PGDIR_SHIFT)) 26#define PTRS_PER_PGD _HV_L1_ENTRIES(HPAGE_SHIFT)
27#define SIZEOF_PGD (PTRS_PER_PGD * sizeof(pgd_t)) 27#define PGD_INDEX(va) _HV_L1_INDEX(va, HPAGE_SHIFT)
28#define SIZEOF_PGD _HV_L1_SIZE(HPAGE_SHIFT)
28 29
29/* 30/*
30 * The level-2 index is defined by the difference between the huge 31 * The level-2 index is defined by the difference between the huge
@@ -33,8 +34,9 @@
33 * Note that the hypervisor docs use PTE for what we call pte_t, so 34 * Note that the hypervisor docs use PTE for what we call pte_t, so
34 * this nomenclature is somewhat confusing. 35 * this nomenclature is somewhat confusing.
35 */ 36 */
36#define PTRS_PER_PTE (1 << (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL)) 37#define PTRS_PER_PTE _HV_L2_ENTRIES(HPAGE_SHIFT, PAGE_SHIFT)
37#define SIZEOF_PTE (PTRS_PER_PTE * sizeof(pte_t)) 38#define PTE_INDEX(va) _HV_L2_INDEX(va, HPAGE_SHIFT, PAGE_SHIFT)
39#define SIZEOF_PTE _HV_L2_SIZE(HPAGE_SHIFT, PAGE_SHIFT)
38 40
39#ifndef __ASSEMBLY__ 41#ifndef __ASSEMBLY__
40 42
@@ -111,24 +113,14 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
111 return pte; 113 return pte;
112} 114}
113 115
114static inline void __set_pmd(pmd_t *pmdp, pmd_t pmdval) 116/*
115{ 117 * pmds are wrappers around pgds, which are the same as ptes.
116 set_pte(&pmdp->pud.pgd, pmdval.pud.pgd); 118 * It's often convenient to "cast" back and forth and use the pte methods,
117} 119 * which are the methods supplied by the hypervisor.
118 120 */
119/* Create a pmd from a PTFN. */ 121#define pmd_pte(pmd) ((pmd).pud.pgd)
120static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot) 122#define pmdp_ptep(pmdp) (&(pmdp)->pud.pgd)
121{ 123#define pte_pmd(pte) ((pmd_t){ { (pte) } })
122 return (pmd_t){ { hv_pte_set_ptfn(prot, ptfn) } };
123}
124
125/* Return the page-table frame number (ptfn) that a pmd_t points at. */
126#define pmd_ptfn(pmd) hv_pte_get_ptfn((pmd).pud.pgd)
127
128static inline void pmd_clear(pmd_t *pmdp)
129{
130 __pte_clear(&pmdp->pud.pgd);
131}
132 124
133#endif /* __ASSEMBLY__ */ 125#endif /* __ASSEMBLY__ */
134 126
diff --git a/arch/tile/include/asm/pgtable_64.h b/arch/tile/include/asm/pgtable_64.h
index fd80328523b4..2492fa5478e7 100644
--- a/arch/tile/include/asm/pgtable_64.h
+++ b/arch/tile/include/asm/pgtable_64.h
@@ -21,17 +21,19 @@
21#define PGDIR_SIZE HV_L1_SPAN 21#define PGDIR_SIZE HV_L1_SPAN
22#define PGDIR_MASK (~(PGDIR_SIZE-1)) 22#define PGDIR_MASK (~(PGDIR_SIZE-1))
23#define PTRS_PER_PGD HV_L0_ENTRIES 23#define PTRS_PER_PGD HV_L0_ENTRIES
24#define SIZEOF_PGD (PTRS_PER_PGD * sizeof(pgd_t)) 24#define PGD_INDEX(va) HV_L0_INDEX(va)
25#define SIZEOF_PGD HV_L0_SIZE
25 26
26/* 27/*
27 * The level-1 index is defined by the huge page size. A PMD is composed 28 * The level-1 index is defined by the huge page size. A PMD is composed
28 * of PTRS_PER_PMD pgd_t's and is the middle level of the page table. 29 * of PTRS_PER_PMD pgd_t's and is the middle level of the page table.
29 */ 30 */
30#define PMD_SHIFT HV_LOG2_PAGE_SIZE_LARGE 31#define PMD_SHIFT HPAGE_SHIFT
31#define PMD_SIZE HV_PAGE_SIZE_LARGE 32#define PMD_SIZE HPAGE_SIZE
32#define PMD_MASK (~(PMD_SIZE-1)) 33#define PMD_MASK (~(PMD_SIZE-1))
33#define PTRS_PER_PMD (1 << (PGDIR_SHIFT - PMD_SHIFT)) 34#define PTRS_PER_PMD _HV_L1_ENTRIES(HPAGE_SHIFT)
34#define SIZEOF_PMD (PTRS_PER_PMD * sizeof(pmd_t)) 35#define PMD_INDEX(va) _HV_L1_INDEX(va, HPAGE_SHIFT)
36#define SIZEOF_PMD _HV_L1_SIZE(HPAGE_SHIFT)
35 37
36/* 38/*
37 * The level-2 index is defined by the difference between the huge 39 * The level-2 index is defined by the difference between the huge
@@ -40,17 +42,19 @@
40 * Note that the hypervisor docs use PTE for what we call pte_t, so 42 * Note that the hypervisor docs use PTE for what we call pte_t, so
41 * this nomenclature is somewhat confusing. 43 * this nomenclature is somewhat confusing.
42 */ 44 */
43#define PTRS_PER_PTE (1 << (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL)) 45#define PTRS_PER_PTE _HV_L2_ENTRIES(HPAGE_SHIFT, PAGE_SHIFT)
44#define SIZEOF_PTE (PTRS_PER_PTE * sizeof(pte_t)) 46#define PTE_INDEX(va) _HV_L2_INDEX(va, HPAGE_SHIFT, PAGE_SHIFT)
47#define SIZEOF_PTE _HV_L2_SIZE(HPAGE_SHIFT, PAGE_SHIFT)
45 48
46/* 49/*
47 * Align the vmalloc area to an L2 page table, and leave a guard page 50 * Align the vmalloc area to an L2 page table. Omit guard pages at
48 * at the beginning and end. The vmalloc code also puts in an internal 51 * the beginning and end for simplicity (particularly in the per-cpu
52 * memory allocation code). The vmalloc code puts in an internal
49 * guard page between each allocation. 53 * guard page between each allocation.
50 */ 54 */
51#define _VMALLOC_END HUGE_VMAP_BASE 55#define _VMALLOC_END HUGE_VMAP_BASE
52#define VMALLOC_END (_VMALLOC_END - PAGE_SIZE) 56#define VMALLOC_END _VMALLOC_END
53#define VMALLOC_START (_VMALLOC_START + PAGE_SIZE) 57#define VMALLOC_START _VMALLOC_START
54 58
55#define HUGE_VMAP_END (HUGE_VMAP_BASE + PGDIR_SIZE) 59#define HUGE_VMAP_END (HUGE_VMAP_BASE + PGDIR_SIZE)
56 60
@@ -98,7 +102,7 @@ static inline int pud_bad(pud_t pud)
98 * A pud_t points to a pmd_t array. Since we can have multiple per 102 * A pud_t points to a pmd_t array. Since we can have multiple per
99 * page, we don't have a one-to-one mapping of pud_t's to pages. 103 * page, we don't have a one-to-one mapping of pud_t's to pages.
100 */ 104 */
101#define pud_page(pud) pfn_to_page(HV_PTFN_TO_PFN(pud_ptfn(pud))) 105#define pud_page(pud) pfn_to_page(PFN_DOWN(HV_PTFN_TO_CPA(pud_ptfn(pud))))
102 106
103static inline unsigned long pud_index(unsigned long address) 107static inline unsigned long pud_index(unsigned long address)
104{ 108{
@@ -108,28 +112,6 @@ static inline unsigned long pud_index(unsigned long address)
108#define pmd_offset(pud, address) \ 112#define pmd_offset(pud, address) \
109 ((pmd_t *)pud_page_vaddr(*(pud)) + pmd_index(address)) 113 ((pmd_t *)pud_page_vaddr(*(pud)) + pmd_index(address))
110 114
111static inline void __set_pmd(pmd_t *pmdp, pmd_t pmdval)
112{
113 set_pte(pmdp, pmdval);
114}
115
116/* Create a pmd from a PTFN and pgprot. */
117static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot)
118{
119 return hv_pte_set_ptfn(prot, ptfn);
120}
121
122/* Return the page-table frame number (ptfn) that a pmd_t points at. */
123static inline unsigned long pmd_ptfn(pmd_t pmd)
124{
125 return hv_pte_get_ptfn(pmd);
126}
127
128static inline void pmd_clear(pmd_t *pmdp)
129{
130 __pte_clear(pmdp);
131}
132
133/* Normalize an address to having the correct high bits set. */ 115/* Normalize an address to having the correct high bits set. */
134#define pgd_addr_normalize pgd_addr_normalize 116#define pgd_addr_normalize pgd_addr_normalize
135static inline unsigned long pgd_addr_normalize(unsigned long addr) 117static inline unsigned long pgd_addr_normalize(unsigned long addr)
@@ -170,6 +152,13 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
170 return hv_pte(__insn_exch(&ptep->val, 0UL)); 152 return hv_pte(__insn_exch(&ptep->val, 0UL));
171} 153}
172 154
155/*
156 * pmds are the same as pgds and ptes, so converting is a no-op.
157 */
158#define pmd_pte(pmd) (pmd)
159#define pmdp_ptep(pmdp) (pmdp)
160#define pte_pmd(pte) (pte)
161
173#endif /* __ASSEMBLY__ */ 162#endif /* __ASSEMBLY__ */
174 163
175#endif /* _ASM_TILE_PGTABLE_64_H */ 164#endif /* _ASM_TILE_PGTABLE_64_H */
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index 15cd8a4a06ce..8c4dd9ff91eb 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -76,6 +76,17 @@ struct async_tlb {
76 76
77#ifdef CONFIG_HARDWALL 77#ifdef CONFIG_HARDWALL
78struct hardwall_info; 78struct hardwall_info;
79struct hardwall_task {
80 /* Which hardwall is this task tied to? (or NULL if none) */
81 struct hardwall_info *info;
82 /* Chains this task into the list at info->task_head. */
83 struct list_head list;
84};
85#ifdef __tilepro__
86#define HARDWALL_TYPES 1 /* udn */
87#else
88#define HARDWALL_TYPES 3 /* udn, idn, and ipi */
89#endif
79#endif 90#endif
80 91
81struct thread_struct { 92struct thread_struct {
@@ -116,10 +127,8 @@ struct thread_struct {
116 unsigned long dstream_pf; 127 unsigned long dstream_pf;
117#endif 128#endif
118#ifdef CONFIG_HARDWALL 129#ifdef CONFIG_HARDWALL
119 /* Is this task tied to an activated hardwall? */ 130 /* Hardwall information for various resources. */
120 struct hardwall_info *hardwall; 131 struct hardwall_task hardwall[HARDWALL_TYPES];
121 /* Chains this task into the list at hardwall->list. */
122 struct list_head hardwall_list;
123#endif 132#endif
124#if CHIP_HAS_TILE_DMA() 133#if CHIP_HAS_TILE_DMA()
125 /* Async DMA TLB fault information */ 134 /* Async DMA TLB fault information */
diff --git a/arch/tile/include/asm/setup.h b/arch/tile/include/asm/setup.h
index e58613e0752f..c67eb70ea78e 100644
--- a/arch/tile/include/asm/setup.h
+++ b/arch/tile/include/asm/setup.h
@@ -41,15 +41,15 @@ void restrict_dma_mpls(void);
41#ifdef CONFIG_HARDWALL 41#ifdef CONFIG_HARDWALL
42/* User-level network management functions */ 42/* User-level network management functions */
43void reset_network_state(void); 43void reset_network_state(void);
44void grant_network_mpls(void);
45void restrict_network_mpls(void);
46struct task_struct; 44struct task_struct;
47int hardwall_deactivate(struct task_struct *task); 45void hardwall_switch_tasks(struct task_struct *prev, struct task_struct *next);
46void hardwall_deactivate_all(struct task_struct *task);
47int hardwall_ipi_valid(int cpu);
48 48
49/* Hook hardwall code into changes in affinity. */ 49/* Hook hardwall code into changes in affinity. */
50#define arch_set_cpus_allowed(p, new_mask) do { \ 50#define arch_set_cpus_allowed(p, new_mask) do { \
51 if (p->thread.hardwall && !cpumask_equal(&p->cpus_allowed, new_mask)) \ 51 if (!cpumask_equal(&p->cpus_allowed, new_mask)) \
52 hardwall_deactivate(p); \ 52 hardwall_deactivate_all(p); \
53} while (0) 53} while (0)
54#endif 54#endif
55 55
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h
index 3b5507c31eae..06f0464cfed9 100644
--- a/arch/tile/include/asm/syscalls.h
+++ b/arch/tile/include/asm/syscalls.h
@@ -43,7 +43,8 @@ long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi,
43 u32 len, int advice); 43 u32 len, int advice);
44int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi, 44int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi,
45 u32 len_lo, u32 len_hi, int advice); 45 u32 len_lo, u32 len_hi, int advice);
46long sys_flush_cache(void); 46long sys_cacheflush(unsigned long addr, unsigned long len,
47 unsigned long flags);
47#ifndef __tilegx__ /* No mmap() in the 32-bit kernel. */ 48#ifndef __tilegx__ /* No mmap() in the 32-bit kernel. */
48#define sys_mmap sys_mmap 49#define sys_mmap sys_mmap
49#endif 50#endif
diff --git a/arch/tile/include/asm/tlbflush.h b/arch/tile/include/asm/tlbflush.h
index 96199d214fb8..dcf91b25a1e5 100644
--- a/arch/tile/include/asm/tlbflush.h
+++ b/arch/tile/include/asm/tlbflush.h
@@ -38,16 +38,11 @@ DECLARE_PER_CPU(int, current_asid);
38/* The hypervisor tells us what ASIDs are available to us. */ 38/* The hypervisor tells us what ASIDs are available to us. */
39extern int min_asid, max_asid; 39extern int min_asid, max_asid;
40 40
41static inline unsigned long hv_page_size(const struct vm_area_struct *vma)
42{
43 return (vma->vm_flags & VM_HUGETLB) ? HPAGE_SIZE : PAGE_SIZE;
44}
45
46/* Pass as vma pointer for non-executable mapping, if no vma available. */ 41/* Pass as vma pointer for non-executable mapping, if no vma available. */
47#define FLUSH_NONEXEC ((const struct vm_area_struct *)-1UL) 42#define FLUSH_NONEXEC ((struct vm_area_struct *)-1UL)
48 43
49/* Flush a single user page on this cpu. */ 44/* Flush a single user page on this cpu. */
50static inline void local_flush_tlb_page(const struct vm_area_struct *vma, 45static inline void local_flush_tlb_page(struct vm_area_struct *vma,
51 unsigned long addr, 46 unsigned long addr,
52 unsigned long page_size) 47 unsigned long page_size)
53{ 48{
@@ -60,7 +55,7 @@ static inline void local_flush_tlb_page(const struct vm_area_struct *vma,
60} 55}
61 56
62/* Flush range of user pages on this cpu. */ 57/* Flush range of user pages on this cpu. */
63static inline void local_flush_tlb_pages(const struct vm_area_struct *vma, 58static inline void local_flush_tlb_pages(struct vm_area_struct *vma,
64 unsigned long addr, 59 unsigned long addr,
65 unsigned long page_size, 60 unsigned long page_size,
66 unsigned long len) 61 unsigned long len)
@@ -117,10 +112,10 @@ extern void flush_tlb_all(void);
117extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); 112extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
118extern void flush_tlb_current_task(void); 113extern void flush_tlb_current_task(void);
119extern void flush_tlb_mm(struct mm_struct *); 114extern void flush_tlb_mm(struct mm_struct *);
120extern void flush_tlb_page(const struct vm_area_struct *, unsigned long); 115extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
121extern void flush_tlb_page_mm(const struct vm_area_struct *, 116extern void flush_tlb_page_mm(struct vm_area_struct *,
122 struct mm_struct *, unsigned long); 117 struct mm_struct *, unsigned long);
123extern void flush_tlb_range(const struct vm_area_struct *, 118extern void flush_tlb_range(struct vm_area_struct *,
124 unsigned long start, unsigned long end); 119 unsigned long start, unsigned long end);
125 120
126#define flush_tlb() flush_tlb_current_task() 121#define flush_tlb() flush_tlb_current_task()
diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h
index ef34d2caa5b1..c3dd275f25e2 100644
--- a/arch/tile/include/asm/uaccess.h
+++ b/arch/tile/include/asm/uaccess.h
@@ -114,45 +114,75 @@ struct exception_table_entry {
114extern int fixup_exception(struct pt_regs *regs); 114extern int fixup_exception(struct pt_regs *regs);
115 115
116/* 116/*
117 * We return the __get_user_N function results in a structure, 117 * Support macros for __get_user().
118 * thus in r0 and r1. If "err" is zero, "val" is the result 118 *
119 * of the read; otherwise, "err" is -EFAULT. 119 * Implementation note: The "case 8" logic of casting to the type of
120 * 120 * the result of subtracting the value from itself is basically a way
121 * We rarely need 8-byte values on a 32-bit architecture, but 121 * of keeping all integer types the same, but casting any pointers to
122 * we size the structure to accommodate. In practice, for the 122 * ptrdiff_t, i.e. also an integer type. This way there are no
123 * the smaller reads, we can zero the high word for free, and 123 * questionable casts seen by the compiler on an ILP32 platform.
124 * the caller will ignore it by virtue of casting anyway. 124 *
125 * Note that __get_user() and __put_user() assume proper alignment.
125 */ 126 */
126struct __get_user {
127 unsigned long long val;
128 int err;
129};
130 127
131/* 128#ifdef __LP64__
132 * FIXME: we should express these as inline extended assembler, since 129#define _ASM_PTR ".quad"
133 * they're fundamentally just a variable dereference and some 130#else
134 * supporting exception_table gunk. Note that (a la i386) we can 131#define _ASM_PTR ".long"
135 * extend the copy_to_user and copy_from_user routines to call into 132#endif
136 * such extended assembler routines, though we will have to use a 133
137 * different return code in that case (1, 2, or 4, rather than -EFAULT). 134#define __get_user_asm(OP, x, ptr, ret) \
138 */ 135 asm volatile("1: {" #OP " %1, %2; movei %0, 0 }\n" \
139extern struct __get_user __get_user_1(const void __user *); 136 ".pushsection .fixup,\"ax\"\n" \
140extern struct __get_user __get_user_2(const void __user *); 137 "0: { movei %1, 0; movei %0, %3 }\n" \
141extern struct __get_user __get_user_4(const void __user *); 138 "j 9f\n" \
142extern struct __get_user __get_user_8(const void __user *); 139 ".section __ex_table,\"a\"\n" \
143extern int __put_user_1(long, void __user *); 140 _ASM_PTR " 1b, 0b\n" \
144extern int __put_user_2(long, void __user *); 141 ".popsection\n" \
145extern int __put_user_4(long, void __user *); 142 "9:" \
146extern int __put_user_8(long long, void __user *); 143 : "=r" (ret), "=r" (x) \
147 144 : "r" (ptr), "i" (-EFAULT))
148/* Unimplemented routines to cause linker failures */ 145
149extern struct __get_user __get_user_bad(void); 146#ifdef __tilegx__
150extern int __put_user_bad(void); 147#define __get_user_1(x, ptr, ret) __get_user_asm(ld1u, x, ptr, ret)
148#define __get_user_2(x, ptr, ret) __get_user_asm(ld2u, x, ptr, ret)
149#define __get_user_4(x, ptr, ret) __get_user_asm(ld4u, x, ptr, ret)
150#define __get_user_8(x, ptr, ret) __get_user_asm(ld, x, ptr, ret)
151#else
152#define __get_user_1(x, ptr, ret) __get_user_asm(lb_u, x, ptr, ret)
153#define __get_user_2(x, ptr, ret) __get_user_asm(lh_u, x, ptr, ret)
154#define __get_user_4(x, ptr, ret) __get_user_asm(lw, x, ptr, ret)
155#ifdef __LITTLE_ENDIAN
156#define __lo32(a, b) a
157#define __hi32(a, b) b
158#else
159#define __lo32(a, b) b
160#define __hi32(a, b) a
161#endif
162#define __get_user_8(x, ptr, ret) \
163 ({ \
164 unsigned int __a, __b; \
165 asm volatile("1: { lw %1, %3; addi %2, %3, 4 }\n" \
166 "2: { lw %2, %2; movei %0, 0 }\n" \
167 ".pushsection .fixup,\"ax\"\n" \
168 "0: { movei %1, 0; movei %2, 0 }\n" \
169 "{ movei %0, %4; j 9f }\n" \
170 ".section __ex_table,\"a\"\n" \
171 ".word 1b, 0b\n" \
172 ".word 2b, 0b\n" \
173 ".popsection\n" \
174 "9:" \
175 : "=r" (ret), "=r" (__a), "=&r" (__b) \
176 : "r" (ptr), "i" (-EFAULT)); \
177 (x) = (__typeof(x))(__typeof((x)-(x))) \
178 (((u64)__hi32(__a, __b) << 32) | \
179 __lo32(__a, __b)); \
180 })
181#endif
182
183extern int __get_user_bad(void)
184 __attribute__((warning("sizeof __get_user argument not 1, 2, 4 or 8")));
151 185
152/*
153 * Careful: we have to cast the result to the type of the pointer
154 * for sign reasons.
155 */
156/** 186/**
157 * __get_user: - Get a simple variable from user space, with less checking. 187 * __get_user: - Get a simple variable from user space, with less checking.
158 * @x: Variable to store result. 188 * @x: Variable to store result.
@@ -174,30 +204,62 @@ extern int __put_user_bad(void);
174 * function. 204 * function.
175 */ 205 */
176#define __get_user(x, ptr) \ 206#define __get_user(x, ptr) \
177({ struct __get_user __ret; \ 207 ({ \
178 __typeof__(*(ptr)) const __user *__gu_addr = (ptr); \ 208 int __ret; \
179 __chk_user_ptr(__gu_addr); \ 209 __chk_user_ptr(ptr); \
180 switch (sizeof(*(__gu_addr))) { \ 210 switch (sizeof(*(ptr))) { \
181 case 1: \ 211 case 1: __get_user_1(x, ptr, __ret); break; \
182 __ret = __get_user_1(__gu_addr); \ 212 case 2: __get_user_2(x, ptr, __ret); break; \
183 break; \ 213 case 4: __get_user_4(x, ptr, __ret); break; \
184 case 2: \ 214 case 8: __get_user_8(x, ptr, __ret); break; \
185 __ret = __get_user_2(__gu_addr); \ 215 default: __ret = __get_user_bad(); break; \
186 break; \ 216 } \
187 case 4: \ 217 __ret; \
188 __ret = __get_user_4(__gu_addr); \ 218 })
189 break; \ 219
190 case 8: \ 220/* Support macros for __put_user(). */
191 __ret = __get_user_8(__gu_addr); \ 221
192 break; \ 222#define __put_user_asm(OP, x, ptr, ret) \
193 default: \ 223 asm volatile("1: {" #OP " %1, %2; movei %0, 0 }\n" \
194 __ret = __get_user_bad(); \ 224 ".pushsection .fixup,\"ax\"\n" \
195 break; \ 225 "0: { movei %0, %3; j 9f }\n" \
196 } \ 226 ".section __ex_table,\"a\"\n" \
197 (x) = (__typeof__(*__gu_addr)) (__typeof__(*__gu_addr - *__gu_addr)) \ 227 _ASM_PTR " 1b, 0b\n" \
198 __ret.val; \ 228 ".popsection\n" \
199 __ret.err; \ 229 "9:" \
200}) 230 : "=r" (ret) \
231 : "r" (ptr), "r" (x), "i" (-EFAULT))
232
233#ifdef __tilegx__
234#define __put_user_1(x, ptr, ret) __put_user_asm(st1, x, ptr, ret)
235#define __put_user_2(x, ptr, ret) __put_user_asm(st2, x, ptr, ret)
236#define __put_user_4(x, ptr, ret) __put_user_asm(st4, x, ptr, ret)
237#define __put_user_8(x, ptr, ret) __put_user_asm(st, x, ptr, ret)
238#else
239#define __put_user_1(x, ptr, ret) __put_user_asm(sb, x, ptr, ret)
240#define __put_user_2(x, ptr, ret) __put_user_asm(sh, x, ptr, ret)
241#define __put_user_4(x, ptr, ret) __put_user_asm(sw, x, ptr, ret)
242#define __put_user_8(x, ptr, ret) \
243 ({ \
244 u64 __x = (__typeof((x)-(x)))(x); \
245 int __lo = (int) __x, __hi = (int) (__x >> 32); \
246 asm volatile("1: { sw %1, %2; addi %0, %1, 4 }\n" \
247 "2: { sw %0, %3; movei %0, 0 }\n" \
248 ".pushsection .fixup,\"ax\"\n" \
249 "0: { movei %0, %4; j 9f }\n" \
250 ".section __ex_table,\"a\"\n" \
251 ".word 1b, 0b\n" \
252 ".word 2b, 0b\n" \
253 ".popsection\n" \
254 "9:" \
255 : "=&r" (ret) \
256 : "r" (ptr), "r" (__lo32(__lo, __hi)), \
257 "r" (__hi32(__lo, __hi)), "i" (-EFAULT)); \
258 })
259#endif
260
261extern int __put_user_bad(void)
262 __attribute__((warning("sizeof __put_user argument not 1, 2, 4 or 8")));
201 263
202/** 264/**
203 * __put_user: - Write a simple value into user space, with less checking. 265 * __put_user: - Write a simple value into user space, with less checking.
@@ -217,39 +279,19 @@ extern int __put_user_bad(void);
217 * function. 279 * function.
218 * 280 *
219 * Returns zero on success, or -EFAULT on error. 281 * Returns zero on success, or -EFAULT on error.
220 *
221 * Implementation note: The "case 8" logic of casting to the type of
222 * the result of subtracting the value from itself is basically a way
223 * of keeping all integer types the same, but casting any pointers to
224 * ptrdiff_t, i.e. also an integer type. This way there are no
225 * questionable casts seen by the compiler on an ILP32 platform.
226 */ 282 */
227#define __put_user(x, ptr) \ 283#define __put_user(x, ptr) \
228({ \ 284({ \
229 int __pu_err = 0; \ 285 int __ret; \
230 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ 286 __chk_user_ptr(ptr); \
231 typeof(*__pu_addr) __pu_val = (x); \ 287 switch (sizeof(*(ptr))) { \
232 __chk_user_ptr(__pu_addr); \ 288 case 1: __put_user_1(x, ptr, __ret); break; \
233 switch (sizeof(__pu_val)) { \ 289 case 2: __put_user_2(x, ptr, __ret); break; \
234 case 1: \ 290 case 4: __put_user_4(x, ptr, __ret); break; \
235 __pu_err = __put_user_1((long)__pu_val, __pu_addr); \ 291 case 8: __put_user_8(x, ptr, __ret); break; \
236 break; \ 292 default: __ret = __put_user_bad(); break; \
237 case 2: \
238 __pu_err = __put_user_2((long)__pu_val, __pu_addr); \
239 break; \
240 case 4: \
241 __pu_err = __put_user_4((long)__pu_val, __pu_addr); \
242 break; \
243 case 8: \
244 __pu_err = \
245 __put_user_8((__typeof__(__pu_val - __pu_val))__pu_val,\
246 __pu_addr); \
247 break; \
248 default: \
249 __pu_err = __put_user_bad(); \
250 break; \
251 } \ 293 } \
252 __pu_err; \ 294 __ret; \
253}) 295})
254 296
255/* 297/*
@@ -378,7 +420,7 @@ static inline unsigned long __must_check copy_from_user(void *to,
378/** 420/**
379 * __copy_in_user() - copy data within user space, with less checking. 421 * __copy_in_user() - copy data within user space, with less checking.
380 * @to: Destination address, in user space. 422 * @to: Destination address, in user space.
381 * @from: Source address, in kernel space. 423 * @from: Source address, in user space.
382 * @n: Number of bytes to copy. 424 * @n: Number of bytes to copy.
383 * 425 *
384 * Context: User context only. This function may sleep. 426 * Context: User context only. This function may sleep.
diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h
index f70bf1c541f1..a017246ca0ce 100644
--- a/arch/tile/include/asm/unistd.h
+++ b/arch/tile/include/asm/unistd.h
@@ -24,8 +24,8 @@
24#include <asm-generic/unistd.h> 24#include <asm-generic/unistd.h>
25 25
26/* Additional Tilera-specific syscalls. */ 26/* Additional Tilera-specific syscalls. */
27#define __NR_flush_cache (__NR_arch_specific_syscall + 1) 27#define __NR_cacheflush (__NR_arch_specific_syscall + 1)
28__SYSCALL(__NR_flush_cache, sys_flush_cache) 28__SYSCALL(__NR_cacheflush, sys_cacheflush)
29 29
30#ifndef __tilegx__ 30#ifndef __tilegx__
31/* "Fast" syscalls provide atomic support for 32-bit chips. */ 31/* "Fast" syscalls provide atomic support for 32-bit chips. */
diff --git a/arch/tile/include/hv/drv_xgbe_intf.h b/arch/tile/include/hv/drv_xgbe_intf.h
index f13188ac281a..2a20b266d944 100644
--- a/arch/tile/include/hv/drv_xgbe_intf.h
+++ b/arch/tile/include/hv/drv_xgbe_intf.h
@@ -460,7 +460,7 @@ typedef void* lepp_comp_t;
460 * linux's "MAX_SKB_FRAGS", and presumably over-estimates by one, for 460 * linux's "MAX_SKB_FRAGS", and presumably over-estimates by one, for
461 * our page size of exactly 65536. We add one for a "body" fragment. 461 * our page size of exactly 65536. We add one for a "body" fragment.
462 */ 462 */
463#define LEPP_MAX_FRAGS (65536 / HV_PAGE_SIZE_SMALL + 2 + 1) 463#define LEPP_MAX_FRAGS (65536 / HV_DEFAULT_PAGE_SIZE_SMALL + 2 + 1)
464 464
465/** Total number of bytes needed for an lepp_tso_cmd_t. */ 465/** Total number of bytes needed for an lepp_tso_cmd_t. */
466#define LEPP_TSO_CMD_SIZE(num_frags, header_size) \ 466#define LEPP_TSO_CMD_SIZE(num_frags, header_size) \
diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h
index 72ec1e972f15..ccd847e2347f 100644
--- a/arch/tile/include/hv/hypervisor.h
+++ b/arch/tile/include/hv/hypervisor.h
@@ -17,8 +17,8 @@
17 * The hypervisor's public API. 17 * The hypervisor's public API.
18 */ 18 */
19 19
20#ifndef _TILE_HV_H 20#ifndef _HV_HV_H
21#define _TILE_HV_H 21#define _HV_HV_H
22 22
23#include <arch/chip.h> 23#include <arch/chip.h>
24 24
@@ -42,25 +42,45 @@
42 */ 42 */
43#define HV_L1_SPAN (__HV_SIZE_ONE << HV_LOG2_L1_SPAN) 43#define HV_L1_SPAN (__HV_SIZE_ONE << HV_LOG2_L1_SPAN)
44 44
45/** The log2 of the size of small pages, in bytes. This value should 45/** The log2 of the initial size of small pages, in bytes.
46 * be verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL). 46 * See HV_DEFAULT_PAGE_SIZE_SMALL.
47 */ 47 */
48#define HV_LOG2_PAGE_SIZE_SMALL 16 48#define HV_LOG2_DEFAULT_PAGE_SIZE_SMALL 16
49 49
50/** The size of small pages, in bytes. This value should be verified 50/** The initial size of small pages, in bytes. This value should be verified
51 * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL). 51 * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL).
52 * It may also be modified when installing a new context.
52 */ 53 */
53#define HV_PAGE_SIZE_SMALL (__HV_SIZE_ONE << HV_LOG2_PAGE_SIZE_SMALL) 54#define HV_DEFAULT_PAGE_SIZE_SMALL \
55 (__HV_SIZE_ONE << HV_LOG2_DEFAULT_PAGE_SIZE_SMALL)
54 56
55/** The log2 of the size of large pages, in bytes. This value should be 57/** The log2 of the initial size of large pages, in bytes.
56 * verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE). 58 * See HV_DEFAULT_PAGE_SIZE_LARGE.
57 */ 59 */
58#define HV_LOG2_PAGE_SIZE_LARGE 24 60#define HV_LOG2_DEFAULT_PAGE_SIZE_LARGE 24
59 61
60/** The size of large pages, in bytes. This value should be verified 62/** The initial size of large pages, in bytes. This value should be verified
61 * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE). 63 * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE).
64 * It may also be modified when installing a new context.
62 */ 65 */
63#define HV_PAGE_SIZE_LARGE (__HV_SIZE_ONE << HV_LOG2_PAGE_SIZE_LARGE) 66#define HV_DEFAULT_PAGE_SIZE_LARGE \
67 (__HV_SIZE_ONE << HV_LOG2_DEFAULT_PAGE_SIZE_LARGE)
68
69#if CHIP_VA_WIDTH() > 32
70
71/** The log2 of the initial size of jumbo pages, in bytes.
72 * See HV_DEFAULT_PAGE_SIZE_JUMBO.
73 */
74#define HV_LOG2_DEFAULT_PAGE_SIZE_JUMBO 32
75
76/** The initial size of jumbo pages, in bytes. This value should
77 * be verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_JUMBO).
78 * It may also be modified when installing a new context.
79 */
80#define HV_DEFAULT_PAGE_SIZE_JUMBO \
81 (__HV_SIZE_ONE << HV_LOG2_DEFAULT_PAGE_SIZE_JUMBO)
82
83#endif
64 84
65/** The log2 of the granularity at which page tables must be aligned; 85/** The log2 of the granularity at which page tables must be aligned;
66 * in other words, the CPA for a page table must have this many zero 86 * in other words, the CPA for a page table must have this many zero
@@ -280,8 +300,11 @@
280#define HV_DISPATCH_GET_IPI_PTE 56 300#define HV_DISPATCH_GET_IPI_PTE 56
281#endif 301#endif
282 302
303/** hv_set_pte_super_shift */
304#define HV_DISPATCH_SET_PTE_SUPER_SHIFT 57
305
283/** One more than the largest dispatch value */ 306/** One more than the largest dispatch value */
284#define _HV_DISPATCH_END 57 307#define _HV_DISPATCH_END 58
285 308
286 309
287#ifndef __ASSEMBLER__ 310#ifndef __ASSEMBLER__
@@ -401,7 +424,18 @@ typedef enum {
401 * that the temperature has hit an upper limit and is no longer being 424 * that the temperature has hit an upper limit and is no longer being
402 * accurately tracked. 425 * accurately tracked.
403 */ 426 */
404 HV_SYSCONF_BOARD_TEMP = 6 427 HV_SYSCONF_BOARD_TEMP = 6,
428
429 /** Legal page size bitmask for hv_install_context().
430 * For example, if 16KB and 64KB small pages are supported,
431 * it would return "HV_CTX_PG_SM_16K | HV_CTX_PG_SM_64K".
432 */
433 HV_SYSCONF_VALID_PAGE_SIZES = 7,
434
435 /** The size of jumbo pages, in bytes.
436 * If no jumbo pages are available, zero will be returned.
437 */
438 HV_SYSCONF_PAGE_SIZE_JUMBO = 8,
405 439
406} HV_SysconfQuery; 440} HV_SysconfQuery;
407 441
@@ -474,7 +508,19 @@ typedef enum {
474 HV_CONFSTR_SWITCH_CONTROL = 14, 508 HV_CONFSTR_SWITCH_CONTROL = 14,
475 509
476 /** Chip revision level. */ 510 /** Chip revision level. */
477 HV_CONFSTR_CHIP_REV = 15 511 HV_CONFSTR_CHIP_REV = 15,
512
513 /** CPU module part number. */
514 HV_CONFSTR_CPUMOD_PART_NUM = 16,
515
516 /** CPU module serial number. */
517 HV_CONFSTR_CPUMOD_SERIAL_NUM = 17,
518
519 /** CPU module revision level. */
520 HV_CONFSTR_CPUMOD_REV = 18,
521
522 /** Human-readable CPU module description. */
523 HV_CONFSTR_CPUMOD_DESC = 19
478 524
479} HV_ConfstrQuery; 525} HV_ConfstrQuery;
480 526
@@ -494,11 +540,16 @@ int hv_confstr(HV_ConfstrQuery query, HV_VirtAddr buf, int len);
494/** Tile coordinate */ 540/** Tile coordinate */
495typedef struct 541typedef struct
496{ 542{
543#ifndef __BIG_ENDIAN__
497 /** X coordinate, relative to supervisor's top-left coordinate */ 544 /** X coordinate, relative to supervisor's top-left coordinate */
498 int x; 545 int x;
499 546
500 /** Y coordinate, relative to supervisor's top-left coordinate */ 547 /** Y coordinate, relative to supervisor's top-left coordinate */
501 int y; 548 int y;
549#else
550 int y;
551 int x;
552#endif
502} HV_Coord; 553} HV_Coord;
503 554
504 555
@@ -649,6 +700,12 @@ void hv_set_rtc(HV_RTCTime time);
649 * new page table does not need to contain any mapping for the 700 * new page table does not need to contain any mapping for the
650 * hv_install_context address itself. 701 * hv_install_context address itself.
651 * 702 *
703 * At most one HV_CTX_PG_SM_* flag may be specified in "flags";
704 * if multiple flags are specified, HV_EINVAL is returned.
705 * Specifying none of the flags results in using the default page size.
706 * All cores participating in a given client must request the same
707 * page size, or the results are undefined.
708 *
652 * @param page_table Root of the page table. 709 * @param page_table Root of the page table.
653 * @param access PTE providing info on how to read the page table. This 710 * @param access PTE providing info on how to read the page table. This
654 * value must be consistent between multiple tiles sharing a page table, 711 * value must be consistent between multiple tiles sharing a page table,
@@ -667,8 +724,36 @@ int hv_install_context(HV_PhysAddr page_table, HV_PTE access, HV_ASID asid,
667#define HV_CTX_DIRECTIO 0x1 /**< Direct I/O requests are accepted from 724#define HV_CTX_DIRECTIO 0x1 /**< Direct I/O requests are accepted from
668 PL0. */ 725 PL0. */
669 726
727#define HV_CTX_PG_SM_4K 0x10 /**< Use 4K small pages, if available. */
728#define HV_CTX_PG_SM_16K 0x20 /**< Use 16K small pages, if available. */
729#define HV_CTX_PG_SM_64K 0x40 /**< Use 64K small pages, if available. */
730#define HV_CTX_PG_SM_MASK 0xf0 /**< Mask of all possible small pages. */
731
670#ifndef __ASSEMBLER__ 732#ifndef __ASSEMBLER__
671 733
734
735/** Set the number of pages ganged together by HV_PTE_SUPER at a
736 * particular level of the page table.
737 *
738 * The current TILE-Gx hardware only supports powers of four
739 * (i.e. log2_count must be a multiple of two), and the requested
740 * "super" page size must be less than the span of the next level in
741 * the page table. The largest size that can be requested is 64GB.
742 *
743 * The shift value is initially "0" for all page table levels,
744 * indicating that the HV_PTE_SUPER bit is effectively ignored.
745 *
746 * If you change the count from one non-zero value to another, the
747 * hypervisor will flush the entire TLB and TSB to avoid confusion.
748 *
749 * @param level Page table level (0, 1, or 2)
750 * @param log2_count Base-2 log of the number of pages to gang together,
751 * i.e. how much to shift left the base page size for the super page size.
752 * @return Zero on success, or a hypervisor error code on failure.
753 */
754int hv_set_pte_super_shift(int level, int log2_count);
755
756
672/** Value returned from hv_inquire_context(). */ 757/** Value returned from hv_inquire_context(). */
673typedef struct 758typedef struct
674{ 759{
@@ -986,8 +1071,13 @@ HV_VirtAddrRange hv_inquire_virtual(int idx);
986/** A range of ASID values. */ 1071/** A range of ASID values. */
987typedef struct 1072typedef struct
988{ 1073{
1074#ifndef __BIG_ENDIAN__
989 HV_ASID start; /**< First ASID in the range. */ 1075 HV_ASID start; /**< First ASID in the range. */
990 unsigned int size; /**< Number of ASIDs. Zero for an invalid range. */ 1076 unsigned int size; /**< Number of ASIDs. Zero for an invalid range. */
1077#else
1078 unsigned int size; /**< Number of ASIDs. Zero for an invalid range. */
1079 HV_ASID start; /**< First ASID in the range. */
1080#endif
991} HV_ASIDRange; 1081} HV_ASIDRange;
992 1082
993/** Returns information about a range of ASIDs. 1083/** Returns information about a range of ASIDs.
@@ -1238,11 +1328,14 @@ HV_Errno hv_set_command_line(HV_VirtAddr buf, int length);
1238 * with the existing priority pages) or "red/black" (if they don't). 1328 * with the existing priority pages) or "red/black" (if they don't).
1239 * The bitmask provides information on which parts of the cache 1329 * The bitmask provides information on which parts of the cache
1240 * have been used for pinned pages so far on this tile; if (1 << N) 1330 * have been used for pinned pages so far on this tile; if (1 << N)
1241 * appears in the bitmask, that indicates that a page has been marked 1331 * appears in the bitmask, that indicates that a 4KB region of the
1242 * "priority" whose PFN equals N, mod 8. 1332 * cache starting at (N * 4KB) is in use by a "priority" page.
1333 * The portion of cache used by a particular page can be computed
1334 * by taking the page's PA, modulo CHIP_L2_CACHE_SIZE(), and setting
1335 * all the "4KB" bits corresponding to the actual page size.
1243 * @param bitmask A bitmap of priority page set values 1336 * @param bitmask A bitmap of priority page set values
1244 */ 1337 */
1245void hv_set_caching(unsigned int bitmask); 1338void hv_set_caching(unsigned long bitmask);
1246 1339
1247 1340
1248/** Zero out a specified number of pages. 1341/** Zero out a specified number of pages.
@@ -1308,6 +1401,7 @@ typedef enum
1308/** Message recipient. */ 1401/** Message recipient. */
1309typedef struct 1402typedef struct
1310{ 1403{
1404#ifndef __BIG_ENDIAN__
1311 /** X coordinate, relative to supervisor's top-left coordinate */ 1405 /** X coordinate, relative to supervisor's top-left coordinate */
1312 unsigned int x:11; 1406 unsigned int x:11;
1313 1407
@@ -1316,6 +1410,11 @@ typedef struct
1316 1410
1317 /** Status of this recipient */ 1411 /** Status of this recipient */
1318 HV_Recip_State state:10; 1412 HV_Recip_State state:10;
1413#else //__BIG_ENDIAN__
1414 HV_Recip_State state:10;
1415 unsigned int y:11;
1416 unsigned int x:11;
1417#endif
1319} HV_Recipient; 1418} HV_Recipient;
1320 1419
1321/** Send a message to a set of recipients. 1420/** Send a message to a set of recipients.
@@ -1851,12 +1950,12 @@ int hv_flush_remote(HV_PhysAddr cache_pa, unsigned long cache_control,
1851#define HV_PTE_INDEX_USER 10 /**< Page is user-accessible */ 1950#define HV_PTE_INDEX_USER 10 /**< Page is user-accessible */
1852#define HV_PTE_INDEX_ACCESSED 11 /**< Page has been accessed */ 1951#define HV_PTE_INDEX_ACCESSED 11 /**< Page has been accessed */
1853#define HV_PTE_INDEX_DIRTY 12 /**< Page has been written */ 1952#define HV_PTE_INDEX_DIRTY 12 /**< Page has been written */
1854 /* Bits 13-15 are reserved for 1953 /* Bits 13-14 are reserved for
1855 future use. */ 1954 future use. */
1955#define HV_PTE_INDEX_SUPER 15 /**< Pages ganged together for TLB */
1856#define HV_PTE_INDEX_MODE 16 /**< Page mode; see HV_PTE_MODE_xxx */ 1956#define HV_PTE_INDEX_MODE 16 /**< Page mode; see HV_PTE_MODE_xxx */
1857#define HV_PTE_MODE_BITS 3 /**< Number of bits in mode */ 1957#define HV_PTE_MODE_BITS 3 /**< Number of bits in mode */
1858 /* Bit 19 is reserved for 1958#define HV_PTE_INDEX_CLIENT2 19 /**< Page client state 2 */
1859 future use. */
1860#define HV_PTE_INDEX_LOTAR 20 /**< Page's LOTAR; must be high bits 1959#define HV_PTE_INDEX_LOTAR 20 /**< Page's LOTAR; must be high bits
1861 of word */ 1960 of word */
1862#define HV_PTE_LOTAR_BITS 12 /**< Number of bits in a LOTAR */ 1961#define HV_PTE_LOTAR_BITS 12 /**< Number of bits in a LOTAR */
@@ -1869,15 +1968,6 @@ int hv_flush_remote(HV_PhysAddr cache_pa, unsigned long cache_control,
1869 of word */ 1968 of word */
1870#define HV_PTE_PTFN_BITS 29 /**< Number of bits in a PTFN */ 1969#define HV_PTE_PTFN_BITS 29 /**< Number of bits in a PTFN */
1871 1970
1872/** Position of the PFN field within the PTE (subset of the PTFN). */
1873#define HV_PTE_INDEX_PFN (HV_PTE_INDEX_PTFN + (HV_LOG2_PAGE_SIZE_SMALL - \
1874 HV_LOG2_PAGE_TABLE_ALIGN))
1875
1876/** Length of the PFN field within the PTE (subset of the PTFN). */
1877#define HV_PTE_INDEX_PFN_BITS (HV_PTE_INDEX_PTFN_BITS - \
1878 (HV_LOG2_PAGE_SIZE_SMALL - \
1879 HV_LOG2_PAGE_TABLE_ALIGN))
1880
1881/* 1971/*
1882 * Legal values for the PTE's mode field 1972 * Legal values for the PTE's mode field
1883 */ 1973 */
@@ -1957,7 +2047,10 @@ int hv_flush_remote(HV_PhysAddr cache_pa, unsigned long cache_control,
1957 2047
1958/** Does this PTE map a page? 2048/** Does this PTE map a page?
1959 * 2049 *
1960 * If this bit is set in the level-1 page table, the entry should be 2050 * If this bit is set in a level-0 page table, the entry should be
2051 * interpreted as a level-2 page table entry mapping a jumbo page.
2052 *
2053 * If this bit is set in a level-1 page table, the entry should be
1961 * interpreted as a level-2 page table entry mapping a large page. 2054 * interpreted as a level-2 page table entry mapping a large page.
1962 * 2055 *
1963 * This bit should not be modified by the client while PRESENT is set, as 2056 * This bit should not be modified by the client while PRESENT is set, as
@@ -1967,6 +2060,18 @@ int hv_flush_remote(HV_PhysAddr cache_pa, unsigned long cache_control,
1967 */ 2060 */
1968#define HV_PTE_PAGE (__HV_PTE_ONE << HV_PTE_INDEX_PAGE) 2061#define HV_PTE_PAGE (__HV_PTE_ONE << HV_PTE_INDEX_PAGE)
1969 2062
2063/** Does this PTE implicitly reference multiple pages?
2064 *
2065 * If this bit is set in the page table (either in the level-2 page table,
2066 * or in a higher level page table in conjunction with the PAGE bit)
2067 * then the PTE specifies a range of contiguous pages, not a single page.
2068 * The hv_set_pte_super_shift() allows you to specify the count for
2069 * each level of the page table.
2070 *
2071 * Note: this bit is not supported on TILEPro systems.
2072 */
2073#define HV_PTE_SUPER (__HV_PTE_ONE << HV_PTE_INDEX_SUPER)
2074
1970/** Is this a global (non-ASID) mapping? 2075/** Is this a global (non-ASID) mapping?
1971 * 2076 *
1972 * If this bit is set, the translations established by this PTE will 2077 * If this bit is set, the translations established by this PTE will
@@ -2046,6 +2151,13 @@ int hv_flush_remote(HV_PhysAddr cache_pa, unsigned long cache_control,
2046 */ 2151 */
2047#define HV_PTE_CLIENT1 (__HV_PTE_ONE << HV_PTE_INDEX_CLIENT1) 2152#define HV_PTE_CLIENT1 (__HV_PTE_ONE << HV_PTE_INDEX_CLIENT1)
2048 2153
2154/** Client-private bit in PTE.
2155 *
2156 * This bit is guaranteed not to be inspected or modified by the
2157 * hypervisor.
2158 */
2159#define HV_PTE_CLIENT2 (__HV_PTE_ONE << HV_PTE_INDEX_CLIENT2)
2160
2049/** Non-coherent (NC) bit in PTE. 2161/** Non-coherent (NC) bit in PTE.
2050 * 2162 *
2051 * If this bit is set, the mapping that is set up will be non-coherent 2163 * If this bit is set, the mapping that is set up will be non-coherent
@@ -2178,8 +2290,10 @@ hv_pte_clear_##name(HV_PTE pte) \
2178 */ 2290 */
2179_HV_BIT(present, PRESENT) 2291_HV_BIT(present, PRESENT)
2180_HV_BIT(page, PAGE) 2292_HV_BIT(page, PAGE)
2293_HV_BIT(super, SUPER)
2181_HV_BIT(client0, CLIENT0) 2294_HV_BIT(client0, CLIENT0)
2182_HV_BIT(client1, CLIENT1) 2295_HV_BIT(client1, CLIENT1)
2296_HV_BIT(client2, CLIENT2)
2183_HV_BIT(migrating, MIGRATING) 2297_HV_BIT(migrating, MIGRATING)
2184_HV_BIT(nc, NC) 2298_HV_BIT(nc, NC)
2185_HV_BIT(readable, READABLE) 2299_HV_BIT(readable, READABLE)
@@ -2222,40 +2336,11 @@ hv_pte_set_mode(HV_PTE pte, unsigned int val)
2222 * 2336 *
2223 * This field contains the upper bits of the CPA (client physical 2337 * This field contains the upper bits of the CPA (client physical
2224 * address) of the target page; the complete CPA is this field with 2338 * address) of the target page; the complete CPA is this field with
2225 * HV_LOG2_PAGE_SIZE_SMALL zero bits appended to it. 2339 * HV_LOG2_PAGE_TABLE_ALIGN zero bits appended to it.
2226 *
2227 * For PTEs in a level-1 page table where the Page bit is set, the
2228 * CPA must be aligned modulo the large page size.
2229 */
2230static __inline unsigned int
2231hv_pte_get_pfn(const HV_PTE pte)
2232{
2233 return pte.val >> HV_PTE_INDEX_PFN;
2234}
2235
2236
2237/** Set the page frame number into a PTE. See hv_pte_get_pfn. */
2238static __inline HV_PTE
2239hv_pte_set_pfn(HV_PTE pte, unsigned int val)
2240{
2241 /*
2242 * Note that the use of "PTFN" in the next line is intentional; we
2243 * don't want any garbage lower bits left in that field.
2244 */
2245 pte.val &= ~(((1ULL << HV_PTE_PTFN_BITS) - 1) << HV_PTE_INDEX_PTFN);
2246 pte.val |= (__hv64) val << HV_PTE_INDEX_PFN;
2247 return pte;
2248}
2249
2250/** Get the page table frame number from the PTE.
2251 *
2252 * This field contains the upper bits of the CPA (client physical
2253 * address) of the target page table; the complete CPA is this field with
2254 * with HV_PAGE_TABLE_ALIGN zero bits appended to it.
2255 * 2340 *
2256 * For PTEs in a level-1 page table when the Page bit is not set, the 2341 * For all PTEs in the lowest-level page table, and for all PTEs with
2257 * CPA must be aligned modulo the sticter of HV_PAGE_TABLE_ALIGN and 2342 * the Page bit set in all page tables, the CPA must be aligned modulo
2258 * the level-2 page table size. 2343 * the relevant page size.
2259 */ 2344 */
2260static __inline unsigned long 2345static __inline unsigned long
2261hv_pte_get_ptfn(const HV_PTE pte) 2346hv_pte_get_ptfn(const HV_PTE pte)
@@ -2263,7 +2348,6 @@ hv_pte_get_ptfn(const HV_PTE pte)
2263 return pte.val >> HV_PTE_INDEX_PTFN; 2348 return pte.val >> HV_PTE_INDEX_PTFN;
2264} 2349}
2265 2350
2266
2267/** Set the page table frame number into a PTE. See hv_pte_get_ptfn. */ 2351/** Set the page table frame number into a PTE. See hv_pte_get_ptfn. */
2268static __inline HV_PTE 2352static __inline HV_PTE
2269hv_pte_set_ptfn(HV_PTE pte, unsigned long val) 2353hv_pte_set_ptfn(HV_PTE pte, unsigned long val)
@@ -2273,6 +2357,20 @@ hv_pte_set_ptfn(HV_PTE pte, unsigned long val)
2273 return pte; 2357 return pte;
2274} 2358}
2275 2359
2360/** Get the client physical address from the PTE. See hv_pte_set_ptfn. */
2361static __inline HV_PhysAddr
2362hv_pte_get_pa(const HV_PTE pte)
2363{
2364 return (__hv64) hv_pte_get_ptfn(pte) << HV_LOG2_PAGE_TABLE_ALIGN;
2365}
2366
2367/** Set the client physical address into a PTE. See hv_pte_get_ptfn. */
2368static __inline HV_PTE
2369hv_pte_set_pa(HV_PTE pte, HV_PhysAddr pa)
2370{
2371 return hv_pte_set_ptfn(pte, pa >> HV_LOG2_PAGE_TABLE_ALIGN);
2372}
2373
2276 2374
2277/** Get the remote tile caching this page. 2375/** Get the remote tile caching this page.
2278 * 2376 *
@@ -2308,28 +2406,20 @@ hv_pte_set_lotar(HV_PTE pte, unsigned int val)
2308 2406
2309#endif /* !__ASSEMBLER__ */ 2407#endif /* !__ASSEMBLER__ */
2310 2408
2311/** Converts a client physical address to a pfn. */
2312#define HV_CPA_TO_PFN(p) ((p) >> HV_LOG2_PAGE_SIZE_SMALL)
2313
2314/** Converts a pfn to a client physical address. */
2315#define HV_PFN_TO_CPA(p) (((HV_PhysAddr)(p)) << HV_LOG2_PAGE_SIZE_SMALL)
2316
2317/** Converts a client physical address to a ptfn. */ 2409/** Converts a client physical address to a ptfn. */
2318#define HV_CPA_TO_PTFN(p) ((p) >> HV_LOG2_PAGE_TABLE_ALIGN) 2410#define HV_CPA_TO_PTFN(p) ((p) >> HV_LOG2_PAGE_TABLE_ALIGN)
2319 2411
2320/** Converts a ptfn to a client physical address. */ 2412/** Converts a ptfn to a client physical address. */
2321#define HV_PTFN_TO_CPA(p) (((HV_PhysAddr)(p)) << HV_LOG2_PAGE_TABLE_ALIGN) 2413#define HV_PTFN_TO_CPA(p) (((HV_PhysAddr)(p)) << HV_LOG2_PAGE_TABLE_ALIGN)
2322 2414
2323/** Converts a ptfn to a pfn. */
2324#define HV_PTFN_TO_PFN(p) \
2325 ((p) >> (HV_LOG2_PAGE_SIZE_SMALL - HV_LOG2_PAGE_TABLE_ALIGN))
2326
2327/** Converts a pfn to a ptfn. */
2328#define HV_PFN_TO_PTFN(p) \
2329 ((p) << (HV_LOG2_PAGE_SIZE_SMALL - HV_LOG2_PAGE_TABLE_ALIGN))
2330
2331#if CHIP_VA_WIDTH() > 32 2415#if CHIP_VA_WIDTH() > 32
2332 2416
2417/*
2418 * Note that we currently do not allow customizing the page size
2419 * of the L0 pages, but fix them at 4GB, so we do not use the
2420 * "_HV_xxx" nomenclature for the L0 macros.
2421 */
2422
2333/** Log number of HV_PTE entries in L0 page table */ 2423/** Log number of HV_PTE entries in L0 page table */
2334#define HV_LOG2_L0_ENTRIES (CHIP_VA_WIDTH() - HV_LOG2_L1_SPAN) 2424#define HV_LOG2_L0_ENTRIES (CHIP_VA_WIDTH() - HV_LOG2_L1_SPAN)
2335 2425
@@ -2359,69 +2449,104 @@ hv_pte_set_lotar(HV_PTE pte, unsigned int val)
2359#endif /* CHIP_VA_WIDTH() > 32 */ 2449#endif /* CHIP_VA_WIDTH() > 32 */
2360 2450
2361/** Log number of HV_PTE entries in L1 page table */ 2451/** Log number of HV_PTE entries in L1 page table */
2362#define HV_LOG2_L1_ENTRIES (HV_LOG2_L1_SPAN - HV_LOG2_PAGE_SIZE_LARGE) 2452#define _HV_LOG2_L1_ENTRIES(log2_page_size_large) \
2453 (HV_LOG2_L1_SPAN - log2_page_size_large)
2363 2454
2364/** Number of HV_PTE entries in L1 page table */ 2455/** Number of HV_PTE entries in L1 page table */
2365#define HV_L1_ENTRIES (1 << HV_LOG2_L1_ENTRIES) 2456#define _HV_L1_ENTRIES(log2_page_size_large) \
2457 (1 << _HV_LOG2_L1_ENTRIES(log2_page_size_large))
2366 2458
2367/** Log size of L1 page table in bytes */ 2459/** Log size of L1 page table in bytes */
2368#define HV_LOG2_L1_SIZE (HV_LOG2_PTE_SIZE + HV_LOG2_L1_ENTRIES) 2460#define _HV_LOG2_L1_SIZE(log2_page_size_large) \
2461 (HV_LOG2_PTE_SIZE + _HV_LOG2_L1_ENTRIES(log2_page_size_large))
2369 2462
2370/** Size of L1 page table in bytes */ 2463/** Size of L1 page table in bytes */
2371#define HV_L1_SIZE (1 << HV_LOG2_L1_SIZE) 2464#define _HV_L1_SIZE(log2_page_size_large) \
2465 (1 << _HV_LOG2_L1_SIZE(log2_page_size_large))
2372 2466
2373/** Log number of HV_PTE entries in level-2 page table */ 2467/** Log number of HV_PTE entries in level-2 page table */
2374#define HV_LOG2_L2_ENTRIES (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL) 2468#define _HV_LOG2_L2_ENTRIES(log2_page_size_large, log2_page_size_small) \
2469 (log2_page_size_large - log2_page_size_small)
2375 2470
2376/** Number of HV_PTE entries in level-2 page table */ 2471/** Number of HV_PTE entries in level-2 page table */
2377#define HV_L2_ENTRIES (1 << HV_LOG2_L2_ENTRIES) 2472#define _HV_L2_ENTRIES(log2_page_size_large, log2_page_size_small) \
2473 (1 << _HV_LOG2_L2_ENTRIES(log2_page_size_large, log2_page_size_small))
2378 2474
2379/** Log size of level-2 page table in bytes */ 2475/** Log size of level-2 page table in bytes */
2380#define HV_LOG2_L2_SIZE (HV_LOG2_PTE_SIZE + HV_LOG2_L2_ENTRIES) 2476#define _HV_LOG2_L2_SIZE(log2_page_size_large, log2_page_size_small) \
2477 (HV_LOG2_PTE_SIZE + \
2478 _HV_LOG2_L2_ENTRIES(log2_page_size_large, log2_page_size_small))
2381 2479
2382/** Size of level-2 page table in bytes */ 2480/** Size of level-2 page table in bytes */
2383#define HV_L2_SIZE (1 << HV_LOG2_L2_SIZE) 2481#define _HV_L2_SIZE(log2_page_size_large, log2_page_size_small) \
2482 (1 << _HV_LOG2_L2_SIZE(log2_page_size_large, log2_page_size_small))
2384 2483
2385#ifdef __ASSEMBLER__ 2484#ifdef __ASSEMBLER__
2386 2485
2387#if CHIP_VA_WIDTH() > 32 2486#if CHIP_VA_WIDTH() > 32
2388 2487
2389/** Index in L1 for a specific VA */ 2488/** Index in L1 for a specific VA */
2390#define HV_L1_INDEX(va) \ 2489#define _HV_L1_INDEX(va, log2_page_size_large) \
2391 (((va) >> HV_LOG2_PAGE_SIZE_LARGE) & (HV_L1_ENTRIES - 1)) 2490 (((va) >> log2_page_size_large) & (_HV_L1_ENTRIES(log2_page_size_large) - 1))
2392 2491
2393#else /* CHIP_VA_WIDTH() > 32 */ 2492#else /* CHIP_VA_WIDTH() > 32 */
2394 2493
2395/** Index in L1 for a specific VA */ 2494/** Index in L1 for a specific VA */
2396#define HV_L1_INDEX(va) \ 2495#define _HV_L1_INDEX(va, log2_page_size_large) \
2397 (((va) >> HV_LOG2_PAGE_SIZE_LARGE)) 2496 (((va) >> log2_page_size_large))
2398 2497
2399#endif /* CHIP_VA_WIDTH() > 32 */ 2498#endif /* CHIP_VA_WIDTH() > 32 */
2400 2499
2401/** Index in level-2 page table for a specific VA */ 2500/** Index in level-2 page table for a specific VA */
2402#define HV_L2_INDEX(va) \ 2501#define _HV_L2_INDEX(va, log2_page_size_large, log2_page_size_small) \
2403 (((va) >> HV_LOG2_PAGE_SIZE_SMALL) & (HV_L2_ENTRIES - 1)) 2502 (((va) >> log2_page_size_small) & \
2503 (_HV_L2_ENTRIES(log2_page_size_large, log2_page_size_small) - 1))
2404 2504
2405#else /* __ASSEMBLER __ */ 2505#else /* __ASSEMBLER __ */
2406 2506
2407#if CHIP_VA_WIDTH() > 32 2507#if CHIP_VA_WIDTH() > 32
2408 2508
2409/** Index in L1 for a specific VA */ 2509/** Index in L1 for a specific VA */
2410#define HV_L1_INDEX(va) \ 2510#define _HV_L1_INDEX(va, log2_page_size_large) \
2411 (((HV_VirtAddr)(va) >> HV_LOG2_PAGE_SIZE_LARGE) & (HV_L1_ENTRIES - 1)) 2511 (((HV_VirtAddr)(va) >> log2_page_size_large) & \
2512 (_HV_L1_ENTRIES(log2_page_size_large) - 1))
2412 2513
2413#else /* CHIP_VA_WIDTH() > 32 */ 2514#else /* CHIP_VA_WIDTH() > 32 */
2414 2515
2415/** Index in L1 for a specific VA */ 2516/** Index in L1 for a specific VA */
2416#define HV_L1_INDEX(va) \ 2517#define _HV_L1_INDEX(va, log2_page_size_large) \
2417 (((HV_VirtAddr)(va) >> HV_LOG2_PAGE_SIZE_LARGE)) 2518 (((HV_VirtAddr)(va) >> log2_page_size_large))
2418 2519
2419#endif /* CHIP_VA_WIDTH() > 32 */ 2520#endif /* CHIP_VA_WIDTH() > 32 */
2420 2521
2421/** Index in level-2 page table for a specific VA */ 2522/** Index in level-2 page table for a specific VA */
2422#define HV_L2_INDEX(va) \ 2523#define _HV_L2_INDEX(va, log2_page_size_large, log2_page_size_small) \
2423 (((HV_VirtAddr)(va) >> HV_LOG2_PAGE_SIZE_SMALL) & (HV_L2_ENTRIES - 1)) 2524 (((HV_VirtAddr)(va) >> log2_page_size_small) & \
2525 (_HV_L2_ENTRIES(log2_page_size_large, log2_page_size_small) - 1))
2424 2526
2425#endif /* __ASSEMBLER __ */ 2527#endif /* __ASSEMBLER __ */
2426 2528
2427#endif /* _TILE_HV_H */ 2529/** Position of the PFN field within the PTE (subset of the PTFN). */
2530#define _HV_PTE_INDEX_PFN(log2_page_size) \
2531 (HV_PTE_INDEX_PTFN + (log2_page_size - HV_LOG2_PAGE_TABLE_ALIGN))
2532
2533/** Length of the PFN field within the PTE (subset of the PTFN). */
2534#define _HV_PTE_INDEX_PFN_BITS(log2_page_size) \
2535 (HV_PTE_INDEX_PTFN_BITS - (log2_page_size - HV_LOG2_PAGE_TABLE_ALIGN))
2536
2537/** Converts a client physical address to a pfn. */
2538#define _HV_CPA_TO_PFN(p, log2_page_size) ((p) >> log2_page_size)
2539
2540/** Converts a pfn to a client physical address. */
2541#define _HV_PFN_TO_CPA(p, log2_page_size) \
2542 (((HV_PhysAddr)(p)) << log2_page_size)
2543
2544/** Converts a ptfn to a pfn. */
2545#define _HV_PTFN_TO_PFN(p, log2_page_size) \
2546 ((p) >> (log2_page_size - HV_LOG2_PAGE_TABLE_ALIGN))
2547
2548/** Converts a pfn to a ptfn. */
2549#define _HV_PFN_TO_PTFN(p, log2_page_size) \
2550 ((p) << (log2_page_size - HV_LOG2_PAGE_TABLE_ALIGN))
2551
2552#endif /* _HV_HV_H */
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile
index 0d826faf8f35..5de99248d8df 100644
--- a/arch/tile/kernel/Makefile
+++ b/arch/tile/kernel/Makefile
@@ -9,10 +9,9 @@ obj-y := backtrace.o entry.o irq.o messaging.o \
9 intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o 9 intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o
10 10
11obj-$(CONFIG_HARDWALL) += hardwall.o 11obj-$(CONFIG_HARDWALL) += hardwall.o
12obj-$(CONFIG_TILEGX) += futex_64.o
13obj-$(CONFIG_COMPAT) += compat.o compat_signal.o 12obj-$(CONFIG_COMPAT) += compat.o compat_signal.o
14obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o 13obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o
15obj-$(CONFIG_MODULES) += module.o 14obj-$(CONFIG_MODULES) += module.o
16obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 15obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
17obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 16obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel_$(BITS).o
18obj-$(CONFIG_PCI) += pci.o 17obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
index ec91568df880..133c4b56a99e 100644
--- a/arch/tile/kernel/entry.S
+++ b/arch/tile/kernel/entry.S
@@ -100,8 +100,9 @@ STD_ENTRY(smp_nap)
100 */ 100 */
101STD_ENTRY(_cpu_idle) 101STD_ENTRY(_cpu_idle)
102 movei r1, 1 102 movei r1, 1
103 IRQ_ENABLE_LOAD(r2, r3)
103 mtspr INTERRUPT_CRITICAL_SECTION, r1 104 mtspr INTERRUPT_CRITICAL_SECTION, r1
104 IRQ_ENABLE(r2, r3) /* unmask, but still with ICS set */ 105 IRQ_ENABLE_APPLY(r2, r3) /* unmask, but still with ICS set */
105 mtspr INTERRUPT_CRITICAL_SECTION, zero 106 mtspr INTERRUPT_CRITICAL_SECTION, zero
106 .global _cpu_idle_nap 107 .global _cpu_idle_nap
107_cpu_idle_nap: 108_cpu_idle_nap:
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index 8c41891aab34..20273ee37deb 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -33,59 +33,157 @@
33 33
34 34
35/* 35/*
36 * This data structure tracks the rectangle data, etc., associated 36 * Implement a per-cpu "hardwall" resource class such as UDN or IPI.
37 * one-to-one with a "struct file *" from opening HARDWALL_FILE. 37 * We use "hardwall" nomenclature throughout for historical reasons.
38 * The lock here controls access to the list data structure as well as
39 * to the items on the list.
40 */
41struct hardwall_type {
42 int index;
43 int is_xdn;
44 int is_idn;
45 int disabled;
46 const char *name;
47 struct list_head list;
48 spinlock_t lock;
49 struct proc_dir_entry *proc_dir;
50};
51
52enum hardwall_index {
53 HARDWALL_UDN = 0,
54#ifndef __tilepro__
55 HARDWALL_IDN = 1,
56 HARDWALL_IPI = 2,
57#endif
58 _HARDWALL_TYPES
59};
60
61static struct hardwall_type hardwall_types[] = {
62 { /* user-space access to UDN */
63 0,
64 1,
65 0,
66 0,
67 "udn",
68 LIST_HEAD_INIT(hardwall_types[HARDWALL_UDN].list),
69 __SPIN_LOCK_INITIALIZER(hardwall_types[HARDWALL_UDN].lock),
70 NULL
71 },
72#ifndef __tilepro__
73 { /* user-space access to IDN */
74 1,
75 1,
76 1,
77 1, /* disabled pending hypervisor support */
78 "idn",
79 LIST_HEAD_INIT(hardwall_types[HARDWALL_IDN].list),
80 __SPIN_LOCK_INITIALIZER(hardwall_types[HARDWALL_IDN].lock),
81 NULL
82 },
83 { /* access to user-space IPI */
84 2,
85 0,
86 0,
87 0,
88 "ipi",
89 LIST_HEAD_INIT(hardwall_types[HARDWALL_IPI].list),
90 __SPIN_LOCK_INITIALIZER(hardwall_types[HARDWALL_IPI].lock),
91 NULL
92 },
93#endif
94};
95
96/*
97 * This data structure tracks the cpu data, etc., associated
98 * one-to-one with a "struct file *" from opening a hardwall device file.
38 * Note that the file's private data points back to this structure. 99 * Note that the file's private data points back to this structure.
39 */ 100 */
40struct hardwall_info { 101struct hardwall_info {
41 struct list_head list; /* "rectangles" list */ 102 struct list_head list; /* for hardwall_types.list */
42 struct list_head task_head; /* head of tasks in this hardwall */ 103 struct list_head task_head; /* head of tasks in this hardwall */
43 struct cpumask cpumask; /* cpus in the rectangle */ 104 struct hardwall_type *type; /* type of this resource */
105 struct cpumask cpumask; /* cpus reserved */
106 int id; /* integer id for this hardwall */
107 int teardown_in_progress; /* are we tearing this one down? */
108
109 /* Remaining fields only valid for user-network resources. */
44 int ulhc_x; /* upper left hand corner x coord */ 110 int ulhc_x; /* upper left hand corner x coord */
45 int ulhc_y; /* upper left hand corner y coord */ 111 int ulhc_y; /* upper left hand corner y coord */
46 int width; /* rectangle width */ 112 int width; /* rectangle width */
47 int height; /* rectangle height */ 113 int height; /* rectangle height */
48 int id; /* integer id for this hardwall */ 114#if CHIP_HAS_REV1_XDN()
49 int teardown_in_progress; /* are we tearing this one down? */ 115 atomic_t xdn_pending_count; /* cores in phase 1 of drain */
116#endif
50}; 117};
51 118
52/* Currently allocated hardwall rectangles */
53static LIST_HEAD(rectangles);
54 119
55/* /proc/tile/hardwall */ 120/* /proc/tile/hardwall */
56static struct proc_dir_entry *hardwall_proc_dir; 121static struct proc_dir_entry *hardwall_proc_dir;
57 122
58/* Functions to manage files in /proc/tile/hardwall. */ 123/* Functions to manage files in /proc/tile/hardwall. */
59static void hardwall_add_proc(struct hardwall_info *rect); 124static void hardwall_add_proc(struct hardwall_info *);
60static void hardwall_remove_proc(struct hardwall_info *rect); 125static void hardwall_remove_proc(struct hardwall_info *);
61
62/*
63 * Guard changes to the hardwall data structures.
64 * This could be finer grained (e.g. one lock for the list of hardwall
65 * rectangles, then separate embedded locks for each one's list of tasks),
66 * but there are subtle correctness issues when trying to start with
67 * a task's "hardwall" pointer and lock the correct rectangle's embedded
68 * lock in the presence of a simultaneous deactivation, so it seems
69 * easier to have a single lock, given that none of these data
70 * structures are touched very frequently during normal operation.
71 */
72static DEFINE_SPINLOCK(hardwall_lock);
73 126
74/* Allow disabling UDN access. */ 127/* Allow disabling UDN access. */
75static int udn_disabled;
76static int __init noudn(char *str) 128static int __init noudn(char *str)
77{ 129{
78 pr_info("User-space UDN access is disabled\n"); 130 pr_info("User-space UDN access is disabled\n");
79 udn_disabled = 1; 131 hardwall_types[HARDWALL_UDN].disabled = 1;
80 return 0; 132 return 0;
81} 133}
82early_param("noudn", noudn); 134early_param("noudn", noudn);
83 135
136#ifndef __tilepro__
137/* Allow disabling IDN access. */
138static int __init noidn(char *str)
139{
140 pr_info("User-space IDN access is disabled\n");
141 hardwall_types[HARDWALL_IDN].disabled = 1;
142 return 0;
143}
144early_param("noidn", noidn);
145
146/* Allow disabling IPI access. */
147static int __init noipi(char *str)
148{
149 pr_info("User-space IPI access is disabled\n");
150 hardwall_types[HARDWALL_IPI].disabled = 1;
151 return 0;
152}
153early_param("noipi", noipi);
154#endif
155
84 156
85/* 157/*
86 * Low-level primitives 158 * Low-level primitives for UDN/IDN
87 */ 159 */
88 160
161#ifdef __tilepro__
162#define mtspr_XDN(hwt, name, val) \
163 do { (void)(hwt); __insn_mtspr(SPR_UDN_##name, (val)); } while (0)
164#define mtspr_MPL_XDN(hwt, name, val) \
165 do { (void)(hwt); __insn_mtspr(SPR_MPL_UDN_##name, (val)); } while (0)
166#define mfspr_XDN(hwt, name) \
167 ((void)(hwt), __insn_mfspr(SPR_UDN_##name))
168#else
169#define mtspr_XDN(hwt, name, val) \
170 do { \
171 if ((hwt)->is_idn) \
172 __insn_mtspr(SPR_IDN_##name, (val)); \
173 else \
174 __insn_mtspr(SPR_UDN_##name, (val)); \
175 } while (0)
176#define mtspr_MPL_XDN(hwt, name, val) \
177 do { \
178 if ((hwt)->is_idn) \
179 __insn_mtspr(SPR_MPL_IDN_##name, (val)); \
180 else \
181 __insn_mtspr(SPR_MPL_UDN_##name, (val)); \
182 } while (0)
183#define mfspr_XDN(hwt, name) \
184 ((hwt)->is_idn ? __insn_mfspr(SPR_IDN_##name) : __insn_mfspr(SPR_UDN_##name))
185#endif
186
89/* Set a CPU bit if the CPU is online. */ 187/* Set a CPU bit if the CPU is online. */
90#define cpu_online_set(cpu, dst) do { \ 188#define cpu_online_set(cpu, dst) do { \
91 if (cpu_online(cpu)) \ 189 if (cpu_online(cpu)) \
@@ -101,7 +199,7 @@ static int contains(struct hardwall_info *r, int x, int y)
101} 199}
102 200
103/* Compute the rectangle parameters and validate the cpumask. */ 201/* Compute the rectangle parameters and validate the cpumask. */
104static int setup_rectangle(struct hardwall_info *r, struct cpumask *mask) 202static int check_rectangle(struct hardwall_info *r, struct cpumask *mask)
105{ 203{
106 int x, y, cpu, ulhc, lrhc; 204 int x, y, cpu, ulhc, lrhc;
107 205
@@ -114,8 +212,6 @@ static int setup_rectangle(struct hardwall_info *r, struct cpumask *mask)
114 r->ulhc_y = cpu_y(ulhc); 212 r->ulhc_y = cpu_y(ulhc);
115 r->width = cpu_x(lrhc) - r->ulhc_x + 1; 213 r->width = cpu_x(lrhc) - r->ulhc_x + 1;
116 r->height = cpu_y(lrhc) - r->ulhc_y + 1; 214 r->height = cpu_y(lrhc) - r->ulhc_y + 1;
117 cpumask_copy(&r->cpumask, mask);
118 r->id = ulhc; /* The ulhc cpu id can be the hardwall id. */
119 215
120 /* Width and height must be positive */ 216 /* Width and height must be positive */
121 if (r->width <= 0 || r->height <= 0) 217 if (r->width <= 0 || r->height <= 0)
@@ -128,7 +224,7 @@ static int setup_rectangle(struct hardwall_info *r, struct cpumask *mask)
128 return -EINVAL; 224 return -EINVAL;
129 225
130 /* 226 /*
131 * Note that offline cpus can't be drained when this UDN 227 * Note that offline cpus can't be drained when this user network
132 * rectangle eventually closes. We used to detect this 228 * rectangle eventually closes. We used to detect this
133 * situation and print a warning, but it annoyed users and 229 * situation and print a warning, but it annoyed users and
134 * they ignored it anyway, so now we just return without a 230 * they ignored it anyway, so now we just return without a
@@ -137,16 +233,6 @@ static int setup_rectangle(struct hardwall_info *r, struct cpumask *mask)
137 return 0; 233 return 0;
138} 234}
139 235
140/* Do the two given rectangles overlap on any cpu? */
141static int overlaps(struct hardwall_info *a, struct hardwall_info *b)
142{
143 return a->ulhc_x + a->width > b->ulhc_x && /* A not to the left */
144 b->ulhc_x + b->width > a->ulhc_x && /* B not to the left */
145 a->ulhc_y + a->height > b->ulhc_y && /* A not above */
146 b->ulhc_y + b->height > a->ulhc_y; /* B not above */
147}
148
149
150/* 236/*
151 * Hardware management of hardwall setup, teardown, trapping, 237 * Hardware management of hardwall setup, teardown, trapping,
152 * and enabling/disabling PL0 access to the networks. 238 * and enabling/disabling PL0 access to the networks.
@@ -157,23 +243,35 @@ enum direction_protect {
157 N_PROTECT = (1 << 0), 243 N_PROTECT = (1 << 0),
158 E_PROTECT = (1 << 1), 244 E_PROTECT = (1 << 1),
159 S_PROTECT = (1 << 2), 245 S_PROTECT = (1 << 2),
160 W_PROTECT = (1 << 3) 246 W_PROTECT = (1 << 3),
247 C_PROTECT = (1 << 4),
161}; 248};
162 249
163static void enable_firewall_interrupts(void) 250static inline int xdn_which_interrupt(struct hardwall_type *hwt)
251{
252#ifndef __tilepro__
253 if (hwt->is_idn)
254 return INT_IDN_FIREWALL;
255#endif
256 return INT_UDN_FIREWALL;
257}
258
259static void enable_firewall_interrupts(struct hardwall_type *hwt)
164{ 260{
165 arch_local_irq_unmask_now(INT_UDN_FIREWALL); 261 arch_local_irq_unmask_now(xdn_which_interrupt(hwt));
166} 262}
167 263
168static void disable_firewall_interrupts(void) 264static void disable_firewall_interrupts(struct hardwall_type *hwt)
169{ 265{
170 arch_local_irq_mask_now(INT_UDN_FIREWALL); 266 arch_local_irq_mask_now(xdn_which_interrupt(hwt));
171} 267}
172 268
173/* Set up hardwall on this cpu based on the passed hardwall_info. */ 269/* Set up hardwall on this cpu based on the passed hardwall_info. */
174static void hardwall_setup_ipi_func(void *info) 270static void hardwall_setup_func(void *info)
175{ 271{
176 struct hardwall_info *r = info; 272 struct hardwall_info *r = info;
273 struct hardwall_type *hwt = r->type;
274
177 int cpu = smp_processor_id(); 275 int cpu = smp_processor_id();
178 int x = cpu % smp_width; 276 int x = cpu % smp_width;
179 int y = cpu / smp_width; 277 int y = cpu / smp_width;
@@ -187,13 +285,12 @@ static void hardwall_setup_ipi_func(void *info)
187 if (y == r->ulhc_y + r->height - 1) 285 if (y == r->ulhc_y + r->height - 1)
188 bits |= S_PROTECT; 286 bits |= S_PROTECT;
189 BUG_ON(bits == 0); 287 BUG_ON(bits == 0);
190 __insn_mtspr(SPR_UDN_DIRECTION_PROTECT, bits); 288 mtspr_XDN(hwt, DIRECTION_PROTECT, bits);
191 enable_firewall_interrupts(); 289 enable_firewall_interrupts(hwt);
192
193} 290}
194 291
195/* Set up all cpus on edge of rectangle to enable/disable hardwall SPRs. */ 292/* Set up all cpus on edge of rectangle to enable/disable hardwall SPRs. */
196static void hardwall_setup(struct hardwall_info *r) 293static void hardwall_protect_rectangle(struct hardwall_info *r)
197{ 294{
198 int x, y, cpu, delta; 295 int x, y, cpu, delta;
199 struct cpumask rect_cpus; 296 struct cpumask rect_cpus;
@@ -217,37 +314,50 @@ static void hardwall_setup(struct hardwall_info *r)
217 } 314 }
218 315
219 /* Then tell all the cpus to set up their protection SPR */ 316 /* Then tell all the cpus to set up their protection SPR */
220 on_each_cpu_mask(&rect_cpus, hardwall_setup_ipi_func, r, 1); 317 on_each_cpu_mask(&rect_cpus, hardwall_setup_func, r, 1);
221} 318}
222 319
223void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num) 320void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num)
224{ 321{
225 struct hardwall_info *rect; 322 struct hardwall_info *rect;
323 struct hardwall_type *hwt;
226 struct task_struct *p; 324 struct task_struct *p;
227 struct siginfo info; 325 struct siginfo info;
228 int x, y;
229 int cpu = smp_processor_id(); 326 int cpu = smp_processor_id();
230 int found_processes; 327 int found_processes;
231 unsigned long flags; 328 unsigned long flags;
232
233 struct pt_regs *old_regs = set_irq_regs(regs); 329 struct pt_regs *old_regs = set_irq_regs(regs);
330
234 irq_enter(); 331 irq_enter();
235 332
333 /* Figure out which network trapped. */
334 switch (fault_num) {
335#ifndef __tilepro__
336 case INT_IDN_FIREWALL:
337 hwt = &hardwall_types[HARDWALL_IDN];
338 break;
339#endif
340 case INT_UDN_FIREWALL:
341 hwt = &hardwall_types[HARDWALL_UDN];
342 break;
343 default:
344 BUG();
345 }
346 BUG_ON(hwt->disabled);
347
236 /* This tile trapped a network access; find the rectangle. */ 348 /* This tile trapped a network access; find the rectangle. */
237 x = cpu % smp_width; 349 spin_lock_irqsave(&hwt->lock, flags);
238 y = cpu / smp_width; 350 list_for_each_entry(rect, &hwt->list, list) {
239 spin_lock_irqsave(&hardwall_lock, flags); 351 if (cpumask_test_cpu(cpu, &rect->cpumask))
240 list_for_each_entry(rect, &rectangles, list) {
241 if (contains(rect, x, y))
242 break; 352 break;
243 } 353 }
244 354
245 /* 355 /*
246 * It shouldn't be possible not to find this cpu on the 356 * It shouldn't be possible not to find this cpu on the
247 * rectangle list, since only cpus in rectangles get hardwalled. 357 * rectangle list, since only cpus in rectangles get hardwalled.
248 * The hardwall is only removed after the UDN is drained. 358 * The hardwall is only removed after the user network is drained.
249 */ 359 */
250 BUG_ON(&rect->list == &rectangles); 360 BUG_ON(&rect->list == &hwt->list);
251 361
252 /* 362 /*
253 * If we already started teardown on this hardwall, don't worry; 363 * If we already started teardown on this hardwall, don't worry;
@@ -255,30 +365,32 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num)
255 * to quiesce. 365 * to quiesce.
256 */ 366 */
257 if (rect->teardown_in_progress) { 367 if (rect->teardown_in_progress) {
258 pr_notice("cpu %d: detected hardwall violation %#lx" 368 pr_notice("cpu %d: detected %s hardwall violation %#lx"
259 " while teardown already in progress\n", 369 " while teardown already in progress\n",
260 cpu, (long) __insn_mfspr(SPR_UDN_DIRECTION_PROTECT)); 370 cpu, hwt->name,
371 (long)mfspr_XDN(hwt, DIRECTION_PROTECT));
261 goto done; 372 goto done;
262 } 373 }
263 374
264 /* 375 /*
265 * Kill off any process that is activated in this rectangle. 376 * Kill off any process that is activated in this rectangle.
266 * We bypass security to deliver the signal, since it must be 377 * We bypass security to deliver the signal, since it must be
267 * one of the activated processes that generated the UDN 378 * one of the activated processes that generated the user network
268 * message that caused this trap, and all the activated 379 * message that caused this trap, and all the activated
269 * processes shared a single open file so are pretty tightly 380 * processes shared a single open file so are pretty tightly
270 * bound together from a security point of view to begin with. 381 * bound together from a security point of view to begin with.
271 */ 382 */
272 rect->teardown_in_progress = 1; 383 rect->teardown_in_progress = 1;
273 wmb(); /* Ensure visibility of rectangle before notifying processes. */ 384 wmb(); /* Ensure visibility of rectangle before notifying processes. */
274 pr_notice("cpu %d: detected hardwall violation %#lx...\n", 385 pr_notice("cpu %d: detected %s hardwall violation %#lx...\n",
275 cpu, (long) __insn_mfspr(SPR_UDN_DIRECTION_PROTECT)); 386 cpu, hwt->name, (long)mfspr_XDN(hwt, DIRECTION_PROTECT));
276 info.si_signo = SIGILL; 387 info.si_signo = SIGILL;
277 info.si_errno = 0; 388 info.si_errno = 0;
278 info.si_code = ILL_HARDWALL; 389 info.si_code = ILL_HARDWALL;
279 found_processes = 0; 390 found_processes = 0;
280 list_for_each_entry(p, &rect->task_head, thread.hardwall_list) { 391 list_for_each_entry(p, &rect->task_head,
281 BUG_ON(p->thread.hardwall != rect); 392 thread.hardwall[hwt->index].list) {
393 BUG_ON(p->thread.hardwall[hwt->index].info != rect);
282 if (!(p->flags & PF_EXITING)) { 394 if (!(p->flags & PF_EXITING)) {
283 found_processes = 1; 395 found_processes = 1;
284 pr_notice("hardwall: killing %d\n", p->pid); 396 pr_notice("hardwall: killing %d\n", p->pid);
@@ -289,7 +401,7 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num)
289 pr_notice("hardwall: no associated processes!\n"); 401 pr_notice("hardwall: no associated processes!\n");
290 402
291 done: 403 done:
292 spin_unlock_irqrestore(&hardwall_lock, flags); 404 spin_unlock_irqrestore(&hwt->lock, flags);
293 405
294 /* 406 /*
295 * We have to disable firewall interrupts now, or else when we 407 * We have to disable firewall interrupts now, or else when we
@@ -298,48 +410,87 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num)
298 * haven't yet drained the network, and that would allow packets 410 * haven't yet drained the network, and that would allow packets
299 * to cross out of the hardwall region. 411 * to cross out of the hardwall region.
300 */ 412 */
301 disable_firewall_interrupts(); 413 disable_firewall_interrupts(hwt);
302 414
303 irq_exit(); 415 irq_exit();
304 set_irq_regs(old_regs); 416 set_irq_regs(old_regs);
305} 417}
306 418
307/* Allow access from user space to the UDN. */ 419/* Allow access from user space to the user network. */
308void grant_network_mpls(void) 420void grant_hardwall_mpls(struct hardwall_type *hwt)
309{ 421{
310 __insn_mtspr(SPR_MPL_UDN_ACCESS_SET_0, 1); 422#ifndef __tilepro__
311 __insn_mtspr(SPR_MPL_UDN_AVAIL_SET_0, 1); 423 if (!hwt->is_xdn) {
312 __insn_mtspr(SPR_MPL_UDN_COMPLETE_SET_0, 1); 424 __insn_mtspr(SPR_MPL_IPI_0_SET_0, 1);
313 __insn_mtspr(SPR_MPL_UDN_TIMER_SET_0, 1); 425 return;
426 }
427#endif
428 mtspr_MPL_XDN(hwt, ACCESS_SET_0, 1);
429 mtspr_MPL_XDN(hwt, AVAIL_SET_0, 1);
430 mtspr_MPL_XDN(hwt, COMPLETE_SET_0, 1);
431 mtspr_MPL_XDN(hwt, TIMER_SET_0, 1);
314#if !CHIP_HAS_REV1_XDN() 432#if !CHIP_HAS_REV1_XDN()
315 __insn_mtspr(SPR_MPL_UDN_REFILL_SET_0, 1); 433 mtspr_MPL_XDN(hwt, REFILL_SET_0, 1);
316 __insn_mtspr(SPR_MPL_UDN_CA_SET_0, 1); 434 mtspr_MPL_XDN(hwt, CA_SET_0, 1);
317#endif 435#endif
318} 436}
319 437
320/* Deny access from user space to the UDN. */ 438/* Deny access from user space to the user network. */
321void restrict_network_mpls(void) 439void restrict_hardwall_mpls(struct hardwall_type *hwt)
322{ 440{
323 __insn_mtspr(SPR_MPL_UDN_ACCESS_SET_1, 1); 441#ifndef __tilepro__
324 __insn_mtspr(SPR_MPL_UDN_AVAIL_SET_1, 1); 442 if (!hwt->is_xdn) {
325 __insn_mtspr(SPR_MPL_UDN_COMPLETE_SET_1, 1); 443 __insn_mtspr(SPR_MPL_IPI_0_SET_1, 1);
326 __insn_mtspr(SPR_MPL_UDN_TIMER_SET_1, 1); 444 return;
445 }
446#endif
447 mtspr_MPL_XDN(hwt, ACCESS_SET_1, 1);
448 mtspr_MPL_XDN(hwt, AVAIL_SET_1, 1);
449 mtspr_MPL_XDN(hwt, COMPLETE_SET_1, 1);
450 mtspr_MPL_XDN(hwt, TIMER_SET_1, 1);
327#if !CHIP_HAS_REV1_XDN() 451#if !CHIP_HAS_REV1_XDN()
328 __insn_mtspr(SPR_MPL_UDN_REFILL_SET_1, 1); 452 mtspr_MPL_XDN(hwt, REFILL_SET_1, 1);
329 __insn_mtspr(SPR_MPL_UDN_CA_SET_1, 1); 453 mtspr_MPL_XDN(hwt, CA_SET_1, 1);
330#endif 454#endif
331} 455}
332 456
457/* Restrict or deny as necessary for the task we're switching to. */
458void hardwall_switch_tasks(struct task_struct *prev,
459 struct task_struct *next)
460{
461 int i;
462 for (i = 0; i < HARDWALL_TYPES; ++i) {
463 if (prev->thread.hardwall[i].info != NULL) {
464 if (next->thread.hardwall[i].info == NULL)
465 restrict_hardwall_mpls(&hardwall_types[i]);
466 } else if (next->thread.hardwall[i].info != NULL) {
467 grant_hardwall_mpls(&hardwall_types[i]);
468 }
469 }
470}
471
472/* Does this task have the right to IPI the given cpu? */
473int hardwall_ipi_valid(int cpu)
474{
475#ifdef __tilegx__
476 struct hardwall_info *info =
477 current->thread.hardwall[HARDWALL_IPI].info;
478 return info && cpumask_test_cpu(cpu, &info->cpumask);
479#else
480 return 0;
481#endif
482}
333 483
334/* 484/*
335 * Code to create, activate, deactivate, and destroy hardwall rectangles. 485 * Code to create, activate, deactivate, and destroy hardwall resources.
336 */ 486 */
337 487
338/* Create a hardwall for the given rectangle */ 488/* Create a hardwall for the given resource */
339static struct hardwall_info *hardwall_create( 489static struct hardwall_info *hardwall_create(struct hardwall_type *hwt,
340 size_t size, const unsigned char __user *bits) 490 size_t size,
491 const unsigned char __user *bits)
341{ 492{
342 struct hardwall_info *iter, *rect; 493 struct hardwall_info *iter, *info;
343 struct cpumask mask; 494 struct cpumask mask;
344 unsigned long flags; 495 unsigned long flags;
345 int rc; 496 int rc;
@@ -370,55 +521,62 @@ static struct hardwall_info *hardwall_create(
370 } 521 }
371 } 522 }
372 523
373 /* Allocate a new rectangle optimistically. */ 524 /* Allocate a new hardwall_info optimistically. */
374 rect = kmalloc(sizeof(struct hardwall_info), 525 info = kmalloc(sizeof(struct hardwall_info),
375 GFP_KERNEL | __GFP_ZERO); 526 GFP_KERNEL | __GFP_ZERO);
376 if (rect == NULL) 527 if (info == NULL)
377 return ERR_PTR(-ENOMEM); 528 return ERR_PTR(-ENOMEM);
378 INIT_LIST_HEAD(&rect->task_head); 529 INIT_LIST_HEAD(&info->task_head);
530 info->type = hwt;
379 531
380 /* Compute the rectangle size and validate that it's plausible. */ 532 /* Compute the rectangle size and validate that it's plausible. */
381 rc = setup_rectangle(rect, &mask); 533 cpumask_copy(&info->cpumask, &mask);
382 if (rc != 0) { 534 info->id = find_first_bit(cpumask_bits(&mask), nr_cpumask_bits);
383 kfree(rect); 535 if (hwt->is_xdn) {
384 return ERR_PTR(rc); 536 rc = check_rectangle(info, &mask);
537 if (rc != 0) {
538 kfree(info);
539 return ERR_PTR(rc);
540 }
385 } 541 }
386 542
387 /* Confirm it doesn't overlap and add it to the list. */ 543 /* Confirm it doesn't overlap and add it to the list. */
388 spin_lock_irqsave(&hardwall_lock, flags); 544 spin_lock_irqsave(&hwt->lock, flags);
389 list_for_each_entry(iter, &rectangles, list) { 545 list_for_each_entry(iter, &hwt->list, list) {
390 if (overlaps(iter, rect)) { 546 if (cpumask_intersects(&iter->cpumask, &info->cpumask)) {
391 spin_unlock_irqrestore(&hardwall_lock, flags); 547 spin_unlock_irqrestore(&hwt->lock, flags);
392 kfree(rect); 548 kfree(info);
393 return ERR_PTR(-EBUSY); 549 return ERR_PTR(-EBUSY);
394 } 550 }
395 } 551 }
396 list_add_tail(&rect->list, &rectangles); 552 list_add_tail(&info->list, &hwt->list);
397 spin_unlock_irqrestore(&hardwall_lock, flags); 553 spin_unlock_irqrestore(&hwt->lock, flags);
398 554
399 /* Set up appropriate hardwalling on all affected cpus. */ 555 /* Set up appropriate hardwalling on all affected cpus. */
400 hardwall_setup(rect); 556 if (hwt->is_xdn)
557 hardwall_protect_rectangle(info);
401 558
402 /* Create a /proc/tile/hardwall entry. */ 559 /* Create a /proc/tile/hardwall entry. */
403 hardwall_add_proc(rect); 560 hardwall_add_proc(info);
404 561
405 return rect; 562 return info;
406} 563}
407 564
408/* Activate a given hardwall on this cpu for this process. */ 565/* Activate a given hardwall on this cpu for this process. */
409static int hardwall_activate(struct hardwall_info *rect) 566static int hardwall_activate(struct hardwall_info *info)
410{ 567{
411 int cpu, x, y; 568 int cpu;
412 unsigned long flags; 569 unsigned long flags;
413 struct task_struct *p = current; 570 struct task_struct *p = current;
414 struct thread_struct *ts = &p->thread; 571 struct thread_struct *ts = &p->thread;
572 struct hardwall_type *hwt;
415 573
416 /* Require a rectangle. */ 574 /* Require a hardwall. */
417 if (rect == NULL) 575 if (info == NULL)
418 return -ENODATA; 576 return -ENODATA;
419 577
420 /* Not allowed to activate a rectangle that is being torn down. */ 578 /* Not allowed to activate a hardwall that is being torn down. */
421 if (rect->teardown_in_progress) 579 if (info->teardown_in_progress)
422 return -EINVAL; 580 return -EINVAL;
423 581
424 /* 582 /*
@@ -428,78 +586,87 @@ static int hardwall_activate(struct hardwall_info *rect)
428 if (cpumask_weight(&p->cpus_allowed) != 1) 586 if (cpumask_weight(&p->cpus_allowed) != 1)
429 return -EPERM; 587 return -EPERM;
430 588
431 /* Make sure we are bound to a cpu in this rectangle. */ 589 /* Make sure we are bound to a cpu assigned to this resource. */
432 cpu = smp_processor_id(); 590 cpu = smp_processor_id();
433 BUG_ON(cpumask_first(&p->cpus_allowed) != cpu); 591 BUG_ON(cpumask_first(&p->cpus_allowed) != cpu);
434 x = cpu_x(cpu); 592 if (!cpumask_test_cpu(cpu, &info->cpumask))
435 y = cpu_y(cpu);
436 if (!contains(rect, x, y))
437 return -EINVAL; 593 return -EINVAL;
438 594
439 /* If we are already bound to this hardwall, it's a no-op. */ 595 /* If we are already bound to this hardwall, it's a no-op. */
440 if (ts->hardwall) { 596 hwt = info->type;
441 BUG_ON(ts->hardwall != rect); 597 if (ts->hardwall[hwt->index].info) {
598 BUG_ON(ts->hardwall[hwt->index].info != info);
442 return 0; 599 return 0;
443 } 600 }
444 601
445 /* Success! This process gets to use the user networks on this cpu. */ 602 /* Success! This process gets to use the resource on this cpu. */
446 ts->hardwall = rect; 603 ts->hardwall[hwt->index].info = info;
447 spin_lock_irqsave(&hardwall_lock, flags); 604 spin_lock_irqsave(&hwt->lock, flags);
448 list_add(&ts->hardwall_list, &rect->task_head); 605 list_add(&ts->hardwall[hwt->index].list, &info->task_head);
449 spin_unlock_irqrestore(&hardwall_lock, flags); 606 spin_unlock_irqrestore(&hwt->lock, flags);
450 grant_network_mpls(); 607 grant_hardwall_mpls(hwt);
451 printk(KERN_DEBUG "Pid %d (%s) activated for hardwall: cpu %d\n", 608 printk(KERN_DEBUG "Pid %d (%s) activated for %s hardwall: cpu %d\n",
452 p->pid, p->comm, cpu); 609 p->pid, p->comm, hwt->name, cpu);
453 return 0; 610 return 0;
454} 611}
455 612
456/* 613/*
457 * Deactivate a task's hardwall. Must hold hardwall_lock. 614 * Deactivate a task's hardwall. Must hold lock for hardwall_type.
458 * This method may be called from free_task(), so we don't want to 615 * This method may be called from free_task(), so we don't want to
459 * rely on too many fields of struct task_struct still being valid. 616 * rely on too many fields of struct task_struct still being valid.
460 * We assume the cpus_allowed, pid, and comm fields are still valid. 617 * We assume the cpus_allowed, pid, and comm fields are still valid.
461 */ 618 */
462static void _hardwall_deactivate(struct task_struct *task) 619static void _hardwall_deactivate(struct hardwall_type *hwt,
620 struct task_struct *task)
463{ 621{
464 struct thread_struct *ts = &task->thread; 622 struct thread_struct *ts = &task->thread;
465 623
466 if (cpumask_weight(&task->cpus_allowed) != 1) { 624 if (cpumask_weight(&task->cpus_allowed) != 1) {
467 pr_err("pid %d (%s) releasing networks with" 625 pr_err("pid %d (%s) releasing %s hardwall with"
468 " an affinity mask containing %d cpus!\n", 626 " an affinity mask containing %d cpus!\n",
469 task->pid, task->comm, 627 task->pid, task->comm, hwt->name,
470 cpumask_weight(&task->cpus_allowed)); 628 cpumask_weight(&task->cpus_allowed));
471 BUG(); 629 BUG();
472 } 630 }
473 631
474 BUG_ON(ts->hardwall == NULL); 632 BUG_ON(ts->hardwall[hwt->index].info == NULL);
475 ts->hardwall = NULL; 633 ts->hardwall[hwt->index].info = NULL;
476 list_del(&ts->hardwall_list); 634 list_del(&ts->hardwall[hwt->index].list);
477 if (task == current) 635 if (task == current)
478 restrict_network_mpls(); 636 restrict_hardwall_mpls(hwt);
479} 637}
480 638
481/* Deactivate a task's hardwall. */ 639/* Deactivate a task's hardwall. */
482int hardwall_deactivate(struct task_struct *task) 640static int hardwall_deactivate(struct hardwall_type *hwt,
641 struct task_struct *task)
483{ 642{
484 unsigned long flags; 643 unsigned long flags;
485 int activated; 644 int activated;
486 645
487 spin_lock_irqsave(&hardwall_lock, flags); 646 spin_lock_irqsave(&hwt->lock, flags);
488 activated = (task->thread.hardwall != NULL); 647 activated = (task->thread.hardwall[hwt->index].info != NULL);
489 if (activated) 648 if (activated)
490 _hardwall_deactivate(task); 649 _hardwall_deactivate(hwt, task);
491 spin_unlock_irqrestore(&hardwall_lock, flags); 650 spin_unlock_irqrestore(&hwt->lock, flags);
492 651
493 if (!activated) 652 if (!activated)
494 return -EINVAL; 653 return -EINVAL;
495 654
496 printk(KERN_DEBUG "Pid %d (%s) deactivated for hardwall: cpu %d\n", 655 printk(KERN_DEBUG "Pid %d (%s) deactivated for %s hardwall: cpu %d\n",
497 task->pid, task->comm, smp_processor_id()); 656 task->pid, task->comm, hwt->name, smp_processor_id());
498 return 0; 657 return 0;
499} 658}
500 659
501/* Stop a UDN switch before draining the network. */ 660void hardwall_deactivate_all(struct task_struct *task)
502static void stop_udn_switch(void *ignored) 661{
662 int i;
663 for (i = 0; i < HARDWALL_TYPES; ++i)
664 if (task->thread.hardwall[i].info)
665 hardwall_deactivate(&hardwall_types[i], task);
666}
667
668/* Stop the switch before draining the network. */
669static void stop_xdn_switch(void *arg)
503{ 670{
504#if !CHIP_HAS_REV1_XDN() 671#if !CHIP_HAS_REV1_XDN()
505 /* Freeze the switch and the demux. */ 672 /* Freeze the switch and the demux. */
@@ -507,13 +674,71 @@ static void stop_udn_switch(void *ignored)
507 SPR_UDN_SP_FREEZE__SP_FRZ_MASK | 674 SPR_UDN_SP_FREEZE__SP_FRZ_MASK |
508 SPR_UDN_SP_FREEZE__DEMUX_FRZ_MASK | 675 SPR_UDN_SP_FREEZE__DEMUX_FRZ_MASK |
509 SPR_UDN_SP_FREEZE__NON_DEST_EXT_MASK); 676 SPR_UDN_SP_FREEZE__NON_DEST_EXT_MASK);
677#else
678 /*
679 * Drop all packets bound for the core or off the edge.
680 * We rely on the normal hardwall protection setup code
681 * to have set the low four bits to trigger firewall interrupts,
682 * and shift those bits up to trigger "drop on send" semantics,
683 * plus adding "drop on send to core" for all switches.
684 * In practice it seems the switches latch the DIRECTION_PROTECT
685 * SPR so they won't start dropping if they're already
686 * delivering the last message to the core, but it doesn't
687 * hurt to enable it here.
688 */
689 struct hardwall_type *hwt = arg;
690 unsigned long protect = mfspr_XDN(hwt, DIRECTION_PROTECT);
691 mtspr_XDN(hwt, DIRECTION_PROTECT, (protect | C_PROTECT) << 5);
510#endif 692#endif
511} 693}
512 694
695static void empty_xdn_demuxes(struct hardwall_type *hwt)
696{
697#ifndef __tilepro__
698 if (hwt->is_idn) {
699 while (__insn_mfspr(SPR_IDN_DATA_AVAIL) & (1 << 0))
700 (void) __tile_idn0_receive();
701 while (__insn_mfspr(SPR_IDN_DATA_AVAIL) & (1 << 1))
702 (void) __tile_idn1_receive();
703 return;
704 }
705#endif
706 while (__insn_mfspr(SPR_UDN_DATA_AVAIL) & (1 << 0))
707 (void) __tile_udn0_receive();
708 while (__insn_mfspr(SPR_UDN_DATA_AVAIL) & (1 << 1))
709 (void) __tile_udn1_receive();
710 while (__insn_mfspr(SPR_UDN_DATA_AVAIL) & (1 << 2))
711 (void) __tile_udn2_receive();
712 while (__insn_mfspr(SPR_UDN_DATA_AVAIL) & (1 << 3))
713 (void) __tile_udn3_receive();
714}
715
513/* Drain all the state from a stopped switch. */ 716/* Drain all the state from a stopped switch. */
514static void drain_udn_switch(void *ignored) 717static void drain_xdn_switch(void *arg)
515{ 718{
516#if !CHIP_HAS_REV1_XDN() 719 struct hardwall_info *info = arg;
720 struct hardwall_type *hwt = info->type;
721
722#if CHIP_HAS_REV1_XDN()
723 /*
724 * The switches have been configured to drop any messages
725 * destined for cores (or off the edge of the rectangle).
726 * But the current message may continue to be delivered,
727 * so we wait until all the cores have finished any pending
728 * messages before we stop draining.
729 */
730 int pending = mfspr_XDN(hwt, PENDING);
731 while (pending--) {
732 empty_xdn_demuxes(hwt);
733 if (hwt->is_idn)
734 __tile_idn_send(0);
735 else
736 __tile_udn_send(0);
737 }
738 atomic_dec(&info->xdn_pending_count);
739 while (atomic_read(&info->xdn_pending_count))
740 empty_xdn_demuxes(hwt);
741#else
517 int i; 742 int i;
518 int from_tile_words, ca_count; 743 int from_tile_words, ca_count;
519 744
@@ -533,15 +758,7 @@ static void drain_udn_switch(void *ignored)
533 (void) __insn_mfspr(SPR_UDN_DEMUX_WRITE_FIFO); 758 (void) __insn_mfspr(SPR_UDN_DEMUX_WRITE_FIFO);
534 759
535 /* Empty out demuxes. */ 760 /* Empty out demuxes. */
536 while (__insn_mfspr(SPR_UDN_DATA_AVAIL) & (1 << 0)) 761 empty_xdn_demuxes(hwt);
537 (void) __tile_udn0_receive();
538 while (__insn_mfspr(SPR_UDN_DATA_AVAIL) & (1 << 1))
539 (void) __tile_udn1_receive();
540 while (__insn_mfspr(SPR_UDN_DATA_AVAIL) & (1 << 2))
541 (void) __tile_udn2_receive();
542 while (__insn_mfspr(SPR_UDN_DATA_AVAIL) & (1 << 3))
543 (void) __tile_udn3_receive();
544 BUG_ON((__insn_mfspr(SPR_UDN_DATA_AVAIL) & 0xF) != 0);
545 762
546 /* Empty out catch all. */ 763 /* Empty out catch all. */
547 ca_count = __insn_mfspr(SPR_UDN_DEMUX_CA_COUNT); 764 ca_count = __insn_mfspr(SPR_UDN_DEMUX_CA_COUNT);
@@ -563,21 +780,25 @@ static void drain_udn_switch(void *ignored)
563#endif 780#endif
564} 781}
565 782
566/* Reset random UDN state registers at boot up and during hardwall teardown. */ 783/* Reset random XDN state registers at boot up and during hardwall teardown. */
567void reset_network_state(void) 784static void reset_xdn_network_state(struct hardwall_type *hwt)
568{ 785{
569#if !CHIP_HAS_REV1_XDN() 786 if (hwt->disabled)
570 /* Reset UDN coordinates to their standard value */
571 unsigned int cpu = smp_processor_id();
572 unsigned int x = cpu % smp_width;
573 unsigned int y = cpu / smp_width;
574#endif
575
576 if (udn_disabled)
577 return; 787 return;
578 788
789 /* Clear out other random registers so we have a clean slate. */
790 mtspr_XDN(hwt, DIRECTION_PROTECT, 0);
791 mtspr_XDN(hwt, AVAIL_EN, 0);
792 mtspr_XDN(hwt, DEADLOCK_TIMEOUT, 0);
793
579#if !CHIP_HAS_REV1_XDN() 794#if !CHIP_HAS_REV1_XDN()
580 __insn_mtspr(SPR_UDN_TILE_COORD, (x << 18) | (y << 7)); 795 /* Reset UDN coordinates to their standard value */
796 {
797 unsigned int cpu = smp_processor_id();
798 unsigned int x = cpu % smp_width;
799 unsigned int y = cpu / smp_width;
800 __insn_mtspr(SPR_UDN_TILE_COORD, (x << 18) | (y << 7));
801 }
581 802
582 /* Set demux tags to predefined values and enable them. */ 803 /* Set demux tags to predefined values and enable them. */
583 __insn_mtspr(SPR_UDN_TAG_VALID, 0xf); 804 __insn_mtspr(SPR_UDN_TAG_VALID, 0xf);
@@ -585,56 +806,50 @@ void reset_network_state(void)
585 __insn_mtspr(SPR_UDN_TAG_1, (1 << 1)); 806 __insn_mtspr(SPR_UDN_TAG_1, (1 << 1));
586 __insn_mtspr(SPR_UDN_TAG_2, (1 << 2)); 807 __insn_mtspr(SPR_UDN_TAG_2, (1 << 2));
587 __insn_mtspr(SPR_UDN_TAG_3, (1 << 3)); 808 __insn_mtspr(SPR_UDN_TAG_3, (1 << 3));
588#endif
589 809
590 /* Clear out other random registers so we have a clean slate. */ 810 /* Set other rev0 random registers to a clean state. */
591 __insn_mtspr(SPR_UDN_AVAIL_EN, 0);
592 __insn_mtspr(SPR_UDN_DEADLOCK_TIMEOUT, 0);
593#if !CHIP_HAS_REV1_XDN()
594 __insn_mtspr(SPR_UDN_REFILL_EN, 0); 811 __insn_mtspr(SPR_UDN_REFILL_EN, 0);
595 __insn_mtspr(SPR_UDN_DEMUX_QUEUE_SEL, 0); 812 __insn_mtspr(SPR_UDN_DEMUX_QUEUE_SEL, 0);
596 __insn_mtspr(SPR_UDN_SP_FIFO_SEL, 0); 813 __insn_mtspr(SPR_UDN_SP_FIFO_SEL, 0);
597#endif
598 814
599 /* Start the switch and demux. */ 815 /* Start the switch and demux. */
600#if !CHIP_HAS_REV1_XDN()
601 __insn_mtspr(SPR_UDN_SP_FREEZE, 0); 816 __insn_mtspr(SPR_UDN_SP_FREEZE, 0);
602#endif 817#endif
603} 818}
604 819
605/* Restart a UDN switch after draining. */ 820void reset_network_state(void)
606static void restart_udn_switch(void *ignored)
607{ 821{
608 reset_network_state(); 822 reset_xdn_network_state(&hardwall_types[HARDWALL_UDN]);
609 823#ifndef __tilepro__
610 /* Disable firewall interrupts. */ 824 reset_xdn_network_state(&hardwall_types[HARDWALL_IDN]);
611 __insn_mtspr(SPR_UDN_DIRECTION_PROTECT, 0); 825#endif
612 disable_firewall_interrupts();
613} 826}
614 827
615/* Build a struct cpumask containing all valid tiles in bounding rectangle. */ 828/* Restart an XDN switch after draining. */
616static void fill_mask(struct hardwall_info *r, struct cpumask *result) 829static void restart_xdn_switch(void *arg)
617{ 830{
618 int x, y, cpu; 831 struct hardwall_type *hwt = arg;
619 832
620 cpumask_clear(result); 833#if CHIP_HAS_REV1_XDN()
834 /* One last drain step to avoid races with injection and draining. */
835 empty_xdn_demuxes(hwt);
836#endif
621 837
622 cpu = r->ulhc_y * smp_width + r->ulhc_x; 838 reset_xdn_network_state(hwt);
623 for (y = 0; y < r->height; ++y, cpu += smp_width - r->width) { 839
624 for (x = 0; x < r->width; ++x, ++cpu) 840 /* Disable firewall interrupts. */
625 cpu_online_set(cpu, result); 841 disable_firewall_interrupts(hwt);
626 }
627} 842}
628 843
629/* Last reference to a hardwall is gone, so clear the network. */ 844/* Last reference to a hardwall is gone, so clear the network. */
630static void hardwall_destroy(struct hardwall_info *rect) 845static void hardwall_destroy(struct hardwall_info *info)
631{ 846{
632 struct task_struct *task; 847 struct task_struct *task;
848 struct hardwall_type *hwt;
633 unsigned long flags; 849 unsigned long flags;
634 struct cpumask mask;
635 850
636 /* Make sure this file actually represents a rectangle. */ 851 /* Make sure this file actually represents a hardwall. */
637 if (rect == NULL) 852 if (info == NULL)
638 return; 853 return;
639 854
640 /* 855 /*
@@ -644,39 +859,53 @@ static void hardwall_destroy(struct hardwall_info *rect)
644 * deactivate any remaining tasks before freeing the 859 * deactivate any remaining tasks before freeing the
645 * hardwall_info object itself. 860 * hardwall_info object itself.
646 */ 861 */
647 spin_lock_irqsave(&hardwall_lock, flags); 862 hwt = info->type;
648 list_for_each_entry(task, &rect->task_head, thread.hardwall_list) 863 info->teardown_in_progress = 1;
649 _hardwall_deactivate(task); 864 spin_lock_irqsave(&hwt->lock, flags);
650 spin_unlock_irqrestore(&hardwall_lock, flags); 865 list_for_each_entry(task, &info->task_head,
651 866 thread.hardwall[hwt->index].list)
652 /* Drain the UDN. */ 867 _hardwall_deactivate(hwt, task);
653 printk(KERN_DEBUG "Clearing hardwall rectangle %dx%d %d,%d\n", 868 spin_unlock_irqrestore(&hwt->lock, flags);
654 rect->width, rect->height, rect->ulhc_x, rect->ulhc_y); 869
655 fill_mask(rect, &mask); 870 if (hwt->is_xdn) {
656 on_each_cpu_mask(&mask, stop_udn_switch, NULL, 1); 871 /* Configure the switches for draining the user network. */
657 on_each_cpu_mask(&mask, drain_udn_switch, NULL, 1); 872 printk(KERN_DEBUG
873 "Clearing %s hardwall rectangle %dx%d %d,%d\n",
874 hwt->name, info->width, info->height,
875 info->ulhc_x, info->ulhc_y);
876 on_each_cpu_mask(&info->cpumask, stop_xdn_switch, hwt, 1);
877
878 /* Drain the network. */
879#if CHIP_HAS_REV1_XDN()
880 atomic_set(&info->xdn_pending_count,
881 cpumask_weight(&info->cpumask));
882 on_each_cpu_mask(&info->cpumask, drain_xdn_switch, info, 0);
883#else
884 on_each_cpu_mask(&info->cpumask, drain_xdn_switch, info, 1);
885#endif
658 886
659 /* Restart switch and disable firewall. */ 887 /* Restart switch and disable firewall. */
660 on_each_cpu_mask(&mask, restart_udn_switch, NULL, 1); 888 on_each_cpu_mask(&info->cpumask, restart_xdn_switch, hwt, 1);
889 }
661 890
662 /* Remove the /proc/tile/hardwall entry. */ 891 /* Remove the /proc/tile/hardwall entry. */
663 hardwall_remove_proc(rect); 892 hardwall_remove_proc(info);
664 893
665 /* Now free the rectangle from the list. */ 894 /* Now free the hardwall from the list. */
666 spin_lock_irqsave(&hardwall_lock, flags); 895 spin_lock_irqsave(&hwt->lock, flags);
667 BUG_ON(!list_empty(&rect->task_head)); 896 BUG_ON(!list_empty(&info->task_head));
668 list_del(&rect->list); 897 list_del(&info->list);
669 spin_unlock_irqrestore(&hardwall_lock, flags); 898 spin_unlock_irqrestore(&hwt->lock, flags);
670 kfree(rect); 899 kfree(info);
671} 900}
672 901
673 902
674static int hardwall_proc_show(struct seq_file *sf, void *v) 903static int hardwall_proc_show(struct seq_file *sf, void *v)
675{ 904{
676 struct hardwall_info *rect = sf->private; 905 struct hardwall_info *info = sf->private;
677 char buf[256]; 906 char buf[256];
678 907
679 int rc = cpulist_scnprintf(buf, sizeof(buf), &rect->cpumask); 908 int rc = cpulist_scnprintf(buf, sizeof(buf), &info->cpumask);
680 buf[rc++] = '\n'; 909 buf[rc++] = '\n';
681 seq_write(sf, buf, rc); 910 seq_write(sf, buf, rc);
682 return 0; 911 return 0;
@@ -695,31 +924,45 @@ static const struct file_operations hardwall_proc_fops = {
695 .release = single_release, 924 .release = single_release,
696}; 925};
697 926
698static void hardwall_add_proc(struct hardwall_info *rect) 927static void hardwall_add_proc(struct hardwall_info *info)
699{ 928{
700 char buf[64]; 929 char buf[64];
701 snprintf(buf, sizeof(buf), "%d", rect->id); 930 snprintf(buf, sizeof(buf), "%d", info->id);
702 proc_create_data(buf, 0444, hardwall_proc_dir, 931 proc_create_data(buf, 0444, info->type->proc_dir,
703 &hardwall_proc_fops, rect); 932 &hardwall_proc_fops, info);
704} 933}
705 934
706static void hardwall_remove_proc(struct hardwall_info *rect) 935static void hardwall_remove_proc(struct hardwall_info *info)
707{ 936{
708 char buf[64]; 937 char buf[64];
709 snprintf(buf, sizeof(buf), "%d", rect->id); 938 snprintf(buf, sizeof(buf), "%d", info->id);
710 remove_proc_entry(buf, hardwall_proc_dir); 939 remove_proc_entry(buf, info->type->proc_dir);
711} 940}
712 941
713int proc_pid_hardwall(struct task_struct *task, char *buffer) 942int proc_pid_hardwall(struct task_struct *task, char *buffer)
714{ 943{
715 struct hardwall_info *rect = task->thread.hardwall; 944 int i;
716 return rect ? sprintf(buffer, "%d\n", rect->id) : 0; 945 int n = 0;
946 for (i = 0; i < HARDWALL_TYPES; ++i) {
947 struct hardwall_info *info = task->thread.hardwall[i].info;
948 if (info)
949 n += sprintf(&buffer[n], "%s: %d\n",
950 info->type->name, info->id);
951 }
952 return n;
717} 953}
718 954
719void proc_tile_hardwall_init(struct proc_dir_entry *root) 955void proc_tile_hardwall_init(struct proc_dir_entry *root)
720{ 956{
721 if (!udn_disabled) 957 int i;
722 hardwall_proc_dir = proc_mkdir("hardwall", root); 958 for (i = 0; i < HARDWALL_TYPES; ++i) {
959 struct hardwall_type *hwt = &hardwall_types[i];
960 if (hwt->disabled)
961 continue;
962 if (hardwall_proc_dir == NULL)
963 hardwall_proc_dir = proc_mkdir("hardwall", root);
964 hwt->proc_dir = proc_mkdir(hwt->name, hardwall_proc_dir);
965 }
723} 966}
724 967
725 968
@@ -729,34 +972,45 @@ void proc_tile_hardwall_init(struct proc_dir_entry *root)
729 972
730static long hardwall_ioctl(struct file *file, unsigned int a, unsigned long b) 973static long hardwall_ioctl(struct file *file, unsigned int a, unsigned long b)
731{ 974{
732 struct hardwall_info *rect = file->private_data; 975 struct hardwall_info *info = file->private_data;
976 int minor = iminor(file->f_mapping->host);
977 struct hardwall_type* hwt;
733 978
734 if (_IOC_TYPE(a) != HARDWALL_IOCTL_BASE) 979 if (_IOC_TYPE(a) != HARDWALL_IOCTL_BASE)
735 return -EINVAL; 980 return -EINVAL;
736 981
982 BUILD_BUG_ON(HARDWALL_TYPES != _HARDWALL_TYPES);
983 BUILD_BUG_ON(HARDWALL_TYPES !=
984 sizeof(hardwall_types)/sizeof(hardwall_types[0]));
985
986 if (minor < 0 || minor >= HARDWALL_TYPES)
987 return -EINVAL;
988 hwt = &hardwall_types[minor];
989 WARN_ON(info && hwt != info->type);
990
737 switch (_IOC_NR(a)) { 991 switch (_IOC_NR(a)) {
738 case _HARDWALL_CREATE: 992 case _HARDWALL_CREATE:
739 if (udn_disabled) 993 if (hwt->disabled)
740 return -ENOSYS; 994 return -ENOSYS;
741 if (rect != NULL) 995 if (info != NULL)
742 return -EALREADY; 996 return -EALREADY;
743 rect = hardwall_create(_IOC_SIZE(a), 997 info = hardwall_create(hwt, _IOC_SIZE(a),
744 (const unsigned char __user *)b); 998 (const unsigned char __user *)b);
745 if (IS_ERR(rect)) 999 if (IS_ERR(info))
746 return PTR_ERR(rect); 1000 return PTR_ERR(info);
747 file->private_data = rect; 1001 file->private_data = info;
748 return 0; 1002 return 0;
749 1003
750 case _HARDWALL_ACTIVATE: 1004 case _HARDWALL_ACTIVATE:
751 return hardwall_activate(rect); 1005 return hardwall_activate(info);
752 1006
753 case _HARDWALL_DEACTIVATE: 1007 case _HARDWALL_DEACTIVATE:
754 if (current->thread.hardwall != rect) 1008 if (current->thread.hardwall[hwt->index].info != info)
755 return -EINVAL; 1009 return -EINVAL;
756 return hardwall_deactivate(current); 1010 return hardwall_deactivate(hwt, current);
757 1011
758 case _HARDWALL_GET_ID: 1012 case _HARDWALL_GET_ID:
759 return rect ? rect->id : -EINVAL; 1013 return info ? info->id : -EINVAL;
760 1014
761 default: 1015 default:
762 return -EINVAL; 1016 return -EINVAL;
@@ -775,26 +1029,28 @@ static long hardwall_compat_ioctl(struct file *file,
775/* The user process closed the file; revoke access to user networks. */ 1029/* The user process closed the file; revoke access to user networks. */
776static int hardwall_flush(struct file *file, fl_owner_t owner) 1030static int hardwall_flush(struct file *file, fl_owner_t owner)
777{ 1031{
778 struct hardwall_info *rect = file->private_data; 1032 struct hardwall_info *info = file->private_data;
779 struct task_struct *task, *tmp; 1033 struct task_struct *task, *tmp;
780 unsigned long flags; 1034 unsigned long flags;
781 1035
782 if (rect) { 1036 if (info) {
783 /* 1037 /*
784 * NOTE: if multiple threads are activated on this hardwall 1038 * NOTE: if multiple threads are activated on this hardwall
785 * file, the other threads will continue having access to the 1039 * file, the other threads will continue having access to the
786 * UDN until they are context-switched out and back in again. 1040 * user network until they are context-switched out and back
1041 * in again.
787 * 1042 *
788 * NOTE: A NULL files pointer means the task is being torn 1043 * NOTE: A NULL files pointer means the task is being torn
789 * down, so in that case we also deactivate it. 1044 * down, so in that case we also deactivate it.
790 */ 1045 */
791 spin_lock_irqsave(&hardwall_lock, flags); 1046 struct hardwall_type *hwt = info->type;
792 list_for_each_entry_safe(task, tmp, &rect->task_head, 1047 spin_lock_irqsave(&hwt->lock, flags);
793 thread.hardwall_list) { 1048 list_for_each_entry_safe(task, tmp, &info->task_head,
1049 thread.hardwall[hwt->index].list) {
794 if (task->files == owner || task->files == NULL) 1050 if (task->files == owner || task->files == NULL)
795 _hardwall_deactivate(task); 1051 _hardwall_deactivate(hwt, task);
796 } 1052 }
797 spin_unlock_irqrestore(&hardwall_lock, flags); 1053 spin_unlock_irqrestore(&hwt->lock, flags);
798 } 1054 }
799 1055
800 return 0; 1056 return 0;
@@ -824,11 +1080,11 @@ static int __init dev_hardwall_init(void)
824 int rc; 1080 int rc;
825 dev_t dev; 1081 dev_t dev;
826 1082
827 rc = alloc_chrdev_region(&dev, 0, 1, "hardwall"); 1083 rc = alloc_chrdev_region(&dev, 0, HARDWALL_TYPES, "hardwall");
828 if (rc < 0) 1084 if (rc < 0)
829 return rc; 1085 return rc;
830 cdev_init(&hardwall_dev, &dev_hardwall_fops); 1086 cdev_init(&hardwall_dev, &dev_hardwall_fops);
831 rc = cdev_add(&hardwall_dev, dev, 1); 1087 rc = cdev_add(&hardwall_dev, dev, HARDWALL_TYPES);
832 if (rc < 0) 1088 if (rc < 0)
833 return rc; 1089 return rc;
834 1090
diff --git a/arch/tile/kernel/head_32.S b/arch/tile/kernel/head_32.S
index 1a39b7c1c87e..f71bfeeaf1a9 100644
--- a/arch/tile/kernel/head_32.S
+++ b/arch/tile/kernel/head_32.S
@@ -69,7 +69,7 @@ ENTRY(_start)
69 } 69 }
70 { 70 {
71 moveli lr, lo16(1f) 71 moveli lr, lo16(1f)
72 move r5, zero 72 moveli r5, CTX_PAGE_FLAG
73 } 73 }
74 { 74 {
75 auli lr, lr, ha16(1f) 75 auli lr, lr, ha16(1f)
@@ -141,11 +141,11 @@ ENTRY(empty_zero_page)
141 141
142 .macro PTE va, cpa, bits1, no_org=0 142 .macro PTE va, cpa, bits1, no_org=0
143 .ifeq \no_org 143 .ifeq \no_org
144 .org swapper_pg_dir + HV_L1_INDEX(\va) * HV_PTE_SIZE 144 .org swapper_pg_dir + PGD_INDEX(\va) * HV_PTE_SIZE
145 .endif 145 .endif
146 .word HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED | \ 146 .word HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED | \
147 (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) 147 (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE)
148 .word (\bits1) | (HV_CPA_TO_PFN(\cpa) << (HV_PTE_INDEX_PFN - 32)) 148 .word (\bits1) | (HV_CPA_TO_PTFN(\cpa) << (HV_PTE_INDEX_PTFN - 32))
149 .endm 149 .endm
150 150
151__PAGE_ALIGNED_DATA 151__PAGE_ALIGNED_DATA
@@ -166,7 +166,7 @@ ENTRY(swapper_pg_dir)
166 /* The true text VAs are mapped as VA = PA + MEM_SV_INTRPT */ 166 /* The true text VAs are mapped as VA = PA + MEM_SV_INTRPT */
167 PTE MEM_SV_INTRPT, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \ 167 PTE MEM_SV_INTRPT, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \
168 (1 << (HV_PTE_INDEX_EXECUTABLE - 32)) 168 (1 << (HV_PTE_INDEX_EXECUTABLE - 32))
169 .org swapper_pg_dir + HV_L1_SIZE 169 .org swapper_pg_dir + PGDIR_SIZE
170 END(swapper_pg_dir) 170 END(swapper_pg_dir)
171 171
172 /* 172 /*
diff --git a/arch/tile/kernel/head_64.S b/arch/tile/kernel/head_64.S
index 6bc3a932fe45..f9a2734f7b82 100644
--- a/arch/tile/kernel/head_64.S
+++ b/arch/tile/kernel/head_64.S
@@ -114,7 +114,7 @@ ENTRY(_start)
114 shl16insli r0, r0, hw0(swapper_pg_dir - PAGE_OFFSET) 114 shl16insli r0, r0, hw0(swapper_pg_dir - PAGE_OFFSET)
115 } 115 }
116 { 116 {
117 move r3, zero 117 moveli r3, CTX_PAGE_FLAG
118 j hv_install_context 118 j hv_install_context
119 } 119 }
1201: 1201:
@@ -210,19 +210,19 @@ ENTRY(empty_zero_page)
210 .macro PTE cpa, bits1 210 .macro PTE cpa, bits1
211 .quad HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED |\ 211 .quad HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED |\
212 HV_PTE_GLOBAL | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) |\ 212 HV_PTE_GLOBAL | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) |\
213 (\bits1) | (HV_CPA_TO_PFN(\cpa) << HV_PTE_INDEX_PFN) 213 (\bits1) | (HV_CPA_TO_PTFN(\cpa) << HV_PTE_INDEX_PTFN)
214 .endm 214 .endm
215 215
216__PAGE_ALIGNED_DATA 216__PAGE_ALIGNED_DATA
217 .align PAGE_SIZE 217 .align PAGE_SIZE
218ENTRY(swapper_pg_dir) 218ENTRY(swapper_pg_dir)
219 .org swapper_pg_dir + HV_L0_INDEX(PAGE_OFFSET) * HV_PTE_SIZE 219 .org swapper_pg_dir + PGD_INDEX(PAGE_OFFSET) * HV_PTE_SIZE
220.Lsv_data_pmd: 220.Lsv_data_pmd:
221 .quad 0 /* PTE temp_data_pmd - PAGE_OFFSET, 0 */ 221 .quad 0 /* PTE temp_data_pmd - PAGE_OFFSET, 0 */
222 .org swapper_pg_dir + HV_L0_INDEX(MEM_SV_START) * HV_PTE_SIZE 222 .org swapper_pg_dir + PGD_INDEX(MEM_SV_START) * HV_PTE_SIZE
223.Lsv_code_pmd: 223.Lsv_code_pmd:
224 .quad 0 /* PTE temp_code_pmd - PAGE_OFFSET, 0 */ 224 .quad 0 /* PTE temp_code_pmd - PAGE_OFFSET, 0 */
225 .org swapper_pg_dir + HV_L0_SIZE 225 .org swapper_pg_dir + SIZEOF_PGD
226 END(swapper_pg_dir) 226 END(swapper_pg_dir)
227 227
228 .align HV_PAGE_TABLE_ALIGN 228 .align HV_PAGE_TABLE_ALIGN
@@ -233,11 +233,11 @@ ENTRY(temp_data_pmd)
233 * permissions later. 233 * permissions later.
234 */ 234 */
235 .set addr, 0 235 .set addr, 0
236 .rept HV_L1_ENTRIES 236 .rept PTRS_PER_PMD
237 PTE addr, HV_PTE_READABLE | HV_PTE_WRITABLE 237 PTE addr, HV_PTE_READABLE | HV_PTE_WRITABLE
238 .set addr, addr + HV_PAGE_SIZE_LARGE 238 .set addr, addr + HPAGE_SIZE
239 .endr 239 .endr
240 .org temp_data_pmd + HV_L1_SIZE 240 .org temp_data_pmd + SIZEOF_PMD
241 END(temp_data_pmd) 241 END(temp_data_pmd)
242 242
243 .align HV_PAGE_TABLE_ALIGN 243 .align HV_PAGE_TABLE_ALIGN
@@ -248,11 +248,11 @@ ENTRY(temp_code_pmd)
248 * permissions later. 248 * permissions later.
249 */ 249 */
250 .set addr, 0 250 .set addr, 0
251 .rept HV_L1_ENTRIES 251 .rept PTRS_PER_PMD
252 PTE addr, HV_PTE_READABLE | HV_PTE_EXECUTABLE 252 PTE addr, HV_PTE_READABLE | HV_PTE_EXECUTABLE
253 .set addr, addr + HV_PAGE_SIZE_LARGE 253 .set addr, addr + HPAGE_SIZE
254 .endr 254 .endr
255 .org temp_code_pmd + HV_L1_SIZE 255 .org temp_code_pmd + SIZEOF_PMD
256 END(temp_code_pmd) 256 END(temp_code_pmd)
257 257
258 /* 258 /*
diff --git a/arch/tile/kernel/hvglue.lds b/arch/tile/kernel/hvglue.lds
index 2b7cd0a659a9..d44c5a67a1ed 100644
--- a/arch/tile/kernel/hvglue.lds
+++ b/arch/tile/kernel/hvglue.lds
@@ -55,4 +55,5 @@ hv_store_mapping = TEXT_OFFSET + 0x106a0;
55hv_inquire_realpa = TEXT_OFFSET + 0x106c0; 55hv_inquire_realpa = TEXT_OFFSET + 0x106c0;
56hv_flush_all = TEXT_OFFSET + 0x106e0; 56hv_flush_all = TEXT_OFFSET + 0x106e0;
57hv_get_ipi_pte = TEXT_OFFSET + 0x10700; 57hv_get_ipi_pte = TEXT_OFFSET + 0x10700;
58hv_glue_internals = TEXT_OFFSET + 0x10720; 58hv_set_pte_super_shift = TEXT_OFFSET + 0x10720;
59hv_glue_internals = TEXT_OFFSET + 0x10740;
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S
index 30ae76e50c44..7c06d597ffd0 100644
--- a/arch/tile/kernel/intvec_64.S
+++ b/arch/tile/kernel/intvec_64.S
@@ -220,7 +220,9 @@ intvec_\vecname:
220 * This routine saves just the first four registers, plus the 220 * This routine saves just the first four registers, plus the
221 * stack context so we can do proper backtracing right away, 221 * stack context so we can do proper backtracing right away,
222 * and defers to handle_interrupt to save the rest. 222 * and defers to handle_interrupt to save the rest.
223 * The backtracer needs pc, ex1, lr, sp, r52, and faultnum. 223 * The backtracer needs pc, ex1, lr, sp, r52, and faultnum,
224 * and needs sp set to its final location at the bottom of
225 * the stack frame.
224 */ 226 */
225 addli r0, r0, PTREGS_OFFSET_LR - (PTREGS_SIZE + KSTK_PTREGS_GAP) 227 addli r0, r0, PTREGS_OFFSET_LR - (PTREGS_SIZE + KSTK_PTREGS_GAP)
226 wh64 r0 /* cache line 7 */ 228 wh64 r0 /* cache line 7 */
@@ -450,23 +452,6 @@ intvec_\vecname:
450 push_reg r5, r52 452 push_reg r5, r52
451 st r52, r4 453 st r52, r4
452 454
453 /* Load tp with our per-cpu offset. */
454#ifdef CONFIG_SMP
455 {
456 mfspr r20, SPR_SYSTEM_SAVE_K_0
457 moveli r21, hw2_last(__per_cpu_offset)
458 }
459 {
460 shl16insli r21, r21, hw1(__per_cpu_offset)
461 bfextu r20, r20, 0, LOG2_THREAD_SIZE-1
462 }
463 shl16insli r21, r21, hw0(__per_cpu_offset)
464 shl3add r20, r20, r21
465 ld tp, r20
466#else
467 move tp, zero
468#endif
469
470 /* 455 /*
471 * If we will be returning to the kernel, we will need to 456 * If we will be returning to the kernel, we will need to
472 * reset the interrupt masks to the state they had before. 457 * reset the interrupt masks to the state they had before.
@@ -489,6 +474,44 @@ intvec_\vecname:
489 .endif 474 .endif
490 st r21, r32 475 st r21, r32
491 476
477 /*
478 * we've captured enough state to the stack (including in
479 * particular our EX_CONTEXT state) that we can now release
480 * the interrupt critical section and replace it with our
481 * standard "interrupts disabled" mask value. This allows
482 * synchronous interrupts (and profile interrupts) to punch
483 * through from this point onwards.
484 *
485 * It's important that no code before this point touch memory
486 * other than our own stack (to keep the invariant that this
487 * is all that gets touched under ICS), and that no code after
488 * this point reference any interrupt-specific SPR, in particular
489 * the EX_CONTEXT_K_ values.
490 */
491 .ifc \function,handle_nmi
492 IRQ_DISABLE_ALL(r20)
493 .else
494 IRQ_DISABLE(r20, r21)
495 .endif
496 mtspr INTERRUPT_CRITICAL_SECTION, zero
497
498 /* Load tp with our per-cpu offset. */
499#ifdef CONFIG_SMP
500 {
501 mfspr r20, SPR_SYSTEM_SAVE_K_0
502 moveli r21, hw2_last(__per_cpu_offset)
503 }
504 {
505 shl16insli r21, r21, hw1(__per_cpu_offset)
506 bfextu r20, r20, 0, LOG2_THREAD_SIZE-1
507 }
508 shl16insli r21, r21, hw0(__per_cpu_offset)
509 shl3add r20, r20, r21
510 ld tp, r20
511#else
512 move tp, zero
513#endif
514
492#ifdef __COLLECT_LINKER_FEEDBACK__ 515#ifdef __COLLECT_LINKER_FEEDBACK__
493 /* 516 /*
494 * Notify the feedback routines that we were in the 517 * Notify the feedback routines that we were in the
@@ -513,21 +536,6 @@ intvec_\vecname:
513#endif 536#endif
514 537
515 /* 538 /*
516 * we've captured enough state to the stack (including in
517 * particular our EX_CONTEXT state) that we can now release
518 * the interrupt critical section and replace it with our
519 * standard "interrupts disabled" mask value. This allows
520 * synchronous interrupts (and profile interrupts) to punch
521 * through from this point onwards.
522 */
523 .ifc \function,handle_nmi
524 IRQ_DISABLE_ALL(r20)
525 .else
526 IRQ_DISABLE(r20, r21)
527 .endif
528 mtspr INTERRUPT_CRITICAL_SECTION, zero
529
530 /*
531 * Prepare the first 256 stack bytes to be rapidly accessible 539 * Prepare the first 256 stack bytes to be rapidly accessible
532 * without having to fetch the background data. 540 * without having to fetch the background data.
533 */ 541 */
@@ -736,9 +744,10 @@ STD_ENTRY(interrupt_return)
736 beqzt r30, .Lrestore_regs 744 beqzt r30, .Lrestore_regs
737 j 3f 745 j 3f
7382: TRACE_IRQS_ON 7462: TRACE_IRQS_ON
747 IRQ_ENABLE_LOAD(r20, r21)
739 movei r0, 1 748 movei r0, 1
740 mtspr INTERRUPT_CRITICAL_SECTION, r0 749 mtspr INTERRUPT_CRITICAL_SECTION, r0
741 IRQ_ENABLE(r20, r21) 750 IRQ_ENABLE_APPLY(r20, r21)
742 beqzt r30, .Lrestore_regs 751 beqzt r30, .Lrestore_regs
7433: 7523:
744 753
@@ -755,7 +764,6 @@ STD_ENTRY(interrupt_return)
755 * that will save some cycles if this turns out to be a syscall. 764 * that will save some cycles if this turns out to be a syscall.
756 */ 765 */
757.Lrestore_regs: 766.Lrestore_regs:
758 FEEDBACK_REENTER(interrupt_return) /* called from elsewhere */
759 767
760 /* 768 /*
761 * Rotate so we have one high bit and one low bit to test. 769 * Rotate so we have one high bit and one low bit to test.
@@ -1249,7 +1257,7 @@ STD_ENTRY(fill_ra_stack)
1249 int_hand INT_UNALIGN_DATA, UNALIGN_DATA, int_unalign 1257 int_hand INT_UNALIGN_DATA, UNALIGN_DATA, int_unalign
1250 int_hand INT_DTLB_MISS, DTLB_MISS, do_page_fault 1258 int_hand INT_DTLB_MISS, DTLB_MISS, do_page_fault
1251 int_hand INT_DTLB_ACCESS, DTLB_ACCESS, do_page_fault 1259 int_hand INT_DTLB_ACCESS, DTLB_ACCESS, do_page_fault
1252 int_hand INT_IDN_FIREWALL, IDN_FIREWALL, bad_intr 1260 int_hand INT_IDN_FIREWALL, IDN_FIREWALL, do_hardwall_trap
1253 int_hand INT_UDN_FIREWALL, UDN_FIREWALL, do_hardwall_trap 1261 int_hand INT_UDN_FIREWALL, UDN_FIREWALL, do_hardwall_trap
1254 int_hand INT_TILE_TIMER, TILE_TIMER, do_timer_interrupt 1262 int_hand INT_TILE_TIMER, TILE_TIMER, do_timer_interrupt
1255 int_hand INT_IDN_TIMER, IDN_TIMER, bad_intr 1263 int_hand INT_IDN_TIMER, IDN_TIMER, bad_intr
diff --git a/arch/tile/kernel/machine_kexec.c b/arch/tile/kernel/machine_kexec.c
index 6255f2eab112..f0b54a934712 100644
--- a/arch/tile/kernel/machine_kexec.c
+++ b/arch/tile/kernel/machine_kexec.c
@@ -31,6 +31,8 @@
31#include <asm/pgalloc.h> 31#include <asm/pgalloc.h>
32#include <asm/cacheflush.h> 32#include <asm/cacheflush.h>
33#include <asm/checksum.h> 33#include <asm/checksum.h>
34#include <asm/tlbflush.h>
35#include <asm/homecache.h>
34#include <hv/hypervisor.h> 36#include <hv/hypervisor.h>
35 37
36 38
@@ -222,11 +224,22 @@ struct page *kimage_alloc_pages_arch(gfp_t gfp_mask, unsigned int order)
222 return alloc_pages_node(0, gfp_mask, order); 224 return alloc_pages_node(0, gfp_mask, order);
223} 225}
224 226
227/*
228 * Address range in which pa=va mapping is set in setup_quasi_va_is_pa().
229 * For tilepro, PAGE_OFFSET is used since this is the largest possbile value
230 * for tilepro, while for tilegx, we limit it to entire middle level page
231 * table which we assume has been allocated and is undoubtedly large enough.
232 */
233#ifndef __tilegx__
234#define QUASI_VA_IS_PA_ADDR_RANGE PAGE_OFFSET
235#else
236#define QUASI_VA_IS_PA_ADDR_RANGE PGDIR_SIZE
237#endif
238
225static void setup_quasi_va_is_pa(void) 239static void setup_quasi_va_is_pa(void)
226{ 240{
227 HV_PTE *pgtable;
228 HV_PTE pte; 241 HV_PTE pte;
229 int i; 242 unsigned long i;
230 243
231 /* 244 /*
232 * Flush our TLB to prevent conflicts between the previous contents 245 * Flush our TLB to prevent conflicts between the previous contents
@@ -234,16 +247,22 @@ static void setup_quasi_va_is_pa(void)
234 */ 247 */
235 local_flush_tlb_all(); 248 local_flush_tlb_all();
236 249
237 /* setup VA is PA, at least up to PAGE_OFFSET */ 250 /*
238 251 * setup VA is PA, at least up to QUASI_VA_IS_PA_ADDR_RANGE.
239 pgtable = (HV_PTE *)current->mm->pgd; 252 * Note here we assume that level-1 page table is defined by
253 * HPAGE_SIZE.
254 */
240 pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE); 255 pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE);
241 pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3); 256 pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3);
242 257 for (i = 0; i < (QUASI_VA_IS_PA_ADDR_RANGE >> HPAGE_SHIFT); i++) {
243 for (i = 0; i < pgd_index(PAGE_OFFSET); i++) { 258 unsigned long vaddr = i << HPAGE_SHIFT;
259 pgd_t *pgd = pgd_offset(current->mm, vaddr);
260 pud_t *pud = pud_offset(pgd, vaddr);
261 pte_t *ptep = (pte_t *) pmd_offset(pud, vaddr);
244 unsigned long pfn = i << (HPAGE_SHIFT - PAGE_SHIFT); 262 unsigned long pfn = i << (HPAGE_SHIFT - PAGE_SHIFT);
263
245 if (pfn_valid(pfn)) 264 if (pfn_valid(pfn))
246 __set_pte(&pgtable[i], pfn_pte(pfn, pte)); 265 __set_pte(ptep, pfn_pte(pfn, pte));
247 } 266 }
248} 267}
249 268
@@ -251,6 +270,7 @@ static void setup_quasi_va_is_pa(void)
251void machine_kexec(struct kimage *image) 270void machine_kexec(struct kimage *image)
252{ 271{
253 void *reboot_code_buffer; 272 void *reboot_code_buffer;
273 pte_t *ptep;
254 void (*rnk)(unsigned long, void *, unsigned long) 274 void (*rnk)(unsigned long, void *, unsigned long)
255 __noreturn; 275 __noreturn;
256 276
@@ -266,8 +286,10 @@ void machine_kexec(struct kimage *image)
266 */ 286 */
267 homecache_change_page_home(image->control_code_page, 0, 287 homecache_change_page_home(image->control_code_page, 0,
268 smp_processor_id()); 288 smp_processor_id());
269 reboot_code_buffer = vmap(&image->control_code_page, 1, 0, 289 reboot_code_buffer = page_address(image->control_code_page);
270 __pgprot(_PAGE_KERNEL | _PAGE_EXECUTABLE)); 290 BUG_ON(reboot_code_buffer == NULL);
291 ptep = virt_to_pte(NULL, (unsigned long)reboot_code_buffer);
292 __set_pte(ptep, pte_mkexec(*ptep));
271 memcpy(reboot_code_buffer, relocate_new_kernel, 293 memcpy(reboot_code_buffer, relocate_new_kernel,
272 relocate_new_kernel_size); 294 relocate_new_kernel_size);
273 __flush_icache_range( 295 __flush_icache_range(
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c
index 98d476920106..001cbfa10ac6 100644
--- a/arch/tile/kernel/module.c
+++ b/arch/tile/kernel/module.c
@@ -159,7 +159,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
159 159
160 switch (ELF_R_TYPE(rel[i].r_info)) { 160 switch (ELF_R_TYPE(rel[i].r_info)) {
161 161
162#define MUNGE(func) (*location = ((*location & ~func(-1)) | func(value))) 162#ifdef __LITTLE_ENDIAN
163# define MUNGE(func) \
164 (*location = ((*location & ~func(-1)) | func(value)))
165#else
166/*
167 * Instructions are always little-endian, so when we read them as data,
168 * we have to swap them around before and after modifying them.
169 */
170# define MUNGE(func) \
171 (*location = swab64((swab64(*location) & ~func(-1)) | func(value)))
172#endif
163 173
164#ifndef __tilegx__ 174#ifndef __tilegx__
165 case R_TILE_32: 175 case R_TILE_32:
diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c
index 446a7f52cc11..dafc447b5125 100644
--- a/arch/tile/kernel/proc.c
+++ b/arch/tile/kernel/proc.c
@@ -22,6 +22,7 @@
22#include <linux/proc_fs.h> 22#include <linux/proc_fs.h>
23#include <linux/sysctl.h> 23#include <linux/sysctl.h>
24#include <linux/hardirq.h> 24#include <linux/hardirq.h>
25#include <linux/hugetlb.h>
25#include <linux/mman.h> 26#include <linux/mman.h>
26#include <asm/unaligned.h> 27#include <asm/unaligned.h>
27#include <asm/pgtable.h> 28#include <asm/pgtable.h>
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index f572c19c4082..ba1023d8a021 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -128,10 +128,10 @@ void arch_release_thread_info(struct thread_info *info)
128 * Calling deactivate here just frees up the data structures. 128 * Calling deactivate here just frees up the data structures.
129 * If the task we're freeing held the last reference to a 129 * If the task we're freeing held the last reference to a
130 * hardwall fd, it would have been released prior to this point 130 * hardwall fd, it would have been released prior to this point
131 * anyway via exit_files(), and "hardwall" would be NULL by now. 131 * anyway via exit_files(), and the hardwall_task.info pointers
132 * would be NULL by now.
132 */ 133 */
133 if (info->task->thread.hardwall) 134 hardwall_deactivate_all(info->task);
134 hardwall_deactivate(info->task);
135#endif 135#endif
136 136
137 if (step_state) { 137 if (step_state) {
@@ -245,7 +245,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
245 245
246#ifdef CONFIG_HARDWALL 246#ifdef CONFIG_HARDWALL
247 /* New thread does not own any networks. */ 247 /* New thread does not own any networks. */
248 p->thread.hardwall = NULL; 248 memset(&p->thread.hardwall[0], 0,
249 sizeof(struct hardwall_task) * HARDWALL_TYPES);
249#endif 250#endif
250 251
251 252
@@ -515,12 +516,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
515 516
516#ifdef CONFIG_HARDWALL 517#ifdef CONFIG_HARDWALL
517 /* Enable or disable access to the network registers appropriately. */ 518 /* Enable or disable access to the network registers appropriately. */
518 if (prev->thread.hardwall != NULL) { 519 hardwall_switch_tasks(prev, next);
519 if (next->thread.hardwall == NULL)
520 restrict_network_mpls();
521 } else if (next->thread.hardwall != NULL) {
522 grant_network_mpls();
523 }
524#endif 520#endif
525 521
526 /* 522 /*
diff --git a/arch/tile/kernel/relocate_kernel.S b/arch/tile/kernel/relocate_kernel_32.S
index 010b418515f8..010b418515f8 100644
--- a/arch/tile/kernel/relocate_kernel.S
+++ b/arch/tile/kernel/relocate_kernel_32.S
diff --git a/arch/tile/kernel/relocate_kernel_64.S b/arch/tile/kernel/relocate_kernel_64.S
new file mode 100644
index 000000000000..1c09a4f5a4ea
--- /dev/null
+++ b/arch/tile/kernel/relocate_kernel_64.S
@@ -0,0 +1,260 @@
1/*
2 * Copyright 2011 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 *
14 * copy new kernel into place and then call hv_reexec
15 *
16 */
17
18#include <linux/linkage.h>
19#include <arch/chip.h>
20#include <asm/page.h>
21#include <hv/hypervisor.h>
22
23#undef RELOCATE_NEW_KERNEL_VERBOSE
24
25STD_ENTRY(relocate_new_kernel)
26
27 move r30, r0 /* page list */
28 move r31, r1 /* address of page we are on */
29 move r32, r2 /* start address of new kernel */
30
31 shrui r1, r1, PAGE_SHIFT
32 addi r1, r1, 1
33 shli sp, r1, PAGE_SHIFT
34 addi sp, sp, -8
35 /* we now have a stack (whether we need one or not) */
36
37 moveli r40, hw2_last(hv_console_putc)
38 shl16insli r40, r40, hw1(hv_console_putc)
39 shl16insli r40, r40, hw0(hv_console_putc)
40
41#ifdef RELOCATE_NEW_KERNEL_VERBOSE
42 moveli r0, 'r'
43 jalr r40
44
45 moveli r0, '_'
46 jalr r40
47
48 moveli r0, 'n'
49 jalr r40
50
51 moveli r0, '_'
52 jalr r40
53
54 moveli r0, 'k'
55 jalr r40
56
57 moveli r0, '\n'
58 jalr r40
59#endif
60
61 /*
62 * Throughout this code r30 is pointer to the element of page
63 * list we are working on.
64 *
65 * Normally we get to the next element of the page list by
66 * incrementing r30 by eight. The exception is if the element
67 * on the page list is an IND_INDIRECTION in which case we use
68 * the element with the low bits masked off as the new value
69 * of r30.
70 *
71 * To get this started, we need the value passed to us (which
72 * will always be an IND_INDIRECTION) in memory somewhere with
73 * r30 pointing at it. To do that, we push the value passed
74 * to us on the stack and make r30 point to it.
75 */
76
77 st sp, r30
78 move r30, sp
79 addi sp, sp, -16
80
81#if CHIP_HAS_CBOX_HOME_MAP()
82 /*
83 * On TILE-GX, we need to flush all tiles' caches, since we may
84 * have been doing hash-for-home caching there. Note that we
85 * must do this _after_ we're completely done modifying any memory
86 * other than our output buffer (which we know is locally cached).
87 * We want the caches to be fully clean when we do the reexec,
88 * because the hypervisor is going to do this flush again at that
89 * point, and we don't want that second flush to overwrite any memory.
90 */
91 {
92 move r0, zero /* cache_pa */
93 moveli r1, hw2_last(HV_FLUSH_EVICT_L2)
94 }
95 {
96 shl16insli r1, r1, hw1(HV_FLUSH_EVICT_L2)
97 movei r2, -1 /* cache_cpumask; -1 means all client tiles */
98 }
99 {
100 shl16insli r1, r1, hw0(HV_FLUSH_EVICT_L2) /* cache_control */
101 move r3, zero /* tlb_va */
102 }
103 {
104 move r4, zero /* tlb_length */
105 move r5, zero /* tlb_pgsize */
106 }
107 {
108 move r6, zero /* tlb_cpumask */
109 move r7, zero /* asids */
110 }
111 {
112 moveli r20, hw2_last(hv_flush_remote)
113 move r8, zero /* asidcount */
114 }
115 shl16insli r20, r20, hw1(hv_flush_remote)
116 shl16insli r20, r20, hw0(hv_flush_remote)
117
118 jalr r20
119#endif
120
121 /* r33 is destination pointer, default to zero */
122
123 moveli r33, 0
124
125.Lloop: ld r10, r30
126
127 andi r9, r10, 0xf /* low 4 bits tell us what type it is */
128 xor r10, r10, r9 /* r10 is now value with low 4 bits stripped */
129
130 cmpeqi r0, r9, 0x1 /* IND_DESTINATION */
131 beqzt r0, .Ltry2
132
133 move r33, r10
134
135#ifdef RELOCATE_NEW_KERNEL_VERBOSE
136 moveli r0, 'd'
137 jalr r40
138#endif
139
140 addi r30, r30, 8
141 j .Lloop
142
143.Ltry2:
144 cmpeqi r0, r9, 0x2 /* IND_INDIRECTION */
145 beqzt r0, .Ltry4
146
147 move r30, r10
148
149#ifdef RELOCATE_NEW_KERNEL_VERBOSE
150 moveli r0, 'i'
151 jalr r40
152#endif
153
154 j .Lloop
155
156.Ltry4:
157 cmpeqi r0, r9, 0x4 /* IND_DONE */
158 beqzt r0, .Ltry8
159
160 mf
161
162#ifdef RELOCATE_NEW_KERNEL_VERBOSE
163 moveli r0, 'D'
164 jalr r40
165 moveli r0, '\n'
166 jalr r40
167#endif
168
169 move r0, r32
170
171 moveli r41, hw2_last(hv_reexec)
172 shl16insli r41, r41, hw1(hv_reexec)
173 shl16insli r41, r41, hw0(hv_reexec)
174
175 jalr r41
176
177 /* we should not get here */
178
179 moveli r0, '?'
180 jalr r40
181 moveli r0, '\n'
182 jalr r40
183
184 j .Lhalt
185
186.Ltry8: cmpeqi r0, r9, 0x8 /* IND_SOURCE */
187 beqz r0, .Lerr /* unknown type */
188
189 /* copy page at r10 to page at r33 */
190
191 move r11, r33
192
193 moveli r0, hw2_last(PAGE_SIZE)
194 shl16insli r0, r0, hw1(PAGE_SIZE)
195 shl16insli r0, r0, hw0(PAGE_SIZE)
196 add r33, r33, r0
197
198 /* copy word at r10 to word at r11 until r11 equals r33 */
199
200 /* We know page size must be multiple of 8, so we can unroll
201 * 8 times safely without any edge case checking.
202 *
203 * Issue a flush of the destination every 8 words to avoid
204 * incoherence when starting the new kernel. (Now this is
205 * just good paranoia because the hv_reexec call will also
206 * take care of this.)
207 */
208
2091:
210 { ld r0, r10; addi r10, r10, 8 }
211 { st r11, r0; addi r11, r11, 8 }
212 { ld r0, r10; addi r10, r10, 8 }
213 { st r11, r0; addi r11, r11, 8 }
214 { ld r0, r10; addi r10, r10, 8 }
215 { st r11, r0; addi r11, r11, 8 }
216 { ld r0, r10; addi r10, r10, 8 }
217 { st r11, r0; addi r11, r11, 8 }
218 { ld r0, r10; addi r10, r10, 8 }
219 { st r11, r0; addi r11, r11, 8 }
220 { ld r0, r10; addi r10, r10, 8 }
221 { st r11, r0; addi r11, r11, 8 }
222 { ld r0, r10; addi r10, r10, 8 }
223 { st r11, r0; addi r11, r11, 8 }
224 { ld r0, r10; addi r10, r10, 8 }
225 { st r11, r0 }
226 { flush r11 ; addi r11, r11, 8 }
227
228 cmpeq r0, r33, r11
229 beqzt r0, 1b
230
231#ifdef RELOCATE_NEW_KERNEL_VERBOSE
232 moveli r0, 's'
233 jalr r40
234#endif
235
236 addi r30, r30, 8
237 j .Lloop
238
239
240.Lerr: moveli r0, 'e'
241 jalr r40
242 moveli r0, 'r'
243 jalr r40
244 moveli r0, 'r'
245 jalr r40
246 moveli r0, '\n'
247 jalr r40
248.Lhalt:
249 moveli r41, hw2_last(hv_halt)
250 shl16insli r41, r41, hw1(hv_halt)
251 shl16insli r41, r41, hw0(hv_halt)
252
253 jalr r41
254 STD_ENDPROC(relocate_new_kernel)
255
256 .section .rodata,"a"
257
258 .globl relocate_new_kernel_size
259relocate_new_kernel_size:
260 .long .Lend_relocate_new_kernel - relocate_new_kernel
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 98d80eb49ddb..6098ccc59be2 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -28,6 +28,7 @@
28#include <linux/highmem.h> 28#include <linux/highmem.h>
29#include <linux/smp.h> 29#include <linux/smp.h>
30#include <linux/timex.h> 30#include <linux/timex.h>
31#include <linux/hugetlb.h>
31#include <asm/setup.h> 32#include <asm/setup.h>
32#include <asm/sections.h> 33#include <asm/sections.h>
33#include <asm/cacheflush.h> 34#include <asm/cacheflush.h>
@@ -49,9 +50,6 @@ char chip_model[64] __write_once;
49struct pglist_data node_data[MAX_NUMNODES] __read_mostly; 50struct pglist_data node_data[MAX_NUMNODES] __read_mostly;
50EXPORT_SYMBOL(node_data); 51EXPORT_SYMBOL(node_data);
51 52
52/* We only create bootmem data on node 0. */
53static bootmem_data_t __initdata node0_bdata;
54
55/* Information on the NUMA nodes that we compute early */ 53/* Information on the NUMA nodes that we compute early */
56unsigned long __cpuinitdata node_start_pfn[MAX_NUMNODES]; 54unsigned long __cpuinitdata node_start_pfn[MAX_NUMNODES];
57unsigned long __cpuinitdata node_end_pfn[MAX_NUMNODES]; 55unsigned long __cpuinitdata node_end_pfn[MAX_NUMNODES];
@@ -534,37 +532,96 @@ static void __init setup_memory(void)
534#endif 532#endif
535} 533}
536 534
537static void __init setup_bootmem_allocator(void) 535/*
536 * On 32-bit machines, we only put bootmem on the low controller,
537 * since PAs > 4GB can't be used in bootmem. In principle one could
538 * imagine, e.g., multiple 1 GB controllers all of which could support
539 * bootmem, but in practice using controllers this small isn't a
540 * particularly interesting scenario, so we just keep it simple and
541 * use only the first controller for bootmem on 32-bit machines.
542 */
543static inline int node_has_bootmem(int nid)
538{ 544{
539 unsigned long bootmap_size, first_alloc_pfn, last_alloc_pfn; 545#ifdef CONFIG_64BIT
546 return 1;
547#else
548 return nid == 0;
549#endif
550}
540 551
541 /* Provide a node 0 bdata. */ 552static inline unsigned long alloc_bootmem_pfn(int nid,
542 NODE_DATA(0)->bdata = &node0_bdata; 553 unsigned long size,
554 unsigned long goal)
555{
556 void *kva = __alloc_bootmem_node(NODE_DATA(nid), size,
557 PAGE_SIZE, goal);
558 unsigned long pfn = kaddr_to_pfn(kva);
559 BUG_ON(goal && PFN_PHYS(pfn) != goal);
560 return pfn;
561}
543 562
544#ifdef CONFIG_PCI 563static void __init setup_bootmem_allocator_node(int i)
545 /* Don't let boot memory alias the PCI region. */ 564{
546 last_alloc_pfn = min(max_low_pfn, pci_reserve_start_pfn); 565 unsigned long start, end, mapsize, mapstart;
566
567 if (node_has_bootmem(i)) {
568 NODE_DATA(i)->bdata = &bootmem_node_data[i];
569 } else {
570 /* Share controller zero's bdata for now. */
571 NODE_DATA(i)->bdata = &bootmem_node_data[0];
572 return;
573 }
574
575 /* Skip up to after the bss in node 0. */
576 start = (i == 0) ? min_low_pfn : node_start_pfn[i];
577
578 /* Only lowmem, if we're a HIGHMEM build. */
579#ifdef CONFIG_HIGHMEM
580 end = node_lowmem_end_pfn[i];
547#else 581#else
548 last_alloc_pfn = max_low_pfn; 582 end = node_end_pfn[i];
549#endif 583#endif
550 584
551 /* 585 /* No memory here. */
552 * Initialize the boot-time allocator (with low memory only): 586 if (end == start)
553 * The first argument says where to put the bitmap, and the 587 return;
554 * second says where the end of allocatable memory is. 588
555 */ 589 /* Figure out where the bootmem bitmap is located. */
556 bootmap_size = init_bootmem(min_low_pfn, last_alloc_pfn); 590 mapsize = bootmem_bootmap_pages(end - start);
591 if (i == 0) {
592 /* Use some space right before the heap on node 0. */
593 mapstart = start;
594 start += mapsize;
595 } else {
596 /* Allocate bitmap on node 0 to avoid page table issues. */
597 mapstart = alloc_bootmem_pfn(0, PFN_PHYS(mapsize), 0);
598 }
557 599
600 /* Initialize a node. */
601 init_bootmem_node(NODE_DATA(i), mapstart, start, end);
602
603 /* Free all the space back into the allocator. */
604 free_bootmem(PFN_PHYS(start), PFN_PHYS(end - start));
605
606#if defined(CONFIG_PCI)
558 /* 607 /*
559 * Let the bootmem allocator use all the space we've given it 608 * Throw away any memory aliased by the PCI region. FIXME: this
560 * except for its own bitmap. 609 * is a temporary hack to work around bug 10502, and needs to be
610 * fixed properly.
561 */ 611 */
562 first_alloc_pfn = min_low_pfn + PFN_UP(bootmap_size); 612 if (pci_reserve_start_pfn < end && pci_reserve_end_pfn > start)
563 if (first_alloc_pfn >= last_alloc_pfn) 613 reserve_bootmem(PFN_PHYS(pci_reserve_start_pfn),
564 early_panic("Not enough memory on controller 0 for bootmem\n"); 614 PFN_PHYS(pci_reserve_end_pfn -
615 pci_reserve_start_pfn),
616 BOOTMEM_EXCLUSIVE);
617#endif
618}
565 619
566 free_bootmem(PFN_PHYS(first_alloc_pfn), 620static void __init setup_bootmem_allocator(void)
567 PFN_PHYS(last_alloc_pfn - first_alloc_pfn)); 621{
622 int i;
623 for (i = 0; i < MAX_NUMNODES; ++i)
624 setup_bootmem_allocator_node(i);
568 625
569#ifdef CONFIG_KEXEC 626#ifdef CONFIG_KEXEC
570 if (crashk_res.start != crashk_res.end) 627 if (crashk_res.start != crashk_res.end)
@@ -595,14 +652,6 @@ static int __init percpu_size(void)
595 return size; 652 return size;
596} 653}
597 654
598static inline unsigned long alloc_bootmem_pfn(int size, unsigned long goal)
599{
600 void *kva = __alloc_bootmem(size, PAGE_SIZE, goal);
601 unsigned long pfn = kaddr_to_pfn(kva);
602 BUG_ON(goal && PFN_PHYS(pfn) != goal);
603 return pfn;
604}
605
606static void __init zone_sizes_init(void) 655static void __init zone_sizes_init(void)
607{ 656{
608 unsigned long zones_size[MAX_NR_ZONES] = { 0 }; 657 unsigned long zones_size[MAX_NR_ZONES] = { 0 };
@@ -640,21 +689,22 @@ static void __init zone_sizes_init(void)
640 * though, there'll be no lowmem, so we just alloc_bootmem 689 * though, there'll be no lowmem, so we just alloc_bootmem
641 * the memmap. There will be no percpu memory either. 690 * the memmap. There will be no percpu memory either.
642 */ 691 */
643 if (__pfn_to_highbits(start) == 0) { 692 if (i != 0 && cpu_isset(i, isolnodes)) {
644 /* In low PAs, allocate via bootmem. */ 693 node_memmap_pfn[i] =
694 alloc_bootmem_pfn(0, memmap_size, 0);
695 BUG_ON(node_percpu[i] != 0);
696 } else if (node_has_bootmem(start)) {
645 unsigned long goal = 0; 697 unsigned long goal = 0;
646 node_memmap_pfn[i] = 698 node_memmap_pfn[i] =
647 alloc_bootmem_pfn(memmap_size, goal); 699 alloc_bootmem_pfn(i, memmap_size, 0);
648 if (kdata_huge) 700 if (kdata_huge)
649 goal = PFN_PHYS(lowmem_end) - node_percpu[i]; 701 goal = PFN_PHYS(lowmem_end) - node_percpu[i];
650 if (node_percpu[i]) 702 if (node_percpu[i])
651 node_percpu_pfn[i] = 703 node_percpu_pfn[i] =
652 alloc_bootmem_pfn(node_percpu[i], goal); 704 alloc_bootmem_pfn(i, node_percpu[i],
653 } else if (cpu_isset(i, isolnodes)) { 705 goal);
654 node_memmap_pfn[i] = alloc_bootmem_pfn(memmap_size, 0);
655 BUG_ON(node_percpu[i] != 0);
656 } else { 706 } else {
657 /* In high PAs, just reserve some pages. */ 707 /* In non-bootmem zones, just reserve some pages. */
658 node_memmap_pfn[i] = node_free_pfn[i]; 708 node_memmap_pfn[i] = node_free_pfn[i];
659 node_free_pfn[i] += PFN_UP(memmap_size); 709 node_free_pfn[i] += PFN_UP(memmap_size);
660 if (!kdata_huge) { 710 if (!kdata_huge) {
@@ -678,16 +728,9 @@ static void __init zone_sizes_init(void)
678 zones_size[ZONE_NORMAL] = end - start; 728 zones_size[ZONE_NORMAL] = end - start;
679#endif 729#endif
680 730
681 /* 731 /* Take zone metadata from controller 0 if we're isolnode. */
682 * Everyone shares node 0's bootmem allocator, but 732 if (node_isset(i, isolnodes))
683 * we use alloc_remap(), above, to put the actual 733 NODE_DATA(i)->bdata = &bootmem_node_data[0];
684 * struct page array on the individual controllers,
685 * which is most of the data that we actually care about.
686 * We can't place bootmem allocators on the other
687 * controllers since the bootmem allocator can only
688 * operate on 32-bit physical addresses.
689 */
690 NODE_DATA(i)->bdata = NODE_DATA(0)->bdata;
691 734
692 free_area_init_node(i, zones_size, start, NULL); 735 free_area_init_node(i, zones_size, start, NULL);
693 printk(KERN_DEBUG " Normal zone: %ld per-cpu pages\n", 736 printk(KERN_DEBUG " Normal zone: %ld per-cpu pages\n",
@@ -870,6 +913,22 @@ subsys_initcall(topology_init);
870 913
871#endif /* CONFIG_NUMA */ 914#endif /* CONFIG_NUMA */
872 915
916/*
917 * Initialize hugepage support on this cpu. We do this on all cores
918 * early in boot: before argument parsing for the boot cpu, and after
919 * argument parsing but before the init functions run on the secondaries.
920 * So the values we set up here in the hypervisor may be overridden on
921 * the boot cpu as arguments are parsed.
922 */
923static __cpuinit void init_super_pages(void)
924{
925#ifdef CONFIG_HUGETLB_SUPER_PAGES
926 int i;
927 for (i = 0; i < HUGE_SHIFT_ENTRIES; ++i)
928 hv_set_pte_super_shift(i, huge_shift[i]);
929#endif
930}
931
873/** 932/**
874 * setup_cpu() - Do all necessary per-cpu, tile-specific initialization. 933 * setup_cpu() - Do all necessary per-cpu, tile-specific initialization.
875 * @boot: Is this the boot cpu? 934 * @boot: Is this the boot cpu?
@@ -924,6 +983,8 @@ void __cpuinit setup_cpu(int boot)
924 /* Reset the network state on this cpu. */ 983 /* Reset the network state on this cpu. */
925 reset_network_state(); 984 reset_network_state();
926#endif 985#endif
986
987 init_super_pages();
927} 988}
928 989
929#ifdef CONFIG_BLK_DEV_INITRD 990#ifdef CONFIG_BLK_DEV_INITRD
@@ -1412,13 +1473,13 @@ void __init setup_per_cpu_areas(void)
1412 for (i = 0; i < size; i += PAGE_SIZE, ++pfn, ++pg) { 1473 for (i = 0; i < size; i += PAGE_SIZE, ++pfn, ++pg) {
1413 1474
1414 /* Update the vmalloc mapping and page home. */ 1475 /* Update the vmalloc mapping and page home. */
1415 pte_t *ptep = 1476 unsigned long addr = (unsigned long)ptr + i;
1416 virt_to_pte(NULL, (unsigned long)ptr + i); 1477 pte_t *ptep = virt_to_pte(NULL, addr);
1417 pte_t pte = *ptep; 1478 pte_t pte = *ptep;
1418 BUG_ON(pfn != pte_pfn(pte)); 1479 BUG_ON(pfn != pte_pfn(pte));
1419 pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_TILE_L3); 1480 pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_TILE_L3);
1420 pte = set_remote_cache_cpu(pte, cpu); 1481 pte = set_remote_cache_cpu(pte, cpu);
1421 set_pte(ptep, pte); 1482 set_pte_at(&init_mm, addr, ptep, pte);
1422 1483
1423 /* Update the lowmem mapping for consistency. */ 1484 /* Update the lowmem mapping for consistency. */
1424 lowmem_va = (unsigned long)pfn_to_kaddr(pfn); 1485 lowmem_va = (unsigned long)pfn_to_kaddr(pfn);
@@ -1431,7 +1492,7 @@ void __init setup_per_cpu_areas(void)
1431 BUG_ON(pte_huge(*ptep)); 1492 BUG_ON(pte_huge(*ptep));
1432 } 1493 }
1433 BUG_ON(pfn != pte_pfn(*ptep)); 1494 BUG_ON(pfn != pte_pfn(*ptep));
1434 set_pte(ptep, pte); 1495 set_pte_at(&init_mm, lowmem_va, ptep, pte);
1435 } 1496 }
1436 } 1497 }
1437 1498
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index 89529c9f0605..27742e87e255 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -172,9 +172,6 @@ static tile_bundle_bits rewrite_load_store_unaligned(
172 return (tilepro_bundle_bits) 0; 172 return (tilepro_bundle_bits) 0;
173 } 173 }
174 174
175#ifndef __LITTLE_ENDIAN
176# error We assume little-endian representation with copy_xx_user size 2 here
177#endif
178 /* Handle unaligned load/store */ 175 /* Handle unaligned load/store */
179 if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) { 176 if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) {
180 unsigned short val_16; 177 unsigned short val_16;
@@ -195,8 +192,19 @@ static tile_bundle_bits rewrite_load_store_unaligned(
195 state->update = 1; 192 state->update = 1;
196 } 193 }
197 } else { 194 } else {
195 unsigned short val_16;
198 val = (val_reg == TREG_ZERO) ? 0 : regs->regs[val_reg]; 196 val = (val_reg == TREG_ZERO) ? 0 : regs->regs[val_reg];
199 err = copy_to_user(addr, &val, size); 197 switch (size) {
198 case 2:
199 val_16 = val;
200 err = copy_to_user(addr, &val_16, sizeof(val_16));
201 break;
202 case 4:
203 err = copy_to_user(addr, &val, sizeof(val));
204 break;
205 default:
206 BUG();
207 }
200 } 208 }
201 209
202 if (err) { 210 if (err) {
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c
index 91da0f721958..cbc73a8b8fe1 100644
--- a/arch/tile/kernel/smp.c
+++ b/arch/tile/kernel/smp.c
@@ -203,7 +203,7 @@ void __init ipi_init(void)
203 if (hv_get_ipi_pte(tile, KERNEL_PL, &pte) != 0) 203 if (hv_get_ipi_pte(tile, KERNEL_PL, &pte) != 0)
204 panic("Failed to initialize IPI for cpu %d\n", cpu); 204 panic("Failed to initialize IPI for cpu %d\n", cpu);
205 205
206 offset = hv_pte_get_pfn(pte) << PAGE_SHIFT; 206 offset = PFN_PHYS(pte_pfn(pte));
207 ipi_mappings[cpu] = ioremap_prot(offset, PAGE_SIZE, pte); 207 ipi_mappings[cpu] = ioremap_prot(offset, PAGE_SIZE, pte);
208 } 208 }
209#endif 209#endif
diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c
index cb44ba7ccd2d..b08095b402d6 100644
--- a/arch/tile/kernel/sys.c
+++ b/arch/tile/kernel/sys.c
@@ -32,11 +32,17 @@
32#include <asm/syscalls.h> 32#include <asm/syscalls.h>
33#include <asm/pgtable.h> 33#include <asm/pgtable.h>
34#include <asm/homecache.h> 34#include <asm/homecache.h>
35#include <asm/cachectl.h>
35#include <arch/chip.h> 36#include <arch/chip.h>
36 37
37SYSCALL_DEFINE0(flush_cache) 38SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, len,
39 unsigned long, flags)
38{ 40{
39 homecache_evict(cpumask_of(smp_processor_id())); 41 if (flags & DCACHE)
42 homecache_evict(cpumask_of(smp_processor_id()));
43 if (flags & ICACHE)
44 flush_remote(0, HV_FLUSH_EVICT_L1I, mm_cpumask(current->mm),
45 0, 0, 0, NULL, NULL, 0);
40 return 0; 46 return 0;
41} 47}
42 48
diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c
index 71ae728e9d0b..e25b0a89c18f 100644
--- a/arch/tile/kernel/sysfs.c
+++ b/arch/tile/kernel/sysfs.c
@@ -93,6 +93,10 @@ HV_CONF_ATTR(mezz_part, HV_CONFSTR_MEZZ_PART_NUM)
93HV_CONF_ATTR(mezz_serial, HV_CONFSTR_MEZZ_SERIAL_NUM) 93HV_CONF_ATTR(mezz_serial, HV_CONFSTR_MEZZ_SERIAL_NUM)
94HV_CONF_ATTR(mezz_revision, HV_CONFSTR_MEZZ_REV) 94HV_CONF_ATTR(mezz_revision, HV_CONFSTR_MEZZ_REV)
95HV_CONF_ATTR(mezz_description, HV_CONFSTR_MEZZ_DESC) 95HV_CONF_ATTR(mezz_description, HV_CONFSTR_MEZZ_DESC)
96HV_CONF_ATTR(cpumod_part, HV_CONFSTR_CPUMOD_PART_NUM)
97HV_CONF_ATTR(cpumod_serial, HV_CONFSTR_CPUMOD_SERIAL_NUM)
98HV_CONF_ATTR(cpumod_revision, HV_CONFSTR_CPUMOD_REV)
99HV_CONF_ATTR(cpumod_description,HV_CONFSTR_CPUMOD_DESC)
96HV_CONF_ATTR(switch_control, HV_CONFSTR_SWITCH_CONTROL) 100HV_CONF_ATTR(switch_control, HV_CONFSTR_SWITCH_CONTROL)
97 101
98static struct attribute *board_attrs[] = { 102static struct attribute *board_attrs[] = {
@@ -104,6 +108,10 @@ static struct attribute *board_attrs[] = {
104 &dev_attr_mezz_serial.attr, 108 &dev_attr_mezz_serial.attr,
105 &dev_attr_mezz_revision.attr, 109 &dev_attr_mezz_revision.attr,
106 &dev_attr_mezz_description.attr, 110 &dev_attr_mezz_description.attr,
111 &dev_attr_cpumod_part.attr,
112 &dev_attr_cpumod_serial.attr,
113 &dev_attr_cpumod_revision.attr,
114 &dev_attr_cpumod_description.attr,
107 &dev_attr_switch_control.attr, 115 &dev_attr_switch_control.attr,
108 NULL 116 NULL
109}; 117};
diff --git a/arch/tile/kernel/tlb.c b/arch/tile/kernel/tlb.c
index a5f241c24cac..3fd54d5bbd4c 100644
--- a/arch/tile/kernel/tlb.c
+++ b/arch/tile/kernel/tlb.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/cpumask.h> 16#include <linux/cpumask.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/hugetlb.h>
18#include <asm/tlbflush.h> 19#include <asm/tlbflush.h>
19#include <asm/homecache.h> 20#include <asm/homecache.h>
20#include <hv/hypervisor.h> 21#include <hv/hypervisor.h>
@@ -49,25 +50,25 @@ void flush_tlb_current_task(void)
49 flush_tlb_mm(current->mm); 50 flush_tlb_mm(current->mm);
50} 51}
51 52
52void flush_tlb_page_mm(const struct vm_area_struct *vma, struct mm_struct *mm, 53void flush_tlb_page_mm(struct vm_area_struct *vma, struct mm_struct *mm,
53 unsigned long va) 54 unsigned long va)
54{ 55{
55 unsigned long size = hv_page_size(vma); 56 unsigned long size = vma_kernel_pagesize(vma);
56 int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; 57 int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0;
57 flush_remote(0, cache, mm_cpumask(mm), 58 flush_remote(0, cache, mm_cpumask(mm),
58 va, size, size, mm_cpumask(mm), NULL, 0); 59 va, size, size, mm_cpumask(mm), NULL, 0);
59} 60}
60 61
61void flush_tlb_page(const struct vm_area_struct *vma, unsigned long va) 62void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
62{ 63{
63 flush_tlb_page_mm(vma, vma->vm_mm, va); 64 flush_tlb_page_mm(vma, vma->vm_mm, va);
64} 65}
65EXPORT_SYMBOL(flush_tlb_page); 66EXPORT_SYMBOL(flush_tlb_page);
66 67
67void flush_tlb_range(const struct vm_area_struct *vma, 68void flush_tlb_range(struct vm_area_struct *vma,
68 unsigned long start, unsigned long end) 69 unsigned long start, unsigned long end)
69{ 70{
70 unsigned long size = hv_page_size(vma); 71 unsigned long size = vma_kernel_pagesize(vma);
71 struct mm_struct *mm = vma->vm_mm; 72 struct mm_struct *mm = vma->vm_mm;
72 int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; 73 int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0;
73 flush_remote(0, cache, mm_cpumask(mm), start, end - start, size, 74 flush_remote(0, cache, mm_cpumask(mm), start, end - start, size,
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c
index 73cff814ac57..5b19a23c8908 100644
--- a/arch/tile/kernel/traps.c
+++ b/arch/tile/kernel/traps.c
@@ -195,6 +195,25 @@ static int special_ill(bundle_bits bundle, int *sigp, int *codep)
195 return 1; 195 return 1;
196} 196}
197 197
198static const char *const int_name[] = {
199 [INT_MEM_ERROR] = "Memory error",
200 [INT_ILL] = "Illegal instruction",
201 [INT_GPV] = "General protection violation",
202 [INT_UDN_ACCESS] = "UDN access",
203 [INT_IDN_ACCESS] = "IDN access",
204#if CHIP_HAS_SN()
205 [INT_SN_ACCESS] = "SN access",
206#endif
207 [INT_SWINT_3] = "Software interrupt 3",
208 [INT_SWINT_2] = "Software interrupt 2",
209 [INT_SWINT_0] = "Software interrupt 0",
210 [INT_UNALIGN_DATA] = "Unaligned data",
211 [INT_DOUBLE_FAULT] = "Double fault",
212#ifdef __tilegx__
213 [INT_ILL_TRANS] = "Illegal virtual address",
214#endif
215};
216
198void __kprobes do_trap(struct pt_regs *regs, int fault_num, 217void __kprobes do_trap(struct pt_regs *regs, int fault_num,
199 unsigned long reason) 218 unsigned long reason)
200{ 219{
@@ -211,10 +230,17 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
211 * current process and hope for the best. 230 * current process and hope for the best.
212 */ 231 */
213 if (!user_mode(regs)) { 232 if (!user_mode(regs)) {
233 const char *name;
214 if (fixup_exception(regs)) /* only UNALIGN_DATA in practice */ 234 if (fixup_exception(regs)) /* only UNALIGN_DATA in practice */
215 return; 235 return;
216 pr_alert("Kernel took bad trap %d at PC %#lx\n", 236 if (fault_num >= 0 &&
217 fault_num, regs->pc); 237 fault_num < sizeof(int_name)/sizeof(int_name[0]) &&
238 int_name[fault_num] != NULL)
239 name = int_name[fault_num];
240 else
241 name = "Unknown interrupt";
242 pr_alert("Kernel took bad trap %d (%s) at PC %#lx\n",
243 fault_num, name, regs->pc);
218 if (fault_num == INT_GPV) 244 if (fault_num == INT_GPV)
219 pr_alert("GPV_REASON is %#lx\n", reason); 245 pr_alert("GPV_REASON is %#lx\n", reason);
220 show_regs(regs); 246 show_regs(regs);
diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c
index 771b251b409d..f5cada70c3c8 100644
--- a/arch/tile/lib/atomic_32.c
+++ b/arch/tile/lib/atomic_32.c
@@ -18,7 +18,6 @@
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/atomic.h> 20#include <linux/atomic.h>
21#include <asm/futex.h>
22#include <arch/chip.h> 21#include <arch/chip.h>
23 22
24/* See <asm/atomic_32.h> */ 23/* See <asm/atomic_32.h> */
@@ -50,7 +49,7 @@ int atomic_locks[PAGE_SIZE / sizeof(int)] __page_aligned_bss;
50 49
51#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ 50#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
52 51
53static inline int *__atomic_hashed_lock(volatile void *v) 52int *__atomic_hashed_lock(volatile void *v)
54{ 53{
55 /* NOTE: this code must match "sys_cmpxchg" in kernel/intvec_32.S */ 54 /* NOTE: this code must match "sys_cmpxchg" in kernel/intvec_32.S */
56#if ATOMIC_LOCKS_FOUND_VIA_TABLE() 55#if ATOMIC_LOCKS_FOUND_VIA_TABLE()
@@ -191,47 +190,6 @@ u64 _atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n)
191EXPORT_SYMBOL(_atomic64_cmpxchg); 190EXPORT_SYMBOL(_atomic64_cmpxchg);
192 191
193 192
194static inline int *__futex_setup(int __user *v)
195{
196 /*
197 * Issue a prefetch to the counter to bring it into cache.
198 * As for __atomic_setup, but we can't do a read into the L1
199 * since it might fault; instead we do a prefetch into the L2.
200 */
201 __insn_prefetch(v);
202 return __atomic_hashed_lock((int __force *)v);
203}
204
205struct __get_user futex_set(u32 __user *v, int i)
206{
207 return __atomic_xchg((int __force *)v, __futex_setup(v), i);
208}
209
210struct __get_user futex_add(u32 __user *v, int n)
211{
212 return __atomic_xchg_add((int __force *)v, __futex_setup(v), n);
213}
214
215struct __get_user futex_or(u32 __user *v, int n)
216{
217 return __atomic_or((int __force *)v, __futex_setup(v), n);
218}
219
220struct __get_user futex_andn(u32 __user *v, int n)
221{
222 return __atomic_andn((int __force *)v, __futex_setup(v), n);
223}
224
225struct __get_user futex_xor(u32 __user *v, int n)
226{
227 return __atomic_xor((int __force *)v, __futex_setup(v), n);
228}
229
230struct __get_user futex_cmpxchg(u32 __user *v, int o, int n)
231{
232 return __atomic_cmpxchg((int __force *)v, __futex_setup(v), o, n);
233}
234
235/* 193/*
236 * If any of the atomic or futex routines hit a bad address (not in 194 * If any of the atomic or futex routines hit a bad address (not in
237 * the page tables at kernel PL) this routine is called. The futex 195 * the page tables at kernel PL) this routine is called. The futex
@@ -323,7 +281,4 @@ void __init __init_atomic_per_cpu(void)
323 BUILD_BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE); 281 BUILD_BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE);
324 282
325#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ 283#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
326
327 /* The futex code makes this assumption, so we validate it here. */
328 BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
329} 284}
diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c
index 2a81d32de0da..dd5f0a33fdaf 100644
--- a/arch/tile/lib/exports.c
+++ b/arch/tile/lib/exports.c
@@ -18,14 +18,6 @@
18 18
19/* arch/tile/lib/usercopy.S */ 19/* arch/tile/lib/usercopy.S */
20#include <linux/uaccess.h> 20#include <linux/uaccess.h>
21EXPORT_SYMBOL(__get_user_1);
22EXPORT_SYMBOL(__get_user_2);
23EXPORT_SYMBOL(__get_user_4);
24EXPORT_SYMBOL(__get_user_8);
25EXPORT_SYMBOL(__put_user_1);
26EXPORT_SYMBOL(__put_user_2);
27EXPORT_SYMBOL(__put_user_4);
28EXPORT_SYMBOL(__put_user_8);
29EXPORT_SYMBOL(strnlen_user_asm); 21EXPORT_SYMBOL(strnlen_user_asm);
30EXPORT_SYMBOL(strncpy_from_user_asm); 22EXPORT_SYMBOL(strncpy_from_user_asm);
31EXPORT_SYMBOL(clear_user_asm); 23EXPORT_SYMBOL(clear_user_asm);
diff --git a/arch/tile/lib/memchr_64.c b/arch/tile/lib/memchr_64.c
index 84fdc8d8e735..6f867dbf7c56 100644
--- a/arch/tile/lib/memchr_64.c
+++ b/arch/tile/lib/memchr_64.c
@@ -15,6 +15,7 @@
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include "string-endian.h"
18 19
19void *memchr(const void *s, int c, size_t n) 20void *memchr(const void *s, int c, size_t n)
20{ 21{
@@ -39,11 +40,8 @@ void *memchr(const void *s, int c, size_t n)
39 40
40 /* Read the first word, but munge it so that bytes before the array 41 /* Read the first word, but munge it so that bytes before the array
41 * will not match goal. 42 * will not match goal.
42 *
43 * Note that this shift count expression works because we know
44 * shift counts are taken mod 64.
45 */ 43 */
46 before_mask = (1ULL << (s_int << 3)) - 1; 44 before_mask = MASK(s_int);
47 v = (*p | before_mask) ^ (goal & before_mask); 45 v = (*p | before_mask) ^ (goal & before_mask);
48 46
49 /* Compute the address of the last byte. */ 47 /* Compute the address of the last byte. */
@@ -65,7 +63,7 @@ void *memchr(const void *s, int c, size_t n)
65 /* We found a match, but it might be in a byte past the end 63 /* We found a match, but it might be in a byte past the end
66 * of the array. 64 * of the array.
67 */ 65 */
68 ret = ((char *)p) + (__insn_ctz(bits) >> 3); 66 ret = ((char *)p) + (CFZ(bits) >> 3);
69 return (ret <= last_byte_ptr) ? ret : NULL; 67 return (ret <= last_byte_ptr) ? ret : NULL;
70} 68}
71EXPORT_SYMBOL(memchr); 69EXPORT_SYMBOL(memchr);
diff --git a/arch/tile/lib/memcpy_64.c b/arch/tile/lib/memcpy_64.c
index 3fab9a6a2bbe..c79b8e7c6828 100644
--- a/arch/tile/lib/memcpy_64.c
+++ b/arch/tile/lib/memcpy_64.c
@@ -15,7 +15,6 @@
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#define __memcpy memcpy
19/* EXPORT_SYMBOL() is in arch/tile/lib/exports.c since this should be asm. */ 18/* EXPORT_SYMBOL() is in arch/tile/lib/exports.c since this should be asm. */
20 19
21/* Must be 8 bytes in size. */ 20/* Must be 8 bytes in size. */
@@ -188,6 +187,7 @@ int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n)
188 187
189 /* n != 0 if we get here. Write out any trailing bytes. */ 188 /* n != 0 if we get here. Write out any trailing bytes. */
190 dst1 = (char *)dst8; 189 dst1 = (char *)dst8;
190#ifndef __BIG_ENDIAN__
191 if (n & 4) { 191 if (n & 4) {
192 ST4((uint32_t *)dst1, final); 192 ST4((uint32_t *)dst1, final);
193 dst1 += 4; 193 dst1 += 4;
@@ -202,11 +202,30 @@ int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n)
202 } 202 }
203 if (n) 203 if (n)
204 ST1((uint8_t *)dst1, final); 204 ST1((uint8_t *)dst1, final);
205#else
206 if (n & 4) {
207 ST4((uint32_t *)dst1, final >> 32);
208 dst1 += 4;
209 }
210 else
211 {
212 final >>= 32;
213 }
214 if (n & 2) {
215 ST2((uint16_t *)dst1, final >> 16);
216 dst1 += 2;
217 }
218 else
219 {
220 final >>= 16;
221 }
222 if (n & 1)
223 ST1((uint8_t *)dst1, final >> 8);
224#endif
205 225
206 return RETVAL; 226 return RETVAL;
207} 227}
208 228
209
210#ifdef USERCOPY_FUNC 229#ifdef USERCOPY_FUNC
211#undef ST1 230#undef ST1
212#undef ST2 231#undef ST2
diff --git a/arch/tile/lib/memcpy_tile64.c b/arch/tile/lib/memcpy_tile64.c
index b2fe15e01075..3bc4b4e40d93 100644
--- a/arch/tile/lib/memcpy_tile64.c
+++ b/arch/tile/lib/memcpy_tile64.c
@@ -160,7 +160,7 @@ retry_source:
160 break; 160 break;
161 if (get_remote_cache_cpu(src_pte) == smp_processor_id()) 161 if (get_remote_cache_cpu(src_pte) == smp_processor_id())
162 break; 162 break;
163 src_page = pfn_to_page(hv_pte_get_pfn(src_pte)); 163 src_page = pfn_to_page(pte_pfn(src_pte));
164 get_page(src_page); 164 get_page(src_page);
165 if (pte_val(src_pte) != pte_val(*src_ptep)) { 165 if (pte_val(src_pte) != pte_val(*src_ptep)) {
166 put_page(src_page); 166 put_page(src_page);
@@ -168,7 +168,7 @@ retry_source:
168 } 168 }
169 if (pte_huge(src_pte)) { 169 if (pte_huge(src_pte)) {
170 /* Adjust the PTE to correspond to a small page */ 170 /* Adjust the PTE to correspond to a small page */
171 int pfn = hv_pte_get_pfn(src_pte); 171 int pfn = pte_pfn(src_pte);
172 pfn += (((unsigned long)source & (HPAGE_SIZE-1)) 172 pfn += (((unsigned long)source & (HPAGE_SIZE-1))
173 >> PAGE_SHIFT); 173 >> PAGE_SHIFT);
174 src_pte = pfn_pte(pfn, src_pte); 174 src_pte = pfn_pte(pfn, src_pte);
@@ -188,7 +188,7 @@ retry_dest:
188 put_page(src_page); 188 put_page(src_page);
189 break; 189 break;
190 } 190 }
191 dst_page = pfn_to_page(hv_pte_get_pfn(dst_pte)); 191 dst_page = pfn_to_page(pte_pfn(dst_pte));
192 if (dst_page == src_page) { 192 if (dst_page == src_page) {
193 /* 193 /*
194 * Source and dest are on the same page; this 194 * Source and dest are on the same page; this
@@ -206,7 +206,7 @@ retry_dest:
206 } 206 }
207 if (pte_huge(dst_pte)) { 207 if (pte_huge(dst_pte)) {
208 /* Adjust the PTE to correspond to a small page */ 208 /* Adjust the PTE to correspond to a small page */
209 int pfn = hv_pte_get_pfn(dst_pte); 209 int pfn = pte_pfn(dst_pte);
210 pfn += (((unsigned long)dest & (HPAGE_SIZE-1)) 210 pfn += (((unsigned long)dest & (HPAGE_SIZE-1))
211 >> PAGE_SHIFT); 211 >> PAGE_SHIFT);
212 dst_pte = pfn_pte(pfn, dst_pte); 212 dst_pte = pfn_pte(pfn, dst_pte);
diff --git a/arch/tile/lib/strchr_64.c b/arch/tile/lib/strchr_64.c
index 617a9273aaa8..f39f9dc422b0 100644
--- a/arch/tile/lib/strchr_64.c
+++ b/arch/tile/lib/strchr_64.c
@@ -15,8 +15,7 @@
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/module.h> 17#include <linux/module.h>
18 18#include "string-endian.h"
19#undef strchr
20 19
21char *strchr(const char *s, int c) 20char *strchr(const char *s, int c)
22{ 21{
@@ -33,13 +32,9 @@ char *strchr(const char *s, int c)
33 * match neither zero nor goal (we make sure the high bit of each 32 * match neither zero nor goal (we make sure the high bit of each
34 * byte is 1, and the low 7 bits are all the opposite of the goal 33 * byte is 1, and the low 7 bits are all the opposite of the goal
35 * byte). 34 * byte).
36 *
37 * Note that this shift count expression works because we know shift
38 * counts are taken mod 64.
39 */ 35 */
40 const uint64_t before_mask = (1ULL << (s_int << 3)) - 1; 36 const uint64_t before_mask = MASK(s_int);
41 uint64_t v = (*p | before_mask) ^ 37 uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui(before_mask, 1));
42 (goal & __insn_v1shrsi(before_mask, 1));
43 38
44 uint64_t zero_matches, goal_matches; 39 uint64_t zero_matches, goal_matches;
45 while (1) { 40 while (1) {
@@ -55,8 +50,8 @@ char *strchr(const char *s, int c)
55 v = *++p; 50 v = *++p;
56 } 51 }
57 52
58 z = __insn_ctz(zero_matches); 53 z = CFZ(zero_matches);
59 g = __insn_ctz(goal_matches); 54 g = CFZ(goal_matches);
60 55
61 /* If we found c before '\0' we got a match. Note that if c == '\0' 56 /* If we found c before '\0' we got a match. Note that if c == '\0'
62 * then g == z, and we correctly return the address of the '\0' 57 * then g == z, and we correctly return the address of the '\0'
diff --git a/arch/tile/lib/string-endian.h b/arch/tile/lib/string-endian.h
new file mode 100644
index 000000000000..c0eed7ce69c3
--- /dev/null
+++ b/arch/tile/lib/string-endian.h
@@ -0,0 +1,33 @@
1/*
2 * Copyright 2011 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 *
14 * Provide a mask based on the pointer alignment that
15 * sets up non-zero bytes before the beginning of the string.
16 * The MASK expression works because shift counts are taken mod 64.
17 * Also, specify how to count "first" and "last" bits
18 * when the bits have been read as a word.
19 */
20
21#include <asm/byteorder.h>
22
23#ifdef __LITTLE_ENDIAN
24#define MASK(x) (__insn_shl(1ULL, (x << 3)) - 1)
25#define NULMASK(x) ((2ULL << x) - 1)
26#define CFZ(x) __insn_ctz(x)
27#define REVCZ(x) __insn_clz(x)
28#else
29#define MASK(x) (__insn_shl(-2LL, ((-x << 3) - 1)))
30#define NULMASK(x) (-2LL << (63 - x))
31#define CFZ(x) __insn_clz(x)
32#define REVCZ(x) __insn_ctz(x)
33#endif
diff --git a/arch/tile/lib/strlen_64.c b/arch/tile/lib/strlen_64.c
index 1c92d46202a8..9583fc3361fa 100644
--- a/arch/tile/lib/strlen_64.c
+++ b/arch/tile/lib/strlen_64.c
@@ -15,8 +15,7 @@
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/module.h> 17#include <linux/module.h>
18 18#include "string-endian.h"
19#undef strlen
20 19
21size_t strlen(const char *s) 20size_t strlen(const char *s)
22{ 21{
@@ -24,15 +23,13 @@ size_t strlen(const char *s)
24 const uintptr_t s_int = (uintptr_t) s; 23 const uintptr_t s_int = (uintptr_t) s;
25 const uint64_t *p = (const uint64_t *)(s_int & -8); 24 const uint64_t *p = (const uint64_t *)(s_int & -8);
26 25
27 /* Read the first word, but force bytes before the string to be nonzero. 26 /* Read and MASK the first word. */
28 * This expression works because we know shift counts are taken mod 64. 27 uint64_t v = *p | MASK(s_int);
29 */
30 uint64_t v = *p | ((1ULL << (s_int << 3)) - 1);
31 28
32 uint64_t bits; 29 uint64_t bits;
33 while ((bits = __insn_v1cmpeqi(v, 0)) == 0) 30 while ((bits = __insn_v1cmpeqi(v, 0)) == 0)
34 v = *++p; 31 v = *++p;
35 32
36 return ((const char *)p) + (__insn_ctz(bits) >> 3) - s; 33 return ((const char *)p) + (CFZ(bits) >> 3) - s;
37} 34}
38EXPORT_SYMBOL(strlen); 35EXPORT_SYMBOL(strlen);
diff --git a/arch/tile/lib/usercopy_32.S b/arch/tile/lib/usercopy_32.S
index 979f76d83746..b62d002af009 100644
--- a/arch/tile/lib/usercopy_32.S
+++ b/arch/tile/lib/usercopy_32.S
@@ -19,82 +19,6 @@
19 19
20/* Access user memory, but use MMU to avoid propagating kernel exceptions. */ 20/* Access user memory, but use MMU to avoid propagating kernel exceptions. */
21 21
22 .pushsection .fixup,"ax"
23
24get_user_fault:
25 { move r0, zero; move r1, zero }
26 { movei r2, -EFAULT; jrp lr }
27 ENDPROC(get_user_fault)
28
29put_user_fault:
30 { movei r0, -EFAULT; jrp lr }
31 ENDPROC(put_user_fault)
32
33 .popsection
34
35/*
36 * __get_user_N functions take a pointer in r0, and return 0 in r2
37 * on success, with the value in r0; or else -EFAULT in r2.
38 */
39#define __get_user_N(bytes, LOAD) \
40 STD_ENTRY(__get_user_##bytes); \
411: { LOAD r0, r0; move r1, zero; move r2, zero }; \
42 jrp lr; \
43 STD_ENDPROC(__get_user_##bytes); \
44 .pushsection __ex_table,"a"; \
45 .word 1b, get_user_fault; \
46 .popsection
47
48__get_user_N(1, lb_u)
49__get_user_N(2, lh_u)
50__get_user_N(4, lw)
51
52/*
53 * __get_user_8 takes a pointer in r0, and returns 0 in r2
54 * on success, with the value in r0/r1; or else -EFAULT in r2.
55 */
56 STD_ENTRY(__get_user_8);
571: { lw r0, r0; addi r1, r0, 4 };
582: { lw r1, r1; move r2, zero };
59 jrp lr;
60 STD_ENDPROC(__get_user_8);
61 .pushsection __ex_table,"a";
62 .word 1b, get_user_fault;
63 .word 2b, get_user_fault;
64 .popsection
65
66/*
67 * __put_user_N functions take a value in r0 and a pointer in r1,
68 * and return 0 in r0 on success or -EFAULT on failure.
69 */
70#define __put_user_N(bytes, STORE) \
71 STD_ENTRY(__put_user_##bytes); \
721: { STORE r1, r0; move r0, zero }; \
73 jrp lr; \
74 STD_ENDPROC(__put_user_##bytes); \
75 .pushsection __ex_table,"a"; \
76 .word 1b, put_user_fault; \
77 .popsection
78
79__put_user_N(1, sb)
80__put_user_N(2, sh)
81__put_user_N(4, sw)
82
83/*
84 * __put_user_8 takes a value in r0/r1 and a pointer in r2,
85 * and returns 0 in r0 on success or -EFAULT on failure.
86 */
87STD_ENTRY(__put_user_8)
881: { sw r2, r0; addi r2, r2, 4 }
892: { sw r2, r1; move r0, zero }
90 jrp lr
91 STD_ENDPROC(__put_user_8)
92 .pushsection __ex_table,"a"
93 .word 1b, put_user_fault
94 .word 2b, put_user_fault
95 .popsection
96
97
98/* 22/*
99 * strnlen_user_asm takes the pointer in r0, and the length bound in r1. 23 * strnlen_user_asm takes the pointer in r0, and the length bound in r1.
100 * It returns the length, including the terminating NUL, or zero on exception. 24 * It returns the length, including the terminating NUL, or zero on exception.
diff --git a/arch/tile/lib/usercopy_64.S b/arch/tile/lib/usercopy_64.S
index 2ff44f87b78e..adb2dbbc70cd 100644
--- a/arch/tile/lib/usercopy_64.S
+++ b/arch/tile/lib/usercopy_64.S
@@ -19,55 +19,6 @@
19 19
20/* Access user memory, but use MMU to avoid propagating kernel exceptions. */ 20/* Access user memory, but use MMU to avoid propagating kernel exceptions. */
21 21
22 .pushsection .fixup,"ax"
23
24get_user_fault:
25 { movei r1, -EFAULT; move r0, zero }
26 jrp lr
27 ENDPROC(get_user_fault)
28
29put_user_fault:
30 { movei r0, -EFAULT; jrp lr }
31 ENDPROC(put_user_fault)
32
33 .popsection
34
35/*
36 * __get_user_N functions take a pointer in r0, and return 0 in r1
37 * on success, with the value in r0; or else -EFAULT in r1.
38 */
39#define __get_user_N(bytes, LOAD) \
40 STD_ENTRY(__get_user_##bytes); \
411: { LOAD r0, r0; move r1, zero }; \
42 jrp lr; \
43 STD_ENDPROC(__get_user_##bytes); \
44 .pushsection __ex_table,"a"; \
45 .quad 1b, get_user_fault; \
46 .popsection
47
48__get_user_N(1, ld1u)
49__get_user_N(2, ld2u)
50__get_user_N(4, ld4u)
51__get_user_N(8, ld)
52
53/*
54 * __put_user_N functions take a value in r0 and a pointer in r1,
55 * and return 0 in r0 on success or -EFAULT on failure.
56 */
57#define __put_user_N(bytes, STORE) \
58 STD_ENTRY(__put_user_##bytes); \
591: { STORE r1, r0; move r0, zero }; \
60 jrp lr; \
61 STD_ENDPROC(__put_user_##bytes); \
62 .pushsection __ex_table,"a"; \
63 .quad 1b, put_user_fault; \
64 .popsection
65
66__put_user_N(1, st1)
67__put_user_N(2, st2)
68__put_user_N(4, st4)
69__put_user_N(8, st)
70
71/* 22/*
72 * strnlen_user_asm takes the pointer in r0, and the length bound in r1. 23 * strnlen_user_asm takes the pointer in r0, and the length bound in r1.
73 * It returns the length, including the terminating NUL, or zero on exception. 24 * It returns the length, including the terminating NUL, or zero on exception.
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index 22e58f51ed23..84ce7abbf5af 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -187,7 +187,7 @@ static pgd_t *get_current_pgd(void)
187 HV_Context ctx = hv_inquire_context(); 187 HV_Context ctx = hv_inquire_context();
188 unsigned long pgd_pfn = ctx.page_table >> PAGE_SHIFT; 188 unsigned long pgd_pfn = ctx.page_table >> PAGE_SHIFT;
189 struct page *pgd_page = pfn_to_page(pgd_pfn); 189 struct page *pgd_page = pfn_to_page(pgd_pfn);
190 BUG_ON(PageHighMem(pgd_page)); /* oops, HIGHPTE? */ 190 BUG_ON(PageHighMem(pgd_page));
191 return (pgd_t *) __va(ctx.page_table); 191 return (pgd_t *) __va(ctx.page_table);
192} 192}
193 193
@@ -273,11 +273,15 @@ static int handle_page_fault(struct pt_regs *regs,
273 int si_code; 273 int si_code;
274 int is_kernel_mode; 274 int is_kernel_mode;
275 pgd_t *pgd; 275 pgd_t *pgd;
276 unsigned int flags;
276 277
277 /* on TILE, protection faults are always writes */ 278 /* on TILE, protection faults are always writes */
278 if (!is_page_fault) 279 if (!is_page_fault)
279 write = 1; 280 write = 1;
280 281
282 flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
283 (write ? FAULT_FLAG_WRITE : 0));
284
281 is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL); 285 is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL);
282 286
283 tsk = validate_current(); 287 tsk = validate_current();
@@ -382,6 +386,8 @@ static int handle_page_fault(struct pt_regs *regs,
382 vma = NULL; /* happy compiler */ 386 vma = NULL; /* happy compiler */
383 goto bad_area_nosemaphore; 387 goto bad_area_nosemaphore;
384 } 388 }
389
390retry:
385 down_read(&mm->mmap_sem); 391 down_read(&mm->mmap_sem);
386 } 392 }
387 393
@@ -429,7 +435,11 @@ good_area:
429 * make sure we exit gracefully rather than endlessly redo 435 * make sure we exit gracefully rather than endlessly redo
430 * the fault. 436 * the fault.
431 */ 437 */
432 fault = handle_mm_fault(mm, vma, address, write); 438 fault = handle_mm_fault(mm, vma, address, flags);
439
440 if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
441 return 0;
442
433 if (unlikely(fault & VM_FAULT_ERROR)) { 443 if (unlikely(fault & VM_FAULT_ERROR)) {
434 if (fault & VM_FAULT_OOM) 444 if (fault & VM_FAULT_OOM)
435 goto out_of_memory; 445 goto out_of_memory;
@@ -437,10 +447,22 @@ good_area:
437 goto do_sigbus; 447 goto do_sigbus;
438 BUG(); 448 BUG();
439 } 449 }
440 if (fault & VM_FAULT_MAJOR) 450 if (flags & FAULT_FLAG_ALLOW_RETRY) {
441 tsk->maj_flt++; 451 if (fault & VM_FAULT_MAJOR)
442 else 452 tsk->maj_flt++;
443 tsk->min_flt++; 453 else
454 tsk->min_flt++;
455 if (fault & VM_FAULT_RETRY) {
456 flags &= ~FAULT_FLAG_ALLOW_RETRY;
457
458 /*
459 * No need to up_read(&mm->mmap_sem) as we would
460 * have already released it in __lock_page_or_retry
461 * in mm/filemap.c.
462 */
463 goto retry;
464 }
465 }
444 466
445#if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() 467#if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC()
446 /* 468 /*
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c
index 499f73770b05..dbcbdf7b8aa8 100644
--- a/arch/tile/mm/homecache.c
+++ b/arch/tile/mm/homecache.c
@@ -30,6 +30,7 @@
30#include <linux/cache.h> 30#include <linux/cache.h>
31#include <linux/smp.h> 31#include <linux/smp.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/hugetlb.h>
33 34
34#include <asm/page.h> 35#include <asm/page.h>
35#include <asm/sections.h> 36#include <asm/sections.h>
diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c
index 42cfcba4e1ef..812e2d037972 100644
--- a/arch/tile/mm/hugetlbpage.c
+++ b/arch/tile/mm/hugetlbpage.c
@@ -27,85 +27,161 @@
27#include <linux/mman.h> 27#include <linux/mman.h>
28#include <asm/tlb.h> 28#include <asm/tlb.h>
29#include <asm/tlbflush.h> 29#include <asm/tlbflush.h>
30#include <asm/setup.h>
31
32#ifdef CONFIG_HUGETLB_SUPER_PAGES
33
34/*
35 * Provide an additional huge page size (in addition to the regular default
36 * huge page size) if no "hugepagesz" arguments are specified.
37 * Note that it must be smaller than the default huge page size so
38 * that it's possible to allocate them on demand from the buddy allocator.
39 * You can change this to 64K (on a 16K build), 256K, 1M, or 4M,
40 * or not define it at all.
41 */
42#define ADDITIONAL_HUGE_SIZE (1024 * 1024UL)
43
44/* "Extra" page-size multipliers, one per level of the page table. */
45int huge_shift[HUGE_SHIFT_ENTRIES] = {
46#ifdef ADDITIONAL_HUGE_SIZE
47#define ADDITIONAL_HUGE_SHIFT __builtin_ctzl(ADDITIONAL_HUGE_SIZE / PAGE_SIZE)
48 [HUGE_SHIFT_PAGE] = ADDITIONAL_HUGE_SHIFT
49#endif
50};
51
52/*
53 * This routine is a hybrid of pte_alloc_map() and pte_alloc_kernel().
54 * It assumes that L2 PTEs are never in HIGHMEM (we don't support that).
55 * It locks the user pagetable, and bumps up the mm->nr_ptes field,
56 * but otherwise allocate the page table using the kernel versions.
57 */
58static pte_t *pte_alloc_hugetlb(struct mm_struct *mm, pmd_t *pmd,
59 unsigned long address)
60{
61 pte_t *new;
62
63 if (pmd_none(*pmd)) {
64 new = pte_alloc_one_kernel(mm, address);
65 if (!new)
66 return NULL;
67
68 smp_wmb(); /* See comment in __pte_alloc */
69
70 spin_lock(&mm->page_table_lock);
71 if (likely(pmd_none(*pmd))) { /* Has another populated it ? */
72 mm->nr_ptes++;
73 pmd_populate_kernel(mm, pmd, new);
74 new = NULL;
75 } else
76 VM_BUG_ON(pmd_trans_splitting(*pmd));
77 spin_unlock(&mm->page_table_lock);
78 if (new)
79 pte_free_kernel(mm, new);
80 }
81
82 return pte_offset_kernel(pmd, address);
83}
84#endif
30 85
31pte_t *huge_pte_alloc(struct mm_struct *mm, 86pte_t *huge_pte_alloc(struct mm_struct *mm,
32 unsigned long addr, unsigned long sz) 87 unsigned long addr, unsigned long sz)
33{ 88{
34 pgd_t *pgd; 89 pgd_t *pgd;
35 pud_t *pud; 90 pud_t *pud;
36 pte_t *pte = NULL;
37 91
38 /* We do not yet support multiple huge page sizes. */ 92 addr &= -sz; /* Mask off any low bits in the address. */
39 BUG_ON(sz != PMD_SIZE);
40 93
41 pgd = pgd_offset(mm, addr); 94 pgd = pgd_offset(mm, addr);
42 pud = pud_alloc(mm, pgd, addr); 95 pud = pud_alloc(mm, pgd, addr);
43 if (pud)
44 pte = (pte_t *) pmd_alloc(mm, pud, addr);
45 BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
46 96
47 return pte; 97#ifdef CONFIG_HUGETLB_SUPER_PAGES
98 if (sz >= PGDIR_SIZE) {
99 BUG_ON(sz != PGDIR_SIZE &&
100 sz != PGDIR_SIZE << huge_shift[HUGE_SHIFT_PGDIR]);
101 return (pte_t *)pud;
102 } else {
103 pmd_t *pmd = pmd_alloc(mm, pud, addr);
104 if (sz >= PMD_SIZE) {
105 BUG_ON(sz != PMD_SIZE &&
106 sz != (PMD_SIZE << huge_shift[HUGE_SHIFT_PMD]));
107 return (pte_t *)pmd;
108 }
109 else {
110 if (sz != PAGE_SIZE << huge_shift[HUGE_SHIFT_PAGE])
111 panic("Unexpected page size %#lx\n", sz);
112 return pte_alloc_hugetlb(mm, pmd, addr);
113 }
114 }
115#else
116 BUG_ON(sz != PMD_SIZE);
117 return (pte_t *) pmd_alloc(mm, pud, addr);
118#endif
48} 119}
49 120
50pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) 121static pte_t *get_pte(pte_t *base, int index, int level)
51{ 122{
52 pgd_t *pgd; 123 pte_t *ptep = base + index;
53 pud_t *pud; 124#ifdef CONFIG_HUGETLB_SUPER_PAGES
54 pmd_t *pmd = NULL; 125 if (!pte_present(*ptep) && huge_shift[level] != 0) {
55 126 unsigned long mask = -1UL << huge_shift[level];
56 pgd = pgd_offset(mm, addr); 127 pte_t *super_ptep = base + (index & mask);
57 if (pgd_present(*pgd)) { 128 pte_t pte = *super_ptep;
58 pud = pud_offset(pgd, addr); 129 if (pte_present(pte) && pte_super(pte))
59 if (pud_present(*pud)) 130 ptep = super_ptep;
60 pmd = pmd_offset(pud, addr);
61 } 131 }
62 return (pte_t *) pmd; 132#endif
133 return ptep;
63} 134}
64 135
65#ifdef HUGETLB_TEST 136pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
66struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
67 int write)
68{ 137{
69 unsigned long start = address; 138 pgd_t *pgd;
70 int length = 1; 139 pud_t *pud;
71 int nr; 140 pmd_t *pmd;
72 struct page *page; 141#ifdef CONFIG_HUGETLB_SUPER_PAGES
73 struct vm_area_struct *vma; 142 pte_t *pte;
74 143#endif
75 vma = find_vma(mm, addr);
76 if (!vma || !is_vm_hugetlb_page(vma))
77 return ERR_PTR(-EINVAL);
78
79 pte = huge_pte_offset(mm, address);
80 144
81 /* hugetlb should be locked, and hence, prefaulted */ 145 /* Get the top-level page table entry. */
82 WARN_ON(!pte || pte_none(*pte)); 146 pgd = (pgd_t *)get_pte((pte_t *)mm->pgd, pgd_index(addr), 0);
147 if (!pgd_present(*pgd))
148 return NULL;
83 149
84 page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; 150 /* We don't have four levels. */
151 pud = pud_offset(pgd, addr);
152#ifndef __PAGETABLE_PUD_FOLDED
153# error support fourth page table level
154#endif
85 155
86 WARN_ON(!PageHead(page)); 156 /* Check for an L0 huge PTE, if we have three levels. */
157#ifndef __PAGETABLE_PMD_FOLDED
158 if (pud_huge(*pud))
159 return (pte_t *)pud;
87 160
88 return page; 161 pmd = (pmd_t *)get_pte((pte_t *)pud_page_vaddr(*pud),
89} 162 pmd_index(addr), 1);
90 163 if (!pmd_present(*pmd))
91int pmd_huge(pmd_t pmd) 164 return NULL;
92{ 165#else
93 return 0; 166 pmd = pmd_offset(pud, addr);
94} 167#endif
95 168
96int pud_huge(pud_t pud) 169 /* Check for an L1 huge PTE. */
97{ 170 if (pmd_huge(*pmd))
98 return 0; 171 return (pte_t *)pmd;
99} 172
173#ifdef CONFIG_HUGETLB_SUPER_PAGES
174 /* Check for an L2 huge PTE. */
175 pte = get_pte((pte_t *)pmd_page_vaddr(*pmd), pte_index(addr), 2);
176 if (!pte_present(*pte))
177 return NULL;
178 if (pte_super(*pte))
179 return pte;
180#endif
100 181
101struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
102 pmd_t *pmd, int write)
103{
104 return NULL; 182 return NULL;
105} 183}
106 184
107#else
108
109struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, 185struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
110 int write) 186 int write)
111{ 187{
@@ -149,8 +225,6 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
149 return 0; 225 return 0;
150} 226}
151 227
152#endif
153
154#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA 228#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
155static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, 229static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
156 unsigned long addr, unsigned long len, 230 unsigned long addr, unsigned long len,
@@ -322,21 +396,102 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
322 return hugetlb_get_unmapped_area_topdown(file, addr, len, 396 return hugetlb_get_unmapped_area_topdown(file, addr, len,
323 pgoff, flags); 397 pgoff, flags);
324} 398}
399#endif /* HAVE_ARCH_HUGETLB_UNMAPPED_AREA */
325 400
326static __init int setup_hugepagesz(char *opt) 401#ifdef CONFIG_HUGETLB_SUPER_PAGES
402static __init int __setup_hugepagesz(unsigned long ps)
327{ 403{
328 unsigned long ps = memparse(opt, &opt); 404 int log_ps = __builtin_ctzl(ps);
329 if (ps == PMD_SIZE) { 405 int level, base_shift;
330 hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT); 406
331 } else if (ps == PUD_SIZE) { 407 if ((1UL << log_ps) != ps || (log_ps & 1) != 0) {
332 hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT); 408 pr_warn("Not enabling %ld byte huge pages;"
409 " must be a power of four.\n", ps);
410 return -EINVAL;
411 }
412
413 if (ps > 64*1024*1024*1024UL) {
414 pr_warn("Not enabling %ld MB huge pages;"
415 " largest legal value is 64 GB .\n", ps >> 20);
416 return -EINVAL;
417 } else if (ps >= PUD_SIZE) {
418 static long hv_jpage_size;
419 if (hv_jpage_size == 0)
420 hv_jpage_size = hv_sysconf(HV_SYSCONF_PAGE_SIZE_JUMBO);
421 if (hv_jpage_size != PUD_SIZE) {
422 pr_warn("Not enabling >= %ld MB huge pages:"
423 " hypervisor reports size %ld\n",
424 PUD_SIZE >> 20, hv_jpage_size);
425 return -EINVAL;
426 }
427 level = 0;
428 base_shift = PUD_SHIFT;
429 } else if (ps >= PMD_SIZE) {
430 level = 1;
431 base_shift = PMD_SHIFT;
432 } else if (ps > PAGE_SIZE) {
433 level = 2;
434 base_shift = PAGE_SHIFT;
333 } else { 435 } else {
334 pr_err("hugepagesz: Unsupported page size %lu M\n", 436 pr_err("hugepagesz: huge page size %ld too small\n", ps);
335 ps >> 20); 437 return -EINVAL;
336 return 0;
337 } 438 }
338 return 1; 439
440 if (log_ps != base_shift) {
441 int shift_val = log_ps - base_shift;
442 if (huge_shift[level] != 0) {
443 int old_shift = base_shift + huge_shift[level];
444 pr_warn("Not enabling %ld MB huge pages;"
445 " already have size %ld MB.\n",
446 ps >> 20, (1UL << old_shift) >> 20);
447 return -EINVAL;
448 }
449 if (hv_set_pte_super_shift(level, shift_val) != 0) {
450 pr_warn("Not enabling %ld MB huge pages;"
451 " no hypervisor support.\n", ps >> 20);
452 return -EINVAL;
453 }
454 printk(KERN_DEBUG "Enabled %ld MB huge pages\n", ps >> 20);
455 huge_shift[level] = shift_val;
456 }
457
458 hugetlb_add_hstate(log_ps - PAGE_SHIFT);
459
460 return 0;
461}
462
463static bool saw_hugepagesz;
464
465static __init int setup_hugepagesz(char *opt)
466{
467 if (!saw_hugepagesz) {
468 saw_hugepagesz = true;
469 memset(huge_shift, 0, sizeof(huge_shift));
470 }
471 return __setup_hugepagesz(memparse(opt, NULL));
339} 472}
340__setup("hugepagesz=", setup_hugepagesz); 473__setup("hugepagesz=", setup_hugepagesz);
341 474
342#endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/ 475#ifdef ADDITIONAL_HUGE_SIZE
476/*
477 * Provide an additional huge page size if no "hugepagesz" args are given.
478 * In that case, all the cores have properly set up their hv super_shift
479 * already, but we need to notify the hugetlb code to enable the
480 * new huge page size from the Linux point of view.
481 */
482static __init int add_default_hugepagesz(void)
483{
484 if (!saw_hugepagesz) {
485 BUILD_BUG_ON(ADDITIONAL_HUGE_SIZE >= PMD_SIZE ||
486 ADDITIONAL_HUGE_SIZE <= PAGE_SIZE);
487 BUILD_BUG_ON((PAGE_SIZE << ADDITIONAL_HUGE_SHIFT) !=
488 ADDITIONAL_HUGE_SIZE);
489 BUILD_BUG_ON(ADDITIONAL_HUGE_SHIFT & 1);
490 hugetlb_add_hstate(ADDITIONAL_HUGE_SHIFT);
491 }
492 return 0;
493}
494arch_initcall(add_default_hugepagesz);
495#endif
496
497#endif /* CONFIG_HUGETLB_SUPER_PAGES */
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c
index 6a9d20ddc34f..630dd2ce2afe 100644
--- a/arch/tile/mm/init.c
+++ b/arch/tile/mm/init.c
@@ -82,7 +82,7 @@ static int num_l2_ptes[MAX_NUMNODES];
82 82
83static void init_prealloc_ptes(int node, int pages) 83static void init_prealloc_ptes(int node, int pages)
84{ 84{
85 BUG_ON(pages & (HV_L2_ENTRIES-1)); 85 BUG_ON(pages & (PTRS_PER_PTE - 1));
86 if (pages) { 86 if (pages) {
87 num_l2_ptes[node] = pages; 87 num_l2_ptes[node] = pages;
88 l2_ptes[node] = __alloc_bootmem(pages * sizeof(pte_t), 88 l2_ptes[node] = __alloc_bootmem(pages * sizeof(pte_t),
@@ -131,14 +131,9 @@ static void __init assign_pte(pmd_t *pmd, pte_t *page_table)
131 131
132#ifdef __tilegx__ 132#ifdef __tilegx__
133 133
134#if HV_L1_SIZE != HV_L2_SIZE
135# error Rework assumption that L1 and L2 page tables are same size.
136#endif
137
138/* Since pmd_t arrays and pte_t arrays are the same size, just use casts. */
139static inline pmd_t *alloc_pmd(void) 134static inline pmd_t *alloc_pmd(void)
140{ 135{
141 return (pmd_t *)alloc_pte(); 136 return __alloc_bootmem(L1_KERNEL_PGTABLE_SIZE, HV_PAGE_TABLE_ALIGN, 0);
142} 137}
143 138
144static inline void assign_pmd(pud_t *pud, pmd_t *pmd) 139static inline void assign_pmd(pud_t *pud, pmd_t *pmd)
@@ -444,6 +439,7 @@ static pgd_t pgtables[PTRS_PER_PGD]
444 */ 439 */
445static void __init kernel_physical_mapping_init(pgd_t *pgd_base) 440static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
446{ 441{
442 unsigned long long irqmask;
447 unsigned long address, pfn; 443 unsigned long address, pfn;
448 pmd_t *pmd; 444 pmd_t *pmd;
449 pte_t *pte; 445 pte_t *pte;
@@ -633,10 +629,13 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
633 * - install pgtables[] as the real page table 629 * - install pgtables[] as the real page table
634 * - flush the TLB so the new page table takes effect 630 * - flush the TLB so the new page table takes effect
635 */ 631 */
632 irqmask = interrupt_mask_save_mask();
633 interrupt_mask_set_mask(-1ULL);
636 rc = flush_and_install_context(__pa(pgtables), 634 rc = flush_and_install_context(__pa(pgtables),
637 init_pgprot((unsigned long)pgtables), 635 init_pgprot((unsigned long)pgtables),
638 __get_cpu_var(current_asid), 636 __get_cpu_var(current_asid),
639 cpumask_bits(my_cpu_mask)); 637 cpumask_bits(my_cpu_mask));
638 interrupt_mask_restore_mask(irqmask);
640 BUG_ON(rc != 0); 639 BUG_ON(rc != 0);
641 640
642 /* Copy the page table back to the normal swapper_pg_dir. */ 641 /* Copy the page table back to the normal swapper_pg_dir. */
@@ -699,6 +698,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
699#endif /* CONFIG_HIGHMEM */ 698#endif /* CONFIG_HIGHMEM */
700 699
701 700
701#ifndef CONFIG_64BIT
702static void __init init_free_pfn_range(unsigned long start, unsigned long end) 702static void __init init_free_pfn_range(unsigned long start, unsigned long end)
703{ 703{
704 unsigned long pfn; 704 unsigned long pfn;
@@ -771,6 +771,7 @@ static void __init set_non_bootmem_pages_init(void)
771 init_free_pfn_range(start, end); 771 init_free_pfn_range(start, end);
772 } 772 }
773} 773}
774#endif
774 775
775/* 776/*
776 * paging_init() sets up the page tables - note that all of lowmem is 777 * paging_init() sets up the page tables - note that all of lowmem is
@@ -807,7 +808,7 @@ void __init paging_init(void)
807 * changing init_mm once we get up and running, and there's no 808 * changing init_mm once we get up and running, and there's no
808 * need for e.g. vmalloc_sync_all(). 809 * need for e.g. vmalloc_sync_all().
809 */ 810 */
810 BUILD_BUG_ON(pgd_index(VMALLOC_START) != pgd_index(VMALLOC_END)); 811 BUILD_BUG_ON(pgd_index(VMALLOC_START) != pgd_index(VMALLOC_END - 1));
811 pud = pud_offset(pgd_base + pgd_index(VMALLOC_START), VMALLOC_START); 812 pud = pud_offset(pgd_base + pgd_index(VMALLOC_START), VMALLOC_START);
812 assign_pmd(pud, alloc_pmd()); 813 assign_pmd(pud, alloc_pmd());
813#endif 814#endif
@@ -859,8 +860,10 @@ void __init mem_init(void)
859 /* this will put all bootmem onto the freelists */ 860 /* this will put all bootmem onto the freelists */
860 totalram_pages += free_all_bootmem(); 861 totalram_pages += free_all_bootmem();
861 862
863#ifndef CONFIG_64BIT
862 /* count all remaining LOWMEM and give all HIGHMEM to page allocator */ 864 /* count all remaining LOWMEM and give all HIGHMEM to page allocator */
863 set_non_bootmem_pages_init(); 865 set_non_bootmem_pages_init();
866#endif
864 867
865 codesize = (unsigned long)&_etext - (unsigned long)&_text; 868 codesize = (unsigned long)&_etext - (unsigned long)&_text;
866 datasize = (unsigned long)&_end - (unsigned long)&_sdata; 869 datasize = (unsigned long)&_end - (unsigned long)&_sdata;
diff --git a/arch/tile/mm/migrate.h b/arch/tile/mm/migrate.h
index cd45a0837fa6..91683d97917e 100644
--- a/arch/tile/mm/migrate.h
+++ b/arch/tile/mm/migrate.h
@@ -24,6 +24,9 @@
24/* 24/*
25 * This function is used as a helper when setting up the initial 25 * This function is used as a helper when setting up the initial
26 * page table (swapper_pg_dir). 26 * page table (swapper_pg_dir).
27 *
28 * You must mask ALL interrupts prior to invoking this code, since
29 * you can't legally touch the stack during the cache flush.
27 */ 30 */
28extern int flush_and_install_context(HV_PhysAddr page_table, HV_PTE access, 31extern int flush_and_install_context(HV_PhysAddr page_table, HV_PTE access,
29 HV_ASID asid, 32 HV_ASID asid,
@@ -39,6 +42,9 @@ extern int flush_and_install_context(HV_PhysAddr page_table, HV_PTE access,
39 * 42 *
40 * Note that any non-NULL pointers must not point to the page that 43 * Note that any non-NULL pointers must not point to the page that
41 * is handled by the stack_pte itself. 44 * is handled by the stack_pte itself.
45 *
46 * You must mask ALL interrupts prior to invoking this code, since
47 * you can't legally touch the stack during the cache flush.
42 */ 48 */
43extern int homecache_migrate_stack_and_flush(pte_t stack_pte, unsigned long va, 49extern int homecache_migrate_stack_and_flush(pte_t stack_pte, unsigned long va,
44 size_t length, pte_t *stack_ptep, 50 size_t length, pte_t *stack_ptep,
diff --git a/arch/tile/mm/migrate_32.S b/arch/tile/mm/migrate_32.S
index ac01a7cdf77f..5305814bf187 100644
--- a/arch/tile/mm/migrate_32.S
+++ b/arch/tile/mm/migrate_32.S
@@ -40,8 +40,7 @@
40#define FRAME_R32 16 40#define FRAME_R32 16
41#define FRAME_R33 20 41#define FRAME_R33 20
42#define FRAME_R34 24 42#define FRAME_R34 24
43#define FRAME_R35 28 43#define FRAME_SIZE 28
44#define FRAME_SIZE 32
45 44
46 45
47 46
@@ -66,12 +65,11 @@
66#define r_my_cpumask r5 65#define r_my_cpumask r5
67 66
68/* Locals (callee-save); must not be more than FRAME_xxx above. */ 67/* Locals (callee-save); must not be more than FRAME_xxx above. */
69#define r_save_ics r30 68#define r_context_lo r30
70#define r_context_lo r31 69#define r_context_hi r31
71#define r_context_hi r32 70#define r_access_lo r32
72#define r_access_lo r33 71#define r_access_hi r33
73#define r_access_hi r34 72#define r_asid r34
74#define r_asid r35
75 73
76STD_ENTRY(flush_and_install_context) 74STD_ENTRY(flush_and_install_context)
77 /* 75 /*
@@ -104,11 +102,7 @@ STD_ENTRY(flush_and_install_context)
104 sw r_tmp, r33 102 sw r_tmp, r33
105 addi r_tmp, sp, FRAME_R34 103 addi r_tmp, sp, FRAME_R34
106 } 104 }
107 { 105 sw r_tmp, r34
108 sw r_tmp, r34
109 addi r_tmp, sp, FRAME_R35
110 }
111 sw r_tmp, r35
112 106
113 /* Move some arguments to callee-save registers. */ 107 /* Move some arguments to callee-save registers. */
114 { 108 {
@@ -121,13 +115,6 @@ STD_ENTRY(flush_and_install_context)
121 } 115 }
122 move r_asid, r_asid_in 116 move r_asid, r_asid_in
123 117
124 /* Disable interrupts, since we can't use our stack. */
125 {
126 mfspr r_save_ics, INTERRUPT_CRITICAL_SECTION
127 movei r_tmp, 1
128 }
129 mtspr INTERRUPT_CRITICAL_SECTION, r_tmp
130
131 /* First, flush our L2 cache. */ 118 /* First, flush our L2 cache. */
132 { 119 {
133 move r0, zero /* cache_pa */ 120 move r0, zero /* cache_pa */
@@ -163,7 +150,7 @@ STD_ENTRY(flush_and_install_context)
163 } 150 }
164 { 151 {
165 move r4, r_asid 152 move r4, r_asid
166 movei r5, HV_CTX_DIRECTIO 153 moveli r5, HV_CTX_DIRECTIO | CTX_PAGE_FLAG
167 } 154 }
168 jal hv_install_context 155 jal hv_install_context
169 bnz r0, .Ldone 156 bnz r0, .Ldone
@@ -175,9 +162,6 @@ STD_ENTRY(flush_and_install_context)
175 } 162 }
176 163
177.Ldone: 164.Ldone:
178 /* Reset interrupts back how they were before. */
179 mtspr INTERRUPT_CRITICAL_SECTION, r_save_ics
180
181 /* Restore the callee-saved registers and return. */ 165 /* Restore the callee-saved registers and return. */
182 addli lr, sp, FRAME_SIZE 166 addli lr, sp, FRAME_SIZE
183 { 167 {
@@ -202,10 +186,6 @@ STD_ENTRY(flush_and_install_context)
202 } 186 }
203 { 187 {
204 lw r34, r_tmp 188 lw r34, r_tmp
205 addli r_tmp, sp, FRAME_R35
206 }
207 {
208 lw r35, r_tmp
209 addi sp, sp, FRAME_SIZE 189 addi sp, sp, FRAME_SIZE
210 } 190 }
211 jrp lr 191 jrp lr
diff --git a/arch/tile/mm/migrate_64.S b/arch/tile/mm/migrate_64.S
index e76fea688beb..1d15b10833d1 100644
--- a/arch/tile/mm/migrate_64.S
+++ b/arch/tile/mm/migrate_64.S
@@ -38,8 +38,7 @@
38#define FRAME_R30 16 38#define FRAME_R30 16
39#define FRAME_R31 24 39#define FRAME_R31 24
40#define FRAME_R32 32 40#define FRAME_R32 32
41#define FRAME_R33 40 41#define FRAME_SIZE 40
42#define FRAME_SIZE 48
43 42
44 43
45 44
@@ -60,10 +59,9 @@
60#define r_my_cpumask r3 59#define r_my_cpumask r3
61 60
62/* Locals (callee-save); must not be more than FRAME_xxx above. */ 61/* Locals (callee-save); must not be more than FRAME_xxx above. */
63#define r_save_ics r30 62#define r_context r30
64#define r_context r31 63#define r_access r31
65#define r_access r32 64#define r_asid r32
66#define r_asid r33
67 65
68/* 66/*
69 * Caller-save locals and frame constants are the same as 67 * Caller-save locals and frame constants are the same as
@@ -93,11 +91,7 @@ STD_ENTRY(flush_and_install_context)
93 st r_tmp, r31 91 st r_tmp, r31
94 addi r_tmp, sp, FRAME_R32 92 addi r_tmp, sp, FRAME_R32
95 } 93 }
96 { 94 st r_tmp, r32
97 st r_tmp, r32
98 addi r_tmp, sp, FRAME_R33
99 }
100 st r_tmp, r33
101 95
102 /* Move some arguments to callee-save registers. */ 96 /* Move some arguments to callee-save registers. */
103 { 97 {
@@ -106,13 +100,6 @@ STD_ENTRY(flush_and_install_context)
106 } 100 }
107 move r_asid, r_asid_in 101 move r_asid, r_asid_in
108 102
109 /* Disable interrupts, since we can't use our stack. */
110 {
111 mfspr r_save_ics, INTERRUPT_CRITICAL_SECTION
112 movei r_tmp, 1
113 }
114 mtspr INTERRUPT_CRITICAL_SECTION, r_tmp
115
116 /* First, flush our L2 cache. */ 103 /* First, flush our L2 cache. */
117 { 104 {
118 move r0, zero /* cache_pa */ 105 move r0, zero /* cache_pa */
@@ -147,7 +134,7 @@ STD_ENTRY(flush_and_install_context)
147 } 134 }
148 { 135 {
149 move r2, r_asid 136 move r2, r_asid
150 movei r3, HV_CTX_DIRECTIO 137 moveli r3, HV_CTX_DIRECTIO | CTX_PAGE_FLAG
151 } 138 }
152 jal hv_install_context 139 jal hv_install_context
153 bnez r0, 1f 140 bnez r0, 1f
@@ -158,10 +145,7 @@ STD_ENTRY(flush_and_install_context)
158 jal hv_flush_all 145 jal hv_flush_all
159 } 146 }
160 147
1611: /* Reset interrupts back how they were before. */ 1481: /* Restore the callee-saved registers and return. */
162 mtspr INTERRUPT_CRITICAL_SECTION, r_save_ics
163
164 /* Restore the callee-saved registers and return. */
165 addli lr, sp, FRAME_SIZE 149 addli lr, sp, FRAME_SIZE
166 { 150 {
167 ld lr, lr 151 ld lr, lr
@@ -177,10 +161,6 @@ STD_ENTRY(flush_and_install_context)
177 } 161 }
178 { 162 {
179 ld r32, r_tmp 163 ld r32, r_tmp
180 addli r_tmp, sp, FRAME_R33
181 }
182 {
183 ld r33, r_tmp
184 addi sp, sp, FRAME_SIZE 164 addi sp, sp, FRAME_SIZE
185 } 165 }
186 jrp lr 166 jrp lr
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
index 2410aa899b3e..345edfed9fcd 100644
--- a/arch/tile/mm/pgtable.c
+++ b/arch/tile/mm/pgtable.c
@@ -132,15 +132,6 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
132 set_pte_pfn(address, phys >> PAGE_SHIFT, flags); 132 set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
133} 133}
134 134
135#if defined(CONFIG_HIGHPTE)
136pte_t *_pte_offset_map(pmd_t *dir, unsigned long address)
137{
138 pte_t *pte = kmap_atomic(pmd_page(*dir)) +
139 (pmd_ptfn(*dir) << HV_LOG2_PAGE_TABLE_ALIGN) & ~PAGE_MASK;
140 return &pte[pte_index(address)];
141}
142#endif
143
144/** 135/**
145 * shatter_huge_page() - ensure a given address is mapped by a small page. 136 * shatter_huge_page() - ensure a given address is mapped by a small page.
146 * 137 *
@@ -289,33 +280,26 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
289 280
290#define L2_USER_PGTABLE_PAGES (1 << L2_USER_PGTABLE_ORDER) 281#define L2_USER_PGTABLE_PAGES (1 << L2_USER_PGTABLE_ORDER)
291 282
292struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) 283struct page *pgtable_alloc_one(struct mm_struct *mm, unsigned long address,
284 int order)
293{ 285{
294 gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO; 286 gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO;
295 struct page *p; 287 struct page *p;
296#if L2_USER_PGTABLE_ORDER > 0
297 int i; 288 int i;
298#endif
299
300#ifdef CONFIG_HIGHPTE
301 flags |= __GFP_HIGHMEM;
302#endif
303 289
304 p = alloc_pages(flags, L2_USER_PGTABLE_ORDER); 290 p = alloc_pages(flags, L2_USER_PGTABLE_ORDER);
305 if (p == NULL) 291 if (p == NULL)
306 return NULL; 292 return NULL;
307 293
308#if L2_USER_PGTABLE_ORDER > 0
309 /* 294 /*
310 * Make every page have a page_count() of one, not just the first. 295 * Make every page have a page_count() of one, not just the first.
311 * We don't use __GFP_COMP since it doesn't look like it works 296 * We don't use __GFP_COMP since it doesn't look like it works
312 * correctly with tlb_remove_page(). 297 * correctly with tlb_remove_page().
313 */ 298 */
314 for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) { 299 for (i = 1; i < order; ++i) {
315 init_page_count(p+i); 300 init_page_count(p+i);
316 inc_zone_page_state(p+i, NR_PAGETABLE); 301 inc_zone_page_state(p+i, NR_PAGETABLE);
317 } 302 }
318#endif
319 303
320 pgtable_page_ctor(p); 304 pgtable_page_ctor(p);
321 return p; 305 return p;
@@ -326,28 +310,28 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
326 * process). We have to correct whatever pte_alloc_one() did before 310 * process). We have to correct whatever pte_alloc_one() did before
327 * returning the pages to the allocator. 311 * returning the pages to the allocator.
328 */ 312 */
329void pte_free(struct mm_struct *mm, struct page *p) 313void pgtable_free(struct mm_struct *mm, struct page *p, int order)
330{ 314{
331 int i; 315 int i;
332 316
333 pgtable_page_dtor(p); 317 pgtable_page_dtor(p);
334 __free_page(p); 318 __free_page(p);
335 319
336 for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) { 320 for (i = 1; i < order; ++i) {
337 __free_page(p+i); 321 __free_page(p+i);
338 dec_zone_page_state(p+i, NR_PAGETABLE); 322 dec_zone_page_state(p+i, NR_PAGETABLE);
339 } 323 }
340} 324}
341 325
342void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, 326void __pgtable_free_tlb(struct mmu_gather *tlb, struct page *pte,
343 unsigned long address) 327 unsigned long address, int order)
344{ 328{
345 int i; 329 int i;
346 330
347 pgtable_page_dtor(pte); 331 pgtable_page_dtor(pte);
348 tlb_remove_page(tlb, pte); 332 tlb_remove_page(tlb, pte);
349 333
350 for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) { 334 for (i = 1; i < order; ++i) {
351 tlb_remove_page(tlb, pte + i); 335 tlb_remove_page(tlb, pte + i);
352 dec_zone_page_state(pte + i, NR_PAGETABLE); 336 dec_zone_page_state(pte + i, NR_PAGETABLE);
353 } 337 }
@@ -490,7 +474,7 @@ void set_pte(pte_t *ptep, pte_t pte)
490/* Can this mm load a PTE with cached_priority set? */ 474/* Can this mm load a PTE with cached_priority set? */
491static inline int mm_is_priority_cached(struct mm_struct *mm) 475static inline int mm_is_priority_cached(struct mm_struct *mm)
492{ 476{
493 return mm->context.priority_cached; 477 return mm->context.priority_cached != 0;
494} 478}
495 479
496/* 480/*
@@ -500,8 +484,8 @@ static inline int mm_is_priority_cached(struct mm_struct *mm)
500void start_mm_caching(struct mm_struct *mm) 484void start_mm_caching(struct mm_struct *mm)
501{ 485{
502 if (!mm_is_priority_cached(mm)) { 486 if (!mm_is_priority_cached(mm)) {
503 mm->context.priority_cached = -1U; 487 mm->context.priority_cached = -1UL;
504 hv_set_caching(-1U); 488 hv_set_caching(-1UL);
505 } 489 }
506} 490}
507 491
@@ -516,7 +500,7 @@ void start_mm_caching(struct mm_struct *mm)
516 * Presumably we'll come back later and have more luck and clear 500 * Presumably we'll come back later and have more luck and clear
517 * the value then; for now we'll just keep the cache marked for priority. 501 * the value then; for now we'll just keep the cache marked for priority.
518 */ 502 */
519static unsigned int update_priority_cached(struct mm_struct *mm) 503static unsigned long update_priority_cached(struct mm_struct *mm)
520{ 504{
521 if (mm->context.priority_cached && down_write_trylock(&mm->mmap_sem)) { 505 if (mm->context.priority_cached && down_write_trylock(&mm->mmap_sem)) {
522 struct vm_area_struct *vm; 506 struct vm_area_struct *vm;