Deleted Added
full compact
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 ---