From: Steven Jaconette Date: Thu, 27 Aug 2009 17:30:52 +0000 (-0500) Subject: From 294306ec5026ea691a4f1380598114688b061c99 Mon Sep 17 00:00:00 2001 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=b54cbe1dbbe15ed228de7472ea284df96ecce909;hp=1786dcbd1b5a05d2591556db17bff62465713ee1 From 294306ec5026ea691a4f1380598114688b061c99 Mon Sep 17 00:00:00 2001 Subject: [PATCH] Reorganized video card/virtual console --- diff --git a/Kconfig b/Kconfig index d682920..0b55661 100644 --- a/Kconfig +++ b/Kconfig @@ -55,6 +55,12 @@ config SYMBIOTIC_SWAP_TELEMETRY Enable the telemetry information for the symbiotic swap subsystem +config PASSTHROUGH_VIDEO + bool "Enable Passthrough Video" + default y + help + Configures Palacios to map a guest's framebuffer directly + to the hardware framebuffer config INSTRUMENT_VMM bool "Enable VMM instrumentation" diff --git a/palacios/include/devices/video.h b/palacios/include/devices/cga.h similarity index 50% copy from palacios/include/devices/video.h copy to palacios/include/devices/cga.h index cdb927d..b2c168c 100644 --- a/palacios/include/devices/video.h +++ b/palacios/include/devices/cga.h @@ -7,35 +7,26 @@ * and the University of New Mexico. You can find out more at * http://www.v3vee.org * - * Copyright (c) 2009, Robert Deloatch - * Copyright (c) 2009, Steven Jaconette - * Copyright (c) 2009, The V3VEE Project + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project * All rights reserved. * - * Author: Robdert Deloatch - * Steven Jaconette + * Author: Jack Lange * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "V3VEE_LICENSE". */ -#ifndef __DEVICES_VIDEO_H__ -#define __DEVICES_VIDEO_H__ +#ifndef __DEVICES_CGA_H__ +#define __DEVICES_CGA_H__ #ifdef __V3VEE__ +#include -//#include -#include +int v3_console_register_cga(struct vm_device * cga_dev, struct v3_console_ops * ops, void * private_data); -//struct vm_device * v3_create_video(); - -struct video_cfg { - char pci[32]; -}; - - -#endif // ! __V3VEE__ +#endif #endif diff --git a/palacios/include/devices/console.h b/palacios/include/devices/console.h new file mode 100644 index 0000000..70eeff7 --- /dev/null +++ b/palacios/include/devices/console.h @@ -0,0 +1,41 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __DEVICES_CONSOLE_H__ +#define __DEVICES_CONSOLE_H__ + +#ifdef __V3VEE__ + + +struct v3_console_ops { + + // filled in by the backend device + int (*update_screen)(uint_t x, uint_t y, uint_t length, void * private_data); + int (*update_cursor)(uint_t x, uint_t y, void * private_data); + int (*scroll)(uint_t rows, void * private_data); +}; + + + +int v3_cons_get_fb(struct vm_device * frontend_dev, uint8_t * dst, uint_t offset, uint_t length); + +#endif // ! __V3VEE__ + + +#endif diff --git a/palacios/include/devices/video.h b/palacios/include/devices/telnet_cons.h similarity index 50% rename from palacios/include/devices/video.h rename to palacios/include/devices/telnet_cons.h index cdb927d..afca897 100644 --- a/palacios/include/devices/video.h +++ b/palacios/include/devices/telnet_cons.h @@ -7,35 +7,30 @@ * and the University of New Mexico. You can find out more at * http://www.v3vee.org * - * Copyright (c) 2009, Robert Deloatch - * Copyright (c) 2009, Steven Jaconette - * Copyright (c) 2009, The V3VEE Project + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project * All rights reserved. * - * Author: Robdert Deloatch - * Steven Jaconette + * Author: Jack Lange * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "V3VEE_LICENSE". */ -#ifndef __DEVICES_VIDEO_H__ -#define __DEVICES_VIDEO_H__ +#ifndef __DEVICES_TELNET_CONS_H__ +#define __DEVICES_TELNET_CONS_H__ #ifdef __V3VEE__ -//#include -#include - -//struct vm_device * v3_create_video(); - -struct video_cfg { - char pci[32]; +struct telnet_cons_cfg { + char frontend[32]; + uint16_t port; }; -#endif // ! __V3VEE__ + +#endif #endif diff --git a/palacios/src/devices/Kconfig b/palacios/src/devices/Kconfig index e62b00c..6f63f23 100644 --- a/palacios/src/devices/Kconfig +++ b/palacios/src/devices/Kconfig @@ -259,11 +259,20 @@ config SYM_SWAP help Includes the symbiotic ram based swap disk -config VIDEO - bool "VIDEO" +config CGA + bool "CGA" default n - depends on PCI && EXPERIMENTAL + depends on !PASSTHROUGH_VIDEO help - Includes the Virtual Video Card Device + Includes the Virtual CGA video support + + +config TELNET_CONSOLE + bool "Telnet Virtual Console" + default n + depends on CGA && !PASSTHROUGH_VIDEO + help + Includes the virtual telnet console endmenu + diff --git a/palacios/src/devices/Makefile b/palacios/src/devices/Makefile index 1d6b0df..f720996 100644 --- a/palacios/src/devices/Makefile +++ b/palacios/src/devices/Makefile @@ -23,4 +23,5 @@ obj-$(CONFIG_NE2K) += ne2k.o obj-$(CONFIG_NET_CD) += net_cd.o obj-$(CONFIG_NET_HD) += net_hd.o -obj-$(CONFIG_VIDEO) += video.o +obj-$(CONFIG_CGA) += cga.o +obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o diff --git a/palacios/src/devices/cga.c b/palacios/src/devices/cga.c new file mode 100644 index 0000000..aabe810 --- /dev/null +++ b/palacios/src/devices/cga.c @@ -0,0 +1,410 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2009, Robert Deloatch + * Copyright (c) 2009, Steven Jaconette + * Copyright (c) 2009, The V3VEE Project + * All rights reserved. + * + * Author: Robdert Deloatch + * Steven Jaconette + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include + +#include + + + +/* +#ifndef DEBUG_CGA +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif +*/ + +#define START_ADDR 0xB8000 +#define END_ADDR 0xC0000 + +#define FRAMEBUF_SIZE (END_ADDR - START_ADDR) +#define SCREEN_SIZE 4000 + +#define BASE_CGA_PORT 0x3B0 + +#define NUM_COLS 80 +#define NUM_ROWS 25 +#define BYTES_PER_ROW (NUM_COLS * 2) +#define BYTES_PER_COL 2 + + +struct video_internal { + uint8_t * framebuf; + + // These store the values for unhandled ports, in case of a read op + uint8_t port_store[44]; + + + uint8_t crtc_index_reg; // io port 3D4 + uint8_t crtc_data_regs[25]; // io port 3D5 + + uint16_t screen_offset; // relative to the framebuffer + uint16_t cursor_offset; // relative to the framebuffer + + // updating the screen offset is not atomic, + // so we need a temp variable to hold the partial update + uint16_t tmp_screen_offset; + + + uint8_t passthrough; + + + struct v3_console_ops * ops; + void * private_data; + + + +}; + + + + +static void passthrough_in(uint16_t port, void * src, uint_t length) { + switch (length) { + case 1: + *(uint8_t *)src = v3_inb(port); + break; + case 2: + *(uint16_t *)src = v3_inw(port); + break; + case 4: + *(uint32_t *)src = v3_indw(port); + break; + default: + break; + } +} + + +static void passthrough_out(uint16_t port, void * src, uint_t length) { + switch (length) { + case 1: + v3_outb(port, *(uint8_t *)src); + break; + case 2: + v3_outw(port, *(uint16_t *)src); + break; + case 4: + v3_outdw(port, *(uint32_t *)src); + break; + default: + break; + } +} + +static int video_write_mem(addr_t guest_addr, void * dest, uint_t length, void * priv_data) { + struct vm_device * dev = (struct vm_device *)priv_data; + struct video_internal * state = (struct video_internal *)dev->private_data; + uint_t fb_offset = guest_addr - START_ADDR; + uint_t screen_byte_offset = state->screen_offset * BYTES_PER_COL; + + PrintDebug("Guest address: %p length = %d, fb_offset=%d, screen_offset=%d\n", + (void *)guest_addr, length, fb_offset, screen_byte_offset); + + if (state->passthrough) { + memcpy(state->framebuf + fb_offset, V3_VAddr((void *)guest_addr), length); + } + + if ((fb_offset >= screen_byte_offset) && (fb_offset < (screen_byte_offset + SCREEN_SIZE))) { + uint_t screen_pos = fb_offset - screen_byte_offset; + uint_t x = (screen_pos % BYTES_PER_ROW) / BYTES_PER_COL; + uint_t y = screen_pos / BYTES_PER_ROW; + PrintDebug("Sending Screen update\n"); + + if (state->ops) { + PrintDebug("\tcalling update_screen()\n"); + state->ops->update_screen(x, y, length, state->private_data); + } + } + + return length; +} + +static int video_read_port(uint16_t port, void * dest, uint_t length, struct vm_device * dev) { + struct video_internal * video_state = (struct video_internal *)dev->private_data; + + + PrintDebug("Video: Read port 0x%x\n", port); + + if (video_state->passthrough) { + passthrough_in(port, dest, length); + } + + return length; +} + + + +static int video_write_port(uint16_t port, void * src, uint_t length, struct vm_device * dev) { + struct video_internal * video_state = (struct video_internal *)dev->private_data; + + + PrintDebug("Video: write port 0x%x...\n", port); + + if (video_state->passthrough) { + passthrough_out(port, src, length); + } + + return length; +} + + + +static int crtc_data_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) { + struct video_internal * video_state = (struct video_internal *)dev->private_data; + uint8_t val = *(uint8_t *)src; + uint_t index = video_state->crtc_index_reg; + + if (length != 1) { + PrintError("Invalid write length for port 0x%x\n", port); + return -1; + } + + PrintDebug("Video: write on port 0x%x... (val=0x%x)\n", port, val); + + video_state->crtc_data_regs[index] = val; + + switch (index) { + case 0x0c: { // scroll high byte + uint16_t tmp_val = val; + video_state->tmp_screen_offset = ((tmp_val << 8) & 0xff00); + break; + } + case 0x0d: { // Scroll low byte + int diff = 0; + + video_state->tmp_screen_offset += val; + diff = (video_state->tmp_screen_offset - video_state->screen_offset) / NUM_COLS; + + // Update the true offset value + video_state->screen_offset = video_state->tmp_screen_offset; + video_state->tmp_screen_offset = 0; + + PrintDebug("Scroll lines = %d, new screen offset=%d\n", + diff, video_state->screen_offset * BYTES_PER_COL); + + if (video_state->ops) { + if (video_state->ops->scroll(diff, video_state->private_data) == -1) { + PrintError("Error sending scroll event\n"); + return -1; + } + } + break; + } + case 0x0E: { // Cursor adjustment High byte + uint16_t tmp_val = val; + video_state->cursor_offset = ((tmp_val << 8) & 0xff00); + + break; + } + case 0x0F: { // cursor adjustment low byte + uint_t x = 0; + uint_t y = 0; + + video_state->cursor_offset += val; + + x = video_state->cursor_offset % NUM_COLS; + y = (video_state->cursor_offset - video_state->screen_offset) / NUM_COLS; + + PrintDebug("New Cursor Location; X=%d Y=%d\n", x, y); + + if (video_state->ops) { + if (video_state->ops->update_cursor(x, y, video_state->private_data) == -1) { + PrintError("Error updating cursor\n"); + return -1; + } + } + + break; + } + default: + break; + } + + if (video_state->passthrough) { + passthrough_out(port, src, length); + } + + return length; +} + + +static int crtc_index_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) { + struct video_internal * video_state = (struct video_internal *)dev->private_data; + + if (length > 2) { + PrintError("Invalid write length for crtc index register port: %d (0x%x)\n", + port, port); + return -1; + } + + + video_state->crtc_index_reg = *(uint8_t *)src; + + // Only do the passthrough IO for the first byte + // the second byte will be done in the data register handler + if (video_state->passthrough) { + passthrough_out(port, src, 1); + } + + if (length == 2) { + if (crtc_data_write(port + 1, src + 1, length - 1, dev) != (length - 1)) { + PrintError("could not handle implicit crtc data write\n"); + return -1; + } + } + + return length; +} + + + +int v3_cons_get_fb(struct vm_device * frontend_dev, uint8_t * dst, uint_t offset, uint_t length) { + struct video_internal * state = (struct video_internal *)frontend_dev->private_data; + uint_t screen_byte_offset = state->screen_offset * BYTES_PER_COL; + + PrintDebug("Getting framebuffer for screen; framebuf=%p, screen_offset=%d, offset=%d, length=%d\n", + state->framebuf, screen_byte_offset, offset, length); + + memcpy(dst, state->framebuf + screen_byte_offset + offset, length); + + return 0; +} + + + +static int free_device(struct vm_device * dev) { + v3_unhook_mem(dev->vm, START_ADDR); + return 0; +} + + + +static struct v3_device_ops dev_ops = { + .free = free_device, + .reset = NULL, + .start = NULL, + .stop = NULL, +}; + +static int cga_init(struct guest_info * vm, void * cfg_data) { + struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal)); + addr_t frame_buf_pa = 0; + uint32_t enable_passthrough = (uint32_t)(addr_t)cfg_data; + + + PrintDebug("video: init_device\n"); + + struct vm_device * dev = v3_allocate_device("CGA_VIDEO", &dev_ops, video_state); + + if (v3_attach_device(vm, dev) == -1) { + PrintError("Could not attach device %s\n", "CGA_VIDEO"); + return -1; + } + + frame_buf_pa = (addr_t)V3_AllocPages(FRAMEBUF_SIZE / 4096); + + video_state->framebuf = V3_VAddr((void *)frame_buf_pa); + memset(video_state->framebuf, 0, FRAMEBUF_SIZE); + + PrintDebug("PA of array: %p\n", (void *)frame_buf_pa); + + video_state->passthrough = enable_passthrough; + + video_state->ops = NULL; + video_state->private_data = NULL; + + if (enable_passthrough) { + PrintDebug("Enabling CGA Passthrough\n"); + + if (v3_hook_write_mem(vm, START_ADDR, END_ADDR, START_ADDR, &video_write_mem, dev) == -1) { + PrintDebug("\n\nVideo Hook failed.\n\n"); + } + } else { + if (v3_hook_write_mem(vm, START_ADDR, END_ADDR, frame_buf_pa, &video_write_mem, dev) == -1) { + PrintDebug("\n\nVideo Hook failed.\n\n"); + } + } + + + v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d4, &video_read_port, &crtc_index_write); + v3_dev_hook_io(dev, 0x3d5, &video_read_port, &crtc_data_write); + v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3da, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port); + + + return 0; +} + +device_register("CGA_VIDEO", cga_init); + + +int v3_console_register_cga(struct vm_device * cga_dev, struct v3_console_ops * ops, void * private_data) { + struct video_internal * video_state = (struct video_internal *)cga_dev->private_data; + + video_state->ops = ops; + video_state->private_data = private_data; + + return 0; +} diff --git a/palacios/src/devices/cirrus_gfx_card.c b/palacios/src/devices/cirrus_gfx_card.c new file mode 100644 index 0000000..a768007 --- /dev/null +++ b/palacios/src/devices/cirrus_gfx_card.c @@ -0,0 +1,580 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2009, Robert Deloatch + * Copyright (c) 2009, Steven Jaconette + * Copyright (c) 2009, The V3VEE Project + * All rights reserved. + * + * Author: Robdert Deloatch + * Steven Jaconette + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "network_console.h" + + + +/* #ifndef DEBUG_CIRRUS_GFX_CARD +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif */ + + +#define START_ADDR 0xA0000 +#define END_ADDR 0xC0000 + +#define SIZE_OF_REGION (END_ADDR - START_ADDR) + +#define PASSTHROUGH 1 +#define PORT_OFFSET 0x3B0 + +struct video_internal { + addr_t video_memory_pa; + uint8_t * video_memory; + + struct vm_device * pci_bus; + struct pci_device * pci_dev; + + int client_fd; + + uint_t screen_bottom; + uint_t ports[44]; + uint8_t reg_3C4[256]; + uint8_t reg_3CE[256]; + uint16_t start_addr_offset; + uint16_t old_start_addr_offset; + uint16_t cursor_addr; + uint8_t reg_3D5[25]; + +}; + +void video_do_in(uint16_t port, void * src, uint_t length){ +#if PASSTHROUGH + uint_t i; + switch (length) { + case 1: + ((uint8_t *)src)[0] = v3_inb(port); + break; + case 2: + ((uint16_t *)src)[0] = v3_inw(port); + break; + case 4: + ((uint32_t *)src)[0] = v3_indw(port); + break; + default: + for (i = 0; i < length; i++) { + ((uint8_t *)src)[i] = v3_inb(port); + } + } +#endif +} + +void video_do_out(uint16_t port, void * src, uint_t length){ +#if PASSTHROUGH + uint_t i; + switch (length) { + case 1: + v3_outb(port,((uint8_t *)src)[0]); + break; + case 2: + v3_outw(port,((uint16_t *)src)[0]); + break; + case 4: + v3_outdw(port,((uint32_t *)src)[0]); + break; + default: + for (i = 0; i < length; i++) { + v3_outb(port, ((uint8_t *)src)[i]); + } + } +#endif +} + +static int video_write_mem(addr_t guest_addr, void * dest, uint_t length, void * priv_data) { + struct vm_device * dev = (struct vm_device *)priv_data; + struct video_internal * data = (struct video_internal *)dev->private_data; + addr_t write_offset = guest_addr - START_ADDR; + uint_t difference = 0x18000; + int i = 0; + + + PrintDebug("\n\nInside Video Write Memory.\n\n"); + PrintDebug("Guest address: %p length = %d\n", (void *)guest_addr, length); + + PrintDebug("Write offset: 0x%x\n", (uint_t)write_offset); + PrintDebug("Video_Memory: "); + + for (i = 0; i < length; i += 2) { + PrintDebug("%c", ((char *)(V3_VAddr((void *)guest_addr)))[i]); + } + +#if PASSTHROUGH + memcpy(data->video_memory + write_offset, V3_VAddr((void*)guest_addr), length); +#endif + + + + if (send_update(data->client_fd, data->video_memory + difference, write_offset-difference, data->start_addr_offset, length) == -1) { + PrintError("Error sending update to client\n"); + return -1; + } + + PrintDebug(" Done.\n"); + return length; +} + +static int video_read_port(uint16_t port, void * dest, uint_t length, struct vm_device * dev) { + //PrintDebug("Video: Read port 0x%x\n",port); + video_do_in(port, dest, length); + return length; +} + +static int video_read_port_generic(uint16_t port, void * dest, uint_t length, struct vm_device * dev) { + memset(dest, 0, length); + video_do_in(port, dest, length); + return length; +} + + +static int video_write_port(uint16_t port, void * src, uint_t length, struct vm_device * dev) { + /* + PrintDebug("Video: write port 0x%x...Wrote: ", port); + uint_t i; + for(i = 0; i < length; i++){ + PrintDebug("%x", ((uint8_t*)src)[i]); + } + PrintDebug("...Done\n"); */ + video_do_out(port, src, length); + return length; +} + +static int video_write_port_store(uint16_t port, void * src, uint_t length, struct vm_device * dev) { + /* + PrintDebug("Entering video_write_port_store...port 0x%x\n", port); + uint_t i; + for(i = 0; i < length; i++){ + PrintDebug("%x", ((uint8_t*)src)[i]); + } + PrintDebug("...Done\n"); + */ + struct video_internal * video_state = (struct video_internal *)dev->private_data; + + video_state->ports[port - PORT_OFFSET] = 0; + memcpy(video_state->ports + (port - PORT_OFFSET), src, length); + video_do_out(port, src, length); + + return length; +} + +static int video_write_port_3D5(uint16_t port, void * src, uint_t length, struct vm_device * dev) { + struct video_internal * video_state = (struct video_internal *)dev->private_data; + uint8_t new_start = 0; + uint_t index = 0; + + PrintDebug("Video: write port 0x%x...Wrote: ", port); + { + uint_t i = 0; + for (i = 0; i < length; i++){ + PrintDebug("%x", ((uint8_t*)src)[i]); + } + PrintDebug("...Done\n"); + } + + video_state->ports[port - PORT_OFFSET] = 0; + + memcpy(video_state->ports + (port - PORT_OFFSET), src, length); + + memcpy(&(video_state->reg_3D5[index]), src, length); + + index = video_state->ports[port - 1 - PORT_OFFSET]; + + // JRL: Add length check + new_start = *((uint8_t *)src); + + + switch (index) { + case 0x0c: + video_state->old_start_addr_offset = video_state->start_addr_offset; + + video_state->start_addr_offset = (new_start << 8); + + break; + case 0x0d: { + int diff = 0; + + video_state->start_addr_offset += new_start; + + diff = video_state->start_addr_offset - video_state->old_start_addr_offset; + diff /= 80; + + PrintDebug("Scroll lines = %d\n", diff); + + send_scroll(video_state->client_fd, diff, video_state->video_memory); + + break; + } + case 0x0E: + video_state->cursor_addr = new_start << 8; + + break; + case 0x0F: { + uint_t x = 0; + uint_t y = 0; + + video_state->cursor_addr += new_start; + + x = ((video_state->cursor_addr) % 80) + 1; + y = (((video_state->cursor_addr) / 80) - ((video_state->start_addr_offset / 80))) + 1; + + PrintDebug("New Cursor Location; X=%d Y=%d\n", x, y); + + send_cursor_update(video_state->client_fd, x, y); + break; + } + default: + break; + } + + video_do_out(port, src, length); + + return length; +} + + +static int video_write_port_3C5(uint16_t port, void * src, uint_t length, struct vm_device * dev) { + struct video_internal * video_state = (struct video_internal *)dev->private_data; + uint_t index = 0; + + + PrintDebug("Entering write_port_3C5....port 0x%x\n", port); + { + uint_t i = 0; + for(i = 0; i < length; i++){ + PrintDebug("%x", ((uint8_t*)src)[i]); + } + PrintDebug("...Done\n"); + } + + video_state->ports[port - PORT_OFFSET] = 0; + memcpy(video_state->ports + (port - PORT_OFFSET), src, length); + + index = video_state->ports[port - 1 - PORT_OFFSET]; + + memcpy(&(video_state->reg_3C4[index]), src, length); + video_do_out(port, src, length); + + return length; +} + +static int video_write_port_3CF(uint16_t port, void * src, uint_t length, struct vm_device * dev) { + struct video_internal * video_state = (struct video_internal *)dev->private_data; + + PrintDebug("Entering write_port_3CF....port 0x%x\n", port); + + { + uint_t i = 0; + for(i = 0; i < length; i++){ + PrintDebug("%x", ((uint8_t*)src)[i]); + } + PrintDebug("...Done\n"); + } + + video_state->ports[port - PORT_OFFSET] = 0; + memcpy(video_state->ports + (port - PORT_OFFSET), src, length); + + uint_t index = video_state->ports[port - 1 - PORT_OFFSET]; + memcpy(&(video_state->reg_3CE[index]), src, length); + video_do_out(port, src, length); + return length; +} + +static int video_write_port_3D4(uint16_t port, void * src, uint_t length, struct vm_device * dev){ + struct video_internal * video_state = (struct video_internal *) dev -> private_data; + +#if 1 + if (length == 1) { + + video_state->ports[port - PORT_OFFSET] = 0; + memcpy(video_state->ports + (port - PORT_OFFSET), src, length); + + } else if (length == 2) { + uint16_t new_start = *((uint16_t *)src); + uint16_t cursor_start = *((uint16_t *)src);; + + //Updating the cursor + if ((cursor_start & 0x00FF) == 0x000E) { + + cursor_start = (cursor_start & 0xFF00); + video_state->cursor_addr = cursor_start; + + } else if ((cursor_start & 0x00FF) == 0x000F) { + uint_t x = 0; + uint_t y = 0; + + video_state->cursor_addr += ((cursor_start >> 8) & 0x00FF); + + x = ((video_state->cursor_addr) % 80) + 1; + y = (((video_state->cursor_addr) / 80) - ((video_state->start_addr_offset / 80))) + 1; + + PrintDebug("New Cursor Location; X=%d Y=%d\n", x, y); + + send_cursor_update(video_state->client_fd, x, y); + } + + //Checking to see if scrolling is needed + if ((new_start & 0x00FF) == 0x000C) { + + video_state->old_start_addr_offset = video_state->start_addr_offset; + new_start = (new_start & 0xFF00); + video_state->start_addr_offset = new_start; + + } else if ((new_start & 0x00FF) == 0x000D) { + int diff = 0; + + video_state->start_addr_offset += ((new_start >> 8) & 0x00FF); + + diff = video_state->start_addr_offset - video_state->old_start_addr_offset; + diff /= 80; + + PrintDebug("Scroll lines = %d\n", diff); + + send_scroll(video_state->client_fd, diff, video_state->video_memory+0x18000); + } + } else { + // JRL ?? + return -1; + } +#endif + video_do_out(port, src, length); + return length; +} + +static int video_write_mem_region(addr_t guest_addr, void * src, uint_t length, void * priv_data) {; + PrintDebug("Video write mem region guest_addr: 0x%p, src: 0x%p, length: %d, Value?= %x\n", (void *)guest_addr, src, length, *((uint32_t *)V3_VAddr((void *)guest_addr))); + return length; +} + +static int video_read_mem_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){ + PrintDebug("Video: Within video_read_mem_region\n"); + return length; +} + +static int video_write_io_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){ + PrintDebug("Video: Within video_write_io_region\n"); + return length; +} + +static int video_read_io_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){ + PrintDebug("Video: Within video_read_io_region\n"); + return length; +} + +static int cirrus_gfx_card_free(struct vm_device * dev) { + v3_unhook_mem(dev->vm, START_ADDR); + return 0; +} + +static int cirrus_gfx_card_reset_device(struct vm_device * dev) { + PrintDebug("Video: reset device\n"); + return 0; +} + +static int cirrus_gfx_card_start_device(struct vm_device * dev) { + PrintDebug("Video: start device\n"); + return 0; +} + +static int cirrus_gfx_card_stop_device(struct vm_device * dev) { + PrintDebug("Video: stop device\n"); + return 0; +} + +static struct v3_device_ops dev_ops = { + .free = cirrus_gfx_card_free, + .reset = cirrus_gfx_card_reset_device, + .start = cirrus_gfx_card_start_device, + .stop = cirrus_gfx_card_stop_device, +}; + +static int cirrus_gfx_card_init(struct guest_info * vm, void * cfg_data){ + struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal)); + struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data); + struct vm_device * dev = v3_allocate_device("TEXT_GFX_CARD", &dev_ops, video_state); + + if (v3_attach_device(vm, dev) == -1) { + PrintError("Could not attach device %s\n", "TEXT_GFX_CARD"); + return -1; + } + + PrintDebug("video: init_device\n"); + PrintDebug("Num Pages=%d\n", SIZE_OF_REGION / 4096); + + video_state->video_memory_pa = (addr_t)V3_AllocPages(SIZE_OF_REGION / 4096); + video_state->video_memory = V3_VAddr((void *)video_state->video_memory_pa); + + memset(video_state->video_memory, 0, SIZE_OF_REGION); + + + v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port_store); + v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port_store); + v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port_store); + v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port_3C5); + v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port_store); + v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port_store); + v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port_store); + v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port_store); + v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port_3CF); + v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d4, &video_read_port, &video_write_port_3D4); + v3_dev_hook_io(dev, 0x3d5, &video_read_port, &video_write_port_3D5); + v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3da, &video_read_port_generic, &video_write_port); + v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port); + v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port); + + + PrintDebug("PA of array: %p\n", (void *)video_state->video_memory_pa); + + +#if PASSTHROUGH + if (v3_hook_write_mem(vm, START_ADDR, END_ADDR, START_ADDR, &video_write_mem, dev) == -1){ + PrintDebug("\n\nVideo Hook failed.\n\n"); + } +#else + if (v3_hook_write_mem(vm, START_ADDR, END_ADDR, video_memory_pa, &video_write_mem, dev) == -1){ + PrintDebug("\n\nVideo Hook failed.\n\n"); + } +#endif + + PrintDebug("Video: Getting client connection\n"); + + video_state->client_fd = get_client_connection(vm); + + PrintDebug("Video: Client connection established\n"); + + video_state->screen_bottom = 25; + + video_state->pci_bus = pci_bus; + + if (video_state->pci_bus == NULL) { + PrintError("Could not find PCI device\n"); + return -1; + } else { + struct v3_pci_bar bars[6]; + struct pci_device * pci_dev = NULL; + + int i; + for (i = 0; i < 6; i++) { + bars[i].type = PCI_BAR_NONE; + } + + bars[0].type = PCI_BAR_MEM32; + bars[0].num_pages = 8192; + bars[0].default_base_addr = 0xf0000000; + + bars[0].mem_read = video_read_mem_region; + bars[0].mem_write = video_write_mem_region; + + bars[1].type = PCI_BAR_MEM32; + bars[1].num_pages = 1; + bars[1].default_base_addr = 0xf2000000; + + bars[1].mem_read = video_read_io_region; + bars[1].mem_write = video_write_io_region; + //-1 Means autoassign + // Not sure if STD + pci_dev = v3_pci_register_device(video_state->pci_bus, PCI_STD_DEVICE, 0, + //or0 1st null could be pci_config_update + -1, 0, "CIRRUS_GFX_CARD", bars, NULL, NULL, + NULL, dev); + + if (pci_dev == NULL) { + PrintError("Failed to register VIDEO %d with PCI\n", i); + return -1; + } else{ + PrintDebug("Registering PCI_VIDEO succeeded\n"); + } + //Need to set some pci_dev->config_header.vendor_id type variables + + pci_dev->config_header.vendor_id = 0x1013; + pci_dev->config_header.device_id = 0x00B8; + pci_dev->config_header.revision = 0x00; + + //If we treat video as a VGA device than below is correct + //If treated as a VGA compatible controller, which has mapping + //0xA0000-0xB0000 and I/O addresses 0x3B0-0x3BB than change + //#define from VGA to 0 + + //pci_dev->config_header.class = 0x00; + //pci_dev->config_header.subclass = 0x01; + + pci_dev->config_header.class = 0x03; + pci_dev->config_header.subclass = 0x00; + pci_dev->config_header.prog_if = 0x00; + + + //We have a subsystem ID, but optional to provide: 1AF4:1100 + pci_dev->config_header.subsystem_vendor_id = 0x1AF4; + pci_dev->config_header.subsystem_id = 0x1100; + //pci_dev->config_header.header_type = 0x00; + pci_dev->config_header.command = 0x03; + video_state->pci_dev = pci_dev; + } + + PrintDebug("Video: init complete\n"); + return 0; +} + +device_register("CIRRUS_GFX_CARD", cirrus_gfx_card_init) diff --git a/palacios/src/devices/telnet_cons.c b/palacios/src/devices/telnet_cons.c new file mode 100644 index 0000000..4abe5a0 --- /dev/null +++ b/palacios/src/devices/telnet_cons.c @@ -0,0 +1,552 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2009, Robert Deloatch + * Copyright (c) 2009, Steven Jaconette + * Copyright (c) 2009, The V3VEE Project + * All rights reserved. + * + * Author: Robdert Deloatch + * Steven Jaconette + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +/* Interface between virtual video card and client apps */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define NUM_ROWS 25 +#define NUM_COLS 80 +#define BYTES_PER_ROW (NUM_COLS * 2) +#define BYTES_PER_COL 2 + + +#define SCREEN_SIZE 4000 + +#define NO_KEY { 0, 0 } +#define ESC_CHAR ((uint8_t)0x1b) +#define CR_CHAR ((uint8_t)0x0d) + +#define ASCII_CTRL_CODE 0x1d + + +struct cons_state { + int server_fd; + int client_fd; + + uint16_t port; + + int connected; + + v3_lock_t cons_lock; + + struct vm_device * frontend_dev; +}; + +struct key_code { + uint8_t scan_code; + uint8_t capital; +}; + + +static const struct key_code ascii_to_key_code[] = { // ASCII Value Serves as Index + NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x00 - 0x03 + NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x04 - 0x07 + { 0x0E, 0 }, { 0x0F, 0 }, { 0x1C, 0 }, NO_KEY, // 0x08 - 0x0B + NO_KEY, { 0x1C, 0 }, NO_KEY, NO_KEY, // 0x0C - 0x0F + NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x10 - 0x13 + NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x14 - 0x17 + NO_KEY, NO_KEY, NO_KEY, { 0x01, 0 }, // 0x18 - 0x1B + NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x1C - 0x1F + { 0x39, 0 }, { 0x02, 1 }, { 0x28, 1 }, { 0x04, 1 }, // 0x20 - 0x23 + { 0x05, 1 }, { 0x06, 1 }, { 0x08, 1 }, { 0x28, 0 }, // 0x24 - 0x27 + { 0x0A, 1 }, { 0x0B, 1 }, { 0x09, 1 }, { 0x0D, 1 }, // 0x28 - 0x2B + { 0x33, 0 }, { 0x0C, 0 }, { 0x34, 0 }, { 0x35, 0 }, // 0x2C - 0x2F + { 0x0B, 0 }, { 0x02, 0 }, { 0x03, 0 }, { 0x04, 0 }, // 0x30 - 0x33 + { 0x05, 0 }, { 0x06, 0 }, { 0x07, 0 }, { 0x08, 0 }, // 0x34 - 0x37 + { 0x09, 0 }, { 0x0A, 0 }, { 0x27, 1 }, { 0x27, 0 }, // 0x38 - 0x3B + { 0x33, 1 }, { 0x0D, 0 }, { 0x34, 1 }, { 0x35, 1 }, // 0x3C - 0x3F + { 0x03, 1 }, { 0x1E, 1 }, { 0x30, 1 }, { 0x2E, 1 }, // 0x40 - 0x43 + { 0x20, 1 }, { 0x12, 1 }, { 0x21, 1 }, { 0x22, 1 }, // 0x44 - 0x47 + { 0x23, 1 }, { 0x17, 1 }, { 0x24, 1 }, { 0x25, 1 }, // 0x48 - 0x4B + { 0x26, 1 }, { 0x32, 1 }, { 0x31, 1 }, { 0x18, 1 }, // 0x4C - 0x4F + { 0x19, 1 }, { 0x10, 1 }, { 0x13, 1 }, { 0x1F, 1 }, // 0x50 - 0x53 + { 0x14, 1 }, { 0x16, 1 }, { 0x2F, 1 }, { 0x11, 1 }, // 0x54 - 0x57 + { 0x2D, 1 }, { 0x15, 1 }, { 0x2C, 1 }, { 0x1A, 0 }, // 0x58 - 0x5B + { 0x2B, 0 }, { 0x1B, 0 }, { 0x07, 1 }, { 0x0C, 1 }, // 0x5C - 0x5F + { 0x29, 0 }, { 0x1E, 0 }, { 0x30, 0 }, { 0x2E, 0 }, // 0x60 - 0x63 + { 0x20, 0 }, { 0x12, 0 }, { 0x21, 0 }, { 0x22, 0 }, // 0x64 - 0x67 + { 0x23, 0 }, { 0x17, 0 }, { 0x24, 0 }, { 0x25, 0 }, // 0x68 - 0x6B + { 0x26, 0 }, { 0x32, 0 }, { 0x31, 0 }, { 0x18, 0 }, // 0x6C - 0x6F + { 0x19, 0 }, { 0x10, 0 }, { 0x13, 0 }, { 0x1F, 0 }, // 0x70 - 0x73 + { 0x14, 0 }, { 0x16, 0 }, { 0x2F, 0 }, { 0x11, 0 }, // 0x74 - 0x77 + { 0x2D, 0 }, { 0x15, 0 }, { 0x2C, 0 }, { 0x1A, 1 }, // 0x78 - 0x7B + { 0x2B, 1 }, { 0x1B, 1 }, { 0x29, 1 }, { 0x0E, 0 } // 0x7C - 0x7F +}; + + + +static int deliver_scan_code(struct vm_device * dev, struct key_code * key) { + struct v3_keyboard_event key_event; + struct v3_keyboard_event key_shift; + uint_t cap = key->capital; + + key_event.status = 0; + key_event.scan_code = (uint8_t)key->scan_code; + + PrintDebug("Scan code: 0x%x\n", key_event.scan_code); + + + if (cap) { + key_shift.status = 0; + key_shift.scan_code = (uint8_t)0x2A; + + if (v3_deliver_keyboard_event(dev->vm, &key_shift) == -1) { + PrintError("Video: Error delivering key event\n"); + return -1; + } + } + + // Press + if (v3_deliver_keyboard_event(dev->vm, &key_event) == -1) { + PrintError("Video: Error delivering key event\n"); + return -1; + } + + // Release + key_event.scan_code = key_event.scan_code | 0x80; + + if (v3_deliver_keyboard_event(dev->vm, &key_event) == -1) { + PrintError("Video: Error delivering key event\n"); + return -1; + } + + + if (cap) { + key_shift.scan_code = 0x2A | 0x80; + + if (v3_deliver_keyboard_event(dev->vm, &key_shift) == -1) { + PrintError("Video: Error delivering key event\n"); + return -1; + } + } + + PrintDebug("Finished with Key delivery\n"); + return 0; +} + + + + +static int recv_all(int socket, char * buf, int length) { + int bytes_read = 0; + + PrintDebug("Reading %d bytes\n", length - bytes_read); + while (bytes_read < length) { + int tmp_bytes = V3_Recv(socket, buf + bytes_read, length - bytes_read); + PrintDebug("Received %d bytes\n", tmp_bytes); + + if (tmp_bytes == 0) { + PrintError("Connection Closed unexpectedly\n"); + return 0; + } else if (tmp_bytes == -1) { + PrintError("Socket Error in for V3_RECV\n"); + return -1; + } + + bytes_read += tmp_bytes; + } + + return bytes_read; +} + + +static int send_all(const int sock, const char * buf, const int len){ + int bytes_left = len; + + while (bytes_left != 0) { + int written = 0; + + if ((written = V3_Send(sock, buf + (len - bytes_left), bytes_left)) == -1) { + return -1; + } + + bytes_left -= written; + } + return 0; +} + +// Translate attribute color into terminal escape sequence color +static const uint8_t fg_color_map[] = { + 30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97 +}; + +static const uint8_t bg_color_map[] = { + 40, 44, 42, 46, 41, 45, 43, 47, 100, 104, 102, 106, 101, 105, 103, 107 +}; + + +#define INT_TO_CHAR(index, buf, val) \ + do { \ + uint8_t base = '0'; \ + if ((val) >= 100) buf[(index)++] = base + ((val) / 100); \ + if ((val) >= 10) buf[(index)++] = base + ((val) / 10); \ + buf[(index)++] = base + ((val) % 10); \ + } while (0) + + +static int send_update(struct vm_device * dev, uint8_t x, uint8_t y, uint8_t attrib, uint8_t val) { + struct cons_state * state = (struct cons_state *)dev->private_data; + uint8_t fg_color = fg_color_map[(attrib & 0x0f) % 16]; + uint8_t bg_color = bg_color_map[(attrib & 0xf0) % 16]; + uint8_t buf[32]; + int ret = 0; + int i = 0; + + memset(buf, 0, 32); + + buf[i++] = ESC_CHAR; + buf[i++] = '['; + + INT_TO_CHAR(i, buf, y + 1); + + buf[i++] = ';'; + + INT_TO_CHAR(i, buf, x + 1); + + buf[i++] = 'H'; + buf[i++] = ESC_CHAR; + buf[i++] = '['; + buf[i++] = '0'; + buf[i++] = 'm'; + buf[i++] = ESC_CHAR; + buf[i++] = '['; + + INT_TO_CHAR(i, buf, fg_color); + + buf[i++] = ';'; + + INT_TO_CHAR(i, buf, bg_color); + + buf[i++] = 'm'; + + // Add value + + buf[i++] = ESC_CHAR; + buf[i++] = '['; + INT_TO_CHAR(i, buf, y + 1); + buf[i++] = ';'; + INT_TO_CHAR(i, buf, x + 1); + buf[i++] = 'H'; + buf[i++] = val; + + PrintDebug("printing value '%c'\n", val); + + if (state->connected) { + uint64_t start, end; + + rdtscll(start); + ret = send_all(state->client_fd, buf, 32); + rdtscll(end); + + PrintDebug("Sendall latency=%d cycles\n", (uint32_t)(end - start)); + } + + return ret; +} + + + +static int cursor_update(uint_t x, uint_t y, void * private_data) { + struct vm_device * dev = (struct vm_device *)private_data; + struct cons_state * state = (struct cons_state *)dev->private_data; + uint8_t buf[16]; + int ret = 0; + addr_t irq_state = 0; + int i = 0; + + memset(buf, 0, 16); + + buf[i++] = ESC_CHAR; + buf[i++] = '['; + INT_TO_CHAR(i, buf, y + 1); + buf[i++] = ';'; + INT_TO_CHAR(i, buf, x + 1); + buf[i++] = 'H'; + + + irq_state = v3_lock_irqsave(state->cons_lock); + + if (state->connected) { + ret = send_all(state->client_fd, buf, 16); + } + + v3_unlock_irqrestore(state->cons_lock, irq_state); + + return ret; +} + + +static int screen_update(uint_t x, uint_t y, uint_t length, void * private_data) { + struct vm_device * dev = (struct vm_device *)private_data; + struct cons_state * state = (struct cons_state *)dev->private_data; + uint_t offset = (x * BYTES_PER_COL) + (y * BYTES_PER_ROW); + uint8_t fb_buf[length]; + int i = 0; + uint_t cur_x = x; + uint_t cur_y = y; + addr_t irq_state = 0; + int ret = 0; + + memset(fb_buf, 0, length); + + + + irq_state = v3_lock_irqsave(state->cons_lock); + + v3_cons_get_fb(state->frontend_dev, fb_buf, offset, length); + + v3_unlock_irqrestore(state->cons_lock, irq_state); + + + for (i = 0; i < length; i += 2) { + uint_t col_index = i; + uint8_t col[2]; + + col[0] = fb_buf[col_index]; // Character + col[1] = fb_buf[col_index + 1]; // Attribute + + irq_state = v3_lock_irqsave(state->cons_lock); + + if (send_update(dev, cur_x, cur_y, col[1], col[0]) == -1) { + PrintError("Could not send attribute to telnet session\n"); + ret = -1; + break; + } + + v3_unlock_irqrestore(state->cons_lock, irq_state); + + + // CAUTION: the order of these statements is critical + // cur_y depends on the previous value of cur_x + cur_y = cur_y + ((cur_x + 1) / NUM_COLS); + cur_x = (cur_x + 1) % NUM_COLS; + } + + + return ret; +} + +static int scroll(uint_t rows, void * private_data) { + struct vm_device * dev = (struct vm_device *)private_data; + struct cons_state * state = (struct cons_state *)dev->private_data; + addr_t irq_state = 0; + int ret = 0; + + if (rows > 0) { + int i = 0; + + irq_state = v3_lock_irqsave(state->cons_lock); + + for (i = rows; i > 0; i--) { + uint8_t message[2] = { ESC_CHAR, 'D' }; + + if (state->connected) { + if (send_all(state->client_fd, message, sizeof(message)) == -1) { + PrintError("Could not send scroll command\n"); + ret = -1; + break; + } + } + } + + v3_unlock_irqrestore(state->cons_lock, irq_state); + + } else if (rows < 0) { + ret = screen_update(0, 0, SCREEN_SIZE, private_data); + } + + return ret; +} + + + +static struct v3_console_ops cons_ops = { + .update_screen = screen_update, + .update_cursor = cursor_update, + .scroll = scroll, +}; + + +static struct v3_device_ops dev_ops = { + .free = NULL, + .reset = NULL, + .start = NULL, + .stop = NULL, +}; + + + +static int key_handler(struct vm_device * dev, uint8_t ascii) { + struct cons_state * state = (struct cons_state *)dev->private_data; + + PrintDebug("Character recieved: 0x%x\n", ascii); + + // printable + if (ascii < 0x80) { + const struct key_code * key = &(ascii_to_key_code[ascii]); + + if (deliver_scan_code(dev, (struct key_code *)key) == -1) { + PrintError("Could not deliver scan code to vm\n"); + return -1; + } + + } else if (ascii == ESC_CHAR) { // Escape Key + // This means that another 2 characters are pending + // receive it and deliver accordingly + char esc_seq[2] = {0, 0}; + + int recv = recv_all(state->client_fd, esc_seq, 2); + + if (recv == -1) { + PrintError("Video: Error getting key from network\n"); + return -1; + } else if (recv == 0) { + PrintDebug("Video: Client Disconnected\n"); + return -1; + } + + + if (esc_seq[0] != '[') { + PrintDebug("Ignoring non handled escape sequence (codes = %d %d)\n", + esc_seq[0], esc_seq[1]); + return 0; + } + + + if (esc_seq[1] == 'A') { // UP ARROW + struct key_code up = { 0x48, 0 }; + deliver_scan_code(dev, &up); + } else if (esc_seq[1] == 'B') { // DOWN ARROW + struct key_code down = { 0x50, 0 }; + deliver_scan_code(dev, &down); + } else if (esc_seq[1] == 'C') { // RIGHT ARROW + struct key_code right = { 0x4D, 0 }; + deliver_scan_code(dev, &right); + } else if (esc_seq[1] == 'D') { // LEFT ARROW + struct key_code left = { 0x4B, 0 }; + deliver_scan_code(dev, &left); + } + } else { + PrintError("Invalid character received from network (%c) (code=%d)\n", + ascii, ascii); + // return 0; + } + + return 0; +} + +static int cons_server(void * arg) { + struct vm_device * dev = (struct vm_device *)arg; + struct cons_state * state = (struct cons_state *)dev->private_data; + + state->server_fd = V3_Create_TCP_Socket(); + + + PrintDebug("Video: Socket File Descriptor: %d\n", state->server_fd); + + if (V3_Bind_Socket(state->server_fd, state->port) == -1) { + PrintError("Video: Failed to bind to socket %d\n", state->port); + } + + if (V3_Listen_Socket(state->server_fd, 8) == -1) { + PrintError("Video: Failed to listen with socket %d\n", state->server_fd); + } + + while (1) { + uint32_t client_ip; + uint32_t client_port; + uint8_t ascii_code = 0; + int recv = 0; + + if ((state->client_fd = V3_Accept_Socket(state->server_fd, &client_ip, &client_port)) == -1) { + PrintError("Video: Failed to accept connection on port %d\n", client_port); + } + PrintDebug("Accepted Telnet Console connection\n"); + state->connected = 1; + + screen_update(0, 0, SCREEN_SIZE, dev); + + while (1) { + recv = recv_all(state->client_fd, &ascii_code, sizeof(ascii_code)); + + PrintDebug("Telnet console Received %d bytes\n", recv); + + if (recv == -1) { + PrintError("Video: Error getting key from network\n"); + break; + } else if (recv == 0) { + PrintDebug("Video: Client Disconnected\n"); + break; + } + + if (key_handler(dev, ascii_code) == -1) { + PrintError("Error in key handler\n"); + break; + } + } + + state->connected = 0; + V3_Close_Socket(state->client_fd); + } +} + + +static int cons_init(struct guest_info * vm, void * cfg_data) { + struct telnet_cons_cfg * cfg = (struct telnet_cons_cfg *)cfg_data; + struct cons_state * state = (struct cons_state *)V3_Malloc(sizeof(struct cons_state)); + struct vm_device * frontend = v3_find_dev(vm, cfg->frontend); + + + state->server_fd = 0; + state->client_fd = 0; + state->frontend_dev = frontend; + state->port = cfg->port; + v3_lock_init(&(state->cons_lock)); + + + struct vm_device * dev = v3_allocate_device("TELNET_CONS", &dev_ops, state); + + if (v3_attach_device(vm, dev) == -1) { + PrintError("Could not attach device %s\n", "TELNET_CONS"); + return -1; + } + + + v3_console_register_cga(frontend, &cons_ops, dev); + + V3_CREATE_THREAD(cons_server, dev, "Telnet Console Network Server"); + + return 0; +} + + + +device_register("TELNET_CONSOLE", cons_init) diff --git a/palacios/src/devices/video.c b/palacios/src/devices/video.c deleted file mode 100644 index 2c5ff2f..0000000 --- a/palacios/src/devices/video.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * This file is part of the Palacios Virtual Machine Monitor developed - * by the V3VEE Project with funding from the United States National - * Science Foundation and the Department of Energy. - * - * The V3VEE Project is a joint project between Northwestern University - * and the University of New Mexico. You can find out more at - * http://www.v3vee.org - * - * Copyright (c) 2009, Robert Deloatch - * Copyright (c) 2009, Steven Jaconette - * Copyright (c) 2009, The V3VEE Project - * All rights reserved. - * - * Author: Robdert Deloatch - * Steven Jaconette - * - * This is free software. You are permitted to use, - * redistribute, and modify it as specified in the file "V3VEE_LICENSE". - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -/* #ifndef DEBUG_VIDEO */ -/* #undef PrintDebug */ -/* #define PrintDebug(fmt, args...) */ -/* #endif */ - - -#define START_ADDR 0xA0000 //0xB0000 //Attempting to hook entire region -#define END_ADDR 0xC0000 //0xC0000//(START_ADDR + ROWS * COLS * DEPTH) - -#define SIZE_OF_REGION (END_ADDR-START_ADDR) - -#define PCI_ENABLED 1 - -#define SEND_UPDATE_RAW 0 -#define SEND_UPDATE_ALL_VT100 0 -#define SEND_UPDATE_INCREMENTAL_VT100 1 -#define SCROLLING_ENABLED 1 -#define PASSTHROUGH 1 -#define PORT 19997 - -#define NO_CODE 0 -#define PORT_OFFSET 0x3B0 - -#define ESC_CHAR ((unsigned char)0x1b) - -struct key_code { - char scan_code; - uint_t capital; -}; - -#define NO_KEY { NO_CODE, 0 } - -static const struct key_code ascii_to_key_code[] = { // ASCII Value Serves as Index - NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x00 - 0x03 - NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x04 - 0x07 - { 0x0E, 0 }, { 0x0F, 0 }, NO_KEY, NO_KEY, // 0x08 - 0x0B - NO_KEY, { 0x1C, 0 }, NO_KEY, NO_KEY, // 0x0C - 0x0F - NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x10 - 0x13 - NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x14 - 0x17 - NO_KEY, NO_KEY, NO_KEY, { 0x01, 0 }, // 0x18 - 0x1B - NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x1C - 0x1F - { 0x39, 0 }, { 0x02, 1 }, { 0x28, 1 }, { 0x04, 1 }, // 0x20 - 0x23 - { 0x05, 1 }, { 0x06, 1 }, { 0x08, 1 }, { 0x28, 0 }, // 0x24 - 0x27 - { 0x0A, 1 }, { 0x0B, 1 }, { 0x09, 1 }, { 0x0D, 1 }, // 0x28 - 0x2B - { 0x33, 0 }, { 0x0C, 0 }, { 0x34, 0 }, { 0x35, 0 }, // 0x2C - 0x2F - { 0x0B, 0 }, { 0x02, 0 }, { 0x03, 0 }, { 0x04, 0 }, // 0x30 - 0x33 - { 0x05, 0 }, { 0x06, 0 }, { 0x07, 0 }, { 0x08, 0 }, // 0x34 - 0x37 - { 0x09, 0 }, { 0x0A, 0 }, { 0x27, 1 }, { 0x27, 0 }, // 0x38 - 0x3B - { 0x33, 1 }, { 0x0D, 0 }, { 0x34, 1 }, { 0x35, 1 }, // 0x3C - 0x3F - { 0x03, 1 }, { 0x1E, 1 }, { 0x30, 1 }, { 0x2E, 1 }, // 0x40 - 0x43 - { 0x20, 1 }, { 0x12, 1 }, { 0x21, 1 }, { 0x22, 1 }, // 0x44 - 0x47 - { 0x23, 1 }, { 0x17, 1 }, { 0x24, 1 }, { 0x25, 1 }, // 0x48 - 0x4B - { 0x26, 1 }, { 0x32, 1 }, { 0x31, 1 }, { 0x18, 1 }, // 0x4C - 0x4F - { 0x19, 1 }, { 0x10, 1 }, { 0x13, 1 }, { 0x1F, 1 }, // 0x50 - 0x53 - { 0x14, 1 }, { 0x16, 1 }, { 0x2F, 1 }, { 0x11, 1 }, // 0x54 - 0x57 - { 0x2D, 1 }, { 0x15, 1 }, { 0x2C, 1 }, { 0x1A, 0 }, // 0x58 - 0x5B - { 0x2B, 0 }, { 0x1B, 0 }, { 0x07, 1 }, { 0x0C, 1 }, // 0x5C - 0x5F - { 0x29, 0 }, { 0x1E, 0 }, { 0x30, 0 }, { 0x2E, 0 }, // 0x60 - 0x63 - { 0x20, 0 }, { 0x12, 0 }, { 0x21, 0 }, { 0x22, 0 }, // 0x64 - 0x67 - { 0x23, 0 }, { 0x17, 0 }, { 0x24, 0 }, { 0x25, 0 }, // 0x68 - 0x6B - { 0x26, 0 }, { 0x32, 0 }, { 0x31, 0 }, { 0x18, 0 }, // 0x6C - 0x6F - { 0x19, 0 }, { 0x10, 0 }, { 0x13, 0 }, { 0x1F, 0 }, // 0x70 - 0x73 - { 0x14, 0 }, { 0x16, 0 }, { 0x2F, 0 }, { 0x11, 0 }, // 0x74 - 0x77 - { 0x2D, 0 }, { 0x15, 0 }, { 0x2C, 0 }, { 0x1A, 1 }, // 0x78 - 0x7B - { 0x2B, 1 }, { 0x1B, 1 }, { 0x29, 1 }, { 0x0E, 0 } // 0x7C - 0x7F -}; - -struct get_keys_arg { - struct guest_info * info; - int fd; -}; - -struct video_internal { - addr_t video_memory_pa; - uchar_t * video_memory; - -#if PCI_ENABLED - struct vm_device * pci_bus; - struct pci_device * pci_dev; -#endif - - int socket_fd; - int client_fd; - - struct get_keys_arg key_arg; - - uint_t screen_bottom; - uint_t ports[44]; - uchar_t reg_3C4[0x100]; - uchar_t reg_3CE[0x100]; - ushort_t start_addr_offset; - ushort_t old_start_addr_offset; - ushort_t cursor_addr; - - uchar_t reg_3D5[0x19]; - - uint_t high_addr; - uint_t low_addr; -}; - -void video_do_in(ushort_t port, void *src, uint_t length){ - #if PASSTHROUGH - uint_t i; - - switch (length) { - case 1: - ((uchar_t*)src)[0] = v3_inb(port); - break; - case 2: - ((ushort_t*)src)[0] = v3_inw(port); - break; - case 4: - ((uint_t*)src)[0] = v3_indw(port); - break; - default: - for (i = 0; i < length; i++) { - ((uchar_t*)src)[i] = v3_inb(port); - } - }//switch length - #endif -} - -void video_do_out(ushort_t port, void * src, uint_t length){ - #if PASSTHROUGH - uint_t i; - switch (length) { - case 1: - v3_outb(port,((uchar_t*)src)[0]); - break; - case 2: - v3_outw(port,((ushort_t*)src)[0]); - break; - case 4: - v3_outdw(port,((uint_t*)src)[0]); - break; - default: - for (i = 0; i < length; i++) { - v3_outb(port, ((uchar_t*)src)[i]); - } - } //switch length - #endif -} - -static int deliver_scan_code(struct get_keys_arg * args, struct key_code * k) { - uint_t cap = k->capital; - struct v3_keyboard_event key_event; - key_event.status = 0; - key_event.scan_code = (unsigned char)k->scan_code; - PrintDebug("Scan code: 0x%x\n", key_event.scan_code); - struct v3_keyboard_event key_shift; - key_shift.status = 0; - key_shift.scan_code = (unsigned char)0x2A; - if(cap) { - if(v3_deliver_keyboard_event(args->info, &key_shift) == -1) { - PrintError("Video: Error delivering key event\n"); - return -1; - } - } - // Press - if(v3_deliver_keyboard_event(args->info, &key_event) == -1) { - PrintError("Video: Error delivering key event\n"); - return -1; - } - // Release - if(key_event.scan_code != 0x1c) { - key_event.scan_code = key_event.scan_code|0x80; - if(v3_deliver_keyboard_event(args->info, &key_event) == -1) { - PrintError("Video: Error delivering key event\n"); - return -1; - } - } - if(cap) { - key_shift.scan_code = 0x2A|0x80; - if(v3_deliver_keyboard_event(args->info, &key_shift) == -1) { - PrintError("Video: Error delivering key event\n"); - return -1; - } - } - PrintDebug("Finished with Key delivery\n"); - return 0; -} - -static int get_keys(void * arg) { - struct get_keys_arg * args = &(((struct video_internal *)arg)->key_arg); - while(1) { - PrintDebug("Get keys loop start\n"); - uint_t cap; - char key[1]; - memset(key, 0, 1); - - int recv = V3_Recv(args->fd, key, 1); - if(recv == -1){ - PrintError("Video: Error getting key from network\n"); - } - else if(recv == 0){ - PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd); - break; - } - - uint_t i; - for(i = 0; i < 1; i++) { - cap = 0; - uchar_t ascii = (uchar_t)key[i]; - - if(ascii == 0) { - PrintDebug("Recieved ASCII NULL character\n"); - break; - } - - PrintDebug("Character recieved: 0x%x\n", ascii); - if(ascii < 0x80) { - key[i] = ascii_to_key_code[ascii].scan_code; - cap = ascii_to_key_code[ascii].capital; - if(key[i]) { - // Special Terminal Escape Sequences (UP, DOWN, LEFT, RIGHT) - if(key[i] == 0x01) { - int j; - int esc = 0; - for(j = 0; j < 2; j++) { - int recv2 = V3_Recv(args->fd, key, 1); - if(recv2 == -1){ - PrintDebug("Video: Error getting key from network\n"); - break; - } - else if(recv2 == 0){ - PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd); - break; - } - if(key[0] == '[') { - esc = 1; - } - // UP ARROW - if(esc == 1 && key[0] == 'A') { - struct key_code up = { 0x48, 0 }; - deliver_scan_code(args, &up); - } - // DOWN ARROW - if(esc == 1 && key[0] == 'B') { - struct key_code down = { 0x50, 0 }; - deliver_scan_code(args, &down); - } - // RIGHT ARROW - if(esc == 1 && key[0] == 'C') { - struct key_code right = { 0x4D, 0 }; - deliver_scan_code(args, &right); - } - // LEFT ARROW - if(esc == 1 && key[0] == 'D') { - struct key_code left = { 0x4B, 0 }; - deliver_scan_code(args, &left); - } - } - break; - } - else if(key[i] == 0x1D){ - int recv2 = V3_Recv(args->fd, key, 1); - if(recv2 == -1){ - PrintDebug("Video: Error getting key from network\n"); - } - else if(recv2 == 0){ - PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd); - } - break; - } - else { - struct key_code k = { ascii_to_key_code[ascii].scan_code, ascii_to_key_code[ascii].capital }; - deliver_scan_code(args, &k); - } - } - else { - break; - } - } - } - } - return 0; -} - -#if SEND_UPDATE_INCREMENTAL_VT100 -static int send_all(struct video_internal * data, const int sock, const char * buf, const int len){ - int bytes_left = len; - while(bytes_left != 0) { - int written = 0; - if((written = V3_Send(sock, buf + (len-bytes_left), bytes_left)) == -1) { - return -1; - } - bytes_left -= written; - } - return 0; -} -#endif - -// Translate attribute color into terminal escape sequence color -static unsigned char text_mode_fg_color[] = { - 30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97 -}; - -static unsigned char text_mode_bg_color[] = { - 40, 44, 42, 46, 41, 45, 43, 47, 100, 104, 102, 106, 101, 105, 103, 107 -}; - -#if SEND_UPDATE_INCREMENTAL_VT100 -static unsigned char * append_char_as_digits(unsigned char *s, unsigned char c) -{ - if (c/100) { - *s++ = '0'+ c/100; - } - c %= 100; - if (c/10) { - *s++= '0' + c/10; - } - c %= 10; - *s++ = '0'+ c; - return s; -} - - -static unsigned char * append_write_attribute_at(unsigned char *s, unsigned char x, unsigned char y, unsigned char c) -{ - // Update cursor - *s++ = ESC_CHAR; - *s++ = '['; - s = append_char_as_digits(s,y+1); - *s++ = ';'; - s = append_char_as_digits(s,x+1); - *s++ = 'H'; - - *s++ = ESC_CHAR; - *s++ = '['; - *s++ = '0'; - *s++ = 'm'; - - // Update attribute - unsigned char fg_color = 0; - unsigned char bg_color = 0; - - *s++ = ESC_CHAR; - *s++ = '['; - unsigned char low = c & 0x0F; - unsigned char high = (c & 0xF0) >> 4; - low = low % 16; - fg_color = text_mode_fg_color[low]; - s = append_char_as_digits(s,fg_color); - *s++ = '\x3b'; - high = high % 16; - bg_color = text_mode_bg_color[high]; - s = append_char_as_digits(s,bg_color); - *s++ = 'm'; - return s; -} - -static unsigned char * append_write_char_at(unsigned char *s, unsigned char x, unsigned char y, unsigned char c) { - *s++ = ESC_CHAR; - *s++ = '['; - s = append_char_as_digits(s,y+1); - *s++ = ';'; - s = append_char_as_digits(s,x+1); - *s++ = 'H'; - *s++ = c; - return s; -} -#endif -static int video_write_mem(addr_t guest_addr, void * dest, uint_t length, void * priv_data) { - PrintDebug("\n\nInside Video Write Memory.\n\n"); - PrintDebug("Guest address: 0x%x length = %d\n", (uint_t)guest_addr, length); - - struct vm_device * dev = (struct vm_device *) priv_data; - struct video_internal * data = (struct video_internal *) dev->private_data; - addr_t write_offset = guest_addr - START_ADDR; - -#if 1 - PrintDebug("Write offset: 0x%p\n", (void*)write_offset); - - { - int i; - PrintDebug("Video_Memory: "); - for(i = 0; i < length; i += 2){ - PrintDebug("%c",((char *)(V3_VAddr((void*)guest_addr)))[i]); - } - } -#endif - - memcpy(data->video_memory + write_offset, V3_VAddr((void*)guest_addr), length); - -#if SEND_UPDATE_RAW - send_all(data, data->client_fd, (char *)(data->video_memory + write_offset), length); -#endif - -#if SEND_UPDATE_INCREMENTAL_VT100 - - unsigned char buf[32]; - unsigned char *n; - unsigned char *a; - uint_t difference = 0x18000; - - - unsigned char x,y,c; - uint_t offset; - uint_t l = length; - - for (offset=0;offsetstart_addr_offset *2) + offset)/160) ; - if(y < 25){ - // PrintDebug(" Video: Y value = %d ", y); - x = ((write_offset - difference + offset)%160)/2; - c = (data->video_memory + difference + data->start_addr_offset * 2)[y*160+x*2+1]; - a = append_write_attribute_at(buf,x,y,c); - send_all(data,data->client_fd, (char*)buf, 32); - memset(buf, 0, 32); - c = (data->video_memory + difference + data->start_addr_offset * 2)[y*160+x*2]; - n = append_write_char_at(buf,x,y,c); - send_all(data,data->client_fd, (char *)buf, 32); - } - } - -#endif - -#if SEND_UPDATE_ALL_VT100 - - unsigned char buf[16]; - unsigned char *n; - - unsigned char x,y,c; - - for (y=0;y<25;y++) { - for (x=0;x<80;x++) { - c = data->video_memory[y*160+x*2]; - n = append_write_char_at(buf,x,y,c); - send_all(data,data->client_fd, (char *)buf, n-buf); - } - } -#endif - PrintDebug(" Done.\n"); - return length; -} - -static int video_read_port(ushort_t port, - void * dest, - uint_t length, - struct vm_device * dev) { - PrintDebug("Video: Read port 0x%x\n",port); - video_do_in(port, dest, length); - return length; -} - -static int video_read_port_generic(ushort_t port, - void * dest, - uint_t length, - struct vm_device * dev) { - memset(dest, 0, length); - video_do_in(port, dest, length); - return length; -} - - -static int video_write_port(ushort_t port, - void * src, - uint_t length, - struct vm_device * dev) { - - PrintDebug("Video: write port 0x%x...Wrote: ", port); - uint_t i; - for(i = 0; i < length; i++){ - PrintDebug("%x", ((uchar_t*)src)[i]); - } - PrintDebug("...Done\n"); - video_do_out(port, src, length); - return length; -} - -static int video_write_port_store(ushort_t port, - void * src, - uint_t length, - struct vm_device * dev) { - - PrintDebug("Entering video_write_port_store...port 0x%x\n", port); - uint_t i; - for(i = 0; i < length; i++){ - PrintDebug("%x", ((uchar_t*)src)[i]); - } - PrintDebug("...Done\n"); - - struct video_internal * video_state = (struct video_internal *)dev->private_data; - video_state->ports[port - PORT_OFFSET] = 0; - memcpy(video_state->ports + (port - PORT_OFFSET), src, length); - video_do_out(port, src, length); - return length; -} - -static int video_write_port_3D5(ushort_t port, - void * src, - uint_t length, - struct vm_device * dev) { - PrintDebug("Video: write port 0x%x...Wrote: ", port); - uint_t i; - for(i = 0; i < length; i++){ - PrintDebug("%x", ((uchar_t*)src)[i]); - } - PrintDebug("...Done\n"); - struct video_internal * video_state = (struct video_internal *)dev->private_data; - video_state->ports[port - PORT_OFFSET] = 0; - memcpy(video_state->ports + (port - PORT_OFFSET), src, length); - - uint_t index = video_state->ports[port - 1 - PORT_OFFSET]; - memcpy(&(video_state->reg_3D5[index]), src, length); - uchar_t new_start; - switch(index) { - case 0x0c: - video_state->old_start_addr_offset = video_state->start_addr_offset; - new_start = *((uchar_t *)src); - video_state->start_addr_offset = (new_start << 8); - break; - case 0x0d: - new_start = *((uchar_t *)src); - video_state->start_addr_offset += new_start; - int diff = video_state->start_addr_offset - video_state->old_start_addr_offset; - if(diff > 0) { - for(diff /= 80; diff > 0; diff--){ - unsigned char message[2]; - memset(message, 0, 2); - message[0] = ESC_CHAR; - message[1] = 'D'; - send_all(video_state,video_state->client_fd, (char *)message, 2); - } - } - // Scroll Up? - break; - case 0x0E: - new_start = *((uchar_t *)src); - video_state->cursor_addr = new_start << 8; - break; - case 0x0F: - new_start = *((uchar_t *)src); - video_state->cursor_addr += new_start; - // Update cursor - unsigned char s[16]; - memset(s, 0, 16); - unsigned char *n = s; - *n++ = ESC_CHAR; - *n++ = '['; - n = append_char_as_digits(n,(((video_state->cursor_addr)/80))+1); - *n++ = ';'; - n = append_char_as_digits(n,((video_state->cursor_addr)% 80)+1); - *n++ = 'H'; - send_all(video_state, video_state->client_fd, (char *)s, 16); - break; - default: - break; - } - video_do_out(port, src, length); - return length; -} - - -static int video_write_port_3C5(ushort_t port, - void * src, - uint_t length, - struct vm_device * dev) { - PrintDebug("Entering write_port_3C5....port 0x%x\n", port); - uint_t i; - for(i = 0; i < length; i++){ - PrintDebug("%x", ((uchar_t*)src)[i]); - } - PrintDebug("...Done\n"); - - struct video_internal * video_state = (struct video_internal *)dev->private_data; - video_state->ports[port - PORT_OFFSET] = 0; - memcpy(video_state->ports + (port - PORT_OFFSET), src, length); - - uint_t index = video_state->ports[port - 1 - PORT_OFFSET]; - memcpy(&(video_state->reg_3C4[index]), src, length); - video_do_out(port, src, length); - return length; -} - -static int video_write_port_3CF(ushort_t port, - void * src, - uint_t length, - struct vm_device * dev) { - PrintDebug("Entering write_port_3CF....port 0x%x\n", port); - uint_t i; - for(i = 0; i < length; i++){ - PrintDebug("%x", ((uchar_t*)src)[i]); - } - PrintDebug("...Done\n"); - - struct video_internal * video_state = (struct video_internal *)dev->private_data; - video_state->ports[port - PORT_OFFSET] = 0; - memcpy(video_state->ports + (port - PORT_OFFSET), src, length); - - uint_t index = video_state->ports[port - 1 - PORT_OFFSET]; - memcpy(&(video_state->reg_3CE[index]), src, length); - video_do_out(port, src, length); - return length; -} - -static int video_write_port_3D4(ushort_t port, void *src, uint_t length, - struct vm_device *dev){ - struct video_internal *video_state = (struct video_internal *) dev -> private_data; - -#if 1 - - if(length == 1) { - video_state->ports[port - PORT_OFFSET] = 0; - memcpy(video_state->ports + (port - PORT_OFFSET), src, length); - } - else if(length == 2){ - ushort_t new_start = 0; - ushort_t cursor_start = 0; - new_start = *((ushort_t *)src); - cursor_start = *((ushort_t *)src); - - //Updating the cursor - if((cursor_start & 0x00FF) == 0x000E){ - PrintDebug("Video: E Case cursor start = 0x%x\n", cursor_start); - cursor_start = (cursor_start & 0xFF00); //0x70 - PrintDebug("Video: cursor start after and = 0x%x\n", cursor_start); - video_state->cursor_addr = cursor_start; - } - else if((cursor_start & 0x00FF) == 0x000F){ - PrintDebug("Video: F Case cursor start = 0x%x\n", cursor_start); - PrintDebug("Cursor Address after: 0x%x\n", video_state->cursor_addr); - video_state->cursor_addr += ((cursor_start >> 8) & 0x00FF); - // Update cursor - unsigned char s[16]; - memset(s, 0, 16); - unsigned char *n = s; - *n++ = ESC_CHAR; - *n++ = '['; - n = append_char_as_digits(n,(((video_state->cursor_addr)/80))+1); - *n++ = ';'; - n = append_char_as_digits(n,((video_state->cursor_addr)% 80)+1); - *n++ = 'H'; - PrintDebug("Cursor Address: 0x%x\n", video_state->cursor_addr); - PrintDebug("Cursor Y location should be: %d\n", ((video_state->cursor_addr)/80)+1); - PrintDebug("Cursor X location should be: %d\n",((video_state->cursor_addr % 80)/2)+1); - send_all(video_state, video_state->client_fd, (char *)s, 16); - } - //Checking to see if scrolling is needed - if((new_start & 0x00FF) == 0x000C){ - video_state->old_start_addr_offset = video_state->start_addr_offset; - new_start = (new_start & 0xFF00); - video_state->start_addr_offset = new_start; - } - else if((new_start & 0x00FF) == 0x000D){ - video_state->start_addr_offset += ((new_start >> 8) & 0x00FF); - int diff = video_state->start_addr_offset - video_state->old_start_addr_offset; - if(diff > 0){ -#if 1 - for(diff /= 80; diff > 0; diff--){ - unsigned char message[2]; - memset(message, 0, 2); - message[0] = ESC_CHAR; - message[1] = 'D'; - send_all(video_state,video_state->client_fd, (char *)message, 2); - } -#endif - } - //Still need to handle scroll up - } - } -#endif - video_do_out(port, src, length); - return length; -} - - - -#if PCI_ENABLED -static int video_write_mem_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){ - - struct vm_device * dev = (struct vm_device *) priv_data; - struct video_internal * data = (struct video_internal *) dev->private_data; - - if(data->low_addr == 0){ - data->low_addr = guest_addr; - //memset(V3_VAddr((void*)0xA0000),0,0x10000); - memset(V3_VAddr((void *)0xA000000),0, 0x4affc); - memset(V3_VAddr((void *)0xF0000000),0, 0x4affc); - } - - if(guest_addr > data->high_addr){ - data->high_addr = guest_addr; - } - if(guest_addr < data->low_addr){ - data->low_addr = guest_addr; - } - - - PrintDebug("Video: Within video_write_mem_region\n"); - - PrintDebug("Length of write: %d\n", length); - PrintDebug("Guest Address of write: 0x%p\n", (void *)guest_addr); - //PrintDebug("\"Src Address\": 0x%p\n", (void *)src); - - - //PrintDebug("Write Mem Value: "); - // PrintDebug("0x%x",*((uint32_t *)(V3_VAddr((void*)guest_addr)))); - // PrintDebug("0x%x",*((uint32_t *)src)); - /* - unsigned char message[4]; - memset(message, 0, 4); - message[0] = (*((char *)(V3_VAddr((void*)guest_addr)))); - message[1] = (*((char *)(V3_VAddr((void*)guest_addr) + 1))); - message[2] = (*((char *)(V3_VAddr((void*)guest_addr) + 2))); - message[3] = (*((char *)(V3_VAddr((void*)guest_addr) + 3))); - PrintDebug("Character Value: %s\n", message); - //send_all(data,data->client_fd, (char *)message, 4); - */ - - PrintDebug("\nLowest address written to..."); - PrintDebug("0x%x",data->low_addr); - - PrintDebug("\nHighest address written to..."); - PrintDebug("0x%x\n",data->high_addr); - - // memcpy(V3_VAddr((void*)0xF0000000), V3_VAddr((void*)guest_addr) , length); - //addr_t write_offset = guest_addr - 0xA000000;// % 0x20000; // (guest_addr - 0xA000000);// % 0x20000 - // PrintDebug("0x%x",*((uint32_t *)(src + ))); - //memcpy(V3_VAddr((void *)(0xF0000000 + write_offset)), src, length); - /*If(write_offset < 0x10000) { - memcpy(V3_VAddr((void *)(START_ADDR + write_offset)), V3_VAddr((void*)guest_addr) , length); - } - else { - memset(V3_VAddr((void*)0xA0000),0,0x10000); - }*/ - // memset(V3_VAddr((void *)(0xF0000000)), 5, 0x4affc); - //memset(V3_VAddr((void *)(0xF004affa)), 7, 0xF); - - //Int i; - //PrintDebug("Write Mem Value: "); - //for(i = 0; i < length; i++){ - // PrintDebug("%x",((char *)(V3_VAddr((void*)guest_addr)))[i]); - //} - - PrintDebug("\n...Done\n"); - - return length; -} - -static int video_read_mem_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){ - PrintDebug("Video: Within video_read_mem_region\n"); - return length; -} - -static int video_write_io_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){ - PrintDebug("Video: Within video_write_io_region\n"); - return length; -} - -static int video_read_io_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){ - PrintDebug("Video: Within video_read_io_region\n"); - return length; -} -#endif - -static int video_free(struct vm_device * dev) { - v3_unhook_mem(dev->vm, START_ADDR); - return 0; -} - -static int video_reset_device(struct vm_device * dev) { - PrintDebug("Video: reset device\n"); - return 0; -} - -static int video_start_device(struct vm_device * dev) { - PrintDebug("Video: start device\n"); - return 0; -} - -static int video_stop_device(struct vm_device * dev) { - PrintDebug("Video: stop device\n"); - return 0; -} - -static struct v3_device_ops dev_ops = { - .free = video_free, - .reset = video_reset_device, - .start = video_start_device, - .stop = video_stop_device, -}; - -static int video_init(struct guest_info * vm, void * cfg_data){ - PrintDebug("video: init_device\n"); -struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal)); - - struct vm_device * dev = v3_allocate_device("VIDEO", &dev_ops, video_state); - - if (v3_attach_device(vm, dev) == -1) { - PrintError("Could not attach device %s\n", "VIDEO"); - return -1; - } - - PrintDebug("Num Pages=%d\n", SIZE_OF_REGION / 4096); - video_state->video_memory_pa = (addr_t)V3_AllocPages(SIZE_OF_REGION / 4096); - video_state->video_memory = V3_VAddr((void*)video_state->video_memory_pa); - - memset(video_state->video_memory, 0, SIZE_OF_REGION); - PrintDebug("Video: hook io ports\n"); -#if 1 - v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port_store); - v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port_store); - v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port_store); - v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port_3C5); - v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port_store); - v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port_store); - v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port_store); - v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port_store); - v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port_3CF); - v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3d4, &video_read_port, &video_write_port_3D4); - v3_dev_hook_io(dev, 0x3d5, &video_read_port, &video_write_port_3D5); - v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3da, &video_read_port_generic, &video_write_port); - v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port); - v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port); -#endif - PrintDebug("Video: End i/o hooks\n"); - struct guest_info * info = vm; - PrintDebug("PA of array: %p\n", (void*)video_state->video_memory_pa); - - if(v3_hook_write_mem(info, START_ADDR, END_ADDR, START_ADDR, &video_write_mem, dev) == -1){ - PrintDebug("\n\nVideo Hook failed.\n\n"); - } - print_shadow_map(info); - - - // Testing out network stuff - video_state->socket_fd = V3_Create_TCP_Socket(); - PrintDebug("Video: Socket File Descriptor: %d\n", video_state->socket_fd); - -#if 1 - - if(V3_Bind_Socket(video_state->socket_fd, PORT) == -1) { - PrintError("Video: Failed to bind to socket %d\n", PORT); - } - if(V3_Listen_Socket(video_state->socket_fd, 10) == -1) { - PrintError("Video: Failed to listen with socket %d\n", video_state->socket_fd); - } - const char * ip_string = "10.10.10.138"; - PrintDebug("Video: IP Address in string form: %s\n", ip_string); - uint32_t ip_h = v3_inet_addr(ip_string); - PrintDebug("Video: IP Address in host integer form: %x\n", ip_h); - uint32_t ip_n = v3_htonl(ip_h); - PrintDebug("Video: IP Address in network integer form %x\n", ip_n); - uint32_t port = PORT; - unsigned int ip_ptr = (ip_n); - unsigned int port_ptr = (port); - if((video_state->client_fd = V3_Accept_Socket(video_state->socket_fd, &ip_ptr, &port_ptr)) == -1) { - PrintDebug("Video: Failed to accept connection on port %d", PORT); - } - PrintDebug("Video: Accept worked? FD= %d\n", video_state->client_fd); -#endif - - video_state->key_arg.info = info; - video_state->key_arg.fd = video_state->client_fd; - V3_CREATE_THREAD(get_keys,(void *)video_state, "Get Keys from Network"); - - video_state->screen_bottom = 25; - PrintDebug("video: init complete\n"); - - - -#if PCI_ENABLED - if(video_state->pci_bus){ - struct v3_pci_bar bars[6]; - struct pci_device * pci_dev = NULL; - - int i; - for(i = 0; i < 6; i++){ - bars[i].type = PCI_BAR_NONE; - } - - bars[0].type = PCI_BAR_MEM32; - bars[0].num_pages = /*0x20000/0x1000;*/ 0x2000000/0x1000; - bars[0].default_base_addr = (addr_t)V3_VAddr((void *)0xF0000000);//(addr_t)V3_VAddr(V3_AllocPages(bars[0].num_pages)); - - bars[0].mem_read = video_read_mem_region; - bars[0].mem_write = video_write_mem_region; - - bars[1].type = PCI_BAR_MEM32; - bars[1].num_pages = 1; - bars[1].default_base_addr = (addr_t)V3_VAddr(V3_AllocPages(bars[1].num_pages)); - - bars[1].mem_read = video_read_io_region; - bars[1].mem_write = video_write_io_region; - //-1 Means autoassign - // Not sure if STD - pci_dev = v3_pci_register_device(video_state->pci_bus, PCI_STD_DEVICE, 0, - //or0 1st null could be pci_config_update - -1, 0, "VIDEO", bars, NULL, NULL, - NULL, dev); - - if (pci_dev == NULL) { - PrintError("Failed to register VIDEO %d with PCI\n", i); - return -1; - } - else{ - PrintDebug("Registering PCI_VIDEO succeeded\n"); - } - //Need to set some pci_dev->config_header.vendor_id type variables - - pci_dev->config_header.vendor_id = 0x1013; - pci_dev->config_header.device_id = 0x00B8; - pci_dev->config_header.revision = 0x00; - - //If we treat video as a VGA device than below is correct - //If treated as a VGA compatible controller, which has mapping - //0xA0000-0xB0000 and I/O addresses 0x3B0-0x3BB than change - //#define from VGA to 0 - - //pci_dev->config_header.class = 0x00; - //pci_dev->config_header.subclass = 0x01; - - pci_dev->config_header.class = 0x03; - pci_dev->config_header.subclass = 0x00; - pci_dev->config_header.prog_if = 0x00; - - - //We have a subsystem ID, but optional to provide: 1AF4:1100 - pci_dev->config_header.subsystem_vendor_id = 0x1AF4; - pci_dev->config_header.subsystem_id = 0x1100; - //pci_dev->config_header.header_type = 0x00; - pci_dev->config_header.command = 0x03; - video_state->pci_dev = pci_dev; - } -#endif - return 0; -} - -device_register("VIDEO", video_init) - - -/* -#if PCI_ENABLED -struct vm_device * v3_create_video(struct vm_device * pci_bus) { - -#else -struct vm_device * v3_create_video() { -#endif - PrintDebug("Video Print Debug in create\n"); - - PrintDebug("Video, before initial \n"); - - struct video_internal * video_state = NULL; - - video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal)); - - PrintDebug("video: internal at %p\n", (void *)video_state); - - struct vm_device * device = v3_create_device("VIDEO", &dev_ops, video_state); - -#if PCI_ENABLED - if(pci_bus != NULL){ - video_state->pci_bus = pci_bus; - } -#endif - - return device; -} -*/ - diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index af45a0a..1cadad7 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -39,7 +39,7 @@ #include #include -#include +#include @@ -57,7 +57,7 @@ static int configure_generic(struct guest_info * info, struct v3_vm_config * con -#ifndef CONFIG_VIDEO +#ifdef CONFIG_PASSTHROUGH_VIDEO static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) { return length; @@ -178,7 +178,7 @@ int v3_post_config_guest(struct guest_info * info, struct v3_vm_config * config_ */ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) { -#ifndef CONFIG_VIDEO +#ifdef CONFIG_PASSTHROUGH_VIDEO PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024))); // VGA frame buffer @@ -244,6 +244,11 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ v3_create_device(info, "VMNET", NULL); + v3_create_device(info, "CGA_VIDEO", (void *)1); + { + struct telnet_cons_cfg cons_cfg = {"CGA_VIDEO", 19997}; + v3_create_device(info, "TELNET_CONSOLE", &cons_cfg); + } if (config_ptr->enable_pci == 1) { struct ide_cfg ide_config = {"PCI", "PIIX3"}; @@ -258,8 +263,6 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ v3_create_device(info, "LNX_VIRTIO_BALLOON", "PCI"); v3_create_device(info, "SYM_SWAP", "LNX_VIRTIO_BLK"); - v3_create_device(info, "VIDEO", "PCI"); - v3_create_device(info, "IDE", &ide_config); } else { v3_create_device(info, "IDE", NULL); @@ -447,7 +450,7 @@ static int configure_generic(struct guest_info * info, struct v3_vm_config * con #endif -#ifndef CONFIG_VIDEO +#ifdef CONFIG_PASTHROUGH_VIDEO // Monitor graphics card operations diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index ba6e9c5..9ed9102 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -327,7 +327,7 @@ int v3_handle_cr3_write(struct guest_info * info) { PrintError("Failed to activate 32 bit shadow page table\n"); return -1; } - } + } PrintDebug("New Shadow CR3=%p; New Guest CR3=%p\n", (void *)(addr_t)(info->ctrl_regs.cr3),