vmm_instruction_emul.c (282407) | vmm_instruction_emul.c (282558) |
---|---|
1/*- 2 * Copyright (c) 2012 Sandvine, Inc. 3 * Copyright (c) 2012 NetApp, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * | 1/*- 2 * Copyright (c) 2012 Sandvine, Inc. 3 * Copyright (c) 2012 NetApp, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $FreeBSD: head/sys/amd64/vmm/vmm_instruction_emul.c 282407 2015-05-04 04:27:23Z neel $ | 27 * $FreeBSD: head/sys/amd64/vmm/vmm_instruction_emul.c 282558 2015-05-06 16:25:20Z neel $ |
28 */ 29 30#include <sys/cdefs.h> | 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/amd64/vmm/vmm_instruction_emul.c 282407 2015-05-04 04:27:23Z neel $"); | 31__FBSDID("$FreeBSD: head/sys/amd64/vmm/vmm_instruction_emul.c 282558 2015-05-06 16:25:20Z neel $"); |
32 33#ifdef _KERNEL 34#include <sys/param.h> 35#include <sys/pcpu.h> 36#include <sys/systm.h> 37#include <sys/proc.h> 38 39#include <vm/vm.h> --- 552 unchanged lines hidden (view full) --- 592 default: 593 break; 594 } 595 return (error); 596} 597 598/* 599 * Helper function to calculate and validate a linear address. | 32 33#ifdef _KERNEL 34#include <sys/param.h> 35#include <sys/pcpu.h> 36#include <sys/systm.h> 37#include <sys/proc.h> 38 39#include <vm/vm.h> --- 552 unchanged lines hidden (view full) --- 592 default: 593 break; 594 } 595 return (error); 596} 597 598/* 599 * Helper function to calculate and validate a linear address. |
600 * 601 * Returns 0 on success and 1 if an exception was injected into the guest. | |
602 */ 603static int 604get_gla(void *vm, int vcpuid, struct vie *vie, struct vm_guest_paging *paging, 605 int opsize, int addrsize, int prot, enum vm_reg_name seg, | 600 */ 601static int 602get_gla(void *vm, int vcpuid, struct vie *vie, struct vm_guest_paging *paging, 603 int opsize, int addrsize, int prot, enum vm_reg_name seg, |
606 enum vm_reg_name gpr, uint64_t *gla) | 604 enum vm_reg_name gpr, uint64_t *gla, int *fault) |
607{ 608 struct seg_desc desc; 609 uint64_t cr0, val, rflags; 610 int error; 611 612 error = vie_read_register(vm, vcpuid, VM_REG_GUEST_CR0, &cr0); 613 KASSERT(error == 0, ("%s: error %d getting cr0", __func__, error)); 614 --- 9 unchanged lines hidden (view full) --- 624 error, gpr)); 625 626 if (vie_calculate_gla(paging->cpu_mode, seg, &desc, val, opsize, 627 addrsize, prot, gla)) { 628 if (seg == VM_REG_GUEST_SS) 629 vm_inject_ss(vm, vcpuid, 0); 630 else 631 vm_inject_gp(vm, vcpuid); | 605{ 606 struct seg_desc desc; 607 uint64_t cr0, val, rflags; 608 int error; 609 610 error = vie_read_register(vm, vcpuid, VM_REG_GUEST_CR0, &cr0); 611 KASSERT(error == 0, ("%s: error %d getting cr0", __func__, error)); 612 --- 9 unchanged lines hidden (view full) --- 622 error, gpr)); 623 624 if (vie_calculate_gla(paging->cpu_mode, seg, &desc, val, opsize, 625 addrsize, prot, gla)) { 626 if (seg == VM_REG_GUEST_SS) 627 vm_inject_ss(vm, vcpuid, 0); 628 else 629 vm_inject_gp(vm, vcpuid); |
632 return (1); | 630 goto guest_fault; |
633 } 634 635 if (vie_canonical_check(paging->cpu_mode, *gla)) { 636 if (seg == VM_REG_GUEST_SS) 637 vm_inject_ss(vm, vcpuid, 0); 638 else 639 vm_inject_gp(vm, vcpuid); | 631 } 632 633 if (vie_canonical_check(paging->cpu_mode, *gla)) { 634 if (seg == VM_REG_GUEST_SS) 635 vm_inject_ss(vm, vcpuid, 0); 636 else 637 vm_inject_gp(vm, vcpuid); |
640 return (1); | 638 goto guest_fault; |
641 } 642 643 if (vie_alignment_check(paging->cpl, opsize, cr0, rflags, *gla)) { 644 vm_inject_ac(vm, vcpuid, 0); | 639 } 640 641 if (vie_alignment_check(paging->cpl, opsize, cr0, rflags, *gla)) { 642 vm_inject_ac(vm, vcpuid, 0); |
645 return (1); | 643 goto guest_fault; |
646 } 647 | 644 } 645 |
646 *fault = 0; |
|
648 return (0); | 647 return (0); |
648 649guest_fault: 650 *fault = 1; 651 return (0); |
|
649} 650 651static int 652emulate_movs(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 653 struct vm_guest_paging *paging, mem_region_read_t memread, 654 mem_region_write_t memwrite, void *arg) 655{ 656#ifdef _KERNEL 657 struct vm_copyinfo copyinfo[2]; 658#else 659 struct iovec copyinfo[2]; 660#endif 661 uint64_t dstaddr, srcaddr, dstgpa, srcgpa, val; 662 uint64_t rcx, rdi, rsi, rflags; | 652} 653 654static int 655emulate_movs(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 656 struct vm_guest_paging *paging, mem_region_read_t memread, 657 mem_region_write_t memwrite, void *arg) 658{ 659#ifdef _KERNEL 660 struct vm_copyinfo copyinfo[2]; 661#else 662 struct iovec copyinfo[2]; 663#endif 664 uint64_t dstaddr, srcaddr, dstgpa, srcgpa, val; 665 uint64_t rcx, rdi, rsi, rflags; |
663 int error, opsize, seg, repeat; | 666 int error, fault, opsize, seg, repeat; |
664 665 opsize = (vie->op.op_byte == 0xA4) ? 1 : vie->opsize; 666 val = 0; 667 error = 0; 668 669 /* 670 * XXX although the MOVS instruction is only supposed to be used with 671 * the "rep" prefix some guests like FreeBSD will use "repnz" instead. --- 6 unchanged lines hidden (view full) --- 678 if (repeat) { 679 error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RCX, &rcx); 680 KASSERT(!error, ("%s: error %d getting rcx", __func__, error)); 681 682 /* 683 * The count register is %rcx, %ecx or %cx depending on the 684 * address size of the instruction. 685 */ | 667 668 opsize = (vie->op.op_byte == 0xA4) ? 1 : vie->opsize; 669 val = 0; 670 error = 0; 671 672 /* 673 * XXX although the MOVS instruction is only supposed to be used with 674 * the "rep" prefix some guests like FreeBSD will use "repnz" instead. --- 6 unchanged lines hidden (view full) --- 681 if (repeat) { 682 error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RCX, &rcx); 683 KASSERT(!error, ("%s: error %d getting rcx", __func__, error)); 684 685 /* 686 * The count register is %rcx, %ecx or %cx depending on the 687 * address size of the instruction. 688 */ |
686 if ((rcx & vie_size2mask(vie->addrsize)) == 0) 687 return (0); | 689 if ((rcx & vie_size2mask(vie->addrsize)) == 0) { 690 error = 0; 691 goto done; 692 } |
688 } 689 690 /* 691 * Source Destination Comments 692 * -------------------------------------------- 693 * (1) memory memory n/a 694 * (2) memory mmio emulated 695 * (3) mmio memory emulated --- 4 unchanged lines hidden (view full) --- 700 * out because it will succeed only when operating on regular memory. 701 * 702 * XXX the emulation doesn't properly handle the case where 'gpa' 703 * is straddling the boundary between the normal memory and MMIO. 704 */ 705 706 seg = vie->segment_override ? vie->segment_register : VM_REG_GUEST_DS; 707 error = get_gla(vm, vcpuid, vie, paging, opsize, vie->addrsize, | 693 } 694 695 /* 696 * Source Destination Comments 697 * -------------------------------------------- 698 * (1) memory memory n/a 699 * (2) memory mmio emulated 700 * (3) mmio memory emulated --- 4 unchanged lines hidden (view full) --- 705 * out because it will succeed only when operating on regular memory. 706 * 707 * XXX the emulation doesn't properly handle the case where 'gpa' 708 * is straddling the boundary between the normal memory and MMIO. 709 */ 710 711 seg = vie->segment_override ? vie->segment_register : VM_REG_GUEST_DS; 712 error = get_gla(vm, vcpuid, vie, paging, opsize, vie->addrsize, |
708 PROT_READ, seg, VM_REG_GUEST_RSI, &srcaddr); 709 if (error) | 713 PROT_READ, seg, VM_REG_GUEST_RSI, &srcaddr, &fault); 714 if (error || fault) |
710 goto done; 711 712 error = vm_copy_setup(vm, vcpuid, paging, srcaddr, opsize, PROT_READ, | 715 goto done; 716 717 error = vm_copy_setup(vm, vcpuid, paging, srcaddr, opsize, PROT_READ, |
713 copyinfo, nitems(copyinfo)); | 718 copyinfo, nitems(copyinfo), &fault); |
714 if (error == 0) { | 719 if (error == 0) { |
720 if (fault) 721 goto done; /* Resume guest to handle fault */ 722 |
|
715 /* 716 * case (2): read from system memory and write to mmio. 717 */ 718 vm_copyin(vm, vcpuid, copyinfo, &val, opsize); 719 vm_copy_teardown(vm, vcpuid, copyinfo, nitems(copyinfo)); 720 error = memwrite(vm, vcpuid, gpa, val, opsize, arg); 721 if (error) 722 goto done; | 723 /* 724 * case (2): read from system memory and write to mmio. 725 */ 726 vm_copyin(vm, vcpuid, copyinfo, &val, opsize); 727 vm_copy_teardown(vm, vcpuid, copyinfo, nitems(copyinfo)); 728 error = memwrite(vm, vcpuid, gpa, val, opsize, arg); 729 if (error) 730 goto done; |
723 } else if (error > 0) { 724 /* 725 * Resume guest execution to handle fault. 726 */ 727 goto done; | |
728 } else { 729 /* 730 * 'vm_copy_setup()' is expected to fail for cases (3) and (4) 731 * if 'srcaddr' is in the mmio space. 732 */ 733 734 error = get_gla(vm, vcpuid, vie, paging, opsize, vie->addrsize, | 731 } else { 732 /* 733 * 'vm_copy_setup()' is expected to fail for cases (3) and (4) 734 * if 'srcaddr' is in the mmio space. 735 */ 736 737 error = get_gla(vm, vcpuid, vie, paging, opsize, vie->addrsize, |
735 PROT_WRITE, VM_REG_GUEST_ES, VM_REG_GUEST_RDI, &dstaddr); 736 if (error) | 738 PROT_WRITE, VM_REG_GUEST_ES, VM_REG_GUEST_RDI, &dstaddr, 739 &fault); 740 if (error || fault) |
737 goto done; 738 739 error = vm_copy_setup(vm, vcpuid, paging, dstaddr, opsize, | 741 goto done; 742 743 error = vm_copy_setup(vm, vcpuid, paging, dstaddr, opsize, |
740 PROT_WRITE, copyinfo, nitems(copyinfo)); | 744 PROT_WRITE, copyinfo, nitems(copyinfo), &fault); |
741 if (error == 0) { | 745 if (error == 0) { |
746 if (fault) 747 goto done; /* Resume guest to handle fault */ 748 |
|
742 /* 743 * case (3): read from MMIO and write to system memory. 744 * 745 * A MMIO read can have side-effects so we 746 * commit to it only after vm_copy_setup() is 747 * successful. If a page-fault needs to be 748 * injected into the guest then it will happen 749 * before the MMIO read is attempted. 750 */ 751 error = memread(vm, vcpuid, gpa, &val, opsize, arg); 752 if (error) 753 goto done; 754 755 vm_copyout(vm, vcpuid, &val, copyinfo, opsize); 756 vm_copy_teardown(vm, vcpuid, copyinfo, nitems(copyinfo)); | 749 /* 750 * case (3): read from MMIO and write to system memory. 751 * 752 * A MMIO read can have side-effects so we 753 * commit to it only after vm_copy_setup() is 754 * successful. If a page-fault needs to be 755 * injected into the guest then it will happen 756 * before the MMIO read is attempted. 757 */ 758 error = memread(vm, vcpuid, gpa, &val, opsize, arg); 759 if (error) 760 goto done; 761 762 vm_copyout(vm, vcpuid, &val, copyinfo, opsize); 763 vm_copy_teardown(vm, vcpuid, copyinfo, nitems(copyinfo)); |
757 } else if (error > 0) { 758 /* 759 * Resume guest execution to handle fault. 760 */ 761 goto done; | |
762 } else { 763 /* 764 * Case (4): read from and write to mmio. | 764 } else { 765 /* 766 * Case (4): read from and write to mmio. |
767 * 768 * Commit to the MMIO read/write (with potential 769 * side-effects) only after we are sure that the 770 * instruction is not going to be restarted due 771 * to address translation faults. |
|
765 */ 766 error = vm_gla2gpa(vm, vcpuid, paging, srcaddr, | 772 */ 773 error = vm_gla2gpa(vm, vcpuid, paging, srcaddr, |
767 PROT_READ, &srcgpa); 768 if (error) | 774 PROT_READ, &srcgpa, &fault); 775 if (error || fault) |
769 goto done; | 776 goto done; |
770 error = memread(vm, vcpuid, srcgpa, &val, opsize, arg); 771 if (error) 772 goto done; | |
773 774 error = vm_gla2gpa(vm, vcpuid, paging, dstaddr, | 777 778 error = vm_gla2gpa(vm, vcpuid, paging, dstaddr, |
775 PROT_WRITE, &dstgpa); | 779 PROT_WRITE, &dstgpa, &fault); 780 if (error || fault) 781 goto done; 782 783 error = memread(vm, vcpuid, srcgpa, &val, opsize, arg); |
776 if (error) 777 goto done; | 784 if (error) 785 goto done; |
786 |
|
778 error = memwrite(vm, vcpuid, dstgpa, val, opsize, arg); 779 if (error) 780 goto done; 781 } 782 } 783 784 error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RSI, &rsi); 785 KASSERT(error == 0, ("%s: error %d getting rsi", __func__, error)); --- 28 unchanged lines hidden (view full) --- 814 815 /* 816 * Repeat the instruction if the count register is not zero. 817 */ 818 if ((rcx & vie_size2mask(vie->addrsize)) != 0) 819 vm_restart_instruction(vm, vcpuid); 820 } 821done: | 787 error = memwrite(vm, vcpuid, dstgpa, val, opsize, arg); 788 if (error) 789 goto done; 790 } 791 } 792 793 error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RSI, &rsi); 794 KASSERT(error == 0, ("%s: error %d getting rsi", __func__, error)); --- 28 unchanged lines hidden (view full) --- 823 824 /* 825 * Repeat the instruction if the count register is not zero. 826 */ 827 if ((rcx & vie_size2mask(vie->addrsize)) != 0) 828 vm_restart_instruction(vm, vcpuid); 829 } 830done: |
822 if (error < 0) 823 return (EFAULT); 824 else 825 return (0); | 831 KASSERT(error == 0 || error == EFAULT, ("%s: unexpected error %d", 832 __func__, error)); 833 return (error); |
826} 827 828static int 829emulate_stos(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 830 struct vm_guest_paging *paging, mem_region_read_t memread, 831 mem_region_write_t memwrite, void *arg) 832{ 833 int error, opsize, repeat; --- 346 unchanged lines hidden (view full) --- 1180{ 1181#ifdef _KERNEL 1182 struct vm_copyinfo copyinfo[2]; 1183#else 1184 struct iovec copyinfo[2]; 1185#endif 1186 struct seg_desc ss_desc; 1187 uint64_t cr0, rflags, rsp, stack_gla, val; | 834} 835 836static int 837emulate_stos(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 838 struct vm_guest_paging *paging, mem_region_read_t memread, 839 mem_region_write_t memwrite, void *arg) 840{ 841 int error, opsize, repeat; --- 346 unchanged lines hidden (view full) --- 1188{ 1189#ifdef _KERNEL 1190 struct vm_copyinfo copyinfo[2]; 1191#else 1192 struct iovec copyinfo[2]; 1193#endif 1194 struct seg_desc ss_desc; 1195 uint64_t cr0, rflags, rsp, stack_gla, val; |
1188 int error, size, stackaddrsize, pushop; | 1196 int error, fault, size, stackaddrsize, pushop; |
1189 1190 val = 0; 1191 size = vie->opsize; 1192 pushop = (vie->op.op_type == VIE_OP_TYPE_PUSH) ? 1 : 0; 1193 1194 /* 1195 * From "Address-Size Attributes for Stack Accesses", Intel SDL, Vol 1 1196 */ --- 49 unchanged lines hidden (view full) --- 1246 } 1247 1248 if (vie_alignment_check(paging->cpl, size, cr0, rflags, stack_gla)) { 1249 vm_inject_ac(vm, vcpuid, 0); 1250 return (0); 1251 } 1252 1253 error = vm_copy_setup(vm, vcpuid, paging, stack_gla, size, | 1197 1198 val = 0; 1199 size = vie->opsize; 1200 pushop = (vie->op.op_type == VIE_OP_TYPE_PUSH) ? 1 : 0; 1201 1202 /* 1203 * From "Address-Size Attributes for Stack Accesses", Intel SDL, Vol 1 1204 */ --- 49 unchanged lines hidden (view full) --- 1254 } 1255 1256 if (vie_alignment_check(paging->cpl, size, cr0, rflags, stack_gla)) { 1257 vm_inject_ac(vm, vcpuid, 0); 1258 return (0); 1259 } 1260 1261 error = vm_copy_setup(vm, vcpuid, paging, stack_gla, size, |
1254 pushop ? PROT_WRITE : PROT_READ, copyinfo, nitems(copyinfo)); 1255 if (error == -1) { 1256 /* 1257 * XXX cannot return a negative error value here because it 1258 * ends up being the return value of the VM_RUN() ioctl and 1259 * is interpreted as a pseudo-error (for e.g. ERESTART). 1260 */ 1261 return (EFAULT); 1262 } else if (error == 1) { 1263 /* Resume guest execution to handle page fault */ 1264 return (0); 1265 } | 1262 pushop ? PROT_WRITE : PROT_READ, copyinfo, nitems(copyinfo), 1263 &fault); 1264 if (error || fault) 1265 return (error); |
1266 1267 if (pushop) { 1268 error = memread(vm, vcpuid, mmio_gpa, &val, size, arg); 1269 if (error == 0) 1270 vm_copyout(vm, vcpuid, &val, copyinfo, size); 1271 } else { 1272 vm_copyin(vm, vcpuid, copyinfo, &val, size); 1273 error = memwrite(vm, vcpuid, mmio_gpa, val, size, arg); --- 393 unchanged lines hidden (view full) --- 1667 1668 ptp_release(cookie); 1669 ptr = vm_gpa_hold(vm, ptpphys, len, VM_PROT_RW, cookie); 1670 return (ptr); 1671} 1672 1673int 1674vm_gla2gpa(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, | 1266 1267 if (pushop) { 1268 error = memread(vm, vcpuid, mmio_gpa, &val, size, arg); 1269 if (error == 0) 1270 vm_copyout(vm, vcpuid, &val, copyinfo, size); 1271 } else { 1272 vm_copyin(vm, vcpuid, copyinfo, &val, size); 1273 error = memwrite(vm, vcpuid, mmio_gpa, val, size, arg); --- 393 unchanged lines hidden (view full) --- 1667 1668 ptp_release(cookie); 1669 ptr = vm_gpa_hold(vm, ptpphys, len, VM_PROT_RW, cookie); 1670 return (ptr); 1671} 1672 1673int 1674vm_gla2gpa(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, |
1675 uint64_t gla, int prot, uint64_t *gpa) | 1675 uint64_t gla, int prot, uint64_t *gpa, int *guest_fault) |
1676{ 1677 int nlevels, pfcode, ptpshift, ptpindex, retval, usermode, writable; 1678 u_int retries; 1679 uint64_t *ptpbase, ptpphys, pte, pgsize; 1680 uint32_t *ptpbase32, pte32; 1681 void *cookie; 1682 | 1676{ 1677 int nlevels, pfcode, ptpshift, ptpindex, retval, usermode, writable; 1678 u_int retries; 1679 uint64_t *ptpbase, ptpphys, pte, pgsize; 1680 uint32_t *ptpbase32, pte32; 1681 void *cookie; 1682 |
1683 *guest_fault = 0; 1684 |
|
1683 usermode = (paging->cpl == 3 ? 1 : 0); 1684 writable = prot & VM_PROT_WRITE; 1685 cookie = NULL; 1686 retval = 0; 1687 retries = 0; 1688restart: 1689 ptpphys = paging->cr3; /* root of the page tables */ 1690 ptp_release(&cookie); --- 146 unchanged lines hidden (view full) --- 1837 goto restart; 1838 } 1839 1840 /* Zero out the lower 'ptpshift' bits and the upper 12 bits */ 1841 pte >>= ptpshift; pte <<= (ptpshift + 12); pte >>= 12; 1842 *gpa = pte | (gla & (pgsize - 1)); 1843done: 1844 ptp_release(&cookie); | 1685 usermode = (paging->cpl == 3 ? 1 : 0); 1686 writable = prot & VM_PROT_WRITE; 1687 cookie = NULL; 1688 retval = 0; 1689 retries = 0; 1690restart: 1691 ptpphys = paging->cr3; /* root of the page tables */ 1692 ptp_release(&cookie); --- 146 unchanged lines hidden (view full) --- 1839 goto restart; 1840 } 1841 1842 /* Zero out the lower 'ptpshift' bits and the upper 12 bits */ 1843 pte >>= ptpshift; pte <<= (ptpshift + 12); pte >>= 12; 1844 *gpa = pte | (gla & (pgsize - 1)); 1845done: 1846 ptp_release(&cookie); |
1847 KASSERT(retval == 0 || retval == EFAULT, ("%s: unexpected retval %d", 1848 __func__, retval)); |
|
1845 return (retval); 1846error: | 1849 return (retval); 1850error: |
1847 retval = -1; | 1851 retval = EFAULT; |
1848 goto done; 1849fault: | 1852 goto done; 1853fault: |
1850 retval = 1; | 1854 *guest_fault = 1; |
1851 goto done; 1852} 1853 1854int 1855vmm_fetch_instruction(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, | 1855 goto done; 1856} 1857 1858int 1859vmm_fetch_instruction(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, |
1856 uint64_t rip, int inst_length, struct vie *vie) | 1860 uint64_t rip, int inst_length, struct vie *vie, int *faultptr) |
1857{ 1858 struct vm_copyinfo copyinfo[2]; 1859 int error, prot; 1860 1861 if (inst_length > VIE_INST_SIZE) 1862 panic("vmm_fetch_instruction: invalid length %d", inst_length); 1863 1864 prot = PROT_READ | PROT_EXEC; 1865 error = vm_copy_setup(vm, vcpuid, paging, rip, inst_length, prot, | 1861{ 1862 struct vm_copyinfo copyinfo[2]; 1863 int error, prot; 1864 1865 if (inst_length > VIE_INST_SIZE) 1866 panic("vmm_fetch_instruction: invalid length %d", inst_length); 1867 1868 prot = PROT_READ | PROT_EXEC; 1869 error = vm_copy_setup(vm, vcpuid, paging, rip, inst_length, prot, |
1866 copyinfo, nitems(copyinfo)); 1867 if (error == 0) { 1868 vm_copyin(vm, vcpuid, copyinfo, vie->inst, inst_length); 1869 vm_copy_teardown(vm, vcpuid, copyinfo, nitems(copyinfo)); 1870 vie->num_valid = inst_length; 1871 } 1872 return (error); | 1870 copyinfo, nitems(copyinfo), faultptr); 1871 if (error || *faultptr) 1872 return (error); 1873 1874 vm_copyin(vm, vcpuid, copyinfo, vie->inst, inst_length); 1875 vm_copy_teardown(vm, vcpuid, copyinfo, nitems(copyinfo)); 1876 vie->num_valid = inst_length; 1877 return (0); |
1873} 1874 1875static int 1876vie_peek(struct vie *vie, uint8_t *x) 1877{ 1878 1879 if (vie->num_processed < vie->num_valid) { 1880 *x = vie->inst[vie->num_processed]; --- 522 unchanged lines hidden --- | 1878} 1879 1880static int 1881vie_peek(struct vie *vie, uint8_t *x) 1882{ 1883 1884 if (vie->num_processed < vie->num_valid) { 1885 *x = vie->inst[vie->num_processed]; --- 522 unchanged lines hidden --- |