Skip to content

Commit

Permalink
LoongArch: KVM: Add IPI user mode read and write function
Browse files Browse the repository at this point in the history
Implement the communication interface between the user mode programs
and the kernel in IPI interrupt controller simulation, which is used
to obtain or send the simulation data of the interrupt controller in
the user mode process, and is also used in VM migration or VM saving
and restoration.

Signed-off-by: Min Zhou <zhoumin@loongson.cn>
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
  • Loading branch information
Xianglai Li authored and Huacai Chen committed Nov 13, 2024
1 parent daee2f9 commit 8e30542
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 2 deletions.
2 changes: 2 additions & 0 deletions arch/loongarch/include/uapi/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,6 @@ struct kvm_iocsr_entry {
#define KVM_IRQCHIP_NUM_PINS 64
#define KVM_MAX_CORES 256

#define KVM_DEV_LOONGARCH_IPI_GRP_REGS 0x40000001

#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
92 changes: 90 additions & 2 deletions arch/loongarch/kvm/intc/ipi.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,16 +301,104 @@ static const struct kvm_io_device_ops kvm_ipi_ops = {
.write = kvm_ipi_write,
};

static int kvm_ipi_regs_access(struct kvm_device *dev,
struct kvm_device_attr *attr,
bool is_write)
{
int len = 4;
int cpu, addr;
uint64_t val;
void *p = NULL;
struct kvm_vcpu *vcpu;

cpu = (attr->attr >> 16) & 0x3ff;
addr = attr->attr & 0xff;

vcpu = kvm_get_vcpu(dev->kvm, cpu);
if (unlikely(vcpu == NULL)) {
kvm_err("%s: invalid target cpu: %d\n", __func__, cpu);
return -EINVAL;
}

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;
}

if (is_write) {
if (len == 4) {
if (get_user(val, (uint32_t __user *)attr->addr))
return -EFAULT;
*(uint32_t *)p = (uint32_t)val;
} else if (len == 8) {
if (get_user(val, (uint64_t __user *)attr->addr))
return -EFAULT;
*(uint64_t *)p = val;
}
} else {
if (len == 4) {
val = *(uint32_t *)p;
return put_user(val, (uint32_t __user *)attr->addr);
} else if (len == 8) {
val = *(uint64_t *)p;
return put_user(val, (uint64_t __user *)attr->addr);
}
}

return 0;
}

static int kvm_ipi_get_attr(struct kvm_device *dev,
struct kvm_device_attr *attr)
{
return 0;
switch (attr->group) {
case KVM_DEV_LOONGARCH_IPI_GRP_REGS:
return kvm_ipi_regs_access(dev, attr, false);
default:
kvm_err("%s: unknown group (%d)\n", __func__, attr->group);
return -EINVAL;
}
}

static int kvm_ipi_set_attr(struct kvm_device *dev,
struct kvm_device_attr *attr)
{
return 0;
switch (attr->group) {
case KVM_DEV_LOONGARCH_IPI_GRP_REGS:
return kvm_ipi_regs_access(dev, attr, true);
default:
kvm_err("%s: unknown group (%d)\n", __func__, attr->group);
return -EINVAL;
}
}

static int kvm_ipi_create(struct kvm_device *dev, u32 type)
Expand Down

0 comments on commit 8e30542

Please sign in to comment.