diff options
author | Avi Kivity <avi@qumranet.com> | 2007-10-21 05:00:39 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:55 -0500 |
commit | e00c8cf29b9798eb9918469b0cce1766e0ae40d7 (patch) | |
tree | 2824cf4bfffc96faeda6981a790295c2e4f49690 | |
parent | 34c16eecf78ed4cf01f39ac7211f5b57942ec899 (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>
-rw-r--r-- | drivers/kvm/kvm.h | 2 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 8 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 4 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 178 |
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 | ||
560 | static void svm_vcpu_reset(struct kvm_vcpu *vcpu) | 560 | static 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 | ||
573 | static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) | 575 | static 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 | |||
1530 | static 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 | ||
1631 | static 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 | |||
1638 | static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) | 1638 | static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) |
1639 | { | 1639 | { |
1640 | u16 ent[2]; | 1640 | u16 ent[2]; |