debuggers.hg

view xen/common/stop_machine.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents 2d4fe1a048cd
children
line source
1 /******************************************************************************
2 * common/stop_machine.c
3 *
4 * Facilities to put whole machine in a safe 'stop' state
5 *
6 * Copyright 2005 Rusty Russell rusty@rustcorp.com.au IBM Corporation
7 * Copyright 2008 Kevin Tian <kevin.tian@intel.com>, Intel Corporation.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20 * Place - Suite 330, Boston, MA 02111-1307 USA.
21 */
23 #include <xen/config.h>
24 #include <xen/init.h>
25 #include <xen/sched.h>
26 #include <xen/spinlock.h>
27 #include <xen/tasklet.h>
28 #include <xen/stop_machine.h>
29 #include <xen/errno.h>
30 #include <xen/smp.h>
31 #include <xen/cpu.h>
32 #include <asm/current.h>
33 #include <asm/processor.h>
35 enum stopmachine_state {
36 STOPMACHINE_START,
37 STOPMACHINE_PREPARE,
38 STOPMACHINE_DISABLE_IRQ,
39 STOPMACHINE_INVOKE,
40 STOPMACHINE_EXIT
41 };
43 struct stopmachine_data {
44 unsigned int nr_cpus;
46 enum stopmachine_state state;
47 atomic_t done;
49 unsigned int fn_cpu;
50 int fn_result;
51 int (*fn)(void *);
52 void *fn_data;
53 };
55 static DEFINE_PER_CPU(struct tasklet, stopmachine_tasklet);
56 static struct stopmachine_data stopmachine_data;
57 static DEFINE_SPINLOCK(stopmachine_lock);
59 static void stopmachine_set_state(enum stopmachine_state state)
60 {
61 atomic_set(&stopmachine_data.done, 0);
62 smp_wmb();
63 stopmachine_data.state = state;
64 }
66 static void stopmachine_wait_state(void)
67 {
68 while ( atomic_read(&stopmachine_data.done) != stopmachine_data.nr_cpus )
69 cpu_relax();
70 }
72 int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu)
73 {
74 cpumask_t allbutself;
75 unsigned int i, nr_cpus;
76 int ret;
78 BUG_ON(!local_irq_is_enabled());
80 /* cpu_online_map must not change. */
81 if ( !get_cpu_maps() )
82 return -EBUSY;
84 allbutself = cpu_online_map;
85 cpu_clear(smp_processor_id(), allbutself);
86 nr_cpus = cpus_weight(allbutself);
88 /* Must not spin here as the holder will expect us to be descheduled. */
89 if ( !spin_trylock(&stopmachine_lock) )
90 {
91 put_cpu_maps();
92 return -EBUSY;
93 }
95 stopmachine_data.fn = fn;
96 stopmachine_data.fn_data = data;
97 stopmachine_data.nr_cpus = nr_cpus;
98 stopmachine_data.fn_cpu = cpu;
99 atomic_set(&stopmachine_data.done, 0);
100 stopmachine_data.state = STOPMACHINE_START;
102 smp_wmb();
104 for_each_cpu_mask ( i, allbutself )
105 tasklet_schedule_on_cpu(&per_cpu(stopmachine_tasklet, i), i);
107 stopmachine_set_state(STOPMACHINE_PREPARE);
108 stopmachine_wait_state();
110 local_irq_disable();
111 stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);
112 stopmachine_wait_state();
114 stopmachine_set_state(STOPMACHINE_INVOKE);
115 if ( (cpu == smp_processor_id()) || (cpu == NR_CPUS) )
116 stopmachine_data.fn_result = (*fn)(data);
117 stopmachine_wait_state();
118 ret = stopmachine_data.fn_result;
120 stopmachine_set_state(STOPMACHINE_EXIT);
121 stopmachine_wait_state();
122 local_irq_enable();
124 spin_unlock(&stopmachine_lock);
126 put_cpu_maps();
128 return ret;
129 }
131 static void stopmachine_action(unsigned long cpu)
132 {
133 enum stopmachine_state state = STOPMACHINE_START;
135 BUG_ON(cpu != smp_processor_id());
137 smp_mb();
139 while ( state != STOPMACHINE_EXIT )
140 {
141 while ( stopmachine_data.state == state )
142 cpu_relax();
144 state = stopmachine_data.state;
145 switch ( state )
146 {
147 case STOPMACHINE_DISABLE_IRQ:
148 local_irq_disable();
149 break;
150 case STOPMACHINE_INVOKE:
151 if ( (stopmachine_data.fn_cpu == smp_processor_id()) ||
152 (stopmachine_data.fn_cpu == NR_CPUS) )
153 stopmachine_data.fn_result =
154 stopmachine_data.fn(stopmachine_data.fn_data);
155 break;
156 default:
157 break;
158 }
160 smp_mb();
161 atomic_inc(&stopmachine_data.done);
162 }
164 local_irq_enable();
165 }
167 static int cpu_callback(
168 struct notifier_block *nfb, unsigned long action, void *hcpu)
169 {
170 unsigned int cpu = (unsigned long)hcpu;
172 if ( action == CPU_UP_PREPARE )
173 tasklet_init(&per_cpu(stopmachine_tasklet, cpu),
174 stopmachine_action, cpu);
176 return NOTIFY_DONE;
177 }
179 static struct notifier_block cpu_nfb = {
180 .notifier_call = cpu_callback
181 };
183 static int __init cpu_stopmachine_init(void)
184 {
185 unsigned int cpu;
186 for_each_online_cpu ( cpu )
187 {
188 void *hcpu = (void *)(long)cpu;
189 cpu_callback(&cpu_nfb, CPU_UP_PREPARE, hcpu);
190 }
191 register_cpu_notifier(&cpu_nfb);
192 return 0;
193 }
194 __initcall(cpu_stopmachine_init);