Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/vmm/vmm.c
Show First 20 Lines • Show All 1,250 Lines • ▼ Show 20 Lines | vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu) | ||||
struct vie *vie; | struct vie *vie; | ||||
struct vcpu *vcpu; | struct vcpu *vcpu; | ||||
struct vm_exit *vme; | struct vm_exit *vme; | ||||
uint64_t gla, gpa, cs_base; | uint64_t gla, gpa, cs_base; | ||||
struct vm_guest_paging *paging; | struct vm_guest_paging *paging; | ||||
mem_region_read_t mread; | mem_region_read_t mread; | ||||
mem_region_write_t mwrite; | mem_region_write_t mwrite; | ||||
enum vm_cpu_mode cpu_mode; | enum vm_cpu_mode cpu_mode; | ||||
int cs_d, error, length; | int cs_d, error, fault, length; | ||||
vcpu = &vm->vcpu[vcpuid]; | vcpu = &vm->vcpu[vcpuid]; | ||||
vme = &vcpu->exitinfo; | vme = &vcpu->exitinfo; | ||||
gla = vme->u.inst_emul.gla; | gla = vme->u.inst_emul.gla; | ||||
gpa = vme->u.inst_emul.gpa; | gpa = vme->u.inst_emul.gpa; | ||||
cs_base = vme->u.inst_emul.cs_base; | cs_base = vme->u.inst_emul.cs_base; | ||||
cs_d = vme->u.inst_emul.cs_d; | cs_d = vme->u.inst_emul.cs_d; | ||||
vie = &vme->u.inst_emul.vie; | vie = &vme->u.inst_emul.vie; | ||||
paging = &vme->u.inst_emul.paging; | paging = &vme->u.inst_emul.paging; | ||||
cpu_mode = paging->cpu_mode; | cpu_mode = paging->cpu_mode; | ||||
VCPU_CTR1(vm, vcpuid, "inst_emul fault accessing gpa %#lx", gpa); | VCPU_CTR1(vm, vcpuid, "inst_emul fault accessing gpa %#lx", gpa); | ||||
/* Fetch, decode and emulate the faulting instruction */ | /* Fetch, decode and emulate the faulting instruction */ | ||||
if (vie->num_valid == 0) { | if (vie->num_valid == 0) { | ||||
/* | /* | ||||
* If the instruction length is not known then assume a | * If the instruction length is not known then assume a | ||||
* maximum size instruction. | * maximum size instruction. | ||||
*/ | */ | ||||
length = vme->inst_length ? vme->inst_length : VIE_INST_SIZE; | length = vme->inst_length ? vme->inst_length : VIE_INST_SIZE; | ||||
error = vmm_fetch_instruction(vm, vcpuid, paging, vme->rip + | error = vmm_fetch_instruction(vm, vcpuid, paging, vme->rip + | ||||
cs_base, length, vie); | cs_base, length, vie, &fault); | ||||
} else { | } else { | ||||
/* | /* | ||||
* The instruction bytes have already been copied into 'vie' | * The instruction bytes have already been copied into 'vie' | ||||
*/ | */ | ||||
error = 0; | error = fault = 0; | ||||
} | } | ||||
if (error == 1) | if (error || fault) | ||||
return (0); /* Resume guest to handle page fault */ | return (error); | ||||
else if (error == -1) | |||||
return (EFAULT); | |||||
else if (error != 0) | |||||
panic("%s: vmm_fetch_instruction error %d", __func__, error); | |||||
if (vmm_decode_instruction(vm, vcpuid, gla, cpu_mode, cs_d, vie) != 0) { | if (vmm_decode_instruction(vm, vcpuid, gla, cpu_mode, cs_d, vie) != 0) { | ||||
VCPU_CTR1(vm, vcpuid, "Error decoding instruction at %#lx", | VCPU_CTR1(vm, vcpuid, "Error decoding instruction at %#lx", | ||||
vme->rip + cs_base); | vme->rip + cs_base); | ||||
*retu = true; /* dump instruction bytes in userspace */ | *retu = true; /* dump instruction bytes in userspace */ | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,015 Lines • ▼ Show 20 Lines | if (copyinfo[idx].cookie != NULL) | ||||
vm_gpa_release(copyinfo[idx].cookie); | vm_gpa_release(copyinfo[idx].cookie); | ||||
} | } | ||||
bzero(copyinfo, num_copyinfo * sizeof(struct vm_copyinfo)); | bzero(copyinfo, num_copyinfo * sizeof(struct vm_copyinfo)); | ||||
} | } | ||||
int | int | ||||
vm_copy_setup(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, | vm_copy_setup(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, | ||||
uint64_t gla, size_t len, int prot, struct vm_copyinfo *copyinfo, | uint64_t gla, size_t len, int prot, struct vm_copyinfo *copyinfo, | ||||
int num_copyinfo) | int num_copyinfo, int *fault) | ||||
{ | { | ||||
int error, idx, nused; | int error, idx, nused; | ||||
size_t n, off, remaining; | size_t n, off, remaining; | ||||
void *hva, *cookie; | void *hva, *cookie; | ||||
uint64_t gpa; | uint64_t gpa; | ||||
bzero(copyinfo, sizeof(struct vm_copyinfo) * num_copyinfo); | bzero(copyinfo, sizeof(struct vm_copyinfo) * num_copyinfo); | ||||
nused = 0; | nused = 0; | ||||
remaining = len; | remaining = len; | ||||
while (remaining > 0) { | while (remaining > 0) { | ||||
KASSERT(nused < num_copyinfo, ("insufficient vm_copyinfo")); | KASSERT(nused < num_copyinfo, ("insufficient vm_copyinfo")); | ||||
error = vm_gla2gpa(vm, vcpuid, paging, gla, prot, &gpa); | error = vm_gla2gpa(vm, vcpuid, paging, gla, prot, &gpa, fault); | ||||
if (error) | if (error || *fault) | ||||
return (error); | return (error); | ||||
off = gpa & PAGE_MASK; | off = gpa & PAGE_MASK; | ||||
n = min(remaining, PAGE_SIZE - off); | n = min(remaining, PAGE_SIZE - off); | ||||
copyinfo[nused].gpa = gpa; | copyinfo[nused].gpa = gpa; | ||||
copyinfo[nused].len = n; | copyinfo[nused].len = n; | ||||
remaining -= n; | remaining -= n; | ||||
gla += n; | gla += n; | ||||
nused++; | nused++; | ||||
} | } | ||||
for (idx = 0; idx < nused; idx++) { | for (idx = 0; idx < nused; idx++) { | ||||
hva = vm_gpa_hold(vm, copyinfo[idx].gpa, copyinfo[idx].len, | hva = vm_gpa_hold(vm, copyinfo[idx].gpa, copyinfo[idx].len, | ||||
prot, &cookie); | prot, &cookie); | ||||
if (hva == NULL) | if (hva == NULL) | ||||
break; | break; | ||||
copyinfo[idx].hva = hva; | copyinfo[idx].hva = hva; | ||||
copyinfo[idx].cookie = cookie; | copyinfo[idx].cookie = cookie; | ||||
} | } | ||||
if (idx != nused) { | if (idx != nused) { | ||||
vm_copy_teardown(vm, vcpuid, copyinfo, num_copyinfo); | vm_copy_teardown(vm, vcpuid, copyinfo, num_copyinfo); | ||||
return (-1); | return (EFAULT); | ||||
} else { | } else { | ||||
*fault = 0; | |||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
vm_copyin(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo, void *kaddr, | vm_copyin(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo, void *kaddr, | ||||
size_t len) | size_t len) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |