1*e785dfacSXianglai Li // SPDX-License-Identifier: GPL-2.0 2*e785dfacSXianglai Li /* 3*e785dfacSXianglai Li * Copyright (C) 2024 Loongson Technology Corporation Limited 4*e785dfacSXianglai Li */ 5*e785dfacSXianglai Li 6*e785dfacSXianglai Li #include <asm/kvm_eiointc.h> 7*e785dfacSXianglai Li #include <asm/kvm_pch_pic.h> 8*e785dfacSXianglai Li #include <asm/kvm_vcpu.h> 9*e785dfacSXianglai Li #include <linux/count_zeros.h> 10*e785dfacSXianglai Li 11*e785dfacSXianglai Li static int kvm_pch_pic_read(struct kvm_vcpu *vcpu, 12*e785dfacSXianglai Li struct kvm_io_device *dev, 13*e785dfacSXianglai Li gpa_t addr, int len, void *val) 14*e785dfacSXianglai Li { 15*e785dfacSXianglai Li return 0; 16*e785dfacSXianglai Li } 17*e785dfacSXianglai Li 18*e785dfacSXianglai Li static int kvm_pch_pic_write(struct kvm_vcpu *vcpu, 19*e785dfacSXianglai Li struct kvm_io_device *dev, 20*e785dfacSXianglai Li gpa_t addr, int len, const void *val) 21*e785dfacSXianglai Li { 22*e785dfacSXianglai Li return 0; 23*e785dfacSXianglai Li } 24*e785dfacSXianglai Li 25*e785dfacSXianglai Li static const struct kvm_io_device_ops kvm_pch_pic_ops = { 26*e785dfacSXianglai Li .read = kvm_pch_pic_read, 27*e785dfacSXianglai Li .write = kvm_pch_pic_write, 28*e785dfacSXianglai Li }; 29*e785dfacSXianglai Li 30*e785dfacSXianglai Li static int kvm_pch_pic_get_attr(struct kvm_device *dev, 31*e785dfacSXianglai Li struct kvm_device_attr *attr) 32*e785dfacSXianglai Li { 33*e785dfacSXianglai Li return 0; 34*e785dfacSXianglai Li } 35*e785dfacSXianglai Li 36*e785dfacSXianglai Li static int kvm_pch_pic_set_attr(struct kvm_device *dev, 37*e785dfacSXianglai Li struct kvm_device_attr *attr) 38*e785dfacSXianglai Li { 39*e785dfacSXianglai Li return 0; 40*e785dfacSXianglai Li } 41*e785dfacSXianglai Li 42*e785dfacSXianglai Li static int kvm_pch_pic_create(struct kvm_device *dev, u32 type) 43*e785dfacSXianglai Li { 44*e785dfacSXianglai Li struct kvm *kvm = dev->kvm; 45*e785dfacSXianglai Li struct loongarch_pch_pic *s; 46*e785dfacSXianglai Li 47*e785dfacSXianglai Li /* pch pic should not has been created */ 48*e785dfacSXianglai Li if (kvm->arch.pch_pic) 49*e785dfacSXianglai Li return -EINVAL; 50*e785dfacSXianglai Li 51*e785dfacSXianglai Li s = kzalloc(sizeof(struct loongarch_pch_pic), GFP_KERNEL); 52*e785dfacSXianglai Li if (!s) 53*e785dfacSXianglai Li return -ENOMEM; 54*e785dfacSXianglai Li 55*e785dfacSXianglai Li spin_lock_init(&s->lock); 56*e785dfacSXianglai Li s->kvm = kvm; 57*e785dfacSXianglai Li kvm->arch.pch_pic = s; 58*e785dfacSXianglai Li 59*e785dfacSXianglai Li return 0; 60*e785dfacSXianglai Li } 61*e785dfacSXianglai Li 62*e785dfacSXianglai Li static void kvm_pch_pic_destroy(struct kvm_device *dev) 63*e785dfacSXianglai Li { 64*e785dfacSXianglai Li struct kvm *kvm; 65*e785dfacSXianglai Li struct loongarch_pch_pic *s; 66*e785dfacSXianglai Li 67*e785dfacSXianglai Li if (!dev || !dev->kvm || !dev->kvm->arch.pch_pic) 68*e785dfacSXianglai Li return; 69*e785dfacSXianglai Li 70*e785dfacSXianglai Li kvm = dev->kvm; 71*e785dfacSXianglai Li s = kvm->arch.pch_pic; 72*e785dfacSXianglai Li /* unregister pch pic device and free it's memory */ 73*e785dfacSXianglai Li kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &s->device); 74*e785dfacSXianglai Li kfree(s); 75*e785dfacSXianglai Li } 76*e785dfacSXianglai Li 77*e785dfacSXianglai Li static struct kvm_device_ops kvm_pch_pic_dev_ops = { 78*e785dfacSXianglai Li .name = "kvm-loongarch-pch-pic", 79*e785dfacSXianglai Li .create = kvm_pch_pic_create, 80*e785dfacSXianglai Li .destroy = kvm_pch_pic_destroy, 81*e785dfacSXianglai Li .set_attr = kvm_pch_pic_set_attr, 82*e785dfacSXianglai Li .get_attr = kvm_pch_pic_get_attr, 83*e785dfacSXianglai Li }; 84*e785dfacSXianglai Li 85*e785dfacSXianglai Li int kvm_loongarch_register_pch_pic_device(void) 86*e785dfacSXianglai Li { 87*e785dfacSXianglai Li return kvm_register_device_ops(&kvm_pch_pic_dev_ops, KVM_DEV_TYPE_LOONGARCH_PCHPIC); 88*e785dfacSXianglai Li } 89