Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions driver/hvisor_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ static int hvisor_finish_req(void) {
return 0;
}

#ifdef LOONGARCH64
static int hvisor_deassert_irq(struct hvisor_irq_line_args __user *arg) {
struct hvisor_irq_line_args kargs;

if (copy_from_user(&kargs, arg, sizeof(kargs)))
return -EFAULT;

pr_debug("hvisor.ko: deassert zone=%u irq=%u\n", kargs.zone_id,
kargs.irq_id);
return hvisor_call(HVISOR_HC_CLEAR_INJECT_IRQ, kargs.zone_id, kargs.irq_id);
}
#endif

// Flush mapped cache range to memory.
static int flush_cache_mapped(void *vaddr, __u64 size) {
unsigned long start, end, addr, line_size;
Expand Down Expand Up @@ -375,8 +388,8 @@ static long hvisor_ioctl(struct file *file, unsigned int ioctl,
break;
#endif
#ifdef LOONGARCH64
case HVISOR_CLEAR_INJECT_IRQ:
err = hvisor_call(HVISOR_HC_CLEAR_INJECT_IRQ, 0, 0);
case HVISOR_DEASSERT_IRQ:
err = hvisor_deassert_irq((struct hvisor_irq_line_args __user *)arg);
break;
#endif
default:
Expand Down
113 changes: 67 additions & 46 deletions driver/ivc_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,16 @@ extern u8 __dtb_hivc_template_begin[], __dtb_hivc_template_end[];

static int hvisor_ivc_info(void) {
int err = 0;
if (ivc_info == NULL)
ivc_info = kmalloc(sizeof(ivc_info_t), GFP_KERNEL);
if (ivc_info == NULL) {
ivc_info = kzalloc(sizeof(ivc_info_t), GFP_KERNEL);
if (!ivc_info)
return -ENOMEM;
}
err = hvisor_call(HVISOR_HC_IVC_INFO, __pa(ivc_info), sizeof(ivc_info_t));
if (err)
return err;
if (ivc_info->len == 0 || ivc_info->len > CONFIG_MAX_IVC_CONFIGS)
return -EINVAL;
return err;
}

Expand Down Expand Up @@ -167,51 +174,20 @@ static irqreturn_t ivc_irq_handler(int irq, void *dev_id) {
return IRQ_HANDLED;
}

// static struct property *alloc_property(const char *name, int len) {
// struct property *prop;
// prop = kzalloc(sizeof(struct property), GFP_KERNEL);
// prop->name = kstrdup(name, GFP_KERNEL);
// prop->length = len;
// prop->value = kzalloc(len, GFP_KERNEL);
// return prop;
// }

// static int add_ivc_device_node(void)
// {
// int err, i, j, overlay_id;
// struct device_node *node = NULL;
// struct property *prop;
// u32* values;
// err = of_overlay_fdt_apply(__dtb_hivc_template_begin,
// __dtb_hivc_template_end - __dtb_hivc_template_begin,
// &overlay_id);
// if (err) return err;

// struct of_changeset overlay_changeset;
// of_changeset_init(&overlay_changeset);
// node = of_find_node_by_path("/hvisor_ivc_device");

// // TODO: Add detection for gic interrupt cell and error handling
// prop = alloc_property("interrupts", sizeof(u32)*3*dev_len);
// values = prop->value;
// for(i=0; i<dev_len; i++) {
// j = i * 3;
// values[j++] = 0x00;
// values[j++] = ivc_info->ivc_irqs[i] - 32;
// values[j++] = 0x01;
// }
// of_changeset_add_property(&overlay_changeset, node, prop);
// of_changeset_apply(&overlay_changeset);
// return 0;
// }

static int __init ivc_init(void) {
int err, i, soft_irq;
struct device_node *node = NULL;
hvisor_ivc_info();
err = hvisor_ivc_info();
if (err)
Comment thread
li041 marked this conversation as resolved.
goto err1;
dev_len = ivc_info->len;

ivc_devs = kmalloc(sizeof(struct ivc_dev) * dev_len, GFP_KERNEL);
pr_info("ivc: hypervisor reports %d channel(s)\n", dev_len);
ivc_devs = kcalloc(dev_len, sizeof(struct ivc_dev), GFP_KERNEL);
if (!ivc_devs) {
err = -ENOMEM;
goto err1;
}
err = alloc_chrdev_region(&mdev_id, 0, dev_len, "hivc");
if (err)
goto err1;
Expand All @@ -233,6 +209,7 @@ static int __init ivc_init(void) {
ivc_devs[i].ivc_id = ivc_info->ivc_ids[i];
ivc_devs[i].dev_id = MKDEV(MAJOR(mdev_id), i);
ivc_devs[i].idx = i;
ivc_devs[i].ivc_irq = -1;
ivc_devs[i].cdev.owner = THIS_MODULE;
ivc_devs[i].received_irq = 0;
init_waitqueue_head(&ivc_devs[i].wq);
Expand All @@ -254,13 +231,20 @@ static int __init ivc_init(void) {
} else {
for (i = 0; i < dev_len; i++) {
soft_irq = of_irq_get(node, i);
if (soft_irq < 0) {
pr_err("ivc: of_irq_get channel %d failed (%d)\n", i, soft_irq);
continue;
}
err = request_irq(soft_irq, ivc_irq_handler,
IRQF_SHARED | IRQF_TRIGGER_RISING,
"hvisor_ivc_device", &ivc_devs[i]);
if (err) {
pr_err("request irq failed\n");
pr_err("ivc: request irq channel %d failed (%d)\n", i, err);
goto err2;
}
ivc_devs[i].ivc_irq = soft_irq;
pr_info("ivc: ch%d id=%d linux_irq=%d hv_irq=%u\n", i,
ivc_devs[i].ivc_id, soft_irq, ivc_info->ivc_irqs[i]);
}
}
of_node_put(node);
Expand All @@ -269,8 +253,13 @@ static int __init ivc_init(void) {

err2:
for (i = 0; i < dev_len; i++) {
if (ivc_devs[i].ivc_irq >= 0) {
free_irq(ivc_devs[i].ivc_irq, &ivc_devs[i]);
ivc_devs[i].ivc_irq = -1;
}
cdev_del(&ivc_devs[i].cdev);
device_destroy(ivc_class, ivc_devs[i].dev_id);
if (ivc_class && !IS_ERR(ivc_class))
device_destroy(ivc_class, ivc_devs[i].dev_id);
}
class_destroy(ivc_class);
unregister_chrdev_region(mdev_id, dev_len);
Expand All @@ -281,7 +270,39 @@ static int __init ivc_init(void) {
}

static void __exit ivc_exit(void) {
// TODO
int i;

if (!ivc_devs || dev_len <= 0) {
kfree(ivc_info);
ivc_info = NULL;
pr_info("ivc exit done!!!\n");
return;
}
/* Free the IRQ first to prevent user-space and kernel paths from being
* woken. */
for (i = 0; i < dev_len; i++) {
if (ivc_devs[i].ivc_irq >= 0) {
free_irq(ivc_devs[i].ivc_irq, &ivc_devs[i]);
ivc_devs[i].ivc_irq = -1;
}
}

/* Destroy the character devices and sysfs device nodes. */
if (ivc_class && !IS_ERR(ivc_class)) {
for (i = 0; i < dev_len; i++) {
cdev_del(&ivc_devs[i].cdev);
device_destroy(ivc_class, ivc_devs[i].dev_id);
}
class_destroy(ivc_class);
}
unregister_chrdev_region(mdev_id, dev_len);

kfree(ivc_devs);
ivc_devs = NULL;
kfree(ivc_info);
ivc_info = NULL;
dev_len = 0;

pr_info("ivc exit done!!!\n");
}

Expand All @@ -300,4 +321,4 @@ module_exit(ivc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("KouweiLee <15035660024@163.com>");
MODULE_DESCRIPTION("The hvisor device driver");
MODULE_VERSION("1:0.0");
MODULE_VERSION("1:0.0");
9 changes: 7 additions & 2 deletions include/hvisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ struct device_res {
__u32 irq_id;
};

struct hvisor_irq_line_args {
__u32 zone_id;
__u32 irq_id;
};

struct virtio_bridge {
__u32 req_front;
__u32 req_rear;
Expand Down Expand Up @@ -215,8 +220,8 @@ struct hvisor_scmi_power_args {

#ifdef LOONGARCH64

#define HVISOR_CLEAR_INJECT_IRQ _IO(1, 6) // used for ioctl
#define HVISOR_HC_CLEAR_INJECT_IRQ 20 // hvcall code in hvisor
#define HVISOR_DEASSERT_IRQ _IOW(1, 11, struct hvisor_irq_line_args)
#define HVISOR_HC_CLEAR_INJECT_IRQ 11 // hvcall code in hvisor

#endif /* LOONGARCH64 */
#ifdef LOONGARCH64
Expand Down
2 changes: 1 addition & 1 deletion tools/hvisor.c
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,7 @@ static int zone_start_from_json(const char *json_config_path,

close(fd);

return 0;
return err;
err_out:
if (root)
cJSON_Delete(root);
Expand Down
5 changes: 2 additions & 3 deletions tools/virtio/include/virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ typedef struct VirtMmioRegs {
uint32_t queue_sel; // The driver frontend writes this register to select
// which virtqueue to use
uint32_t interrupt_status;
// interrupt_count doesn't exist in virtio specification,
// only used for ensuring the correctness of interrupt_status.
uint32_t interrupt_count;
uint32_t status;
uint32_t generation;
uint64_t dev_feature; // device_features
Expand Down Expand Up @@ -130,6 +127,8 @@ struct VirtIODevice {
void (*status_changed)(VirtIODevice *vdev,
uint32_t status); // Called on STATUS register write
bool activated; // Whether the current virtio device is activated
pthread_mutex_t interrupt_lock;
bool interrupt_line_asserted;
};

// used event idx for driver telling device when to notify driver.
Expand Down
Loading
Loading