switch (len) { case 1: return data & 0xff; case 2: return data & 0xffff; case 4: return data & 0xffffffff; case 8: return data; default:
kvm_err("%s: unknown data len: %d\n", __func__, len); return 0;
}
}
staticvoid write_mailbox(struct kvm_vcpu *vcpu, int offset, uint64_t data, int len)
{ void *pbuf;
switch (len) { case 1:
*(unsignedchar *)pbuf = (unsignedchar)data; break; case 2:
*(unsignedshort *)pbuf = (unsignedshort)data; break; case 4:
*(unsignedint *)pbuf = (unsignedint)data; break; case 8:
*(unsignedlong *)pbuf = (unsignedlong)data; break; default:
kvm_err("%s: unknown data len: %d\n", __func__, len);
}
spin_unlock(&vcpu->arch.ipi_state.lock);
}
staticint send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
{ int i, idx, ret;
uint64_t val = 0, mask = 0;
/* * Bit 27-30 is mask for byte writing. * If the mask is 0, we need not to do anything.
*/ if ((data >> 27) & 0xf) { /* Read the old val */
idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, 4, &val);
srcu_read_unlock(&vcpu->kvm->srcu, idx); if (unlikely(ret)) {
kvm_err("%s: : read data from addr %llx failed\n", __func__, addr); return ret;
} /* Construct the mask by scanning the bit 27-30 */ for (i = 0; i < 4; i++) { if (data & (BIT(27 + i)))
mask |= (0xff << (i * 8));
} /* Save the old part of val */
val &= mask;
}
val |= ((uint32_t)(data >> 32) & ~mask);
idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, 4, &val);
srcu_read_unlock(&vcpu->kvm->srcu, idx); if (unlikely(ret))
kvm_err("%s: : write data to addr %llx failed\n", __func__, addr);
switch (offset) { case IOCSR_IPI_STATUS:
ret = -EINVAL; break; case IOCSR_IPI_EN:
spin_lock(&vcpu->arch.ipi_state.lock);
vcpu->arch.ipi_state.en = data;
spin_unlock(&vcpu->arch.ipi_state.lock); break; case IOCSR_IPI_SET:
ret = -EINVAL; break; case IOCSR_IPI_CLEAR: /* Just clear the status of the current vcpu */
ipi_clear(vcpu, data); break; case IOCSR_IPI_BUF_20 ... IOCSR_IPI_BUF_38 + 7: if (offset + len > IOCSR_IPI_BUF_38 + 8) {
kvm_err("%s: invalid offset or len: offset = %d, len = %d\n",
__func__, offset, len);
ret = -EINVAL; break;
}
write_mailbox(vcpu, offset, data, len); break; case IOCSR_IPI_SEND:
ipi_send(vcpu->kvm, data); break; case IOCSR_MAIL_SEND:
ret = mail_send(vcpu->kvm, *(uint64_t *)val); break; case IOCSR_ANY_SEND:
ret = any_send(vcpu->kvm, *(uint64_t *)val); break; default:
kvm_err("%s: unknown addr: %llx\n", __func__, addr);
ret = -EINVAL; break;
}
switch (addr) { case IOCSR_IPI_STATUS:
p = &vcpu->arch.ipi_state.status; break; case IOCSR_IPI_EN:
p = &vcpu->arch.ipi_state.en; break; case IOCSR_IPI_SET:
p = &vcpu->arch.ipi_state.set; break; case IOCSR_IPI_CLEAR:
p = &vcpu->arch.ipi_state.clear; break; case IOCSR_IPI_BUF_20:
p = &vcpu->arch.ipi_state.buf[0];
len = 8; break; case IOCSR_IPI_BUF_28:
p = &vcpu->arch.ipi_state.buf[1];
len = 8; break; case IOCSR_IPI_BUF_30:
p = &vcpu->arch.ipi_state.buf[2];
len = 8; break; case IOCSR_IPI_BUF_38:
p = &vcpu->arch.ipi_state.buf[3];
len = 8; break; default:
kvm_err("%s: unknown ipi register, addr = %d\n", __func__, addr); return -EINVAL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.