Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_fbuf.c
Show All 36 Lines | |||||
#include <machine/vmm.h> | #include <machine/vmm.h> | ||||
#include <machine/vmm_snapshot.h> | #include <machine/vmm_snapshot.h> | ||||
#include <vmmapi.h> | #include <vmmapi.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <err.h> | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "bhyvegc.h" | #include "bhyvegc.h" | ||||
#include "bhyverun.h" | #include "bhyverun.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "console.h" | #include "console.h" | ||||
#include "inout.h" | #include "inout.h" | ||||
▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | pci_fbuf_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | ||||
DPRINTF(DEBUG_VERBOSE, | DPRINTF(DEBUG_VERBOSE, | ||||
("fbuf rd: offset 0x%lx, size: %d, value: 0x%lx", | ("fbuf rd: offset 0x%lx, size: %d, value: 0x%lx", | ||||
offset, size, value)); | offset, size, value)); | ||||
return (value); | return (value); | ||||
} | } | ||||
static void | |||||
pci_fbuf_baraddr(struct vmctx *ctx, struct pci_devinst *pi, int baridx, | |||||
int enabled, uint64_t address) | |||||
{ | |||||
struct pci_fbuf_softc *sc; | |||||
int prot; | |||||
if (baridx != 1) | |||||
return; | |||||
sc = pi->pi_arg; | |||||
if (!enabled && sc->fbaddr != 0) { | |||||
if (vm_munmap_memseg(ctx, sc->fbaddr, FB_SIZE) != 0) | |||||
warnx("pci_fbuf: munmap_memseg failed"); | |||||
sc->fbaddr = 0; | |||||
} else if (sc->fb_base != NULL && sc->fbaddr == 0) { | |||||
prot = PROT_READ | PROT_WRITE; | |||||
if (vm_mmap_memseg(ctx, address, VM_FRAMEBUFFER, 0, FB_SIZE, prot) != 0) | |||||
warnx("pci_fbuf: mmap_memseg failed"); | |||||
sc->fbaddr = address; | |||||
} | |||||
} | |||||
static int | static int | ||||
pci_fbuf_parse_opts(struct pci_fbuf_softc *sc, char *opts) | pci_fbuf_parse_opts(struct pci_fbuf_softc *sc, char *opts) | ||||
{ | { | ||||
char *uopts, *uoptsbak, *xopts, *config; | char *uopts, *uoptsbak, *xopts, *config; | ||||
char *tmpstr; | char *tmpstr; | ||||
int ret; | int ret; | ||||
ret = 0; | ret = 0; | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | pci_fbuf_render(struct bhyvegc *gc, void *arg) | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
static int | static int | ||||
pci_fbuf_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | pci_fbuf_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | ||||
{ | { | ||||
int error, prot; | int error; | ||||
struct pci_fbuf_softc *sc; | struct pci_fbuf_softc *sc; | ||||
if (fbuf_sc != NULL) { | if (fbuf_sc != NULL) { | ||||
EPRINTLN("Only one frame buffer device is allowed."); | EPRINTLN("Only one frame buffer device is allowed."); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
sc = calloc(1, sizeof(struct pci_fbuf_softc)); | sc = calloc(1, sizeof(struct pci_fbuf_softc)); | ||||
Show All 39 Lines | pci_fbuf_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | ||||
sc->fb_base = vm_create_devmem(ctx, VM_FRAMEBUFFER, "framebuffer", FB_SIZE); | sc->fb_base = vm_create_devmem(ctx, VM_FRAMEBUFFER, "framebuffer", FB_SIZE); | ||||
if (sc->fb_base == MAP_FAILED) { | if (sc->fb_base == MAP_FAILED) { | ||||
error = -1; | error = -1; | ||||
goto done; | goto done; | ||||
} | } | ||||
DPRINTF(DEBUG_INFO, ("fbuf frame buffer base: %p [sz %lu]", | DPRINTF(DEBUG_INFO, ("fbuf frame buffer base: %p [sz %lu]", | ||||
sc->fb_base, FB_SIZE)); | sc->fb_base, FB_SIZE)); | ||||
/* | |||||
* Map the framebuffer into the guest address space. | |||||
* XXX This may fail if the BAR is different than a prior | |||||
* run. In this case flag the error. This will be fixed | |||||
* when a change_memseg api is available. | |||||
*/ | |||||
prot = PROT_READ | PROT_WRITE; | |||||
if (vm_mmap_memseg(ctx, sc->fbaddr, VM_FRAMEBUFFER, 0, FB_SIZE, prot) != 0) { | |||||
EPRINTLN("pci_fbuf: mapseg failed - try deleting VM and restarting"); | |||||
error = -1; | |||||
goto done; | |||||
} | |||||
console_init(sc->memregs.width, sc->memregs.height, sc->fb_base); | console_init(sc->memregs.width, sc->memregs.height, sc->fb_base); | ||||
console_fb_register(pci_fbuf_render, sc); | console_fb_register(pci_fbuf_render, sc); | ||||
if (sc->vga_enabled) | if (sc->vga_enabled) | ||||
sc->vgasc = vga_init(!sc->vga_full); | sc->vgasc = vga_init(!sc->vga_full); | ||||
sc->gc_image = console_get_image(); | sc->gc_image = console_get_image(); | ||||
fbuf_sc = sc; | fbuf_sc = sc; | ||||
Show All 21 Lines | |||||
} | } | ||||
#endif | #endif | ||||
struct pci_devemu pci_fbuf = { | struct pci_devemu pci_fbuf = { | ||||
.pe_emu = "fbuf", | .pe_emu = "fbuf", | ||||
.pe_init = pci_fbuf_init, | .pe_init = pci_fbuf_init, | ||||
.pe_barwrite = pci_fbuf_write, | .pe_barwrite = pci_fbuf_write, | ||||
.pe_barread = pci_fbuf_read, | .pe_barread = pci_fbuf_read, | ||||
.pe_baraddr = pci_fbuf_baraddr, | |||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
.pe_snapshot = pci_fbuf_snapshot, | .pe_snapshot = pci_fbuf_snapshot, | ||||
#endif | #endif | ||||
}; | }; | ||||
PCI_EMUL_SET(pci_fbuf); | PCI_EMUL_SET(pci_fbuf); |