ia64/xen-unstable

view xen/common/keyhandler.c @ 12390:e28beea6d228

[IA64] Fix time services of EFI emulation

This patch serializes the execution of following efi.runtimes.
- GetTime
- SetTime
- GetWakeTime
- SetWakeTime

Linux/ia64 uses similar spinlocks in the EFI RTC driver.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author awilliam@xenbuild.aw
date Fri Nov 10 12:03:19 2006 -0700 (2006-11-10)
parents fac36a01c06e
children 4c8f157a3a47
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 <asm/debugger.h>
16 #include <asm/shadow.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 ( 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 strncpy(key_table[key].desc, desc, STR_MAX);
70 key_table[key].desc[STR_MAX-1] = '\0';
71 }
73 void register_irq_keyhandler(
74 unsigned char key, irq_keyhandler_t *handler, char *desc)
75 {
76 ASSERT(key_table[key].u.irq_handler == NULL);
77 key_table[key].u.irq_handler = handler;
78 key_table[key].flags = KEYHANDLER_IRQ_CALLBACK;
79 strncpy(key_table[key].desc, desc, STR_MAX);
80 key_table[key].desc[STR_MAX-1] = '\0';
81 }
83 static void show_handlers(unsigned char key)
84 {
85 int i;
86 printk("'%c' pressed -> showing installed handlers\n", key);
87 for ( i = 0; i < KEY_MAX; i++ )
88 if ( key_table[i].u.handler != NULL )
89 printk(" key '%c' (ascii '%02x') => %s\n",
90 (i<33 || i>126)?(' '):(i),i,
91 key_table[i].desc);
92 }
94 static void __dump_execstate(void *unused)
95 {
96 dump_execution_state();
97 }
99 static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
100 {
101 unsigned int cpu;
103 printk("'%c' pressed -> dumping registers\n", key);
105 /* Get local execution state out immediately, in case we get stuck. */
106 printk("\n*** Dumping CPU%d state: ***\n", smp_processor_id());
107 show_execution_state(regs);
109 for_each_online_cpu ( cpu )
110 {
111 if ( cpu == smp_processor_id() )
112 continue;
113 printk("\n*** Dumping CPU%d state: ***\n", cpu);
114 on_selected_cpus(cpumask_of_cpu(cpu), __dump_execstate, NULL, 1, 1);
115 }
116 }
118 static void halt_machine(unsigned char key, struct cpu_user_regs *regs)
119 {
120 printk("'%c' pressed -> rebooting machine\n", key);
121 machine_restart(NULL);
122 }
124 static void cpuset_print(char *set, int size, cpumask_t mask)
125 {
126 *set++ = '{';
127 set += cpulist_scnprintf(set, size-2, mask);
128 *set++ = '}';
129 *set++ = '\0';
130 }
132 static void dump_domains(unsigned char key)
133 {
134 struct domain *d;
135 struct vcpu *v;
136 s_time_t now = NOW();
137 char cpuset[100];
139 printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
140 (u32)(now>>32), (u32)now);
142 read_lock(&domlist_lock);
144 for_each_domain ( d )
145 {
146 printk("General information for domain %u:\n", d->domain_id);
147 cpuset_print(cpuset, sizeof(cpuset), d->domain_dirty_cpumask);
148 printk(" flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d "
149 "dirty_cpus=%s\n",
150 d->domain_flags, atomic_read(&d->refcnt),
151 d->tot_pages, d->xenheap_pages, cpuset);
152 printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
153 "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
154 d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
155 d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7],
156 d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11],
157 d->handle[12], d->handle[13], d->handle[14], d->handle[15],
158 d->vm_assist);
160 arch_dump_domain_info(d);
162 rangeset_domain_printk(d);
164 dump_pageframe_info(d);
166 printk("VCPU information and callbacks for domain %u:\n",
167 d->domain_id);
168 for_each_vcpu ( d, v ) {
169 printk(" VCPU%d: CPU%d [has=%c] flags=%lx "
170 "upcall_pend = %02x, upcall_mask = %02x ",
171 v->vcpu_id, v->processor,
172 test_bit(_VCPUF_running, &v->vcpu_flags) ? 'T':'F',
173 v->vcpu_flags,
174 v->vcpu_info->evtchn_upcall_pending,
175 v->vcpu_info->evtchn_upcall_mask);
176 cpuset_print(cpuset, sizeof(cpuset), v->vcpu_dirty_cpumask);
177 printk("dirty_cpus=%s ", cpuset);
178 cpuset_print(cpuset, sizeof(cpuset), v->cpu_affinity);
179 printk("cpu_affinity=%s\n", cpuset);
180 arch_dump_vcpu_info(v);
181 printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
182 VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
183 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
184 d->shared_info->evtchn_pending),
185 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
186 d->shared_info->evtchn_mask),
187 test_bit(v->virq_to_evtchn[VIRQ_DEBUG]/BITS_PER_LONG,
188 &v->vcpu_info->evtchn_pending_sel));
189 send_guest_vcpu_virq(v, VIRQ_DEBUG);
190 }
191 }
193 read_unlock(&domlist_lock);
194 }
196 static cpumask_t read_clocks_cpumask = CPU_MASK_NONE;
197 static s_time_t read_clocks_time[NR_CPUS];
199 static void read_clocks_slave(void *unused)
200 {
201 unsigned int cpu = smp_processor_id();
202 while ( !cpu_isset(cpu, read_clocks_cpumask) )
203 cpu_relax();
204 read_clocks_time[cpu] = NOW();
205 cpu_clear(cpu, read_clocks_cpumask);
206 }
208 static void read_clocks(unsigned char key)
209 {
210 unsigned int cpu = smp_processor_id(), min_cpu, max_cpu;
211 u64 min, max, dif, difus;
212 static DEFINE_SPINLOCK(lock);
214 spin_lock(&lock);
216 smp_call_function(read_clocks_slave, NULL, 0, 0);
218 local_irq_disable();
219 read_clocks_cpumask = cpu_online_map;
220 read_clocks_time[cpu] = NOW();
221 cpu_clear(cpu, read_clocks_cpumask);
222 local_irq_enable();
224 while ( !cpus_empty(read_clocks_cpumask) )
225 cpu_relax();
227 min_cpu = max_cpu = cpu;
228 for_each_online_cpu ( cpu )
229 {
230 if ( read_clocks_time[cpu] < read_clocks_time[min_cpu] )
231 min_cpu = cpu;
232 if ( read_clocks_time[cpu] > read_clocks_time[max_cpu] )
233 max_cpu = cpu;
234 }
236 min = read_clocks_time[min_cpu];
237 max = read_clocks_time[max_cpu];
239 spin_unlock(&lock);
241 dif = difus = max - min;
242 do_div(difus, 1000);
243 printk("Min = %"PRIu64" ; Max = %"PRIu64" ; Diff = %"PRIu64
244 " (%"PRIu64" microseconds)\n",
245 min, max, dif, difus);
246 }
248 extern void dump_runq(unsigned char key);
250 #ifdef PERF_COUNTERS
251 extern void perfc_printall(unsigned char key);
252 extern void perfc_reset(unsigned char key);
253 #endif
255 static void do_debug_key(unsigned char key, struct cpu_user_regs *regs)
256 {
257 (void)debugger_trap_fatal(0xf001, regs);
258 nop(); /* Prevent the compiler doing tail call
259 optimisation, as that confuses xendbg a
260 bit. */
261 }
263 void initialize_keytable(void)
264 {
265 open_softirq(KEYPRESS_SOFTIRQ, keypress_softirq);
267 register_irq_keyhandler(
268 'd', dump_registers, "dump registers");
269 register_keyhandler(
270 'h', show_handlers, "show this message");
271 register_keyhandler(
272 'q', dump_domains, "dump domain (and guest debug) info");
273 register_keyhandler(
274 'r', dump_runq, "dump run queues");
275 register_irq_keyhandler(
276 'R', halt_machine, "reboot machine");
278 register_keyhandler(
279 't', read_clocks, "display multi-cpu clock info");
281 #ifdef PERF_COUNTERS
282 register_keyhandler(
283 'p', perfc_printall, "print performance counters");
284 register_keyhandler(
285 'P', perfc_reset, "reset performance counters");
286 #endif
288 register_irq_keyhandler('%', do_debug_key, "Trap to xendbg");
289 }
291 /*
292 * Local variables:
293 * mode: C
294 * c-set-style: "BSD"
295 * c-basic-offset: 4
296 * tab-width: 4
297 * indent-tabs-mode: nil
298 * End:
299 */