static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { struct kvm_mmio_req *p; struct kvm_io_device *mmio_dev; int r; p = kvm_get_vcpu_ioreq(vcpu); if ((p->addr & PAGE_MASK) == IOAPIC_DEFAULT_BASE_ADDRESS) goto mmio; vcpu->mmio_needed = 1; vcpu->mmio_phys_addr = kvm_run->mmio.phys_addr = p->addr; vcpu->mmio_size = kvm_run->mmio.len = p->size; vcpu->mmio_is_write = kvm_run->mmio.is_write = !p->dir; if (vcpu->mmio_is_write) memcpy(vcpu->mmio_data, &p->data, p->size); memcpy(kvm_run->mmio.data, &p->data, p->size); kvm_run->exit_reason = KVM_EXIT_MMIO; return 0; mmio: if (p->dir) r = kvm_io_bus_read(&vcpu->kvm->mmio_bus, p->addr, p->size, &p->data); else r = kvm_io_bus_write(&vcpu->kvm->mmio_bus, p->addr, p->size, &p->data); if (r) printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr); p->state = STATE_IORESP_READY; return 1; }
int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, phys_addr_t fault_ipa) { unsigned long data; unsigned long rt; int ret; bool is_write; int len; u8 data_buf[8]; /* * Prepare MMIO operation. First decode the syndrome data we get * from the CPU. Then try if some in-kernel emulation feels * responsible, otherwise let user space do its magic. */ if (kvm_vcpu_dabt_isvalid(vcpu)) { ret = decode_hsr(vcpu, &is_write, &len); if (ret) return ret; } else { kvm_err("load/store instruction decoding not implemented\n"); return -ENOSYS; } rt = vcpu->arch.mmio_decode.rt; if (is_write) { data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt), len); trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data); mmio_write_buf(data_buf, len, data); ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len, data_buf); } else { trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len, fault_ipa, 0); ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len, data_buf); } /* Now prepare kvm_run for the potential return to userland. */ run->mmio.is_write = is_write; run->mmio.phys_addr = fault_ipa; run->mmio.len = len; memcpy(run->mmio.data, data_buf, len); if (!ret) { /* We handled the access successfully in the kernel. */ kvm_handle_mmio_return(vcpu, run); return 1; } run->exit_reason = KVM_EXIT_MMIO; return 0; }
int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, u64 val, unsigned int bytes, int is_default_endian) { void *data = run->mmio.data; int idx, ret; int is_bigendian; if (kvmppc_need_byteswap(vcpu)) { /* Default endianness is "little endian". */ is_bigendian = !is_default_endian; } else { /* Default endianness is "big endian". */ is_bigendian = is_default_endian; } if (bytes > sizeof(run->mmio.data)) { printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, run->mmio.len); } run->mmio.phys_addr = vcpu->arch.paddr_accessed; run->mmio.len = bytes; run->mmio.is_write = 1; vcpu->mmio_needed = 1; vcpu->mmio_is_write = 1; /* Store the value at the lowest bytes in 'data'. */ if (is_bigendian) { switch (bytes) { case 8: *(u64 *)data = val; break; case 4: *(u32 *)data = val; break; case 2: *(u16 *)data = val; break; case 1: *(u8 *)data = val; break; } } else { /* Store LE value into 'data'. */ switch (bytes) { case 4: st_le32(data, val); break; case 2: st_le16(data, val); break; case 1: *(u8 *)data = val; break; } } idx = srcu_read_lock(&vcpu->kvm->srcu); ret = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr, bytes, &run->mmio.data); srcu_read_unlock(&vcpu->kvm->srcu, idx); if (!ret) { vcpu->mmio_needed = 0; return EMULATE_DONE; } return EMULATE_DO_MMIO; }
int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, u64 val, unsigned int bytes, int is_default_endian) { void *data = run->mmio.data; int idx, ret; bool host_swabbed; /* Pity C doesn't have a logical XOR operator */ if (kvmppc_need_byteswap(vcpu)) { host_swabbed = is_default_endian; } else { host_swabbed = !is_default_endian; } if (bytes > sizeof(run->mmio.data)) { printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, run->mmio.len); } run->mmio.phys_addr = vcpu->arch.paddr_accessed; run->mmio.len = bytes; run->mmio.is_write = 1; vcpu->mmio_needed = 1; vcpu->mmio_is_write = 1; /* Store the value at the lowest bytes in 'data'. */ if (!host_swabbed) { switch (bytes) { case 8: *(u64 *)data = val; break; case 4: *(u32 *)data = val; break; case 2: *(u16 *)data = val; break; case 1: *(u8 *)data = val; break; } } else { switch (bytes) { case 8: *(u64 *)data = swab64(val); break; case 4: *(u32 *)data = swab32(val); break; case 2: *(u16 *)data = swab16(val); break; case 1: *(u8 *)data = val; break; } } idx = srcu_read_lock(&vcpu->kvm->srcu); ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr, bytes, &run->mmio.data); srcu_read_unlock(&vcpu->kvm->srcu, idx); if (!ret) { vcpu->mmio_needed = 0; return EMULATE_DONE; } return EMULATE_DO_MMIO; }
int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, u64 val, unsigned int bytes, int is_bigendian) { void *data = run->mmio.data; if (bytes > sizeof(run->mmio.data)) { printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, run->mmio.len); } run->mmio.phys_addr = vcpu->arch.paddr_accessed; run->mmio.len = bytes; run->mmio.is_write = 1; vcpu->mmio_needed = 1; vcpu->mmio_is_write = 1; /* Store the value at the lowest bytes in 'data'. */ if (is_bigendian) { switch (bytes) { case 8: *(u64 *)data = val; break; case 4: *(u32 *)data = val; break; case 2: *(u16 *)data = val; break; case 1: *(u8 *)data = val; break; } } else { /* Store LE value into 'data'. */ switch (bytes) { case 4: st_le32(data, val); break; case 2: st_le16(data, val); break; case 1: *(u8 *)data = val; break; } } if (!kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr, bytes, &run->mmio.data)) { kvmppc_complete_mmio_load(vcpu, run); vcpu->mmio_needed = 0; return EMULATE_DONE; } return EMULATE_DO_MMIO; }