aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-10-21 05:00:39 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:55 -0500
commite00c8cf29b9798eb9918469b0cce1766e0ae40d7 (patch)
tree2824cf4bfffc96faeda6981a790295c2e4f49690 /drivers/kvm
parent34c16eecf78ed4cf01f39ac7211f5b57942ec899 (diff)
KVM: Move vmx_vcpu_reset() out of vmx_vcpu_setup()
Split guest reset code out of vmx_vcpu_setup(). Besides being cleaner, this moves the realmode tss setup (which can sleep) outside vmx_vcpu_setup() (which is executed with preemption enabled). [izik: remove unused variable] Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm')
-rw-r--r--drivers/kvm/kvm.h2
-rw-r--r--drivers/kvm/kvm_main.c8
-rw-r--r--drivers/kvm/svm.c4
-rw-r--r--drivers/kvm/vmx.c178
4 files changed, 99 insertions, 93 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index db18d278c1c0..f7181a407be1 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -412,7 +412,7 @@ struct kvm_x86_ops {
412 /* Create, but do not attach this VCPU */ 412 /* Create, but do not attach this VCPU */
413 struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned id); 413 struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned id);
414 void (*vcpu_free)(struct kvm_vcpu *vcpu); 414 void (*vcpu_free)(struct kvm_vcpu *vcpu);
415 void (*vcpu_reset)(struct kvm_vcpu *vcpu); 415 int (*vcpu_reset)(struct kvm_vcpu *vcpu);
416 416
417 void (*prepare_guest_switch)(struct kvm_vcpu *vcpu); 417 void (*prepare_guest_switch)(struct kvm_vcpu *vcpu);
418 void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu); 418 void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu);
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 0b23657f434c..a6e3165043d1 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -2122,7 +2122,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2122 pr_debug("vcpu %d received sipi with vector # %x\n", 2122 pr_debug("vcpu %d received sipi with vector # %x\n",
2123 vcpu->vcpu_id, vcpu->sipi_vector); 2123 vcpu->vcpu_id, vcpu->sipi_vector);
2124 kvm_lapic_reset(vcpu); 2124 kvm_lapic_reset(vcpu);
2125 kvm_x86_ops->vcpu_reset(vcpu); 2125 r = kvm_x86_ops->vcpu_reset(vcpu);
2126 if (r)
2127 return r;
2126 vcpu->mp_state = VCPU_MP_STATE_RUNNABLE; 2128 vcpu->mp_state = VCPU_MP_STATE_RUNNABLE;
2127 } 2129 }
2128 2130
@@ -2637,7 +2639,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
2637 BUG_ON((unsigned long)&vcpu->host_fx_image & 0xF); 2639 BUG_ON((unsigned long)&vcpu->host_fx_image & 0xF);
2638 2640
2639 vcpu_load(vcpu); 2641 vcpu_load(vcpu);
2640 r = kvm_mmu_setup(vcpu); 2642 r = kvm_x86_ops->vcpu_reset(vcpu);
2643 if (r == 0)
2644 r = kvm_mmu_setup(vcpu);
2641 vcpu_put(vcpu); 2645 vcpu_put(vcpu);
2642 if (r < 0) 2646 if (r < 0)
2643 goto free_vcpu; 2647 goto free_vcpu;
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 035c8e6898f1..953c111544e1 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -557,7 +557,7 @@ static void init_vmcb(struct vmcb *vmcb)
557 /* rdx = ?? */ 557 /* rdx = ?? */
558} 558}
559 559
560static void svm_vcpu_reset(struct kvm_vcpu *vcpu) 560static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
561{ 561{
562 struct vcpu_svm *svm = to_svm(vcpu); 562 struct vcpu_svm *svm = to_svm(vcpu);
563 563
@@ -568,6 +568,8 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu)
568 svm->vmcb->save.cs.base = svm->vcpu.sipi_vector << 12; 568 svm->vmcb->save.cs.base = svm->vcpu.sipi_vector << 12;
569 svm->vmcb->save.cs.selector = svm->vcpu.sipi_vector << 8; 569 svm->vmcb->save.cs.selector = svm->vcpu.sipi_vector << 8;
570 } 570 }
571
572 return 0;
571} 573}
572 574
573static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) 575static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 87ff35128825..768ea88beb45 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1433,92 +1433,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1433 unsigned long a; 1433 unsigned long a;
1434 struct descriptor_table dt; 1434 struct descriptor_table dt;
1435 int i; 1435 int i;
1436 int ret = 0;
1437 unsigned long kvm_vmx_return; 1436 unsigned long kvm_vmx_return;
1438 u64 msr;
1439 u32 exec_control; 1437 u32 exec_control;
1440 1438
1441 if (!init_rmode_tss(vmx->vcpu.kvm)) {
1442 ret = -ENOMEM;
1443 goto out;
1444 }
1445
1446 vmx->vcpu.rmode.active = 0;
1447
1448 vmx->vcpu.regs[VCPU_REGS_RDX] = get_rdx_init_val();
1449 set_cr8(&vmx->vcpu, 0);
1450 msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
1451 if (vmx->vcpu.vcpu_id == 0)
1452 msr |= MSR_IA32_APICBASE_BSP;
1453 kvm_set_apic_base(&vmx->vcpu, msr);
1454
1455 fx_init(&vmx->vcpu);
1456
1457 /*
1458 * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode
1459 * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4. Sigh.
1460 */
1461 if (vmx->vcpu.vcpu_id == 0) {
1462 vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
1463 vmcs_writel(GUEST_CS_BASE, 0x000f0000);
1464 } else {
1465 vmcs_write16(GUEST_CS_SELECTOR, vmx->vcpu.sipi_vector << 8);
1466 vmcs_writel(GUEST_CS_BASE, vmx->vcpu.sipi_vector << 12);
1467 }
1468 vmcs_write32(GUEST_CS_LIMIT, 0xffff);
1469 vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
1470
1471 seg_setup(VCPU_SREG_DS);
1472 seg_setup(VCPU_SREG_ES);
1473 seg_setup(VCPU_SREG_FS);
1474 seg_setup(VCPU_SREG_GS);
1475 seg_setup(VCPU_SREG_SS);
1476
1477 vmcs_write16(GUEST_TR_SELECTOR, 0);
1478 vmcs_writel(GUEST_TR_BASE, 0);
1479 vmcs_write32(GUEST_TR_LIMIT, 0xffff);
1480 vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
1481
1482 vmcs_write16(GUEST_LDTR_SELECTOR, 0);
1483 vmcs_writel(GUEST_LDTR_BASE, 0);
1484 vmcs_write32(GUEST_LDTR_LIMIT, 0xffff);
1485 vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082);
1486
1487 vmcs_write32(GUEST_SYSENTER_CS, 0);
1488 vmcs_writel(GUEST_SYSENTER_ESP, 0);
1489 vmcs_writel(GUEST_SYSENTER_EIP, 0);
1490
1491 vmcs_writel(GUEST_RFLAGS, 0x02);
1492 if (vmx->vcpu.vcpu_id == 0)
1493 vmcs_writel(GUEST_RIP, 0xfff0);
1494 else
1495 vmcs_writel(GUEST_RIP, 0);
1496 vmcs_writel(GUEST_RSP, 0);
1497
1498 /* todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0 */
1499 vmcs_writel(GUEST_DR7, 0x400);
1500
1501 vmcs_writel(GUEST_GDTR_BASE, 0);
1502 vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
1503
1504 vmcs_writel(GUEST_IDTR_BASE, 0);
1505 vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
1506
1507 vmcs_write32(GUEST_ACTIVITY_STATE, 0);
1508 vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
1509 vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0);
1510
1511 /* I/O */ 1439 /* I/O */
1512 vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a)); 1440 vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
1513 vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b)); 1441 vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
1514 1442
1515 guest_write_tsc(0);
1516
1517 vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */ 1443 vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
1518 1444
1519 /* Special registers */
1520 vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
1521
1522 /* Control */ 1445 /* Control */
1523 vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, 1446 vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
1524 vmcs_config.pin_based_exec_ctrl); 1447 vmcs_config.pin_based_exec_ctrl);
@@ -1593,13 +1516,100 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1593 ++vmx->nmsrs; 1516 ++vmx->nmsrs;
1594 } 1517 }
1595 1518
1596 setup_msrs(vmx);
1597
1598 vmcs_write32(VM_EXIT_CONTROLS, vmcs_config.vmexit_ctrl); 1519 vmcs_write32(VM_EXIT_CONTROLS, vmcs_config.vmexit_ctrl);
1599 1520
1600 /* 22.2.1, 20.8.1 */ 1521 /* 22.2.1, 20.8.1 */
1601 vmcs_write32(VM_ENTRY_CONTROLS, vmcs_config.vmentry_ctrl); 1522 vmcs_write32(VM_ENTRY_CONTROLS, vmcs_config.vmentry_ctrl);
1602 1523
1524 vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
1525 vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
1526
1527 return 0;
1528}
1529
1530static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
1531{
1532 struct vcpu_vmx *vmx = to_vmx(vcpu);
1533 u64 msr;
1534 int ret;
1535
1536 if (!init_rmode_tss(vmx->vcpu.kvm)) {
1537 ret = -ENOMEM;
1538 goto out;
1539 }
1540
1541 vmx->vcpu.rmode.active = 0;
1542
1543 vmx->vcpu.regs[VCPU_REGS_RDX] = get_rdx_init_val();
1544 set_cr8(&vmx->vcpu, 0);
1545 msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
1546 if (vmx->vcpu.vcpu_id == 0)
1547 msr |= MSR_IA32_APICBASE_BSP;
1548 kvm_set_apic_base(&vmx->vcpu, msr);
1549
1550 fx_init(&vmx->vcpu);
1551
1552 /*
1553 * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode
1554 * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4. Sigh.
1555 */
1556 if (vmx->vcpu.vcpu_id == 0) {
1557 vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
1558 vmcs_writel(GUEST_CS_BASE, 0x000f0000);
1559 } else {
1560 vmcs_write16(GUEST_CS_SELECTOR, vmx->vcpu.sipi_vector << 8);
1561 vmcs_writel(GUEST_CS_BASE, vmx->vcpu.sipi_vector << 12);
1562 }
1563 vmcs_write32(GUEST_CS_LIMIT, 0xffff);
1564 vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
1565
1566 seg_setup(VCPU_SREG_DS);
1567 seg_setup(VCPU_SREG_ES);
1568 seg_setup(VCPU_SREG_FS);
1569 seg_setup(VCPU_SREG_GS);
1570 seg_setup(VCPU_SREG_SS);
1571
1572 vmcs_write16(GUEST_TR_SELECTOR, 0);
1573 vmcs_writel(GUEST_TR_BASE, 0);
1574 vmcs_write32(GUEST_TR_LIMIT, 0xffff);
1575 vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
1576
1577 vmcs_write16(GUEST_LDTR_SELECTOR, 0);
1578 vmcs_writel(GUEST_LDTR_BASE, 0);
1579 vmcs_write32(GUEST_LDTR_LIMIT, 0xffff);
1580 vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082);
1581
1582 vmcs_write32(GUEST_SYSENTER_CS, 0);
1583 vmcs_writel(GUEST_SYSENTER_ESP, 0);
1584 vmcs_writel(GUEST_SYSENTER_EIP, 0);
1585
1586 vmcs_writel(GUEST_RFLAGS, 0x02);
1587 if (vmx->vcpu.vcpu_id == 0)
1588 vmcs_writel(GUEST_RIP, 0xfff0);
1589 else
1590 vmcs_writel(GUEST_RIP, 0);
1591 vmcs_writel(GUEST_RSP, 0);
1592
1593 /* todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0 */
1594 vmcs_writel(GUEST_DR7, 0x400);
1595
1596 vmcs_writel(GUEST_GDTR_BASE, 0);
1597 vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
1598
1599 vmcs_writel(GUEST_IDTR_BASE, 0);
1600 vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
1601
1602 vmcs_write32(GUEST_ACTIVITY_STATE, 0);
1603 vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
1604 vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0);
1605
1606 guest_write_tsc(0);
1607
1608 /* Special registers */
1609 vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
1610
1611 setup_msrs(vmx);
1612
1603 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */ 1613 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */
1604 1614
1605#ifdef CONFIG_X86_64 1615#ifdef CONFIG_X86_64
@@ -1610,9 +1620,6 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1610 vmcs_write32(TPR_THRESHOLD, 0); 1620 vmcs_write32(TPR_THRESHOLD, 0);
1611#endif 1621#endif
1612 1622
1613 vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
1614 vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
1615
1616 vmx->vcpu.cr0 = 0x60000010; 1623 vmx->vcpu.cr0 = 0x60000010;
1617 vmx_set_cr0(&vmx->vcpu, vmx->vcpu.cr0); /* enter rmode */ 1624 vmx_set_cr0(&vmx->vcpu, vmx->vcpu.cr0); /* enter rmode */
1618 vmx_set_cr4(&vmx->vcpu, 0); 1625 vmx_set_cr4(&vmx->vcpu, 0);
@@ -1628,13 +1635,6 @@ out:
1628 return ret; 1635 return ret;
1629} 1636}
1630 1637
1631static void vmx_vcpu_reset(struct kvm_vcpu *vcpu)
1632{
1633 struct vcpu_vmx *vmx = to_vmx(vcpu);
1634
1635 vmx_vcpu_setup(vmx);
1636}
1637
1638static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) 1638static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq)
1639{ 1639{
1640 u16 ent[2]; 1640 u16 ent[2];