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)
__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)
{
if (__ipipe_current_domain != top) {
......@@ -155,7 +177,6 @@ void ipipe_free_irq(struct ipipe_domain *ipd,
void ipipe_raise_irq(unsigned int irq);
void ipipe_set_hooks(struct ipipe_domain *ipd,
int enables);
......
......@@ -23,6 +23,8 @@
#ifndef __LINUX_IPIPE_BASE_H
#define __LINUX_IPIPE_BASE_H
struct kvm_vcpu;
struct ipipe_vm_notifier;
struct irq_desc;
#ifdef CONFIG_IPIPE
......@@ -42,6 +44,10 @@ struct ipipe_trap_data {
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)
{
return irq >= IPIPE_VIRQ_BASE && irq < IPIPE_NR_IRQS;
......@@ -167,6 +173,8 @@ int __ipipe_notify_trap(int exception, 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)
#else /* !CONFIG_IPIPE */
......@@ -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_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)
#endif /* !CONFIG_IPIPE */
......
......@@ -219,6 +219,9 @@ struct kvm_vcpu {
struct kvm *kvm;
#ifdef CONFIG_PREEMPT_NOTIFIERS
struct preempt_notifier preempt_notifier;
#endif
#ifdef CONFIG_IPIPE
struct ipipe_vm_notifier ipipe_notifier;
#endif
int cpu;
int vcpu_id;
......
......@@ -1256,6 +1256,19 @@ int __ipipe_switch_tail(void)
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 */
{
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