From 66a9cc68640459b14e330f94bcab980ef58fd66d Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Wed, 26 Oct 2022 01:21:24 +0000 Subject: 14957 pcieadm overloads header1.iobasehi Reviewed by: Andy Fiddaman Approved by: Dan McDonald --- usr/src/cmd/pcieadm/pcieadm_cfgspace.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/usr/src/cmd/pcieadm/pcieadm_cfgspace.c b/usr/src/cmd/pcieadm/pcieadm_cfgspace.c index d6a4a931b1..7ee88a6d58 100644 --- a/usr/src/cmd/pcieadm/pcieadm_cfgspace.c +++ b/usr/src/cmd/pcieadm/pcieadm_cfgspace.c @@ -722,7 +722,7 @@ pcieadm_cfgspace_print_bars(pcieadm_cfgspace_walk_t *walkp, break; } - pcieadm_field_printf(walkp, "addr", "Address", addr, + pcieadm_field_printf(walkp, "type", "Memory Type", addr, "%s (0x%x)\n", locstr, type >> 1); pcieadm_field_printf(walkp, "prefetch", "Prefetchable", pre != 0, "%s (0x%x)\n", pre != 0 ? "yes" : "no", @@ -1100,7 +1100,7 @@ static const pcieadm_cfgspace_print_t pcieadm_cfgspace_type1[] = { pcieadm_cfgspace_print_hex }, { PCI_BCNF_IO_BASE_HI, 2, "iobasehi", "I/O Base Upper 16 bits", pcieadm_cfgspace_print_hex }, - { PCI_BCNF_IO_LIMIT_HI, 2, "iobasehi", "I/O Limit Upper 16 bits", + { PCI_BCNF_IO_LIMIT_HI, 2, "iolimithi", "I/O Limit Upper 16 bits", pcieadm_cfgspace_print_hex }, { PCI_BCNF_CAP_PTR, 1, "cap", "Capabilities Pointer", pcieadm_cfgspace_print_hex }, @@ -1494,7 +1494,7 @@ static const pcieadm_regdef_t pcieadm_regdef_pcie_slotcap[] = { .prd_val = { .prdv_strval = { "no", "yes" } } }, { 3, 3, "attnind", "Attention Indicator Present", PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, - { 4, 4, "powind", "Power Indicator Present", PRDV_STRVAL, + { 4, 4, "pwrind", "Power Indicator Present", PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, { 5, 5, "hpsup", "Hot-Plug Surprise", PRDV_STRVAL, .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, @@ -1513,11 +1513,11 @@ static const pcieadm_regdef_t pcieadm_regdef_pcie_slotcap[] = { static const pcieadm_regdef_t pcieadm_regdef_pcie_slotctl[] = { { 0, 0, "attnbtn", "Attention Button Pressed", PRDV_STRVAL, .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, - { 1, 1, "powflt", "Power Fault Detected", PRDV_STRVAL, + { 1, 1, "pwrflt", "Power Fault Detected", PRDV_STRVAL, .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, - { 2, 2, "mrlsen", "MRL Sensor Changed", PRDV_STRVAL, + { 2, 2, "mrlchg", "MRL Sensor Changed", PRDV_STRVAL, .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, - { 3, 3, "presdet", "Presence Detect Changed", PRDV_STRVAL, + { 3, 3, "preschg", "Presence Detect Changed", PRDV_STRVAL, .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, { 4, 4, "ccmpltint", "Command Complete Interrupt", PRDV_STRVAL, .prd_val = { .prdv_strval = { "disabled", "Enabled" } } }, @@ -1525,7 +1525,7 @@ static const pcieadm_regdef_t pcieadm_regdef_pcie_slotctl[] = { .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, { 6, 7, "attnind", "Attention Indicator Control", PRDV_STRVAL, .prd_val = { .prdv_strval = { NULL, "on", "blink", "off" } } }, - { 8, 9, "powin", "Power Indicator Control", PRDV_STRVAL, + { 8, 9, "pwrin", "Power Indicator Control", PRDV_STRVAL, .prd_val = { .prdv_strval = { NULL, "on", "blink", "off" } } }, { 10, 10, "pwrctrl", "Power Controller Control", PRDV_STRVAL, .prd_val = { .prdv_strval = { "power on", "power off" } } }, @@ -1542,11 +1542,11 @@ static const pcieadm_regdef_t pcieadm_regdef_pcie_slotctl[] = { static const pcieadm_regdef_t pcieadm_regdef_pcie_slotsts[] = { { 0, 0, "attnbtn", "Attention Button Pressed", PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, - { 1, 1, "powflt", "Power Fault Detected", PRDV_STRVAL, + { 1, 1, "pwrflt", "Power Fault Detected", PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, - { 2, 2, "mrlsen", "MRL Sensor Changed", PRDV_STRVAL, + { 2, 2, "mrlchg", "MRL Sensor Changed", PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, - { 3, 3, "presdet", "Presence Detect Changed", PRDV_STRVAL, + { 3, 3, "preschg", "Presence Detect Changed", PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, { 4, 4, "ccmplt", "Command Complete", PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, @@ -2373,7 +2373,7 @@ static const pcieadm_cfgspace_print_t pcieadm_cap_l1pm_v1[] = { pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_cap }, { 0x8, 4, "ctl1", "L1 PM Substates Control 1", pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl1 }, - { 0xc, 4, "ctl1", "L1 PM Substates Control 2", + { 0xc, 4, "ctl2", "L1 PM Substates Control 2", pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl2 }, { -1, -1, NULL } }; @@ -2385,7 +2385,7 @@ static const pcieadm_cfgspace_print_t pcieadm_cap_l1pm_v2[] = { pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_cap }, { 0x8, 4, "ctl1", "L1 PM Substates Control 1", pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl1 }, - { 0xc, 4, "ctl1", "L1 PM Substates Control 2", + { 0xc, 4, "ctl2", "L1 PM Substates Control 2", pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl2 }, { 0x10, 4, "sts", "L1 PM Substates Status", pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_sts }, @@ -2408,7 +2408,7 @@ static const pcieadm_cfgspace_print_t pcieadm_cap_ltr[] = { pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, { 0x4, 2, "snoop", "Max Snoop Latency", pcieadm_cfgspace_print_regdef, pcieadm_regdef_ltr }, - { 0x6, 2, "snoop", "Max No-Snoop Latency", + { 0x6, 2, "nosnoop", "Max No-Snoop Latency", pcieadm_cfgspace_print_regdef, pcieadm_regdef_ltr }, { -1, -1, NULL } }; @@ -4743,7 +4743,7 @@ static const pcieadm_pci_cap_t pcieadm_pcie_caps[] = { { { 0x1, 0x1c, pcieadm_cap_vc } } }, { PCIE_EXT_CAP_ID_SER, "sn", "Serial Number", pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_sn } } }, - { PCIE_EXT_CAP_ID_PWR_BUDGET, "powbudg", "Power Budgeting", + { PCIE_EXT_CAP_ID_PWR_BUDGET, "pwrbudg", "Power Budgeting", pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_powbudg } } }, { PCIE_EXT_CAP_ID_RC_LINK_DECL, "rcld", "Root Complex Link Declaration", pcieadm_cap_info_vers, -- cgit v1.2.3 From 56a2adb63cd7b5ba73bb3f0fb3930b2d2730513e Mon Sep 17 00:00:00 2001 From: Prashanth Badari Date: Tue, 11 Jan 2022 18:50:44 +0000 Subject: 15082 SMB Clients see but can't access restricted named streams Reviewed by: Andrew Stormont Reviewed by: Gordon Ross Reviewed by: Toomas Soome Approved by: Dan McDonald --- usr/src/uts/common/fs/smbsrv/smb2_durable.c | 6 +++--- usr/src/uts/common/fs/smbsrv/smb_fsops.c | 9 +++++++-- usr/src/uts/common/fs/smbsrv/smb_odir.c | 23 ++++++++++++++++++----- usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c | 8 ++++---- usr/src/uts/common/smbsrv/smb_kproto.h | 5 +++-- usr/src/uts/common/smbsrv/smb_ktypes.h | 3 ++- 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/usr/src/uts/common/fs/smbsrv/smb2_durable.c b/usr/src/uts/common/fs/smbsrv/smb2_durable.c index c783cd9659..190a7ca6cc 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_durable.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_durable.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2020 Tintri by DDN, Inc. All rights reserved. + * Copyright 2017-2022 Tintri by DDN, Inc. All rights reserved. */ /* @@ -350,8 +350,8 @@ smb2_dh_import_share(void *arg) * Open the ext. attr dir under the share root and * import CA handles for this share. */ - if (smb_odir_openat(sr, snode, &od) != 0) { - cmn_err(CE_NOTE, "Share [%s] CA import, no xattr dir?", + if (smb_odir_openat(sr, snode, &od, B_FALSE) != 0) { + cmn_err(CE_NOTE, "!Share [%s] CA import, no xattr dir?", shr->shr_name); goto out; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c index ef58f15fa8..4247c399f3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012-2021 Tintri by DDN, Inc. All rights reserved. + * Copyright 2012-2022 Tintri by DDN, Inc. All rights reserved. * Copyright 2022 RackTop Systems, Inc. */ @@ -886,7 +886,12 @@ smb_fsop_remove_streams(smb_request_t *sr, cred_t *cr, smb_node_t *fnode) if (SMB_TREE_SUPPORTS_CATIA(sr)) flags |= SMB_CATIA; - status = smb_odir_openat(sr, fnode, &od); + /* + * NB: There aren't currently any restricted streams that could be + * removed by this function. If there ever are, be careful to exclude + * any restricted streams that we DON'T want to remove. + */ + status = smb_odir_openat(sr, fnode, &od, B_FALSE); switch (status) { case 0: break; diff --git a/usr/src/uts/common/fs/smbsrv/smb_odir.c b/usr/src/uts/common/fs/smbsrv/smb_odir.c index d2f56b47b0..24d9beae94 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_odir.c +++ b/usr/src/uts/common/fs/smbsrv/smb_odir.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2022 Tintri by DDN, Inc. All rights reserved. */ /* @@ -277,7 +277,7 @@ static void smb_odir_delete(void *); */ uint32_t smb_odir_openpath(smb_request_t *sr, char *path, uint16_t sattr, - uint32_t flags, smb_odir_t **odp) + uint32_t flags, smb_odir_t **odp) { int rc; smb_tree_t *tree; @@ -338,7 +338,7 @@ smb_odir_openpath(smb_request_t *sr, char *path, uint16_t sattr, */ uint32_t smb_odir_openfh(smb_request_t *sr, const char *pattern, uint16_t sattr, - smb_odir_t **odp) + smb_odir_t **odp) { smb_ofile_t *of = sr->fid_ofile; @@ -365,7 +365,8 @@ smb_odir_openfh(smb_request_t *sr, const char *pattern, uint16_t sattr, * NT status */ uint32_t -smb_odir_openat(smb_request_t *sr, smb_node_t *unode, smb_odir_t **odp) +smb_odir_openat(smb_request_t *sr, smb_node_t *unode, smb_odir_t **odp, + boolean_t restricted) { char pattern[SMB_STREAM_PREFIX_LEN + 2]; vnode_t *xattr_dvp; @@ -401,6 +402,10 @@ smb_odir_openat(smb_request_t *sr, smb_node_t *unode, smb_odir_t **odp) *odp = smb_odir_create(sr, xattr_dnode, pattern, SMB_SEARCH_ATTRIBUTES, 0, cr); + /* Causes restricted stream names to be hidden from the caller */ + if (restricted) + (*odp)->d_flags |= SMB_ODIR_FLAG_RESTRICTED; + smb_node_release(xattr_dnode); return (0); } @@ -724,6 +729,14 @@ smb_odir_read_streaminfo(smb_request_t *sr, smb_odir_t *od, continue; } + /* + * Hide streams that would be restricted if the caller + * is also restricted. + */ + if ((od->d_flags & SMB_ODIR_FLAG_RESTRICTED) != 0 && + smb_strname_restricted(odirent->od_name)) + continue; + rc = smb_fsop_lookup(sr, od->d_cred, 0, od->d_tree->t_snode, od->d_dnode, odirent->od_name, &fnode); if (rc == 0) { @@ -896,7 +909,7 @@ smb_odir_resume_at(smb_odir_t *od, smb_odir_resume_t *resume) */ static smb_odir_t * smb_odir_create(smb_request_t *sr, smb_node_t *dnode, - const char *pattern, uint16_t sattr, uint16_t odid, cred_t *cr) + const char *pattern, uint16_t sattr, uint16_t odid, cred_t *cr) { smb_odir_t *od; smb_tree_t *tree; diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c index cfa3ab4aca..6baef805aa 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + * Copyright 2022 Tintri by DDN, Inc. All rights reserved. */ #include @@ -616,7 +616,7 @@ smb_query_encode_response(smb_request_t *sr, smb_xa_t *xa, */ uint32_t smb_query_stream_info(smb_request_t *sr, mbuf_chain_t *mbc, - smb_queryinfo_t *qinfo) + smb_queryinfo_t *qinfo) { char *stream_name; uint32_t next_offset; @@ -646,7 +646,7 @@ smb_query_stream_info(smb_request_t *sr, mbuf_chain_t *mbc, datasz = attr->sa_vattr.va_size; allocsz = attr->sa_allocsz; - status = smb_odir_openat(sr, fnode, &od); + status = smb_odir_openat(sr, fnode, &od, B_TRUE); switch (status) { case 0: break; @@ -759,7 +759,7 @@ smb_query_stream_info(smb_request_t *sr, mbuf_chain_t *mbc, */ static boolean_t smb_stream_fits(smb_request_t *sr, mbuf_chain_t *mbc, - char *name, uint32_t offset) + char *name, uint32_t offset) { uint32_t len, pad; diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index f61b9aa9a2..76f88c06cb 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -22,7 +22,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2016 Syneto S.R.L. All rights reserved. - * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. + * Copyright 2011-2022 Tintri by DDN, Inc. All rights reserved. */ /* @@ -698,7 +698,8 @@ uint32_t smb_odir_openpath(smb_request_t *, char *, uint16_t, uint32_t, smb_odir_t **); uint32_t smb_odir_openfh(smb_request_t *, const char *, uint16_t, smb_odir_t **); -uint32_t smb_odir_openat(smb_request_t *, smb_node_t *, smb_odir_t **); +uint32_t smb_odir_openat(smb_request_t *, smb_node_t *, smb_odir_t **, + boolean_t); void smb_odir_reopen(smb_odir_t *, const char *, uint16_t); void smb_odir_close(smb_odir_t *); boolean_t smb_odir_hold(smb_odir_t *); diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h index a220faef6b..9896a1baf2 100644 --- a/usr/src/uts/common/smbsrv/smb_ktypes.h +++ b/usr/src/uts/common/smbsrv/smb_ktypes.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2011-2020 Tintri by DDN, Inc. All rights reserved. + * Copyright 2011-2022 Tintri by DDN, Inc. All rights reserved. * Copyright 2022 RackTop Systems, Inc. */ @@ -1227,6 +1227,7 @@ typedef struct smb_tree { #define SMB_ODIR_FLAG_CATIA 0x0010 #define SMB_ODIR_FLAG_ABE 0x0020 #define SMB_ODIR_FLAG_SHORTNAMES 0x0040 +#define SMB_ODIR_FLAG_RESTRICTED 0x0080 typedef enum { SMB_ODIR_STATE_OPEN = 0, -- cgit v1.2.3 From 549ab26f262a63e8892b99d530a98fea6423ad63 Mon Sep 17 00:00:00 2001 From: Matt Barden Date: Tue, 27 Sep 2022 16:56:41 -0400 Subject: 15084 SMBD leaks memory during startup/refresh Reviewed by: Andrew Stormont Reviewed by: Gordon Ross Reviewed by: Marco van Wieringen Approved by: Dan McDonald --- usr/src/lib/libshare/common/libsharecore.c | 3 +-- usr/src/lib/smbsrv/libsmb/common/smb_cfg.c | 12 ++++++------ usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c | 3 +-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/usr/src/lib/libshare/common/libsharecore.c b/usr/src/lib/libshare/common/libsharecore.c index c15291d19d..9f08c0c220 100644 --- a/usr/src/lib/libshare/common/libsharecore.c +++ b/usr/src/lib/libshare/common/libsharecore.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2022 Tintri by DDN, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. */ @@ -1604,7 +1604,6 @@ parse_sharetab(sa_handle_t handle) sa_group_t lgroup; xfs_sharelist_t *list = get_share_list(&err); - list = get_share_list(&err); if (list == NULL) return (legacy); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c index 88890f4f8c..b295916cb3 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2020 Tintri by DDN, Inc. All rights reserved. + * Copyright 2022 Tintri by DDN, Inc. All rights reserved. * Copyright 2021 RackTop Systems, Inc. */ @@ -904,6 +904,7 @@ int smb_config_get_localuuid(uuid_t uu) { char *s; + int rc = 0; uuid_clear(uu); s = smb_config_getenv_generic(MACHINE_UUID, IDMAP_FMRI_PREFIX, @@ -911,12 +912,11 @@ smb_config_get_localuuid(uuid_t uu) if (s == NULL) return (-1); - if (uuid_parse(s, uu) < 0) { - free(s); - return (-1); - } + if (uuid_parse(s, uu) < 0) + rc = -1; - return (0); + free(s); + return (rc); } static int diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c index 0a07771985..66a187abbb 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. + * Copyright 2022 Tintri by DDN, Inc. All rights reserved. * Copyright 2021 RackTop Systems, Inc. */ @@ -482,7 +482,6 @@ again: (void) mutex_lock(&smb_ads_cached_host_mtx); if (!smb_ads_cached_host_info) smb_ads_cached_host_info = smb_ads_dup_host_info(host); - host = smb_ads_dup_host_info(smb_ads_cached_host_info); (void) mutex_unlock(&smb_ads_cached_host_mtx); out: -- cgit v1.2.3 From cfed4d7055842c539437036c634e7fe84d10977d Mon Sep 17 00:00:00 2001 From: Matt Barden Date: Tue, 27 Sep 2022 17:27:44 -0400 Subject: 15085 mech_krb5: memory leaked during context establishment Reviewed by: Gordon Ross Reviewed by: Toomas Soome Approved by: Dan McDonald --- usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c | 6 +++++- usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c | 10 ++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c index 967c8f7fe4..0a3a0d075e 100644 --- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c +++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c @@ -1,6 +1,6 @@ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2022 Tintri by DDN, Inc. All rights reserved. */ /* * lib/krb5/krb/get_in_tkt.c @@ -1306,6 +1306,10 @@ krb5_get_init_creds(krb5_context context, err_reply = NULL; local_as_reply = 0; + + free(hostname_used); + hostname_used = NULL; + if ((ret = send_as_request2(context, &request, &err_reply, &local_as_reply, use_master, &hostname_used))) diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c b/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c index 50488192e8..821327f5da 100644 --- a/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c +++ b/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c @@ -1,5 +1,6 @@ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2022 Tintri by DDN, Inc. All rights reserved. */ /* * Copyright 2000, 2004 by the Massachusetts Institute of Technology. @@ -1142,6 +1143,9 @@ krb5_gss_accept_sec_context(minor_status, context_handle, *delegated_cred_handle = (gss_cred_id_t) deleg_cred; } + if (server_name) + krb5_free_principal(context, server_name); + /* finally! */ *minor_status = 0; @@ -1149,10 +1153,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle, fail: if (mech_type) { - unsigned int min; - gss_buffer_desc oidstr; - oidstr.value = NULL; - /* * This needs to be set/returned even on fail so * gss_accept_sec_context() can map_error_oid() the correct @@ -1160,8 +1160,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle, * (needed in CIFS/SPNEGO case) */ *mech_type = (gss_OID) mech_used; - - (void) gss_oid_to_str(&min, *mech_type, &oidstr); } if (authdat) -- cgit v1.2.3 From 4f3f3e9a1dee62c031fa67cfe64e11d6dd3fab1b Mon Sep 17 00:00:00 2001 From: Andy Fiddaman Date: Wed, 17 Aug 2022 20:44:42 +0000 Subject: 14763 bhyve upstream sync 2022 August Reviewed by: Patrick Mooney Approved by: Robert Mustacchi --- usr/src/cmd/bhyve/README.sync | 10 +- usr/src/cmd/bhyve/acpi.c | 2 +- usr/src/cmd/bhyve/bhyverun.c | 9 +- usr/src/cmd/bhyve/block_if.c | 62 ++++--- usr/src/cmd/bhyve/config.c | 4 +- usr/src/cmd/bhyve/fwctl.c | 2 +- usr/src/cmd/bhyve/gdb.c | 6 +- usr/src/cmd/bhyve/hda_codec.c | 4 +- usr/src/cmd/bhyve/mem.c | 2 +- usr/src/cmd/bhyve/net_backends.c | 15 +- usr/src/cmd/bhyve/pci_ahci.c | 6 +- usr/src/cmd/bhyve/pci_e82545.c | 53 ++++-- usr/src/cmd/bhyve/pci_emul.c | 39 ++-- usr/src/cmd/bhyve/pci_emul.h | 4 +- usr/src/cmd/bhyve/pci_fbuf.c | 6 +- usr/src/cmd/bhyve/pci_hda.c | 7 +- usr/src/cmd/bhyve/pci_hda.h | 2 +- usr/src/cmd/bhyve/pci_hostbridge.c | 4 +- usr/src/cmd/bhyve/pci_lpc.c | 4 +- usr/src/cmd/bhyve/pci_lpc.h | 2 +- usr/src/cmd/bhyve/pci_nvme.c | 225 ++++++++++++++--------- usr/src/cmd/bhyve/pci_passthru.c | 4 +- usr/src/cmd/bhyve/pci_uart.c | 2 +- usr/src/cmd/bhyve/pci_virtio_9p.c | 2 +- usr/src/cmd/bhyve/pci_virtio_block.c | 2 +- usr/src/cmd/bhyve/pci_virtio_console.c | 7 +- usr/src/cmd/bhyve/pci_virtio_input.c | 2 +- usr/src/cmd/bhyve/pci_virtio_net.c | 2 +- usr/src/cmd/bhyve/pci_virtio_rnd.c | 2 +- usr/src/cmd/bhyve/pci_virtio_scsi.c | 2 +- usr/src/cmd/bhyve/pci_xhci.c | 43 +++-- usr/src/cmd/bhyve/smbiostbl.c | 288 +++++++++++++++++++----------- usr/src/contrib/bhyve/dev/nvme/nvme.h | 8 +- usr/src/lib/libvmmapi/common/vmmapi.c | 266 ++++++++++++++++++--------- usr/src/lib/libvmmapi/common/vmmapi.h | 11 +- usr/src/man/man5/bhyve_config.5 | 92 +++++++++- usr/src/man/man8/bhyve.8 | 35 ++-- usr/src/uts/intel/io/vmm/amd/amdvi_hw.c | 7 +- usr/src/uts/intel/io/vmm/amd/svm.c | 10 +- usr/src/uts/intel/io/vmm/amd/vmcb.h | 1 + usr/src/uts/intel/io/vmm/intel/vmx.c | 20 ++- usr/src/uts/intel/io/vmm/sys/vmm_kernel.h | 1 + usr/src/uts/intel/io/vmm/vmm.c | 14 +- 43 files changed, 852 insertions(+), 437 deletions(-) diff --git a/usr/src/cmd/bhyve/README.sync b/usr/src/cmd/bhyve/README.sync index 2031c7ed0a..8175237b32 100644 --- a/usr/src/cmd/bhyve/README.sync +++ b/usr/src/cmd/bhyve/README.sync @@ -5,13 +5,11 @@ The bhyve userland code in this directory, and its associated libraries and parts of the kernel module have been updated to the latest upstream FreeBSD sources as of: - commit 3ebe1109348f53f64b395293578416abedef4090 - Author: Robert Wing - Date: Thu Mar 17 21:55:52 2022 -0800 + commit fa46f3704b7618f9d9493c126df781faf59040a8 + Author: John Baldwin + Date: Wed Aug 17 10:01:16 2022 -0700 - bhyve: sweep MAX_VMNAME - - MAX_VMNAME is no longer used. + bhyve e1000: Skip packets with a small header. Divergence Notes: diff --git a/usr/src/cmd/bhyve/acpi.c b/usr/src/cmd/bhyve/acpi.c index 757111590f..fd0a6f732e 100644 --- a/usr/src/cmd/bhyve/acpi.c +++ b/usr/src/cmd/bhyve/acpi.c @@ -866,7 +866,7 @@ basl_compile(struct vmctx *ctx, int (*fwrite_section)(FILE *), uint64_t offset) { struct basl_fio io[2]; static char iaslbuf[3*MAXPATHLEN + 10]; - char *fmt; + const char *fmt; int err; err = basl_start(&io[0], &io[1]); diff --git a/usr/src/cmd/bhyve/bhyverun.c b/usr/src/cmd/bhyve/bhyverun.c index 4d4c9578b9..90260a4ac9 100644 --- a/usr/src/cmd/bhyve/bhyverun.c +++ b/usr/src/cmd/bhyve/bhyverun.c @@ -252,6 +252,9 @@ usage(int code) " %*s [-s ] [-U uuid] vmname\n" #endif " -a: local apic is in xAPIC mode (deprecated)\n" +#ifndef __FreeBSD__ + " -B type,key=value,...: set SMBIOS information\n" +#endif " -C: include guest memory in core file\n" " -c: number of cpus and/or topology specification\n" " -D: destroy on power-off\n" @@ -1740,11 +1743,9 @@ main(int argc, char *argv[]) } } -#ifndef __FreeBSD__ - smbios_apply(); -#endif error = smbios_build(ctx); - assert(error == 0); + if (error != 0) + exit(4); if (get_config_bool("acpi_tables")) { error = acpi_build(ctx, guest_ncpus); diff --git a/usr/src/cmd/bhyve/block_if.c b/usr/src/cmd/bhyve/block_if.c index 48948b4f23..dfbb9df85e 100644 --- a/usr/src/cmd/bhyve/block_if.c +++ b/usr/src/cmd/bhyve/block_if.c @@ -45,9 +45,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifndef __FreeBSD__ #include #include -#ifndef __FreeBSD__ #include #endif @@ -246,6 +246,29 @@ blockif_complete(struct blockif_ctxt *bc, struct blockif_elem *be) TAILQ_INSERT_TAIL(&bc->bc_freeq, be, be_link); } +static int +blockif_flush_bc(struct blockif_ctxt *bc) +{ +#ifdef __FreeBSD__ + if (bc->bc_ischr) { + if (ioctl(bc->bc_fd, DIOCGFLUSH)) + return (errno); + } else if (fsync(bc->bc_fd)) + return (errno); +#else + /* + * This fsync() should be adequate to flush the cache of a file + * or device. In VFS, the VOP_SYNC operation is converted to + * the appropriate ioctl in both sdev (for real devices) and + * zfs (for zvols). + */ + if (fsync(bc->bc_fd)) + return (errno); +#endif + + return (0); +} + static void blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be, uint8_t *buf) { @@ -255,6 +278,9 @@ blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be, uint8_t *buf) #endif ssize_t clen, len, off, boff, voff; int i, err; +#ifdef __FreeBSD__ + struct spacectl_range range; +#endif br = be->be_req; if (br->br_iovcnt <= 1) @@ -338,22 +364,7 @@ blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be, uint8_t *buf) } break; case BOP_FLUSH: -#ifdef __FreeBSD__ - if (bc->bc_ischr) { - if (ioctl(bc->bc_fd, DIOCGFLUSH)) - err = errno; - } else if (fsync(bc->bc_fd)) - err = errno; -#else - /* - * This fsync() should be adequate to flush the cache of a file - * or device. In VFS, the VOP_SYNC operation is converted to - * the appropriate ioctl in both sdev (for real devices) and - * zfs (for zvols). - */ - if (fsync(bc->bc_fd)) - err = errno; -#endif + err = blockif_flush_bc(bc); break; case BOP_DELETE: if (!bc->bc_candelete) @@ -425,6 +436,12 @@ blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be, uint8_t *buf) (*br->br_callback)(br, err); } +static inline bool +blockif_empty(const struct blockif_ctxt *bc) +{ + return (TAILQ_EMPTY(&bc->bc_pendq) && TAILQ_EMPTY(&bc->bc_busyq)); +} + static void * blockif_thr(void *arg) { @@ -451,6 +468,7 @@ blockif_thr(void *arg) /* Check ctxt status here to see if exit requested */ if (bc->bc_closing) break; + pthread_cond_wait(&bc->bc_cond, &bc->bc_mtx); } pthread_mutex_unlock(&bc->bc_mtx); @@ -915,7 +933,6 @@ blockif_request(struct blockif_ctxt *bc, struct blockif_req *breq, int blockif_read(struct blockif_ctxt *bc, struct blockif_req *breq) { - assert(bc->bc_magic == BLOCKIF_SIG); return (blockif_request(bc, breq, BOP_READ)); } @@ -923,7 +940,6 @@ blockif_read(struct blockif_ctxt *bc, struct blockif_req *breq) int blockif_write(struct blockif_ctxt *bc, struct blockif_req *breq) { - assert(bc->bc_magic == BLOCKIF_SIG); return (blockif_request(bc, breq, BOP_WRITE)); } @@ -931,7 +947,6 @@ blockif_write(struct blockif_ctxt *bc, struct blockif_req *breq) int blockif_flush(struct blockif_ctxt *bc, struct blockif_req *breq) { - assert(bc->bc_magic == BLOCKIF_SIG); return (blockif_request(bc, breq, BOP_FLUSH)); } @@ -939,7 +954,6 @@ blockif_flush(struct blockif_ctxt *bc, struct blockif_req *breq) int blockif_delete(struct blockif_ctxt *bc, struct blockif_req *breq) { - assert(bc->bc_magic == BLOCKIF_SIG); return (blockif_request(bc, breq, BOP_DELETE)); } @@ -1107,7 +1121,6 @@ blockif_chs(struct blockif_ctxt *bc, uint16_t *c, uint8_t *h, uint8_t *s) off_t blockif_size(struct blockif_ctxt *bc) { - assert(bc->bc_magic == BLOCKIF_SIG); return (bc->bc_size); } @@ -1115,7 +1128,6 @@ blockif_size(struct blockif_ctxt *bc) int blockif_sectsz(struct blockif_ctxt *bc) { - assert(bc->bc_magic == BLOCKIF_SIG); return (bc->bc_sectsz); } @@ -1123,7 +1135,6 @@ blockif_sectsz(struct blockif_ctxt *bc) void blockif_psectsz(struct blockif_ctxt *bc, int *size, int *off) { - assert(bc->bc_magic == BLOCKIF_SIG); *size = bc->bc_psectsz; *off = bc->bc_psectoff; @@ -1132,7 +1143,6 @@ blockif_psectsz(struct blockif_ctxt *bc, int *size, int *off) int blockif_queuesz(struct blockif_ctxt *bc) { - assert(bc->bc_magic == BLOCKIF_SIG); return (BLOCKIF_MAXREQ - 1); } @@ -1140,7 +1150,6 @@ blockif_queuesz(struct blockif_ctxt *bc) int blockif_is_ro(struct blockif_ctxt *bc) { - assert(bc->bc_magic == BLOCKIF_SIG); return (bc->bc_rdonly); } @@ -1148,7 +1157,6 @@ blockif_is_ro(struct blockif_ctxt *bc) int blockif_candelete(struct blockif_ctxt *bc) { - assert(bc->bc_magic == BLOCKIF_SIG); return (bc->bc_candelete); } diff --git a/usr/src/cmd/bhyve/config.c b/usr/src/cmd/bhyve/config.c index f8aace3b73..5d6f2c0170 100644 --- a/usr/src/cmd/bhyve/config.c +++ b/usr/src/cmd/bhyve/config.c @@ -312,7 +312,7 @@ _expand_config_value(const char *value, int depth) return (valbuf); } -const char * +static const char * expand_config_value(const char *value) { static char *valbuf; @@ -354,7 +354,7 @@ get_config_value_node(const nvlist_t *parent, const char *name) return (expand_config_value(nvlist_get_string(parent, name))); } -bool +static bool _bool_value(const char *name, const char *value) { diff --git a/usr/src/cmd/bhyve/fwctl.c b/usr/src/cmd/bhyve/fwctl.c index f0f9aa3aff..7027e34a77 100644 --- a/usr/src/cmd/bhyve/fwctl.c +++ b/usr/src/cmd/bhyve/fwctl.c @@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$"); /* * Back-end state-machine */ -enum state { +static enum state { DORMANT, IDENT_WAIT, IDENT_SEND, diff --git a/usr/src/cmd/bhyve/gdb.c b/usr/src/cmd/bhyve/gdb.c index 1d1203e138..5dda1737b3 100644 --- a/usr/src/cmd/bhyve/gdb.c +++ b/usr/src/cmd/bhyve/gdb.c @@ -139,7 +139,7 @@ static struct vcpu_state *vcpu_state; static int cur_vcpu, stopped_vcpu; static bool gdb_active = false; -const int gdb_regset[] = { +static const int gdb_regset[] = { VM_REG_GUEST_RAX, VM_REG_GUEST_RBX, VM_REG_GUEST_RCX, @@ -166,7 +166,7 @@ const int gdb_regset[] = { VM_REG_GUEST_GS }; -const int gdb_regsize[] = { +static const int gdb_regsize[] = { 8, 8, 8, @@ -1838,7 +1838,7 @@ new_connection(int fd, enum ev_type event, void *arg) } #ifndef WITHOUT_CAPSICUM -void +static void limit_gdb_socket(int s) { cap_rights_t rights; diff --git a/usr/src/cmd/bhyve/hda_codec.c b/usr/src/cmd/bhyve/hda_codec.c index 7a6ba345d8..2cc875d3d2 100644 --- a/usr/src/cmd/bhyve/hda_codec.c +++ b/usr/src/cmd/bhyve/hda_codec.c @@ -845,17 +845,15 @@ hda_codec_audio_inout_nid(struct hda_codec_stream *st, uint16_t verb, return (res); } -struct hda_codec_class hda_codec = { +static const struct hda_codec_class hda_codec = { .name = "hda_codec", .init = hda_codec_init, .reset = hda_codec_reset, .command = hda_codec_command, .notify = hda_codec_notify, }; - HDA_EMUL_SET(hda_codec); - /* * HDA Audio Context module function definitions */ diff --git a/usr/src/cmd/bhyve/mem.c b/usr/src/cmd/bhyve/mem.c index 74ce0103a3..08756161a4 100644 --- a/usr/src/cmd/bhyve/mem.c +++ b/usr/src/cmd/bhyve/mem.c @@ -72,7 +72,7 @@ struct mmio_rb_range { struct mmio_rb_tree; RB_PROTOTYPE(mmio_rb_tree, mmio_rb_range, mr_link, mmio_rb_range_compare); -RB_HEAD(mmio_rb_tree, mmio_rb_range) mmio_rb_root, mmio_rb_fallback; +static RB_HEAD(mmio_rb_tree, mmio_rb_range) mmio_rb_root, mmio_rb_fallback; /* * Per-vCPU cache. Since most accesses from a vCPU will be to diff --git a/usr/src/cmd/bhyve/net_backends.c b/usr/src/cmd/bhyve/net_backends.c index 329405964e..b870f4e865 100644 --- a/usr/src/cmd/bhyve/net_backends.c +++ b/usr/src/cmd/bhyve/net_backends.c @@ -196,7 +196,7 @@ SET_DECLARE(net_backend_set, struct net_backend); */ #if defined(INET6) || defined(INET) -const int pf_list[] = { +static const int pf_list[] = { #if defined(INET6) PF_INET6, #endif @@ -1316,6 +1316,7 @@ netbe_legacy_config(nvlist_t *nvl, const char *opts) /* Default to the 'dlpi' backend - can still be overridden by opts */ set_config_value_node(nvl, "backend", "dlpi"); + set_config_value_node(nvl, "type", "dlpi"); config = tofree = strdup(opts); if (config == NULL) @@ -1352,7 +1353,7 @@ netbe_init(struct net_backend **ret, nvlist_t *nvl, net_be_rxeof_t cb, void *param) { struct net_backend **pbe, *nbe, *tbe = NULL; - const char *value; + const char *value, *type; char *devname; int err; @@ -1362,12 +1363,20 @@ netbe_init(struct net_backend **ret, nvlist_t *nvl, net_be_rxeof_t cb, } devname = strdup(value); + /* + * Use the type given by configuration if exists; otherwise + * use the prefix of the backend as the type. + */ + type = get_config_value_node(nvl, "type"); + if (type == NULL) + type = devname; + /* * Find the network backend that matches the user-provided * device name. net_backend_set is built using a linker set. */ SET_FOREACH(pbe, net_backend_set) { - if (strncmp(devname, (*pbe)->prefix, + if (strncmp(type, (*pbe)->prefix, strlen((*pbe)->prefix)) == 0) { tbe = *pbe; assert(tbe->init != NULL); diff --git a/usr/src/cmd/bhyve/pci_ahci.c b/usr/src/cmd/bhyve/pci_ahci.c index f973b8964f..2a4b97fbbf 100644 --- a/usr/src/cmd/bhyve/pci_ahci.c +++ b/usr/src/cmd/bhyve/pci_ahci.c @@ -2570,7 +2570,7 @@ open_fail: /* * Use separate emulation names to distinguish drive and atapi devices */ -struct pci_devemu pci_de_ahci = { +static const struct pci_devemu pci_de_ahci = { .pe_emu = "ahci", .pe_init = pci_ahci_init, .pe_legacy_config = pci_ahci_legacy_config, @@ -2579,14 +2579,14 @@ struct pci_devemu pci_de_ahci = { }; PCI_EMUL_SET(pci_de_ahci); -struct pci_devemu pci_de_ahci_hd = { +static const struct pci_devemu pci_de_ahci_hd = { .pe_emu = "ahci-hd", .pe_legacy_config = pci_ahci_hd_legacy_config, .pe_alias = "ahci", }; PCI_EMUL_SET(pci_de_ahci_hd); -struct pci_devemu pci_de_ahci_cd = { +static const struct pci_devemu pci_de_ahci_cd = { .pe_emu = "ahci-cd", .pe_legacy_config = pci_ahci_cd_legacy_config, .pe_alias = "ahci", diff --git a/usr/src/cmd/bhyve/pci_e82545.c b/usr/src/cmd/bhyve/pci_e82545.c index f4eaa0c93b..363e203692 100644 --- a/usr/src/cmd/bhyve/pci_e82545.c +++ b/usr/src/cmd/bhyve/pci_e82545.c @@ -232,7 +232,7 @@ struct ck_info { * Debug printf */ static int e82545_debug = 0; -#define WPRINTF(msg,params...) PRINTLN("e82545: " msg, params) +#define WPRINTF(msg,params...) PRINTLN("e82545: " msg, ##params) #define DPRINTF(msg,params...) if (e82545_debug) WPRINTF(msg, params) #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -811,7 +811,7 @@ e82545_tx_ctl(struct e82545_softc *sc, uint32_t val) sc->esc_TCTL = val & ~0xFE800005; } -int +static int e82545_bufsz(uint32_t rctl) { @@ -1025,7 +1025,7 @@ e82545_iov_checksum(struct iovec *iov, int iovcnt, int off, int len) /* * Return the transmit descriptor type. */ -int +static int e82545_txdesc_type(uint32_t lower) { int type; @@ -1089,15 +1089,18 @@ e82545_transmit(struct e82545_softc *sc, uint16_t head, uint16_t tail, union e1000_tx_udesc *dsc; int desc, dtype, len, ntype, iovcnt, tcp, tso; int mss, paylen, seg, tiovcnt, left, now, nleft, nnow, pv, pvoff; - unsigned hdrlen, vlen; + unsigned hdrlen, vlen, pktlen; uint32_t tcpsum, tcpseq; uint16_t ipcs, tcpcs, ipid, ohead; + bool invalid; ckinfo[0].ck_valid = ckinfo[1].ck_valid = 0; iovcnt = 0; ntype = 0; tso = 0; + pktlen = 0; ohead = head; + invalid = false; /* iovb[0/1] may be used for writable copy of headers. */ iov = &iovb[2]; @@ -1147,17 +1150,23 @@ e82545_transmit(struct e82545_softc *sc, uint16_t head, uint16_t tail, len = (dtype == E1000_TXD_TYP_L) ? dsc->td.lower.flags.length : dsc->dd.lower.data & 0xFFFFF; - if (len > 0) { - /* Strip checksum supplied by guest. */ - if ((dsc->td.lower.data & E1000_TXD_CMD_EOP) != 0 && - (dsc->td.lower.data & E1000_TXD_CMD_IFCS) == 0) + /* Strip checksum supplied by guest. */ + if ((dsc->td.lower.data & E1000_TXD_CMD_EOP) != 0 && + (dsc->td.lower.data & E1000_TXD_CMD_IFCS) == 0) { + if (len <= 2) { + WPRINTF("final descriptor too short (%d) -- dropped", + len); + invalid = true; + } else len -= 2; - if (iovcnt < I82545_MAX_TXSEGS) { - iov[iovcnt].iov_base = paddr_guest2host( - sc->esc_ctx, dsc->td.buffer_addr, len); - iov[iovcnt].iov_len = len; - } + } + + if (len > 0 && iovcnt < I82545_MAX_TXSEGS) { + iov[iovcnt].iov_base = paddr_guest2host(sc->esc_ctx, + dsc->td.buffer_addr, len); + iov[iovcnt].iov_len = len; iovcnt++; + pktlen += len; } /* @@ -1205,6 +1214,9 @@ e82545_transmit(struct e82545_softc *sc, uint16_t head, uint16_t tail, } } + if (invalid) + goto done; + if (iovcnt > I82545_MAX_TXSEGS) { WPRINTF("tx too many descriptors (%d > %d) -- dropped", iovcnt, I82545_MAX_TXSEGS); @@ -1296,10 +1308,20 @@ e82545_transmit(struct e82545_softc *sc, uint16_t head, uint16_t tail, "(%d) -- dropped", hdrlen); goto done; } + if (ckinfo[1].ck_valid && hdrlen < ckinfo[1].ck_off + 2) { + WPRINTF("TSO hdrlen too small for TCP/UDP fields " + "(%d) -- dropped", hdrlen); + goto done; + } + } + + if (pktlen < hdrlen + vlen) { + WPRINTF("packet too small for writable header"); + goto done; } /* Allocate, fill and prepend writable header vector. */ - if (hdrlen != 0) { + if (hdrlen + vlen != 0) { hdr = __builtin_alloca(hdrlen + vlen); hdr += vlen; for (left = hdrlen, hdrp = hdr; left > 0; @@ -2371,7 +2393,7 @@ e82545_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) return (0); } -struct pci_devemu pci_de_e82545 = { +static const struct pci_devemu pci_de_e82545 = { .pe_emu = "e1000", .pe_init = e82545_init, .pe_legacy_config = netbe_legacy_config, @@ -2379,4 +2401,3 @@ struct pci_devemu pci_de_e82545 = { .pe_barread = e82545_read, }; PCI_EMUL_SET(pci_de_e82545); - diff --git a/usr/src/cmd/bhyve/pci_emul.c b/usr/src/cmd/bhyve/pci_emul.c index 413633411d..ccb1ce9c4d 100644 --- a/usr/src/cmd/bhyve/pci_emul.c +++ b/usr/src/cmd/bhyve/pci_emul.c @@ -178,6 +178,18 @@ CFGREAD(struct pci_devinst *pi, int coff, int bytes) return (pci_get_cfgdata32(pi, coff)); } +static int +is_pcir_bar(int coff) +{ + return (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)); +} + +static int +is_pcir_bios(int coff) +{ + return (coff >= PCIR_BIOS && coff < PCIR_BIOS + 4); +} + /* * I/O access */ @@ -321,7 +333,7 @@ done: } void -pci_print_supported_devices() +pci_print_supported_devices(void) { struct pci_devemu **pdpp, *pdp; @@ -815,9 +827,6 @@ pci_emul_assign_bar(struct pci_devinst *const pdi, const int idx, limit = 0; mask = PCIM_BIOS_ADDR_MASK; lobits = 0; -#ifndef __FreeBSD__ - addr = 0; -#endif break; default: printf("pci_emul_alloc_base: invalid bar type %d\n", type); @@ -832,6 +841,8 @@ pci_emul_assign_bar(struct pci_devinst *const pdi, const int idx, error = pci_emul_alloc_resource(baseptr, limit, size, &addr); if (error != 0) return (error); + } else { + addr = 0; } pdi->pi_bar[idx].type = type; @@ -2132,27 +2143,23 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func, /* * Special handling for write to BAR and ROM registers */ - if ((coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) || - (coff >= PCIR_BIOS && coff < PCIR_BIOS + 4)) { + if (is_pcir_bar(coff) || is_pcir_bios(coff)) { /* * Ignore writes to BAR registers that are not * 4-byte aligned. */ if (bytes != 4 || (coff & 0x3) != 0) return; -#ifndef __FreeBSD__ - if (coff < PCIR_BIOS) { + + if (is_pcir_bar(coff)) { idx = (coff - PCIR_BAR(0)) / 4; - } else { + } else if (is_pcir_bios(coff)) { idx = PCI_ROM_IDX; - } -#else - if (coff != PCIR_BIOS) { - idx = (coff - PCIR_BAR(0)) / 4; } else { - idx = PCI_ROM_IDX; + errx(4, "%s: invalid BAR offset %d", __func__, + coff); } -#endif + mask = ~(pi->pi_bar[idx].size - 1); switch (pi->pi_bar[idx].type) { case PCIBAR_NONE: @@ -2451,7 +2458,7 @@ pci_emul_dior(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, return (value); } -struct pci_devemu pci_dummy = { +static const struct pci_devemu pci_dummy = { .pe_emu = "dummy", .pe_init = pci_emul_dinit, .pe_barwrite = pci_emul_diow, diff --git a/usr/src/cmd/bhyve/pci_emul.h b/usr/src/cmd/bhyve/pci_emul.h index 2929e0c307..c19b6d2fac 100644 --- a/usr/src/cmd/bhyve/pci_emul.h +++ b/usr/src/cmd/bhyve/pci_emul.h @@ -53,7 +53,7 @@ struct pci_devinst; struct memory_region; struct pci_devemu { - char *pe_emu; /* Name of device emulation */ + const char *pe_emu; /* Name of device emulation */ /* instance creation */ int (*pe_init)(struct vmctx *, struct pci_devinst *, @@ -255,7 +255,7 @@ int pci_msix_pba_bar(struct pci_devinst *pi); int pci_msi_maxmsgnum(struct pci_devinst *pi); int pci_parse_legacy_config(nvlist_t *nvl, const char *opt); int pci_parse_slot(char *opt); -void pci_print_supported_devices(); +void pci_print_supported_devices(void); void pci_populate_msicap(struct msicap *cap, int msgs, int nextptr); int pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum); int pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size, diff --git a/usr/src/cmd/bhyve/pci_fbuf.c b/usr/src/cmd/bhyve/pci_fbuf.c index 5a17b1e618..35764f253f 100644 --- a/usr/src/cmd/bhyve/pci_fbuf.c +++ b/usr/src/cmd/bhyve/pci_fbuf.c @@ -174,7 +174,7 @@ pci_fbuf_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, } } -uint64_t +static uint64_t pci_fbuf_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size) { @@ -356,7 +356,7 @@ pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl) extern void vga_render(struct bhyvegc *gc, void *arg); -void +static void pci_fbuf_render(struct bhyvegc *gc, void *arg) { struct pci_fbuf_softc *sc; @@ -479,7 +479,7 @@ done: return (error); } -struct pci_devemu pci_fbuf = { +static const struct pci_devemu pci_fbuf = { .pe_emu = "fbuf", .pe_init = pci_fbuf_init, .pe_barwrite = pci_fbuf_write, diff --git a/usr/src/cmd/bhyve/pci_hda.c b/usr/src/cmd/bhyve/pci_hda.c index 7491944fed..1a2a3844ab 100644 --- a/usr/src/cmd/bhyve/pci_hda.c +++ b/usr/src/cmd/bhyve/pci_hda.c @@ -94,7 +94,7 @@ struct hda_bdle_desc { }; struct hda_codec_cmd_ctl { - char *name; + const char *name; void *dma_vaddr; uint8_t run; uint16_t rp; @@ -270,13 +270,12 @@ static struct hda_ops hops = { .transfer = hda_transfer, }; -struct pci_devemu pci_de_hda = { +static const struct pci_devemu pci_de_hda = { .pe_emu = "hda", .pe_init = pci_hda_init, .pe_barwrite = pci_hda_write, .pe_barread = pci_hda_read }; - PCI_EMUL_SET(pci_de_hda); SET_DECLARE(hda_codec_class_set, struct hda_codec_class); @@ -730,7 +729,7 @@ static inline void hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p) { #if DEBUG_HDA == 1 - char *name = p->name; + const char *name = p->name; #endif DPRINTF("%s size: %d", name, p->size); DPRINTF("%s dma_vaddr: %p", name, p->dma_vaddr); diff --git a/usr/src/cmd/bhyve/pci_hda.h b/usr/src/cmd/bhyve/pci_hda.h index a34366dedc..e868671921 100644 --- a/usr/src/cmd/bhyve/pci_hda.h +++ b/usr/src/cmd/bhyve/pci_hda.h @@ -70,7 +70,7 @@ struct hda_codec_inst { }; struct hda_codec_class { - char *name; + const char *name; int (*init)(struct hda_codec_inst *hci, const char *play, const char *rec); int (*reset)(struct hda_codec_inst *hci); diff --git a/usr/src/cmd/bhyve/pci_hostbridge.c b/usr/src/cmd/bhyve/pci_hostbridge.c index d35bdcf640..db7690e4b6 100644 --- a/usr/src/cmd/bhyve/pci_hostbridge.c +++ b/usr/src/cmd/bhyve/pci_hostbridge.c @@ -156,14 +156,14 @@ pci_amd_hostbridge_legacy_config(nvlist_t *nvl, const char *opts) return (0); } -struct pci_devemu pci_de_amd_hostbridge = { +static const struct pci_devemu pci_de_amd_hostbridge = { .pe_emu = "amd_hostbridge", .pe_legacy_config = pci_amd_hostbridge_legacy_config, .pe_alias = "hostbridge", }; PCI_EMUL_SET(pci_de_amd_hostbridge); -struct pci_devemu pci_de_hostbridge = { +static const struct pci_devemu pci_de_hostbridge = { .pe_emu = "hostbridge", .pe_init = pci_hostbridge_init, }; diff --git a/usr/src/cmd/bhyve/pci_lpc.c b/usr/src/cmd/bhyve/pci_lpc.c index 27cf8004b4..2702e0fdca 100644 --- a/usr/src/cmd/bhyve/pci_lpc.c +++ b/usr/src/cmd/bhyve/pci_lpc.c @@ -146,7 +146,7 @@ done: } void -lpc_print_supported_devices() +lpc_print_supported_devices(void) { size_t i; @@ -521,7 +521,7 @@ lpc_pirq_routed(void) pci_set_cfgdata8(lpc_bridge, 0x68 + pin, pirq_read(pin + 5)); } -struct pci_devemu pci_de_lpc = { +static const struct pci_devemu pci_de_lpc = { .pe_emu = "lpc", .pe_init = pci_lpc_init, .pe_write_dsdt = pci_lpc_write_dsdt, diff --git a/usr/src/cmd/bhyve/pci_lpc.h b/usr/src/cmd/bhyve/pci_lpc.h index 9041f79c50..611b025d43 100644 --- a/usr/src/cmd/bhyve/pci_lpc.h +++ b/usr/src/cmd/bhyve/pci_lpc.h @@ -68,7 +68,7 @@ struct lpc_sysres { #define SYSRES_MEM(base, length) LPC_SYSRES(LPC_SYSRES_MEM, base, length) int lpc_device_parse(const char *opt); -void lpc_print_supported_devices(); +void lpc_print_supported_devices(void); char *lpc_pirq_name(int pin); void lpc_pirq_routed(void); const char *lpc_bootrom(void); diff --git a/usr/src/cmd/bhyve/pci_nvme.c b/usr/src/cmd/bhyve/pci_nvme.c index 488c7d4770..717d400bc0 100644 --- a/usr/src/cmd/bhyve/pci_nvme.c +++ b/usr/src/cmd/bhyve/pci_nvme.c @@ -401,6 +401,7 @@ static void pci_nvme_io_done(struct blockif_req *, int); ((sts) >> NVME_CSTS_REG_RDY_SHIFT & NVME_CSTS_REG_RDY_MASK) #define NVME_CSTS_RDY (1 << NVME_CSTS_REG_RDY_SHIFT) +#define NVME_CSTS_CFS (1 << NVME_CSTS_REG_CFS_SHIFT) /* Completion Queue status word utils */ #define NVME_STATUS_P (1 << NVME_STATUS_P_SHIFT) @@ -548,16 +549,24 @@ pci_nvme_init_ctrldata(struct pci_nvme_softc *sc) cd->aerl = 4; /* Advertise 1, Read-only firmware slot */ - cd->frmw = NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK | + cd->frmw = NVMEB(NVME_CTRLR_DATA_FRMW_SLOT1_RO) | (1 << NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT); cd->lpa = 0; /* TODO: support some simple things like SMART */ cd->elpe = 0; /* max error log page entries */ - cd->npss = 1; /* number of power states support */ + /* + * Report a single power state (zero-based value) + * power_state[] values are left as zero to indicate "Not reported" + */ + cd->npss = 0; /* Warning Composite Temperature Threshold */ cd->wctemp = 0x0157; cd->cctemp = 0x0157; + /* SANICAP must not be 0 for Revision 1.4 and later NVMe Controllers */ + cd->sanicap = (NVME_CTRLR_DATA_SANICAP_NODMMAS_NO << + NVME_CTRLR_DATA_SANICAP_NODMMAS_SHIFT); + cd->sqes = (6 << NVME_CTRLR_DATA_SQES_MAX_SHIFT) | (6 << NVME_CTRLR_DATA_SQES_MIN_SHIFT); cd->cqes = (4 << NVME_CTRLR_DATA_CQES_MAX_SHIFT) | @@ -581,8 +590,6 @@ pci_nvme_init_ctrldata(struct pci_nvme_softc *sc) NVME_CTRLR_DATA_FNA_FORMAT_ALL_SHIFT; cd->vwc = NVME_CTRLR_DATA_VWC_ALL_NO << NVME_CTRLR_DATA_VWC_ALL_SHIFT; - - cd->power_state[0].mp = 10; } /* @@ -698,6 +705,11 @@ pci_nvme_init_logpages(struct pci_nvme_softc *sc) sc->health_log.temperature = NVME_TEMPERATURE; sc->health_log.available_spare = 100; sc->health_log.available_spare_threshold = 10; + + /* Set Active Firmware Info to slot 1 */ + sc->fw_log.afi = (1 << NVME_FIRMWARE_PAGE_AFI_SLOT_SHIFT); + memcpy(&sc->fw_log.revision[0], sc->ctrldata.fr, + sizeof(sc->fw_log.revision[0])); } static void @@ -1026,7 +1038,7 @@ aen_thr(void *arg) pci_nvme_aen_process(sc); pthread_cond_wait(&sc->aen_cond, &sc->aen_mtx); } -#ifdef __FreeBSD__ +#ifdef __FreeBSD__ /* Smatch spots unreachable code */ pthread_mutex_unlock(&sc->aen_mtx); pthread_exit(NULL); @@ -1090,30 +1102,61 @@ pci_nvme_reset(struct pci_nvme_softc *sc) pthread_mutex_unlock(&sc->mtx); } -static void +static int pci_nvme_init_controller(struct vmctx *ctx, struct pci_nvme_softc *sc) { uint16_t acqs, asqs; DPRINTF("%s", __func__); - asqs = (sc->regs.aqa & NVME_AQA_REG_ASQS_MASK) + 1; + /* + * NVMe 2.0 states that "enabling a controller while this field is + * cleared to 0h produces undefined results" for both ACQS and + * ASQS. If zero, set CFS and do not become ready. + */ + asqs = ONE_BASED(sc->regs.aqa & NVME_AQA_REG_ASQS_MASK); + if (asqs < 2) { + EPRINTLN("%s: illegal ASQS value %#x (aqa=%#x)", __func__, + asqs - 1, sc->regs.aqa); + sc->regs.csts |= NVME_CSTS_CFS; + return (-1); + } sc->submit_queues[0].size = asqs; sc->submit_queues[0].qbase = vm_map_gpa(ctx, sc->regs.asq, sizeof(struct nvme_command) * asqs); + if (sc->submit_queues[0].qbase == NULL) { + EPRINTLN("%s: ASQ vm_map_gpa(%lx) failed", __func__, + sc->regs.asq); + sc->regs.csts |= NVME_CSTS_CFS; + return (-1); + } DPRINTF("%s mapping Admin-SQ guest 0x%lx, host: %p", __func__, sc->regs.asq, sc->submit_queues[0].qbase); - acqs = ((sc->regs.aqa >> NVME_AQA_REG_ACQS_SHIFT) & - NVME_AQA_REG_ACQS_MASK) + 1; + acqs = ONE_BASED((sc->regs.aqa >> NVME_AQA_REG_ACQS_SHIFT) & + NVME_AQA_REG_ACQS_MASK); + if (acqs < 2) { + EPRINTLN("%s: illegal ACQS value %#x (aqa=%#x)", __func__, + acqs - 1, sc->regs.aqa); + sc->regs.csts |= NVME_CSTS_CFS; + return (-1); + } sc->compl_queues[0].size = acqs; sc->compl_queues[0].qbase = vm_map_gpa(ctx, sc->regs.acq, sizeof(struct nvme_completion) * acqs); + if (sc->compl_queues[0].qbase == NULL) { + EPRINTLN("%s: ACQ vm_map_gpa(%lx) failed", __func__, + sc->regs.acq); + sc->regs.csts |= NVME_CSTS_CFS; + return (-1); + } sc->compl_queues[0].intr_en = NVME_CQ_INTEN; DPRINTF("%s mapping Admin-CQ guest 0x%lx, host: %p", __func__, sc->regs.acq, sc->compl_queues[0].qbase); + + return (0); } static int @@ -1395,13 +1438,7 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command, { uint64_t logoff; uint32_t logsize; - uint8_t logpage = command->cdw10 & 0xFF; - -#ifndef __FreeBSD__ - logsize = 0; -#endif - - DPRINTF("%s log page %u len %u", __func__, logpage, logsize); + uint8_t logpage; pci_nvme_status_genc(&compl->status, NVME_SC_SUCCESS); @@ -1409,10 +1446,13 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command, * Command specifies the number of dwords to return in fields NUMDU * and NUMDL. This is a zero-based value. */ + logpage = command->cdw10 & 0xFF; logsize = ((command->cdw11 << 16) | (command->cdw10 >> 16)) + 1; logsize *= sizeof(uint32_t); logoff = ((uint64_t)(command->cdw13) << 32) | command->cdw12; + DPRINTF("%s log page %u len %u", __func__, logpage, logsize); + switch (logpage) { case NVME_LOG_ERROR: if (logoff >= sizeof(sc->err_log)) { @@ -1523,7 +1563,7 @@ nvme_opc_identify(struct pci_nvme_softc* sc, struct nvme_command* command, dest = vm_map_gpa(sc->nsc_pi->pi_vmctx, command->prp1, sizeof(uint32_t) * 1024); /* All unused entries shall be zero */ - bzero(dest, sizeof(uint32_t) * 1024); + memset(dest, 0, sizeof(uint32_t) * 1024); ((uint32_t *)dest)[0] = 1; break; case 0x03: /* list of NSID structures in CDW1.NSID, 4096 bytes */ @@ -1535,12 +1575,21 @@ nvme_opc_identify(struct pci_nvme_softc* sc, struct nvme_command* command, dest = vm_map_gpa(sc->nsc_pi->pi_vmctx, command->prp1, sizeof(uint32_t) * 1024); /* All bytes after the descriptor shall be zero */ - bzero(dest, sizeof(uint32_t) * 1024); + memset(dest, 0, sizeof(uint32_t) * 1024); /* Return NIDT=1 (i.e. EUI64) descriptor */ ((uint8_t *)dest)[0] = 1; ((uint8_t *)dest)[1] = sizeof(uint64_t); - bcopy(sc->nsdata.eui64, ((uint8_t *)dest) + 4, sizeof(uint64_t)); + memcpy(((uint8_t *)dest) + 4, sc->nsdata.eui64, sizeof(uint64_t)); + break; + case 0x13: + /* + * Controller list is optional but used by UNH tests. Return + * a valid but empty list. + */ + dest = vm_map_gpa(sc->nsc_pi->pi_vmctx, command->prp1, + sizeof(uint16_t) * 2048); + memset(dest, 0, sizeof(uint16_t) * 2048); break; default: DPRINTF("%s unsupported identify command requested 0x%x", @@ -1655,18 +1704,17 @@ nvme_fid_to_name(uint8_t fid) } static void -nvme_feature_invalid_cb(struct pci_nvme_softc *sc, - struct nvme_feature_obj *feat, - struct nvme_command *command, +nvme_feature_invalid_cb(struct pci_nvme_softc *sc __unused, + struct nvme_feature_obj *feat __unused, + struct nvme_command *command __unused, struct nvme_completion *compl) { - pci_nvme_status_genc(&compl->status, NVME_SC_INVALID_FIELD); } static void nvme_feature_iv_config(struct pci_nvme_softc *sc, - struct nvme_feature_obj *feat, + struct nvme_feature_obj *feat __unused, struct nvme_command *command, struct nvme_completion *compl) { @@ -1698,12 +1746,11 @@ nvme_feature_iv_config(struct pci_nvme_softc *sc, #define NVME_ASYNC_EVENT_ENDURANCE_GROUP (0x4000) static void -nvme_feature_async_event(struct pci_nvme_softc *sc, - struct nvme_feature_obj *feat, +nvme_feature_async_event(struct pci_nvme_softc *sc __unused, + struct nvme_feature_obj *feat __unused, struct nvme_command *command, struct nvme_completion *compl) { - if (command->cdw11 & NVME_ASYNC_EVENT_ENDURANCE_GROUP) pci_nvme_status_genc(&compl->status, NVME_SC_INVALID_FIELD); } @@ -1712,7 +1759,7 @@ nvme_feature_async_event(struct pci_nvme_softc *sc, #define NVME_TEMP_THRESH_UNDER 1 static void nvme_feature_temperature(struct pci_nvme_softc *sc, - struct nvme_feature_obj *feat, + struct nvme_feature_obj *feat __unused, struct nvme_command *command, struct nvme_completion *compl) { @@ -1757,7 +1804,7 @@ nvme_feature_temperature(struct pci_nvme_softc *sc, static void nvme_feature_num_queues(struct pci_nvme_softc *sc, - struct nvme_feature_obj *feat, + struct nvme_feature_obj *feat __unused, struct nvme_command *command, struct nvme_completion *compl) { @@ -1955,8 +2002,8 @@ nvme_opc_format_nvm(struct pci_nvme_softc* sc, struct nvme_command* command, } static int -nvme_opc_abort(struct pci_nvme_softc* sc, struct nvme_command* command, - struct nvme_completion* compl) +nvme_opc_abort(struct pci_nvme_softc *sc __unused, struct nvme_command *command, + struct nvme_completion *compl) { DPRINTF("%s submission queue %u, command ID 0x%x", __func__, command->cdw10 & 0xFFFF, (command->cdw10 >> 16) & 0xFFFF); @@ -2185,9 +2232,10 @@ pci_nvme_out_of_range(struct pci_nvme_blockstore *nvstore, uint64_t slba, static int pci_nvme_append_iov_req(struct pci_nvme_softc *sc, struct pci_nvme_ioreq *req, - uint64_t gpaddr, size_t size, int do_write, uint64_t lba) + uint64_t gpaddr, size_t size, int do_write, uint64_t offset) { int iovidx; + bool range_is_contiguous; if (req == NULL) return (-1); @@ -2196,13 +2244,24 @@ pci_nvme_append_iov_req(struct pci_nvme_softc *sc, struct pci_nvme_ioreq *req, return (-1); } - /* concatenate contig block-iovs to minimize number of iovs */ - if ((req->prev_gpaddr + req->prev_size) == gpaddr) { + /* + * Minimize the number of IOVs by concatenating contiguous address + * ranges. If the IOV count is zero, there is no previous range to + * concatenate. + */ + if (req->io_req.br_iovcnt == 0) + range_is_contiguous = false; + else + range_is_contiguous = (req->prev_gpaddr + req->prev_size) == gpaddr; + + if (range_is_contiguous) { iovidx = req->io_req.br_iovcnt - 1; req->io_req.br_iov[iovidx].iov_base = paddr_guest2host(req->sc->nsc_pi->pi_vmctx, req->prev_gpaddr, size); + if (req->io_req.br_iov[iovidx].iov_base == NULL) + return (-1); req->prev_size += size; req->io_req.br_resid += size; @@ -2211,7 +2270,7 @@ pci_nvme_append_iov_req(struct pci_nvme_softc *sc, struct pci_nvme_ioreq *req, } else { iovidx = req->io_req.br_iovcnt; if (iovidx == 0) { - req->io_req.br_offset = lba; + req->io_req.br_offset = offset; req->io_req.br_resid = 0; req->io_req.br_param = req; } @@ -2219,6 +2278,8 @@ pci_nvme_append_iov_req(struct pci_nvme_softc *sc, struct pci_nvme_ioreq *req, req->io_req.br_iov[iovidx].iov_base = paddr_guest2host(req->sc->nsc_pi->pi_vmctx, gpaddr, size); + if (req->io_req.br_iov[iovidx].iov_base == NULL) + return (-1); req->io_req.br_iov[iovidx].iov_len = size; @@ -2234,8 +2295,7 @@ pci_nvme_append_iov_req(struct pci_nvme_softc *sc, struct pci_nvme_ioreq *req, static void pci_nvme_set_completion(struct pci_nvme_softc *sc, - struct nvme_submission_queue *sq, int sqid, uint16_t cid, - uint32_t cdw0, uint16_t status) + struct nvme_submission_queue *sq, int sqid, uint16_t cid, uint16_t status) { struct nvme_completion_queue *cq = &sc->compl_queues[sq->cqid]; @@ -2243,11 +2303,7 @@ pci_nvme_set_completion(struct pci_nvme_softc *sc, __func__, sqid, sq->cqid, cid, NVME_STATUS_GET_SCT(status), NVME_STATUS_GET_SC(status)); - pci_nvme_cq_update(sc, cq, - 0, /* CDW0 */ - cid, - sqid, - status); + pci_nvme_cq_update(sc, cq, 0, cid, sqid, status); if (cq->head != cq->tail) { if (cq->intr_en & NVME_CQ_INTEN) { @@ -2326,7 +2382,7 @@ pci_nvme_io_done(struct blockif_req *br, int err) code = err ? NVME_SC_DATA_TRANSFER_ERROR : NVME_SC_SUCCESS; pci_nvme_status_genc(&status, code); - pci_nvme_set_completion(req->sc, sq, req->sqid, req->cid, 0, status); + pci_nvme_set_completion(req->sc, sq, req->sqid, req->cid, status); pci_nvme_stats_write_read_update(req->sc, req->opc, req->bytes, status); pci_nvme_release_ioreq(req->sc, req); @@ -2341,8 +2397,8 @@ pci_nvme_io_done(struct blockif_req *br, int err) * not supported (i.e. RAM or as indicated by the blockif). */ static bool -nvme_opc_flush(struct pci_nvme_softc *sc, - struct nvme_command *cmd, +nvme_opc_flush(struct pci_nvme_softc *sc __unused, + struct nvme_command *cmd __unused, struct pci_nvme_blockstore *nvstore, struct pci_nvme_ioreq *req, uint16_t *status) @@ -2417,8 +2473,7 @@ nvme_write_read_blockif(struct pci_nvme_softc *sc, size = MIN(PAGE_SIZE - (prp1 % PAGE_SIZE), bytes); if (pci_nvme_append_iov_req(sc, req, prp1, size, is_write, offset)) { - pci_nvme_status_genc(&status, - NVME_SC_DATA_TRANSFER_ERROR); + err = -1; goto out; } @@ -2431,8 +2486,7 @@ nvme_write_read_blockif(struct pci_nvme_softc *sc, size = bytes; if (pci_nvme_append_iov_req(sc, req, prp2, size, is_write, offset)) { - pci_nvme_status_genc(&status, - NVME_SC_DATA_TRANSFER_ERROR); + err = -1; goto out; } } else { @@ -2448,6 +2502,10 @@ nvme_write_read_blockif(struct pci_nvme_softc *sc, prp_list = paddr_guest2host(vmctx, prp, PAGE_SIZE - (prp % PAGE_SIZE)); + if (prp_list == NULL) { + err = -1; + goto out; + } last = prp_list + (NVME_PRP2_ITEMS - 1); } @@ -2455,8 +2513,7 @@ nvme_write_read_blockif(struct pci_nvme_softc *sc, if (pci_nvme_append_iov_req(sc, req, *prp_list, size, is_write, offset)) { - pci_nvme_status_genc(&status, - NVME_SC_DATA_TRANSFER_ERROR); + err = -1; goto out; } @@ -2471,10 +2528,10 @@ nvme_write_read_blockif(struct pci_nvme_softc *sc, err = blockif_write(nvstore->ctx, &req->io_req); else err = blockif_read(nvstore->ctx, &req->io_req); - +out: if (err) pci_nvme_status_genc(&status, NVME_SC_DATA_TRANSFER_ERROR); -out: + return (status); } @@ -2490,12 +2547,14 @@ nvme_opc_write_read(struct pci_nvme_softc *sc, bool is_write = cmd->opc == NVME_OPC_WRITE; bool pending = false; -#ifndef __FreeBSD__ - bytes = 0; -#endif - lba = ((uint64_t)cmd->cdw11 << 32) | cmd->cdw10; nblocks = (cmd->cdw12 & 0xFFFF) + 1; + bytes = nblocks << nvstore->sectsz_bits; + if (bytes > NVME_MAX_DATA_SIZE) { + WPRINTF("%s command would exceed MDTS", __func__); + pci_nvme_status_genc(status, NVME_SC_INVALID_FIELD); + goto out; + } if (pci_nvme_out_of_range(nvstore, lba, nblocks)) { WPRINTF("%s command would exceed LBA range(slba=%#lx nblocks=%#lx)", @@ -2504,13 +2563,6 @@ nvme_opc_write_read(struct pci_nvme_softc *sc, goto out; } - bytes = nblocks << nvstore->sectsz_bits; - if (bytes > NVME_MAX_DATA_SIZE) { - WPRINTF("%s command would exceed MDTS", __func__); - pci_nvme_status_genc(status, NVME_SC_INVALID_FIELD); - goto out; - } - offset = lba << nvstore->sectsz_bits; req->bytes = bytes; @@ -2570,8 +2622,8 @@ pci_nvme_dealloc_sm(struct blockif_req *br, int err) } if (done) { - pci_nvme_set_completion(sc, req->nvme_sq, req->sqid, - req->cid, 0, status); + pci_nvme_set_completion(sc, req->nvme_sq, req->sqid, req->cid, + status); pci_nvme_release_ioreq(sc, req); } } @@ -2583,15 +2635,11 @@ nvme_opc_dataset_mgmt(struct pci_nvme_softc *sc, struct pci_nvme_ioreq *req, uint16_t *status) { - struct nvme_dsm_range *range; + struct nvme_dsm_range *range = NULL; uint32_t nr, r, non_zero, dr; int err; bool pending = false; -#ifndef __FreeBSD__ - range = NULL; -#endif - if ((sc->ctrldata.oncs & NVME_ONCS_DSM) == 0) { pci_nvme_status_genc(status, NVME_SC_INVALID_OPCODE); goto out; @@ -2781,8 +2829,7 @@ pci_nvme_handle_io_cmd(struct pci_nvme_softc* sc, uint16_t idx) } complete: if (!pending) { - pci_nvme_set_completion(sc, sq, idx, cmd->cid, 0, - status); + pci_nvme_set_completion(sc, sq, idx, cmd->cid, status); if (req != NULL) pci_nvme_release_ioreq(sc, req); } @@ -2794,7 +2841,7 @@ complete: } static void -pci_nvme_handle_doorbell(struct vmctx *ctx, struct pci_nvme_softc* sc, +pci_nvme_handle_doorbell(struct vmctx *ctx __unused, struct pci_nvme_softc* sc, uint64_t idx, int is_sq, uint64_t value) { DPRINTF("nvme doorbell %lu, %s, val 0x%lx", @@ -2898,6 +2945,12 @@ pci_nvme_write_bar_0(struct vmctx *ctx, struct pci_nvme_softc* sc, uint64_t idx = belloffset / 8; /* door bell size = 2*int */ int is_sq = (belloffset % 8) < 4; + if ((sc->regs.csts & NVME_CSTS_RDY) == 0) { + WPRINTF("doorbell write prior to RDY (offset=%#lx)\n", + offset); + return; + } + if (belloffset > ((sc->max_queues+1) * 8 - 4)) { WPRINTF("guest attempted an overflow write offset " "0x%lx, val 0x%lx in %s", @@ -2905,6 +2958,12 @@ pci_nvme_write_bar_0(struct vmctx *ctx, struct pci_nvme_softc* sc, return; } + if (is_sq) { + if (sc->submit_queues[idx].qbase == NULL) + return; + } else if (sc->compl_queues[idx].qbase == NULL) + return; + pci_nvme_handle_doorbell(ctx, sc, idx, is_sq, value); return; } @@ -2971,7 +3030,8 @@ pci_nvme_write_bar_0(struct vmctx *ctx, struct pci_nvme_softc* sc, sc->regs.cc &= ~NVME_CC_NEN_WRITE_MASK; sc->regs.cc |= ccreg & NVME_CC_NEN_WRITE_MASK; sc->regs.csts &= ~NVME_CSTS_RDY; - } else if (sc->pending_ios == 0) { + } else if ((sc->pending_ios == 0) && + !(sc->regs.csts & NVME_CSTS_CFS)) { sc->regs.csts |= NVME_CSTS_RDY; } break; @@ -3007,8 +3067,8 @@ pci_nvme_write_bar_0(struct vmctx *ctx, struct pci_nvme_softc* sc, } static void -pci_nvme_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, - int baridx, uint64_t offset, int size, uint64_t value) +pci_nvme_write(struct vmctx *ctx, int vcpu __unused, struct pci_devinst *pi, + int baridx, uint64_t offset, int size, uint64_t value) { struct pci_nvme_softc* sc = pi->pi_arg; @@ -3070,8 +3130,8 @@ static uint64_t pci_nvme_read_bar_0(struct pci_nvme_softc* sc, static uint64_t -pci_nvme_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, - uint64_t offset, int size) +pci_nvme_read(struct vmctx *ctx __unused, int vcpu __unused, + struct pci_devinst *pi, int baridx, uint64_t offset, int size) { struct pci_nvme_softc* sc = pi->pi_arg; @@ -3198,7 +3258,8 @@ pci_nvme_parse_config(struct pci_nvme_softc *sc, nvlist_t *nvl) } static void -pci_nvme_resized(struct blockif_ctxt *bctxt, void *arg, size_t new_size) +pci_nvme_resized(struct blockif_ctxt *bctxt __unused, void *arg, + size_t new_size) { struct pci_nvme_softc *sc; struct pci_nvme_blockstore *nvstore; @@ -3220,7 +3281,7 @@ pci_nvme_resized(struct blockif_ctxt *bctxt, void *arg, size_t new_size) } static int -pci_nvme_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) +pci_nvme_init(struct vmctx *ctx __unused, struct pci_devinst *pi, nvlist_t *nvl) { struct pci_nvme_softc *sc; uint32_t pci_membar_sz; @@ -3329,7 +3390,7 @@ pci_nvme_legacy_config(nvlist_t *nvl, const char *opts) return (blockif_legacy_config(nvl, opts)); } -struct pci_devemu pci_de_nvme = { +static const struct pci_devemu pci_de_nvme = { .pe_emu = "nvme", .pe_init = pci_nvme_init, .pe_legacy_config = pci_nvme_legacy_config, diff --git a/usr/src/cmd/bhyve/pci_passthru.c b/usr/src/cmd/bhyve/pci_passthru.c index 75176d6fe6..8b5f3d05ab 100644 --- a/usr/src/cmd/bhyve/pci_passthru.c +++ b/usr/src/cmd/bhyve/pci_passthru.c @@ -1087,7 +1087,7 @@ passthru_addr_rom(struct pci_devinst *const pi, const int idx, } else { if (vm_mmap_memseg(pi->pi_vmctx, addr, VM_PCIROM, pi->pi_romoffset, size, PROT_READ | PROT_EXEC) != 0) { - errx(4, "%s: mnmap_memseg @ [%016lx - %016lx] failed", + errx(4, "%s: mmap_memseg @ [%016lx - %016lx] failed", __func__, addr, addr + size); } } @@ -1117,7 +1117,7 @@ passthru_addr(struct vmctx *ctx, struct pci_devinst *pi, int baridx, } } -struct pci_devemu passthru = { +static const struct pci_devemu passthru = { .pe_emu = "passthru", .pe_init = passthru_init, .pe_legacy_config = passthru_legacy_config, diff --git a/usr/src/cmd/bhyve/pci_uart.c b/usr/src/cmd/bhyve/pci_uart.c index 25ef1ed662..3064d6fe62 100644 --- a/usr/src/cmd/bhyve/pci_uart.c +++ b/usr/src/cmd/bhyve/pci_uart.c @@ -125,7 +125,7 @@ pci_uart_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) return (0); } -struct pci_devemu pci_de_com = { +static const struct pci_devemu pci_de_com = { .pe_emu = "uart", .pe_init = pci_uart_init, .pe_legacy_config = pci_uart_legacy_config, diff --git a/usr/src/cmd/bhyve/pci_virtio_9p.c b/usr/src/cmd/bhyve/pci_virtio_9p.c index 9808fee46d..2e169dc7cb 100644 --- a/usr/src/cmd/bhyve/pci_virtio_9p.c +++ b/usr/src/cmd/bhyve/pci_virtio_9p.c @@ -389,7 +389,7 @@ pci_vt9p_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) return (0); } -struct pci_devemu pci_de_v9p = { +static const struct pci_devemu pci_de_v9p = { .pe_emu = "virtio-9p", .pe_legacy_config = pci_vt9p_legacy_config, .pe_init = pci_vt9p_init, diff --git a/usr/src/cmd/bhyve/pci_virtio_block.c b/usr/src/cmd/bhyve/pci_virtio_block.c index 30998161f0..7a0667e7b0 100644 --- a/usr/src/cmd/bhyve/pci_virtio_block.c +++ b/usr/src/cmd/bhyve/pci_virtio_block.c @@ -585,7 +585,7 @@ pci_vtblk_apply_feats(void *vsc, uint64_t caps) } #endif /* __FreeBSD__ */ -struct pci_devemu pci_de_vblk = { +static const struct pci_devemu pci_de_vblk = { .pe_emu = "virtio-blk", .pe_init = pci_vtblk_init, .pe_legacy_config = blockif_legacy_config, diff --git a/usr/src/cmd/bhyve/pci_virtio_console.c b/usr/src/cmd/bhyve/pci_virtio_console.c index 59099e688e..51b7acb1ba 100644 --- a/usr/src/cmd/bhyve/pci_virtio_console.c +++ b/usr/src/cmd/bhyve/pci_virtio_console.c @@ -661,7 +661,6 @@ pci_vtcon_notify_rx(void *vsc, struct vqueue_info *vq) } } -#ifdef __FreeBSD__ /* * Each console device has a "port" node which contains nodes for * each port. Ports are numbered starting at 0. @@ -710,7 +709,6 @@ pci_vtcon_legacy_config(nvlist_t *nvl, const char *opts) free(tofree); return (error); } -#endif static int pci_vtcon_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) @@ -779,10 +777,11 @@ pci_vtcon_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) return (0); } -struct pci_devemu pci_de_vcon = { +static const struct pci_devemu pci_de_vcon = { .pe_emu = "virtio-console", .pe_init = pci_vtcon_init, .pe_barwrite = vi_pci_write, - .pe_barread = vi_pci_read + .pe_barread = vi_pci_read, + .pe_legacy_config = pci_vtcon_legacy_config, }; PCI_EMUL_SET(pci_de_vcon); diff --git a/usr/src/cmd/bhyve/pci_virtio_input.c b/usr/src/cmd/bhyve/pci_virtio_input.c index 4517333b16..404213d907 100644 --- a/usr/src/cmd/bhyve/pci_virtio_input.c +++ b/usr/src/cmd/bhyve/pci_virtio_input.c @@ -772,7 +772,7 @@ failed: return (-1); } -struct pci_devemu pci_de_vinput = { +static const struct pci_devemu pci_de_vinput = { .pe_emu = "virtio-input", .pe_init = pci_vtinput_init, .pe_legacy_config = pci_vtinput_legacy_config, diff --git a/usr/src/cmd/bhyve/pci_virtio_net.c b/usr/src/cmd/bhyve/pci_virtio_net.c index b7094484aa..a496414809 100644 --- a/usr/src/cmd/bhyve/pci_virtio_net.c +++ b/usr/src/cmd/bhyve/pci_virtio_net.c @@ -765,7 +765,7 @@ pci_vtnet_neg_features(void *vsc, uint64_t negotiated_features) pthread_mutex_unlock(&sc->rx_mtx); } -static struct pci_devemu pci_de_vnet = { +static const struct pci_devemu pci_de_vnet = { .pe_emu = "virtio-net", .pe_init = pci_vtnet_init, .pe_legacy_config = netbe_legacy_config, diff --git a/usr/src/cmd/bhyve/pci_virtio_rnd.c b/usr/src/cmd/bhyve/pci_virtio_rnd.c index 4aff95a34e..4fbedc639c 100644 --- a/usr/src/cmd/bhyve/pci_virtio_rnd.c +++ b/usr/src/cmd/bhyve/pci_virtio_rnd.c @@ -204,7 +204,7 @@ pci_vtrnd_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) } -struct pci_devemu pci_de_vrnd = { +static const struct pci_devemu pci_de_vrnd = { .pe_emu = "virtio-rnd", .pe_init = pci_vtrnd_init, .pe_barwrite = vi_pci_write, diff --git a/usr/src/cmd/bhyve/pci_virtio_scsi.c b/usr/src/cmd/bhyve/pci_virtio_scsi.c index 6f00f58811..6f7dceb05d 100644 --- a/usr/src/cmd/bhyve/pci_virtio_scsi.c +++ b/usr/src/cmd/bhyve/pci_virtio_scsi.c @@ -735,7 +735,7 @@ pci_vtscsi_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) } -struct pci_devemu pci_de_vscsi = { +static const struct pci_devemu pci_de_vscsi = { .pe_emu = "virtio-scsi", .pe_init = pci_vtscsi_init, .pe_legacy_config = pci_vtscsi_legacy_config, diff --git a/usr/src/cmd/bhyve/pci_xhci.c b/usr/src/cmd/bhyve/pci_xhci.c index 0b9fde3208..4caa32e981 100644 --- a/usr/src/cmd/bhyve/pci_xhci.c +++ b/usr/src/cmd/bhyve/pci_xhci.c @@ -167,6 +167,13 @@ struct pci_xhci_dev_ep { #define ep_tr _ep_trbsctx._epu_tr #define ep_sctx _ep_trbsctx._epu_sctx + /* + * Caches the value of MaxPStreams from the endpoint context + * when an endpoint is initialized and is used to validate the + * use of ep_ringaddr vs ep_sctx_trbs[] as well as the length + * of ep_sctx_trbs[]. + */ + uint32_t ep_MaxPStreams; union { struct pci_xhci_trb_ring _epu_trb; struct pci_xhci_trb_ring *_epu_sctx_trbs; @@ -565,7 +572,7 @@ pci_xhci_portregs_write(struct pci_xhci_softc *sc, uint64_t offset, } } -struct xhci_dev_ctx * +static struct xhci_dev_ctx * pci_xhci_get_dev_ctx(struct pci_xhci_softc *sc, uint32_t slot) { uint64_t devctx_addr; @@ -589,7 +596,7 @@ pci_xhci_get_dev_ctx(struct pci_xhci_softc *sc, uint32_t slot) return (devctx); } -struct xhci_trb * +static struct xhci_trb * pci_xhci_trb_next(struct pci_xhci_softc *sc, struct xhci_trb *curtrb, uint64_t *guestaddr) { @@ -674,6 +681,7 @@ pci_xhci_init_ep(struct pci_xhci_dev_emu *dev, int epid) devep->ep_tr = XHCI_GADDR(dev->xsc, devep->ep_ringaddr); DPRINTF(("init_ep tr DCS %x", devep->ep_ccs)); } + devep->ep_MaxPStreams = pstreams; if (devep->ep_xfer == NULL) { devep->ep_xfer = malloc(sizeof(struct usb_data_xfer)); @@ -695,9 +703,8 @@ pci_xhci_disable_ep(struct pci_xhci_dev_emu *dev, int epid) ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_DISABLED; devep = &dev->eps[epid]; - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) > 0 && - devep->ep_sctx_trbs != NULL) - free(devep->ep_sctx_trbs); + if (devep->ep_MaxPStreams > 0) + free(devep->ep_sctx_trbs); if (devep->ep_xfer != NULL) { free(devep->ep_xfer); @@ -1157,7 +1164,7 @@ pci_xhci_cmd_reset_ep(struct pci_xhci_softc *sc, uint32_t slot, ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_STOPPED; - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) == 0) + if (devep->ep_MaxPStreams == 0) ep_ctx->qwEpCtx2 = devep->ep_ringaddr | devep->ep_ccs; DPRINTF(("pci_xhci: reset ep[%u] %08x %08x %016lx %08x", @@ -1178,16 +1185,15 @@ done: static uint32_t pci_xhci_find_stream(struct pci_xhci_softc *sc, struct xhci_endp_ctx *ep, - uint32_t streamid, struct xhci_stream_ctx **osctx) + struct pci_xhci_dev_ep *devep, uint32_t streamid, + struct xhci_stream_ctx **osctx) { struct xhci_stream_ctx *sctx; - uint32_t maxpstreams; - maxpstreams = XHCI_EPCTX_0_MAXP_STREAMS_GET(ep->dwEpCtx0); - if (maxpstreams == 0) + if (devep->ep_MaxPStreams == 0) return (XHCI_TRB_ERROR_TRB); - if (maxpstreams > XHCI_STREAMS_MAX) + if (devep->ep_MaxPStreams > XHCI_STREAMS_MAX) return (XHCI_TRB_ERROR_INVALID_SID); if (XHCI_EPCTX_0_LSA_GET(ep->dwEpCtx0) == 0) { @@ -1196,7 +1202,7 @@ pci_xhci_find_stream(struct pci_xhci_softc *sc, struct xhci_endp_ctx *ep, } /* only support primary stream */ - if (streamid > maxpstreams) + if (streamid > devep->ep_MaxPStreams) return (XHCI_TRB_ERROR_STREAM_TYPE); sctx = XHCI_GADDR(sc, ep->qwEpCtx2 & ~0xFUL) + streamid; @@ -1258,11 +1264,12 @@ pci_xhci_cmd_set_tr(struct pci_xhci_softc *sc, uint32_t slot, } streamid = XHCI_TRB_2_STREAM_GET(trb->dwTrb2); - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) > 0) { + if (devep->ep_MaxPStreams > 0) { struct xhci_stream_ctx *sctx; sctx = NULL; - cmderr = pci_xhci_find_stream(sc, ep_ctx, streamid, &sctx); + cmderr = pci_xhci_find_stream(sc, ep_ctx, devep, streamid, + &sctx); if (sctx != NULL) { assert(devep->ep_sctx != NULL); @@ -1632,7 +1639,7 @@ pci_xhci_update_ep_ring(struct pci_xhci_softc *sc, struct pci_xhci_dev_emu *dev, uint32_t streamid, uint64_t ringaddr, int ccs) { - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) != 0) { + if (devep->ep_MaxPStreams != 0) { devep->ep_sctx[streamid].qwSctx0 = (ringaddr & ~0xFUL) | (ccs & 0x1); @@ -1959,7 +1966,7 @@ pci_xhci_device_doorbell(struct pci_xhci_softc *sc, uint32_t slot, } /* get next trb work item */ - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) != 0) { + if (devep->ep_MaxPStreams != 0) { struct xhci_stream_ctx *sctx; /* @@ -1972,7 +1979,7 @@ pci_xhci_device_doorbell(struct pci_xhci_softc *sc, uint32_t slot, } sctx = NULL; - pci_xhci_find_stream(sc, ep_ctx, streamid, &sctx); + pci_xhci_find_stream(sc, ep_ctx, devep, streamid, &sctx); if (sctx == NULL) { DPRINTF(("pci_xhci: invalid stream %u", streamid)); return; @@ -2950,7 +2957,7 @@ done: return (error); } -struct pci_devemu pci_de_xhci = { +static const struct pci_devemu pci_de_xhci = { .pe_emu = "xhci", .pe_init = pci_xhci_init, .pe_legacy_config = pci_xhci_legacy_config, diff --git a/usr/src/cmd/bhyve/smbiostbl.c b/usr/src/cmd/bhyve/smbiostbl.c index 8c3cd6332d..fc0d69e9fc 100644 --- a/usr/src/cmd/bhyve/smbiostbl.c +++ b/usr/src/cmd/bhyve/smbiostbl.c @@ -43,6 +43,10 @@ __FBSDID("$FreeBSD$"); #include #include +#ifndef __FreeBSD__ +#include +#endif + #include "bhyverun.h" #include "config.h" #include "debug.h" @@ -77,13 +81,18 @@ struct smbios_structure { uint16_t handle; } __packed; +struct smbios_string { + const char *node; + const char *value; +}; + typedef int (*initializer_func_t)(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size); struct smbios_template_entry { struct smbios_structure *entry; - const char **strings; + struct smbios_string *strings; initializer_func_t initializer; }; @@ -351,11 +360,11 @@ struct smbios_table_type0 smbios_type0_template = { 0xff /* embedded controller firmware minor release */ }; -const char *smbios_type0_strings[] = { - "BHYVE", /* vendor string */ - FIRMWARE_VERSION, /* bios version string */ - FIRMWARE_RELEASE_DATE, /* bios release date string */ - NULL +struct smbios_string smbios_type0_strings[] = { + { "bios.vendor", "BHYVE" }, /* vendor string */ + { "bios.version", FIRMWARE_VERSION }, /* bios version string */ + { "bios.release_date", FIRMWARE_RELEASE_DATE }, /* bios release date string */ + { 0 } }; struct smbios_table_type1 smbios_type1_template = { @@ -371,17 +380,17 @@ struct smbios_table_type1 smbios_type1_template = { }; static int smbios_type1_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size); -const char *smbios_type1_strings[] = { - "illumos", /* manufacturer string */ - "BHYVE", /* product name string */ - "1.0", /* version string */ - "None", /* serial number string */ - "None", /* sku string */ - "Virtual Machine", /* family name string */ - NULL +struct smbios_string smbios_type1_strings[] = { + { "system.manufacturer", "illumos" }, /* manufacturer string */ + { "system.product_name", "BHYVE" }, /* product string */ + { "system.version", "1.0" }, /* version string */ + { "system.serial_number", "None" }, /* serial number string */ + { "system.sku", "None" }, /* sku string */ + { "system.family_name", "Virtual Machine" }, /* family string */ + { 0 } }; struct smbios_table_type2 smbios_type2_template = { @@ -398,14 +407,14 @@ struct smbios_table_type2 smbios_type2_template = { 0 }; -const char *smbios_type2_strings[] = { - "illumos", /* manufacturer string */ - "BHYVE", /* product name string */ - "1.0", /* version string */ - "None", /* serial number string */ - "None", /* asset tag string */ - "None", /* location string */ - NULL +struct smbios_string smbios_type2_strings[] = { + { "board.manufacturer", "illumos" }, /* manufacturer string */ + { "board.product_name", "BHYVE" }, /* product name string */ + { "board.version", "1.0" }, /* version string */ + { "board.serial_number", "None" }, /* serial number string */ + { "board.asset_tag", "None" }, /* asset tag string */ + { "board.location", "None" }, /* location string */ + { 0 } }; struct smbios_table_type3 smbios_type3_template = { @@ -427,13 +436,13 @@ struct smbios_table_type3 smbios_type3_template = { 5 /* sku number string */ }; -const char *smbios_type3_strings[] = { - "illumos", /* manufacturer string */ - "1.0", /* version string */ - "None", /* serial number string */ - "None", /* asset tag string */ - "None", /* sku number string */ - NULL +struct smbios_string smbios_type3_strings[] = { + { "chassis.manufacturer", "illumos" }, /* manufacturer string */ + { "chassis.version", "1.0" }, /* version string */ + { "chassis.serial_number", "None" }, /* serial number string */ + { "chassis.asset_tag", "None" }, /* asset tag string */ + { "chassis.sku", "None" }, /* sku number string */ + { 0 } }; struct smbios_table_type4 smbios_type4_template = { @@ -463,18 +472,18 @@ struct smbios_table_type4 smbios_type4_template = { SMBIOS_PRF_OTHER }; -const char *smbios_type4_strings[] = { - " ", /* socket designation string */ - " ", /* manufacturer string */ - " ", /* version string */ - "None", /* serial number string */ - "None", /* asset tag string */ - "None", /* part number string */ - NULL +struct smbios_string smbios_type4_strings[] = { + { NULL, " " }, /* socket designation string */ + { NULL, " " }, /* manufacturer string */ + { NULL, " " }, /* version string */ + { NULL, "None" }, /* serial number string */ + { NULL, "None" }, /* asset tag string */ + { NULL, "None" }, /* part number string */ + { 0 } }; static int smbios_type4_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size); struct smbios_table_type16 smbios_type16_template = { @@ -489,7 +498,7 @@ struct smbios_table_type16 smbios_type16_template = { }; static int smbios_type16_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size); struct smbios_table_type17 smbios_type17_template = { @@ -518,18 +527,18 @@ struct smbios_table_type17 smbios_type17_template = { 0 /* configured voltage in mv (0=unknown) */ }; -const char *smbios_type17_strings[] = { - " ", /* device locator string */ - " ", /* physical bank locator string */ - " ", /* manufacturer string */ - "None", /* serial number string */ - "None", /* asset tag string */ - "None", /* part number string */ - NULL +struct smbios_string smbios_type17_strings[] = { + { NULL, " " }, /* device locator string */ + { NULL, " " }, /* physical bank locator string */ + { NULL, " " }, /* manufacturer string */ + { NULL, "None" }, /* serial number string */ + { NULL, "None" }, /* asset tag string */ + { NULL, "None" }, /* part number string */ + { 0 } }; static int smbios_type17_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size); struct smbios_table_type19 smbios_type19_template = { @@ -543,7 +552,7 @@ struct smbios_table_type19 smbios_type19_template = { }; static int smbios_type19_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size); struct smbios_table_type32 smbios_type32_template = { @@ -557,7 +566,7 @@ struct smbios_table_type127 smbios_type127_template = { }; static int smbios_generic_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size); static struct smbios_template_entry smbios_template[] = { @@ -599,7 +608,7 @@ static uint16_t type16_handle; static int smbios_generic_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size) { struct smbios_structure *entry; @@ -611,11 +620,20 @@ smbios_generic_initializer(struct smbios_structure *template_entry, if (template_strings != NULL) { int i; - for (i = 0; template_strings[i] != NULL; i++) { + for (i = 0; template_strings[i].value != NULL; i++) { const char *string; int len; - string = template_strings[i]; + if (template_strings[i].node == NULL) { + string = template_strings[i].value; + } else { + set_config_value_if_unset( + template_strings[i].node, + template_strings[i].value); + string = get_config_value( + template_strings[i].node); + } + len = strlen(string) + 1; memcpy(curaddr, string, len); curaddr += len; @@ -637,7 +655,7 @@ smbios_generic_initializer(struct smbios_structure *template_entry, static int smbios_type1_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size) { struct smbios_table_type1 *type1; @@ -653,8 +671,10 @@ smbios_type1_initializer(struct smbios_structure *template_entry, uint32_t status; uuid_from_string(guest_uuid_str, &uuid, &status); - if (status != uuid_s_ok) + if (status != uuid_s_ok) { + EPRINTLN("Invalid UUID"); return (-1); + } uuid_enc_le(&type1->uuid, &uuid); } else { @@ -693,7 +713,7 @@ smbios_type1_initializer(struct smbios_structure *template_entry, static int smbios_type4_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size) { int i; @@ -735,7 +755,7 @@ smbios_type4_initializer(struct smbios_structure *template_entry, static int smbios_type16_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size) { struct smbios_table_type16 *type16; @@ -752,7 +772,7 @@ smbios_type16_initializer(struct smbios_structure *template_entry, static int smbios_type17_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size) { struct smbios_table_type17 *type17; @@ -796,7 +816,7 @@ smbios_type17_initializer(struct smbios_structure *template_entry, static int smbios_type19_initializer(struct smbios_structure *template_entry, - const char **template_strings, char *curaddr, char **endaddr, + struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n, uint16_t *size) { struct smbios_table_type19 *type19; @@ -862,6 +882,26 @@ smbios_ep_finalizer(struct smbios_entry_point *smbios_ep, uint16_t len, smbios_ep->echecksum = checksum; } +#ifndef __FreeBSD__ +/* + * bhyve on illumos previously used configuration keys starting with 'smbios.' + * to control type 1 SMBIOS information. Since these may still be present in + * bhyve configuration files, the following table is used to translate them + * to their new key names. + */ +static struct { + const char *oldkey; + const char *newkey; +} smbios_legacy_config_map[] = { + { "smbios.manufacturer", "system.manufacturer" }, + { "smbios.family", "system.family_name" }, + { "smbios.product", "system.product_name" }, + { "smbios.serial", "system.serial_number" }, + { "smbios.sku", "system.sku" }, + { "smbios.version", "system.version" }, +}; +#endif + int smbios_build(struct vmctx *ctx) { @@ -881,6 +921,19 @@ smbios_build(struct vmctx *ctx) return (ENOMEM); } +#ifndef __FreeBSD__ + /* Translate legacy illumos configuration keys */ + for (uint_t i = 0; i < ARRAY_SIZE(smbios_legacy_config_map); i++) { + const char *v; + + v = get_config_value(smbios_legacy_config_map[i].oldkey); + if (v != NULL) { + set_config_value_if_unset( + smbios_legacy_config_map[i].newkey, v); + } + } +#endif + curaddr = startaddr; smbios_ep = (struct smbios_entry_point *)curaddr; @@ -893,7 +946,7 @@ smbios_build(struct vmctx *ctx) maxssize = 0; for (i = 0; smbios_template[i].entry != NULL; i++) { struct smbios_structure *entry; - const char **strings; + struct smbios_string *strings; initializer_func_t initializer; char *endaddr; uint16_t size; @@ -920,42 +973,39 @@ smbios_build(struct vmctx *ctx) } #ifndef __FreeBSD__ -struct { +static struct { + uint_t type; const char *key; - const char **targetp; -} type1_map[] = { - { "manufacturer", &smbios_type1_strings[0] }, - { "product", &smbios_type1_strings[1] }, - { "version", &smbios_type1_strings[2] }, - { "serial", &smbios_type1_strings[3] }, - { "sku", &smbios_type1_strings[4] }, - { "family", &smbios_type1_strings[5] }, - { 0 } + char *val; +} smbios_legacy_map[] = { + { 1, "product", "product_name" }, + { 1, "serial", "serial_number" }, + { 1, "family", "family_name" }, }; -void -smbios_apply(void) -{ - nvlist_t *nvl; - - nvl = find_config_node("smbios"); - if (nvl == NULL) - return; - - for (uint_t i = 0; type1_map[i].key != NULL; i++) { - const char *value; - - value = get_config_value_node(nvl, type1_map[i].key); - if (value != NULL) - *type1_map[i].targetp = value; - } -} +static struct smbios_string *smbios_tbl_map[] = { + smbios_type0_strings, + smbios_type1_strings, + smbios_type2_strings, + smbios_type3_strings, +}; +/* + * This function accepts an option of the form + * type,[key=value][,key=value]... + * and sets smbios data for the given type. Keys for type X are defined in the + * smbios_typeX_strings tables above, but for type 1 there are also some + * legacy values which were accepted in earlier versions of bhyve on illumos + * which need to be mapped. + */ int smbios_parse(const char *opts) { - char *buf, *lasts, *token, *end; + char *buf, *lasts, *token, *typekey = NULL; + const char *errstr; + struct smbios_string *tbl; nvlist_t *nvl; + uint_t i; long type; if ((buf = strdup(opts)) == NULL) { @@ -968,59 +1018,79 @@ smbios_parse(const char *opts) goto fail; } - errno = 0; - type = strtol(token, &end, 10); - if (errno != 0 || *end != '\0') { - (void) fprintf(stderr, "first token '%s' is not an integer\n", - token); + type = strtonum(token, 0, 3, &errstr); + if (errstr != NULL) { + fprintf(stderr, "First token (type) is %s\n", errstr); goto fail; } - /* For now, only type 1 is supported. */ - if (type != 1) { - (void) fprintf(stderr, "unsupported type %d\n", type); + tbl = smbios_tbl_map[type]; + + /* Extract the config key for this type */ + typekey = strdup(tbl[0].node); + if (typekey == NULL) { + (void) fprintf(stderr, "out of memory\n"); goto fail; } - nvl = create_config_node("smbios"); + token = strchr(typekey, '.'); + assert(token != NULL); + *token = '\0'; + + nvl = create_config_node(typekey); if (nvl == NULL) { (void) fprintf(stderr, "out of memory\n"); - return (-1); + goto fail; } while ((token = strtok_r(NULL, ",", &lasts)) != NULL) { char *val; - uint_t i; - if ((val = strchr(token, '=')) == NULL) { + if ((val = strchr(token, '=')) == NULL || val[1] == '\0') { (void) fprintf(stderr, "invalid key=value: '%s'\n", token); goto fail; } - *val = '\0'; - val++; + *val++ = '\0'; + /* UUID is a top-level config item, but -U takes priority */ if (strcmp(token, "uuid") == 0) { - set_config_value_node(nvl, token, val); + set_config_value_if_unset(token, val); continue; } - for (i = 0; type1_map[i].key != NULL; i++) { - if (strcmp(token, type1_map[i].key) == 0) { + /* Translate legacy keys */ + for (i = 0; i < ARRAY_SIZE(smbios_legacy_map); i++) { + if (type == smbios_legacy_map[i].type && + strcmp(token, smbios_legacy_map[i].key) == 0) { + token = smbios_legacy_map[i].val; break; } } - if (type1_map[i].key == NULL) { - (void) fprintf(stderr, "invalid key '%s'\n", token); + + for (i = 0; tbl[i].value != NULL; i++) { + if (strcmp(tbl[i].node + strlen(typekey) + 1, + token) == 0) { + /* Found match */ + break; + } + } + + if (tbl[i].value == NULL) { + (void) fprintf(stderr, + "Unknown SMBIOS key %s for type %d\n", token, type); goto fail; } + set_config_value_node(nvl, token, val); } + free(typekey); return (0); fail: free(buf); + free(typekey); return (-1); } #endif diff --git a/usr/src/contrib/bhyve/dev/nvme/nvme.h b/usr/src/contrib/bhyve/dev/nvme/nvme.h index 2f393ea1d1..5820908f3c 100644 --- a/usr/src/contrib/bhyve/dev/nvme/nvme.h +++ b/usr/src/contrib/bhyve/dev/nvme/nvme.h @@ -73,8 +73,11 @@ */ #define NVME_GLOBAL_NAMESPACE_TAG ((uint32_t)0xFFFFFFFF) -/* Cap transfers by the maximum addressable by page-sized PRP (4KB -> 2MB). */ -#define NVME_MAX_XFER_SIZE MIN(maxphys, (PAGE_SIZE/8*PAGE_SIZE)) +/* Host memory buffer sizes are always in 4096 byte chunks */ +#define NVME_HMB_UNITS 4096 + +/* Many items are expressed in terms of power of two times MPS */ +#define NVME_MPS_SHIFT 12 /* Register field definitions */ #define NVME_CAP_LO_REG_MQES_SHIFT (0) @@ -215,6 +218,7 @@ #define NVME_STATUS_GET_P(st) (((st) >> NVME_STATUS_P_SHIFT) & NVME_STATUS_P_MASK) #define NVME_STATUS_GET_SC(st) (((st) >> NVME_STATUS_SC_SHIFT) & NVME_STATUS_SC_MASK) #define NVME_STATUS_GET_SCT(st) (((st) >> NVME_STATUS_SCT_SHIFT) & NVME_STATUS_SCT_MASK) +#define NVME_STATUS_GET_CRD(st) (((st) >> NVME_STATUS_CRD_SHIFT) & NVME_STATUS_CRD_MASK) #define NVME_STATUS_GET_M(st) (((st) >> NVME_STATUS_M_SHIFT) & NVME_STATUS_M_MASK) #define NVME_STATUS_GET_DNR(st) (((st) >> NVME_STATUS_DNR_SHIFT) & NVME_STATUS_DNR_MASK) diff --git a/usr/src/lib/libvmmapi/common/vmmapi.c b/usr/src/lib/libvmmapi/common/vmmapi.c index a3c00d616b..3d47b70214 100644 --- a/usr/src/lib/libvmmapi/common/vmmapi.c +++ b/usr/src/lib/libvmmapi/common/vmmapi.c @@ -60,6 +60,9 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef __FreeBSD__ +#include +#endif #include #include #include @@ -69,6 +72,9 @@ __FBSDID("$FreeBSD$"); #include +#ifdef __FreeBSD__ +#include +#endif #include #include @@ -111,7 +117,27 @@ struct vmctx { #ifdef __FreeBSD__ #define CREATE(x) sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x))) #define DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x))) +#endif + +static int +vm_device_open(const char *name) +{ + int fd, len; + char *vmfile; + len = strlen("/dev/vmm/") + strlen(name) + 1; + vmfile = malloc(len); + assert(vmfile != NULL); + snprintf(vmfile, len, "/dev/vmm/%s", name); + + /* Open the device file */ + fd = open(vmfile, O_RDWR, 0); + + free(vmfile); + return (fd); +} + +#ifdef __FreeBSD__ int vm_create(const char *name) { @@ -120,19 +146,6 @@ vm_create(const char *name) kldload("vmm"); return (CREATE(name)); } - -void -vm_destroy(struct vmctx *vm) -{ - assert(vm != NULL); - - if (vm->fd >= 0) - close(vm->fd); - DESTROY(vm->name); - - free(vm); -} - #else static int vm_do_ctl(int cmd, void *req) @@ -167,51 +180,8 @@ vm_create(const char *name, uint64_t flags) return (vm_do_ctl(VMM_CREATE_VM, &req)); } - -void -vm_close(struct vmctx *vm) -{ - assert(vm != NULL); - assert(vm->fd >= 0); - - (void) close(vm->fd); - - free(vm); -} - -void -vm_destroy(struct vmctx *vm) -{ - assert(vm != NULL); - - if (vm->fd >= 0) { - (void) ioctl(vm->fd, VM_DESTROY_SELF, 0); - (void) close(vm->fd); - vm->fd = -1; - } - - free(vm); -} #endif -static int -vm_device_open(const char *name) -{ - int fd, len; - char *vmfile; - - len = strlen("/dev/vmm/") + strlen(name) + 1; - vmfile = malloc(len); - assert(vmfile != NULL); - snprintf(vmfile, len, "/dev/vmm/%s", name); - - /* Open the device file */ - fd = open(vmfile, O_RDWR, 0); - - free(vmfile); - return (fd); -} - struct vmctx * vm_open(const char *name) { @@ -238,6 +208,53 @@ err: return (NULL); } +#ifdef __FreeBSD__ +void +vm_close(struct vmctx *vm) +{ + assert(vm != NULL); + + close(vm->fd); + free(vm); +} + +void +vm_destroy(struct vmctx *vm) +{ + assert(vm != NULL); + + if (vm->fd >= 0) + close(vm->fd); + DESTROY(vm->name); + + free(vm); +} +#else +void +vm_close(struct vmctx *vm) +{ + assert(vm != NULL); + assert(vm->fd >= 0); + + (void) close(vm->fd); + + free(vm); +} + +void +vm_destroy(struct vmctx *vm) +{ + assert(vm != NULL); + + if (vm->fd >= 0) { + (void) ioctl(vm->fd, VM_DESTROY_SELF, 0); + (void) close(vm->fd); + vm->fd = -1; + } + + free(vm); +} +#endif int vm_parse_memsize(const char *opt, size_t *ret_memsize) @@ -330,6 +347,19 @@ vm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid, vm_ooffset_t off, return (error); } +#ifdef __FreeBSD__ +int +vm_get_guestmem_from_ctx(struct vmctx *ctx, char **guest_baseaddr, + size_t *lowmem_size, size_t *highmem_size) +{ + + *guest_baseaddr = ctx->baseaddr; + *lowmem_size = ctx->lowmem; + *highmem_size = ctx->highmem; + return (0); +} +#endif + int vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, size_t len) { @@ -594,6 +624,33 @@ vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len) return (NULL); } +#ifdef __FreeBSD__ +vm_paddr_t +vm_rev_map_gpa(struct vmctx *ctx, void *addr) +{ + vm_paddr_t offaddr; + + offaddr = (char *)addr - ctx->baseaddr; + + if (ctx->lowmem > 0) + if (offaddr <= ctx->lowmem) + return (offaddr); + + if (ctx->highmem > 0) + if (offaddr >= 4*GB && offaddr < 4*GB + ctx->highmem) + return (offaddr); + + return ((vm_paddr_t)-1); +} + +const char * +vm_get_name(struct vmctx *ctx) +{ + + return (ctx->name); +} +#endif /* __FreeBSD__ */ + size_t vm_get_lowmem_size(struct vmctx *ctx) { @@ -800,6 +857,21 @@ vm_get_register_set(struct vmctx *ctx, int vcpu, unsigned int count, return (error); } +#ifdef __FreeBSD__ +int +vm_run(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit) +{ + int error; + struct vm_run vmrun; + + bzero(&vmrun, sizeof(vmrun)); + vmrun.cpuid = vcpu; + + error = ioctl(ctx->fd, VM_RUN, &vmrun); + bcopy(&vmrun.vm_exit, vmexit, sizeof(struct vm_exit)); + return (error); +} +#else int vm_run(struct vmctx *ctx, int vcpu, const struct vm_entry *vm_entry, struct vm_exit *vm_exit) @@ -812,6 +884,7 @@ vm_run(struct vmctx *ctx, int vcpu, const struct vm_entry *vm_entry, return (ioctl(ctx->fd, VM_RUN, &entry)); } +#endif int vm_suspend(struct vmctx *ctx, enum vm_suspend_how how) @@ -823,22 +896,22 @@ vm_suspend(struct vmctx *ctx, enum vm_suspend_how how) return (ioctl(ctx->fd, VM_SUSPEND, &vmsuspend)); } -#ifndef __FreeBSD__ +#ifdef __FreeBSD__ int -vm_reinit(struct vmctx *ctx, uint64_t flags) +vm_reinit(struct vmctx *ctx) { - struct vm_reinit reinit = { - .flags = flags - }; - return (ioctl(ctx->fd, VM_REINIT, &reinit)); + return (ioctl(ctx->fd, VM_REINIT, 0)); } #else int -vm_reinit(struct vmctx *ctx) +vm_reinit(struct vmctx *ctx, uint64_t flags) { + struct vm_reinit reinit = { + .flags = flags + }; - return (ioctl(ctx->fd, VM_REINIT, 0)); + return (ioctl(ctx->fd, VM_REINIT, &reinit)); } #endif @@ -1200,26 +1273,6 @@ vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func, return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix); } -int -vm_get_pptdev_limits(struct vmctx *ctx, int bus, int slot, int func, - int *msi_limit, int *msix_limit) -{ - struct vm_pptdev_limits pptlimits; - int error; - - bzero(&pptlimits, sizeof (pptlimits)); - pptlimits.bus = bus; - pptlimits.slot = slot; - pptlimits.func = func; - - error = ioctl(ctx->fd, VM_GET_PPTDEV_LIMITS, &pptlimits); - - *msi_limit = pptlimits.msi_limit; - *msix_limit = pptlimits.msix_limit; - - return (error); -} - int vm_disable_pptdev_msix(struct vmctx *ctx, int bus, int slot, int func) { @@ -1370,16 +1423,15 @@ vm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv, if (vmstats.num_entries != nitems(vmstats.statbuf)) break; } - if (have_stats) { if (ret_entries) *ret_entries = count; if (ret_tv) *ret_tv = vmstats.tv; return (stats_buf); + } else { + return (NULL); } - - return (NULL); } const char * @@ -1458,13 +1510,21 @@ vcpu_reset(struct vmctx *vmctx, int vcpu) if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0) goto done; + /* + * According to Intels Software Developer Manual CR0 should be + * initialized with CR0_ET | CR0_NW | CR0_CD but that crashes some + * guests like Windows. + */ cr0 = CR0_NE; if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0) goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR2, zero)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, zero)) != 0) goto done; - + cr4 = 0; if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0) goto done; @@ -1527,6 +1587,9 @@ vcpu_reset(struct vmctx *vmctx, int vcpu) if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, sel)) != 0) goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_EFER, zero)) != 0) + goto done; + /* General purpose registers */ rdx = 0xf00; if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RAX, zero)) != 0) @@ -1545,6 +1608,22 @@ vcpu_reset(struct vmctx *vmctx, int vcpu) goto done; if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, zero)) != 0) goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_R8, zero)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_R9, zero)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_R10, zero)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_R11, zero)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_R12, zero)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_R13, zero)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_R14, zero)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_R15, zero)) != 0) + goto done; /* GDTR, IDTR */ desc_base = 0; @@ -1585,7 +1664,16 @@ vcpu_reset(struct vmctx *vmctx, int vcpu) if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0) goto done; - /* XXX cr2, debug registers */ + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DR6, + 0xffff0ff0)) != 0) + goto done; + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DR7, 0x400)) != + 0) + goto done; + + if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_INTR_SHADOW, + zero)) != 0) + goto done; error = 0; done: diff --git a/usr/src/lib/libvmmapi/common/vmmapi.h b/usr/src/lib/libvmmapi/common/vmmapi.h index 9d5470f729..4dffd7d755 100644 --- a/usr/src/lib/libvmmapi/common/vmmapi.h +++ b/usr/src/lib/libvmmapi/common/vmmapi.h @@ -94,6 +94,10 @@ enum { VM_PCIROM, }; +#ifdef __cplusplus +extern "C" { +#endif + /* * Get the length and name of the memory segment identified by 'segid'. * Note that system memory segments are identified with a nul name. @@ -142,9 +146,7 @@ int vm_create(const char *name); #endif /* __FreeBSD__ */ int vm_get_device_fd(struct vmctx *ctx); struct vmctx *vm_open(const char *name); -#ifndef __FreeBSD__ void vm_close(struct vmctx *ctx); -#endif void vm_destroy(struct vmctx *ctx); int vm_parse_memsize(const char *optarg, size_t *memsize); int vm_setup_memory(struct vmctx *ctx, size_t len, enum vm_mmap_style s); @@ -339,4 +341,9 @@ int vm_setup_freebsd_registers_i386(struct vmctx *vmctx, int vcpu, uint32_t esp); void vm_setup_freebsd_gdt(uint64_t *gdtr); #endif + +#ifdef __cplusplus +} +#endif + #endif /* _VMMAPI_H_ */ diff --git a/usr/src/man/man5/bhyve_config.5 b/usr/src/man/man5/bhyve_config.5 index f031165f89..3a5c0a2615 100644 --- a/usr/src/man/man5/bhyve_config.5 +++ b/usr/src/man/man5/bhyve_config.5 @@ -25,7 +25,7 @@ .\" .\" Portions Copyright 2022 OmniOS Community Edition (OmniOSce) Association. .\" -.Dd April 6, 2022 +.Dd June 1, 2022 .Dt BHYVE_CONFIG 5 .Os .Sh NAME @@ -174,6 +174,96 @@ Enable debug messages relating to the emulated XHCI controller. These messages are sent to .Dv stderr . +.It Va bios.vendor Ta string Ta BHYVE Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va bios.version Ta string Ta 14.0 Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va bios.release_date Ta string Ta 10/17/2021 Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va system.family_name Ta string Ta Virtual Machine Ta +Family the computer belongs to. +This value is used for the guest's System Management BIOS System Information +structure. +.It Va system.manufacturer Ta string Ta illumos Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va system.product_name Ta string Ta BHYVE Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va system.serial_number Ta string Ta None Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va system.sku Ta string Ta None Ta +Stock keeping unit of the computer. +It's also called product ID or purchase order number. +This value is used for the guest's System Management BIOS System Information +structure. +.It Va system.version Ta string Ta 1.0 Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va board.manufacturer Ta string Ta illumos Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va board.product_name Ta string Ta BHYVE Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va board.version Ta string Ta 1.0 Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va board.serial_number Ta string Ta None Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va board.asset_tag Ta string Ta None Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va board.location Ta string Ta None Ta +Describes the board's location within the chassis. +This value is used for the guest's System Management BIOS System Information +structure. +.It Va chassis.manufacturer Ta string Ta illumos Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va chassis.version Ta string Ta 1.0 Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va chassis.serial_number Ta string Ta None Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va chassis.asset_tag Ta string Ta None Ta +This value is used for the guest's System Management BIOS System Information +structure. +.It Va chassis.sku Ta string Ta None Ta +Stock keeping unit of the chassis. +It's also called product ID or purchase order number. +This value is used for the guest's System Management BIOS System Information +structure. +.It Va smbios.family Ta string Ta Virtual Machine Ta +Legacy alias for +.Va system.family_name , +do not use in new configurations. +.It Va smbios.manufacturer Ta string Ta illumos Ta +Legacy alias for +.Va system.manufacturer , +do not use in new configurations. +.It Va smbios.product Ta string Ta BHYVE Ta +Legacy alias for +.Va system.product_name , +do not use in new configurations. +.It Va smbios.serial Ta string Ta None Ta +Legacy alias for +.Va system.serial_number , +do not use in new configurations. +.It Va smbios.sku Ta string Ta None Ta +Legacy alias for +.Va system.sku , +do not use in new configurations. +.It Va smbios.version Ta string Ta 1.0 Ta +Legacy alias for +.Va system.version , +do not use in new configurations. .El .Ss x86-Specific Settings .Bl -column "x86.vmexit_on_pause" "integer" "Default" diff --git a/usr/src/man/man8/bhyve.8 b/usr/src/man/man8/bhyve.8 index a862668b8c..cb5551a33b 100644 --- a/usr/src/man/man8/bhyve.8 +++ b/usr/src/man/man8/bhyve.8 @@ -24,7 +24,7 @@ .\" .\" Portions Copyright 2022 OmniOS Community Edition (OmniOSce) Association. .\" -.Dd February 26, 2022 +.Dd June 1, 2022 .Dt BHYVE 8 .Os .Sh NAME @@ -115,17 +115,28 @@ It will be deprecated in a future version. .Xc Configure smbios data. .Ar type -must be set to -.Sy 1 . -Supported keys are: -.Sy manufacturer , -.Sy product , -.Sy version , -.Sy serial , -.Sy sku , -.Sy family -and -.Sy uuid . +must be set to one of +.Cm 0 , 1 , 2 +or +.Cm 3 . +Supported keys for each type are: +.Bl -tag -width XXX -offset XXX +.It Cm 0 +.Cm vendor , version , release_date . +.It Cm 1 +.Cm manufacturer , +.Cm product_name Pq or Cm product , +.Cm version , +.Cm serial_number Pq or Cm serial , +.Cm sku , +.Cm family_name Pq or Cm family , +.Cm uuid . +.It Cm 2 +.Cm manufacturer , product_name , version , serial_number , asset_tag , +.Cm location +.It Ic 3 +.Cm manufacturer , version , serial_number , asset_tag, sku . +.El .It Xo Fl c .Sm off .Op Oo Cm cpus= Oc Ar numcpus diff --git a/usr/src/uts/intel/io/vmm/amd/amdvi_hw.c b/usr/src/uts/intel/io/vmm/amd/amdvi_hw.c index 33a2557492..c217b19112 100644 --- a/usr/src/uts/intel/io/vmm/amd/amdvi_hw.c +++ b/usr/src/uts/intel/io/vmm/amd/amdvi_hw.c @@ -418,7 +418,7 @@ amdvi_cmd_inv_intr_map(struct amdvi_softc *softc, static void amdvi_inv_domain(struct amdvi_softc *softc, uint16_t domain_id) { - struct amdvi_cmd *cmd; + struct amdvi_cmd *cmd __diagused; cmd = amdvi_get_cmd_tail(softc); KASSERT(cmd != NULL, ("Cmd is NULL")); @@ -439,13 +439,14 @@ amdvi_inv_domain(struct amdvi_softc *softc, uint16_t domain_id) static bool amdvi_cmp_wait(struct amdvi_softc *softc) { - struct amdvi_ctrl *ctrl; +#ifdef AMDVI_DEBUG_CMD + struct amdvi_ctrl *ctrl = softc->ctrl; +#endif const uint64_t VERIFY = 0xA5A5; volatile uint64_t *read; int i; bool status; - ctrl = softc->ctrl; read = &softc->cmp_data; *read = 0; amdvi_cmd_cmp(softc, VERIFY); diff --git a/usr/src/uts/intel/io/vmm/amd/svm.c b/usr/src/uts/intel/io/vmm/amd/svm.c index f4f01ea4b6..a20a844030 100644 --- a/usr/src/uts/intel/io/vmm/amd/svm.c +++ b/usr/src/uts/intel/io/vmm/amd/svm.c @@ -378,6 +378,10 @@ vmcb_init(struct svm_softc *sc, int vcpu, uint64_t iopm_base_pa, svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_STGI); svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_CLGI); svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_SKINIT); + if (vcpu_trap_wbinvd(sc->vm, vcpu) != 0) { + svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, + VMCB_INTCPT_WBINVD); + } /* * The ASID will be set to a non-zero value just before VMRUN. @@ -1448,7 +1452,6 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit) (void) vm_suspend(svm_sc->vm, VM_SUSPEND_TRIPLEFAULT); handled = 1; break; - case VMCB_EXIT_INVD: case VMCB_EXIT_INVLPGA: /* privileged invalidation instructions */ vm_inject_ud(svm_sc->vm, vcpu); @@ -1464,6 +1467,11 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit) vm_inject_ud(svm_sc->vm, vcpu); handled = 1; break; + case VMCB_EXIT_INVD: + case VMCB_EXIT_WBINVD: + /* ignore exit */ + handled = 1; + break; case VMCB_EXIT_VMMCALL: /* No handlers make use of VMMCALL for now */ vm_inject_ud(svm_sc->vm, vcpu); diff --git a/usr/src/uts/intel/io/vmm/amd/vmcb.h b/usr/src/uts/intel/io/vmm/amd/vmcb.h index 7a57979d56..91e00193bf 100644 --- a/usr/src/uts/intel/io/vmm/amd/vmcb.h +++ b/usr/src/uts/intel/io/vmm/amd/vmcb.h @@ -172,6 +172,7 @@ struct svm_softc; #define VMCB_EXIT_STGI 0x84 #define VMCB_EXIT_CLGI 0x85 #define VMCB_EXIT_SKINIT 0x86 +#define VMCB_EXIT_WBINVD 0x89 #define VMCB_EXIT_MONITOR 0x8A #define VMCB_EXIT_MWAIT 0x8B #define VMCB_EXIT_NPF 0x400 diff --git a/usr/src/uts/intel/io/vmm/intel/vmx.c b/usr/src/uts/intel/io/vmm/intel/vmx.c index c16fe1f1d4..e42455a0f3 100644 --- a/usr/src/uts/intel/io/vmm/intel/vmx.c +++ b/usr/src/uts/intel/io/vmm/intel/vmx.c @@ -188,6 +188,9 @@ static int vmx_initialized; /* PAUSE triggers a VM-exit */ static int cap_pause_exit; +/* WBINVD triggers a VM-exit */ +static int cap_wbinvd_exit; + /* Monitor trap flag */ static int cap_monitor_trap; @@ -548,6 +551,11 @@ vmx_init(void) PROCBASED_PAUSE_EXITING, 0, &tmp) == 0); + cap_wbinvd_exit = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, + MSR_VMX_PROCBASED_CTLS2, + PROCBASED2_WBINVD_EXITING, 0, + &tmp) == 0); + cap_invpcid = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, MSR_VMX_PROCBASED_CTLS2, PROCBASED2_ENABLE_INVPCID, 0, &tmp) == 0); @@ -819,7 +827,12 @@ vmx_vminit(struct vm *vm) vmcs_write(VMCS_EPTP, vmx->eptp); vmcs_write(VMCS_PIN_BASED_CTLS, pin_ctls); vmcs_write(VMCS_PRI_PROC_BASED_CTLS, proc_ctls); - vmcs_write(VMCS_SEC_PROC_BASED_CTLS, proc2_ctls); + + uint32_t use_proc2_ctls = proc2_ctls; + if (cap_wbinvd_exit && vcpu_trap_wbinvd(vm, i) != 0) + use_proc2_ctls |= PROCBASED2_WBINVD_EXITING; + vmcs_write(VMCS_SEC_PROC_BASED_CTLS, use_proc2_ctls); + vmcs_write(VMCS_EXIT_CTLS, exit_ctls); vmcs_write(VMCS_ENTRY_CTLS, entry_ctls); vmcs_write(VMCS_MSR_BITMAP, msr_bitmap_pa); @@ -2530,6 +2543,11 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) SDT_PROBE3(vmm, vmx, exit, vminsn, vmx, vcpu, vmexit); vmexit->exitcode = VM_EXITCODE_VMINSN; break; + case EXIT_REASON_INVD: + case EXIT_REASON_WBINVD: + /* ignore exit */ + handled = HANDLED; + break; default: SDT_PROBE4(vmm, vmx, exit, unknown, vmx, vcpu, vmexit, reason); diff --git a/usr/src/uts/intel/io/vmm/sys/vmm_kernel.h b/usr/src/uts/intel/io/vmm/sys/vmm_kernel.h index c5c7d7889e..1ef2d48adf 100644 --- a/usr/src/uts/intel/io/vmm/sys/vmm_kernel.h +++ b/usr/src/uts/intel/io/vmm/sys/vmm_kernel.h @@ -358,6 +358,7 @@ void vm_copyout(struct vm *vm, int vcpuid, const void *kaddr, struct vm_copyinfo *copyinfo, size_t len); int vcpu_trace_exceptions(struct vm *vm, int vcpuid); +int vcpu_trap_wbinvd(struct vm *vm, int vcpuid); void vm_inject_ud(struct vm *vm, int vcpuid); void vm_inject_gp(struct vm *vm, int vcpuid); diff --git a/usr/src/uts/intel/io/vmm/vmm.c b/usr/src/uts/intel/io/vmm/vmm.c index 44f1ee5ca2..136c38c5ab 100644 --- a/usr/src/uts/intel/io/vmm/vmm.c +++ b/usr/src/uts/intel/io/vmm/vmm.c @@ -286,10 +286,13 @@ SYSCTL_NODE(_hw, OID_AUTO, vmm, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, * Halt the guest if all vcpus are executing a HLT instruction with * interrupts disabled. */ -static int halt_detection_enabled = 1; +int halt_detection_enabled = 1; /* Trap into hypervisor on all guest exceptions and reflect them back */ -static int trace_guest_exceptions; +int trace_guest_exceptions; + +/* Trap WBINVD and ignore it */ +int trap_wbinvd = 1; static void vm_free_memmap(struct vm *vm, int ident); static bool sysmem_mapping(struct vm *vm, struct mem_map *mm); @@ -403,10 +406,15 @@ vcpu_init(struct vm *vm, int vcpu_id, bool create) int vcpu_trace_exceptions(struct vm *vm, int vcpuid) { - return (trace_guest_exceptions); } +int +vcpu_trap_wbinvd(struct vm *vm, int vcpuid) +{ + return (trap_wbinvd); +} + struct vm_exit * vm_exitinfo(struct vm *vm, int cpuid) { -- cgit v1.2.3 From b18d44ce328fbdf8d8c82ef1763d30b8a46edfde Mon Sep 17 00:00:00 2001 From: Bryan Cantrill Date: Sat, 20 Aug 2022 22:06:33 +0000 Subject: 14535 cfgadm_usb(8) should provide iSerialNumber in -v output Reviewed by: Robert Mustacchi Reviewed by: Andy Fiddaman Reviewed by: Marco van Wieringen Approved by: Dan McDonald --- usr/src/lib/cfgadm_plugins/usb/common/cfga_usb.c | 29 +++++- usr/src/man/man8/cfgadm_usb.8 | 114 +++++++++++++---------- 2 files changed, 92 insertions(+), 51 deletions(-) diff --git a/usr/src/lib/cfgadm_plugins/usb/common/cfga_usb.c b/usr/src/lib/cfgadm_plugins/usb/common/cfga_usb.c index 47976fb058..663cd02f09 100644 --- a/usr/src/lib/cfgadm_plugins/usb/common/cfga_usb.c +++ b/usr/src/lib/cfgadm_plugins/usb/common/cfga_usb.c @@ -22,9 +22,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. + * Copyright 2022 Oxide Computer Company */ - #include "cfga_usb.h" @@ -889,12 +889,14 @@ fill_in_ap_info(const char *ap_id, char *info_buf, size_t info_size) { char *mfg_str = NULL; /* iManufacturer */ char *prod_str = NULL; /* iProduct */ + char *serial_str = NULL; /* iSerialNumber */ char *cfg_descr = NULL; /* iConfiguration */ uint_t config; /* curr cfg index */ size_t size; /* tmp stuff */ boolean_t flag; /* wether to print ":" or not */ boolean_t free_mfg_str = B_FALSE; boolean_t free_prod_str = B_FALSE; + boolean_t free_serial_str = B_FALSE; boolean_t free_cfg_str = B_FALSE; cfga_usb_ret_t rv = CFGA_USB_OK; usb_dev_descr_t *dev_descrp = NULL; /* device descriptor */ @@ -938,6 +940,22 @@ fill_in_ap_info(const char *ap_id, char *info_buf, size_t info_size) free_prod_str = B_TRUE; } + /* iSerialNumber */ + serial_str = USB_UNDEF_STR; + if (dev_descrp->iSerialNumber != 0) { + if ((rv = do_control_ioctl(ap_id, USB_DESCR_TYPE_STRING, + HUBD_SERIALNO_STR, (void **)&serial_str, + &size)) != CFGA_USB_OK) { + if (rv == CFGA_USB_ZEROLEN) { + rv = CFGA_USB_OK; + } else { + DPRINTF("getting iSerialNumber failed\n"); + goto bailout; + } + } + free_serial_str = B_TRUE; + } + /* Current conifguration */ if ((rv = get_config(ap_id, &config)) != CFGA_USB_OK) { DPRINTF("get_config failed\n"); @@ -968,8 +986,9 @@ fill_in_ap_info(const char *ap_id, char *info_buf, size_t info_size) /* Dump local buf into passed-in buf. */ (void) snprintf(info_buf, info_size, - "Mfg: %s Product: %s NConfigs: %d Config: %d %s%s", mfg_str, - prod_str, dev_descrp->bNumConfigurations, config, + "Mfg: %s Product: %s Serial: %s NConfigs: %d Config: %d %s%s", + mfg_str, prod_str, serial_str, + dev_descrp->bNumConfigurations, config, (flag == B_TRUE) ? ": " : "", cfg_descr); bailout: @@ -985,6 +1004,10 @@ bailout: free(prod_str); } + if ((free_serial_str == B_TRUE) && serial_str) { + free(serial_str); + } + if ((free_cfg_str == B_TRUE) && cfg_descr) { free(cfg_descr); } diff --git a/usr/src/man/man8/cfgadm_usb.8 b/usr/src/man/man8/cfgadm_usb.8 index 885025a8fc..3ec886a51d 100644 --- a/usr/src/man/man8/cfgadm_usb.8 +++ b/usr/src/man/man8/cfgadm_usb.8 @@ -1,13 +1,13 @@ '\" te .\" Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved. +.\" Copyright 2022 Oxide Computer Company .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CFGADM_USB 8 "Mar 1, 2007" +.TH CFGADM_USB 8 "Feb 23, 2022" .SH NAME cfgadm_usb \- USB hardware-specific commands for cfgadm .SH SYNOPSIS -.LP .nf \fB/usr/sbin/cfgadm\fR [\fB-f\fR] [\fB-y\fR | \fB-n\fR] [\fB-v\fR] \fB-c\fR \fIfunction\fR \fIap_id\fR... .fi @@ -30,7 +30,6 @@ cfgadm_usb \- USB hardware-specific commands for cfgadm .fi .SH DESCRIPTION -.LP The Universal Serial Bus (\fBUSB\fR) hardware-specific library \fB/usr/lib/cfgadm/usb.so.1\fR provides the functionality for administering \fBUSB\fR devices via the \fBcfgadm\fR(8) command. \fBcfgadm\fR operates on @@ -179,13 +178,13 @@ The following table shows the somewhat confusing routing for this USB 2.0 chip: .nf logical port number physical port number ------------------- -------------------- - usb1/1 internal port 1 + usb1/1 internal port 1 usb1/2 external port 1 usb1/3 external port 3 - + usb2/1 internal port 2 usb2/2 external port 2 - + usb3/1 internal port 1 usb3/2 internal port 2 usb3/3 external port 1 @@ -332,7 +331,6 @@ before removing its device from the \fBUSB\fR. However, it is not recommended to hot-remove devices currently in use (such as removable disks currently opened by a volume manager or some other application). .SH OPTIONS -.LP \fBcfgadm\fR defines several types of operations. These operations include invoking configuration state changes (\fB-c\fR), invoking hardware-specific functions (\fB-x\fR), and obtaining configuration administration help messages @@ -451,6 +449,12 @@ the \fB-v\fR option, the \fBInformation\fR field contains the following .TP .ie t \(bu .el o +\fBSerial\fR: serial number (\fBiSerialNumber\fR) +.RE +.RS +4 +.TP +.ie t \(bu +.el o \fBNConfigs\fR: total number of configurations the device supports (\fBbNumConfigurations\fR). .RE @@ -623,7 +627,6 @@ connected/configured: .sp .SH EXAMPLES -.LP \fBExample 1 \fRListing the Status of All USB Devices .sp .LP @@ -795,13 +798,19 @@ the '\fBInformation\fR' field: .TP .ie t \(bu .el o -Manufacturer string: Iomega +Manufacturer string: STMicroelectronics .RE .RS +4 .TP .ie t \(bu .el o -Product string: \fBUSB Zip 250\fR +Product string: \fBSTLINK-V3\fR +.RE +.RS +4 +.TP +.ie t \(bu +.el o +Serial number: 003C00174741500520383733 .RE .RS +4 .TP @@ -824,11 +833,12 @@ Configuration string descriptor for configuration 0: Default .sp .in +2 .nf -example# \fBcfgadm -lv usb0/1.5\fR +example# \fBcfgadm -lv usb2/1.2\fR Ap_Id Receptacle Occupant Condition Information -When Type Busy Phys_Id -usb0/1.5 connected configured ok Mfg:"Io -mega" Product:"USB Zip 250" NConfigs:1 Config:0 : Default +When Type Busy Phys_Id +usb2/1.2 connected configured ok Mfg: STMicroelectronics +Product: STLINK-V3 Serial: 003C00174741500520383733 NConfigs: 1 Config: +0 : Default Config .fi .in -2 .sp @@ -836,10 +846,10 @@ mega" Product:"USB Zip 250" NConfigs:1 Config:0 : Default .sp .in +2 .nf -example# \fBcfgadm -l -s "cols=ap_id:info" usb0/1.5\fR +example# \fBcfgadm -l -s "cols=ap_id:info" usb2/1.2\fR Ap_Id Information -usb0/1.5 Mfg:"Iomega" Product:"USB Zip 250" -NConfigs:1 Config:0 : Default +usb2/1.2 Mfg: STMicroelectronics Product: STLINK-V3 +Serial: 003C00174741500520383733 NConfigs: 1 Config: 0 : Default Config .fi .in -2 .sp @@ -855,21 +865,33 @@ on the system: .in +2 .nf example# \fBcfgadm -l -s "select=class(usb),cols=ap_id:info"\fR -Ap_Id Information -usb0/1 Mfg: Product: -NConfigs:1 Config:0 -usb0/2 -usb0/1.1 Mfg: Product: -NConfigs:1 Config:0 -usb0/1.2 -usb0/1.3 -usb0/1.4 Mfg:"Wizard" Product:"Modem/ISDN" -NConfigs:3 Config:1 : V.90 Analog Modem -usb0/1.5 Mfg:"Iomega" Product:"USB Zip 250" -NConfigs:1 Config:0 : Default -usb0/1.6 Mfg:"SOLID YEAR" Product:"SOLID YEAR -USB"NConfigs:1 Config:0 -usb0/1.7 +Ap_Id Information +usb1/3 Mfg: VIA Labs, Inc. Product: USB2.0 Hub +Serial: NConfigs: 1 Config: 0 +usb1/3.1 Mfg: STMicroelectronics Product: STM32 STLink +Serial: 0668FF515754888367141334 NConfigs: 1 Config: 0 +usb1/3.2 +usb1/3.3 Mfg: STMicroelectronics Product: STLINK-V3 +Serial: 003700303137511139383538 NConfigs: 1 Config: 0 : Default Config +usb1/3.4 Mfg: FTDI Product: FT4232H MiniModule +Serial: FT51SZA7 NConfigs: 1 Config: 0 +usb1/4 +usb1/5 +usb1/6 +usb1/7 Mfg: VIA Labs, Inc. Product: USB3.0 Hub +Serial: NConfigs: 1 Config: 0 +usb1/7.1 +usb1/7.2 +usb1/7.3 +usb1/7.4 +usb1/8 +usb2/1 Mfg: Product: Serial: +NConfigs: 1 Config: 0 +usb2/1.1 Mfg: ARM Product: DAPLink CMSIS-DAP +Serial: 02360b000d96e4fc00000000000000000000000097969905 NConfigs: 1 +Config: 0 +usb2/1.2 Mfg: STMicroelectronics Product: STLINK-V3 +Serial: 003C00174741500520383733 NConfigs: 1 Config: 0 : Default Config .fi .in -2 .sp @@ -884,16 +906,14 @@ information about those devices. .in +2 .nf example# \fBcfgadm -l -s "select=class(usb),cols=ap_id:info" | grep Mfg\fR -usb0/1 Mfg: Product: -NConfigs:1 Config:0 -usb0/1.1 Mfg: Product: -NConfigs:1 Config:0 -usb0/1.4 Mfg:"Wizard" Product:"Modem/ISDN" -NConfigs:3 Config:1 : V.90 Analog Modem -usb0/1.5 Mfg:"Iomega" Product:"USB Zip 250" -NConfigs:1 Config:0 : Default -usb0/1.6 Mfg:"SOLID YEAR" Product:"SOLID YEAR USB" -Config:0 +usb1/3 Mfg: VIA Labs, Inc. Product: USB2.0 Hub +Serial: NConfigs: 1 Config: 0 +usb1/3.1 Mfg: STMicroelectronics Product: STM32 STLink +Serial: 0668FF515754888367141334 NConfigs: 1 Config: 0 +usb1/3.3 Mfg: STMicroelectronics Product: STLINK-V3 +Serial: 003700303137511139383538 NConfigs: 1 Config: 0 : Default Config +usb1/3.4 Mfg: FTDI Product: FT4232H MiniModule +Serial: FT51SZA7 NConfigs: 1 Config: 0 .fi .in -2 .sp @@ -913,10 +933,10 @@ are \fB0\fR, \fB1\fR, and \fB2\fR (\fB0\fR to (\fIN\fR\fBConfigs-1\fR)). .sp .in +2 .nf -example# \fBcfgadm -l -s "cols=ap_id:info" usb0/1.4\fR -Ap_Id Information -usb0/1.4 Mfg:"Wizard" Product:"Modem/ISDN" -NConfigs:3 Config:1 V.90 Analog Modem" +example# \fBcfgadm -l -s "cols=ap_id:info" usb1/3.3\fR +Ap_Id Information +usb1/3.3 Mfg: STMicroelectronics Product: STLINK-V3 +Serial: 003700303137511139383538 NConfigs: 1 Config: 0 : Default Config .fi .in -2 .sp @@ -965,7 +985,6 @@ Hardware specific library for generic USB device administration .RE .SH SEE ALSO -.LP .BR config_admin (3CFGADM), .BR scsa2usb (4D), .BR usba (4D), @@ -978,7 +997,6 @@ Universal Serial Bus 1.1 Specification (\fBwww.usb.org\fR) .LP \fI\fR .SH NOTES -.LP \fBcfgadm\fR(8) can not unconfigure, disconnect, reset, or change the configuration of any \fBUSB\fR device currently opened by any application. These operations also fail on a hub if a device in its hierarchy is opened by -- cgit v1.2.3 From 0accf5554adfa8ff02c02d58042253bfa597bfa2 Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Sat, 22 Oct 2022 23:25:41 +0000 Subject: 15114 IP_DONTFRAG more like IP please frag Reviewed by: Dan McDonald Reviewed by: Ryan Zezeski Approved by: Richard Lowe --- usr/src/uts/common/inet/ip/ip.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c index 0f6ac91ce6..6063fa01d2 100644 --- a/usr/src/uts/common/inet/ip/ip.c +++ b/usr/src/uts/common/inet/ip/ip.c @@ -26,6 +26,7 @@ * Copyright (c) 2016 by Delphix. All rights reserved. * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. * Copyright 2021 Joyent, Inc. + * Copyright 2022 Oxide Computer Company */ #include @@ -3750,10 +3751,17 @@ ip_get_pmtu(ip_xmit_attr_t *ixa) pmtu = IP_MAXPACKET; /* - * Decide whether whether IPv4 sets DF - * For IPv6 "no DF" means to use the 1280 mtu - */ - if (ixa->ixa_flags & IXAF_PMTU_DISCOVERY) { + * We need to determine if it is acceptable to set DF for IPv4 or not + * and for IPv6 if we need to use the minimum MTU. If a connection has + * opted into path MTU discovery, then we can use 'DF' in IPv4 and do + * not have to constrain ourselves to the IPv6 minimum MTU. There is a + * second consideration here: IXAF_DONTFRAG. This is set as a result of + * someone setting the IP_DONTFRAG or IPV6_DONTFRAG socket option. In + * such a case, it is acceptable to set DF for IPv4 and to use a larger + * MTU. Note, the actual MTU is constrained by the ill_t later on in + * this function. + */ + if (ixa->ixa_flags & (IXAF_PMTU_DISCOVERY | IXAF_DONTFRAG)) { ixa->ixa_flags |= IXAF_PMTU_IPV4_DF; } else { ixa->ixa_flags &= ~IXAF_PMTU_IPV4_DF; -- cgit v1.2.3 From 5fcf5f8704b3d1b7e6175f9cb17fea58f5e56cdb Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Sat, 22 Oct 2022 23:25:43 +0000 Subject: 15119 truss could support IP, IPv6 sockopts 15115 IP_DONTFRAG could use docs Reviewed by: Ryan Zezeski Approved by: Richard Lowe --- usr/src/cmd/truss/print.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++ usr/src/man/man4p/ip.4p | 16 ++++++ 2 files changed, 146 insertions(+) diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c index b977a5d14e..177239d031 100644 --- a/usr/src/cmd/truss/print.c +++ b/usr/src/cmd/truss/print.c @@ -23,6 +23,7 @@ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2020 Joyent, Inc. * Copyright 2022 Garrett D'Amore + * Copyright 2022 Oxide Computer Company */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -76,6 +77,8 @@ #include #include #include +#include +#include #include #include #include @@ -2109,6 +2112,127 @@ udp_optname(private_t *pri, long val) } +const char * +ip_optname(private_t *pri, long val) +{ + switch (val) { + case IP_OPTIONS: return ("IP_OPTIONS"); + case IP_HDRINCL: return ("IP_HDRINCL"); + case IP_TOS: return ("IP_TOS"); + case IP_TTL: return ("IP_TTL"); + case IP_RECVOPTS: return ("IP_RECVOPTS"); + case IP_RECVRETOPTS: return ("IP_RECVRETOPTS"); + case IP_RECVDSTADDR: return ("IP_RECVDSTADDR"); + case IP_RETOPTS: return ("IP_RETOPTS"); + case IP_RECVIF: return ("IP_RECVIF"); + case IP_RECVSLLA: return ("IP_RECVSLLA"); + case IP_RECVTTL: return ("IP_RECVTTL"); + case IP_RECVTOS: return ("IP_RECVTOS"); + case IP_MULTICAST_IF: return ("IP_MULTICAST_IF"); + case IP_MULTICAST_TTL: return ("IP_MULTICAST_TTL"); + case IP_MULTICAST_LOOP: return ("IP_MULTICAST_LOOP"); + case IP_ADD_MEMBERSHIP: return ("IP_ADD_MEMBERSHIP"); + case IP_DROP_MEMBERSHIP: return ("IP_DROP_MEMBERSHIP"); + case IP_BLOCK_SOURCE: return ("IP_BLOCK_SOURCE"); + case IP_UNBLOCK_SOURCE: return ("IP_UNBLOCK_SOURCE"); + case IP_ADD_SOURCE_MEMBERSHIP: return ("IP_ADD_SOURCE_MEMBERSHIP"); + case IP_DROP_SOURCE_MEMBERSHIP: return ("IP_DROP_SOURCE_MEMBERSHIP"); + case IP_NEXTHOP: return ("IP_NEXTHOP"); + /* IP_PKTINFO and IP_RECVPKTINFO share the same code */ + case IP_PKTINFO: return ("IP_PKTINFO/IP_RECVPKTINFO"); + case IP_DONTFRAG: return ("IP_DONTFRAG"); + case IP_SEC_OPT: return ("IP_SEC_OPT"); + case MCAST_JOIN_GROUP: return ("MCAST_JOIN_GROUP"); + case MCAST_LEAVE_GROUP: return ("MCAST_LEAVE_GROUP"); + case MCAST_BLOCK_SOURCE: return ("MCAST_BLOCK_SOURCE"); + case MCAST_UNBLOCK_SOURCE: return ("MCAST_UNBLOCK_SOURCE"); + case MCAST_JOIN_SOURCE_GROUP: return ("MCAST_JOIN_SOURCE_GROUP"); + case MCAST_LEAVE_SOURCE_GROUP: return ("MCAST_LEAVE_SOURCE_GROUP"); + case MRT_INIT: return ("MRT_INIT"); + case MRT_DONE: return ("MRT_DONE"); + case MRT_ADD_VIF: return ("MRT_ADD_VIF"); + case MRT_DEL_VIF: return ("MRT_DEL_VIF"); + case MRT_ADD_MFC: return ("MRT_ADD_MFC"); + case MRT_DEL_MFC: return ("MRT_DEL_MFC"); + case MRT_VERSION: return ("MRT_VERSION"); + case MRT_ASSERT: return ("MRT_ASSERT"); + case IP_BOUND_IF: return ("IP_BOUND_IF"); + case IP_UNSPEC_SRC: return ("IP_UNSPEC_SRC"); + case IP_BROADCAST_TTL: return ("IP_BROADCAST_TTL"); + case IP_DHCPINIT_IF: return ("IP_DHCPINIT_IF"); + case IP_REUSEADDR: return ("IP_REUSEADDR"); + case IP_DONTROUTE: return ("IP_DONTROUTE"); + case IP_BROADCAST: return ("IP_BROADCAST"); + + default: (void) snprintf(pri->code_buf, + sizeof (pri->code_buf), "0x%lx", + val); + return (pri->code_buf); + } +} + +const char * +ipv6_optname(private_t *pri, long val) +{ + switch (val) { + case IPV6_UNICAST_HOPS: return ("IPV6_UNICAST_HOPS"); + case IPV6_MULTICAST_IF: return ("IPV6_MULTICAST_IF"); + case IPV6_MULTICAST_HOPS: return ("IPV6_MULTICAST_HOPS"); + case IPV6_MULTICAST_LOOP: return ("IPV6_MULTICAST_LOOP"); + case IPV6_JOIN_GROUP: return ("IPV6_JOIN_GROUP"); + case IPV6_LEAVE_GROUP: return ("IPV6_LEAVE_GROUP"); + case IPV6_PKTINFO: return ("IPV6_PKTINFO"); + case IPV6_HOPLIMIT: return ("IPV6_HOPLIMIT"); + case IPV6_NEXTHOP: return ("IPV6_NEXTHOP"); + case IPV6_HOPOPTS: return ("IPV6_HOPOPTS"); + case IPV6_DSTOPTS: return ("IPV6_DSTOPTS"); + case IPV6_RTHDR: return ("IPV6_RTHDR"); + case IPV6_RTHDRDSTOPTS: return ("IPV6_RTHDRDSTOPTS"); + case IPV6_RECVPKTINFO: return ("IPV6_RECVPKTINFO"); + case IPV6_RECVHOPLIMIT: return ("IPV6_RECVHOPLIMIT"); + case IPV6_RECVHOPOPTS: return ("IPV6_RECVHOPOPTS"); + case _OLD_IPV6_RECVDSTOPTS: return ("_OLD_IPV6_RECVDSTOPTS"); + case IPV6_RECVRTHDR: return ("IPV6_RECVRTHDR"); + case IPV6_RECVRTHDRDSTOPTS: return ("IPV6_RECVRTHDRDSTOPTS"); + case IPV6_CHECKSUM: return ("IPV6_CHECKSUM"); + case IPV6_RECVTCLASS: return ("IPV6_RECVTCLASS"); + case IPV6_USE_MIN_MTU: return ("IPV6_USE_MIN_MTU"); + case IPV6_DONTFRAG: return ("IPV6_DONTFRAG"); + case IPV6_SEC_OPT: return ("IPV6_SEC_OPT"); + case IPV6_SRC_PREFERENCES: return ("IPV6_SRC_PREFERENCES"); + case IPV6_RECVPATHMTU: return ("IPV6_RECVPATHMTU"); + case IPV6_PATHMTU: return ("IPV6_PATHMTU"); + case IPV6_TCLASS: return ("IPV6_TCLASS"); + case IPV6_V6ONLY: return ("IPV6_V6ONLY"); + case IPV6_RECVDSTOPTS: return ("IPV6_RECVDSTOPTS"); + case MCAST_JOIN_GROUP: return ("MCAST_JOIN_GROUP"); + case MCAST_LEAVE_GROUP: return ("MCAST_LEAVE_GROUP"); + case MCAST_BLOCK_SOURCE: return ("MCAST_BLOCK_SOURCE"); + case MCAST_UNBLOCK_SOURCE: return ("MCAST_UNBLOCK_SOURCE"); + case MCAST_JOIN_SOURCE_GROUP: return ("MCAST_JOIN_SOURCE_GROUP"); + case MCAST_LEAVE_SOURCE_GROUP: return ("MCAST_LEAVE_SOURCE_GROUP"); + + default: (void) snprintf(pri->code_buf, + sizeof (pri->code_buf), "0x%lx", + val); + return (pri->code_buf); + } +} + + +const char * +icmpv6_optname(private_t *pri, long val) +{ + switch (val) { + case ICMP6_FILTER: return ("ICMP6_FILTER"); + default: (void) snprintf(pri->code_buf, + sizeof (pri->code_buf), "0x%lx", + val); + return (pri->code_buf); + } +} + + /* * Print setsockopt()/getsockopt() 3rd argument. */ @@ -2122,6 +2246,12 @@ prt_son(private_t *pri, int raw, long val) break; case SOL_ROUTE: outstring(pri, route_optname(pri, val)); break; + case IPPROTO_IP: outstring(pri, ip_optname(pri, val)); + break; + case IPPROTO_IPV6: outstring(pri, ipv6_optname(pri, val)); + break; + case IPPROTO_ICMPV6: outstring(pri, icmpv6_optname(pri, val)); + break; case IPPROTO_TCP: outstring(pri, tcp_optname(pri, val)); break; case IPPROTO_UDP: outstring(pri, udp_optname(pri, val)); diff --git a/usr/src/man/man4p/ip.4p b/usr/src/man/man4p/ip.4p index 90d2af5f17..b88f4d9a5a 100644 --- a/usr/src/man/man4p/ip.4p +++ b/usr/src/man/man4p/ip.4p @@ -1,5 +1,6 @@ '\" te .\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. +.\" Copyright 2022 Oxide Computer Company .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved. .\" Copyright 2008 AT&T .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. @@ -165,6 +166,21 @@ The following options are boolean switches controlling the reception of ancillary data. The option value is type \fBint\fR; a non-zero value enables the option whilst a zero value disables it. +.sp +.ne 2 +.na +\fBIP_DONTFRAG\fR +.ad +.RS 22n +This option controls the behavior of IP-level fragmentation. When this option +is enabled (non-zero), then the IP Don't Fragment (DF) flag is always set in +the IP header. At the same time, Path MTU discovery is disabled for the given +socket. When this option is disabled, then the networking stack will determine +when to insert the DF flag in the IP header based on the current state of Path +MTU discovery. The system default is to treat this option as disabled, that is +that Path MTU discovery is in effect. +.RE + .sp .ne 2 .na -- cgit v1.2.3 From 77ef2e2dc992015d6c68f5923c0216f6d000fc96 Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Sat, 22 Oct 2022 21:21:15 +0000 Subject: 15120 dtest missing dependency on CPU counters Reviewed by: Patrick Mooney Approved by: Richard Lowe --- usr/src/pkg/manifests/system-dtrace-tests.p5m | 1 + 1 file changed, 1 insertion(+) diff --git a/usr/src/pkg/manifests/system-dtrace-tests.p5m b/usr/src/pkg/manifests/system-dtrace-tests.p5m index 87c573132b..49529498f3 100644 --- a/usr/src/pkg/manifests/system-dtrace-tests.p5m +++ b/usr/src/pkg/manifests/system-dtrace-tests.p5m @@ -2044,5 +2044,6 @@ legacy pkg=SUNWdtrt category=internal \ hotline="Contact the DTrace discussion forum" name="DTrace Test Suite" license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL +depend type=require fmri=diagnostic/cpu-counters depend type=require fmri=runtime/java depend type=require fmri=runtime/java/runtime64 -- cgit v1.2.3 From 1fde93bfc5537d4261d6ef3ac9db44a76d697e75 Mon Sep 17 00:00:00 2001 From: Andy Fiddaman Date: Mon, 3 Oct 2022 17:22:47 +0000 Subject: 14489 bhyve should emulate imul Reviewed by: Toomas Soome Portions contributed by: Patrick Mooney Approved by: Robert Mustacchi --- usr/src/pkg/manifests/system-bhyve-tests.p5m | 1 + usr/src/test/bhyve-tests/runfiles/default.run | 1 + usr/src/test/bhyve-tests/tests/inst_emul/Makefile | 1 + usr/src/test/bhyve-tests/tests/inst_emul/imul.c | 115 +++++++++++++++++ .../bhyve-tests/tests/inst_emul/payload_imul.s | 59 +++++++++ usr/src/uts/intel/io/vmm/vmm_instruction_emul.c | 139 +++++++++++++++++++++ 6 files changed, 316 insertions(+) create mode 100644 usr/src/test/bhyve-tests/tests/inst_emul/imul.c create mode 100644 usr/src/test/bhyve-tests/tests/inst_emul/payload_imul.s diff --git a/usr/src/pkg/manifests/system-bhyve-tests.p5m b/usr/src/pkg/manifests/system-bhyve-tests.p5m index 4dbd417557..9c98c34969 100644 --- a/usr/src/pkg/manifests/system-bhyve-tests.p5m +++ b/usr/src/pkg/manifests/system-bhyve-tests.p5m @@ -33,6 +33,7 @@ dir path=opt/bhyve-tests/tests dir path=opt/bhyve-tests/tests/inst_emul file path=opt/bhyve-tests/tests/inst_emul/cpuid mode=0555 file path=opt/bhyve-tests/tests/inst_emul/exit_paging mode=0555 +file path=opt/bhyve-tests/tests/inst_emul/imul mode=0555 file path=opt/bhyve-tests/tests/inst_emul/rdmsr mode=0555 file path=opt/bhyve-tests/tests/inst_emul/triple_fault mode=0555 file path=opt/bhyve-tests/tests/inst_emul/wrmsr mode=0555 diff --git a/usr/src/test/bhyve-tests/runfiles/default.run b/usr/src/test/bhyve-tests/runfiles/default.run index f68ac6c719..f424652655 100644 --- a/usr/src/test/bhyve-tests/runfiles/default.run +++ b/usr/src/test/bhyve-tests/runfiles/default.run @@ -53,6 +53,7 @@ tests = [ user = root tests = [ 'cpuid', + 'imul', 'rdmsr', 'wrmsr', 'triple_fault', diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/Makefile b/usr/src/test/bhyve-tests/tests/inst_emul/Makefile index 023a416ae9..37a8b62b4f 100644 --- a/usr/src/test/bhyve-tests/tests/inst_emul/Makefile +++ b/usr/src/test/bhyve-tests/tests/inst_emul/Makefile @@ -17,6 +17,7 @@ include $(SRC)/test/Makefile.com PROG = rdmsr \ wrmsr \ + imul \ cpuid # These should probably go in the `vmm` tests, but since they depend on diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/imul.c b/usr/src/test/bhyve-tests/tests/inst_emul/imul.c new file mode 100644 index 0000000000..d75cc67592 --- /dev/null +++ b/usr/src/test/bhyve-tests/tests/inst_emul/imul.c @@ -0,0 +1,115 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2022 Oxide Computer Company + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "in_guest.h" + +#define MMIO_TEST_BASE 0x10001000 +#define MMIO_TEST_END 0x10002000 + +static bool +handle_test_mmio(const struct vm_exit *vexit, struct vm_entry *ventry) +{ + /* expecting only reads */ + if (vexit->u.mmio.read == 0) { + return (false); + } + + /* expecting only in the [0x10001000 - 0x10002000) range */ + if (vexit->u.mmio.gpa < MMIO_TEST_BASE || + vexit->u.mmio.gpa >= MMIO_TEST_END) { + return (false); + } + + /* + * Emit a pattern of the lowest 16 bits of the address, ascending by the + * 2-byte stride for every 2 additional bytes, as the result. + * + * For example, an 8-byte read of 0x00001234 would result in: + * 0x123a123812361234 being returned + */ + const uint16_t addr = vexit->u.mmio.gpa; + uint64_t val = 0; + switch (vexit->u.mmio.bytes) { + case 8: + val |= (uint64_t)(addr + 6) << 48; + val |= (uint64_t)(addr + 4) << 32; + /* FALLTHROUGH */ + case 4: + val |= (uint32_t)(addr + 2) << 16; + /* FALLTHROUGH */ + case 2: + val |= addr; + break; + default: + /* expect only 2/4/8-byte reads */ + return (false); + } + + ventry_fulfill_mmio(vexit, ventry, val); + return (true); +} + +int +main(int argc, char *argv[]) +{ + const char *test_suite_name = basename(argv[0]); + struct vmctx *ctx = NULL; + int err; + + ctx = test_initialize(test_suite_name); + + err = test_setup_vcpu(ctx, 0, MEM_LOC_PAYLOAD, MEM_LOC_STACK); + if (err != 0) { + test_fail_errno(err, "Could not initialize vcpu0"); + } + + struct vm_entry ventry = { 0 }; + struct vm_exit vexit = { 0 }; + + do { + const enum vm_exit_kind kind = + test_run_vcpu(ctx, 0, &ventry, &vexit); + switch (kind) { + case VEK_REENTR: + break; + case VEK_UNHANDLED: + if (!handle_test_mmio(&vexit, &ventry)) { + test_fail_vmexit(&vexit); + } + break; + case VEK_TEST_PASS: + test_pass(); + break; + case VEK_TEST_FAIL: + default: + test_fail_vmexit(&vexit); + break; + } + } while (true); +} diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/payload_imul.s b/usr/src/test/bhyve-tests/tests/inst_emul/payload_imul.s new file mode 100644 index 0000000000..44da654ea6 --- /dev/null +++ b/usr/src/test/bhyve-tests/tests/inst_emul/payload_imul.s @@ -0,0 +1,59 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2022 Oxide Computer Company + */ + +#include +#include "payload_common.h" + +ENTRY(start) + /* check that the mmio values we expect are emitted */ + movw 0x10001234, %ax + cmpw $0x1234, %ax + jne fail + movl 0x10001232, %eax + cmpl $0x12341232, %eax + jne fail + movq 0x10001230, %rax + movq $0x1236123412321230, %rdx + cmpq %rdx, %rax + jne fail + + /* attempt the imul at 2/4/8 byte widths */ + movl $0x2, %eax + imulw 0x10001234, %ax + cmpw $0x2468, %ax + jne fail + + movl $0x2, %eax + imull 0x10001232, %eax + cmpl $0x24682464, %eax + jne fail + + movl $0x10, %eax + imulq 0x10001230, %rax + movq $0x2361234123212300, %rcx + cmpq %rcx, %rax + jne fail + + movw $IOP_TEST_RESULT, %dx + movb $TEST_RESULT_PASS, %al + outb (%dx) + hlt + +fail: + movw $IOP_TEST_RESULT, %dx + movb $TEST_RESULT_FAIL, %al + outb (%dx) + hlt +SET_SIZE(start) diff --git a/usr/src/uts/intel/io/vmm/vmm_instruction_emul.c b/usr/src/uts/intel/io/vmm/vmm_instruction_emul.c index 14c78f411d..9fbb923cd9 100644 --- a/usr/src/uts/intel/io/vmm/vmm_instruction_emul.c +++ b/usr/src/uts/intel/io/vmm/vmm_instruction_emul.c @@ -182,6 +182,7 @@ enum { VIE_OP_TYPE_TEST, VIE_OP_TYPE_BEXTR, VIE_OP_TYPE_CLTS, + VIE_OP_TYPE_MUL, VIE_OP_TYPE_LAST }; @@ -220,6 +221,10 @@ static const struct vie_op two_byte_opcodes[256] = { .op_byte = 0xAE, .op_type = VIE_OP_TYPE_TWOB_GRP15, }, + [0xAF] = { + .op_byte = 0xAF, + .op_type = VIE_OP_TYPE_MUL, + }, [0xB6] = { .op_byte = 0xB6, .op_type = VIE_OP_TYPE_MOVZX, @@ -419,6 +424,25 @@ static enum vm_reg_name gpr_map[16] = { VM_REG_GUEST_R15 }; +static const char *gpr_name_map[][16] = { + [1] = { + "a[hl]", "c[hl]", "d[hl]", "b[hl]", "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", + }, + [2] = { + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w", + }, + [4] = { + "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", + }, + [8] = { + "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + }, +}; + static enum vm_reg_name cr_map[16] = { VM_REG_GUEST_CR0, VM_REG_LAST, @@ -477,6 +501,14 @@ vie_regnum_map(uint8_t regnum) return (gpr_map[regnum]); } +const char * +vie_regnum_name(uint8_t regnum, uint8_t size) +{ + VERIFY3U(regnum, <, 16); + VERIFY(size == 1 || size == 2 || size == 4 || size == 8); + return (gpr_name_map[size][regnum]); +} + static void vie_calc_bytereg(struct vie *vie, enum vm_reg_name *reg, int *lhbr) { @@ -678,6 +710,40 @@ getaddflags(int opsize, uint64_t x, uint64_t y) return (getaddflags64(x, y)); } +/* + * Macro creation of functions getimulflags{16,32,64} + */ +/* BEGIN CSTYLED */ +#define GETIMULFLAGS(sz) \ +static ulong_t \ +getimulflags##sz(uint##sz##_t x, uint##sz##_t y) \ +{ \ + ulong_t rflags; \ + \ + __asm __volatile("imul %2,%1; pushfq; popq %0" : \ + "=r" (rflags), "+r" (x) : "m" (y)); \ + return (rflags); \ +} struct __hack +/* END CSTYLED */ + +GETIMULFLAGS(16); +GETIMULFLAGS(32); +GETIMULFLAGS(64); + +static ulong_t +getimulflags(int opsize, uint64_t x, uint64_t y) +{ + KASSERT(opsize == 2 || opsize == 4 || opsize == 8, + ("getimulflags: invalid operand size %d", opsize)); + + if (opsize == 2) + return (getimulflags16(x, y)); + else if (opsize == 4) + return (getimulflags32(x, y)); + else + return (getimulflags64(x, y)); +} + /* * Return the status flags that would result from doing (x & y). */ @@ -1842,6 +1908,76 @@ vie_emulate_sub(struct vie *vie, struct vm *vm, int vcpuid, uint64_t gpa) return (error); } +static int +vie_emulate_mul(struct vie *vie, struct vm *vm, int vcpuid, uint64_t gpa) +{ + int error, size; + uint64_t rflags, rflags2, val1, val2; + __int128_t nval; + enum vm_reg_name reg; + ulong_t (*getflags)(int, uint64_t, uint64_t) = NULL; + + size = vie->opsize; + error = EINVAL; + + switch (vie->op.op_byte) { + case 0xAF: + /* + * Multiply the contents of a destination register by + * the contents of a register or memory operand and + * put the signed result in the destination register. + * + * AF/r IMUL r16, r/m16 + * AF/r IMUL r32, r/m32 + * REX.W + AF/r IMUL r64, r/m64 + */ + + getflags = getimulflags; + + /* get the first operand */ + reg = gpr_map[vie->reg]; + error = vm_get_register(vm, vcpuid, reg, &val1); + if (error != 0) + break; + + /* get the second operand */ + error = vie_mmio_read(vie, vm, vcpuid, gpa, &val2, size); + if (error != 0) + break; + + /* perform the operation and write the result */ + nval = (int64_t)val1 * (int64_t)val2; + + error = vie_update_register(vm, vcpuid, reg, nval, size); + + DTRACE_PROBE4(vie__imul, + const char *, vie_regnum_name(vie->reg, size), + uint64_t, val1, uint64_t, val2, __uint128_t, nval); + + break; + default: + break; + } + + if (error == 0) { + rflags2 = getflags(size, val1, val2); + error = vm_get_register(vm, vcpuid, VM_REG_GUEST_RFLAGS, + &rflags); + if (error) + return (error); + + rflags &= ~RFLAGS_STATUS_BITS; + rflags |= rflags2 & RFLAGS_STATUS_BITS; + error = vie_update_register(vm, vcpuid, VM_REG_GUEST_RFLAGS, + rflags, 8); + + DTRACE_PROBE2(vie__imul__rflags, + uint64_t, rflags, uint64_t, rflags2); + } + + return (error); +} + static int vie_emulate_stack_op(struct vie *vie, struct vm *vm, int vcpuid, uint64_t gpa) { @@ -2244,6 +2380,9 @@ vie_emulate_mmio(struct vie *vie, struct vm *vm, int vcpuid) case VIE_OP_TYPE_BEXTR: error = vie_emulate_bextr(vie, vm, vcpuid, gpa); break; + case VIE_OP_TYPE_MUL: + error = vie_emulate_mul(vie, vm, vcpuid, gpa); + break; default: error = EINVAL; break; -- cgit v1.2.3