aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorKumar Gala <galak@kernel.crashing.org>2007-02-13 00:57:21 -0500
committerKumar Gala <galak@kernel.crashing.org>2007-02-13 00:57:21 -0500
commit54c66f6d781e03dc0b23956234963c4911e6d1c0 (patch)
tree40619a66ae6d8703a57bf681d087ffeabbffd346 /arch/powerpc/kernel
parent8ce0a7df6e6117d8814e976d4b7ce6a6b2c9cf93 (diff)
parent17e0e27020d028a790d97699aff85a43af5be472 (diff)
Merge branch 'master' into 85xx
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/cputable.c2
-rw-r--r--arch/powerpc/kernel/head_44x.S2
-rw-r--r--arch/powerpc/kernel/legacy_serial.c2
-rw-r--r--arch/powerpc/kernel/lparcfg.c2
-rw-r--r--arch/powerpc/kernel/nvram_64.c2
-rw-r--r--arch/powerpc/kernel/proc_ppc64.c3
-rw-r--r--arch/powerpc/kernel/prom.c2
-rw-r--r--arch/powerpc/kernel/prom_init.c81
-rw-r--r--arch/powerpc/kernel/rtas-proc.c14
-rw-r--r--arch/powerpc/kernel/rtas_flash.c9
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c67
-rw-r--r--arch/powerpc/kernel/udbg.c2
-rw-r--r--arch/powerpc/kernel/vdso.c124
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S4
14 files changed, 144 insertions, 172 deletions
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index dd17dffbf058..7ec4ac77c0fa 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -44,7 +44,7 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
44extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); 44extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
45extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec); 45extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
46extern void __setup_cpu_pa6t(unsigned long offset, struct cpu_spec* spec); 46extern void __setup_cpu_pa6t(unsigned long offset, struct cpu_spec* spec);
47extern void __restore_cpu_pa6t(unsigned long offset, struct cpu_spec* spec); 47extern void __restore_cpu_pa6t(void);
48extern void __restore_cpu_ppc970(void); 48extern void __restore_cpu_ppc970(void);
49#endif /* CONFIG_PPC64 */ 49#endif /* CONFIG_PPC64 */
50 50
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index accb39d49911..a15d4b8cce48 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -32,8 +32,6 @@
32#include <asm/page.h> 32#include <asm/page.h>
33#include <asm/mmu.h> 33#include <asm/mmu.h>
34#include <asm/pgtable.h> 34#include <asm/pgtable.h>
35#include <asm/ibm4xx.h>
36#include <asm/ibm44x.h>
37#include <asm/cputable.h> 35#include <asm/cputable.h>
38#include <asm/thread_info.h> 36#include <asm/thread_info.h>
39#include <asm/ppc_asm.h> 37#include <asm/ppc_asm.h>
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 5e6ddfa474c0..89f46f377922 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -498,7 +498,7 @@ static int __init check_legacy_serial_console(void)
498 DBG(" -> check_legacy_serial_console()\n"); 498 DBG(" -> check_legacy_serial_console()\n");
499 499
500 /* The user has requested a console so this is already set up. */ 500 /* The user has requested a console so this is already set up. */
501 if (strstr(saved_command_line, "console=")) { 501 if (strstr(boot_command_line, "console=")) {
502 DBG(" console was specified !\n"); 502 DBG(" console was specified !\n");
503 return -EBUSY; 503 return -EBUSY;
504 } 504 }
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 0de5a08cf9b0..89486b631284 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -571,7 +571,7 @@ static int lparcfg_open(struct inode *inode, struct file *file)
571 return single_open(file, lparcfg_data, NULL); 571 return single_open(file, lparcfg_data, NULL);
572} 572}
573 573
574struct file_operations lparcfg_fops = { 574const struct file_operations lparcfg_fops = {
575 .owner = THIS_MODULE, 575 .owner = THIS_MODULE,
576 .read = seq_read, 576 .read = seq_read,
577 .write = lparcfg_write, 577 .write = lparcfg_write,
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 869cebbba967..f9676f52c6d8 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -179,7 +179,7 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file,
179 } 179 }
180} 180}
181 181
182struct file_operations nvram_fops = { 182const struct file_operations nvram_fops = {
183 .owner = THIS_MODULE, 183 .owner = THIS_MODULE,
184 .llseek = dev_nvram_llseek, 184 .llseek = dev_nvram_llseek,
185 .read = dev_nvram_read, 185 .read = dev_nvram_read,
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index dd7001cacf75..f78dfce1b771 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -33,7 +33,7 @@ static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes
33 loff_t *ppos); 33 loff_t *ppos);
34static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); 34static int page_map_mmap( struct file *file, struct vm_area_struct *vma );
35 35
36static struct file_operations page_map_fops = { 36static const struct file_operations page_map_fops = {
37 .llseek = page_map_seek, 37 .llseek = page_map_seek,
38 .read = page_map_read, 38 .read = page_map_read,
39 .mmap = page_map_mmap 39 .mmap = page_map_mmap
@@ -71,7 +71,6 @@ static int __init proc_ppc64_init(void)
71 pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL); 71 pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL);
72 if (!pde) 72 if (!pde)
73 return 1; 73 return 1;
74 pde->nlink = 1;
75 pde->data = vdso_data; 74 pde->data = vdso_data;
76 pde->size = PAGE_SIZE; 75 pde->size = PAGE_SIZE;
77 pde->proc_fops = &page_map_fops; 76 pde->proc_fops = &page_map_fops;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 3be52d693eca..3e86e6e0f778 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -991,7 +991,7 @@ void __init early_init_devtree(void *params)
991 of_scan_flat_dt(early_init_dt_scan_memory, NULL); 991 of_scan_flat_dt(early_init_dt_scan_memory, NULL);
992 992
993 /* Save command line for /proc/cmdline and then parse parameters */ 993 /* Save command line for /proc/cmdline and then parse parameters */
994 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); 994 strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
995 parse_early_param(); 995 parse_early_param();
996 996
997 /* Reserve LMB regions used by kernel, initrd, dt, etc... */ 997 /* Reserve LMB regions used by kernel, initrd, dt, etc... */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 520ef42f642e..4fb5938ce6d3 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2117,11 +2117,92 @@ static void __init fixup_device_tree_pmac(void)
2117#define fixup_device_tree_pmac() 2117#define fixup_device_tree_pmac()
2118#endif 2118#endif
2119 2119
2120#ifdef CONFIG_PPC_EFIKA
2121/* The current fw of the Efika has a device tree needs quite a few
2122 * fixups to be compliant with the mpc52xx bindings. It's currently
2123 * unknown if it will ever be compliant (come on bPlan ...) so we do fixups.
2124 * NOTE that we (barely) tolerate it because the EFIKA was out before
2125 * the bindings were finished, for any new boards -> RTFM ! */
2126
2127struct subst_entry {
2128 char *path;
2129 char *property;
2130 void *value;
2131 int value_len;
2132};
2133
2134static void __init fixup_device_tree_efika(void)
2135{
2136 /* Substitution table */
2137 #define prop_cstr(x) x, sizeof(x)
2138 int prop_sound_irq[3] = { 2, 2, 0 };
2139 int prop_bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2140 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2141 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2142 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2143 struct subst_entry efika_subst_table[] = {
2144 { "/", "device_type", prop_cstr("efika") },
2145 { "/builtin", "compatible", prop_cstr("soc") },
2146 { "/builtin/ata", "compatible", prop_cstr("mpc5200b-ata\0mpc5200-ata"), },
2147 { "/builtin/bestcomm", "compatible", prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") },
2148 { "/builtin/bestcomm", "interrupts", prop_bcomm_irq, sizeof(prop_bcomm_irq) },
2149 { "/builtin/ethernet", "compatible", prop_cstr("mpc5200b-fec\0mpc5200-fec") },
2150 { "/builtin/pic", "compatible", prop_cstr("mpc5200b-pic\0mpc5200-pic") },
2151 { "/builtin/serial", "compatible", prop_cstr("mpc5200b-psc-uart\0mpc5200-psc-uart") },
2152 { "/builtin/sound", "compatible", prop_cstr("mpc5200b-psc-ac97\0mpc5200-psc-ac97") },
2153 { "/builtin/sound", "interrupts", prop_sound_irq, sizeof(prop_sound_irq) },
2154 { "/builtin/sram", "compatible", prop_cstr("mpc5200b-sram\0mpc5200-sram") },
2155 { "/builtin/sram", "device_type", prop_cstr("sram") },
2156 {}
2157 };
2158 #undef prop_cstr
2159
2160 /* Vars */
2161 u32 node;
2162 char prop[64];
2163 int rv, i;
2164
2165 /* Check if we're really running on a EFIKA */
2166 node = call_prom("finddevice", 1, 1, ADDR("/"));
2167 if (!PHANDLE_VALID(node))
2168 return;
2169
2170 rv = prom_getprop(node, "model", prop, sizeof(prop));
2171 if (rv == PROM_ERROR)
2172 return;
2173 if (strcmp(prop, "EFIKA5K2"))
2174 return;
2175
2176 prom_printf("Applying EFIKA device tree fixups\n");
2177
2178 /* Process substitution table */
2179 for (i=0; efika_subst_table[i].path; i++) {
2180 struct subst_entry *se = &efika_subst_table[i];
2181
2182 node = call_prom("finddevice", 1, 1, ADDR(se->path));
2183 if (!PHANDLE_VALID(node)) {
2184 prom_printf("fixup_device_tree_efika: ",
2185 "skipped entry %x - not found\n", i);
2186 continue;
2187 }
2188
2189 rv = prom_setprop(node, se->path, se->property,
2190 se->value, se->value_len );
2191 if (rv == PROM_ERROR)
2192 prom_printf("fixup_device_tree_efika: ",
2193 "skipped entry %x - setprop error\n", i);
2194 }
2195}
2196#else
2197#define fixup_device_tree_efika()
2198#endif
2199
2120static void __init fixup_device_tree(void) 2200static void __init fixup_device_tree(void)
2121{ 2201{
2122 fixup_device_tree_maple(); 2202 fixup_device_tree_maple();
2123 fixup_device_tree_chrp(); 2203 fixup_device_tree_chrp();
2124 fixup_device_tree_pmac(); 2204 fixup_device_tree_pmac();
2205 fixup_device_tree_efika();
2125} 2206}
2126 2207
2127static void __init prom_find_boot_cpu(void) 2208static void __init prom_find_boot_cpu(void)
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 2fe82abf1c52..6cbf2ae5d7aa 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -160,7 +160,7 @@ static int sensors_open(struct inode *inode, struct file *file)
160 return single_open(file, ppc_rtas_sensors_show, NULL); 160 return single_open(file, ppc_rtas_sensors_show, NULL);
161} 161}
162 162
163struct file_operations ppc_rtas_sensors_operations = { 163const struct file_operations ppc_rtas_sensors_operations = {
164 .open = sensors_open, 164 .open = sensors_open,
165 .read = seq_read, 165 .read = seq_read,
166 .llseek = seq_lseek, 166 .llseek = seq_lseek,
@@ -172,7 +172,7 @@ static int poweron_open(struct inode *inode, struct file *file)
172 return single_open(file, ppc_rtas_poweron_show, NULL); 172 return single_open(file, ppc_rtas_poweron_show, NULL);
173} 173}
174 174
175struct file_operations ppc_rtas_poweron_operations = { 175const struct file_operations ppc_rtas_poweron_operations = {
176 .open = poweron_open, 176 .open = poweron_open,
177 .read = seq_read, 177 .read = seq_read,
178 .llseek = seq_lseek, 178 .llseek = seq_lseek,
@@ -185,7 +185,7 @@ static int progress_open(struct inode *inode, struct file *file)
185 return single_open(file, ppc_rtas_progress_show, NULL); 185 return single_open(file, ppc_rtas_progress_show, NULL);
186} 186}
187 187
188struct file_operations ppc_rtas_progress_operations = { 188const struct file_operations ppc_rtas_progress_operations = {
189 .open = progress_open, 189 .open = progress_open,
190 .read = seq_read, 190 .read = seq_read,
191 .llseek = seq_lseek, 191 .llseek = seq_lseek,
@@ -198,7 +198,7 @@ static int clock_open(struct inode *inode, struct file *file)
198 return single_open(file, ppc_rtas_clock_show, NULL); 198 return single_open(file, ppc_rtas_clock_show, NULL);
199} 199}
200 200
201struct file_operations ppc_rtas_clock_operations = { 201const struct file_operations ppc_rtas_clock_operations = {
202 .open = clock_open, 202 .open = clock_open,
203 .read = seq_read, 203 .read = seq_read,
204 .llseek = seq_lseek, 204 .llseek = seq_lseek,
@@ -211,7 +211,7 @@ static int tone_freq_open(struct inode *inode, struct file *file)
211 return single_open(file, ppc_rtas_tone_freq_show, NULL); 211 return single_open(file, ppc_rtas_tone_freq_show, NULL);
212} 212}
213 213
214struct file_operations ppc_rtas_tone_freq_operations = { 214const struct file_operations ppc_rtas_tone_freq_operations = {
215 .open = tone_freq_open, 215 .open = tone_freq_open,
216 .read = seq_read, 216 .read = seq_read,
217 .llseek = seq_lseek, 217 .llseek = seq_lseek,
@@ -224,7 +224,7 @@ static int tone_volume_open(struct inode *inode, struct file *file)
224 return single_open(file, ppc_rtas_tone_volume_show, NULL); 224 return single_open(file, ppc_rtas_tone_volume_show, NULL);
225} 225}
226 226
227struct file_operations ppc_rtas_tone_volume_operations = { 227const struct file_operations ppc_rtas_tone_volume_operations = {
228 .open = tone_volume_open, 228 .open = tone_volume_open,
229 .read = seq_read, 229 .read = seq_read,
230 .llseek = seq_lseek, 230 .llseek = seq_lseek,
@@ -237,7 +237,7 @@ static int rmo_buf_open(struct inode *inode, struct file *file)
237 return single_open(file, ppc_rtas_rmo_buf_show, NULL); 237 return single_open(file, ppc_rtas_rmo_buf_show, NULL);
238} 238}
239 239
240struct file_operations ppc_rtas_rmo_buf_ops = { 240const struct file_operations ppc_rtas_rmo_buf_ops = {
241 .open = rmo_buf_open, 241 .open = rmo_buf_open,
242 .read = seq_read, 242 .read = seq_read,
243 .llseek = seq_lseek, 243 .llseek = seq_lseek,
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 0c4fcd34bfe5..f72118c0844f 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -702,13 +702,12 @@ static int initialize_flash_pde_data(const char *rtas_call_name,
702} 702}
703 703
704static struct proc_dir_entry *create_flash_pde(const char *filename, 704static struct proc_dir_entry *create_flash_pde(const char *filename,
705 struct file_operations *fops) 705 const struct file_operations *fops)
706{ 706{
707 struct proc_dir_entry *ent = NULL; 707 struct proc_dir_entry *ent = NULL;
708 708
709 ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL); 709 ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL);
710 if (ent != NULL) { 710 if (ent != NULL) {
711 ent->nlink = 1;
712 ent->proc_fops = fops; 711 ent->proc_fops = fops;
713 ent->owner = THIS_MODULE; 712 ent->owner = THIS_MODULE;
714 } 713 }
@@ -716,21 +715,21 @@ static struct proc_dir_entry *create_flash_pde(const char *filename,
716 return ent; 715 return ent;
717} 716}
718 717
719static struct file_operations rtas_flash_operations = { 718static const struct file_operations rtas_flash_operations = {
720 .read = rtas_flash_read, 719 .read = rtas_flash_read,
721 .write = rtas_flash_write, 720 .write = rtas_flash_write,
722 .open = rtas_excl_open, 721 .open = rtas_excl_open,
723 .release = rtas_flash_release, 722 .release = rtas_flash_release,
724}; 723};
725 724
726static struct file_operations manage_flash_operations = { 725static const struct file_operations manage_flash_operations = {
727 .read = manage_flash_read, 726 .read = manage_flash_read,
728 .write = manage_flash_write, 727 .write = manage_flash_write,
729 .open = rtas_excl_open, 728 .open = rtas_excl_open,
730 .release = rtas_excl_release, 729 .release = rtas_excl_release,
731}; 730};
732 731
733static struct file_operations validate_flash_operations = { 732static const struct file_operations validate_flash_operations = {
734 .read = validate_flash_read, 733 .read = validate_flash_read,
735 .write = validate_flash_write, 734 .write = validate_flash_write,
736 .open = rtas_excl_open, 735 .open = rtas_excl_open,
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 03a2a2f30d66..673e8d9df7f5 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -198,73 +198,6 @@ static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
198 __put_user(i->tv_usec, &o->tv_usec))); 198 __put_user(i->tv_usec, &o->tv_usec)));
199} 199}
200 200
201struct sysinfo32 {
202 s32 uptime;
203 u32 loads[3];
204 u32 totalram;
205 u32 freeram;
206 u32 sharedram;
207 u32 bufferram;
208 u32 totalswap;
209 u32 freeswap;
210 unsigned short procs;
211 unsigned short pad;
212 u32 totalhigh;
213 u32 freehigh;
214 u32 mem_unit;
215 char _f[20-2*sizeof(int)-sizeof(int)];
216};
217
218asmlinkage long compat_sys_sysinfo(struct sysinfo32 __user *info)
219{
220 struct sysinfo s;
221 int ret, err;
222 int bitcount=0;
223 mm_segment_t old_fs = get_fs ();
224
225 /* The __user cast is valid due to set_fs() */
226 set_fs (KERNEL_DS);
227 ret = sys_sysinfo((struct sysinfo __user *)&s);
228 set_fs (old_fs);
229
230 /* Check to see if any memory value is too large for 32-bit and
231 * scale down if needed.
232 */
233 if ((s.totalram >> 32) || (s.totalswap >> 32)) {
234 while (s.mem_unit < PAGE_SIZE) {
235 s.mem_unit <<= 1;
236 bitcount++;
237 }
238 s.totalram >>=bitcount;
239 s.freeram >>= bitcount;
240 s.sharedram >>= bitcount;
241 s.bufferram >>= bitcount;
242 s.totalswap >>= bitcount;
243 s.freeswap >>= bitcount;
244 s.totalhigh >>= bitcount;
245 s.freehigh >>= bitcount;
246 }
247
248 err = put_user (s.uptime, &info->uptime);
249 err |= __put_user (s.loads[0], &info->loads[0]);
250 err |= __put_user (s.loads[1], &info->loads[1]);
251 err |= __put_user (s.loads[2], &info->loads[2]);
252 err |= __put_user (s.totalram, &info->totalram);
253 err |= __put_user (s.freeram, &info->freeram);
254 err |= __put_user (s.sharedram, &info->sharedram);
255 err |= __put_user (s.bufferram, &info->bufferram);
256 err |= __put_user (s.totalswap, &info->totalswap);
257 err |= __put_user (s.freeswap, &info->freeswap);
258 err |= __put_user (s.procs, &info->procs);
259 err |= __put_user (s.totalhigh, &info->totalhigh);
260 err |= __put_user (s.freehigh, &info->freehigh);
261 err |= __put_user (s.mem_unit, &info->mem_unit);
262 if (err)
263 return -EFAULT;
264
265 return ret;
266}
267
268 201
269 202
270 203
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 8f5afdbad0d5..194a93eeb3e7 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -150,7 +150,7 @@ void __init disable_early_printk(void)
150{ 150{
151 if (!early_console_initialized) 151 if (!early_console_initialized)
152 return; 152 return;
153 if (strstr(saved_command_line, "udbg-immortal")) { 153 if (strstr(boot_command_line, "udbg-immortal")) {
154 printk(KERN_INFO "early console immortal !\n"); 154 printk(KERN_INFO "early console immortal !\n");
155 return; 155 return;
156 } 156 }
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index ae0ede19879d..e46c31b36641 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -51,17 +51,21 @@
51 51
52extern char vdso32_start, vdso32_end; 52extern char vdso32_start, vdso32_end;
53static void *vdso32_kbase = &vdso32_start; 53static void *vdso32_kbase = &vdso32_start;
54unsigned int vdso32_pages; 54static unsigned int vdso32_pages;
55static struct page **vdso32_pagelist;
55unsigned long vdso32_sigtramp; 56unsigned long vdso32_sigtramp;
56unsigned long vdso32_rt_sigtramp; 57unsigned long vdso32_rt_sigtramp;
57 58
58#ifdef CONFIG_PPC64 59#ifdef CONFIG_PPC64
59extern char vdso64_start, vdso64_end; 60extern char vdso64_start, vdso64_end;
60static void *vdso64_kbase = &vdso64_start; 61static void *vdso64_kbase = &vdso64_start;
61unsigned int vdso64_pages; 62static unsigned int vdso64_pages;
63static struct page **vdso64_pagelist;
62unsigned long vdso64_rt_sigtramp; 64unsigned long vdso64_rt_sigtramp;
63#endif /* CONFIG_PPC64 */ 65#endif /* CONFIG_PPC64 */
64 66
67static int vdso_ready;
68
65/* 69/*
66 * The vdso data page (aka. systemcfg for old ppc64 fans) is here. 70 * The vdso data page (aka. systemcfg for old ppc64 fans) is here.
67 * Once the early boot kernel code no longer needs to muck around 71 * Once the early boot kernel code no longer needs to muck around
@@ -165,55 +169,6 @@ static void dump_vdso_pages(struct vm_area_struct * vma)
165#endif /* DEBUG */ 169#endif /* DEBUG */
166 170
167/* 171/*
168 * Keep a dummy vma_close for now, it will prevent VMA merging.
169 */
170static void vdso_vma_close(struct vm_area_struct * vma)
171{
172}
173
174/*
175 * Our nopage() function, maps in the actual vDSO kernel pages, they will
176 * be mapped read-only by do_no_page(), and eventually COW'ed, either
177 * right away for an initial write access, or by do_wp_page().
178 */
179static struct page * vdso_vma_nopage(struct vm_area_struct * vma,
180 unsigned long address, int *type)
181{
182 unsigned long offset = address - vma->vm_start;
183 struct page *pg;
184#ifdef CONFIG_PPC64
185 void *vbase = (vma->vm_mm->task_size > TASK_SIZE_USER32) ?
186 vdso64_kbase : vdso32_kbase;
187#else
188 void *vbase = vdso32_kbase;
189#endif
190
191 DBG("vdso_vma_nopage(current: %s, address: %016lx, off: %lx)\n",
192 current->comm, address, offset);
193
194 if (address < vma->vm_start || address > vma->vm_end)
195 return NOPAGE_SIGBUS;
196
197 /*
198 * Last page is systemcfg.
199 */
200 if ((vma->vm_end - address) <= PAGE_SIZE)
201 pg = virt_to_page(vdso_data);
202 else
203 pg = virt_to_page(vbase + offset);
204
205 get_page(pg);
206 DBG(" ->page count: %d\n", page_count(pg));
207
208 return pg;
209}
210
211static struct vm_operations_struct vdso_vmops = {
212 .close = vdso_vma_close,
213 .nopage = vdso_vma_nopage,
214};
215
216/*
217 * This is called from binfmt_elf, we create the special vma for the 172 * This is called from binfmt_elf, we create the special vma for the
218 * vDSO and insert it into the mm struct tree 173 * vDSO and insert it into the mm struct tree
219 */ 174 */
@@ -221,20 +176,26 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
221 int executable_stack) 176 int executable_stack)
222{ 177{
223 struct mm_struct *mm = current->mm; 178 struct mm_struct *mm = current->mm;
224 struct vm_area_struct *vma; 179 struct page **vdso_pagelist;
225 unsigned long vdso_pages; 180 unsigned long vdso_pages;
226 unsigned long vdso_base; 181 unsigned long vdso_base;
227 int rc; 182 int rc;
228 183
184 if (!vdso_ready)
185 return 0;
186
229#ifdef CONFIG_PPC64 187#ifdef CONFIG_PPC64
230 if (test_thread_flag(TIF_32BIT)) { 188 if (test_thread_flag(TIF_32BIT)) {
189 vdso_pagelist = vdso32_pagelist;
231 vdso_pages = vdso32_pages; 190 vdso_pages = vdso32_pages;
232 vdso_base = VDSO32_MBASE; 191 vdso_base = VDSO32_MBASE;
233 } else { 192 } else {
193 vdso_pagelist = vdso64_pagelist;
234 vdso_pages = vdso64_pages; 194 vdso_pages = vdso64_pages;
235 vdso_base = VDSO64_MBASE; 195 vdso_base = VDSO64_MBASE;
236 } 196 }
237#else 197#else
198 vdso_pagelist = vdso32_pagelist;
238 vdso_pages = vdso32_pages; 199 vdso_pages = vdso32_pages;
239 vdso_base = VDSO32_MBASE; 200 vdso_base = VDSO32_MBASE;
240#endif 201#endif
@@ -262,17 +223,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
262 goto fail_mmapsem; 223 goto fail_mmapsem;
263 } 224 }
264 225
265
266 /* Allocate a VMA structure and fill it up */
267 vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
268 if (vma == NULL) {
269 rc = -ENOMEM;
270 goto fail_mmapsem;
271 }
272 vma->vm_mm = mm;
273 vma->vm_start = vdso_base;
274 vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT);
275
276 /* 226 /*
277 * our vma flags don't have VM_WRITE so by default, the process isn't 227 * our vma flags don't have VM_WRITE so by default, the process isn't
278 * allowed to write those pages. 228 * allowed to write those pages.
@@ -282,32 +232,26 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
282 * and your nice userland gettimeofday will be totally dead. 232 * and your nice userland gettimeofday will be totally dead.
283 * It's fine to use that for setting breakpoints in the vDSO code 233 * It's fine to use that for setting breakpoints in the vDSO code
284 * pages though 234 * pages though
285 */ 235 *
286 vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
287 /*
288 * Make sure the vDSO gets into every core dump. 236 * Make sure the vDSO gets into every core dump.
289 * Dumping its contents makes post-mortem fully interpretable later 237 * Dumping its contents makes post-mortem fully interpretable later
290 * without matching up the same kernel and hardware config to see 238 * without matching up the same kernel and hardware config to see
291 * what PC values meant. 239 * what PC values meant.
292 */ 240 */
293 vma->vm_flags |= VM_ALWAYSDUMP; 241 rc = install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT,
294 vma->vm_flags |= mm->def_flags; 242 VM_READ|VM_EXEC|
295 vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; 243 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
296 vma->vm_ops = &vdso_vmops; 244 VM_ALWAYSDUMP,
297 245 vdso_pagelist);
298 /* Insert new VMA */
299 rc = insert_vm_struct(mm, vma);
300 if (rc) 246 if (rc)
301 goto fail_vma; 247 goto fail_mmapsem;
302 248
303 /* Put vDSO base into mm struct and account for memory usage */ 249 /* Put vDSO base into mm struct */
304 current->mm->context.vdso_base = vdso_base; 250 current->mm->context.vdso_base = vdso_base;
305 mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; 251
306 up_write(&mm->mmap_sem); 252 up_write(&mm->mmap_sem);
307 return 0; 253 return 0;
308 254
309 fail_vma:
310 kmem_cache_free(vm_area_cachep, vma);
311 fail_mmapsem: 255 fail_mmapsem:
312 up_write(&mm->mmap_sem); 256 up_write(&mm->mmap_sem);
313 return rc; 257 return rc;
@@ -719,7 +663,7 @@ static void __init vdso_setup_syscall_map(void)
719} 663}
720 664
721 665
722void __init vdso_init(void) 666static int __init vdso_init(void)
723{ 667{
724 int i; 668 int i;
725 669
@@ -774,26 +718,44 @@ void __init vdso_init(void)
774#ifdef CONFIG_PPC64 718#ifdef CONFIG_PPC64
775 vdso64_pages = 0; 719 vdso64_pages = 0;
776#endif 720#endif
777 return; 721 return 0;
778 } 722 }
779 723
780 /* Make sure pages are in the correct state */ 724 /* Make sure pages are in the correct state */
725 vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 2),
726 GFP_KERNEL);
727 BUG_ON(vdso32_pagelist == NULL);
781 for (i = 0; i < vdso32_pages; i++) { 728 for (i = 0; i < vdso32_pages; i++) {
782 struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); 729 struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
783 ClearPageReserved(pg); 730 ClearPageReserved(pg);
784 get_page(pg); 731 get_page(pg);
785 732 vdso32_pagelist[i] = pg;
786 } 733 }
734 vdso32_pagelist[i++] = virt_to_page(vdso_data);
735 vdso32_pagelist[i] = NULL;
736
787#ifdef CONFIG_PPC64 737#ifdef CONFIG_PPC64
738 vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 2),
739 GFP_KERNEL);
740 BUG_ON(vdso64_pagelist == NULL);
788 for (i = 0; i < vdso64_pages; i++) { 741 for (i = 0; i < vdso64_pages; i++) {
789 struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); 742 struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
790 ClearPageReserved(pg); 743 ClearPageReserved(pg);
791 get_page(pg); 744 get_page(pg);
745 vdso64_pagelist[i] = pg;
792 } 746 }
747 vdso64_pagelist[i++] = virt_to_page(vdso_data);
748 vdso64_pagelist[i] = NULL;
793#endif /* CONFIG_PPC64 */ 749#endif /* CONFIG_PPC64 */
794 750
795 get_page(virt_to_page(vdso_data)); 751 get_page(virt_to_page(vdso_data));
752
753 smp_wmb();
754 vdso_ready = 1;
755
756 return 0;
796} 757}
758arch_initcall(vdso_init);
797 759
798int in_gate_area_no_task(unsigned long addr) 760int in_gate_area_no_task(unsigned long addr)
799{ 761{
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 04b8e71bf5b0..7eefeb4a30e7 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -131,14 +131,14 @@ SECTIONS
131 __stop___fw_ftr_fixup = .; 131 __stop___fw_ftr_fixup = .;
132 } 132 }
133#endif 133#endif
134 134#ifdef CONFIG_BLK_DEV_INITRD
135 . = ALIGN(PAGE_SIZE); 135 . = ALIGN(PAGE_SIZE);
136 .init.ramfs : { 136 .init.ramfs : {
137 __initramfs_start = .; 137 __initramfs_start = .;
138 *(.init.ramfs) 138 *(.init.ramfs)
139 __initramfs_end = .; 139 __initramfs_end = .;
140 } 140 }
141 141#endif
142#ifdef CONFIG_PPC32 142#ifdef CONFIG_PPC32
143 . = ALIGN(32); 143 . = ALIGN(32);
144#else 144#else