Skip to content

Commit 8e30542

Browse files
lixianglaichenhuacai
authored andcommitted
LoongArch: KVM: Add IPI user mode read and write function
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 <[email protected]> Signed-off-by: Tianrui Zhao <[email protected]> Signed-off-by: Xianglai Li <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent daee2f9 commit 8e30542

File tree

2 files changed

+92
-2
lines changed

2 files changed

+92
-2
lines changed

arch/loongarch/include/uapi/asm/kvm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,6 @@ struct kvm_iocsr_entry {
132132
#define KVM_IRQCHIP_NUM_PINS 64
133133
#define KVM_MAX_CORES 256
134134

135+
#define KVM_DEV_LOONGARCH_IPI_GRP_REGS 0x40000001
136+
135137
#endif /* __UAPI_ASM_LOONGARCH_KVM_H */

arch/loongarch/kvm/intc/ipi.c

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,16 +301,104 @@ static const struct kvm_io_device_ops kvm_ipi_ops = {
301301
.write = kvm_ipi_write,
302302
};
303303

304+
static int kvm_ipi_regs_access(struct kvm_device *dev,
305+
struct kvm_device_attr *attr,
306+
bool is_write)
307+
{
308+
int len = 4;
309+
int cpu, addr;
310+
uint64_t val;
311+
void *p = NULL;
312+
struct kvm_vcpu *vcpu;
313+
314+
cpu = (attr->attr >> 16) & 0x3ff;
315+
addr = attr->attr & 0xff;
316+
317+
vcpu = kvm_get_vcpu(dev->kvm, cpu);
318+
if (unlikely(vcpu == NULL)) {
319+
kvm_err("%s: invalid target cpu: %d\n", __func__, cpu);
320+
return -EINVAL;
321+
}
322+
323+
switch (addr) {
324+
case IOCSR_IPI_STATUS:
325+
p = &vcpu->arch.ipi_state.status;
326+
break;
327+
case IOCSR_IPI_EN:
328+
p = &vcpu->arch.ipi_state.en;
329+
break;
330+
case IOCSR_IPI_SET:
331+
p = &vcpu->arch.ipi_state.set;
332+
break;
333+
case IOCSR_IPI_CLEAR:
334+
p = &vcpu->arch.ipi_state.clear;
335+
break;
336+
case IOCSR_IPI_BUF_20:
337+
p = &vcpu->arch.ipi_state.buf[0];
338+
len = 8;
339+
break;
340+
case IOCSR_IPI_BUF_28:
341+
p = &vcpu->arch.ipi_state.buf[1];
342+
len = 8;
343+
break;
344+
case IOCSR_IPI_BUF_30:
345+
p = &vcpu->arch.ipi_state.buf[2];
346+
len = 8;
347+
break;
348+
case IOCSR_IPI_BUF_38:
349+
p = &vcpu->arch.ipi_state.buf[3];
350+
len = 8;
351+
break;
352+
default:
353+
kvm_err("%s: unknown ipi register, addr = %d\n", __func__, addr);
354+
return -EINVAL;
355+
}
356+
357+
if (is_write) {
358+
if (len == 4) {
359+
if (get_user(val, (uint32_t __user *)attr->addr))
360+
return -EFAULT;
361+
*(uint32_t *)p = (uint32_t)val;
362+
} else if (len == 8) {
363+
if (get_user(val, (uint64_t __user *)attr->addr))
364+
return -EFAULT;
365+
*(uint64_t *)p = val;
366+
}
367+
} else {
368+
if (len == 4) {
369+
val = *(uint32_t *)p;
370+
return put_user(val, (uint32_t __user *)attr->addr);
371+
} else if (len == 8) {
372+
val = *(uint64_t *)p;
373+
return put_user(val, (uint64_t __user *)attr->addr);
374+
}
375+
}
376+
377+
return 0;
378+
}
379+
304380
static int kvm_ipi_get_attr(struct kvm_device *dev,
305381
struct kvm_device_attr *attr)
306382
{
307-
return 0;
383+
switch (attr->group) {
384+
case KVM_DEV_LOONGARCH_IPI_GRP_REGS:
385+
return kvm_ipi_regs_access(dev, attr, false);
386+
default:
387+
kvm_err("%s: unknown group (%d)\n", __func__, attr->group);
388+
return -EINVAL;
389+
}
308390
}
309391

310392
static int kvm_ipi_set_attr(struct kvm_device *dev,
311393
struct kvm_device_attr *attr)
312394
{
313-
return 0;
395+
switch (attr->group) {
396+
case KVM_DEV_LOONGARCH_IPI_GRP_REGS:
397+
return kvm_ipi_regs_access(dev, attr, true);
398+
default:
399+
kvm_err("%s: unknown group (%d)\n", __func__, attr->group);
400+
return -EINVAL;
401+
}
314402
}
315403

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

0 commit comments

Comments
 (0)