Commit 88e379f8 authored by Philippe Gerum's avatar Philippe Gerum

KVM: ipipe: keep hypervisor state consistent across domain preemption

In order for the hypervisor to operate properly in presence of a
co-kernel, we need:

- the virtualization core to know when the hypervisor stalls due
  to a preemption by the co-kernel.

- to know when the VM enters and leaves guest mode.
parent 0088b024
...@@ -129,6 +129,28 @@ static inline void __ipipe_nmi_exit(void) ...@@ -129,6 +129,28 @@ static inline void __ipipe_nmi_exit(void)
__clear_bit(IPIPE_STALL_FLAG, &__ipipe_root_status); __clear_bit(IPIPE_STALL_FLAG, &__ipipe_root_status);
} }
/* KVM-side calls, hw IRQs off. */
static inline void __ipipe_enter_vm(struct ipipe_vm_notifier *vmf)
{
struct ipipe_percpu_data *p;
p = raw_cpu_ptr(&ipipe_percpu);
p->vm_notifier = vmf;
barrier();
}
static inline void __ipipe_exit_vm(void)
{
struct ipipe_percpu_data *p;
p = raw_cpu_ptr(&ipipe_percpu);
p->vm_notifier = NULL;
barrier();
}
/* Client-side call, hw IRQs off. */
void __ipipe_notify_vm_preemption(void);
static inline void __ipipe_sync_pipeline(struct ipipe_domain *top) static inline void __ipipe_sync_pipeline(struct ipipe_domain *top)
{ {
if (__ipipe_current_domain != top) { if (__ipipe_current_domain != top) {
...@@ -155,7 +177,6 @@ void ipipe_free_irq(struct ipipe_domain *ipd, ...@@ -155,7 +177,6 @@ void ipipe_free_irq(struct ipipe_domain *ipd,
void ipipe_raise_irq(unsigned int irq); void ipipe_raise_irq(unsigned int irq);
void ipipe_set_hooks(struct ipipe_domain *ipd, void ipipe_set_hooks(struct ipipe_domain *ipd,
int enables); int enables);
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef __LINUX_IPIPE_BASE_H #ifndef __LINUX_IPIPE_BASE_H
#define __LINUX_IPIPE_BASE_H #define __LINUX_IPIPE_BASE_H
struct kvm_vcpu;
struct ipipe_vm_notifier;
struct irq_desc; struct irq_desc;
#ifdef CONFIG_IPIPE #ifdef CONFIG_IPIPE
...@@ -42,6 +44,10 @@ struct ipipe_trap_data { ...@@ -42,6 +44,10 @@ struct ipipe_trap_data {
struct pt_regs *regs; struct pt_regs *regs;
}; };
struct ipipe_vm_notifier {
void (*handler)(struct ipipe_vm_notifier *nfy);
};
static inline int ipipe_virtual_irq_p(unsigned int irq) static inline int ipipe_virtual_irq_p(unsigned int irq)
{ {
return irq >= IPIPE_VIRQ_BASE && irq < IPIPE_NR_IRQS; return irq >= IPIPE_VIRQ_BASE && irq < IPIPE_NR_IRQS;
...@@ -167,6 +173,8 @@ int __ipipe_notify_trap(int exception, struct pt_regs *regs); ...@@ -167,6 +173,8 @@ int __ipipe_notify_trap(int exception, struct pt_regs *regs);
void __ipipe_call_mayday(struct pt_regs *regs); void __ipipe_call_mayday(struct pt_regs *regs);
void __ipipe_notify_vm_preemption(void);
#define __ipipe_serial_debug(__fmt, __args...) raw_printk(__fmt, ##__args) #define __ipipe_serial_debug(__fmt, __args...) raw_printk(__fmt, ##__args)
#else /* !CONFIG_IPIPE */ #else /* !CONFIG_IPIPE */
...@@ -212,6 +220,12 @@ static inline void __ipipe_report_cleanup(struct mm_struct *mm) { } ...@@ -212,6 +220,12 @@ static inline void __ipipe_report_cleanup(struct mm_struct *mm) { }
#define ipipe_handle_demuxed_irq(irq) generic_handle_irq(irq) #define ipipe_handle_demuxed_irq(irq) generic_handle_irq(irq)
#define __ipipe_enter_vm(vmf) do { } while (0)
static inline void __ipipe_exit_vm(void) { }
static inline void __ipipe_notify_vm_preemption(void) { }
#define __ipipe_serial_debug(__fmt, __args...) do { } while (0) #define __ipipe_serial_debug(__fmt, __args...) do { } while (0)
#endif /* !CONFIG_IPIPE */ #endif /* !CONFIG_IPIPE */
......
...@@ -219,6 +219,9 @@ struct kvm_vcpu { ...@@ -219,6 +219,9 @@ struct kvm_vcpu {
struct kvm *kvm; struct kvm *kvm;
#ifdef CONFIG_PREEMPT_NOTIFIERS #ifdef CONFIG_PREEMPT_NOTIFIERS
struct preempt_notifier preempt_notifier; struct preempt_notifier preempt_notifier;
#endif
#ifdef CONFIG_IPIPE
struct ipipe_vm_notifier ipipe_notifier;
#endif #endif
int cpu; int cpu;
int vcpu_id; int vcpu_id;
......
...@@ -1256,6 +1256,19 @@ int __ipipe_switch_tail(void) ...@@ -1256,6 +1256,19 @@ int __ipipe_switch_tail(void)
return !x; return !x;
} }
void __ipipe_notify_vm_preemption(void)
{
struct ipipe_vm_notifier *vmf;
struct ipipe_percpu_data *p;
ipipe_check_irqoff();
p = __ipipe_raw_cpu_ptr(&ipipe_percpu);
vmf = p->vm_notifier;
if (unlikely(vmf))
vmf->handler(vmf);
}
EXPORT_SYMBOL_GPL(__ipipe_notify_vm_preemption);
static void dispatch_irq_head(unsigned int irq) /* hw interrupts off */ static void dispatch_irq_head(unsigned int irq) /* hw interrupts off */
{ {
struct ipipe_percpu_domain_data *p = ipipe_this_cpu_head_context(), *old; struct ipipe_percpu_domain_data *p = ipipe_this_cpu_head_context(), *old;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment