mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio, pc: fixes and features
nvdimm hotplug support
virtio migration and ioeventfd rework
virtio crypto device
ipmi fixes
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Tue 01 Nov 2016 05:23:40 PM GMT
# gpg: using RSA key 0x281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67
# Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469
* remotes/mst/tags/for_upstream: (47 commits)
acpi: fix assert failure caused by commit 35c5a52d
acpi/ipmi: Initialize the fwinfo before fetching it
ipmi: Add graceful shutdown handling to the external BMC
ipmi: fix build config variable name for ipmi_bmc_extern.o
ipmi: Implement shutdown via ACPI overtemp
ipmi: chassis poweroff should use qemu_system_shutdown_request()
ipmi_bmc_sim: Remove an unnecessary mutex
ipmi: Remove hotplug from IPMI BMCs
pc: memhp: enable nvdimm device hotplug
nvdimm acpi: introduce _FIT
nvdimm acpi: introduce fit buffer
nvdimm acpi: prebuild nvdimm devices for available slots
nvdimm acpi: use common macros instead of magic names
acpi nvdimm: rename result_size to dsm_out_buf_siz
nvdimm acpi: compile nvdimm acpi code arch-independently
acpi nvdimm: fix Arg6 usage
acpi nvdimm: fix ARG3 conflict
acpi nvdimm: fix device physical address base
acpi nvdimm: fix OperationRegion definition
acpi nvdimm: fix wrong buffer size returned by DSM method
...
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
+13
@@ -1016,6 +1016,13 @@ F: include/sysemu/rng*.h
|
||||
F: backends/rng*.c
|
||||
F: tests/virtio-rng-test.c
|
||||
|
||||
virtio-crypto
|
||||
M: Gonglei <arei.gonglei@huawei.com>
|
||||
S: Supported
|
||||
F: hw/virtio/virtio-crypto.c
|
||||
F: hw/virtio/virtio-crypto-pci.c
|
||||
F: include/hw/virtio/virtio-crypto.h
|
||||
|
||||
nvme
|
||||
M: Keith Busch <keith.busch@intel.com>
|
||||
L: qemu-block@nongnu.org
|
||||
@@ -1261,6 +1268,12 @@ S: Maintained
|
||||
F: backends/hostmem*.c
|
||||
F: include/sysemu/hostmem.h
|
||||
|
||||
Cryptodev Backends
|
||||
M: Gonglei <arei.gonglei@huawei.com>
|
||||
S: Maintained
|
||||
F: include/sysemu/cryptodev*.h
|
||||
F: backends/cryptodev*.c
|
||||
|
||||
QAPI
|
||||
M: Markus Armbruster <armbru@redhat.com>
|
||||
M: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
|
||||
@@ -9,3 +9,6 @@ common-obj-$(CONFIG_TPM) += tpm.o
|
||||
|
||||
common-obj-y += hostmem.o hostmem-ram.o
|
||||
common-obj-$(CONFIG_LINUX) += hostmem-file.o
|
||||
|
||||
common-obj-y += cryptodev.o
|
||||
common-obj-y += cryptodev-builtin.o
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* QEMU Cryptodev backend for QEMU cipher APIs
|
||||
*
|
||||
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||
*
|
||||
* Authors:
|
||||
* Gonglei <arei.gonglei@huawei.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/cryptodev.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qapi/error.h"
|
||||
#include "standard-headers/linux/virtio_crypto.h"
|
||||
#include "crypto/cipher.h"
|
||||
|
||||
|
||||
/**
|
||||
* @TYPE_CRYPTODEV_BACKEND_BUILTIN:
|
||||
* name of backend that uses QEMU cipher API
|
||||
*/
|
||||
#define TYPE_CRYPTODEV_BACKEND_BUILTIN "cryptodev-backend-builtin"
|
||||
|
||||
#define CRYPTODEV_BACKEND_BUILTIN(obj) \
|
||||
OBJECT_CHECK(CryptoDevBackendBuiltin, \
|
||||
(obj), TYPE_CRYPTODEV_BACKEND_BUILTIN)
|
||||
|
||||
typedef struct CryptoDevBackendBuiltin
|
||||
CryptoDevBackendBuiltin;
|
||||
|
||||
typedef struct CryptoDevBackendBuiltinSession {
|
||||
QCryptoCipher *cipher;
|
||||
uint8_t direction; /* encryption or decryption */
|
||||
uint8_t type; /* cipher? hash? aead? */
|
||||
QTAILQ_ENTRY(CryptoDevBackendBuiltinSession) next;
|
||||
} CryptoDevBackendBuiltinSession;
|
||||
|
||||
/* Max number of symmetric sessions */
|
||||
#define MAX_NUM_SESSIONS 256
|
||||
|
||||
#define CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN 512
|
||||
#define CRYPTODEV_BUITLIN_MAX_CIPHER_KEY_LEN 64
|
||||
|
||||
struct CryptoDevBackendBuiltin {
|
||||
CryptoDevBackend parent_obj;
|
||||
|
||||
CryptoDevBackendBuiltinSession *sessions[MAX_NUM_SESSIONS];
|
||||
};
|
||||
|
||||
static void cryptodev_builtin_init(
|
||||
CryptoDevBackend *backend, Error **errp)
|
||||
{
|
||||
/* Only support one queue */
|
||||
int queues = backend->conf.peers.queues;
|
||||
CryptoDevBackendClient *cc;
|
||||
|
||||
if (queues != 1) {
|
||||
error_setg(errp,
|
||||
"Only support one queue in cryptdov-builtin backend");
|
||||
return;
|
||||
}
|
||||
|
||||
cc = cryptodev_backend_new_client(
|
||||
"cryptodev-builtin", NULL);
|
||||
cc->info_str = g_strdup_printf("cryptodev-builtin0");
|
||||
cc->queue_index = 0;
|
||||
backend->conf.peers.ccs[0] = cc;
|
||||
|
||||
backend->conf.crypto_services =
|
||||
1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
|
||||
1u << VIRTIO_CRYPTO_SERVICE_HASH |
|
||||
1u << VIRTIO_CRYPTO_SERVICE_MAC;
|
||||
backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
|
||||
backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
|
||||
/*
|
||||
* Set the Maximum length of crypto request.
|
||||
* Why this value? Just avoid to overflow when
|
||||
* memory allocation for each crypto request.
|
||||
*/
|
||||
backend->conf.max_size = LONG_MAX - sizeof(CryptoDevBackendSymOpInfo);
|
||||
backend->conf.max_cipher_key_len = CRYPTODEV_BUITLIN_MAX_CIPHER_KEY_LEN;
|
||||
backend->conf.max_auth_key_len = CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
cryptodev_builtin_get_unused_session_index(
|
||||
CryptoDevBackendBuiltin *builtin)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_NUM_SESSIONS; i++) {
|
||||
if (builtin->sessions[i] == NULL) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
cryptodev_builtin_get_aes_algo(uint32_t key_len, Error **errp)
|
||||
{
|
||||
int algo;
|
||||
|
||||
if (key_len == 128 / 8) {
|
||||
algo = QCRYPTO_CIPHER_ALG_AES_128;
|
||||
} else if (key_len == 192 / 8) {
|
||||
algo = QCRYPTO_CIPHER_ALG_AES_192;
|
||||
} else if (key_len == 256 / 8) {
|
||||
algo = QCRYPTO_CIPHER_ALG_AES_256;
|
||||
} else {
|
||||
error_setg(errp, "Unsupported key length :%u", key_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return algo;
|
||||
}
|
||||
|
||||
static int cryptodev_builtin_create_cipher_session(
|
||||
CryptoDevBackendBuiltin *builtin,
|
||||
CryptoDevBackendSymSessionInfo *sess_info,
|
||||
Error **errp)
|
||||
{
|
||||
int algo;
|
||||
int mode;
|
||||
QCryptoCipher *cipher;
|
||||
int index;
|
||||
CryptoDevBackendBuiltinSession *sess;
|
||||
|
||||
if (sess_info->op_type != VIRTIO_CRYPTO_SYM_OP_CIPHER) {
|
||||
error_setg(errp, "Unsupported optype :%u", sess_info->op_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = cryptodev_builtin_get_unused_session_index(builtin);
|
||||
if (index < 0) {
|
||||
error_setg(errp, "Total number of sessions created exceeds %u",
|
||||
MAX_NUM_SESSIONS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (sess_info->cipher_alg) {
|
||||
case VIRTIO_CRYPTO_CIPHER_AES_ECB:
|
||||
algo = cryptodev_builtin_get_aes_algo(sess_info->key_len,
|
||||
errp);
|
||||
if (algo < 0) {
|
||||
return -1;
|
||||
}
|
||||
mode = QCRYPTO_CIPHER_MODE_ECB;
|
||||
break;
|
||||
case VIRTIO_CRYPTO_CIPHER_AES_CBC:
|
||||
algo = cryptodev_builtin_get_aes_algo(sess_info->key_len,
|
||||
errp);
|
||||
if (algo < 0) {
|
||||
return -1;
|
||||
}
|
||||
mode = QCRYPTO_CIPHER_MODE_CBC;
|
||||
break;
|
||||
case VIRTIO_CRYPTO_CIPHER_AES_CTR:
|
||||
algo = cryptodev_builtin_get_aes_algo(sess_info->key_len,
|
||||
errp);
|
||||
if (algo < 0) {
|
||||
return -1;
|
||||
}
|
||||
mode = QCRYPTO_CIPHER_MODE_CTR;
|
||||
break;
|
||||
case VIRTIO_CRYPTO_CIPHER_DES_ECB:
|
||||
algo = QCRYPTO_CIPHER_ALG_DES_RFB;
|
||||
mode = QCRYPTO_CIPHER_MODE_ECB;
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher alg :%u",
|
||||
sess_info->cipher_alg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cipher = qcrypto_cipher_new(algo, mode,
|
||||
sess_info->cipher_key,
|
||||
sess_info->key_len,
|
||||
errp);
|
||||
if (!cipher) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sess = g_new0(CryptoDevBackendBuiltinSession, 1);
|
||||
sess->cipher = cipher;
|
||||
sess->direction = sess_info->direction;
|
||||
sess->type = sess_info->op_type;
|
||||
|
||||
builtin->sessions[index] = sess;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static int64_t cryptodev_builtin_sym_create_session(
|
||||
CryptoDevBackend *backend,
|
||||
CryptoDevBackendSymSessionInfo *sess_info,
|
||||
uint32_t queue_index, Error **errp)
|
||||
{
|
||||
CryptoDevBackendBuiltin *builtin =
|
||||
CRYPTODEV_BACKEND_BUILTIN(backend);
|
||||
int64_t session_id = -1;
|
||||
int ret;
|
||||
|
||||
switch (sess_info->op_code) {
|
||||
case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
|
||||
ret = cryptodev_builtin_create_cipher_session(
|
||||
builtin, sess_info, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
} else {
|
||||
session_id = ret;
|
||||
}
|
||||
break;
|
||||
case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
|
||||
case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
|
||||
default:
|
||||
error_setg(errp, "Unsupported opcode :%" PRIu32 "",
|
||||
sess_info->op_code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return session_id;
|
||||
}
|
||||
|
||||
static int cryptodev_builtin_sym_close_session(
|
||||
CryptoDevBackend *backend,
|
||||
uint64_t session_id,
|
||||
uint32_t queue_index, Error **errp)
|
||||
{
|
||||
CryptoDevBackendBuiltin *builtin =
|
||||
CRYPTODEV_BACKEND_BUILTIN(backend);
|
||||
|
||||
if (session_id >= MAX_NUM_SESSIONS ||
|
||||
builtin->sessions[session_id] == NULL) {
|
||||
error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
|
||||
session_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qcrypto_cipher_free(builtin->sessions[session_id]->cipher);
|
||||
g_free(builtin->sessions[session_id]);
|
||||
builtin->sessions[session_id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cryptodev_builtin_sym_operation(
|
||||
CryptoDevBackend *backend,
|
||||
CryptoDevBackendSymOpInfo *op_info,
|
||||
uint32_t queue_index, Error **errp)
|
||||
{
|
||||
CryptoDevBackendBuiltin *builtin =
|
||||
CRYPTODEV_BACKEND_BUILTIN(backend);
|
||||
CryptoDevBackendBuiltinSession *sess;
|
||||
int ret;
|
||||
|
||||
if (op_info->session_id >= MAX_NUM_SESSIONS ||
|
||||
builtin->sessions[op_info->session_id] == NULL) {
|
||||
error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
|
||||
op_info->session_id);
|
||||
return -VIRTIO_CRYPTO_INVSESS;
|
||||
}
|
||||
|
||||
if (op_info->op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) {
|
||||
error_setg(errp,
|
||||
"Algorithm chain is unsupported for cryptdoev-builtin");
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
|
||||
sess = builtin->sessions[op_info->session_id];
|
||||
|
||||
ret = qcrypto_cipher_setiv(sess->cipher, op_info->iv,
|
||||
op_info->iv_len, errp);
|
||||
if (ret < 0) {
|
||||
return -VIRTIO_CRYPTO_ERR;
|
||||
}
|
||||
|
||||
if (sess->direction == VIRTIO_CRYPTO_OP_ENCRYPT) {
|
||||
ret = qcrypto_cipher_encrypt(sess->cipher, op_info->src,
|
||||
op_info->dst, op_info->src_len, errp);
|
||||
if (ret < 0) {
|
||||
return -VIRTIO_CRYPTO_ERR;
|
||||
}
|
||||
} else {
|
||||
ret = qcrypto_cipher_decrypt(sess->cipher, op_info->src,
|
||||
op_info->dst, op_info->src_len, errp);
|
||||
if (ret < 0) {
|
||||
return -VIRTIO_CRYPTO_ERR;
|
||||
}
|
||||
}
|
||||
return VIRTIO_CRYPTO_OK;
|
||||
}
|
||||
|
||||
static void cryptodev_builtin_cleanup(
|
||||
CryptoDevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
CryptoDevBackendBuiltin *builtin =
|
||||
CRYPTODEV_BACKEND_BUILTIN(backend);
|
||||
size_t i;
|
||||
int queues = backend->conf.peers.queues;
|
||||
CryptoDevBackendClient *cc;
|
||||
|
||||
for (i = 0; i < MAX_NUM_SESSIONS; i++) {
|
||||
if (builtin->sessions[i] != NULL) {
|
||||
cryptodev_builtin_sym_close_session(
|
||||
backend, i, 0, errp);
|
||||
}
|
||||
}
|
||||
|
||||
assert(queues == 1);
|
||||
|
||||
for (i = 0; i < queues; i++) {
|
||||
cc = backend->conf.peers.ccs[i];
|
||||
if (cc) {
|
||||
cryptodev_backend_free_client(cc);
|
||||
backend->conf.peers.ccs[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cryptodev_builtin_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_CLASS(oc);
|
||||
|
||||
bc->init = cryptodev_builtin_init;
|
||||
bc->cleanup = cryptodev_builtin_cleanup;
|
||||
bc->create_session = cryptodev_builtin_sym_create_session;
|
||||
bc->close_session = cryptodev_builtin_sym_close_session;
|
||||
bc->do_sym_op = cryptodev_builtin_sym_operation;
|
||||
}
|
||||
|
||||
static const TypeInfo cryptodev_builtin_info = {
|
||||
.name = TYPE_CRYPTODEV_BACKEND_BUILTIN,
|
||||
.parent = TYPE_CRYPTODEV_BACKEND,
|
||||
.class_init = cryptodev_builtin_class_init,
|
||||
.instance_size = sizeof(CryptoDevBackendBuiltin),
|
||||
};
|
||||
|
||||
static void
|
||||
cryptodev_builtin_register_types(void)
|
||||
{
|
||||
type_register_static(&cryptodev_builtin_info);
|
||||
}
|
||||
|
||||
type_init(cryptodev_builtin_register_types);
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* QEMU Crypto Device Implementation
|
||||
*
|
||||
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||
*
|
||||
* Authors:
|
||||
* Gonglei <arei.gonglei@huawei.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/cryptodev.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi-types.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "hw/virtio/virtio-crypto.h"
|
||||
|
||||
|
||||
static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients;
|
||||
|
||||
|
||||
CryptoDevBackendClient *
|
||||
cryptodev_backend_new_client(const char *model,
|
||||
const char *name)
|
||||
{
|
||||
CryptoDevBackendClient *cc;
|
||||
|
||||
cc = g_malloc0(sizeof(CryptoDevBackendClient));
|
||||
cc->model = g_strdup(model);
|
||||
if (name) {
|
||||
cc->name = g_strdup(name);
|
||||
}
|
||||
|
||||
QTAILQ_INSERT_TAIL(&crypto_clients, cc, next);
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
void cryptodev_backend_free_client(
|
||||
CryptoDevBackendClient *cc)
|
||||
{
|
||||
QTAILQ_REMOVE(&crypto_clients, cc, next);
|
||||
g_free(cc->name);
|
||||
g_free(cc->model);
|
||||
g_free(cc->info_str);
|
||||
g_free(cc);
|
||||
}
|
||||
|
||||
void cryptodev_backend_cleanup(
|
||||
CryptoDevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
CryptoDevBackendClass *bc =
|
||||
CRYPTODEV_BACKEND_GET_CLASS(backend);
|
||||
|
||||
if (bc->cleanup) {
|
||||
bc->cleanup(backend, errp);
|
||||
}
|
||||
|
||||
backend->ready = false;
|
||||
}
|
||||
|
||||
int64_t cryptodev_backend_sym_create_session(
|
||||
CryptoDevBackend *backend,
|
||||
CryptoDevBackendSymSessionInfo *sess_info,
|
||||
uint32_t queue_index, Error **errp)
|
||||
{
|
||||
CryptoDevBackendClass *bc =
|
||||
CRYPTODEV_BACKEND_GET_CLASS(backend);
|
||||
|
||||
if (bc->create_session) {
|
||||
return bc->create_session(backend, sess_info, queue_index, errp);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cryptodev_backend_sym_close_session(
|
||||
CryptoDevBackend *backend,
|
||||
uint64_t session_id,
|
||||
uint32_t queue_index, Error **errp)
|
||||
{
|
||||
CryptoDevBackendClass *bc =
|
||||
CRYPTODEV_BACKEND_GET_CLASS(backend);
|
||||
|
||||
if (bc->close_session) {
|
||||
return bc->close_session(backend, session_id, queue_index, errp);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cryptodev_backend_sym_operation(
|
||||
CryptoDevBackend *backend,
|
||||
CryptoDevBackendSymOpInfo *op_info,
|
||||
uint32_t queue_index, Error **errp)
|
||||
{
|
||||
CryptoDevBackendClass *bc =
|
||||
CRYPTODEV_BACKEND_GET_CLASS(backend);
|
||||
|
||||
if (bc->do_sym_op) {
|
||||
return bc->do_sym_op(backend, op_info, queue_index, errp);
|
||||
}
|
||||
|
||||
return -VIRTIO_CRYPTO_ERR;
|
||||
}
|
||||
|
||||
int cryptodev_backend_crypto_operation(
|
||||
CryptoDevBackend *backend,
|
||||
void *opaque,
|
||||
uint32_t queue_index, Error **errp)
|
||||
{
|
||||
VirtIOCryptoReq *req = opaque;
|
||||
|
||||
if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) {
|
||||
CryptoDevBackendSymOpInfo *op_info;
|
||||
op_info = req->u.sym_op_info;
|
||||
|
||||
return cryptodev_backend_sym_operation(backend,
|
||||
op_info, queue_index, errp);
|
||||
} else {
|
||||
error_setg(errp, "Unsupported cryptodev alg type: %" PRIu32 "",
|
||||
req->flags);
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
|
||||
return -VIRTIO_CRYPTO_ERR;
|
||||
}
|
||||
|
||||
static void
|
||||
cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||
uint32_t value = backend->conf.peers.queues;
|
||||
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void
|
||||
cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||
Error *local_err = NULL;
|
||||
uint32_t value;
|
||||
|
||||
visit_type_uint32(v, name, &value, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
if (!value) {
|
||||
error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
|
||||
PRIu32 "'", object_get_typename(obj), name, value);
|
||||
goto out;
|
||||
}
|
||||
backend->conf.peers.queues = value;
|
||||
out:
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
static void
|
||||
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
||||
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (bc->init) {
|
||||
bc->init(backend, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
backend->ready = true;
|
||||
return;
|
||||
|
||||
out:
|
||||
backend->ready = false;
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
static void cryptodev_backend_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add(obj, "queues", "int",
|
||||
cryptodev_backend_get_queues,
|
||||
cryptodev_backend_set_queues,
|
||||
NULL, NULL, NULL);
|
||||
/* Initialize devices' queues property to 1 */
|
||||
object_property_set_int(obj, 1, "queues", NULL);
|
||||
}
|
||||
|
||||
static void cryptodev_backend_finalize(Object *obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
cryptodev_backend_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
|
||||
|
||||
ucc->complete = cryptodev_backend_complete;
|
||||
|
||||
QTAILQ_INIT(&crypto_clients);
|
||||
}
|
||||
|
||||
static const TypeInfo cryptodev_backend_info = {
|
||||
.name = TYPE_CRYPTODEV_BACKEND,
|
||||
.parent = TYPE_OBJECT,
|
||||
.instance_size = sizeof(CryptoDevBackend),
|
||||
.instance_init = cryptodev_backend_instance_init,
|
||||
.instance_finalize = cryptodev_backend_finalize,
|
||||
.class_size = sizeof(CryptoDevBackendClass),
|
||||
.class_init = cryptodev_backend_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
cryptodev_backend_register_types(void)
|
||||
{
|
||||
type_register_static(&cryptodev_backend_info);
|
||||
}
|
||||
|
||||
type_init(cryptodev_backend_register_types);
|
||||
@@ -4,6 +4,9 @@ QEMU<->ACPI BIOS memory hotplug interface
|
||||
ACPI BIOS GPE.3 handler is dedicated for notifying OS about memory hot-add
|
||||
and hot-remove events.
|
||||
|
||||
ACPI BIOS GPE.4 handler is dedicated for notifying OS about nvdimm device
|
||||
hot-add and hot-remove events.
|
||||
|
||||
Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access):
|
||||
---------------------------------------------------------------
|
||||
0xa00:
|
||||
|
||||
@@ -127,6 +127,58 @@ _DSM process diagram:
|
||||
| result from the page | | |
|
||||
+--------------------------+ +--------------+
|
||||
|
||||
_FIT implementation
|
||||
-------------------
|
||||
TODO (will fill it when nvdimm hotplug is introduced)
|
||||
Device Handle Reservation
|
||||
-------------------------
|
||||
As we mentioned above, byte 0 ~ byte 3 in the DSM memory save NVDIMM device
|
||||
handle. The handle is completely QEMU internal thing, the values in range
|
||||
[0, 0xFFFF] indicate nvdimm device (O means nvdimm root device named NVDR),
|
||||
other values are reserved by other purpose.
|
||||
|
||||
Current reserved handle:
|
||||
0x10000 is reserved for QEMU internal DSM function called on the root
|
||||
device.
|
||||
|
||||
QEMU internal use only _DSM function
|
||||
------------------------------------
|
||||
UUID, 648B9CF2-CDA1-4312-8AD9-49C4AF32BD62, is reserved for QEMU internal
|
||||
DSM function.
|
||||
|
||||
There is the function introduced by QEMU and only used by QEMU internal.
|
||||
|
||||
1) Read FIT
|
||||
As we only reserved one page for NVDIMM ACPI it is impossible to map the
|
||||
whole FIT data to guest's address space. This function is used by _FIT
|
||||
method to read a piece of FIT data from QEMU.
|
||||
|
||||
Input parameters:
|
||||
Arg0 – UUID {set to 648B9CF2-CDA1-4312-8AD9-49C4AF32BD62}
|
||||
Arg1 – Revision ID (set to 1)
|
||||
Arg2 - Function Index, 0x1
|
||||
Arg3 - A package containing a buffer whose layout is as follows:
|
||||
|
||||
+----------+-------------+-------------+-----------------------------------+
|
||||
| Filed | Byte Length | Byte Offset | Description |
|
||||
+----------+-------------+-------------+-----------------------------------+
|
||||
| offset | 4 | 0 | the offset of FIT buffer |
|
||||
+----------+-------------+-------------+-----------------------------------+
|
||||
|
||||
Output:
|
||||
+----------+-------------+-------------+-----------------------------------+
|
||||
| Filed | Byte Length | Byte Offset | Description |
|
||||
+----------+-------------+-------------+-----------------------------------+
|
||||
| | | | return status codes |
|
||||
| | | | 0x100 indicates fit has been |
|
||||
| status | 4 | 0 | updated |
|
||||
| | | | other follows Chapter 3 in DSM |
|
||||
| | | | Spec Rev1 |
|
||||
+----------+-------------+-------------+-----------------------------------+
|
||||
| fit data | Varies | 4 | FIT data |
|
||||
| | | | |
|
||||
+----------+-------------+-------------+-----------------------------------+
|
||||
|
||||
The FIT offset is maintained by the caller itself, current offset plugs
|
||||
the length returned by the function is the next offset we should read.
|
||||
When all the FIT data has been read out, zero length is returned.
|
||||
|
||||
If it returns 0x100, OSPM should restart to read FIT (read from offset 0
|
||||
again).
|
||||
|
||||
@@ -3,7 +3,7 @@ common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
|
||||
common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
|
||||
common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o memory_hotplug_acpi_table.o
|
||||
common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
|
||||
obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
|
||||
common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
|
||||
common-obj-$(CONFIG_ACPI) += acpi_interface.o
|
||||
common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
|
||||
common-obj-$(CONFIG_ACPI) += aml-build.o
|
||||
|
||||
@@ -99,6 +99,7 @@ void build_acpi_ipmi_devices(Aml *scope, BusState *bus)
|
||||
|
||||
ii = IPMI_INTERFACE(obj);
|
||||
iic = IPMI_INTERFACE_GET_CLASS(obj);
|
||||
memset(&info, 0, sizeof(info));
|
||||
iic->get_fwinfo(ii, &info);
|
||||
aml_append(scope, aml_ipmi_device(&info));
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "hw/acpi/memory_hotplug.h"
|
||||
#include "hw/acpi/pc-hotplug.h"
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "trace.h"
|
||||
@@ -232,11 +233,8 @@ void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
MemStatus *mdev;
|
||||
DeviceClass *dc = DEVICE_GET_CLASS(dev);
|
||||
|
||||
if (!dc->hotpluggable) {
|
||||
return;
|
||||
}
|
||||
AcpiEventStatusBits event;
|
||||
bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
|
||||
|
||||
mdev = acpi_memory_slot_status(mem_st, dev, errp);
|
||||
if (!mdev) {
|
||||
@@ -244,10 +242,23 @@ void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
|
||||
}
|
||||
|
||||
mdev->dimm = dev;
|
||||
mdev->is_enabled = true;
|
||||
|
||||
/*
|
||||
* do not set is_enabled and is_inserting if the slot is plugged with
|
||||
* a nvdimm device to stop OSPM inquires memory region from the slot.
|
||||
*/
|
||||
if (is_nvdimm) {
|
||||
event = ACPI_NVDIMM_HOTPLUG_STATUS;
|
||||
} else {
|
||||
mdev->is_enabled = true;
|
||||
event = ACPI_MEMORY_HOTPLUG_STATUS;
|
||||
}
|
||||
|
||||
if (dev->hotplugged) {
|
||||
mdev->is_inserting = true;
|
||||
acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
|
||||
if (!is_nvdimm) {
|
||||
mdev->is_inserting = true;
|
||||
}
|
||||
acpi_send_event(DEVICE(hotplug_dev), event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +273,8 @@ void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
return;
|
||||
}
|
||||
|
||||
/* nvdimm device hot unplug is not supported yet. */
|
||||
assert(!object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM));
|
||||
mdev->is_removing = true;
|
||||
acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
|
||||
}
|
||||
@@ -276,6 +289,8 @@ void acpi_memory_unplug_cb(MemHotplugState *mem_st,
|
||||
return;
|
||||
}
|
||||
|
||||
/* nvdimm device hot unplug is not supported yet. */
|
||||
assert(!object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM));
|
||||
mdev->is_enabled = false;
|
||||
mdev->dimm = NULL;
|
||||
}
|
||||
|
||||
+359
-107
File diff suppressed because it is too large
Load Diff
@@ -88,23 +88,28 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
||||
|
||||
*dataplane = NULL;
|
||||
|
||||
if (!conf->iothread) {
|
||||
return;
|
||||
}
|
||||
if (conf->iothread) {
|
||||
if (!k->set_guest_notifiers || !k->ioeventfd_assign) {
|
||||
error_setg(errp,
|
||||
"device is incompatible with iothread "
|
||||
"(transport does not support notifiers)");
|
||||
return;
|
||||
}
|
||||
if (!virtio_device_ioeventfd_enabled(vdev)) {
|
||||
error_setg(errp, "ioeventfd is required for iothread");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If dataplane is (re-)enabled while the guest is running there could
|
||||
* be block jobs that can conflict.
|
||||
*/
|
||||
if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
|
||||
error_prepend(errp, "cannot start virtio-blk dataplane: ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Don't try if transport does not support notifiers. */
|
||||
if (!k->set_guest_notifiers || !k->ioeventfd_started) {
|
||||
error_setg(errp,
|
||||
"device is incompatible with dataplane "
|
||||
"(transport does not support notifiers)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If dataplane is (re-)enabled while the guest is running there could be
|
||||
* block jobs that can conflict.
|
||||
*/
|
||||
if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
|
||||
error_prepend(errp, "cannot start dataplane thread: ");
|
||||
if (!virtio_device_ioeventfd_enabled(vdev)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -112,9 +117,13 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
||||
s->vdev = vdev;
|
||||
s->conf = conf;
|
||||
|
||||
s->iothread = conf->iothread;
|
||||
object_ref(OBJECT(s->iothread));
|
||||
s->ctx = iothread_get_aio_context(s->iothread);
|
||||
if (conf->iothread) {
|
||||
s->iothread = conf->iothread;
|
||||
object_ref(OBJECT(s->iothread));
|
||||
s->ctx = iothread_get_aio_context(s->iothread);
|
||||
} else {
|
||||
s->ctx = qemu_get_aio_context();
|
||||
}
|
||||
s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
|
||||
s->batch_notify_vqs = bitmap_new(conf->num_queues);
|
||||
|
||||
@@ -124,14 +133,19 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
||||
/* Context: QEMU global mutex held */
|
||||
void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
||||
{
|
||||
VirtIOBlock *vblk;
|
||||
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
||||
virtio_blk_data_plane_stop(s);
|
||||
vblk = VIRTIO_BLK(s->vdev);
|
||||
assert(!vblk->dataplane_started);
|
||||
g_free(s->batch_notify_vqs);
|
||||
qemu_bh_delete(s->bh);
|
||||
object_unref(OBJECT(s->iothread));
|
||||
if (s->iothread) {
|
||||
object_unref(OBJECT(s->iothread));
|
||||
}
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
@@ -147,17 +161,18 @@ static void virtio_blk_data_plane_handle_output(VirtIODevice *vdev,
|
||||
}
|
||||
|
||||
/* Context: QEMU global mutex held */
|
||||
void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
||||
int virtio_blk_data_plane_start(VirtIODevice *vdev)
|
||||
{
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
|
||||
VirtIOBlock *vblk = VIRTIO_BLK(vdev);
|
||||
VirtIOBlockDataPlane *s = vblk->dataplane;
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vblk)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
|
||||
unsigned i;
|
||||
unsigned nvqs = s->conf->num_queues;
|
||||
int r;
|
||||
|
||||
if (vblk->dataplane_started || s->starting) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->starting = true;
|
||||
@@ -204,20 +219,22 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
||||
virtio_blk_data_plane_handle_output);
|
||||
}
|
||||
aio_context_release(s->ctx);
|
||||
return;
|
||||
return 0;
|
||||
|
||||
fail_guest_notifiers:
|
||||
vblk->dataplane_disabled = true;
|
||||
s->starting = false;
|
||||
vblk->dataplane_started = true;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* Context: QEMU global mutex held */
|
||||
void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
|
||||
void virtio_blk_data_plane_stop(VirtIODevice *vdev)
|
||||
{
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
|
||||
VirtIOBlock *vblk = VIRTIO_BLK(vdev);
|
||||
VirtIOBlockDataPlane *s = vblk->dataplane;
|
||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vblk));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
|
||||
unsigned i;
|
||||
unsigned nvqs = s->conf->num_queues;
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
||||
VirtIOBlockDataPlane **dataplane,
|
||||
Error **errp);
|
||||
void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s);
|
||||
void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s);
|
||||
void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s);
|
||||
void virtio_blk_data_plane_drain(VirtIOBlockDataPlane *s);
|
||||
void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s, VirtQueue *vq);
|
||||
|
||||
int virtio_blk_data_plane_start(VirtIODevice *vdev);
|
||||
void virtio_blk_data_plane_stop(VirtIODevice *vdev);
|
||||
|
||||
#endif /* HW_DATAPLANE_VIRTIO_BLK_H */
|
||||
|
||||
@@ -611,7 +611,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
/* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
|
||||
* dataplane here instead of waiting for .set_status().
|
||||
*/
|
||||
virtio_blk_data_plane_start(s->dataplane);
|
||||
virtio_device_start_ioeventfd(vdev);
|
||||
if (!s->dataplane_disabled) {
|
||||
return;
|
||||
}
|
||||
@@ -687,11 +687,9 @@ static void virtio_blk_reset(VirtIODevice *vdev)
|
||||
virtio_blk_free_request(req);
|
||||
}
|
||||
|
||||
if (s->dataplane) {
|
||||
virtio_blk_data_plane_stop(s->dataplane);
|
||||
}
|
||||
aio_context_release(ctx);
|
||||
|
||||
assert(!s->dataplane_started);
|
||||
blk_set_enable_write_cache(s->blk, s->original_wce);
|
||||
}
|
||||
|
||||
@@ -789,9 +787,8 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
|
||||
{
|
||||
VirtIOBlock *s = VIRTIO_BLK(vdev);
|
||||
|
||||
if (s->dataplane && !(status & (VIRTIO_CONFIG_S_DRIVER |
|
||||
VIRTIO_CONFIG_S_DRIVER_OK))) {
|
||||
virtio_blk_data_plane_stop(s->dataplane);
|
||||
if (!(status & (VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK))) {
|
||||
assert(!s->dataplane_started);
|
||||
}
|
||||
|
||||
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||
@@ -919,7 +916,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
|
||||
s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1;
|
||||
|
||||
for (i = 0; i < conf->num_queues; i++) {
|
||||
virtio_add_queue_aio(vdev, 128, virtio_blk_handle_output);
|
||||
virtio_add_queue(vdev, 128, virtio_blk_handle_output);
|
||||
}
|
||||
virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err);
|
||||
if (err != NULL) {
|
||||
@@ -1002,6 +999,8 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
|
||||
vdc->reset = virtio_blk_reset;
|
||||
vdc->save = virtio_blk_save_device;
|
||||
vdc->load = virtio_blk_load_device;
|
||||
vdc->start_ioeventfd = virtio_blk_data_plane_start;
|
||||
vdc->stop_ioeventfd = virtio_blk_data_plane_stop;
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_blk_info = {
|
||||
|
||||
@@ -35,6 +35,17 @@ void hotplug_handler_plug(HotplugHandler *plug_handler,
|
||||
}
|
||||
}
|
||||
|
||||
void hotplug_handler_post_plug(HotplugHandler *plug_handler,
|
||||
DeviceState *plugged_dev,
|
||||
Error **errp)
|
||||
{
|
||||
HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
|
||||
|
||||
if (hdc->post_plug) {
|
||||
hdc->post_plug(plug_handler, plugged_dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
void hotplug_handler_unplug_request(HotplugHandler *plug_handler,
|
||||
DeviceState *plugged_dev,
|
||||
Error **errp)
|
||||
|
||||
+17
-5
@@ -945,10 +945,21 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
||||
goto child_realize_fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->hotplugged) {
|
||||
device_reset(dev);
|
||||
}
|
||||
dev->pending_deleted_event = false;
|
||||
dev->realized = value;
|
||||
|
||||
if (hotplug_ctrl) {
|
||||
hotplug_handler_post_plug(hotplug_ctrl, dev, &local_err);
|
||||
}
|
||||
|
||||
if (local_err != NULL) {
|
||||
dev->realized = value;
|
||||
goto post_realize_fail;
|
||||
}
|
||||
} else if (!value && dev->realized) {
|
||||
Error **local_errp = NULL;
|
||||
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||
@@ -965,13 +976,14 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
||||
}
|
||||
dev->pending_deleted_event = true;
|
||||
DEVICE_LISTENER_CALL(unrealize, Reverse, dev);
|
||||
|
||||
if (local_err != NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev->realized = value;
|
||||
}
|
||||
|
||||
if (local_err != NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev->realized = value;
|
||||
return;
|
||||
|
||||
child_realize_fail:
|
||||
|
||||
@@ -2068,6 +2068,13 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
method = aml_method("_E03", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_call0(MEMORY_HOTPLUG_HANDLER_PATH));
|
||||
aml_append(scope, method);
|
||||
|
||||
if (pcms->acpi_nvdimm_state.is_enabled) {
|
||||
method = aml_method("_E04", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_notify(aml_name("\\_SB.NVDR"),
|
||||
aml_int(0x80)));
|
||||
aml_append(scope, method);
|
||||
}
|
||||
}
|
||||
aml_append(dsdt, scope);
|
||||
|
||||
@@ -2810,7 +2817,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
}
|
||||
if (pcms->acpi_nvdimm_state.is_enabled) {
|
||||
nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
|
||||
pcms->acpi_nvdimm_state.dsm_mem);
|
||||
&pcms->acpi_nvdimm_state, machine->ram_slots);
|
||||
}
|
||||
|
||||
/* Add tables supplied by user (if any) */
|
||||
|
||||
@@ -1721,6 +1721,16 @@ out:
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
static void pc_dimm_post_plug(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
|
||||
nvdimm_acpi_hotplug(&pcms->acpi_nvdimm_state);
|
||||
}
|
||||
}
|
||||
|
||||
static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
@@ -1734,6 +1744,12 @@ static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
|
||||
error_setg(&local_err,
|
||||
"nvdimm device hot unplug is not supported yet.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
|
||||
hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
|
||||
|
||||
@@ -1751,6 +1767,12 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
|
||||
HotplugHandlerClass *hhc;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
|
||||
error_setg(&local_err,
|
||||
"nvdimm device hot unplug is not supported yet.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
|
||||
hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
|
||||
|
||||
@@ -1986,6 +2008,14 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||
}
|
||||
}
|
||||
|
||||
static void pc_machine_device_post_plug_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||
pc_dimm_post_plug(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
@@ -2290,6 +2320,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->reset = pc_machine_reset;
|
||||
hc->pre_plug = pc_machine_device_pre_plug_cb;
|
||||
hc->plug = pc_machine_device_plug_cb;
|
||||
hc->post_plug = pc_machine_device_post_plug_cb;
|
||||
hc->unplug_request = pc_machine_device_unplug_request_cb;
|
||||
hc->unplug = pc_machine_device_unplug_cb;
|
||||
nc->nmi_monitor_handler = x86_nmi;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
common-obj-$(CONFIG_IPMI) += ipmi.o
|
||||
common-obj-$(CONFIG_IPMI_LOCAL) += ipmi_bmc_sim.o
|
||||
common-obj-$(CONFIG_IPMI_LOCAL) += ipmi_bmc_extern.o
|
||||
common-obj-$(CONFIG_IPMI_EXTERN) += ipmi_bmc_extern.o
|
||||
common-obj-$(CONFIG_ISA_IPMI_KCS) += isa_ipmi_kcs.o
|
||||
common-obj-$(CONFIG_ISA_IPMI_BT) += isa_ipmi_bt.o
|
||||
|
||||
+8
-2
@@ -51,7 +51,7 @@ static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
|
||||
if (checkonly) {
|
||||
return 0;
|
||||
}
|
||||
qemu_system_powerdown_request();
|
||||
qemu_system_shutdown_request();
|
||||
return 0;
|
||||
|
||||
case IPMI_SEND_NMI:
|
||||
@@ -61,9 +61,15 @@ static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
|
||||
qmp_inject_nmi(NULL);
|
||||
return 0;
|
||||
|
||||
case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
|
||||
if (checkonly) {
|
||||
return 0;
|
||||
}
|
||||
qemu_system_powerdown_request();
|
||||
return 0;
|
||||
|
||||
case IPMI_POWERCYCLE_CHASSIS:
|
||||
case IPMI_PULSE_DIAG_IRQ:
|
||||
case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
|
||||
case IPMI_POWERON_CHASSIS:
|
||||
default:
|
||||
return IPMI_CC_COMMAND_NOT_SUPPORTED;
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
#define VM_CAPABILITIES_IRQ 0x04
|
||||
#define VM_CAPABILITIES_NMI 0x08
|
||||
#define VM_CAPABILITIES_ATTN 0x10
|
||||
#define VM_CMD_FORCEOFF 0x09
|
||||
#define VM_CAPABILITIES_GRACEFUL_SHUTDOWN 0x20
|
||||
#define VM_CMD_GRACEFUL_SHUTDOWN 0x09
|
||||
|
||||
#define TYPE_IPMI_BMC_EXTERN "ipmi-bmc-extern"
|
||||
#define IPMI_BMC_EXTERN(obj) OBJECT_CHECK(IPMIBmcExtern, (obj), \
|
||||
@@ -276,8 +277,8 @@ static void handle_hw_op(IPMIBmcExtern *ibe, unsigned char hw_op)
|
||||
k->do_hw_op(s, IPMI_SEND_NMI, 0);
|
||||
break;
|
||||
|
||||
case VM_CMD_FORCEOFF:
|
||||
qemu_system_shutdown_request();
|
||||
case VM_CMD_GRACEFUL_SHUTDOWN:
|
||||
k->do_hw_op(s, IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -401,6 +402,10 @@ static void chr_event(void *opaque, int event)
|
||||
if (k->do_hw_op(ibe->parent.intf, IPMI_POWEROFF_CHASSIS, 1) == 0) {
|
||||
v |= VM_CAPABILITIES_POWER;
|
||||
}
|
||||
if (k->do_hw_op(ibe->parent.intf, IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 1)
|
||||
== 0) {
|
||||
v |= VM_CAPABILITIES_GRACEFUL_SHUTDOWN;
|
||||
}
|
||||
if (k->do_hw_op(ibe->parent.intf, IPMI_RESET_CHASSIS, 1) == 0) {
|
||||
v |= VM_CAPABILITIES_RESET;
|
||||
}
|
||||
@@ -512,6 +517,7 @@ static void ipmi_bmc_extern_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
bk->handle_command = ipmi_bmc_extern_handle_command;
|
||||
bk->handle_reset = ipmi_bmc_extern_handle_reset;
|
||||
dc->hotpluggable = false;
|
||||
dc->realize = ipmi_bmc_extern_realize;
|
||||
dc->props = ipmi_bmc_extern_properties;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user