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 /drivers/kvm/vmx.c | |
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>
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r-- | drivers/kvm/vmx.c | 178 |
1 files changed, 89 insertions, 89 deletions
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]; |