aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-26 16:29:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-26 16:29:41 -0400
commit539a5fe22620a1665cce504167953a71a43232ad (patch)
tree3ca071a19e8ef86beffb0b754e794f3d277a1cf8 /arch/x86
parent0124cecfc85a6664b1ad5f1d28cf0ab8df66fc42 (diff)
parentfb884381273669fad034538e6cb186678407cf22 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86-bigbox-bootparam
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86-bigbox-bootparam: x86, boot: Document for linked list of struct setup_data x86, boot: export linked list of struct setup_data via debugfs x86, boot: add linked list of struct setup_data x86, boot: add free_early to early reservation machanism
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/boot/header.S6
-rw-r--r--arch/x86/kernel/e820_64.c22
-rw-r--r--arch/x86/kernel/head64.c20
-rw-r--r--arch/x86/kernel/kdebugfs.c163
-rw-r--r--arch/x86/kernel/setup_64.c24
5 files changed, 229 insertions, 6 deletions
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 6d2df8d61c54..af86e431acfa 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -120,7 +120,7 @@ _start:
120 # Part 2 of the header, from the old setup.S 120 # Part 2 of the header, from the old setup.S
121 121
122 .ascii "HdrS" # header signature 122 .ascii "HdrS" # header signature
123 .word 0x0208 # header version number (>= 0x0105) 123 .word 0x0209 # header version number (>= 0x0105)
124 # or else old loadlin-1.5 will fail) 124 # or else old loadlin-1.5 will fail)
125 .globl realmode_swtch 125 .globl realmode_swtch
126realmode_swtch: .word 0, 0 # default_switch, SETUPSEG 126realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
@@ -227,6 +227,10 @@ hardware_subarch_data: .quad 0
227payload_offset: .long input_data 227payload_offset: .long input_data
228payload_length: .long input_data_end-input_data 228payload_length: .long input_data_end-input_data
229 229
230setup_data: .quad 0 # 64-bit physical pointer to
231 # single linked list of
232 # struct setup_data
233
230# End of setup header ##################################################### 234# End of setup header #####################################################
231 235
232 .section ".inittext", "ax" 236 .section ".inittext", "ax"
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
index cbd42e51cb08..79f0d52fa99a 100644
--- a/arch/x86/kernel/e820_64.c
+++ b/arch/x86/kernel/e820_64.c
@@ -84,6 +84,28 @@ void __init reserve_early(unsigned long start, unsigned long end, char *name)
84 strncpy(r->name, name, sizeof(r->name) - 1); 84 strncpy(r->name, name, sizeof(r->name) - 1);
85} 85}
86 86
87void __init free_early(unsigned long start, unsigned long end)
88{
89 struct early_res *r;
90 int i, j;
91
92 for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
93 r = &early_res[i];
94 if (start == r->start && end == r->end)
95 break;
96 }
97 if (i >= MAX_EARLY_RES || !early_res[i].end)
98 panic("free_early on not reserved area: %lx-%lx!", start, end);
99
100 for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
101 ;
102
103 memcpy(&early_res[i], &early_res[i + 1],
104 (j - 1 - i) * sizeof(struct early_res));
105
106 early_res[j - 1].end = 0;
107}
108
87void __init early_res_to_bootmem(void) 109void __init early_res_to_bootmem(void)
88{ 110{
89 int i; 111 int i;
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index d31d6b72d60d..e25c57b8aa84 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -11,6 +11,7 @@
11#include <linux/string.h> 11#include <linux/string.h>
12#include <linux/percpu.h> 12#include <linux/percpu.h>
13#include <linux/start_kernel.h> 13#include <linux/start_kernel.h>
14#include <linux/io.h>
14 15
15#include <asm/processor.h> 16#include <asm/processor.h>
16#include <asm/proto.h> 17#include <asm/proto.h>
@@ -100,6 +101,24 @@ static void __init reserve_ebda_region(void)
100 reserve_early(lowmem, 0x100000, "BIOS reserved"); 101 reserve_early(lowmem, 0x100000, "BIOS reserved");
101} 102}
102 103
104static void __init reserve_setup_data(void)
105{
106 struct setup_data *data;
107 unsigned long pa_data;
108 char buf[32];
109
110 if (boot_params.hdr.version < 0x0209)
111 return;
112 pa_data = boot_params.hdr.setup_data;
113 while (pa_data) {
114 data = early_ioremap(pa_data, sizeof(*data));
115 sprintf(buf, "setup data %x", data->type);
116 reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
117 pa_data = data->next;
118 early_iounmap(data, sizeof(*data));
119 }
120}
121
103void __init x86_64_start_kernel(char * real_mode_data) 122void __init x86_64_start_kernel(char * real_mode_data)
104{ 123{
105 int i; 124 int i;
@@ -156,6 +175,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
156#endif 175#endif
157 176
158 reserve_ebda_region(); 177 reserve_ebda_region();
178 reserve_setup_data();
159 179
160 /* 180 /*
161 * At this point everything still needed from the boot loader 181 * At this point everything still needed from the boot loader
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index 73354302fda7..c03205991718 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -6,23 +6,171 @@
6 * 6 *
7 * This file is released under the GPLv2. 7 * This file is released under the GPLv2.
8 */ 8 */
9
10#include <linux/debugfs.h> 9#include <linux/debugfs.h>
10#include <linux/uaccess.h>
11#include <linux/stat.h> 11#include <linux/stat.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/io.h>
14#include <linux/mm.h>
13 15
14#include <asm/setup.h> 16#include <asm/setup.h>
15 17
16#ifdef CONFIG_DEBUG_BOOT_PARAMS 18#ifdef CONFIG_DEBUG_BOOT_PARAMS
19struct setup_data_node {
20 u64 paddr;
21 u32 type;
22 u32 len;
23};
24
25static ssize_t
26setup_data_read(struct file *file, char __user *user_buf, size_t count,
27 loff_t *ppos)
28{
29 struct setup_data_node *node = file->private_data;
30 unsigned long remain;
31 loff_t pos = *ppos;
32 struct page *pg;
33 void *p;
34 u64 pa;
35
36 if (pos < 0)
37 return -EINVAL;
38 if (pos >= node->len)
39 return 0;
40
41 if (count > node->len - pos)
42 count = node->len - pos;
43 pa = node->paddr + sizeof(struct setup_data) + pos;
44 pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
45 if (PageHighMem(pg)) {
46 p = ioremap_cache(pa, count);
47 if (!p)
48 return -ENXIO;
49 } else {
50 p = __va(pa);
51 }
52
53 remain = copy_to_user(user_buf, p, count);
54
55 if (PageHighMem(pg))
56 iounmap(p);
57
58 if (remain)
59 return -EFAULT;
60
61 *ppos = pos + count;
62
63 return count;
64}
65
66static int setup_data_open(struct inode *inode, struct file *file)
67{
68 file->private_data = inode->i_private;
69 return 0;
70}
71
72static const struct file_operations fops_setup_data = {
73 .read = setup_data_read,
74 .open = setup_data_open,
75};
76
77static int __init
78create_setup_data_node(struct dentry *parent, int no,
79 struct setup_data_node *node)
80{
81 struct dentry *d, *type, *data;
82 char buf[16];
83 int error;
84
85 sprintf(buf, "%d", no);
86 d = debugfs_create_dir(buf, parent);
87 if (!d) {
88 error = -ENOMEM;
89 goto err_return;
90 }
91 type = debugfs_create_x32("type", S_IRUGO, d, &node->type);
92 if (!type) {
93 error = -ENOMEM;
94 goto err_dir;
95 }
96 data = debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
97 if (!data) {
98 error = -ENOMEM;
99 goto err_type;
100 }
101 return 0;
102
103err_type:
104 debugfs_remove(type);
105err_dir:
106 debugfs_remove(d);
107err_return:
108 return error;
109}
110
111static int __init create_setup_data_nodes(struct dentry *parent)
112{
113 struct setup_data_node *node;
114 struct setup_data *data;
115 int error, no = 0;
116 struct dentry *d;
117 struct page *pg;
118 u64 pa_data;
119
120 d = debugfs_create_dir("setup_data", parent);
121 if (!d) {
122 error = -ENOMEM;
123 goto err_return;
124 }
125
126 pa_data = boot_params.hdr.setup_data;
127
128 while (pa_data) {
129 node = kmalloc(sizeof(*node), GFP_KERNEL);
130 if (!node) {
131 error = -ENOMEM;
132 goto err_dir;
133 }
134 pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);
135 if (PageHighMem(pg)) {
136 data = ioremap_cache(pa_data, sizeof(*data));
137 if (!data) {
138 error = -ENXIO;
139 goto err_dir;
140 }
141 } else {
142 data = __va(pa_data);
143 }
144
145 node->paddr = pa_data;
146 node->type = data->type;
147 node->len = data->len;
148 error = create_setup_data_node(d, no, node);
149 pa_data = data->next;
150
151 if (PageHighMem(pg))
152 iounmap(data);
153 if (error)
154 goto err_dir;
155 no++;
156 }
157 return 0;
158
159err_dir:
160 debugfs_remove(d);
161err_return:
162 return error;
163}
164
17static struct debugfs_blob_wrapper boot_params_blob = { 165static struct debugfs_blob_wrapper boot_params_blob = {
18 .data = &boot_params, 166 .data = &boot_params,
19 .size = sizeof(boot_params), 167 .size = sizeof(boot_params),
20}; 168};
21 169
22static int __init boot_params_kdebugfs_init(void) 170static int __init boot_params_kdebugfs_init(void)
23{ 171{
24 int error;
25 struct dentry *dbp, *version, *data; 172 struct dentry *dbp, *version, *data;
173 int error;
26 174
27 dbp = debugfs_create_dir("boot_params", NULL); 175 dbp = debugfs_create_dir("boot_params", NULL);
28 if (!dbp) { 176 if (!dbp) {
@@ -41,7 +189,13 @@ static int __init boot_params_kdebugfs_init(void)
41 error = -ENOMEM; 189 error = -ENOMEM;
42 goto err_version; 190 goto err_version;
43 } 191 }
192 error = create_setup_data_nodes(dbp);
193 if (error)
194 goto err_data;
44 return 0; 195 return 0;
196
197err_data:
198 debugfs_remove(data);
45err_version: 199err_version:
46 debugfs_remove(version); 200 debugfs_remove(version);
47err_dir: 201err_dir:
@@ -61,5 +215,4 @@ static int __init arch_kdebugfs_init(void)
61 215
62 return error; 216 return error;
63} 217}
64
65arch_initcall(arch_kdebugfs_init); 218arch_initcall(arch_kdebugfs_init);
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 17bdf2343095..b04e2c011e1a 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -264,6 +264,28 @@ void __attribute__((weak)) __init memory_setup(void)
264 machine_specific_memory_setup(); 264 machine_specific_memory_setup();
265} 265}
266 266
267static void __init parse_setup_data(void)
268{
269 struct setup_data *data;
270 unsigned long pa_data;
271
272 if (boot_params.hdr.version < 0x0209)
273 return;
274 pa_data = boot_params.hdr.setup_data;
275 while (pa_data) {
276 data = early_ioremap(pa_data, PAGE_SIZE);
277 switch (data->type) {
278 default:
279 break;
280 }
281#ifndef CONFIG_DEBUG_BOOT_PARAMS
282 free_early(pa_data, pa_data+sizeof(*data)+data->len);
283#endif
284 pa_data = data->next;
285 early_iounmap(data, PAGE_SIZE);
286 }
287}
288
267/* 289/*
268 * setup_arch - architecture-specific boot-time initializations 290 * setup_arch - architecture-specific boot-time initializations
269 * 291 *
@@ -316,6 +338,8 @@ void __init setup_arch(char **cmdline_p)
316 strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); 338 strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
317 *cmdline_p = command_line; 339 *cmdline_p = command_line;
318 340
341 parse_setup_data();
342
319 parse_early_param(); 343 parse_early_param();
320 344
321#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT 345#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT