|
@@ -28,6 +28,7 @@
|
|
#include "qapi/visitor.h"
|
|
#include "qapi/visitor.h"
|
|
#include "qemu/config-file.h"
|
|
#include "qemu/config-file.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/error-report.h"
|
|
|
|
+#include "qemu/main-loop.h"
|
|
#include "qom/object_interfaces.h"
|
|
#include "qom/object_interfaces.h"
|
|
#include "hw/virtio/virtio-crypto.h"
|
|
#include "hw/virtio/virtio-crypto.h"
|
|
|
|
|
|
@@ -203,17 +204,53 @@ static int cryptodev_backend_account(CryptoDevBackend *backend,
|
|
return len;
|
|
return len;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void cryptodev_backend_throttle_timer_cb(void *opaque)
|
|
|
|
+{
|
|
|
|
+ CryptoDevBackend *backend = (CryptoDevBackend *)opaque;
|
|
|
|
+ CryptoDevBackendOpInfo *op_info, *tmpop;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ QTAILQ_FOREACH_SAFE(op_info, &backend->opinfos, next, tmpop) {
|
|
|
|
+ QTAILQ_REMOVE(&backend->opinfos, op_info, next);
|
|
|
|
+ ret = cryptodev_backend_account(backend, op_info);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ op_info->cb(op_info->opaque, ret);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ throttle_account(&backend->ts, true, ret);
|
|
|
|
+ cryptodev_backend_operation(backend, op_info);
|
|
|
|
+ if (throttle_enabled(&backend->tc) &&
|
|
|
|
+ throttle_schedule_timer(&backend->ts, &backend->tt, true)) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
int cryptodev_backend_crypto_operation(
|
|
int cryptodev_backend_crypto_operation(
|
|
CryptoDevBackend *backend,
|
|
CryptoDevBackend *backend,
|
|
CryptoDevBackendOpInfo *op_info)
|
|
CryptoDevBackendOpInfo *op_info)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
+ if (!throttle_enabled(&backend->tc)) {
|
|
|
|
+ goto do_account;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (throttle_schedule_timer(&backend->ts, &backend->tt, true) ||
|
|
|
|
+ !QTAILQ_EMPTY(&backend->opinfos)) {
|
|
|
|
+ QTAILQ_INSERT_TAIL(&backend->opinfos, op_info, next);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+do_account:
|
|
ret = cryptodev_backend_account(backend, op_info);
|
|
ret = cryptodev_backend_account(backend, op_info);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ throttle_account(&backend->ts, true, ret);
|
|
|
|
+
|
|
return cryptodev_backend_operation(backend, op_info);
|
|
return cryptodev_backend_operation(backend, op_info);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -245,12 +282,98 @@ cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
|
|
backend->conf.peers.queues = value;
|
|
backend->conf.peers.queues = value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void cryptodev_backend_set_throttle(CryptoDevBackend *backend, int field,
|
|
|
|
+ uint64_t value, Error **errp)
|
|
|
|
+{
|
|
|
|
+ uint64_t orig = backend->tc.buckets[field].avg;
|
|
|
|
+ bool enabled = throttle_enabled(&backend->tc);
|
|
|
|
+
|
|
|
|
+ if (orig == value) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ backend->tc.buckets[field].avg = value;
|
|
|
|
+ if (!throttle_enabled(&backend->tc)) {
|
|
|
|
+ throttle_timers_destroy(&backend->tt);
|
|
|
|
+ cryptodev_backend_throttle_timer_cb(backend); /* drain opinfos */
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!throttle_is_valid(&backend->tc, errp)) {
|
|
|
|
+ backend->tc.buckets[field].avg = orig; /* revert change */
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!enabled) {
|
|
|
|
+ throttle_init(&backend->ts);
|
|
|
|
+ throttle_timers_init(&backend->tt, qemu_get_aio_context(),
|
|
|
|
+ QEMU_CLOCK_REALTIME,
|
|
|
|
+ cryptodev_backend_throttle_timer_cb, /* FIXME */
|
|
|
|
+ cryptodev_backend_throttle_timer_cb, backend);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ throttle_config(&backend->ts, QEMU_CLOCK_REALTIME, &backend->tc);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cryptodev_backend_get_bps(Object *obj, Visitor *v,
|
|
|
|
+ const char *name, void *opaque,
|
|
|
|
+ Error **errp)
|
|
|
|
+{
|
|
|
|
+ CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
|
|
|
+ uint64_t value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
|
|
|
+
|
|
|
|
+ visit_type_uint64(v, name, &value, errp);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cryptodev_backend_set_bps(Object *obj, Visitor *v, const char *name,
|
|
|
|
+ void *opaque, Error **errp)
|
|
|
|
+{
|
|
|
|
+ CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
|
|
|
+ uint64_t value;
|
|
|
|
+
|
|
|
|
+ if (!visit_type_uint64(v, name, &value, errp)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cryptodev_backend_get_ops(Object *obj, Visitor *v, const char *name,
|
|
|
|
+ void *opaque, Error **errp)
|
|
|
|
+{
|
|
|
|
+ CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
|
|
|
+ uint64_t value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
|
|
|
+
|
|
|
|
+ visit_type_uint64(v, name, &value, errp);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cryptodev_backend_set_ops(Object *obj, Visitor *v,
|
|
|
|
+ const char *name, void *opaque,
|
|
|
|
+ Error **errp)
|
|
|
|
+{
|
|
|
|
+ CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
|
|
|
+ uint64_t value;
|
|
|
|
+
|
|
|
|
+ if (!visit_type_uint64(v, name, &value, errp)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
|
|
|
+}
|
|
|
|
+
|
|
static void
|
|
static void
|
|
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
|
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
|
{
|
|
{
|
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
|
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
|
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
|
uint32_t services;
|
|
uint32_t services;
|
|
|
|
+ uint64_t value;
|
|
|
|
+
|
|
|
|
+ QTAILQ_INIT(&backend->opinfos);
|
|
|
|
+ value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
|
|
|
+ cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
|
|
|
+ value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
|
|
|
+ cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
|
|
|
|
|
if (bc->init) {
|
|
if (bc->init) {
|
|
bc->init(backend, errp);
|
|
bc->init(backend, errp);
|
|
@@ -294,8 +417,12 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc)
|
|
|
|
|
|
static void cryptodev_backend_instance_init(Object *obj)
|
|
static void cryptodev_backend_instance_init(Object *obj)
|
|
{
|
|
{
|
|
|
|
+ CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
|
|
|
+
|
|
/* Initialize devices' queues property to 1 */
|
|
/* Initialize devices' queues property to 1 */
|
|
object_property_set_int(obj, "queues", 1, NULL);
|
|
object_property_set_int(obj, "queues", 1, NULL);
|
|
|
|
+
|
|
|
|
+ throttle_config_init(&backend->tc);
|
|
}
|
|
}
|
|
|
|
|
|
static void cryptodev_backend_finalize(Object *obj)
|
|
static void cryptodev_backend_finalize(Object *obj)
|
|
@@ -303,6 +430,9 @@ static void cryptodev_backend_finalize(Object *obj)
|
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
|
|
|
|
|
cryptodev_backend_cleanup(backend, NULL);
|
|
cryptodev_backend_cleanup(backend, NULL);
|
|
|
|
+ if (throttle_enabled(&backend->tc)) {
|
|
|
|
+ throttle_timers_destroy(&backend->tt);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
@@ -318,6 +448,14 @@ cryptodev_backend_class_init(ObjectClass *oc, void *data)
|
|
cryptodev_backend_get_queues,
|
|
cryptodev_backend_get_queues,
|
|
cryptodev_backend_set_queues,
|
|
cryptodev_backend_set_queues,
|
|
NULL, NULL);
|
|
NULL, NULL);
|
|
|
|
+ object_class_property_add(oc, "throttle-bps", "uint64",
|
|
|
|
+ cryptodev_backend_get_bps,
|
|
|
|
+ cryptodev_backend_set_bps,
|
|
|
|
+ NULL, NULL);
|
|
|
|
+ object_class_property_add(oc, "throttle-ops", "uint64",
|
|
|
|
+ cryptodev_backend_get_ops,
|
|
|
|
+ cryptodev_backend_set_ops,
|
|
|
|
+ NULL, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
static const TypeInfo cryptodev_backend_info = {
|
|
static const TypeInfo cryptodev_backend_info = {
|