| .. | .. |
|---|
| 14 | 14 | #include <linux/mm.h> |
|---|
| 15 | 15 | #include <linux/mmu_notifier.h> |
|---|
| 16 | 16 | #include <linux/preempt.h> |
|---|
| 17 | +#include <linux/dovetail.h> |
|---|
| 17 | 18 | #include <linux/msi.h> |
|---|
| 18 | 19 | #include <linux/slab.h> |
|---|
| 19 | 20 | #include <linux/vmalloc.h> |
|---|
| .. | .. |
|---|
| 260 | 261 | unsigned len; |
|---|
| 261 | 262 | }; |
|---|
| 262 | 263 | |
|---|
| 264 | +/* |
|---|
| 265 | + * Called when the host is about to leave the inband stage. Typically |
|---|
| 266 | + * used for switching the current vcpu out of guest mode before a |
|---|
| 267 | + * companion core reinstates an oob task context. |
|---|
| 268 | + */ |
|---|
| 269 | +struct kvm_oob_notifier { |
|---|
| 270 | + void (*handler)(struct kvm_oob_notifier *nfy); |
|---|
| 271 | + bool put_vcpu; |
|---|
| 272 | +}; |
|---|
| 273 | + |
|---|
| 263 | 274 | struct kvm_vcpu { |
|---|
| 264 | 275 | struct kvm *kvm; |
|---|
| 265 | 276 | #ifdef CONFIG_PREEMPT_NOTIFIERS |
|---|
| 266 | 277 | struct preempt_notifier preempt_notifier; |
|---|
| 278 | +#endif |
|---|
| 279 | +#ifdef CONFIG_DOVETAIL |
|---|
| 280 | + struct kvm_oob_notifier oob_notifier; |
|---|
| 267 | 281 | #endif |
|---|
| 268 | 282 | int cpu; |
|---|
| 269 | 283 | int vcpu_id; /* id given by userspace at creation */ |
|---|
| .. | .. |
|---|
| 1502 | 1516 | } |
|---|
| 1503 | 1517 | #endif /* CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE */ |
|---|
| 1504 | 1518 | |
|---|
| 1519 | +#if defined(CONFIG_DOVETAIL) && defined(CONFIG_KVM) |
|---|
| 1520 | +static inline void inband_init_vcpu(struct kvm_vcpu *vcpu, |
|---|
| 1521 | + void (*preempt_handler)(struct kvm_oob_notifier *nfy)) |
|---|
| 1522 | +{ |
|---|
| 1523 | + vcpu->oob_notifier.handler = preempt_handler; |
|---|
| 1524 | + vcpu->oob_notifier.put_vcpu = false; |
|---|
| 1525 | +} |
|---|
| 1526 | + |
|---|
| 1527 | +static inline void inband_enter_guest(struct kvm_vcpu *vcpu) |
|---|
| 1528 | +{ |
|---|
| 1529 | + struct irq_pipeline_data *p = raw_cpu_ptr(&irq_pipeline); |
|---|
| 1530 | + WRITE_ONCE(p->vcpu_notify, &vcpu->oob_notifier); |
|---|
| 1531 | +} |
|---|
| 1532 | + |
|---|
| 1533 | +static inline void inband_exit_guest(void) |
|---|
| 1534 | +{ |
|---|
| 1535 | + struct irq_pipeline_data *p = raw_cpu_ptr(&irq_pipeline); |
|---|
| 1536 | + WRITE_ONCE(p->vcpu_notify, NULL); |
|---|
| 1537 | +} |
|---|
| 1538 | + |
|---|
| 1539 | +static inline void inband_set_vcpu_release_state(struct kvm_vcpu *vcpu, |
|---|
| 1540 | + bool pending) |
|---|
| 1541 | +{ |
|---|
| 1542 | + vcpu->oob_notifier.put_vcpu = pending; |
|---|
| 1543 | +} |
|---|
| 1544 | +#else |
|---|
| 1545 | +static inline void inband_init_vcpu(struct kvm_vcpu *vcpu, |
|---|
| 1546 | + void (*preempt_handler)(struct kvm_oob_notifier *nfy)) |
|---|
| 1547 | +{ } |
|---|
| 1548 | + |
|---|
| 1549 | +static inline void inband_enter_guest(struct kvm_vcpu *vcpu) |
|---|
| 1550 | +{ } |
|---|
| 1551 | + |
|---|
| 1552 | +static inline void inband_exit_guest(void) |
|---|
| 1553 | +{ } |
|---|
| 1554 | + |
|---|
| 1555 | +static inline void inband_set_vcpu_release_state(struct kvm_vcpu *vcpu, |
|---|
| 1556 | + bool pending) |
|---|
| 1557 | +{ } |
|---|
| 1558 | +#endif |
|---|
| 1559 | + |
|---|
| 1505 | 1560 | typedef int (*kvm_vm_thread_fn_t)(struct kvm *kvm, uintptr_t data); |
|---|
| 1506 | 1561 | |
|---|
| 1507 | 1562 | int kvm_vm_create_worker_thread(struct kvm *kvm, kvm_vm_thread_fn_t thread_fn, |
|---|