debuggers.hg

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