Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_gvt-d.c
| /*- | /*- | |||||||||
| * SPDX-License-Identifier: BSD-2-Clause | * SPDX-License-Identifier: BSD-2-Clause | |||||||||
| * | * | |||||||||
| * Copyright (c) 2020 Beckhoff Automation GmbH & Co. KG | * Copyright (c) 2020 Beckhoff Automation GmbH & Co. KG | |||||||||
| * Author: Corvin Köhne <c.koehne@beckhoff.com> | * Author: Corvin Köhne <c.koehne@beckhoff.com> | |||||||||
| */ | */ | |||||||||
| #include <sys/types.h> | #include <sys/types.h> | |||||||||
| #include <sys/mman.h> | ||||||||||
| #include <sys/sysctl.h> | #include <sys/sysctl.h> | |||||||||
| #include <dev/pci/pcireg.h> | #include <dev/pci/pcireg.h> | |||||||||
| #include <err.h> | #include <err.h> | |||||||||
| #include <errno.h> | #include <errno.h> | |||||||||
| #include <fcntl.h> | ||||||||||
| #include <string.h> | ||||||||||
| #include <unistd.h> | ||||||||||
| #include "e820.h" | #include "e820.h" | |||||||||
| #include "pci_gvt-d-opregion.h" | #include "pci_gvt-d-opregion.h" | |||||||||
| #include "pci_passthru.h" | #include "pci_passthru.h" | |||||||||
| #define KB (1024UL) | #define KB (1024UL) | |||||||||
| #define MB (1024 * KB) | #define MB (1024 * KB) | |||||||||
| #define GB (1024 * MB) | #define GB (1024 * MB) | |||||||||
| #ifndef _PATH_MEM | ||||||||||
| #define _PATH_MEM "/dev/mem" | ||||||||||
| #endif | ||||||||||
| #define PCI_VENDOR_INTEL 0x8086 | #define PCI_VENDOR_INTEL 0x8086 | |||||||||
| #define PCIR_BDSM 0x5C /* Base of Data Stolen Memory register */ | #define PCIR_BDSM 0x5C /* Base of Data Stolen Memory register */ | |||||||||
| #define PCIR_ASLS_CTL 0xFC /* Opregion start address register */ | ||||||||||
| #define PCIM_BDSM_GSM_ALIGNMENT \ | #define PCIM_BDSM_GSM_ALIGNMENT \ | |||||||||
| 0x00100000 /* Graphics Stolen Memory is 1 MB aligned */ | 0x00100000 /* Graphics Stolen Memory is 1 MB aligned */ | |||||||||
| #define GVT_D_MAP_GSM 0 | #define GVT_D_MAP_GSM 0 | |||||||||
| #define GVT_D_MAP_OPREGION 1 | ||||||||||
| static int | static int | |||||||||
| gvt_d_probe(struct pci_devinst *const pi) | gvt_d_probe(struct pci_devinst *const pi) | |||||||||
| { | { | |||||||||
| struct passthru_softc *sc; | struct passthru_softc *sc; | |||||||||
| uint16_t vendor; | uint16_t vendor; | |||||||||
| uint8_t class; | uint8_t class; | |||||||||
| ▲ Show 20 Lines • Show All 123 Lines • ▼ Show 20 Lines | gvt_d_setup_gsm(struct pci_devinst *const pi) | |||||||||
| pci_set_cfgdata32(pi, PCIR_BDSM, | pci_set_cfgdata32(pi, PCIR_BDSM, | |||||||||
| gsm->gpa | (bdsm & (PCIM_BDSM_GSM_ALIGNMENT - 1))); | gsm->gpa | (bdsm & (PCIM_BDSM_GSM_ALIGNMENT - 1))); | |||||||||
| return (set_pcir_handler(sc, PCIR_BDSM, 4, passthru_cfgread_emulate, | return (set_pcir_handler(sc, PCIR_BDSM, 4, passthru_cfgread_emulate, | |||||||||
| passthru_cfgwrite_emulate)); | passthru_cfgwrite_emulate)); | |||||||||
| } | } | |||||||||
| static int | static int | |||||||||
| gvt_d_setup_opregion(struct pci_devinst *const pi) | ||||||||||
| { | ||||||||||
| struct passthru_softc *sc; | ||||||||||
| struct passthru_mmio_mapping *opregion; | ||||||||||
| struct igd_opregion_header *header; | ||||||||||
| uint64_t asls; | ||||||||||
| int memfd; | ||||||||||
| sc = pi->pi_arg; | ||||||||||
| memfd = open(_PATH_MEM, O_RDONLY, 0); | ||||||||||
markj: It can't be O_RDONLY? | ||||||||||
| if (memfd < 0) { | ||||||||||
| warn("%s: Failed to open %s", __func__, _PATH_MEM); | ||||||||||
| return (-1); | ||||||||||
| } | ||||||||||
| opregion = passthru_get_mmio(sc, GVT_D_MAP_OPREGION); | ||||||||||
| if (opregion == NULL) { | ||||||||||
| warnx("%s: Unable to access opregion", __func__); | ||||||||||
| close(memfd); | ||||||||||
| return (-1); | ||||||||||
| } | ||||||||||
| asls = read_config(passthru_get_sel(sc), PCIR_ASLS_CTL, 4); | ||||||||||
| header = mmap(NULL, sizeof(*header), PROT_READ, MAP_SHARED, memfd, | ||||||||||
| asls); | ||||||||||
| if (header == MAP_FAILED) { | ||||||||||
| warn("%s: Unable to map OpRegion header", __func__); | ||||||||||
Done Inline Actions
markj: | ||||||||||
| close(memfd); | ||||||||||
| return (-1); | ||||||||||
Done Inline Actions
markj: | ||||||||||
| } | ||||||||||
| if (memcmp(header->sign, IGD_OPREGION_HEADER_SIGN, | ||||||||||
Done Inline ActionsThe header is guaranteed to be page-aligned? markj: The header is guaranteed to be page-aligned? | ||||||||||
Done Inline ActionsNo, it doesn't have to be page aligned. On my systems it has an offset of +0x18 to page boundary. Don't know why. corvink: No, it doesn't have to be page aligned. On my systems it has an offset of +0x18 to page… | ||||||||||
| sizeof(header->sign)) != 0) { | ||||||||||
| warnx("%s: Invalid OpRegion signature", __func__); | ||||||||||
| munmap(header, sizeof(*header)); | ||||||||||
| close(memfd); | ||||||||||
| return (-1); | ||||||||||
| } | ||||||||||
| opregion->hpa = asls; | ||||||||||
| opregion->len = header->size * KB; | ||||||||||
| munmap(header, sizeof(header)); | ||||||||||
Done Inline Actionsmemfd is leaked here, no? We should be able to close it after mapping the header, I believe. In general we don't want to leave a fd for /dev/mem lying around. markj: `memfd` is leaked here, no? We should be able to close it after mapping the header, I believe. | ||||||||||
| close(memfd); | ||||||||||
| return (0); | ||||||||||
| } | ||||||||||
| static int | ||||||||||
| gvt_d_init(struct pci_devinst *const pi, nvlist_t *const nvl __unused) | gvt_d_init(struct pci_devinst *const pi, nvlist_t *const nvl __unused) | |||||||||
| { | { | |||||||||
| int error; | int error; | |||||||||
| if ((error = gvt_d_setup_gsm(pi)) != 0) { | if ((error = gvt_d_setup_gsm(pi)) != 0) { | |||||||||
| warnx("%s: Unable to setup Graphics Stolen Memory", __func__); | warnx("%s: Unable to setup Graphics Stolen Memory", __func__); | |||||||||
| goto done; | ||||||||||
| } | ||||||||||
| if ((error = gvt_d_setup_opregion(pi)) != 0) { | ||||||||||
| warnx("%s: Unable to setup OpRegion", __func__); | ||||||||||
| goto done; | goto done; | |||||||||
| } | } | |||||||||
| done: | done: | |||||||||
| return (error); | return (error); | |||||||||
| } | } | |||||||||
| static void | static void | |||||||||
| Show All 10 Lines | ||||||||||
It can't be O_RDONLY?