mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
keyhandler: rework process of nonirq keyhandler
Keyhandler may run for a long time in serial port driver's timer handler on the large machine with a lot of physical cpus(e,g dump_timerq()) when serial port driver works in the poll mode(via the exception mechanism). If a timer handler runs a long time, it will block nmi_timer_fn() to feed NMI watchdog and cause Xen hypervisor panic. Inserting process_pending_softirqs() in timer handler will not help. when timer interrupt arrives, timer subsystem calls all expired timer handlers before programming next timer interrupt. There is no timer interrupt arriving to trigger timer softirq during run a timer handler. This patch is to fix the issue to make nonirq keyhandler run in tasklet when receive debug key from serial port. Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
38ab99b26b
commit
610b4eda2c
4 files changed
+10
-6
No files matched your search
@@ -75,19 +75,22 @@ static struct keyhandler {
|
||||
|
||||
static void keypress_action(unsigned long unused)
|
||||
{
|
||||
handle_keypress(keypress_key, NULL);
|
||||
console_start_log_everything();
|
||||
key_table[keypress_key].fn(keypress_key);
|
||||
console_end_log_everything();
|
||||
}
|
||||
|
||||
static DECLARE_TASKLET(keypress_tasklet, keypress_action, 0);
|
||||
|
||||
void handle_keypress(unsigned char key, struct cpu_user_regs *regs)
|
||||
void handle_keypress(unsigned char key, struct cpu_user_regs *regs,
|
||||
bool force_tasklet)
|
||||
{
|
||||
struct keyhandler *h;
|
||||
|
||||
if ( key >= ARRAY_SIZE(key_table) || !(h = &key_table[key])->fn )
|
||||
return;
|
||||
|
||||
if ( !in_irq() || h->irq_callback )
|
||||
if ( h->irq_callback || !force_tasklet )
|
||||
{
|
||||
console_start_log_everything();
|
||||
h->irq_callback ? h->irq_fn(key, regs) : h->fn(key);
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
|
||||
{
|
||||
if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) )
|
||||
goto out;
|
||||
handle_keypress(c, guest_cpu_user_regs());
|
||||
handle_keypress(c, guest_cpu_user_regs(), false);
|
||||
}
|
||||
ret = 0;
|
||||
copyback = 0;
|
||||
|
||||
@@ -347,7 +347,7 @@ static void switch_serial_input(void)
|
||||
static void __serial_rx(char c, struct cpu_user_regs *regs)
|
||||
{
|
||||
if ( xen_rx )
|
||||
return handle_keypress(c, regs);
|
||||
return handle_keypress(c, regs, !in_irq());
|
||||
|
||||
/* Deliver input to guest buffer, unless it is already full. */
|
||||
if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
|
||||
|
||||
@@ -46,7 +46,8 @@ void register_irq_keyhandler(unsigned char key,
|
||||
bool_t diagnostic);
|
||||
|
||||
/* Inject a keypress into the key-handling subsystem. */
|
||||
extern void handle_keypress(unsigned char key, struct cpu_user_regs *regs);
|
||||
extern void handle_keypress(unsigned char key, struct cpu_user_regs *regs,
|
||||
bool force_tasklet);
|
||||
|
||||
/* Scratch space is available for use of any keyhandler. */
|
||||
extern char keyhandler_scratch[1024];
|
||||
|
||||