summaryrefslogtreecommitdiff
path: root/usr/src/cmd/bhyve/smbiostbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/bhyve/smbiostbl.c')
-rw-r--r--usr/src/cmd/bhyve/smbiostbl.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/usr/src/cmd/bhyve/smbiostbl.c b/usr/src/cmd/bhyve/smbiostbl.c
index da227f813a..8af8a85755 100644
--- a/usr/src/cmd/bhyve/smbiostbl.c
+++ b/usr/src/cmd/bhyve/smbiostbl.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <vmmapi.h>
#include "bhyverun.h"
+#include "debug.h"
#include "smbiostbl.h"
#define MB (1024*1024)
@@ -255,7 +256,7 @@ struct smbios_table_type17 {
uint16_t errhand; /* handle of mem error data */
uint16_t twidth; /* total width in bits */
uint16_t dwidth; /* data width in bits */
- uint16_t size; /* size in bytes */
+ uint16_t size; /* size in kb or mb */
uint8_t form; /* form factor */
uint8_t set; /* set */
uint8_t dloc; /* device locator string */
@@ -268,7 +269,7 @@ struct smbios_table_type17 {
uint8_t asset; /* asset tag string */
uint8_t part; /* part number string */
uint8_t attributes; /* attributes */
- uint32_t xsize; /* extended size in mbs */
+ uint32_t xsize; /* extended size in mb */
uint16_t curspeed; /* current speed in mhz */
uint16_t minvoltage; /* minimum voltage */
uint16_t maxvoltage; /* maximum voltage */
@@ -444,7 +445,7 @@ struct smbios_table_type17 smbios_type17_template = {
-1, /* handle of memory error data */
64, /* total width in bits including ecc */
64, /* data width in bits */
- 0x7fff, /* size in bytes (0x7fff=use extended)*/
+ 0, /* size in kb or mb (0x7fff=use extended)*/
SMBIOS_MDFF_UNKNOWN,
0, /* set (0x00=none, 0xff=unknown) */
1, /* device locator string */
@@ -695,20 +696,39 @@ smbios_type17_initializer(struct smbios_structure *template_entry,
uint16_t *n, uint16_t *size)
{
struct smbios_table_type17 *type17;
+ uint64_t memsize, size_KB, size_MB;
smbios_generic_initializer(template_entry, template_strings,
curaddr, endaddr, n, size);
type17 = (struct smbios_table_type17 *)curaddr;
type17->arrayhand = type16_handle;
- type17->xsize = guest_lomem;
- if (guest_himem > 0) {
- curaddr = *endaddr;
- smbios_generic_initializer(template_entry, template_strings,
- curaddr, endaddr, n, size);
- type17 = (struct smbios_table_type17 *)curaddr;
- type17->arrayhand = type16_handle;
- type17->xsize = guest_himem;
+ memsize = guest_lomem + guest_himem;
+ size_KB = memsize / 1024;
+ size_MB = memsize / MB;
+
+ /* A single Type 17 entry can't represent more than ~2PB RAM */
+ if (size_MB > 0x7FFFFFFF) {
+ printf("Warning: guest memory too big for SMBIOS Type 17 table: "
+ "%luMB greater than max supported 2147483647MB\n", size_MB);
+
+ size_MB = 0x7FFFFFFF;
+ }
+
+ /* See SMBIOS 2.7.0 section 7.18 - Memory Device (Type 17) */
+ if (size_KB <= 0x7FFF) {
+ /* Can represent up to 32767KB with the top bit set */
+ type17->size = size_KB | (1 << 15);
+ } else if (size_MB < 0x7FFF) {
+ /* Can represent up to 32766MB with the top bit unset */
+ type17->size = size_MB & 0x7FFF;
+ } else {
+ type17->size = 0x7FFF;
+ /*
+ * Can represent up to 2147483647MB (~2PB)
+ * The top bit is reserved
+ */
+ type17->xsize = size_MB & 0x7FFFFFFF;
}
return (0);
@@ -755,7 +775,7 @@ smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr)
memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR,
SMBIOS_ENTRY_IANCHORLEN);
smbios_ep->staddr = staddr;
- smbios_ep->bcdrev = 0x24;
+ smbios_ep->bcdrev = (smbios_ep->major & 0xf) << 4 | (smbios_ep->minor & 0xf);
}
static void
@@ -797,7 +817,7 @@ smbios_build(struct vmctx *ctx)
startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH);
if (startaddr == NULL) {
- fprintf(stderr, "smbios table requires mapped mem\n");
+ EPRINTLN("smbios table requires mapped mem");
return (ENOMEM);
}