mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-06-02 07:32:29 -04:00
KVM: x86: Move PIT ioctl helpers to i8254.c
Move the PIT ioctl helpers to i8254.c, i.e. to the file that implements PIT emulation. Eliminating PIT code in x86.c will allow adding a Kconfig to control support for in-kernel I/O APIC, PIC, and PIT emulation with minimal #ifdefs. Opportunistically make kvm_pit_set_reinject() and kvm_pit_load_count() local to i8254.c as they were only publicly visible to make them available to the ioctl helpers. No functional change intended. Acked-by: Kai Huang <kai.huang@intel.com> Link: https://lore.kernel.org/r/20250611213557.294358-6-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
@@ -288,7 +288,7 @@ static inline void kvm_pit_reset_reinject(struct kvm_pit *pit)
|
||||
atomic_set(&pit->pit_state.irq_ack, 1);
|
||||
}
|
||||
|
||||
void kvm_pit_set_reinject(struct kvm_pit *pit, bool reinject)
|
||||
static void kvm_pit_set_reinject(struct kvm_pit *pit, bool reinject)
|
||||
{
|
||||
struct kvm_kpit_state *ps = &pit->pit_state;
|
||||
struct kvm *kvm = pit->kvm;
|
||||
@@ -400,8 +400,8 @@ static void pit_load_count(struct kvm_pit *pit, int channel, u32 val)
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_pit_load_count(struct kvm_pit *pit, int channel, u32 val,
|
||||
int hpet_legacy_start)
|
||||
static void kvm_pit_load_count(struct kvm_pit *pit, int channel, u32 val,
|
||||
int hpet_legacy_start)
|
||||
{
|
||||
u8 saved_mode;
|
||||
|
||||
@@ -649,6 +649,79 @@ static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask)
|
||||
kvm_pit_reset_reinject(pit);
|
||||
}
|
||||
|
||||
int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps)
|
||||
{
|
||||
struct kvm_kpit_state *kps = &kvm->arch.vpit->pit_state;
|
||||
|
||||
BUILD_BUG_ON(sizeof(*ps) != sizeof(kps->channels));
|
||||
|
||||
mutex_lock(&kps->lock);
|
||||
memcpy(ps, &kps->channels, sizeof(*ps));
|
||||
mutex_unlock(&kps->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
|
||||
{
|
||||
int i;
|
||||
struct kvm_pit *pit = kvm->arch.vpit;
|
||||
|
||||
mutex_lock(&pit->pit_state.lock);
|
||||
memcpy(&pit->pit_state.channels, ps, sizeof(*ps));
|
||||
for (i = 0; i < 3; i++)
|
||||
kvm_pit_load_count(pit, i, ps->channels[i].count, 0);
|
||||
mutex_unlock(&pit->pit_state.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
|
||||
{
|
||||
mutex_lock(&kvm->arch.vpit->pit_state.lock);
|
||||
memcpy(ps->channels, &kvm->arch.vpit->pit_state.channels,
|
||||
sizeof(ps->channels));
|
||||
ps->flags = kvm->arch.vpit->pit_state.flags;
|
||||
mutex_unlock(&kvm->arch.vpit->pit_state.lock);
|
||||
memset(&ps->reserved, 0, sizeof(ps->reserved));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
|
||||
{
|
||||
int start = 0;
|
||||
int i;
|
||||
u32 prev_legacy, cur_legacy;
|
||||
struct kvm_pit *pit = kvm->arch.vpit;
|
||||
|
||||
mutex_lock(&pit->pit_state.lock);
|
||||
prev_legacy = pit->pit_state.flags & KVM_PIT_FLAGS_HPET_LEGACY;
|
||||
cur_legacy = ps->flags & KVM_PIT_FLAGS_HPET_LEGACY;
|
||||
if (!prev_legacy && cur_legacy)
|
||||
start = 1;
|
||||
memcpy(&pit->pit_state.channels, &ps->channels,
|
||||
sizeof(pit->pit_state.channels));
|
||||
pit->pit_state.flags = ps->flags;
|
||||
for (i = 0; i < 3; i++)
|
||||
kvm_pit_load_count(pit, i, pit->pit_state.channels[i].count,
|
||||
start && i == 0);
|
||||
mutex_unlock(&pit->pit_state.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_vm_ioctl_reinject(struct kvm *kvm, struct kvm_reinject_control *control)
|
||||
{
|
||||
struct kvm_pit *pit = kvm->arch.vpit;
|
||||
|
||||
/* pit->pit_state.lock was overloaded to prevent userspace from getting
|
||||
* an inconsistent state after running multiple KVM_REINJECT_CONTROL
|
||||
* ioctls in parallel. Use a separate lock if that ioctl isn't rare.
|
||||
*/
|
||||
mutex_lock(&pit->pit_state.lock);
|
||||
kvm_pit_set_reinject(pit, control->pit_reinject);
|
||||
mutex_unlock(&pit->pit_state.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct kvm_io_device_ops pit_dev_ops = {
|
||||
.read = pit_ioport_read,
|
||||
.write = pit_ioport_write,
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <kvm/iodev.h>
|
||||
|
||||
#include <uapi/asm/kvm.h>
|
||||
|
||||
struct kvm_kpit_channel_state {
|
||||
u32 count; /* can be 65536 */
|
||||
u16 latched_count;
|
||||
@@ -55,11 +57,13 @@ struct kvm_pit {
|
||||
#define KVM_MAX_PIT_INTR_INTERVAL HZ / 100
|
||||
#define KVM_PIT_CHANNEL_MASK 0x3
|
||||
|
||||
int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps);
|
||||
int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps);
|
||||
int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps);
|
||||
int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps);
|
||||
int kvm_vm_ioctl_reinject(struct kvm *kvm, struct kvm_reinject_control *control);
|
||||
|
||||
struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags);
|
||||
void kvm_free_pit(struct kvm *kvm);
|
||||
|
||||
void kvm_pit_load_count(struct kvm_pit *pit, int channel, u32 val,
|
||||
int hpet_legacy_start);
|
||||
void kvm_pit_set_reinject(struct kvm_pit *pit, bool reinject);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6450,80 +6450,6 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps)
|
||||
{
|
||||
struct kvm_kpit_state *kps = &kvm->arch.vpit->pit_state;
|
||||
|
||||
BUILD_BUG_ON(sizeof(*ps) != sizeof(kps->channels));
|
||||
|
||||
mutex_lock(&kps->lock);
|
||||
memcpy(ps, &kps->channels, sizeof(*ps));
|
||||
mutex_unlock(&kps->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
|
||||
{
|
||||
int i;
|
||||
struct kvm_pit *pit = kvm->arch.vpit;
|
||||
|
||||
mutex_lock(&pit->pit_state.lock);
|
||||
memcpy(&pit->pit_state.channels, ps, sizeof(*ps));
|
||||
for (i = 0; i < 3; i++)
|
||||
kvm_pit_load_count(pit, i, ps->channels[i].count, 0);
|
||||
mutex_unlock(&pit->pit_state.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
|
||||
{
|
||||
mutex_lock(&kvm->arch.vpit->pit_state.lock);
|
||||
memcpy(ps->channels, &kvm->arch.vpit->pit_state.channels,
|
||||
sizeof(ps->channels));
|
||||
ps->flags = kvm->arch.vpit->pit_state.flags;
|
||||
mutex_unlock(&kvm->arch.vpit->pit_state.lock);
|
||||
memset(&ps->reserved, 0, sizeof(ps->reserved));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
|
||||
{
|
||||
int start = 0;
|
||||
int i;
|
||||
u32 prev_legacy, cur_legacy;
|
||||
struct kvm_pit *pit = kvm->arch.vpit;
|
||||
|
||||
mutex_lock(&pit->pit_state.lock);
|
||||
prev_legacy = pit->pit_state.flags & KVM_PIT_FLAGS_HPET_LEGACY;
|
||||
cur_legacy = ps->flags & KVM_PIT_FLAGS_HPET_LEGACY;
|
||||
if (!prev_legacy && cur_legacy)
|
||||
start = 1;
|
||||
memcpy(&pit->pit_state.channels, &ps->channels,
|
||||
sizeof(pit->pit_state.channels));
|
||||
pit->pit_state.flags = ps->flags;
|
||||
for (i = 0; i < 3; i++)
|
||||
kvm_pit_load_count(pit, i, pit->pit_state.channels[i].count,
|
||||
start && i == 0);
|
||||
mutex_unlock(&pit->pit_state.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_vm_ioctl_reinject(struct kvm *kvm,
|
||||
struct kvm_reinject_control *control)
|
||||
{
|
||||
struct kvm_pit *pit = kvm->arch.vpit;
|
||||
|
||||
/* pit->pit_state.lock was overloaded to prevent userspace from getting
|
||||
* an inconsistent state after running multiple KVM_REINJECT_CONTROL
|
||||
* ioctls in parallel. Use a separate lock if that ioctl isn't rare.
|
||||
*/
|
||||
mutex_lock(&pit->pit_state.lock);
|
||||
kvm_pit_set_reinject(pit, control->pit_reinject);
|
||||
mutex_unlock(&pit->pit_state.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
|
||||
{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user