aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-06-09 08:56:28 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:32:52 -0400
commit73880c80aa9c8dc353cd0ad26579023213cd5314 (patch)
treed5bee5c87c3468feb941cc898e342f52c0adce19
parent1ed0ce000a6c20c36ec649e32fc24393ef418ed8 (diff)
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 <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/ia64/include/asm/kvm_host.h1
-rw-r--r--arch/ia64/kvm/Kconfig1
-rw-r--r--arch/ia64/kvm/kvm-ia64.c8
-rw-r--r--arch/ia64/kvm/vcpu.c2
-rw-r--r--arch/x86/kvm/Kconfig1
-rw-r--r--include/linux/kvm.h2
-rw-r--r--include/linux/kvm_host.h6
-rw-r--r--virt/kvm/Kconfig3
-rw-r--r--virt/kvm/kvm_main.c64
9 files changed, 55 insertions, 33 deletions
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h
index 5f43697aed30..9cf1c4b1f92f 100644
--- a/arch/ia64/include/asm/kvm_host.h
+++ b/arch/ia64/include/asm/kvm_host.h
@@ -465,7 +465,6 @@ struct kvm_arch {
465 unsigned long metaphysical_rr4; 465 unsigned long metaphysical_rr4;
466 unsigned long vmm_init_rr; 466 unsigned long vmm_init_rr;
467 467
468 int online_vcpus;
469 int is_sn2; 468 int is_sn2;
470 469
471 struct kvm_ioapic *vioapic; 470 struct kvm_ioapic *vioapic;
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index f922bbba3797..cbadd8a65233 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -25,6 +25,7 @@ config KVM
25 select PREEMPT_NOTIFIERS 25 select PREEMPT_NOTIFIERS
26 select ANON_INODES 26 select ANON_INODES
27 select HAVE_KVM_IRQCHIP 27 select HAVE_KVM_IRQCHIP
28 select KVM_APIC_ARCHITECTURE
28 ---help--- 29 ---help---
29 Support hosting fully virtualized guest machines using hardware 30 Support hosting fully virtualized guest machines using hardware
30 virtualization extensions. You will need a fairly recent 31 virtualization extensions. You will need a fairly recent
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 4082665ace0a..d1f7bcda2c7f 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -338,7 +338,7 @@ static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,
338 union ia64_lid lid; 338 union ia64_lid lid;
339 int i; 339 int i;
340 340
341 for (i = 0; i < kvm->arch.online_vcpus; i++) { 341 for (i = 0; i < atomic_read(&kvm->online_vcpus); i++) {
342 if (kvm->vcpus[i]) { 342 if (kvm->vcpus[i]) {
343 lid.val = VCPU_LID(kvm->vcpus[i]); 343 lid.val = VCPU_LID(kvm->vcpus[i]);
344 if (lid.id == id && lid.eid == eid) 344 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)
412 412
413 call_data.ptc_g_data = p->u.ptc_g_data; 413 call_data.ptc_g_data = p->u.ptc_g_data;
414 414
415 for (i = 0; i < kvm->arch.online_vcpus; i++) { 415 for (i = 0; i < atomic_read(&kvm->online_vcpus); i++) {
416 if (!kvm->vcpus[i] || kvm->vcpus[i]->arch.mp_state == 416 if (!kvm->vcpus[i] || kvm->vcpus[i]->arch.mp_state ==
417 KVM_MP_STATE_UNINITIALIZED || 417 KVM_MP_STATE_UNINITIALIZED ||
418 vcpu == kvm->vcpus[i]) 418 vcpu == kvm->vcpus[i])
@@ -852,8 +852,6 @@ struct kvm *kvm_arch_create_vm(void)
852 852
853 kvm_init_vm(kvm); 853 kvm_init_vm(kvm);
854 854
855 kvm->arch.online_vcpus = 0;
856
857 return kvm; 855 return kvm;
858 856
859} 857}
@@ -1356,8 +1354,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
1356 goto fail; 1354 goto fail;
1357 } 1355 }
1358 1356
1359 kvm->arch.online_vcpus++;
1360
1361 return vcpu; 1357 return vcpu;
1362fail: 1358fail:
1363 return ERR_PTR(r); 1359 return ERR_PTR(r);
diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c
index 61a3320b62c1..dce75b70cdd5 100644
--- a/arch/ia64/kvm/vcpu.c
+++ b/arch/ia64/kvm/vcpu.c
@@ -831,7 +831,7 @@ static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val)
831 kvm = (struct kvm *)KVM_VM_BASE; 831 kvm = (struct kvm *)KVM_VM_BASE;
832 832
833 if (kvm_vcpu_is_bsp(vcpu)) { 833 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++) {
835 v = (struct kvm_vcpu *)((char *)vcpu + 835 v = (struct kvm_vcpu *)((char *)vcpu +
836 sizeof(struct kvm_vcpu_data) * i); 836 sizeof(struct kvm_vcpu_data) * i);
837 VMX(v, itc_offset) = itc_offset; 837 VMX(v, itc_offset) = itc_offset;
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 8cd2a4efe238..7fbedfd34d6c 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -27,6 +27,7 @@ config KVM
27 select ANON_INODES 27 select ANON_INODES
28 select HAVE_KVM_IRQCHIP 28 select HAVE_KVM_IRQCHIP
29 select HAVE_KVM_EVENTFD 29 select HAVE_KVM_EVENTFD
30 select KVM_APIC_ARCHITECTURE
30 ---help--- 31 ---help---
31 Support hosting fully virtualized guest machines using hardware 32 Support hosting fully virtualized guest machines using hardware
32 virtualization extensions. You will need a fairly recent 33 virtualization extensions. You will need a fairly recent
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index f1dada0519eb..5037e170a70d 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -430,6 +430,7 @@ struct kvm_trace_rec {
430#ifdef __KVM_HAVE_PIT 430#ifdef __KVM_HAVE_PIT
431#define KVM_CAP_PIT2 33 431#define KVM_CAP_PIT2 33
432#endif 432#endif
433#define KVM_CAP_SET_BOOT_CPU_ID 34
433 434
434#ifdef KVM_CAP_IRQ_ROUTING 435#ifdef KVM_CAP_IRQ_ROUTING
435 436
@@ -537,6 +538,7 @@ struct kvm_irqfd {
537#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq) 538#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
538#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd) 539#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)
539#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config) 540#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
541#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
540 542
541/* 543/*
542 * ioctls for vcpu fds 544 * ioctls for vcpu fds
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a5bd429e9bd3..d3fdf1a738c9 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -131,8 +131,12 @@ struct kvm {
131 int nmemslots; 131 int nmemslots;
132 struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS + 132 struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS +
133 KVM_PRIVATE_MEM_SLOTS]; 133 KVM_PRIVATE_MEM_SLOTS];
134#ifdef CONFIG_KVM_APIC_ARCHITECTURE
135 u32 bsp_vcpu_id;
134 struct kvm_vcpu *bsp_vcpu; 136 struct kvm_vcpu *bsp_vcpu;
137#endif
135 struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; 138 struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
139 atomic_t online_vcpus;
136 struct list_head vm_list; 140 struct list_head vm_list;
137 struct mutex lock; 141 struct mutex lock;
138 struct kvm_io_bus mmio_bus; 142 struct kvm_io_bus mmio_bus;
@@ -550,8 +554,10 @@ static inline void kvm_irqfd_release(struct kvm *kvm) {}
550 554
551#endif /* CONFIG_HAVE_KVM_EVENTFD */ 555#endif /* CONFIG_HAVE_KVM_EVENTFD */
552 556
557#ifdef CONFIG_KVM_APIC_ARCHITECTURE
553static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu) 558static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
554{ 559{
555 return vcpu->kvm->bsp_vcpu == vcpu; 560 return vcpu->kvm->bsp_vcpu == vcpu;
556} 561}
557#endif 562#endif
563#endif
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index 56c6848d2df8..daece36c0a57 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -9,3 +9,6 @@ config HAVE_KVM_IRQCHIP
9config HAVE_KVM_EVENTFD 9config HAVE_KVM_EVENTFD
10 bool 10 bool
11 select EVENTFD 11 select EVENTFD
12
13config KVM_APIC_ARCHITECTURE
14 bool
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 0d54edecbc70..25e1f9c97b1a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -689,11 +689,6 @@ out:
689} 689}
690#endif 690#endif
691 691
692static inline int valid_vcpu(int n)
693{
694 return likely(n >= 0 && n < KVM_MAX_VCPUS);
695}
696
697inline int kvm_is_mmio_pfn(pfn_t pfn) 692inline int kvm_is_mmio_pfn(pfn_t pfn)
698{ 693{
699 if (pfn_valid(pfn)) { 694 if (pfn_valid(pfn)) {
@@ -1714,24 +1709,18 @@ static struct file_operations kvm_vcpu_fops = {
1714 */ 1709 */
1715static int create_vcpu_fd(struct kvm_vcpu *vcpu) 1710static int create_vcpu_fd(struct kvm_vcpu *vcpu)
1716{ 1711{
1717 int fd = anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0); 1712 return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
1718 if (fd < 0)
1719 kvm_put_kvm(vcpu->kvm);
1720 return fd;
1721} 1713}
1722 1714
1723/* 1715/*
1724 * Creates some virtual cpus. Good luck creating more than one. 1716 * Creates some virtual cpus. Good luck creating more than one.
1725 */ 1717 */
1726static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n) 1718static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
1727{ 1719{
1728 int r; 1720 int r;
1729 struct kvm_vcpu *vcpu; 1721 struct kvm_vcpu *vcpu;
1730 1722
1731 if (!valid_vcpu(n)) 1723 vcpu = kvm_arch_vcpu_create(kvm, id);
1732 return -EINVAL;
1733
1734 vcpu = kvm_arch_vcpu_create(kvm, n);
1735 if (IS_ERR(vcpu)) 1724 if (IS_ERR(vcpu))
1736 return PTR_ERR(vcpu); 1725 return PTR_ERR(vcpu);
1737 1726
@@ -1742,25 +1731,38 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
1742 return r; 1731 return r;
1743 1732
1744 mutex_lock(&kvm->lock); 1733 mutex_lock(&kvm->lock);
1745 if (kvm->vcpus[n]) { 1734 if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) {
1746 r = -EEXIST; 1735 r = -EINVAL;
1747 goto vcpu_destroy; 1736 goto vcpu_destroy;
1748 } 1737 }
1749 kvm->vcpus[n] = vcpu; 1738
1750 if (n == 0) 1739 for (r = 0; r < atomic_read(&kvm->online_vcpus); r++)
1751 kvm->bsp_vcpu = vcpu; 1740 if (kvm->vcpus[r]->vcpu_id == id) {
1752 mutex_unlock(&kvm->lock); 1741 r = -EEXIST;
1742 goto vcpu_destroy;
1743 }
1744
1745 BUG_ON(kvm->vcpus[atomic_read(&kvm->online_vcpus)]);
1753 1746
1754 /* Now it's all set up, let userspace reach it */ 1747 /* Now it's all set up, let userspace reach it */
1755 kvm_get_kvm(kvm); 1748 kvm_get_kvm(kvm);
1756 r = create_vcpu_fd(vcpu); 1749 r = create_vcpu_fd(vcpu);
1757 if (r < 0) 1750 if (r < 0) {
1758 goto unlink; 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);
1759 return r; 1764 return r;
1760 1765
1761unlink:
1762 mutex_lock(&kvm->lock);
1763 kvm->vcpus[n] = NULL;
1764vcpu_destroy: 1766vcpu_destroy:
1765 mutex_unlock(&kvm->lock); 1767 mutex_unlock(&kvm->lock);
1766 kvm_arch_vcpu_destroy(vcpu); 1768 kvm_arch_vcpu_destroy(vcpu);
@@ -2233,6 +2235,15 @@ static long kvm_vm_ioctl(struct file *filp,
2233 r = kvm_irqfd(kvm, data.fd, data.gsi, data.flags); 2235 r = kvm_irqfd(kvm, data.fd, data.gsi, data.flags);
2234 break; 2236 break;
2235 } 2237 }
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
2236 default: 2247 default:
2237 r = kvm_arch_vm_ioctl(filp, ioctl, arg); 2248 r = kvm_arch_vm_ioctl(filp, ioctl, arg);
2238 } 2249 }
@@ -2299,6 +2310,9 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
2299 case KVM_CAP_USER_MEMORY: 2310 case KVM_CAP_USER_MEMORY:
2300 case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: 2311 case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
2301 case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS: 2312 case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
2313#ifdef CONFIG_KVM_APIC_ARCHITECTURE
2314 case KVM_CAP_SET_BOOT_CPU_ID:
2315#endif
2302 return 1; 2316 return 1;
2303#ifdef CONFIG_HAVE_KVM_IRQCHIP 2317#ifdef CONFIG_HAVE_KVM_IRQCHIP
2304 case KVM_CAP_IRQ_ROUTING: 2318 case KVM_CAP_IRQ_ROUTING: