diff --git a/drivers/vhost/CMakeLists.txt b/drivers/vhost/CMakeLists.txt index 9eb6c97bd18..ccd76303ceb 100644 --- a/drivers/vhost/CMakeLists.txt +++ b/drivers/vhost/CMakeLists.txt @@ -23,5 +23,9 @@ if(CONFIG_DRIVERS_VHOST) list(APPEND SRCS vhost.c) endif() +if(CONFIG_DRIVERS_VHOST_RNG) + list(APPEND SRCS vhost_rng.c) +endif() + target_sources(drivers PRIVATE ${SRCS}) target_include_directories(drivers PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index 8f7b2ee3b1b..e2f7bb73ed4 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -10,4 +10,8 @@ menuconfig DRIVERS_VHOST if DRIVERS_VHOST +config DRIVERS_VHOST_RNG + bool "Virtual Host Rng Device Support" + default n + endif # DRIVERS_VHOST diff --git a/drivers/vhost/Make.defs b/drivers/vhost/Make.defs index a82768fc015..13e67ff48ce 100644 --- a/drivers/vhost/Make.defs +++ b/drivers/vhost/Make.defs @@ -24,6 +24,10 @@ ifeq ($(CONFIG_DRIVERS_VHOST),y) CSRCS += vhost.c endif +ifeq ($(CONFIG_DRIVERS_VHOST_RNG),y) + CSRCS += vhost-rng.c +endif + # Include build support DEPPATH += --dep-path vhost diff --git a/drivers/vhost/vhost-rng.c b/drivers/vhost/vhost-rng.c new file mode 100644 index 00000000000..bf3307ac048 --- /dev/null +++ b/drivers/vhost/vhost-rng.c @@ -0,0 +1,189 @@ +/**************************************************************************** + * drivers/vhost/vhost-rng.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct vhost_rng_priv_s +{ + FAR struct vhost_device *hdev; + struct work_s work; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Vhost driver functions */ + +static int vhost_rng_probe(FAR struct vhost_device *hdev); +static void vhost_rng_remove(FAR struct vhost_device *hdev); + +static void vhost_rng_work(FAR void *arg); +static void vhost_rng_handler(FAR struct virtqueue *vq); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct vhost_driver g_vhost_rng_driver = +{ + LIST_INITIAL_VALUE(g_vhost_rng_driver.node), /* Node */ + VIRTIO_ID_ENTROPY, /* Device id */ + vhost_rng_probe, /* Probe */ + vhost_rng_remove, /* Remove */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vhost_rng_thread + ****************************************************************************/ + +static void vhost_rng_work(FAR void *arg) +{ + FAR struct vhost_rng_priv_s *priv = arg; + FAR struct virtqueue *vq; + FAR void *buf; + uint16_t idx; + uint32_t len; + ssize_t ret; + + vq = priv->hdev->vrings_info[0].vq; + for (; ; ) + { + buf = virtqueue_get_available_buffer(vq, &idx, &len); + if (buf == NULL) + { + break; + } + + ret = getrandom(buf, len, 0); + if (ret < 0) + { + vhosterr("getrandom failed, ret=%zd\n", ret); + ret = 0; + } + + virtqueue_add_consumed_buffer(vq, idx, (uint32_t)ret); + virtqueue_kick(vq); + } +} + +/**************************************************************************** + * Name: vhost_rng_handler + ****************************************************************************/ + +static void vhost_rng_handler(FAR struct virtqueue *vq) +{ + FAR struct vhost_rng_priv_s *priv = vq->vq_dev->priv; + + if (work_available(&priv->work)) + { + work_queue(HPWORK, &priv->work, vhost_rng_work, priv, 0); + } +} + +/**************************************************************************** + * Name: vhost_rng_probe + ****************************************************************************/ + +static int vhost_rng_probe(FAR struct vhost_device *hdev) +{ + FAR struct vhost_rng_priv_s *priv; + FAR const char *vqnames[1]; + vq_callback callback[1]; + int ret; + + priv = kmm_zalloc(sizeof(*priv)); + if (priv == NULL) + { + vhosterr("No enough memory\n"); + return -ENOMEM; + } + + priv->hdev = hdev; + hdev->priv = priv; + + /* Create the virtqueues */ + + vqnames[0] = "virtio_rng"; + callback[0] = vhost_rng_handler; + ret = vhost_create_virtqueues(hdev, 0, 1, vqnames, callback); + if (ret < 0) + { + vhosterr("virtio_device_create_virtqueue failed, ret=%d\n", ret); + goto err; + } + + virtqueue_enable_cb(hdev->vrings_info[0].vq); + return ret; + +err: + kmm_free(priv); + return ret; +} + +/**************************************************************************** + * Name: vhost_rng_remove + ****************************************************************************/ + +static void vhost_rng_remove(FAR struct vhost_device *hdev) +{ + FAR struct vhost_rng_priv_s *priv = hdev->priv; + + virtqueue_disable_cb(hdev->vrings_info[0].vq); + work_cancel_sync(HPWORK, &priv->work); + vhost_delete_virtqueues(hdev); + kmm_free(priv); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vhost_register_rng_driver + ****************************************************************************/ + +int vhost_register_rng_driver(void) +{ + return vhost_register_driver(&g_vhost_rng_driver); +} diff --git a/drivers/vhost/vhost-rng.h b/drivers/vhost/vhost-rng.h new file mode 100644 index 00000000000..a03e417c4a1 --- /dev/null +++ b/drivers/vhost/vhost-rng.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * drivers/vhost/vhost-rng.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __DRIVERS_VHOST_VHOST_RNG_H +#define __DRIVERS_VHOST_VHOST_RNG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_DRIVERS_VHOST_RNG + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int vhost_register_rng_driver(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_DRIVERS_VHOST_RNG */ + +#endif /* __DRIVERS_VHOST_VHOST_RNG_H */ diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index f6f7adb4af1..f4103e1521e 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -29,6 +29,8 @@ #include #include +#include "vhost-rng.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -375,4 +377,15 @@ out: void vhost_register_drivers(void) { + int ret; + +#ifdef CONFIG_DRIVERS_VHOST_RNG + ret = vhost_register_rng_driver(); + if (ret < 0) + { + vrterr("vhost_register_rng_driver failed, ret=%d\n", ret); + } +#endif + + UNUSED(ret); }