Skip to content

Commit d206d95

Browse files
lixianglaichenhuacai
authored andcommitted
LoongArch: KVM: Add PCHPIC user mode read and write functions
Implement the communication interface between the user mode programs and the kernel in PCHPIC interrupt control 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: Tianrui Zhao <[email protected]> Signed-off-by: Xianglai Li <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent f5f31ef commit d206d95

File tree

2 files changed

+123
-2
lines changed

2 files changed

+123
-2
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,8 @@ struct kvm_iocsr_entry {
146146
#define KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE 0x1
147147
#define KVM_DEV_LOONGARCH_EXTIOI_CTRL_LOAD_FINISHED 0x3
148148

149+
#define KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS 0x40000005
150+
#define KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL 0x40000006
151+
#define KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT 0
152+
149153
#endif /* __UAPI_ASM_LOONGARCH_KVM_H */

arch/loongarch/kvm/intc/pch_pic.c

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,16 +314,133 @@ static const struct kvm_io_device_ops kvm_pch_pic_ops = {
314314
.write = kvm_pch_pic_write,
315315
};
316316

317+
static int kvm_pch_pic_init(struct kvm_device *dev, u64 addr)
318+
{
319+
int ret;
320+
struct kvm *kvm = dev->kvm;
321+
struct kvm_io_device *device;
322+
struct loongarch_pch_pic *s = dev->kvm->arch.pch_pic;
323+
324+
s->pch_pic_base = addr;
325+
device = &s->device;
326+
/* init device by pch pic writing and reading ops */
327+
kvm_iodevice_init(device, &kvm_pch_pic_ops);
328+
mutex_lock(&kvm->slots_lock);
329+
/* register pch pic device */
330+
ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, addr, PCH_PIC_SIZE, device);
331+
mutex_unlock(&kvm->slots_lock);
332+
333+
return (ret < 0) ? -EFAULT : 0;
334+
}
335+
336+
/* used by user space to get or set pch pic registers */
337+
static int kvm_pch_pic_regs_access(struct kvm_device *dev,
338+
struct kvm_device_attr *attr,
339+
bool is_write)
340+
{
341+
int addr, offset, len = 8, ret = 0;
342+
void __user *data;
343+
void *p = NULL;
344+
struct loongarch_pch_pic *s;
345+
346+
s = dev->kvm->arch.pch_pic;
347+
addr = attr->attr;
348+
data = (void __user *)attr->addr;
349+
350+
/* get pointer to pch pic register by addr */
351+
switch (addr) {
352+
case PCH_PIC_MASK_START:
353+
p = &s->mask;
354+
break;
355+
case PCH_PIC_HTMSI_EN_START:
356+
p = &s->htmsi_en;
357+
break;
358+
case PCH_PIC_EDGE_START:
359+
p = &s->edge;
360+
break;
361+
case PCH_PIC_AUTO_CTRL0_START:
362+
p = &s->auto_ctrl0;
363+
break;
364+
case PCH_PIC_AUTO_CTRL1_START:
365+
p = &s->auto_ctrl1;
366+
break;
367+
case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END:
368+
offset = addr - PCH_PIC_ROUTE_ENTRY_START;
369+
p = &s->route_entry[offset];
370+
len = 1;
371+
break;
372+
case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END:
373+
offset = addr - PCH_PIC_HTMSI_VEC_START;
374+
p = &s->htmsi_vector[offset];
375+
len = 1;
376+
break;
377+
case PCH_PIC_INT_IRR_START:
378+
p = &s->irr;
379+
break;
380+
case PCH_PIC_INT_ISR_START:
381+
p = &s->isr;
382+
break;
383+
case PCH_PIC_POLARITY_START:
384+
p = &s->polarity;
385+
break;
386+
default:
387+
return -EINVAL;
388+
}
389+
390+
spin_lock(&s->lock);
391+
/* write or read value according to is_write */
392+
if (is_write) {
393+
if (copy_from_user(p, data, len))
394+
ret = -EFAULT;
395+
} else {
396+
if (copy_to_user(data, p, len))
397+
ret = -EFAULT;
398+
}
399+
spin_unlock(&s->lock);
400+
401+
return ret;
402+
}
403+
317404
static int kvm_pch_pic_get_attr(struct kvm_device *dev,
318405
struct kvm_device_attr *attr)
319406
{
320-
return 0;
407+
switch (attr->group) {
408+
case KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS:
409+
return kvm_pch_pic_regs_access(dev, attr, false);
410+
default:
411+
return -EINVAL;
412+
}
321413
}
322414

323415
static int kvm_pch_pic_set_attr(struct kvm_device *dev,
324416
struct kvm_device_attr *attr)
325417
{
326-
return 0;
418+
u64 addr;
419+
void __user *uaddr = (void __user *)(long)attr->addr;
420+
421+
switch (attr->group) {
422+
case KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL:
423+
switch (attr->attr) {
424+
case KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT:
425+
if (copy_from_user(&addr, uaddr, sizeof(addr)))
426+
return -EFAULT;
427+
428+
if (!dev->kvm->arch.pch_pic) {
429+
kvm_err("%s: please create pch_pic irqchip first!\n", __func__);
430+
return -ENODEV;
431+
}
432+
433+
return kvm_pch_pic_init(dev, addr);
434+
default:
435+
kvm_err("%s: unknown group (%d) attr (%lld)\n", __func__, attr->group,
436+
attr->attr);
437+
return -EINVAL;
438+
}
439+
case KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS:
440+
return kvm_pch_pic_regs_access(dev, attr, true);
441+
default:
442+
return -EINVAL;
443+
}
327444
}
328445

329446
static int kvm_pch_pic_create(struct kvm_device *dev, u32 type)

0 commit comments

Comments
 (0)