Mark vcpu as no_desched when interrupts are disabled. Signed-off-by: juergen.gross@fujitsu-siemens.com # HG changeset patch # User juergen.gross@fujitsu-siemens.com # Date 1229673855 -3600 # Node ID 0b6ef982e456e4adbd2a547406d475d1b554fcbe # Parent ff9683032b76f533509191bb9532df10cbb9830b added support of vcpu preempt disable diff -r ff9683032b76 -r 0b6ef982e456 arch/x86_64/kernel/xen_entry.S --- a/arch/x86_64/kernel/xen_entry.S Sat Dec 13 16:00:43 2008 +0000 +++ b/arch/x86_64/kernel/xen_entry.S Fri Dec 19 09:04:15 2008 +0100 @@ -4,6 +4,7 @@ /* Offsets into shared_info_t. */ #define evtchn_upcall_pending /* 0 */ #define evtchn_upcall_mask 1 +#define no_desched 2 #define sizeof_vcpu_shift 6 @@ -25,8 +26,10 @@ #define XEN_PUT_VCPU_INFO_fixup #endif -#define XEN_LOCKED_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg) -#define XEN_LOCKED_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg) +#define XEN_LOCKED_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg) ; \ + movb $1,no_desched(reg) +#define XEN_LOCKED_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg) ; \ + movb $0,no_desched(reg) #define XEN_BLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \ XEN_LOCKED_BLOCK_EVENTS(reg) ; \ XEN_PUT_VCPU_INFO(reg) diff -r ff9683032b76 -r 0b6ef982e456 include/asm-x86_64/mach-xen/asm/irqflags.h --- a/include/asm-x86_64/mach-xen/asm/irqflags.h Sat Dec 13 16:00:43 2008 +0000 +++ b/include/asm-x86_64/mach-xen/asm/irqflags.h Fri Dec 19 09:04:15 2008 +0100 @@ -34,7 +34,10 @@ do { \ barrier(); \ _vcpu = current_vcpu_info(); \ if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \ + _vcpu->no_desched = 0; \ barrier(); /* unmask then check (avoid races) */ \ + if ( unlikely(_vcpu->desched_delay) ) \ + VOID(HYPERVISOR_sched_op(SCHEDOP_yield, 0)); \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ force_evtchn_callback(); \ } \ @@ -69,7 +72,10 @@ static inline int raw_irqs_disabled_flag #define raw_local_irq_disable() \ do { \ - current_vcpu_info()->evtchn_upcall_mask = 1; \ + vcpu_info_t *_vcpu; \ + _vcpu = current_vcpu_info(); \ + _vcpu->evtchn_upcall_mask = 1; \ + _vcpu->no_desched = 1; \ barrier(); \ } while (0) @@ -78,8 +84,11 @@ do { \ vcpu_info_t *_vcpu; \ barrier(); \ _vcpu = current_vcpu_info(); \ + _vcpu->no_desched = 0; \ _vcpu->evtchn_upcall_mask = 0; \ barrier(); /* unmask then check (avoid races) */ \ + if ( unlikely(_vcpu->desched_delay) ) \ + VOID(HYPERVISOR_sched_op(SCHEDOP_yield, 0)); \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ force_evtchn_callback(); \ } while (0) diff -r ff9683032b76 -r 0b6ef982e456 include/xen/interface/xen.h --- a/include/xen/interface/xen.h Sat Dec 13 16:00:43 2008 +0000 +++ b/include/xen/interface/xen.h Fri Dec 19 09:04:15 2008 +0100 @@ -434,9 +434,18 @@ struct vcpu_info { * non-zero mask therefore guarantees that the VCPU will not receive * an upcall activation. The mask is cleared when the VCPU requests * to block: this avoids wakeup-waiting races. + * + * The guest can set 'no_desched' to a non-zero value to avoid being + * descheduled. If the hypervisor didn't deschedule the VCPU due to + * 'no_desched' being set, it will itself set 'desched_delay' to inform + * the guest to give up control voluntaryly later. This is just a wish + * of the guest which the hypervisor may not obey (and it will deschedule + * the guest after a reasonable time anyway). */ uint8_t evtchn_upcall_pending; uint8_t evtchn_upcall_mask; + uint8_t no_desched; + uint8_t desched_delay; unsigned long evtchn_pending_sel; struct arch_vcpu_info arch; struct vcpu_time_info time;