Specifies the maximum number of hardware CPUs supported by the OS
For uniprocessor environments, set this to 1
-config FILE
- bool "Host Support for file operations"
- default n
- help
- Select this if your host OS supports file operatoins and you want Palacios to be able to use them.
-
-config KEYED_STREAMS
- bool "Host support for keyed streams"
- default n
- help
- Select this if your host OS supports keyed streams
- Palacios Checkpoint/Restore and Migration depends on this feature
-
-config CONSOLE
- bool "Host Support for VM text-mode console"
- default n
- help
- Select this if you want to forward a guest console interface to some host OS service
- This is for a TEXT MODE console. Select the framebuffer console for graphics and text
-
-config GRAPHICS_CONSOLE
- bool "Host Support for VM graphics and text-mode console based on a frame buffer"
- default n
- help
- Select this if you want to forward a guest graphics-mode (and text-mode) console
- interface to some host OS service. This is for a GRAPHICS console based on a shared frame buffer.
- Text mode output is RENDERED onto the framebuffer
-
-config SOCKET
- bool "Host support for Network Sockets"
- default y
- help
- Select this if you host OS implements a socket API that is available to Palacios. This is required
- to support the internal networking features of Palacios.
-
-
-config PACKET
- bool "Host support for Raw Packet Transmision"
- depends on EXPERIMENTAL
- default n
- help
- Select this if you host OS implements a raw packet network API that is available to Palacios. This is required
- to support the internal networking features of Palacios.
-
endmenu
+source "palacios/src/interfaces/Kconfig"
config TELEMETRY
core-y := palacios/src/palacios/
libs-y := palacios/lib/$(ARCH)/
devices-y := palacios/src/devices/
+interfaces-y := palacios/src/interfaces/
modules-y := modules/
palacios-dirs := $(patsubst %/,%,$(filter %/, \
- $(core-y) $(devices-y) $(libs-y)) $(modules-y))
+ $(core-y) $(devices-y) $(interfaces-y) $(libs-y)) $(modules-y))
palacios-cleandirs := $(sort $(palacios-dirs) $(patsubst %/,%,$(filter %/, \
- $(core-n) $(core-) $(devices-n) $(devices-) $(modules-n) $(modules-))))
+ $(core-n) $(core-) $(devices-n) $(devices-) \
+ $(interfaces-n) $(interfaces-) $(modules-n) $(modules-))))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
devices-y := $(patsubst %/, %/built-in.o, $(devices-y))
+interfaces-y := $(patsubst %/, %/built-in.o, $(interfaces-y))
libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
modules-y := $(patsubst %/, %/built-in.o, $(modules-y))
#lnxmod-y := $(patsubst %/, %/built-in.o, $(lnxmod-y))
-palacios := $(core-y) $(devices-y) $(libs-y) $(modules-y)
+palacios := $(core-y) $(devices-y) $(interfaces-y) $(libs-y) $(modules-y)
# Rule to link palacios - also used during CONFIG_CONFIGKALLSYMS
palacios-dev.o \
palacios-vm.o \
palacios-file.o \
- palacios-stream.o \
palacios-console.o \
palacios-mm.o \
palacios-serial.o \
+ palacios-stream.o \
palacios-queue.o \
palacios-ringbuffer.o \
palacios-debugfs.o
+
ifdef CONFIG_PALACIOS_VNET
v3vee-objs += palacios-vnet.o
endif
#include <linux/file.h>
#include <linux/sched.h>
-#include <palacios/vmm_console.h>
+#include <interfaces/vmm_console.h>
#include <palacios/vmm_host_events.h>
#include "palacios.h"
#include "palacios.h"
-#include <palacios/vmm_file.h>
+#include <interfaces/vmm_file.h>
static struct list_head global_files;
#include <linux/errno.h>
#include <asm/msr.h>
-#include <palacios/vmm_packet.h>
+#include <interfaces/vmm_packet.h>
#include <palacios/vmm_host_events.h>
#include <palacios/vmm_vnet.h>
#include <palacios/vmm_ethernet.h>
* full text of the license.
*/
-#include <palacios/vmm_socket.h>
+#include <interfaces/vmm_socket.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/percpu.h>
#include <linux/sched.h>
-#include <palacios/vmm_stream.h>
+#include <interfaces/vmm_stream.h>
#include "palacios-stream.h"
static struct list_head global_streams;
--- /dev/null
+/*
+ * 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) 2011, Peter Dinda <pdinda@northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Peter Dinda <pdinda@northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __VMM_HOST_DEV_H__
+#define __VMM_HOST_DEV_H__
+
+#include <palacios/vmm.h>
+
+
+/*
+
+ The purpose of this interface is to make it possible to implement
+ virtual devices in the host OS. It is intended to be used by
+ passthrough device implementations, such as the generic device
+ and the PCI passthrough device.
+
+ One use of this interface, and the generic and PCI passthrough devices
+ might be to build an interface with simulated devices in SST
+ under a Linux host. That scenario would look like this:
+
+Guest config:
+
+ generic device:
+ <device class="generic" id="mydev" impl="host_sst">
+ ports, memory regions, interrupts set with PASSTHROUGH option
+ </device>
+
+ PCI passthrough devive:
+ <device class="pci_passthrough" id="mydev", impl="host_sst">
+ vendor and device ids, etc
+ </device>
+
+impl="physical" or lack of an impl key would indicate that direct hardware
+access is expected, which is how these devices currently operate.
+
+
+Host (Linux) side:
+
+ There would be an implementation and registration of the hooks
+ defined and explained in this file
+
+ The implementation might, for example, create an interface to
+ a user space process, for example like the console
+ (palacios-console.[ch] + v3_cons.c) or graphics console
+ (palacios-graphics-console.[ch] + v3_vncserver.c) do
+ and route the hook functions defined here through it.
+ Through this interface, the calls could be routed to an SST
+ device module.
+
+*/
+
+
+/* A host device is opaque to the palacios */
+typedef void * v3_host_dev_t;
+/* A guest device is opaque to the host */
+typedef void * v3_guest_dev_t;
+
+
+/* There is a notion of a bus class to which the device is attached */
+typedef enum { DIRECT, PCI } v3_bus_class_t;
+
+#ifdef __V3VEE__
+
+v3_host_dev_t v3_host_dev_open(char *impl,
+ v3_bus_class_t bus,
+ v3_guest_dev_t gdev);
+
+uin64_t v3_host_dev_read_io(v3_host_dev_t hostdev,
+ uint16_t port,
+ void *dest
+ uint64_t len);
+
+uint64_t v3_host_dev_write_io(v3_host_dev_t hostdev,
+ uint16_t port,
+ void *src,
+ uint64_t len);
+
+uint64_t v3_host_dev_read_mem(v3_host_dev_t hostdev,
+ addr_t gpa,
+ void *dest,
+ uint64_t len);
+
+uint64_t v3_host_dev_write_mem(v3_host_dev_t hostdev,
+ addr_t gpa,
+ void *src,
+ uint64_t len);
+
+int v3_host_dev_ack_irq(v3_host_dev_t hostdev, uint32_t irq);
+
+uint64_t v3_host_dev_config_read(v3_host_dev_t hostdev,
+ void *dest,
+ uint64_t len);
+
+uint64_t v3_host_dev_config_write(v3_host_dev_t hostdev,
+ void *src,
+ uint64_t len);
+
+#endif
+
+struct v3_host_dev_hooks {
+
+ // The host is given the implementation name, the type of bus
+ // this device is attached to and an opaque pointer back to the
+ // guest device. It returns an opaque representation of
+ // the host device it has attached to, with zero indicating
+ // failure
+ v3_host_dev_t (*open)(char *impl,
+ v3_bus_class_t bus,
+ v3_guest_dev_t gdev);
+
+ // Read/Write from/to an IO port. The read must either
+ // completely succeed, returning len or completely
+ // fail, returning != len
+ // Callee gets the host dev id and the port in the guest
+ uint64_t (*read_io)(v3_host_dev_t hostdev,
+ uint16_t port,
+ void *dest
+ uint64_t len);
+
+ uint64_t (*write_io)(v3_host_dev_t hostdev,
+ uint16_t port,
+ void *src,
+ uint64_t len);
+
+ // Read/Write from/to memory. The reads/writes must
+ // completely succeed, returning len or completely
+ // fail, returning != len
+ // Callee gets the host dev id, and the guest physical address
+ uint64_t (*read_mem)(v3_host_dev_t hostdev,
+ addr_t gpa,
+ void *dest,
+ uint64_t len);
+
+ uint64_t (*write_mem)(v3_host_dev_t hostdev,
+ addr_t gpa,
+ void *src,
+ uint64_t len);
+
+ // Palacis will call this when it has taken posession of the
+ // IRQ ad wants the host device to lower it
+ // This interface is unclear
+ //
+ // One potential use would be to allow for a palacios
+ // side device to raise the irq asynchronously from
+ // the host device. If this is permitted, then we
+ // need a way of informing the host device that the
+ // irq has actually been signalled.
+ int (*ack_irq)(v3_host_dev_t hostdev, uint8_t irq);
+
+ // Configuration space reads/writes for devices that
+ // have them, such as PCI devices
+ // As with other reads/writes, these must be fully successful
+ // or fail
+ //
+ // Palacios maintains its own configuration for some
+ // devices (e.g., pci_passthrough) and will take care of
+ // relevant hooking/unhooking, and maintain its own
+ // config space info. However, a read will return
+ // the host device's config, while a write will affect
+ // both the palacios-internal config and the hsot device's config
+ uint64_t (*config_read)(v3_host_dev_t hostdev,
+ void *dest,
+ uint64_t len);
+
+ uint64_t (*config_write)(v3_host_dev_t hostdev,
+ void *src,
+ uint64_t len);
+
+};
+
+/* This function is how the host will raise an irq to palacios
+ for the device. The IRQ argument will be ignored for devices
+ whose irqs are managed by palacios */
+int v3_host_dev_raise_irq(v3_host_dev_t hostdev,
+ v3_guest_dev_t guest_dev,
+ uint8_t irq);
+
+/* These functions allow the host to read and write the guest
+ memory by physical address, for example to implement DMA
+
+ These functions are incremental - that is, they can return
+ a smaller amount than requested
+*/
+uint64_t v3_host_dev_read_guest_mem(v3_host_dev_t hostdev,
+ v3_guest_dev_t guest_dev,
+ addr_t gpa,
+ void *dest,
+ uint64_t len);
+
+uint64_t v3_host_dev_write_guest_mem(v3_host_dev_t hostdev,
+ v3_guest_dev_t guest_dev,
+ addr_t gpa,
+ void *src,
+ uint64_t len);
+
+
+extern void V3_Init_Host_Device_Support(struct v3_host_dev_hooks *hooks);
+
+#endif
addr_t operand;
uint_t size;
v3_operand_type_t type;
- uint8_t read : 1;
- uint8_t write : 1;
-};
+ uint8_t read : 1; // This operand value will be read by the instruction
+ uint8_t write : 1; // This operand value will be written to by the instruction
+} __attribute__((packed));
struct x86_prefixes {
uint_t lock : 1; // 0xF0
#include <palacios/vmm_msr.h>
#include <palacios/vmm_config.h>
#include <palacios/vmm_ethernet.h>
-#include <palacios/vmm_keyed_stream.h>
struct v3_vm_info;
int V3_deinit_devices();
+#ifdef CONFIG_KEYED_STREAMS
+#include <interfaces/vmm_keyed_stream.h>
+#endif
+
struct v3_device_ops {
int (*free)(void * private_data);
+#ifdef CONFIG_KEYED_STREAMS
int (*checkpoint)(struct vm_device *dev, v3_keyed_stream_t stream);
int (*restore)(struct vm_device *dev, v3_keyed_stream_t stream);
+#endif
};
*/
#include <palacios/vmm.h>
-#include <palacios/vmm_stream.h>
+#include <interfaces/vmm_stream.h>
#include <palacios/vmm_dev_mgr.h>
#include <palacios/vmm_sprintf.h>
#include <palacios/vmm_host_events.h>
#include <palacios/vmm_paging.h>
#include <palacios/vmm_instr_emulator.h>
#include <palacios/vm_guest_mem.h>
-#include <palacios/vmm_socket.h>
+#include <interfaces/vmm_socket.h>
#include <palacios/vmm_host_events.h>
#include <devices/pci.h>
#include <devices/pci_types.h>
/* Interface between virtual video card and console */
#include <palacios/vmm.h>
-#include <palacios/vmm_console.h>
+#include <interfaces/vmm_console.h>
#include <palacios/vmm_dev_mgr.h>
#include <palacios/vmm_sprintf.h>
#include <palacios/vmm_host_events.h>
#include <palacios/vmm.h>
#include <palacios/vmm_dev_mgr.h>
-#include <palacios/vmm_file.h>
+#include <interfaces/vmm_file.h>
#include <palacios/vm_guest.h>
#ifndef CONFIG_DEBUG_FILEDISK
#include <palacios/vmm.h>
#include <palacios/vmm_dev_mgr.h>
-#include <palacios/vmm_socket.h>
+#include <interfaces/vmm_socket.h>
#ifndef CONFIG_DEBUG_IDE
#undef PrintDebug
#include <palacios/vmm_dev_mgr.h>
#include <palacios/vm_guest_mem.h>
#include <palacios/vmm_sprintf.h>
-#include <palacios/vmm_packet.h>
+#include <interfaces/vmm_packet.h>
#ifndef CONFIG_DEBUG_NIC_BRIDGE
#undef PrintDebug
#include <palacios/vmm_host_events.h>
#include <palacios/vmm_lock.h>
#include <palacios/vmm_string.h>
-#include <palacios/vmm_socket.h>
+#include <interfaces/vmm_socket.h>
#include <devices/console.h>
#include <palacios/vmm_types.h>
#include <palacios/vm_guest_mem.h>
#include <palacios/vmm_io.h>
-#include <palacios/vmm_graphics_console.h>
+#include <interfaces/vmm_graphics_console.h>
#include "vga_regs.h"
#define VGA_DAC_NUM_ENTRIES 256
+
+#define VGA_FONT_WIDTH 8
+#define VGA_MAX_FONT_HEIGHT 32
+
struct vga_misc_regs {
/* Read: 0x3cc; Write: 0x3c2 */
struct vga_misc_out_reg vga_misc_out;
/* index 8 */
struct vga_preset_row_scan_reg vga_preset_row_scan;
/* index 9 */
- struct vga_max_row_scan_reg vga_row_scan;
+ struct vga_max_row_scan_reg vga_max_row_scan;
/* index 10 */
struct vga_cursor_start_reg vga_cursor_start;
/* index 11 */
/* index 17 */
struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
/* index 18 */
- vga_vertical_display_enable_end_reg vga_vertical_display_enable;
+ vga_vertical_display_enable_end_reg vga_vertical_display_enable_end;
/* index 19 */
vga_offset_reg vga_offset;
/* index 20 */
-static int render(struct vga_internal *vga)
+static void find_text_char_dim(struct vga_internal *vga, uint32_t *w, uint32_t *h)
{
- vga->updates_since_render++;
+ *w = (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
- if (vga->host_cons && v3_graphics_console_inform_update(vga->host_cons)>0) {
- // Draw some crap for testing for now
+ *h = vga->vga_crt_controller.vga_max_row_scan.max_scan_line+1;
- void *fb;
- struct v3_frame_buffer_spec *s;
+}
- fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
+static void find_text_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
+{
+ uint32_t vert_lsb, vert_msb;
+ uint32_t ph;
+ uint32_t ch, cw;
+
+ *width = (vga->vga_crt_controller.vga_horizontal_display_enable_end + 1)
+ - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew;
+
+ vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
+ vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1) // 2 bits here
+ + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
+
+ ph = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
+
+ find_text_char_dim(vga,&cw, &ch);
+
+ *height = ph / ch;
+
+}
+
+
+static void find_text_data_start(struct vga_internal *vga, void **data)
+{
+ uint32_t offset;
+
+ offset = vga->vga_crt_controller.vga_start_address_high;
+ offset <<= 8;
+ offset += vga->vga_crt_controller.vga_start_address_low;
+
+ *data = vga->map[0]+offset;
+
+}
+
+static void find_text_attr_start(struct vga_internal *vga, void **data)
+{
+ uint32_t offset;
+
+ offset = vga->vga_crt_controller.vga_start_address_high;
+ offset <<= 8;
+ offset += vga->vga_crt_controller.vga_start_address_low;
+
+ *data = vga->map[1]+offset;
+
+}
+
+static void find_text_cursor_pos(struct vga_internal *vga, uint32_t *x, uint32_t *y, void **data)
+{
+ uint32_t w,h;
+ uint32_t offset;
+ uint32_t charsin;
+ void *buf;
+
+ find_text_res(vga,&w,&h);
+
+ find_text_data_start(vga,&buf);
+
+ offset = vga->vga_crt_controller.vga_cursor_location_high;
+ offset <<= 8;
+ offset += vga->vga_crt_controller.vga_cursor_location_low;
+
+ *data = vga->map[0]+offset;
+
+ charsin = (uint32_t)(*data - buf);
+
+ *x = charsin % w;
+ *y = charsin / w;
+
+}
+
+
+static void find_text_font_start(struct vga_internal *vga, void **data, uint8_t char_map)
+{
+ uint32_t mapa_offset, mapb_offset;
+
+
+ switch (char_map) {
+ case 0:
+ mapa_offset = (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb << 1)
+ + vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb ;
+ *data = vga->map[2] + mapa_offset;
+ break;
+
+ case 1:
+ mapb_offset = (vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb << 1)
+ + vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb ;
+ *data = vga->map[2] + mapb_offset;
+ break;
+ default:
+ PrintError("vga: unknown char_map given to find_text_font_start\n");
+ break;
+
+ }
+}
+
+static int extended_fontset(struct vga_internal *vga)
+{
+ if (vga->vga_sequencer.vga_mem_mode.extended_memory &&
+ ! ( (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb
+ == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb) &&
+ (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb
+ == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb))) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+static int blinking(struct vga_internal *vga)
+{
+ return vga->vga_attribute_controller.vga_attribute_mode_control.enable_blink;
+}
+
+
+static void find_graphics_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
+{
+ uint32_t vert_lsb, vert_msb;
+
+ *width = ((vga->vga_crt_controller.vga_horizontal_display_enable_end + 1)
+ - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew);
+
+ *width *= (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
- s=&(vga->target_spec);
+ vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
+ vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1) // 2 bits here
+ + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
+
+ *height = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
+
+}
+
+
+static void find_graphics_cursor_pos(struct vga_internal *vga, uint32_t *width, uint32_t *height)
+{
+
+}
+
+static void render_graphics(struct vga_internal *vga, void *fb)
+{
+
+ PrintDebug("vga: render_graphics is unimplemented\n");
+ // Multiuplane 16
+ // Packed pixel mono
+ // packed pixel 4 color
+ // packed pixel 256 color
+
+ find_graphics_cursor_pos(0,0,0);
+
+}
+
+static void render_text_cursor(struct vga_internal *vga, void *fb)
+{
+}
+
+
+
+static void dac_lookup_24bit_color(struct vga_internal *vga,
+ uint8_t entry,
+ uint8_t *red,
+ uint8_t *green,
+ uint8_t *blue)
+{
+ // use internal or external palette?
+
+ vga_palette_reg *r = &(vga->vga_dac.vga_dac_palette[entry]);
+
+ // converting from 6 bits to 8 bits so << 2
+ *red = (*r & 0x3f) << 2;
+ *green = ((*r >> 8) & 0x3f) << 2;
+ *blue = ((*r >> 16) & 0x3f) << 2;
+
+}
+
+//
+// A variant of this function could render to
+// a text console interface as well
+//
+static void render_text(struct vga_internal *vga, void *fb)
+{
+ // line graphics enable bit means to dupe column 8 to 9 when
+ // in 9 dot wide mode
+ // otherwise 9th dot is background
+
+ struct v3_frame_buffer_spec *spec = &(vga->target_spec);
+
+ uint32_t gw, gh; // graphics w/h
+ uint32_t tw, th; // text w/h
+ uint32_t rtw, rth; // rendered text w/h
+ uint32_t cw, ch; // char font w/h including 8/9
+ uint32_t fw, fh; // fb w/h
+
+ uint32_t px, py; // cursor position
+
+ uint32_t x, y, l, p; // text location, line and pixel within the char
+ uint32_t fx, fy; // pixel position within the frame buffer
+
+ uint8_t *text_start;
+ uint8_t *text; // points to current char
+ uint8_t *attr; // and its matching attribute
+ uint8_t *curs; // to where the cursor is
+ uint8_t *font; // to where the current font is
+
+ uint8_t fg_entry; // foreground color entry
+ uint8_t bg_entry; // background color entry
+ uint8_t fgr,fgg,fgb; // looked up foreground colors
+ uint8_t bgr,bgg,bgb; // looked up bg colors
+
+ uint8_t ct, ca; // the current char and attribute
+ struct vga_attribute_byte a; // decoded attribute
- if (fb && s->height>=480 && s->width>=640 ) {
- uint8_t color = (uint8_t)(vga->updates_since_render);
+ void *pixel; // current pixel in the fb
+ uint8_t *red; // and the channels in the pixel
+ uint8_t *green; //
+ uint8_t *blue; //
- uint32_t x, y;
+
+
+ find_graphics_res(vga,&gw,&gh);
+ find_text_res(vga,&tw,&th);
+ find_text_char_dim(vga,&cw,&ch);
+ fw = spec->width;
+ fh = spec->height;
+
+ find_text_cursor_pos(vga,&px,&py,(void**)&curs);
+ find_text_data_start(vga,(void**)&text);
+ find_text_attr_start(vga,(void**)&attr);
+
+ find_text_font_start(vga,(void**)&font,0); // will need to switch this as we go since it is part of attr
+
+ PrintDebug("vga: attempting text render: graphics_res=(%u,%u), fb_res=(%u,%u), text_res=(%u,%u), "
+ "char_res=(%u,%u), cursor=(%u,%u) font=0x%p, text=0x%p, attr=0x%p, curs=0x%p, fb=0x%p"
+ "graphics extension=%u, extended_fontset=%d, blinking=%d\n",
+ gw,gh,fw,fh,tw,th,cw,ch,px,py,font,text,attr,curs,fb,
+ vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code,
+ extended_fontset(vga), blinking(vga));
+
+ text_start=text;
+
+ // First we need to clip to what we can actually show
+ rtw = tw < fw/cw ? tw : fw/cw;
+ rth = th < fh/ch ? th : fh/ch;
+
+
+
+ // Now let's scan by char across the whole thing
+ for (y=0;y<th;y++) {
+ for (x=0;x<tw;x++, text++, attr++) {
+ if (x < rtw && y < rth) {
+ // grab the character and attribute for the position
+ ct = *text;
+ ca = *attr;
+ a.val = ca;
+
+ // find the character's font bitmap (one byte per row)
+ find_text_font_start(vga,(void**)&font,
+ extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 );
+
+ font += ct * ((VGA_MAX_FONT_HEIGHT * VGA_FONT_WIDTH)/8);
+
+ // Now let's find out what colors we will be using
+ // foreground
+
+ if (!extended_fontset(vga)) {
+ fg_entry = ((uint8_t)(a.foreground_intensity_or_font_select)) << 3;
+ } else {
+ fg_entry = 0;
+ }
+ fg_entry |= a.fore;
+
+ dac_lookup_24bit_color(vga,fg_entry,&fgr,&fgg,&fgb);
+
+ if (!blinking(vga)) {
+ bg_entry = ((uint8_t)(a.blinking_or_bg_intensity)) << 3;
+ } else {
+ bg_entry = 0;
+ }
+ bg_entry |= a.back;
+
+ dac_lookup_24bit_color(vga,bg_entry,&bgr,&bgg,&bgb);
+
+ // Draw the character
+ for (l=0; l<ch; l++, font++) {
+ uint8_t frow = *font; // this is the row of of the font map
+ for (p=0;p<cw;p++) {
+ uint8_t fbit;
+
+ // a char can be 9 bits wide, but the font map
+ // is only 8 bits wide, which means we need to know where to
+ // get the 9th bit
+ if (p >= 8) {
+ // We get it from the font map if
+ // its line line graphics mode and its a graphics char
+ // otherwise it's the background color
+ if (vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code
+ && ct>=0xc0 && ct<=0xdf ) {
+ fbit = frow & 0x1;
+ } else {
+ fbit = 0;
+ }
+ } else {
+ fbit= (frow >> (7-p) ) & 0x1;
+ }
+
+ // We are now at the pixel level, with fbit being the pixel we draw (color+attr or bg+attr)
+ // For now, we will draw it as black/white
+
+ // find its position in the framebuffer;
+ fx = x*cw + p;
+ fy = y*ch + l;
+ pixel = fb + ((fx + (fy*spec->width)) * spec->bytes_per_pixel);
+ red = pixel + spec->red_offset;
+ green = pixel + spec->green_offset;
+ blue = pixel + spec->blue_offset;
+
+ // Are we on the cursor?
+ // if so, let's negate this pixel to invert the cell
+ if (curs==text) {
+ fbit^=0x1;
+ }
+ // update the framebuffer
+ if (fbit) {
+ *red=fgr;
+ *green=fgg;
+ *blue=fgb;
+ } else {
+ *red=bgr;
+ *green=bgg;
+ *blue=bgb;
+ }
+ }
+ }
+ }
+ }
+ PrintDebug("\n");
+ }
+
+}
+
+
+
- for (y=0;y<480;y++) {
- for (x=0;x<640;x++) {
- void *pixel = fb + (x + y*s->width) *s->bytes_per_pixel;
+
+static void render_test(struct vga_internal *vga, void *fb)
+{
+ struct v3_frame_buffer_spec *s;
+
+ s=&(vga->target_spec);
+
+ if (fb && s->height>=480 && s->width>=640 ) {
+ uint8_t color = (uint8_t)(vga->updates_since_render);
+
+ uint32_t x, y;
+
+ for (y=0;y<480;y++) {
+ for (x=0;x<640;x++) {
+ void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
+ uint8_t *red = pixel + s->red_offset;
+ uint8_t *green = pixel + s->green_offset;
+ uint8_t *blue = pixel + s->blue_offset;
+
+ if (y<(480/4)) {
+ *red=color+x;
+ *green=0;
+ *blue=0;
+ } else if (y<(480/2)) {
+ *red=0;
+ *green=color+x;
+ *blue=0;
+ } else if (y<(3*(480/4))) {
+ *red=0;
+ *green=0;
+ *blue=color+x;
+ } else {
+ *red=*green=*blue=color+x;
+ }
+ }
+ }
+ }
+}
+
+static void render_maps(struct vga_internal *vga, void *fb)
+{
+
+ struct v3_frame_buffer_spec *s;
+
+
+ s=&(vga->target_spec);
+
+ if (fb && s->height>=768 && s->width>=1024 && !(vga->updates_since_render % 100)) {
+ // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
+ uint8_t m;
+ uint32_t x,y;
+ uint8_t *b;
+
+ for (m=0;m<4;m++) {
+ b=(vga->map[m]);
+ for (y=480+32;y<768;y++) {
+ for (x=m*256;x<(m+1)*256;x++,b++) {
+ void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
uint8_t *red = pixel + s->red_offset;
uint8_t *green = pixel + s->green_offset;
uint8_t *blue = pixel + s->blue_offset;
-
- if (y<480/4) {
- *red=color+x;
- *green=0;
- *blue=0;
- } else if (y<480/2) {
- *red=0;
- *green=color+x;
- *blue=0;
- } else if (y<3*480/4) {
- *red=0;
- *green=0;
- *blue=color+x;
- } else {
- *red=*green=*blue=color+x;
- }
+
+ *red=*green=*blue=*b;
}
}
}
}
+}
+
+
+static int render(struct vga_internal *vga)
+{
+ void *fb;
+
+
+ vga->updates_since_render++;
+
+ if (vga->updates_since_render%100) {
+ // skip render
+ return 0;
+ }
+
+ if (vga->host_cons && v3_graphics_console_inform_update(vga->host_cons)>0) {
+
+ fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
+
+ // Draw some crap for testing for now
+ if (0) { render_test(vga,fb);}
+ // Draw the maps for debugging
+ if (0) { render_maps(vga,fb);}
+
+ if (vga->vga_graphics_controller.vga_misc.graphics_mode) {
+ render_graphics(vga,fb);
+ } else {
+ render_text(vga,fb);
+ render_text_cursor(vga,fb);
+ }
+
+ render_maps(vga,fb);
+
+
+ v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
+ }
return 0;
}
}
}
-static uint64_t find_offset(struct vga_internal *vga, addr_t guest_addr)
+static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
{
uint64_t mem_start, mem_end;
+ uint64_t size;
mem_start=mem_end=0;
get_mem_region(vga, &mem_start, &mem_end);
+
+ size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
- return (guest_addr-mem_start) % (mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
-
+ if (vga->vga_sequencer.vga_mem_mode.odd_even) {
+ return (guest_addr-mem_start) % size;
+ } else {
+ // odd/even mode
+ return ((guest_addr-mem_start) >> 1 ) % size;
+ }
}
+
+
+// Determines which maps should be enabled for this single byte write
+// and what the increment (actually 1/increment for the copy loop
+//
+// memory_mode.odd_even == 0 => even address = maps 0 and 2 enabled; 1,3 otherwise
+//
+static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
+{
+ uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
+
+ if (vga->vga_sequencer.vga_mem_mode.odd_even) {
+ return mm;
+ } else {
+ if (guest_addr & 0x1) {
+ return mm & 0xa; // 0x1010
+ } else {
+ return mm & 0x5; // 0x0101
+ }
+ }
+}
+
+static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
+{
+ if (vga->vga_sequencer.vga_mem_mode.odd_even) {
+ return 1;
+ } else {
+ return !(new_guest_addr & 0x1);
+ }
+}
+
static int vga_write(struct guest_info * core,
uint_t length,
void * priv_data)
{
- int i;
struct vm_device *dev = (struct vm_device *)priv_data;
struct vga_internal *vga = (struct vga_internal *) dev->private_data;
memcpy(V3_VAddr((void*)guest_addr),src,length);
}
- PrintDebug("vga: data written was \"");
+#if 0
+ int i;
+ PrintDebug("vga: data written was 0x");
+ for (i=0;i<length;i++) {
+ uint8_t c= ((char*)src)[i];
+ PrintDebug("%.2x", c);
+ }
+ PrintDebug(" \"");
for (i=0;i<length;i++) {
char c= ((char*)src)[i];
- PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') ? c : '.');
+ PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
}
PrintDebug("\"\n");
+#endif
/* Write mode determine by Graphics Mode Register (Index 05h).writemode */
-
+
+ // Probably need to add odd/even mode access here for text
+
+ PrintDebug("vga: write is with odd/even = %u\n", vga->vga_sequencer.vga_mem_mode.odd_even);
+
+
switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
case 0: {
uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
- offset = find_offset(vga, guest_addr);
+ offset = find_offset_write(vga, guest_addr);
PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
- for (i=0;i<length;i++,offset++) {
+ for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
// now for each map
uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
- uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
+ uint8_t mm = find_map_write(vga,guest_addr+i);
+
+ PrintDebug("vga: write i=%u, mm=0x%x, offset=0x%x\n",i,(unsigned int)mm,(unsigned int)offset);
for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, bm>>=1, mm>>=1) {
vga_map map = vga->map[mapnum];
int i;
- uint64_t offset = find_offset(vga,guest_addr);
+ uint64_t offset = find_offset_write(vga,guest_addr);
PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
- for (i=0;i<length;i++,offset++) {
+ for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
uint8_t mapnum;
- uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
+ uint8_t mm = find_map_write(vga,guest_addr+i);
for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
vga_map map = vga->map[mapnum];
uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
- offset = find_offset(vga, guest_addr);
+ offset = find_offset_write(vga, guest_addr);
PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
- for (i=0;i<length;i++,offset++) {
+ for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
// now for each map
uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
- uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
+ uint8_t mm = find_map_write(vga,guest_addr+i);
for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
vga_map map = vga->map[mapnum];
uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
- offset = find_offset(vga, guest_addr);
+ offset = find_offset_write(vga, guest_addr);
PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
- for (i=0;i<length;i++,offset++) {
+ for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
// now for each map
uint8_t data = ((uint8_t *)src)[i];
uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
- uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
+ uint8_t mm = find_map_write(vga,guest_addr+i);
for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
vga_map map = vga->map[mapnum];
}
-/*
-up to 256K mapped through a window of 32 to 128K
-
-most cards support linear mode as well
-
-Need to implement readability too
-
-Write extended memory bit to enable all 256K:
-
- Sequencer Memory Mode Register (Index 04h) . extended memory
-
-Must enable writes before effects happen:
-
- Miscellaneous Output Register (Read at 3CCh, Write at 3C2h).ram enable
-
-Choose which addresses are supported for CPU writes:
-
-Miscellaneous Graphics Register (Index 06h).memory map select
-
-00b -- A0000h-BFFFFh (128K region)
-01b -- A0000h-AFFFFh (64K region)
-10b -- B0000h-B7FFFh (32K region)
-11b -- B8000h-BFFFFh (32K region)
-
-There are three addressing modes: Chain 4, Odd/Even mode, and normal mode:
-
-Chain 4: This mode is used for MCGA emulation in the 320x200 256-color mode. The address is mapped to memory MOD 4 (shifted right 2 places.)
-
-Memory model: 64K 32 bit locations; divided into 4 64K bit planes
-
-
-
+static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
+{
+ uint64_t mem_start, mem_end;
+ uint64_t size;
+
+ mem_start=mem_end=0;
+
+ get_mem_region(vga, &mem_start, &mem_end);
+
+ size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
-Assume linear framebuffer, starting at address buf:
+ if (!vga->vga_sequencer.vga_mem_mode.chain4) {
+ return (guest_addr-mem_start) % size;
+ } else {
+ // chain4 mode
+ return ((guest_addr - mem_start) >> 2) % size;
+ }
+}
-*/
+static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
+{
+ if (vga->vga_sequencer.vga_mem_mode.chain4) {
+ return !(new_guest_addr & 0x3);
+ } else {
+ return 1;
+ }
+}
static int vga_read(struct guest_info * core,
uint_t length,
void * priv_data)
{
- int i;
struct vm_device *dev = (struct vm_device *)priv_data;
struct vga_internal *vga = (struct vga_internal *) dev->private_data;
PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
-
-
+
/*
Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
uint8_t mapnum;
uint64_t offset;
-
- mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
- offset = find_offset(vga,guest_addr);
-
- if (offset>=65536) {
- PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
- }
- memcpy(dst,(vga->map[mapnum])+offset,length);
- // load the latches with the last item read
- for (mapnum=0;mapnum<4;mapnum++) {
- vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
+ if (vga->vga_sequencer.vga_mem_mode.chain4) {
+ uint32_t i;
+ offset = find_offset_read(vga,guest_addr);
+ // address bytes select the map
+ for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
+ mapnum = (guest_addr+i) % 4;
+ ((uint8_t*)dst)[i] = vga->latch[mapnum] = *(vga->map[mapnum]+offset);
+ }
+ } else {
+ mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
+ offset = find_offset_read(vga,guest_addr);
+
+ if (offset>=65536) {
+ PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
+ }
+
+ memcpy(dst,(vga->map[mapnum])+offset,length);
+
+ // load the latches with the last item read
+ for (mapnum=0;mapnum<4;mapnum++) {
+ vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
+ }
}
-
}
break;
uint8_t byte;
uint8_t bits;
- offset = find_offset(vga,guest_addr);
+ offset = find_offset_read(vga,guest_addr);
for (i=0;i<length;i++,offset++) {
vga_map map;
}
- PrintDebug("vga: data read is \"");
+#if 0
+ int i;
+ PrintDebug("vga: data read is 0x");
+ for (i=0;i<length;i++) {
+ uint8_t c= ((char*)dst)[i];
+ PrintDebug("%.2x", c);
+ }
+ PrintDebug(" \"");
for (i=0;i<length;i++) {
char c= ((char*)dst)[i];
- PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') ? c : '.');
+ PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
}
PrintDebug("\"\n");
+#endif
return length;
// This is red, green, blue
typedef uint32_t vga_palette_reg;
+
+//
+// What attribute bytes mean in text mode
+//
+struct vga_attribute_byte {
+ union {
+ uint8_t val;
+ struct {
+ union {
+ uint8_t fore:3;
+ struct {
+ uint8_t fore_red:1;
+ uint8_t fore_green:1;
+ uint8_t fore_blue:1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+ uint8_t foreground_intensity_or_font_select:1; // depends on char map select reg
+ // character map selection is effected
+ // when memory_mode.extended meomory=1
+ // and the two character map enteries on character_map_select are
+ // different
+ union {
+ uint8_t back:3;
+ struct {
+ uint8_t back_red:1;
+ uint8_t back_green:1;
+ uint8_t back_blue:1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+ uint8_t blinking_or_bg_intensity:1;
+ // attribute mode control.enableblink = 1 => blink
+ // =0 => intensity (16 colors of bg)
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
#endif
--- /dev/null
+menu "Host Interfaces"
+
+config FILE
+ bool "Host Support for file operations"
+ default n
+ help
+ Select this if your host OS supports file operatoins and you want Palacios to be able to use them.
+
+config KEYED_STREAMS
+ bool "Host support for keyed streams"
+ default n
+ help
+ Select this if your host OS supports keyed streams
+ Palacios Checkpoint/Restore and Migration depends on this feature
+
+config STREAM
+ bool "Stream support"
+ default n
+
+
+config CONSOLE
+ bool "Host Support for VM text-mode console"
+ default n
+ help
+ Select this if you want to forward a guest console interface to some host OS service
+ This is for a TEXT MODE console. Select the framebuffer console for graphics and text
+
+config GRAPHICS_CONSOLE
+ bool "Host Support for VM graphics and text-mode console based on a frame buffer"
+ default n
+ help
+ Select this if you want to forward a guest graphics-mode (and text-mode) console
+ interface to some host OS service. This is for a GRAPHICS console based on a shared frame buffer.
+ Text mode output is RENDERED onto the framebuffer
+
+config SOCKET
+ bool "Host support for Network Sockets"
+ default y
+ help
+ Select this if you host OS implements a socket API that is available to Palacios. This is required
+ to support the internal networking features of Palacios.
+
+
+config PACKET
+ bool "Host support for Raw Packet Transmision"
+ depends on EXPERIMENTAL
+ default n
+ help
+ Select this if you host OS implements a raw packet network API that is available to Palacios. This is required
+ to support the internal networking features of Palacios.
+
+
+endmenu
--- /dev/null
+obj-$(CONFIG_SOCKET) += vmm_socket.o
+obj-$(CONFIG_PACKET) += vmm_packet.o
+obj-$(CONFIG_FILE) += vmm_file.o
+obj-$(CONFIG_CONSOLE) += vmm_console.o
+obj-$(CONFIG_STREAM) += vmm_stream.o
+obj-$(CONFIG_GRAPHICS_CONSOLE) += vmm_graphics_console.o
+obj-$(CONFIG_KEYED_STREAMS) += vmm_keyed_stream.o
+
+
*/
-#include <palacios/vmm_console.h>
+#include <interfaces/vmm_console.h>
#include <palacios/vmm.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_types.h>
*/
-#include <palacios/vmm_file.h>
+#include <interfaces/vmm_file.h>
#include <palacios/vmm.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_types.h>
*/
-#include <palacios/vmm_graphics_console.h>
+#include <interfaces/vmm_graphics_console.h>
#include <palacios/vmm.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_types.h>
*/
-#include <palacios/vmm_keyed_stream.h>
+#include <interfaces/vmm_keyed_stream.h>
#include <palacios/vmm.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_types.h>
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "V3VEE_LICENSE".
*/
-#include <palacios/vmm.h>
+
+#include <interfaces/vmm.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_types.h>
#include <palacios/vm_guest.h>
*/
-#include <palacios/vmm_socket.h>
+#include <interfaces/vmm_socket.h>
#include <palacios/vmm.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_types.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_types.h>
-#include <palacios/vmm_stream.h>
+#include <interfaces/vmm_stream.h>
#include <palacios/vm_guest.h>
static struct v3_stream_hooks * stream_hooks = NULL;
obj-$(CONFIG_INSTRUMENT_VMM) += vmm_instrument.o
obj-$(CONFIG_TELEMETRY) += vmm_telemetry.o
-obj-$(CONFIG_SOCKET) += vmm_socket.o
-obj-$(CONFIG_PACKET) += vmm_packet.o
+
obj-$(CONFIG_VNET) += vmm_vnet_core.o
-obj-$(CONFIG_FILE) += vmm_file.o
-obj-$(CONFIG_CONSOLE) += vmm_console.o vmm_stream.o
-obj-$(CONFIG_GRAPHICS_CONSOLE) += vmm_graphics_console.o
-obj-$(CONFIG_KEYED_STREAMS) += vmm_keyed_stream.o
obj-$(CONFIG_SYMBIOTIC) += vmm_symbiotic.o vmm_symspy.o
#include <palacios/vmm_host_events.h>
-#include <palacios/vmm_socket.h>
#include "vmm_config_class.h"
int emulation_length = op_size * rep_cnt;
struct rflags * flags_reg = (struct rflags *)&(core->ctrl_regs.rflags);
+
+ PrintError("Emulation_len=%d, tmp_rcx=%d\n", emulation_length, (uint_t)tmp_rcx);
+
+
if (instr->op_type == V3_OP_MOVS) {
if (op_size== 1) {
movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
return -1;
}
+
+
if (flags_reg->df == 0) {
core->vm_regs.rdi += emulation_length;
} else {
addr_t src_hva = 0;
addr_t dst_hva = 0;
-
- PrintError("USING THE NEW EMULATOR\n");
+
if (instr->src_operand.type == MEM_OPERAND) {
src_hva = mem_hva_src;
} else {
src_hva = (addr_t)&(instr->src_operand.operand);
}
-
+
if (instr->dst_operand.type == MEM_OPERAND) {
dst_hva = mem_hva_dst;
} else if (instr->dst_operand.type == REG_OPERAND) {
} else {
dst_hva = (addr_t)&(instr->dst_operand.operand);
}
-
+
if (instr->is_str_op == 0) {
int src_op_len = instr->src_operand.size;
}
-
return -1;
}
}
+
// Test source operand, if it's memory we need to do some translations, and handle a possible hook
if (instr.src_operand.type == MEM_OPERAND) {
struct v3_mem_region * src_reg = NULL;
}
}
- if ((guest_pa >= reg->guest_start) &&
- (guest_pa <= reg->guest_end)) {
+ if ((src_mem_op_gpa >= reg->guest_start) &&
+ (src_mem_op_gpa < reg->guest_end)) {
// Src address corresponds to faulted region
src_reg = reg;
} else {
}
}
- if ((guest_pa >= reg->guest_start) &&
- (guest_pa <= reg->guest_end)) {
+ if ((dst_mem_op_gpa >= reg->guest_start) &&
+ (dst_mem_op_gpa < reg->guest_end)) {
// Dst address corresponds to faulted region
dst_reg = reg;
} else {
#define MASK(val, length) ({ \
- ullong_t mask = 0x0LL; \
+ uint64_t mask = 0x0LL; \
switch (length) { \
case 1: \
mask = 0x00000000000000ffLL; \
form = op_code_to_form((uint8_t *)(instr_ptr + length), &length);
-
V3_Print("\t decoded as (%s)\n", op_form_to_str(form));
if (form == INVALID_INSTR) {
return -1;
}
length += ret;
-
instr->instr_length += length;
-
v3_print_instr(instr);
return 0;
break;
}
+ case MOVSX_8:
+ case MOVZX_8: {
+ uint8_t reg_code = 0;
+
+ ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->src_operand), ®_code);
+ instr->src_operand.size = 1;
+
+ if (ret == -1) {
+ PrintError("Error decoding operand\n");
+ return -1;
+ }
+
+ instr_ptr += ret;
+
+ instr->dst_operand.size = operand_width;
+ instr->dst_operand.type = REG_OPERAND;
+ decode_gpr(core, reg_code, &(instr->dst_operand));
+
+ instr->src_operand.read = 1;
+ instr->dst_operand.write = 1;
+
+ instr->num_operands = 2;
+
+ break;
+ }
+ case MOVSX:
+ case MOVZX: {
+ uint8_t reg_code = 0;
+
+ ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->src_operand), ®_code);
+ instr->src_operand.size = 2;
+
+ if (ret == -1) {
+ PrintError("Error decoding operand\n");
+ return -1;
+ }
+
+ instr_ptr += ret;
+
+ instr->dst_operand.size = operand_width;
+ instr->dst_operand.type = REG_OPERAND;
+ decode_gpr(core, reg_code, &(instr->dst_operand));
+
+ instr->src_operand.read = 1;
+ instr->dst_operand.write = 1;
+
+ instr->num_operands = 2;
+
+ break;
+ }
case ADC_IMM2SX_8:
case ADD_IMM2SX_8:
case AND_IMM2SX_8:
ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), ®_code);
-
if (ret == -1) {
PrintError("Error decoding operand\n");
return -1;
instr->src_operand.type = IMM_OPERAND;
instr->src_operand.size = operand_width;
- instr->src_operand.operand = *(sint8_t *)instr_ptr; // sign extend.
+ instr->src_operand.operand = (addr_t)MASK((sint64_t)*(sint8_t *)instr_ptr, operand_width); // sign extend.
instr->src_operand.read = 1;
instr->dst_operand.write = 1;
instr->num_operands = 2;
break;
+ }
+ case MOV_2CR: {
+ uint8_t reg_code = 0;
+
+ ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->src_operand),
+ ®_code);
- case MOV_2CR: {
- uint8_t reg_code = 0;
-
- ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->src_operand),
- ®_code);
-
- if (ret == -1) {
- PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
- return -1;
- }
-
- instr_ptr += ret;
-
- instr->dst_operand.type = REG_OPERAND;
- instr->dst_operand.size = operand_width;
- decode_cr(core, reg_code, &(instr->dst_operand));
-
- instr->src_operand.read = 1;
- instr->dst_operand.write = 1;
-
- instr->num_operands = 2;
- break;
+ if (ret == -1) {
+ PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
+ return -1;
}
- case MOV_CR2: {
- uint8_t reg_code = 0;
-
- ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand),
- ®_code);
-
-
- if (ret == -1) {
- PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
- return -1;
- }
-
- instr_ptr += ret;
- instr->src_operand.type = REG_OPERAND;
- instr->src_operand.size = operand_width;
- decode_cr(core, reg_code, &(instr->src_operand));
+ instr_ptr += ret;
- instr->src_operand.read = 1;
- instr->dst_operand.write = 1;
+ instr->dst_operand.type = REG_OPERAND;
+ instr->dst_operand.size = operand_width;
+ decode_cr(core, reg_code, &(instr->dst_operand));
+
+ instr->src_operand.read = 1;
+ instr->dst_operand.write = 1;
- instr->num_operands = 2;
- break;
+ instr->num_operands = 2;
+ break;
+ }
+ case MOV_CR2: {
+ uint8_t reg_code = 0;
+
+ ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand),
+ ®_code);
+
+ if (ret == -1) {
+ PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
+ return -1;
}
- case STOS:
- case STOS_8: {
- instr->is_str_op = 1;
-
- if (instr->prefixes.rep == 1) {
- instr->str_op_length = MASK(core->vm_regs.rcx, operand_width);
- } else {
- instr->str_op_length = 1;
- }
-
- instr->src_operand.size = operand_width;
- instr->src_operand.type = REG_OPERAND;
- instr->src_operand.operand = (addr_t)&(core->vm_regs.rax);
- instr->dst_operand.type = MEM_OPERAND;
- instr->dst_operand.size = operand_width;
- instr->dst_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
+ instr_ptr += ret;
+
+ instr->src_operand.type = REG_OPERAND;
+ instr->src_operand.size = operand_width;
+ decode_cr(core, reg_code, &(instr->src_operand));
- instr->src_operand.read = 1;
- instr->dst_operand.write = 1;
+ instr->src_operand.read = 1;
+ instr->dst_operand.write = 1;
- instr->num_operands = 2;
+ instr->num_operands = 2;
+ break;
+ }
+ case STOS:
+ case STOS_8: {
+ instr->is_str_op = 1;
- break;
+ if (instr->prefixes.rep == 1) {
+ instr->str_op_length = MASK(core->vm_regs.rcx, operand_width);
+ } else {
+ instr->str_op_length = 1;
}
- case INVLPG: {
- uint8_t reg_code = 0;
- ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), ®_code);
+ instr->src_operand.size = operand_width;
+ instr->src_operand.type = REG_OPERAND;
+ instr->src_operand.operand = (addr_t)&(core->vm_regs.rax);
- if (ret == -1) {
- PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
- return -1;
- }
+ instr->dst_operand.type = MEM_OPERAND;
+ instr->dst_operand.size = operand_width;
+ instr->dst_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
- instr_ptr += ret;
+ instr->src_operand.read = 1;
+ instr->dst_operand.write = 1;
- instr->num_operands = 1;
- break;
- }
- case CLTS: {
- // no operands.
- break;
+ instr->num_operands = 2;
+ break;
+ }
+ case INVLPG: {
+ uint8_t reg_code = 0;
+
+ ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), ®_code);
+
+ if (ret == -1) {
+ PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
+ return -1;
}
+
+ instr_ptr += ret;
+
+ instr->num_operands = 1;
+ break;
+ }
+ case CLTS: {
+ // no operands.
+ break;
+
}
default:
PrintError("Invalid Instruction form: %s\n", op_form_to_str(form));
xed_decoded_inst_t xed_instr;
xed_error_enum_t xed_error;
+ memset(instr, 0, sizeof(struct x86_instr));
+
v3_get_prefixes((uchar_t *)instr_ptr, &(instr->prefixes));
v3_op = &(instr->dst_operand);
- if ((op->_rw == XED_OPERAND_ACTION_RW) ||
- (op->_rw == XED_OPERAND_ACTION_R)||
- (op->_rw == XED_OPERAND_ACTION_RCW)) {
- v3_op->read = 1;
- }
-
- if ((op->_rw == XED_OPERAND_ACTION_RW) ||
- (op->_rw == XED_OPERAND_ACTION_W) ||
- (op->_rw == XED_OPERAND_ACTION_CRW)) {
- v3_op->write = 1;
- }
-
if (xed_operand_is_register(op_enum)) {
xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
int v3_reg_type = xed_reg_to_v3_reg(info,
return -1;
}
}
+
+ V3_Print("Operand 0 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op)));
+
+
+ if (xed_operand_read(op)) {
+ v3_op->read = 1;
+ }
+
+ if (xed_operand_written(op)) {
+ v3_op->write = 1;
+ }
+
}
// set second operand
*/
v3_op = &(instr->src_operand);
- if ((op->_rw == XED_OPERAND_ACTION_RW) ||
- (op->_rw == XED_OPERAND_ACTION_R)||
- (op->_rw == XED_OPERAND_ACTION_RCW)) {
- v3_op->read = 1;
- }
-
- if ((op->_rw == XED_OPERAND_ACTION_RW) ||
- (op->_rw == XED_OPERAND_ACTION_W) ||
- (op->_rw == XED_OPERAND_ACTION_CRW)) {
- v3_op->write = 1;
- }
if (xed_operand_is_register(op_enum)) {
xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
return -1;
}
}
+
+ V3_Print("Operand 1 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op)));
+
+ if (xed_operand_read(op)) {
+ v3_op->read = 1;
+ }
+
+ if (xed_operand_written(op)) {
+ v3_op->write = 1;
+ }
+
}
// set third operand
xed_operand_type_enum_t op_type = xed_operand_type(op);
xed_operand_enum_t op_enum = xed_operand_name(op);
- if ((op->_rw == XED_OPERAND_ACTION_RW) ||
- (op->_rw == XED_OPERAND_ACTION_R)||
- (op->_rw == XED_OPERAND_ACTION_RCW)) {
- instr->third_operand.read = 1;
- }
- if ((op->_rw == XED_OPERAND_ACTION_RW) ||
- (op->_rw == XED_OPERAND_ACTION_W) ||
- (op->_rw == XED_OPERAND_ACTION_CRW)) {
- instr->third_operand.write = 1;
- }
if (xed_operand_is_register(op_enum)) {
xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
instr->third_operand.type = REG_OPERAND;
+ PrintDebug("Operand 3 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op)));
+
+
+ if (xed_operand_read(op)) {
+ instr->third_operand.read = 1;
+ }
+
+ if (xed_operand_written(op)) {
+ instr->third_operand.write = 1;
+ }
+
} else {
PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
instr->num_operands = 2;