ia64/xen-unstable

view xen/common/keyhandler.c @ 17062:0769835cf50f

x86 shadow: Reduce scope of shadow lock.

emulate_map_dest doesn't require holding lock, since
only shadow related operation possibly involved is to
remove shadow which is less frequent and can acquire
lock inside. Rest are either guest table walk or
per-vcpu monitor table manipulation

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 14 10:33:12 2008 +0000 (2008-02-14)
parents 514d450ad729
children af33f2054f47
line source
1 /******************************************************************************
2 * keyhandler.c
3 */
5 #include <asm/regs.h>
6 #include <xen/keyhandler.h>
7 #include <xen/shutdown.h>
8 #include <xen/event.h>
9 #include <xen/console.h>
10 #include <xen/serial.h>
11 #include <xen/sched.h>
12 #include <xen/softirq.h>
13 #include <xen/domain.h>
14 #include <xen/rangeset.h>
15 #include <xen/compat.h>
16 #include <asm/debugger.h>
17 #include <asm/div64.h>
19 #define KEY_MAX 256
20 #define STR_MAX 64
22 static struct {
23 union {
24 keyhandler_t *handler;
25 irq_keyhandler_t *irq_handler;
26 } u;
27 unsigned int flags;
28 char desc[STR_MAX];
29 } key_table[KEY_MAX];
31 #define KEYHANDLER_IRQ_CALLBACK 0x1
33 static unsigned char keypress_key;
35 static void keypress_softirq(void)
36 {
37 keyhandler_t *h;
38 unsigned char key = keypress_key;
39 console_start_log_everything();
40 if ( (h = key_table[key].u.handler) != NULL )
41 (*h)(key);
42 console_end_log_everything();
43 }
45 void handle_keypress(unsigned char key, struct cpu_user_regs *regs)
46 {
47 irq_keyhandler_t *h;
49 if ( !in_irq() || (key_table[key].flags & KEYHANDLER_IRQ_CALLBACK) )
50 {
51 console_start_log_everything();
52 if ( (h = key_table[key].u.irq_handler) != NULL )
53 (*h)(key, regs);
54 console_end_log_everything();
55 }
56 else
57 {
58 keypress_key = key;
59 raise_softirq(KEYPRESS_SOFTIRQ);
60 }
61 }
63 void register_keyhandler(
64 unsigned char key, keyhandler_t *handler, char *desc)
65 {
66 ASSERT(key_table[key].u.handler == NULL);
67 key_table[key].u.handler = handler;
68 key_table[key].flags = 0;
69 safe_strcpy(key_table[key].desc, desc);
70 }
72 void register_irq_keyhandler(
73 unsigned char key, irq_keyhandler_t *handler, char *desc)
74 {
75 ASSERT(key_table[key].u.irq_handler == NULL);
76 key_table[key].u.irq_handler = handler;
77 key_table[key].flags = KEYHANDLER_IRQ_CALLBACK;
78 safe_strcpy(key_table[key].desc, desc);
79 }
81 static void show_handlers(unsigned char key)
82 {
83 int i;
84 printk("'%c' pressed -> showing installed handlers\n", key);
85 for ( i = 0; i < KEY_MAX; i++ )
86 if ( key_table[i].u.handler != NULL )
87 printk(" key '%c' (ascii '%02x') => %s\n",
88 (i<33 || i>126)?(' '):(i),i,
89 key_table[i].desc);
90 }
92 static void __dump_execstate(void *unused)
93 {
94 dump_execution_state();
95 printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id());
96 if ( is_idle_vcpu(current) )
97 printk("No guest context (CPU is idle).\n");
98 else
99 show_execution_state(guest_cpu_user_regs());
100 }
102 static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
103 {
104 unsigned int cpu;
106 printk("'%c' pressed -> dumping registers\n", key);
108 /* Get local execution state out immediately, in case we get stuck. */
109 printk("\n*** Dumping CPU%d host state: ***\n", smp_processor_id());
110 __dump_execstate(NULL);
112 for_each_online_cpu ( cpu )
113 {
114 if ( cpu == smp_processor_id() )
115 continue;
116 printk("\n*** Dumping CPU%d host state: ***\n", cpu);
117 on_selected_cpus(cpumask_of_cpu(cpu), __dump_execstate, NULL, 1, 1);
118 }
120 printk("\n");
121 }
123 static void halt_machine(unsigned char key, struct cpu_user_regs *regs)
124 {
125 printk("'%c' pressed -> rebooting machine\n", key);
126 machine_restart();
127 }
129 static void cpuset_print(char *set, int size, cpumask_t mask)
130 {
131 *set++ = '{';
132 set += cpulist_scnprintf(set, size-2, mask);
133 *set++ = '}';
134 *set++ = '\0';
135 }
137 static void periodic_timer_print(char *str, int size, uint64_t period)
138 {
139 if ( period == 0 )
140 {
141 strlcpy(str, "No periodic timer", size);
142 return;
143 }
145 snprintf(str, size,
146 "%u Hz periodic timer (period %u ms)",
147 1000000000/(int)period, (int)period/1000000);
148 }
150 static void dump_domains(unsigned char key)
151 {
152 struct domain *d;
153 struct vcpu *v;
154 s_time_t now = NOW();
155 char tmpstr[100];
157 printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
158 (u32)(now>>32), (u32)now);
160 rcu_read_lock(&domlist_read_lock);
162 for_each_domain ( d )
163 {
164 printk("General information for domain %u:\n", d->domain_id);
165 cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
166 printk(" refcnt=%d nr_pages=%d xenheap_pages=%d "
167 "dirty_cpus=%s\n",
168 atomic_read(&d->refcnt),
169 d->tot_pages, d->xenheap_pages, tmpstr);
170 printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
171 "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
172 d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
173 d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7],
174 d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11],
175 d->handle[12], d->handle[13], d->handle[14], d->handle[15],
176 d->vm_assist);
178 arch_dump_domain_info(d);
180 rangeset_domain_printk(d);
182 dump_pageframe_info(d);
184 printk("VCPU information and callbacks for domain %u:\n",
185 d->domain_id);
186 for_each_vcpu ( d, v ) {
187 printk(" VCPU%d: CPU%d [has=%c] flags=%lx "
188 "upcall_pend = %02x, upcall_mask = %02x ",
189 v->vcpu_id, v->processor,
190 v->is_running ? 'T':'F',
191 v->pause_flags,
192 vcpu_info(v, evtchn_upcall_pending),
193 vcpu_info(v, evtchn_upcall_mask));
194 cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
195 printk("dirty_cpus=%s ", tmpstr);
196 cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
197 printk("cpu_affinity=%s\n", tmpstr);
198 arch_dump_vcpu_info(v);
199 periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
200 printk(" %s\n", tmpstr);
201 printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
202 VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
203 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
204 shared_info_addr(d, evtchn_pending)),
205 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
206 shared_info_addr(d, evtchn_mask)),
207 test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
208 BITS_PER_GUEST_LONG(d),
209 vcpu_info_addr(v, evtchn_pending_sel)));
210 send_guest_vcpu_virq(v, VIRQ_DEBUG);
211 }
212 }
214 rcu_read_unlock(&domlist_read_lock);
215 }
217 static cpumask_t read_clocks_cpumask = CPU_MASK_NONE;
218 static s_time_t read_clocks_time[NR_CPUS];
220 static void read_clocks_slave(void *unused)
221 {
222 unsigned int cpu = smp_processor_id();
223 while ( !cpu_isset(cpu, read_clocks_cpumask) )
224 cpu_relax();
225 read_clocks_time[cpu] = NOW();
226 cpu_clear(cpu, read_clocks_cpumask);
227 }
229 static void read_clocks(unsigned char key)
230 {
231 unsigned int cpu = smp_processor_id(), min_cpu, max_cpu;
232 u64 min, max, dif, difus;
233 static DEFINE_SPINLOCK(lock);
235 spin_lock(&lock);
237 smp_call_function(read_clocks_slave, NULL, 0, 0);
239 local_irq_disable();
240 read_clocks_cpumask = cpu_online_map;
241 read_clocks_time[cpu] = NOW();
242 cpu_clear(cpu, read_clocks_cpumask);
243 local_irq_enable();
245 while ( !cpus_empty(read_clocks_cpumask) )
246 cpu_relax();
248 min_cpu = max_cpu = cpu;
249 for_each_online_cpu ( cpu )
250 {
251 if ( read_clocks_time[cpu] < read_clocks_time[min_cpu] )
252 min_cpu = cpu;
253 if ( read_clocks_time[cpu] > read_clocks_time[max_cpu] )
254 max_cpu = cpu;
255 }
257 min = read_clocks_time[min_cpu];
258 max = read_clocks_time[max_cpu];
260 spin_unlock(&lock);
262 dif = difus = max - min;
263 do_div(difus, 1000);
264 printk("Min = %"PRIu64" ; Max = %"PRIu64" ; Diff = %"PRIu64
265 " (%"PRIu64" microseconds)\n",
266 min, max, dif, difus);
267 }
269 extern void dump_runq(unsigned char key);
271 #ifdef PERF_COUNTERS
272 extern void perfc_printall(unsigned char key);
273 extern void perfc_reset(unsigned char key);
274 #endif
276 static void do_debug_key(unsigned char key, struct cpu_user_regs *regs)
277 {
278 printk("'%c' pressed -> trapping into debugger\n", key);
279 (void)debugger_trap_fatal(0xf001, regs);
280 nop(); /* Prevent the compiler doing tail call
281 optimisation, as that confuses xendbg a
282 bit. */
283 }
285 void __init initialize_keytable(void)
286 {
287 open_softirq(KEYPRESS_SOFTIRQ, keypress_softirq);
289 register_irq_keyhandler(
290 'd', dump_registers, "dump registers");
291 register_keyhandler(
292 'h', show_handlers, "show this message");
293 register_keyhandler(
294 'q', dump_domains, "dump domain (and guest debug) info");
295 register_keyhandler(
296 'r', dump_runq, "dump run queues");
297 register_irq_keyhandler(
298 'R', halt_machine, "reboot machine");
300 register_keyhandler(
301 't', read_clocks, "display multi-cpu clock info");
303 #ifdef PERF_COUNTERS
304 register_keyhandler(
305 'p', perfc_printall, "print performance counters");
306 register_keyhandler(
307 'P', perfc_reset, "reset performance counters");
308 #endif
310 register_irq_keyhandler('%', do_debug_key, "Trap to xendbg");
311 }
313 /*
314 * Local variables:
315 * mode: C
316 * c-set-style: "BSD"
317 * c-basic-offset: 4
318 * tab-width: 4
319 * indent-tabs-mode: nil
320 * End:
321 */