bhyve: add common fwcfg items
Qemu defines some common fwcfg items. We don't need to support all of them. Only a subset needs to be present for fwcfg to work properly. - signature The signature is used by the guest to check if qemu's fwcfg is available or not. - id The id is used by the guest to check which features are supported by the fwcfg implementation of the hypervisor. - file_dir The file dir reports all fwcfg items which don't have a fixed index. These are mostly user defined fwcfg items. Reviewed by: <If someone else reviewed your modification.> MFC after: 1 week Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D38335
This commit is contained in:
parent
3ef46195ac
commit
34f804e547
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/endian.h>
|
||||
|
||||
#include <machine/vmm.h>
|
||||
|
||||
@ -38,6 +39,12 @@
|
||||
#define QEMU_FWCFG_ARCHITECTURE_GENERIC 0
|
||||
#define QEMU_FWCFG_ARCHITECTURE_SPECIFIC 1
|
||||
|
||||
#define QEMU_FWCFG_INDEX_SIGNATURE 0x00
|
||||
#define QEMU_FWCFG_INDEX_ID 0x01
|
||||
#define QEMU_FWCFG_INDEX_FILE_DIR 0x19
|
||||
|
||||
#define QEMU_FWCFG_MIN_FILES 10
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
union qemu_fwcfg_selector {
|
||||
@ -49,6 +56,28 @@ union qemu_fwcfg_selector {
|
||||
uint16_t bits;
|
||||
};
|
||||
|
||||
struct qemu_fwcfg_signature {
|
||||
uint8_t signature[4];
|
||||
};
|
||||
|
||||
struct qemu_fwcfg_id {
|
||||
uint32_t interface : 1; /* always set */
|
||||
uint32_t DMA : 1;
|
||||
uint32_t reserved : 30;
|
||||
};
|
||||
|
||||
struct qemu_fwcfg_file {
|
||||
uint32_t be_size;
|
||||
uint16_t be_selector;
|
||||
uint16_t reserved;
|
||||
uint8_t name[QEMU_FWCFG_MAX_NAME];
|
||||
};
|
||||
|
||||
struct qemu_fwcfg_directory {
|
||||
uint32_t be_count;
|
||||
struct qemu_fwcfg_file files[0];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
struct qemu_fwcfg_softc {
|
||||
@ -155,6 +184,62 @@ qemu_fwcfg_add_item(const uint16_t architecture, const uint16_t index,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
qemu_fwcfg_add_item_file_dir(void)
|
||||
{
|
||||
const size_t size = sizeof(struct qemu_fwcfg_directory) +
|
||||
QEMU_FWCFG_MIN_FILES * sizeof(struct qemu_fwcfg_file);
|
||||
struct qemu_fwcfg_directory *const fwcfg_directory = calloc(1, size);
|
||||
if (fwcfg_directory == NULL) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
fwcfg_sc.directory = fwcfg_directory;
|
||||
|
||||
return (qemu_fwcfg_add_item(QEMU_FWCFG_ARCHITECTURE_GENERIC,
|
||||
QEMU_FWCFG_INDEX_FILE_DIR, sizeof(struct qemu_fwcfg_directory),
|
||||
(uint8_t *)fwcfg_sc.directory));
|
||||
}
|
||||
|
||||
static int
|
||||
qemu_fwcfg_add_item_id(void)
|
||||
{
|
||||
struct qemu_fwcfg_id *const fwcfg_id = calloc(1,
|
||||
sizeof(struct qemu_fwcfg_id));
|
||||
if (fwcfg_id == NULL) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
fwcfg_id->interface = 1;
|
||||
fwcfg_id->DMA = 0;
|
||||
|
||||
uint32_t *const le_fwcfg_id_ptr = (uint32_t *)fwcfg_id;
|
||||
*le_fwcfg_id_ptr = htole32(*le_fwcfg_id_ptr);
|
||||
|
||||
return (qemu_fwcfg_add_item(QEMU_FWCFG_ARCHITECTURE_GENERIC,
|
||||
QEMU_FWCFG_INDEX_ID, sizeof(struct qemu_fwcfg_id),
|
||||
(uint8_t *)fwcfg_id));
|
||||
}
|
||||
|
||||
static int
|
||||
qemu_fwcfg_add_item_signature(void)
|
||||
{
|
||||
struct qemu_fwcfg_signature *const fwcfg_signature = calloc(1,
|
||||
sizeof(struct qemu_fwcfg_signature));
|
||||
if (fwcfg_signature == NULL) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
fwcfg_signature->signature[0] = 'Q';
|
||||
fwcfg_signature->signature[1] = 'E';
|
||||
fwcfg_signature->signature[2] = 'M';
|
||||
fwcfg_signature->signature[3] = 'U';
|
||||
|
||||
return (qemu_fwcfg_add_item(QEMU_FWCFG_ARCHITECTURE_GENERIC,
|
||||
QEMU_FWCFG_INDEX_SIGNATURE, sizeof(struct qemu_fwcfg_signature),
|
||||
(uint8_t *)fwcfg_signature));
|
||||
}
|
||||
|
||||
static int
|
||||
qemu_fwcfg_register_port(const char *const name, const int port, const int size,
|
||||
const int flags, const inout_func_t handler)
|
||||
@ -209,6 +294,20 @@ qemu_fwcfg_init(struct vmctx *const ctx)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* add common fwcfg items */
|
||||
if ((error = qemu_fwcfg_add_item_signature()) != 0) {
|
||||
warnx("%s: Unable to add signature item", __func__);
|
||||
goto done;
|
||||
}
|
||||
if ((error = qemu_fwcfg_add_item_id()) != 0) {
|
||||
warnx("%s: Unable to add id item", __func__);
|
||||
goto done;
|
||||
}
|
||||
if ((error = qemu_fwcfg_add_item_file_dir()) != 0) {
|
||||
warnx("%s: Unable to add file_dir item", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
if (error) {
|
||||
acpi_device_destroy(fwcfg_sc.acpi_dev);
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#define QEMU_FWCFG_MAX_ARCHS 0x2
|
||||
#define QEMU_FWCFG_MAX_ENTRIES 0x4000
|
||||
#define QEMU_FWCFG_MAX_NAME 56
|
||||
|
||||
struct qemu_fwcfg_item {
|
||||
uint32_t size;
|
||||
|
Loading…
Reference in New Issue
Block a user