Skip to content

Commit 73880c8

Browse files
Gleb Natapovavikivity
authored andcommitted
KVM: Break dependency between vcpu index in vcpus array and vcpu_id.
Archs are free to use vcpu_id as they see fit. For x86 it is used as vcpu's apic id. New ioctl is added to configure boot vcpu id that was assumed to be 0 till now. Signed-off-by: Gleb Natapov <[email protected]> Signed-off-by: Avi Kivity <[email protected]>
1 parent 1ed0ce0 commit 73880c8

File tree

9 files changed

+55
-33
lines changed

9 files changed

+55
-33
lines changed

arch/ia64/include/asm/kvm_host.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,6 @@ struct kvm_arch {
465465
unsigned long metaphysical_rr4;
466466
unsigned long vmm_init_rr;
467467

468-
int online_vcpus;
469468
int is_sn2;
470469

471470
struct kvm_ioapic *vioapic;

arch/ia64/kvm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ config KVM
2525
select PREEMPT_NOTIFIERS
2626
select ANON_INODES
2727
select HAVE_KVM_IRQCHIP
28+
select KVM_APIC_ARCHITECTURE
2829
---help---
2930
Support hosting fully virtualized guest machines using hardware
3031
virtualization extensions. You will need a fairly recent

arch/ia64/kvm/kvm-ia64.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,
338338
union ia64_lid lid;
339339
int i;
340340

341-
for (i = 0; i < kvm->arch.online_vcpus; i++) {
341+
for (i = 0; i < atomic_read(&kvm->online_vcpus); i++) {
342342
if (kvm->vcpus[i]) {
343343
lid.val = VCPU_LID(kvm->vcpus[i]);
344344
if (lid.id == id && lid.eid == eid)
@@ -412,7 +412,7 @@ static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
412412

413413
call_data.ptc_g_data = p->u.ptc_g_data;
414414

415-
for (i = 0; i < kvm->arch.online_vcpus; i++) {
415+
for (i = 0; i < atomic_read(&kvm->online_vcpus); i++) {
416416
if (!kvm->vcpus[i] || kvm->vcpus[i]->arch.mp_state ==
417417
KVM_MP_STATE_UNINITIALIZED ||
418418
vcpu == kvm->vcpus[i])
@@ -852,8 +852,6 @@ struct kvm *kvm_arch_create_vm(void)
852852

853853
kvm_init_vm(kvm);
854854

855-
kvm->arch.online_vcpus = 0;
856-
857855
return kvm;
858856

859857
}
@@ -1356,8 +1354,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
13561354
goto fail;
13571355
}
13581356

1359-
kvm->arch.online_vcpus++;
1360-
13611357
return vcpu;
13621358
fail:
13631359
return ERR_PTR(r);

arch/ia64/kvm/vcpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val)
831831
kvm = (struct kvm *)KVM_VM_BASE;
832832

833833
if (kvm_vcpu_is_bsp(vcpu)) {
834-
for (i = 0; i < kvm->arch.online_vcpus; i++) {
834+
for (i = 0; i < atomic_read(&kvm->online_vcpus); i++) {
835835
v = (struct kvm_vcpu *)((char *)vcpu +
836836
sizeof(struct kvm_vcpu_data) * i);
837837
VMX(v, itc_offset) = itc_offset;

arch/x86/kvm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ config KVM
2727
select ANON_INODES
2828
select HAVE_KVM_IRQCHIP
2929
select HAVE_KVM_EVENTFD
30+
select KVM_APIC_ARCHITECTURE
3031
---help---
3132
Support hosting fully virtualized guest machines using hardware
3233
virtualization extensions. You will need a fairly recent

include/linux/kvm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ struct kvm_trace_rec {
430430
#ifdef __KVM_HAVE_PIT
431431
#define KVM_CAP_PIT2 33
432432
#endif
433+
#define KVM_CAP_SET_BOOT_CPU_ID 34
433434

434435
#ifdef KVM_CAP_IRQ_ROUTING
435436

@@ -537,6 +538,7 @@ struct kvm_irqfd {
537538
#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
538539
#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)
539540
#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
541+
#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
540542

541543
/*
542544
* ioctls for vcpu fds

include/linux/kvm_host.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,12 @@ struct kvm {
131131
int nmemslots;
132132
struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS +
133133
KVM_PRIVATE_MEM_SLOTS];
134+
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
135+
u32 bsp_vcpu_id;
134136
struct kvm_vcpu *bsp_vcpu;
137+
#endif
135138
struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
139+
atomic_t online_vcpus;
136140
struct list_head vm_list;
137141
struct mutex lock;
138142
struct kvm_io_bus mmio_bus;
@@ -550,8 +554,10 @@ static inline void kvm_irqfd_release(struct kvm *kvm) {}
550554

551555
#endif /* CONFIG_HAVE_KVM_EVENTFD */
552556

557+
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
553558
static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
554559
{
555560
return vcpu->kvm->bsp_vcpu == vcpu;
556561
}
557562
#endif
563+
#endif

virt/kvm/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ config HAVE_KVM_IRQCHIP
99
config HAVE_KVM_EVENTFD
1010
bool
1111
select EVENTFD
12+
13+
config KVM_APIC_ARCHITECTURE
14+
bool

virt/kvm/kvm_main.c

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -689,11 +689,6 @@ static int kvm_vm_ioctl_deassign_device(struct kvm *kvm,
689689
}
690690
#endif
691691

692-
static inline int valid_vcpu(int n)
693-
{
694-
return likely(n >= 0 && n < KVM_MAX_VCPUS);
695-
}
696-
697692
inline int kvm_is_mmio_pfn(pfn_t pfn)
698693
{
699694
if (pfn_valid(pfn)) {
@@ -1714,24 +1709,18 @@ static struct file_operations kvm_vcpu_fops = {
17141709
*/
17151710
static int create_vcpu_fd(struct kvm_vcpu *vcpu)
17161711
{
1717-
int fd = anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
1718-
if (fd < 0)
1719-
kvm_put_kvm(vcpu->kvm);
1720-
return fd;
1712+
return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
17211713
}
17221714

17231715
/*
17241716
* Creates some virtual cpus. Good luck creating more than one.
17251717
*/
1726-
static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
1718+
static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
17271719
{
17281720
int r;
17291721
struct kvm_vcpu *vcpu;
17301722

1731-
if (!valid_vcpu(n))
1732-
return -EINVAL;
1733-
1734-
vcpu = kvm_arch_vcpu_create(kvm, n);
1723+
vcpu = kvm_arch_vcpu_create(kvm, id);
17351724
if (IS_ERR(vcpu))
17361725
return PTR_ERR(vcpu);
17371726

@@ -1742,25 +1731,38 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
17421731
return r;
17431732

17441733
mutex_lock(&kvm->lock);
1745-
if (kvm->vcpus[n]) {
1746-
r = -EEXIST;
1734+
if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) {
1735+
r = -EINVAL;
17471736
goto vcpu_destroy;
17481737
}
1749-
kvm->vcpus[n] = vcpu;
1750-
if (n == 0)
1751-
kvm->bsp_vcpu = vcpu;
1752-
mutex_unlock(&kvm->lock);
1738+
1739+
for (r = 0; r < atomic_read(&kvm->online_vcpus); r++)
1740+
if (kvm->vcpus[r]->vcpu_id == id) {
1741+
r = -EEXIST;
1742+
goto vcpu_destroy;
1743+
}
1744+
1745+
BUG_ON(kvm->vcpus[atomic_read(&kvm->online_vcpus)]);
17531746

17541747
/* Now it's all set up, let userspace reach it */
17551748
kvm_get_kvm(kvm);
17561749
r = create_vcpu_fd(vcpu);
1757-
if (r < 0)
1758-
goto unlink;
1750+
if (r < 0) {
1751+
kvm_put_kvm(kvm);
1752+
goto vcpu_destroy;
1753+
}
1754+
1755+
kvm->vcpus[atomic_read(&kvm->online_vcpus)] = vcpu;
1756+
smp_wmb();
1757+
atomic_inc(&kvm->online_vcpus);
1758+
1759+
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
1760+
if (kvm->bsp_vcpu_id == id)
1761+
kvm->bsp_vcpu = vcpu;
1762+
#endif
1763+
mutex_unlock(&kvm->lock);
17591764
return r;
17601765

1761-
unlink:
1762-
mutex_lock(&kvm->lock);
1763-
kvm->vcpus[n] = NULL;
17641766
vcpu_destroy:
17651767
mutex_unlock(&kvm->lock);
17661768
kvm_arch_vcpu_destroy(vcpu);
@@ -2233,6 +2235,15 @@ static long kvm_vm_ioctl(struct file *filp,
22332235
r = kvm_irqfd(kvm, data.fd, data.gsi, data.flags);
22342236
break;
22352237
}
2238+
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
2239+
case KVM_SET_BOOT_CPU_ID:
2240+
r = 0;
2241+
if (atomic_read(&kvm->online_vcpus) != 0)
2242+
r = -EBUSY;
2243+
else
2244+
kvm->bsp_vcpu_id = arg;
2245+
break;
2246+
#endif
22362247
default:
22372248
r = kvm_arch_vm_ioctl(filp, ioctl, arg);
22382249
}
@@ -2299,6 +2310,9 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
22992310
case KVM_CAP_USER_MEMORY:
23002311
case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
23012312
case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
2313+
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
2314+
case KVM_CAP_SET_BOOT_CPU_ID:
2315+
#endif
23022316
return 1;
23032317
#ifdef CONFIG_HAVE_KVM_IRQCHIP
23042318
case KVM_CAP_IRQ_ROUTING:

0 commit comments

Comments
 (0)