Commit c5ff41ce authored by Jan Kiszka's avatar Jan Kiszka Committed by Avi Kivity

KVM: Allow PIT emulation without speaker port

The in-kernel speaker emulation is only a dummy and also unneeded from
the performance point of view. Rather, it takes user space support to
generate sound output on the host, e.g. console beeps.

To allow this, introduce KVM_CREATE_PIT2 which controls in-kernel
speaker port emulation via a flag passed along the new IOCTL. It also
leaves room for future extensions of the PIT configuration interface.
Signed-off-by: default avatarJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 721eecbf
...@@ -563,7 +563,7 @@ static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask) ...@@ -563,7 +563,7 @@ static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask)
} }
} }
struct kvm_pit *kvm_create_pit(struct kvm *kvm) struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
{ {
struct kvm_pit *pit; struct kvm_pit *pit;
struct kvm_kpit_state *pit_state; struct kvm_kpit_state *pit_state;
...@@ -589,11 +589,13 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) ...@@ -589,11 +589,13 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
pit->dev.private = pit; pit->dev.private = pit;
kvm_io_bus_register_dev(&kvm->pio_bus, &pit->dev); kvm_io_bus_register_dev(&kvm->pio_bus, &pit->dev);
pit->speaker_dev.read = speaker_ioport_read; if (flags & KVM_PIT_SPEAKER_DUMMY) {
pit->speaker_dev.write = speaker_ioport_write; pit->speaker_dev.read = speaker_ioport_read;
pit->speaker_dev.in_range = speaker_in_range; pit->speaker_dev.write = speaker_ioport_write;
pit->speaker_dev.private = pit; pit->speaker_dev.in_range = speaker_in_range;
kvm_io_bus_register_dev(&kvm->pio_bus, &pit->speaker_dev); pit->speaker_dev.private = pit;
kvm_io_bus_register_dev(&kvm->pio_bus, &pit->speaker_dev);
}
kvm->arch.vpit = pit; kvm->arch.vpit = pit;
pit->kvm = kvm; pit->kvm = kvm;
......
...@@ -50,7 +50,7 @@ struct kvm_pit { ...@@ -50,7 +50,7 @@ struct kvm_pit {
void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu); void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu);
void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val); void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val);
struct kvm_pit *kvm_create_pit(struct kvm *kvm); struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags);
void kvm_free_pit(struct kvm *kvm); void kvm_free_pit(struct kvm *kvm);
void kvm_pit_reset(struct kvm_pit *pit); void kvm_pit_reset(struct kvm_pit *pit);
......
...@@ -1127,6 +1127,7 @@ int kvm_dev_ioctl_check_extension(long ext) ...@@ -1127,6 +1127,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_IRQ_INJECT_STATUS: case KVM_CAP_IRQ_INJECT_STATUS:
case KVM_CAP_ASSIGN_DEV_IRQ: case KVM_CAP_ASSIGN_DEV_IRQ:
case KVM_CAP_IRQFD: case KVM_CAP_IRQFD:
case KVM_CAP_PIT2:
r = 1; r = 1;
break; break;
case KVM_CAP_COALESCED_MMIO: case KVM_CAP_COALESCED_MMIO:
...@@ -2038,6 +2039,7 @@ long kvm_arch_vm_ioctl(struct file *filp, ...@@ -2038,6 +2039,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
union { union {
struct kvm_pit_state ps; struct kvm_pit_state ps;
struct kvm_memory_alias alias; struct kvm_memory_alias alias;
struct kvm_pit_config pit_config;
} u; } u;
switch (ioctl) { switch (ioctl) {
...@@ -2098,12 +2100,20 @@ long kvm_arch_vm_ioctl(struct file *filp, ...@@ -2098,12 +2100,20 @@ long kvm_arch_vm_ioctl(struct file *filp,
} }
break; break;
case KVM_CREATE_PIT: case KVM_CREATE_PIT:
u.pit_config.flags = KVM_PIT_SPEAKER_DUMMY;
goto create_pit;
case KVM_CREATE_PIT2:
r = -EFAULT;
if (copy_from_user(&u.pit_config, argp,
sizeof(struct kvm_pit_config)))
goto out;
create_pit:
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
r = -EEXIST; r = -EEXIST;
if (kvm->arch.vpit) if (kvm->arch.vpit)
goto create_pit_unlock; goto create_pit_unlock;
r = -ENOMEM; r = -ENOMEM;
kvm->arch.vpit = kvm_create_pit(kvm); kvm->arch.vpit = kvm_create_pit(kvm, u.pit_config.flags);
if (kvm->arch.vpit) if (kvm->arch.vpit)
r = 0; r = 0;
create_pit_unlock: create_pit_unlock:
......
...@@ -70,6 +70,14 @@ struct kvm_irqchip { ...@@ -70,6 +70,14 @@ struct kvm_irqchip {
} chip; } chip;
}; };
/* for KVM_CREATE_PIT2 */
struct kvm_pit_config {
__u32 flags;
__u32 pad[15];
};
#define KVM_PIT_SPEAKER_DUMMY 1
#define KVM_EXIT_UNKNOWN 0 #define KVM_EXIT_UNKNOWN 0
#define KVM_EXIT_EXCEPTION 1 #define KVM_EXIT_EXCEPTION 1
#define KVM_EXIT_IO 2 #define KVM_EXIT_IO 2
...@@ -419,6 +427,9 @@ struct kvm_trace_rec { ...@@ -419,6 +427,9 @@ struct kvm_trace_rec {
#define KVM_CAP_MCE 31 #define KVM_CAP_MCE 31
#endif #endif
#define KVM_CAP_IRQFD 32 #define KVM_CAP_IRQFD 32
#ifdef __KVM_HAVE_PIT
#define KVM_CAP_PIT2 33
#endif
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
...@@ -525,6 +536,7 @@ struct kvm_irqfd { ...@@ -525,6 +536,7 @@ struct kvm_irqfd {
_IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry) _IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry)
#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq) #define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd) #define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)
#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
/* /*
* ioctls for vcpu fds * ioctls for vcpu fds
......
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