bool "Linux 2.6"
select BUILT_IN_STDLIB
select BUILT_IN_ATOI
+ select FILE
help
This enables the necessary options to compile Palacios with Linux 2.6
Currently, this is in development, and only 2.6.32 is verified to work
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 CONSOLE
bool "Host Support for VM console"
v3_paging_mode_t shdw_pg_mode;
struct v3_shdw_pg_state shdw_pg_state;
addr_t direct_map_pt;
+
+
+ union {
+ uint32_t flags;
+ struct {
+ uint8_t use_large_pages : 1; /* Enable virtual page tables to use large pages */
+ uint32_t rsvd : 31;
+ } __attribute__((packed));
+ } __attribute__((packed));
- // This structure is how we get interrupts for the guest
+
+ /* This structure is how we get interrupts for the guest */
struct v3_intr_core_state intr_core_state;
- // This structure is how we get exceptions for the guest
+ /* This structure is how we get exceptions for the guest */
struct v3_excp_state excp_state;
#endif
- // struct v3_core_dev_mgr core_dev_mgr;
+ /* struct v3_core_dev_mgr core_dev_mgr; */
void * decoder_state;
#ifdef CONFIG_SYMBIOTIC
- // Symbiotic state
+ /* Symbiotic state */
struct v3_sym_core_state sym_core_state;
#endif
struct v3_vm_info * vm_info;
- // the logical cpu on which this core runs
+ /* the logical cpu on which this core runs */
uint32_t cpu_id;
};
struct v3_vm_info {
v3_vm_class_t vm_class;
- addr_t mem_size; // In bytes for now
+ addr_t mem_size; /* In bytes for now */
+ uint32_t mem_align;
struct v3_mem_map mem_map;
v3_paging_size_t paging_size; // for nested paging
struct v3_intr_routers intr_routers;
- // device_map
+
+ /* device_map */
struct vmm_dev_mgr dev_mgr;
struct v3_host_events host_event_hooks;
v3_vm_operating_mode_t run_state;
#ifdef CONFIG_SYMBIOTIC
- // Symbiotic state
+ /* Symbiotic state */
struct v3_sym_vm_state sym_vm_state;
#endif
void v3_print_stack(struct guest_info * info);
-#endif // ! __V3VEE__
+#endif /* ! __V3VEE__ */
#endif
void *(*vaddr_to_paddr)(void *addr);
int (*hook_interrupt)(struct v3_vm_info * vm, unsigned int irq);
-
int (*ack_irq)(int irq);
unsigned int (*get_cpu_khz)(void);
void Init_V3(struct v3_os_hooks * hooks, int num_cpus);
-int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask);
struct v3_vm_info * v3_create_vm(void * cfg);
+int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask);
+
int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr);
--- /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) 2010, Peter Dinda (pdinda@cs.northwestern.edu>
+ * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Peter Dinda <pdinda@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __VMM_FILE_H__
+#define __VMM_FILE_H__
+
+#include <palacios/vmm.h>
+
+
+#ifdef __V3VEE__
+
+#define V3_FileOpen(path, mode) \
+ ({ \
+ extern struct v3_file_hooks *file_hooks; \
+ ((file_hooks) && (file_hooks)->file_open) ? \
+ (file_hooks)->file_open((path), (mode)) : -1 ; \
+ })
+
+#define V3_FileClose(fd) \
+ ({ \
+ extern struct v3_file_hooks *file_hooks; \
+ ((file_hooks) && (file_hooks)->file_close) ? \
+ (file_hooks)->file_close((fd)) : -1 ; \
+ })
+
+#define V3_FileSize(fd) \
+ ({ \
+ extern struct v3_file_hooks *file_hooks; \
+ ((file_hooks) && (file_hooks)->file_size) ? \
+ (file_hooks)->file_size((fd)) : -1 ; \
+ })
+
+#define V3_FileRead(fd,start,buf,len) \
+ ({ \
+ extern struct v3_file_hooks *file_hooks; \
+ ((file_hooks) && (file_hooks)->file_read) ? \
+ (file_hooks)->file_read((fd),(start),(buf),(len)) : -1 ; \
+ })
+
+#define V3_FileWrite(fd,start,buf,len) \
+ ({ \
+ extern struct v3_file_hooks *file_hooks; \
+ ((file_hooks) && (file_hooks)->file_write) ? \
+ (file_hooks)->file_write((fd),(start),(buf),(len)) : -1 ; \
+ })
+
+
+#endif
+
+#define FILE_OPEN_MODE_READ (1 << 0)
+#define FILE_OPEN_MODE_WRITE (1 << 1)
+
+struct v3_file_hooks {
+
+ int (*file_open)(const char *path, int mode);
+ int (*file_close)(int fd);
+
+ long long (*file_size)(int fd);
+
+ // blocking reads and writes
+ long long (*file_read)(int fd, long long start, void *buffer, long long length);
+ long long (*file_write)(int fd, long long start, void *buffer, long long length);
+
+};
+
+
+extern void V3_Init_File(struct v3_file_hooks * hooks);
+
+#endif
void v3_print_mem_map(struct v3_vm_info * vm);
-
-
+uint32_t v3_get_max_page_size(struct guest_info * core, addr_t fault_addr, uint32_t req_size);
+uint32_t v3_compute_page_alignment(addr_t addr);
#endif // ! __V3VEE__
struct {
uint8_t pci_map_valid : 1;
uint8_t symmod_enabled : 1;
+ uint8_t sec_symmod_enabled : 1;
} __attribute__((packed));
} __attribute__((packed));
#define CHANNEL1_PORT 0x41
#define CHANNEL2_PORT 0x42
#define COMMAND_PORT 0x43
+#define SPEAKER_PORT 0x61
#define PIT_INTR_NUM 0
+#define PIT_SPEAKER_GATE 0x01
/* The order of these typedefs is important because the numerical values correspond to the
* values coming from the io ports
struct channel ch_0;
struct channel ch_1;
struct channel ch_2;
+ uint8_t speaker;
};
}
//handle_crystal_tics(dev, &(state->ch_1), oscillations);
- //handle_crystal_tics(dev, &(state->ch_2), oscillations);
+ handle_crystal_tics(dev, &(state->ch_2), oscillations);
}
}
+static int handle_speaker_read(uint8_t *speaker, struct channel * ch, char * val) {
+ *val = *speaker;
+ if ((*speaker & PIT_SPEAKER_GATE)) {
+ *val |= (ch->output_pin << 5);
+ }
+
+ return 0;
+}
-
+static int handle_speaker_write(uint8_t *speaker, struct channel * ch, char val) {
+ *speaker = (val & ~0x20);
+ return 0;
+}
static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
ch->op_mode = cmd.op_mode;
return -1;
}
break;
+ case SPEAKER_PORT:
+ if (handle_speaker_read(&state->speaker, &(state->ch_2), val) == -1) {
+ PrintError("SPEAKER read error\n");
+ return -1;
+ }
+ break;
default:
PrintError("8254 PIT: Read from invalid port (%d)\n", port);
return -1;
return -1;
}
break;
+ case SPEAKER_PORT:
+ if (handle_speaker_write(&state->speaker, &(state->ch_2), val) == -1) {
+ PrintError("SPEAKER write error\n");
+ return -1;
+ }
+ break;
default:
PrintError("8254 PIT: Write to invalid port (%d)\n", port);
return -1;
static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct pit * pit_state = NULL;
struct vm_device * dev = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
// PIT is only usable in non-multicore environments
// just hardcode the core context
pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
V3_ASSERT(pit_state != NULL);
+ pit_state->speaker = 0;
- dev = v3_allocate_device(name, &dev_ops, pit_state);
+ dev = v3_allocate_device(dev_id, &dev_ops, pit_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
+ v3_dev_hook_io(dev, SPEAKER_PORT, &pit_read_channel, &pit_write_channel);
#ifdef CONFIG_DEBUG_PIT
PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
static int pic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct pic_internal * state = NULL;
state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
// PIC is only usable in non-multicore environments
// just hardcode the core context
V3_ASSERT(state != NULL);
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
config APIC
bool "APIC"
default y
- depends on ICC_BUS
+ depends on ICC_BUS && EXPERIMENTAL
help
Includes the Virtual APIC device
config IO_APIC
bool "IOAPIC"
- depends on ICC_BUS
+ depends on ICC_BUS && EXPERIMENTAL
default y
help
Includes the Virtual IO APIC
config ICC_BUS
bool "ICC BUS"
default y
+ depends on EXPERIMENTAL
help
The ICC Bus for APIC/IOAPIC communication
help
Enable debugging for the PIT
+config FILEDISK
+ bool "FILEDISK storage backend"
+ default y
+ depends on FILE && (IDE || LINUX_VIRTIO_BLOCK)
+ help
+ Includes the file based disk backend
+
config NETDISK
bool "NETDISK storage backend"
obj-$(CONFIG_TMPDISK) += tmpdisk.o
obj-$(CONFIG_RAMDISK) += ramdisk.o
obj-$(CONFIG_NETDISK) += netdisk.o
+obj-$(CONFIG_FILEDISK) += filedisk.o
obj-$(CONFIG_CGA) += cga.o
obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o
#define APIC_EXTINT_DELIVERY 0x7
-#define BASE_ADDR_MSR 0x0000001B
+#define BASE_ADDR_MSR 0x0000001B
#define DEFAULT_BASE_ADDR 0xfee00000
#define APIC_ID_OFFSET 0x020
union {
uint64_t value;
struct {
- uchar_t rsvd;
- uint_t bootstrap_cpu : 1;
- uint_t rsvd2 : 2;
- uint_t apic_enable : 1;
- ullong_t base_addr : 40;
- uint_t rsvd3 : 12;
+ uint8_t rsvd;
+ uint8_t bootstrap_cpu : 1;
+ uint8_t rsvd2 : 2;
+ uint8_t apic_enable : 1;
+ uint64_t base_addr : 40;
+ uint32_t rsvd3 : 12;
} __attribute__((packed));
} __attribute__((packed));
} __attribute__((packed));
uint32_t rem_rd_data;
- uchar_t int_req_reg[32];
- uchar_t int_svc_reg[32];
- uchar_t int_en_reg[32];
- uchar_t trig_mode_reg[32];
+ uint8_t int_req_reg[32];
+ uint8_t int_svc_reg[32];
+ uint8_t int_en_reg[32];
+ uint8_t trig_mode_reg[32];
uint32_t eoi;
static void init_apic_state(struct apic_state * apic, uint32_t id, struct vm_device * icc) {
apic->base_addr = DEFAULT_BASE_ADDR;
- if (id==0) {
+
+ if (id == 0) {
// boot processor, enabled
apic->base_addr_msr.value = 0x0000000000000900LL;
} else {
struct apic_state * apics = (struct apic_state *)(dev->private_data);
struct apic_state * apic = &(apics[core->cpu_id]);
- PrintDebug("apic %u: core %u: MSR read\n",apic->lapic_id.val,core->cpu_id);
+ PrintDebug("apic %u: core %u: MSR read\n", apic->lapic_id.val, core->cpu_id);
v3_lock(apic->lock);
dst->value = apic->base_addr;
v3_unlock(apic->lock);
if (old_reg == NULL) {
// uh oh...
- PrintError("apic %u: core %u: APIC Base address region does not exit...\n",apic->lapic_id.val,core->cpu_id);
+ PrintError("apic %u: core %u: APIC Base address region does not exit...\n",
+ apic->lapic_id.val, core->cpu_id);
return -1;
}
apic->base_addr = src.value;
if (v3_hook_full_mem(dev->vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev) == -1) {
- PrintError("apic %u: core %u: Could not hook new APIC Base address\n",apic->lapic_id.val,core->cpu_id);
+ PrintError("apic %u: core %u: Could not hook new APIC Base address\n",
+ apic->lapic_id.val, core->cpu_id);
v3_unlock(apic->lock);
return -1;
}
static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
int major_offset = (irq_num & ~0x00000007) >> 3;
int minor_offset = irq_num & 0x00000007;
- uchar_t * req_location = apic->int_req_reg + major_offset;
- uchar_t * en_location = apic->int_en_reg + major_offset;
- uchar_t flag = 0x1 << minor_offset;
+ uint8_t * req_location = apic->int_req_reg + major_offset;
+ uint8_t * en_location = apic->int_en_reg + major_offset;
+ uint8_t flag = 0x1 << minor_offset;
-#if 1
if (irq_num <= 15) {
- PrintError("apic %u: core ?: Attempting to raise an invalid interrupt: %d\n", apic->lapic_id.val,irq_num);
+// PrintError("apic %u: core ?: Attempting to raise an invalid interrupt: %d\n", apic->lapic_id.val,irq_num);
return -1;
}
-#endif
-
- PrintDebug("apic %u: core ?: Raising APIC IRQ %d\n", apic->lapic_id.val,irq_num);
+ PrintDebug("apic %u: core ?: Raising APIC IRQ %d\n", apic->lapic_id.val, irq_num);
if (*req_location & flag) {
//V3_Print("Interrupts coallescing\n");
if (*en_location & flag) {
*req_location |= flag;
} else {
- PrintDebug("apic %u: core ?: Interrupt not enabled... %.2x\n", apic->lapic_id.val, *en_location);
+ PrintDebug("apic %u: core ?: Interrupt not enabled... %.2x\n",
+ apic->lapic_id.val, *en_location);
return 0;
}
// We iterate backwards to find the highest priority
for (i = 31; i >= 0; i--) {
- uchar_t * svc_major = apic->int_svc_reg + i;
+ uint8_t * svc_major = apic->int_svc_reg + i;
if ((*svc_major) & 0xff) {
for (j = 7; j >= 0; j--) {
- uchar_t flag = 0x1 << j;
+ uint8_t flag = 0x1 << j;
if ((*svc_major) & flag) {
return ((i * 8) + j);
}
// We iterate backwards to find the highest priority
for (i = 31; i >= 0; i--) {
- uchar_t * req_major = apic->int_req_reg + i;
+ uint8_t * req_major = apic->int_req_reg + i;
if ((*req_major) & 0xff) {
for (j = 7; j >= 0; j--) {
- uchar_t flag = 0x1 << j;
+ uint8_t flag = 0x1 << j;
if ((*req_major) & flag) {
return ((i * 8) + j);
}
if (isr_irq != -1) {
int major_offset = (isr_irq & ~0x00000007) >> 3;
int minor_offset = isr_irq & 0x00000007;
- uchar_t flag = 0x1 << minor_offset;
- uchar_t * svc_location = apic->int_svc_reg + major_offset;
+ uint8_t flag = 0x1 << minor_offset;
+ uint8_t * svc_location = apic->int_svc_reg + major_offset;
PrintDebug("apic %u: core ?: Received APIC EOI for IRQ %d\n", apic->lapic_id.val,isr_irq);
if ((isr_irq == 238) ||
(isr_irq == 239)) {
- PrintError("apic %u: core ?: Acking IRQ %d\n", apic->lapic_id.val,isr_irq);
+ PrintDebug("apic %u: core ?: Acking IRQ %d\n", apic->lapic_id.val,isr_irq);
}
if (isr_irq == 238) {
masked = apic->err_vec_tbl.mask;
break;
default:
- PrintError("apic %u: core ?: Invalid APIC interrupt type\n",apic->lapic_id.val);
+ PrintError("apic %u: core ?: Invalid APIC interrupt type\n", apic->lapic_id.val);
return -1;
}
// interrupt is masked, don't send
if (masked == 1) {
- PrintDebug("apic %u: core ?: Inerrupt is masked\n",apic->lapic_id.val);
+ PrintDebug("apic %u: core ?: Inerrupt is masked\n", apic->lapic_id.val);
return 0;
}
//PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
return activate_apic_irq(apic, vec_num);
} else {
- PrintError("apic %u: core ?: Unhandled Delivery Mode\n",apic->lapic_id.val);
+ PrintError("apic %u: core ?: Unhandled Delivery Mode\n", apic->lapic_id.val);
return -1;
}
}
uint32_t val = 0;
- PrintDebug("apic %u: core %u: at %p: Read apic address space (%p)\n",apic->lapic_id.val,core->cpu_id, apic, (void *)guest_addr);
+ PrintDebug("apic %u: core %u: at %p: Read apic address space (%p)\n",
+ apic->lapic_id.val, core->cpu_id, apic, (void *)guest_addr);
if (msr->apic_enable == 0) {
- PrintError("apic %u: core %u: Read from APIC address space with disabled APIC, apic msr=0x%llx\n",apic->lapic_id.val,core->cpu_id,apic->base_addr_msr.value);
+ PrintError("apic %u: core %u: Read from APIC address space with disabled APIC, apic msr=0x%llx\n",
+ apic->lapic_id.val, core->cpu_id, apic->base_addr_msr.value);
return -1;
}
case SEOI_OFFSET:
default:
- PrintError("apic %u: core %u: Read from Unhandled APIC Register: %x (getting zero)\n", apic->lapic_id.val,core->cpu_id, (uint32_t)reg_addr);
- // return -1;
- val=0;
+ PrintError("apic %u: core %u: Read from Unhandled APIC Register: %x (getting zero)\n",
+ apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
+ return -1;
}
*val_ptr = val;
} else {
- PrintError("apic %u: core %u: Invalid apic read length (%d)\n", apic->lapic_id.val,core->cpu_id, length);
+ PrintError("apic %u: core %u: Invalid apic read length (%d)\n",
+ apic->lapic_id.val, core->cpu_id, length);
return -1;
}
- PrintDebug("apic %u: core %u: Read finished (val=%x)\n", apic->lapic_id.val,core->cpu_id, *(uint32_t *)dst);
+ PrintDebug("apic %u: core %u: Read finished (val=%x)\n",
+ apic->lapic_id.val, core->cpu_id, *(uint32_t *)dst);
return length;
}
struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
uint32_t op_val = *(uint32_t *)src;
- PrintDebug("apic %u: core %u: at %p and priv_data is at %p: Write to address space (%p) (val=%x)\n",
- apic->lapic_id.val, core->cpu_id, apic,priv_data,
+ PrintDebug("apic %u: core %u: at %p and priv_data is at %p\n",
+ apic->lapic_id.val, core->cpu_id, apic, priv_data);
+
+ PrintDebug("Write to address space (%p) (val=%x)\n",
(void *)guest_addr, *(uint32_t *)src);
if (msr->apic_enable == 0) {
- PrintError("apic %u: core %u: Write to APIC address space with disabled APIC, apic msr=0x%llx\n",apic->lapic_id.val,core->cpu_id,apic->base_addr_msr.value);
+ PrintError("apic %u: core %u: Write to APIC address space with disabled APIC, apic msr=0x%llx\n",
+ apic->lapic_id.val, core->cpu_id, apic->base_addr_msr.value);
return -1;
}
if (length != 4) {
- PrintError("apic %u: core %u: Invalid apic write length (%d)\n", apic->lapic_id.val, length,core->cpu_id);
+ PrintError("apic %u: core %u: Invalid apic write length (%d)\n",
+ apic->lapic_id.val, length, core->cpu_id);
return -1;
}
case TRIG_OFFSET7:
case PPR_OFFSET:
case EXT_APIC_FEATURE_OFFSET:
-#if 1
- PrintError("apic %u: core %u: Attempting to write to read only register %p (ignored)\n", apic->lapic_id.val,core->cpu_id, (void *)reg_addr);
-#else
- PrintError("apic %u: core %u: Attempting to write to read only register %p (error)\n", apic->lapic_id.val,core->cpu_id, (void *)reg_addr);
+
+ PrintError("apic %u: core %u: Attempting to write to read only register %p (error)\n",
+ apic->lapic_id.val, core->cpu_id, (void *)reg_addr);
return -1;
-#endif
+
break;
// Data registers
case APIC_ID_OFFSET:
- PrintDebug("apic %u: core %u: my id is being changed to %u\n",apic->lapic_id.val,core->cpu_id,op_val);
+ PrintDebug("apic %u: core %u: my id is being changed to %u\n",
+ apic->lapic_id.val, core->cpu_id, op_val);
+
apic->lapic_id.val = op_val;
break;
case TPR_OFFSET:
case INT_CMD_LO_OFFSET:
apic->int_cmd.lo = op_val;
+
// ICC???
- PrintDebug("apic %u: core %u: sending cmd 0x%llx to apic %u\n",apic->lapic_id.val,core->cpu_id,
+ PrintDebug("apic %u: core %u: sending cmd 0x%llx to apic %u\n",
+ apic->clapic_id.val, core->cpu_id,
apic->int_cmd.val, apic->int_cmd.dst);
if (v3_icc_send_ipi(apic->icc_bus, apic->lapic_id.val, apic->int_cmd.val,apic->dst_fmt.val,0)==-1) {
return -1;
}
break;
+
case INT_CMD_HI_OFFSET:
apic->int_cmd.hi = op_val;
break;
- // Unhandled Registers
+
+ // Unhandled Registers
case EXT_APIC_CMD_OFFSET:
case SEOI_OFFSET:
default:
- PrintError("apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n", apic->lapic_id.val,core->cpu_id, (uint32_t)reg_addr);
- // return -1;
+ PrintError("apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n",
+ apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
+
+ return -1;
}
- PrintDebug("apic %u: core %u: Write finished\n",apic->lapic_id.val,core->cpu_id);
+ PrintDebug("apic %u: core %u: Write finished\n", apic->lapic_id.val, core->cpu_id);
return length;
}
struct apic_state * apic = (struct apic_state *)private_data;
int major_offset = (irq & ~0x00000007) >> 3;
int minor_offset = irq & 0x00000007;
- uchar_t * req_location = apic->int_req_reg + major_offset;
- uchar_t * svc_location = apic->int_svc_reg + major_offset;
- uchar_t flag = 0x01 << minor_offset;
+ uint8_t * req_location = apic->int_req_reg + major_offset;
+ uint8_t * svc_location = apic->int_svc_reg + major_offset;
+ uint8_t flag = 0x01 << minor_offset;
if (*req_location & flag) {
// we will only pay attention to a begin irq if we
} else {
// do nothing...
PrintDebug("apic %u: core %u: begin irq for %d ignored since I don't own it\n",
- apic->lapic_id.val,info->cpu_id,irq);
+ apic->lapic_id.val, info->cpu_id, irq);
}
-
-
return 0;
}
/* Timer Functions */
-static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
+static void apic_update_time(struct guest_info * info,
+ uint64_t cpu_cycles, uint64_t cpu_freq,
+ void * priv_data) {
struct apic_state * apic = (struct apic_state *)(priv_data);
// The 32 bit GCC runtime is a pile of shit
#ifdef __V3_64BIT__
uint32_t tmr_ticks = 0;
#endif
- uchar_t tmr_div = *(uchar_t *)&(apic->tmr_div_cfg.val);
+ uint8_t tmr_div = *(uint8_t *)&(apic->tmr_div_cfg.val);
uint_t shift_num = 0;
shift_num = 7;
break;
default:
- PrintError("apic %u: core %u: Invalid Timer Divider configuration\n",apic->lapic_id.val,info->cpu_id);
+ PrintError("apic %u: core %u: Invalid Timer Divider configuration\n",
+ apic->lapic_id.val, info->cpu_id);
return;
}
apic->tmr_cur_cnt = 0;
// raise irq
- PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", apic->lapic_id.val,info->cpu_id,
+ PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n",
+ apic->lapic_id.val, info->cpu_id,
apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
if (apic_intr_pending(info, priv_data)) {
- PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n", apic->lapic_id.val,info->cpu_id, apic_get_intr_number(info, priv_data));
+ PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n",
+ apic->lapic_id.val, info->cpu_id,
+ apic_get_intr_number(info, priv_data));
}
if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
- PrintError("apic %u: core %u: Could not raise Timer interrupt\n",apic->lapic_id.val,info->cpu_id);
+ PrintError("apic %u: core %u: Could not raise Timer interrupt\n",
+ apic->lapic_id.val, info->cpu_id);
}
if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
PrintDebug("apic: creating an APIC for each core\n");
- char * name = v3_cfg_val(cfg, "name");
- char * icc_name = v3_cfg_val(cfg,"bus");
- struct vm_device * icc = v3_find_dev(vm, icc_name);
+ char * dev_id = v3_cfg_val(cfg, "ID");
+ char * icc_bus_id = v3_cfg_val(cfg, "bus");
+ struct vm_device * icc = v3_find_dev(vm, icc_bus_id);
int i;
if (!icc) {
- PrintError("apic: Cannot find ICC Bus (%s)\n", icc_name);
+ PrintError("apic: Cannot find ICC Bus (%s)\n", icc_bus_id);
return -1;
}
// 0..num_cores-1 at num_cores is the ioapic (one only)
struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state) * vm->num_cores);
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, apic);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, apic);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("apic: Could not attach device %s\n", name);
+ PrintError("apic: Could not attach device %s\n", dev_id);
return -1;
}
v3_icc_register_apic(core, icc, i, &icc_ops, &(apic[i]));
- PrintDebug("apic %u: (setup device): done, my id is %u\n",i,apic[i].lapic_id.val);
+ PrintDebug("apic %u: (setup device): done, my id is %u\n", i, apic[i].lapic_id.val);
}
- for (i=0;i<vm->num_cores;i++) {
+ for (i = 0; i < vm->num_cores; i++) {
PrintDebug("apic: sanity check: apic %u (at %p) has id %u and msr value %llx\n",
i, &(apic[i]), apic[i].lapic_id.val, apic[i].base_addr_msr.value);
}
+
PrintDebug("apic: priv_data is at %p\n", apic);
v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
static int debug_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct debug_state * state = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
V3_ASSERT(state != NULL);
PrintDebug("Creating Bochs Debug Device\n");
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
}
}
-static int video_write_mem(addr_t guest_addr, void * dest, uint_t length, void * priv_data) {
+static int video_write_mem(struct guest_info * core, 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;
return length;
}
-static int video_read_port(uint16_t port, void * dest, uint_t length, struct vm_device * dev) {
+static int video_read_port(struct guest_info * core, uint16_t port, void * dest, uint_t length, struct vm_device * dev) {
struct video_internal * video_state = (struct video_internal *)dev->private_data;
-static int video_write_port(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+static int video_write_port(struct guest_info * core, uint16_t port, void * src, uint_t length, struct vm_device * dev) {
struct video_internal * video_state = (struct video_internal *)dev->private_data;
-static int crtc_data_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+static int crtc_data_write(struct guest_info * core, 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;
}
-static int crtc_index_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+static int crtc_index_write(struct guest_info * core, 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) {
}
if (length == 2) {
- if (crtc_data_write(port + 1, src + 1, length - 1, dev) != (length - 1)) {
+ if (crtc_data_write(core, port + 1, src + 1, length - 1, dev) != (length - 1)) {
PrintError("could not handle implicit crtc data write\n");
return -1;
}
static int free_device(struct vm_device * dev) {
- v3_unhook_mem(dev->vm, START_ADDR);
+ v3_unhook_mem(dev->vm, V3_MEM_CORE_ANY, START_ADDR);
return 0;
}
.stop = NULL,
};
-static int cga_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+static int cga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
addr_t frame_buf_pa = 0;
int enable_passthrough = 0;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
enable_passthrough = (strcasecmp(v3_cfg_val(cfg, "passthrough"), "enable") == 0) ? 1 : 0;
PrintDebug("video: init_device\n");
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, video_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, video_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
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) {
+ if (v3_hook_write_mem(vm, V3_MEM_CORE_ANY, 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) {
+ if (v3_hook_write_mem(vm, V3_MEM_CORE_ANY, START_ADDR, END_ADDR, frame_buf_pa, &video_write_mem, dev) == -1) {
PrintDebug("\n\nVideo Hook failed.\n\n");
}
}
static int cirrus_gfx_card_init(struct guest_info * vm, v3_cfg_tree_t * cfg){
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);
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
- struct vm_device * dev = v3_allocate_device("TEXT_GFX_CARD", &dev_ops, video_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, video_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", "TEXT_GFX_CARD");
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
.stop = NULL,
};
-static int cons_init(struct guest_info * vm, v3_cfg_tree_t * cfg)
+static int cons_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg)
{
- struct cons_state * state;
- v3_cfg_tree_t * frontend_cfg;
- const char *frontend_tag;
- struct vm_device * frontend;
- char *name, *ttypath;
+ struct cons_state * state = NULL;
+ v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
+ const char * frontend_tag = v3_cfg_val(frontend_cfg, "tag");
+ struct vm_device * frontend = v3_find_dev(vm, frontend_tag);
+ char * dev_id = v3_cfg_val(cfg, "ID");
+ char * ttypath = v3_cfg_val(cfg, "tty");
/* read configuration */
- frontend_cfg = v3_cfg_subtree(cfg, "frontend");
V3_ASSERT(frontend_cfg);
- frontend_tag = v3_cfg_val(frontend_cfg, "tag");
V3_ASSERT(frontend_tag);
- frontend = v3_find_dev(vm, frontend_tag);
V3_ASSERT(frontend);
- name = v3_cfg_val(cfg, "name");
+
/* allocate state */
- state = (struct cons_state *) V3_Malloc(sizeof(struct cons_state));
+ state = (struct cons_state *)V3_Malloc(sizeof(struct cons_state));
V3_ASSERT(state);
state->frontend_dev = frontend;
- ttypath = v3_cfg_val(cfg, "tty");
V3_ASSERT(ttypath);
/* open tty for screen display */
}
/* allocate device */
- struct vm_device *dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device *dev = v3_allocate_device(dev_id, &dev_ops, state);
V3_ASSERT(dev);
/* attach device to virtual machine */
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
V3_Free(state);
return -1;
}
static int model_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, NULL);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, NULL);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
- if (v3_dev_add_blk_frontend(vm, name, connect_fn, NULL) == -1) {
- PrintError("Could not register %s as block frontend\n", name);
+ if (v3_dev_add_blk_frontend(vm, dev_id, connect_fn, NULL) == -1) {
+ PrintError("Could not register %s as block frontend\n", dev_id);
return -1;
}
--- /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) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * 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 <palacios/vmm_dev_mgr.h>
+
+#include <palacios/vmm_file.h>
+
+#ifndef CONFIG_DEBUG_FILEDISK
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+struct disk_state {
+ uint64_t capacity; // in bytes
+
+ int fd;
+};
+
+
+static int read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
+ struct disk_state * disk = (struct disk_state *)private_data;
+
+ PrintDebug("Reading %d bytes from %p to %p\n", (uint32_t)num_bytes, (uint8_t *)(disk->disk_image + lba), buf);
+
+ V3_FileRead(disk->fd, lba, buf, num_bytes);
+
+ return 0;
+}
+
+
+static int write(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
+ struct disk_state * disk = (struct disk_state *)private_data;
+
+ PrintDebug("Writing %d bytes from %p to %p\n", (uint32_t)num_bytes, buf, (uint8_t *)(disk->disk_image + lba));
+
+ V3_FileWrite(disk->fd, lba, buf, num_bytes);
+
+ return 0;
+}
+
+
+static uint64_t get_capacity(void * private_data) {
+ struct disk_state * disk = (struct disk_state *)private_data;
+
+ PrintDebug("Querying RAMDISK capacity %d\n",
+ (uint32_t)(disk->capacity));
+
+ return disk->capacity;
+}
+
+static struct v3_dev_blk_ops blk_ops = {
+ .read = read,
+ .write = write,
+ .get_capacity = get_capacity,
+};
+
+
+
+
+static int disk_free(struct vm_device * dev) {
+ return 0;
+}
+
+static struct v3_device_ops dev_ops = {
+ .free = disk_free,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
+};
+
+
+
+
+static int disk_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+ struct disk_state * disk = NULL;
+ char * path = v3_cfg_val(cfg, "path");
+ char * dev_id = v3_cfg_val(cfg, "ID");
+ char * filename = v3_cfg_val(cfg, "file");
+
+
+ v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
+
+ disk = (struct disk_state *)V3_Malloc(sizeof(struct disk_state));
+ memset(disk, 0, sizeof(struct disk_state));
+
+
+ if (!path) {
+ PrintError("Missing path (%s) for %s\n", path, dev_id);
+ return -1;
+ }
+
+ disk->fd = V3_FileOpen(path, 0);
+ disk->capacity = V3_FileSize(disk->fd);
+
+ PrintDebug("Registering RAMDISK at %p (size=%d)\n",
+ (void *)file->data, (uint32_t)file->size);
+
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, disk);
+
+ if (v3_attach_device(vm, dev) == -1) {
+ PrintError("Could not attach device %s\n", dev_id);
+ return -1;
+ }
+
+ if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"),
+ &blk_ops, frontend_cfg, disk) == -1) {
+ PrintError("Could not connect %s to frontend %s\n",
+ dev_id, v3_cfg_val(frontend_cfg, "tag"));
+ return -1;
+ }
+
+
+ return 0;
+}
+
+
+device_register("FILEDISK", disk_init)
static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct generic_internal * state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
v3_cfg_tree_t * port_cfg = v3_cfg_subtree(cfg, "ports");
state->num_port_ranges = 0;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
int i;
struct i440_state * state = NULL;
struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
if (!pci) {
PrintError("could not find PCI Device\n");
state->pci = pci;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
// So the selector needs to be VV00
// and the base needs to be VV000
//
- core->rip=0;
- core->segments.cs.selector = icr->vec<<8;
- core->segments.cs.limit= 0xffff;
- core->segments.cs.base = icr->vec<<12;
+ core->rip = 0;
+ core->segments.cs.selector = icr->vec << 8;
+ core->segments.cs.limit = 0xffff;
+ core->segments.cs.base = icr->vec << 12;
PrintDebug("icc_bus: SIPI delivery (0x%x -> 0x%x:0x0) to core %u\n",
icr->vec, core->segments.cs.selector, core->cpu_id);
// Maybe need to adjust the APIC?
// We transition the target core to SIPI state
- core->cpu_mode=REAL; // note: locking should not be needed here
+ core->cpu_mode = REAL; // note: locking should not be needed here
// As with INIT, we should not need to do anything else
static int icc_bus_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
PrintDebug("icc_bus: Creating ICC_BUS\n");
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
struct icc_bus_state * icc_bus = (struct icc_bus_state *)V3_Malloc(sizeof(struct icc_bus_state));
memset(icc_bus, 0, sizeof(struct icc_bus_state));
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, icc_bus);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, icc_bus);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("icc_bus: Could not attach device %s\n", name);
+ PrintError("icc_bus: Could not attach device %s\n", dev_id);
return -1;
}
static int ide_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct ide_internal * ide = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
PrintDebug("IDE: Initializing IDE\n");
memset(ide, 0, sizeof(struct ide_internal));
PrintDebug("IDE: Creating IDE bus x 2\n");
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, ide);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, ide);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
}
- if (v3_dev_add_blk_frontend(vm, name, connect_fn, (void *)ide) == -1) {
- PrintError("Could not register %s as frontend\n", name);
+ if (v3_dev_add_blk_frontend(vm, dev_id, connect_fn, (void *)ide) == -1) {
+ PrintError("Could not register %s as frontend\n", dev_id);
return -1;
}
return 0;
}
-
-
-
ioapic->base_addr = IO_APIC_BASE_ADDR;
ioapic->index_reg = 0;
- ioapic->ioapic_id.val = id;
+ ioapic->ioapic_id.id = id;
ioapic->ioapic_ver.val = 0x00170011;
ioapic->ioapic_arb_id.val = 0x00000000;
uint32_t reg_tgt = guest_addr - ioapic->base_addr;
uint32_t * op_val = (uint32_t *)dst;
- PrintDebug("ioapic %u: IOAPIC Read at %p\n", ioapic->ioapic_id.val, (void *)guest_addr);
+ PrintDebug("ioapic %u: IOAPIC Read at %p\n", ioapic->ioapic_id.id, (void *)guest_addr);
if (reg_tgt == 0x00) {
*op_val = ioapic->index_reg;
case IOAPIC_ARB_REG:
*op_val = ioapic->ioapic_arb_id.val;
break;
- default:
- {
- uint_t redir_index = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) >> 1;
- uint_t hi_val = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) % 1;
-
- if (redir_index > 0x3f) {
- PrintError("ioapic %u: Invalid redirection table entry %x\n", ioapic->ioapic_id.val, (uint32_t)redir_index);
- return -1;
- }
- if (hi_val) {
- *op_val = ioapic->redir_tbl[redir_index].hi;
- } else {
- *op_val = ioapic->redir_tbl[redir_index].lo;
- }
+ default: {
+ uint_t redir_index = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) >> 1;
+ uint_t hi_val = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) % 1;
+
+ if (redir_index > 0x3f) {
+ PrintError("ioapic %u: Invalid redirection table entry %x\n", ioapic->ioapic_id.id, (uint32_t)redir_index);
+ return -1;
+ }
+
+ if (hi_val) {
+ *op_val = ioapic->redir_tbl[redir_index].hi;
+ } else {
+ *op_val = ioapic->redir_tbl[redir_index].lo;
}
+ }
}
}
- PrintDebug("ioapic %u: IOAPIC Read at %p gave value 0x%x\n", ioapic->ioapic_id.val, (void *)guest_addr, *op_val);
+ PrintDebug("ioapic %u: IOAPIC Read at %p gave value 0x%x\n", ioapic->ioapic_id.id, (void *)guest_addr, *op_val);
return length;
}
uint32_t reg_tgt = guest_addr - ioapic->base_addr;
uint32_t op_val = *(uint32_t *)src;
- PrintDebug("ioapic %u: IOAPIC Write at %p (val = %d)\n", ioapic->ioapic_id.val, (void *)guest_addr, *(uint32_t *)src);
+ PrintDebug("ioapic %u: IOAPIC Write at %p (val = %d)\n", ioapic->ioapic_id.id, (void *)guest_addr, *(uint32_t *)src);
if (reg_tgt == 0x00) {
ioapic->index_reg = op_val;
// IOWIN register
switch (ioapic->index_reg) {
case IOAPIC_ID_REG:
+ // What does this do to our relationship with the ICC bus?
ioapic->ioapic_id.val = op_val;
break;
case IOAPIC_VER_REG:
// GPF/PageFault/Ignore?
- PrintError("ioapic %u: Writing to read only IOAPIC register\n", ioapic->ioapic_id.val);
+ PrintError("ioapic %u: Writing to read only IOAPIC register\n", ioapic->ioapic_id.id);
return -1;
case IOAPIC_ARB_REG:
ioapic->ioapic_arb_id.val = op_val;
if (redir_index > 0x3f) {
- PrintError("ioapic %u: Invalid redirection table entry %x\n", ioapic->ioapic_id.val, (uint32_t)redir_index);
+ PrintError("ioapic %u: Invalid redirection table entry %x\n", ioapic->ioapic_id.id, (uint32_t)redir_index);
return -1;
}
if (hi_val) {
PrintDebug("ioapic %u: Writing to hi of pin %d\n", ioapic->ioapic_id.val, redir_index);
ioapic->redir_tbl[redir_index].hi = op_val;
} else {
- PrintDebug("ioapic %u: Writing to lo of pin %d\n", ioapic->ioapic_id.val, redir_index);
+ PrintDebug("ioapic %u: Writing to lo of pin %d\n", ioapic->ioapic_id.id, redir_index);
op_val &= REDIR_LO_MASK;
ioapic->redir_tbl[redir_index].lo &= ~REDIR_LO_MASK;
ioapic->redir_tbl[redir_index].lo |= op_val;
struct redir_tbl_entry * irq_entry = NULL;
if (irq > 24) {
- PrintDebug("ioapic %u: IRQ out of range of IO APIC\n", ioapic->ioapic_id.val);
+ PrintDebug("ioapic %u: IRQ out of range of IO APIC\n", ioapic->ioapic_id.id);
return -1;
}
if (irq_entry->mask == 0) {
- PrintDebug("ioapic %u: IOAPIC Signalling APIC to raise INTR %d\n", ioapic->ioapic_id.val, irq_entry->vec);
+ PrintDebug("ioapic %u: IOAPIC Signalling APIC to raise INTR %d\n", ioapic->ioapic_id.id, irq_entry->vec);
// the format of the redirection table entry is just slightly
// Note: 0 yhere is "cluster model", but it should be irrelevant
// since we are sending this as a physical destination
- v3_icc_send_ipi(ioapic->icc_bus, ioapic->ioapic_id.val,icr.val, 0, irq);
+ PrintDebug("io apic %u: raising irq %u on ICC bus.\n",
+ ioapic->ioapic_id.id, irq);
+ v3_icc_send_ipi(ioapic->icc_bus, ioapic->ioapic_id.id,icr.val, 0, irq);
}
return 0;
static int ioapic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct vm_device * icc_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
if (!icc_bus) {
PrintError("ioapic: Could not locate ICC BUS device (%s)\n", v3_cfg_val(cfg, "bus"));
ioapic->icc_bus = icc_bus;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, ioapic);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, ioapic);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("ioapic: Could not attach device %s\n", name);
+ PrintError("ioapic: Could not attach device %s\n", dev_id);
return -1;
}
init_ioapic_state(ioapic,vm->num_cores);
- v3_icc_register_ioapic(vm,icc_bus,ioapic->ioapic_id.val);
+ v3_icc_register_ioapic(vm,icc_bus,ioapic->ioapic_id.id);
v3_hook_full_mem(vm, V3_MEM_CORE_ANY, ioapic->base_addr, ioapic->base_addr + PAGE_SIZE_4KB,
ioapic_read, ioapic_write, dev);
static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct keyboard_internal * keyboard_state = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
PrintDebug("keyboard: init_device\n");
keyboard_state->mouse_enabled = 0;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, keyboard_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, keyboard_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
struct virtio_balloon_state * virtio_state = NULL;
struct pci_device * pci_dev = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
PrintDebug("Initializing VIRTIO Balloon device\n");
memset(virtio_state, 0, sizeof(struct virtio_balloon_state));
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, virtio_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
struct virtio_dev_state * virtio_state = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
PrintDebug("Initializing VIRTIO Block device\n");
virtio_state->pci_bus = pci_bus;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, virtio_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
- if (v3_dev_add_blk_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
- PrintError("Could not register %s as block frontend\n", name);
+ if (v3_dev_add_blk_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
+ PrintError("Could not register %s as block frontend\n", dev_id);
return -1;
}
static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
struct virtio_dev_state * virtio_state = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
- PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", name);
+ PrintDebug("Virtio NIC: Initializing VIRTIO Network device: %s\n", dev_id);
if (pci_bus == NULL) {
PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
virtio_state->pci_bus = pci_bus;
virtio_state->vm = vm;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, virtio_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Virtio NIC: Could not attach device %s\n", name);
+ PrintError("Virtio NIC: Could not attach device %s\n", dev_id);
return -1;
}
- if (v3_dev_add_net_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
- PrintError("Virtio NIC: Could not register %s as net frontend\n", name);
+ if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
+ PrintError("Virtio NIC: Could not register %s as net frontend\n", dev_id);
return -1;
}
struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
struct virtio_sym_state * virtio_state = NULL;
struct pci_device * pci_dev = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
PrintDebug("Initializing VIRTIO Symbiotic device\n");
memset(virtio_state, 0, sizeof(struct virtio_sym_state));
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, virtio_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
struct virtio_sym_state * virtio_state = NULL;
struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
struct pci_device * pci_dev = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
PrintDebug("SYMMOD: Initializing VIRTIO Symbiotic Module device\n");
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, virtio_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
int io_range_size;
v3_lock_t lock;
- ulong_t pkt_sent, pkt_recv, pkt_drop, tx_exit, rx_exit, total_exit;
+ uint32_t pkt_sent;
+ uint32_t pkt_recv;
+ uint32_t pkt_drop;
+ uint32_t tx_exit;
+ uint32_t rx_exit;
+ uint32_t total_exit;
+
int ready;
};
uint8_t status = 0;
- PrintDebug("VNET Bridge: CMD: Descriptor Count=%d, index=%d, desc_idx=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE, desc_idx);
+ PrintDebug("VNET Bridge: CMD: Descriptor Count=%d, index=%d, desc_idx=%d\n",
+ desc_cnt, q->cur_avail_idx % QUEUE_SIZE, desc_idx);
if (desc_cnt < 3) {
PrintError("VNET Bridge cmd must include at least 3 descriptors (cnt=%d)\n", desc_cnt);
int ret_val = -1;
unsigned long flags;
uint16_t sent;
- struct v3_vnet_pkt *pkt;
+ struct v3_vnet_pkt * pkt = NULL;
- if(pkt_num <= 0)
+ if (pkt_num <= 0) {
return 0;
+ }
flags = v3_lock_irqsave(vnet_state->lock);
if (q->ring_avail_addr == 0) {
PrintError("Queue is not set\n");
- goto exit;
+ v3_unlock_irqrestore(vnet_state->lock, flags);
+ return ret_val;
}
PrintDebug("VNET Bridge: RX: running on cpu: %d, num of pkts: %d\n", V3_Get_CPU(), pkt_num);
- for(sent = 0; sent < pkt_num; sent ++) {
+ for (sent = 0; sent < pkt_num; sent++) {
pkt = &vnet_pkts[sent];
- vnet_state->pkt_recv ++;
+ vnet_state->pkt_recv++;
if (q->cur_avail_idx != q->avail->index) {
uint16_t pkt_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
if (v3_gpa_to_hva(&(vm->cores[0]), pkt_desc->addr_gpa, (addr_t *)&(virtio_pkt)) == -1) {
PrintError("Could not translate buffer address\n");
- goto exit;
+ v3_unlock_irqrestore(vnet_state->lock, flags);
+ return ret_val;
}
PrintDebug("VNET Bridge: RX: pkt sent to guest pkt size: %d, dst link: %d\n", pkt->size, pkt->dst_id);
q->used->index++;
q->cur_avail_idx++;
} else {
- vnet_state->pkt_drop ++;
+ vnet_state->pkt_drop++;
v3_vnet_disable_bridge();
}
}
- if(sent == 0){
- goto exit;
+ if (sent == 0) {
+ v3_unlock_irqrestore(vnet_state->lock, flags);
+ return ret_val;
}
if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
#ifdef CONFIG_VNET_PROFILE
if (vnet_state->pkt_recv % 200000 == 0)
PrintError("Vnet Bridge: sent: %ld, rxed: %ld, dropped: %ld, total exit: %ld, tx exit: %ld, rx exit: %ld\n",
- vnet_state->pkt_sent,
- vnet_state->pkt_recv,
- vnet_state->pkt_drop,
- vnet_state->total_exit,
- vnet_state->tx_exit,
- vnet_state->rx_exit);
+ vnet_state->pkt_sent,
+ vnet_state->pkt_recv,
+ vnet_state->pkt_drop,
+ vnet_state->total_exit,
+ vnet_state->tx_exit,
+ vnet_state->rx_exit);
#endif
-exit:
-
v3_unlock_irqrestore(vnet_state->lock, flags);
-
+
return ret_val;
+
}
-static void vnet_pkt_input_xcall(void *data){
- struct v3_vnet_bridge_input_args *args = (struct v3_vnet_bridge_input_args *)data;
+static void vnet_pkt_input_xcall(void * data) {
+ struct v3_vnet_bridge_input_args * args = (struct v3_vnet_bridge_input_args *)data;
vnet_pkt_input_cb(args->vm, args->vnet_pkts, args->pkt_num, args->private_data);
}
-static int handle_pkt_kick(struct guest_info *core, struct virtio_vnet_state * vnet_state)
-{
+static int handle_pkt_kick(struct guest_info * core, struct virtio_vnet_state * vnet_state) {
struct virtio_queue * q = &(vnet_state->queue[XMIT_QUEUE]);
unsigned long flags = 0;
int recvd = 0;
-
+ int cpu = V3_Get_CPU();
+
flags = v3_lock_irqsave(vnet_state->lock);
if (q->ring_avail_addr == 0) {
- goto exit;
+ v3_unlock_irqrestore(vnet_state->lock,flags);
+ return 0;
}
while (q->cur_avail_idx != q->avail->index) {
q->used->ring[q->used->index % q->queue_size].length = pkt_desc->length; // What do we set this to????
q->used->index++;
- vnet_state->pkt_sent ++;
- recvd ++;
+ vnet_state->pkt_sent++;
+ recvd++;
q->cur_avail_idx++;
}
- if(recvd == 0){
- goto exit;
+ if (recvd == 0) {
+ v3_unlock_irqrestore(vnet_state->lock,flags);
+ return 0;
}
//PrintError("In polling get %d\n", recvd);
//if on the dom0 core, interrupt the domU core to poll pkts
//otherwise, call the polling directly
- int cpu = V3_Get_CPU();
- if(vnet_state->vm->cores[0].cpu_id == cpu){
- cpu = (cpu == 0)?1:0;
+
+
+ if (vnet_state->vm->cores[0].cpu_id == cpu) {
+ cpu = (cpu == 0) ? 1 : 0;
v3_interrupt_cpu(vnet_state->vm, cpu, V3_VNET_POLLING_VECTOR);
- }else{
+ } else {
v3_vnet_polling();
}
- if((vnet_state->pkt_sent % (QUEUE_SIZE/20)) == 0) { //optimized for guest's, batch the interrupts
- if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
- v3_pci_raise_irq(vnet_state->pci_bus, 0, vnet_state->pci_dev);
- vnet_state->virtio_cfg.pci_isr = 0x1;
- }
+ if ((vnet_state->pkt_sent % (QUEUE_SIZE/20)) == 0) {
+ //optimized for guest's, batch the interrupts
+
+ if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
+ v3_pci_raise_irq(vnet_state->pci_bus, 0, vnet_state->pci_dev);
+ vnet_state->virtio_cfg.pci_isr = 0x1;
+ }
}
-
+
#ifdef CONFIG_VNET_PROFILE
if (vnet_state->pkt_sent % 200000 == 0)
PrintError("Vnet Bridge: sent: %ld, rxed: %ld, dropped: %ld, total exit: %ld, tx exit: %ld, rx exit: %ld\n",
- vnet_state->pkt_sent,
- vnet_state->pkt_recv,
- vnet_state->pkt_drop,
- vnet_state->total_exit,
- vnet_state->tx_exit,
- vnet_state->rx_exit);
+ vnet_state->pkt_sent,
+ vnet_state->pkt_recv,
+ vnet_state->pkt_drop,
+ vnet_state->total_exit,
+ vnet_state->tx_exit,
+ vnet_state->rx_exit);
#endif
-exit:
v3_unlock_irqrestore(vnet_state->lock,flags);
return 0;
}
-static int polling_pkt_from_guest(struct v3_vm_info * vm, void *private_data){
+static int polling_pkt_from_guest(struct v3_vm_info * vm, void *private_data) {
struct virtio_vnet_state * vnet_state = (struct virtio_vnet_state *)private_data;
return handle_pkt_kick(&(vm->cores[0]), vnet_state);
}
-static int handle_rx_kick(struct guest_info *core, struct virtio_vnet_state * vnet_state)
-{
+static int handle_rx_kick(struct guest_info *core, struct virtio_vnet_state * vnet_state) {
v3_vnet_enable_bridge();
return 0;
port, length, *(uint32_t *)src);
PrintDebug("VNET Bridge: port idx=%d\n", port_idx);
- vnet_state->total_exit ++;
+ vnet_state->total_exit++;
switch (port_idx) {
case GUEST_FEATURES_PORT:
+
if (length != 4) {
PrintError("Illegal write length for guest features\n");
return -1;
}
+
vnet_state->virtio_cfg.guest_features = *(uint32_t *)src;
break;
- case VRING_PG_NUM_PORT:
- if (length == 4) {
- addr_t pfn = *(uint32_t *)src;
- addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
+ case VRING_PG_NUM_PORT: {
- vnet_state->cur_queue->pfn = pfn;
-
- vnet_state->cur_queue->ring_desc_addr = page_addr ;
- vnet_state->cur_queue->ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
- vnet_state->cur_queue->ring_used_addr = ( vnet_state->cur_queue->ring_avail_addr + \
- sizeof(struct vring_avail) + \
- (QUEUE_SIZE * sizeof(uint16_t)));
-
- // round up to next page boundary.
- vnet_state->cur_queue->ring_used_addr = (vnet_state->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
+ addr_t pfn = *(uint32_t *)src;
+ addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
- if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_desc_addr, (addr_t *)&(vnet_state->cur_queue->desc)) == -1) {
- PrintError("Could not translate ring descriptor address\n");
- return -1;
- }
-
- if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_avail_addr, (addr_t *)&(vnet_state->cur_queue->avail)) == -1) {
- PrintError("Could not translate ring available address\n");
- return -1;
- }
-
- if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_used_addr, (addr_t *)&(vnet_state->cur_queue->used)) == -1) {
- PrintError("Could not translate ring used address\n");
- return -1;
- }
-
- PrintDebug("VNET Bridge: RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
- (void *)(vnet_state->cur_queue->ring_desc_addr),
- (void *)(vnet_state->cur_queue->ring_avail_addr),
- (void *)(vnet_state->cur_queue->ring_used_addr));
-
- PrintDebug("VNET Bridge: RingDesc=%p, Avail=%p, Used=%p\n",
- vnet_state->cur_queue->desc, vnet_state->cur_queue->avail, vnet_state->cur_queue->used);
-
- if(vnet_state->queue[RECV_QUEUE].avail != NULL){
- vnet_state->ready = 1;
- }
+ if (length != 4) {
+ PrintError("Illegal write length for page frame number\n");
+ return -1;
+ }
+
- //No notify when there is pkt tx from guest
- if(vnet_state->queue[XMIT_QUEUE].used != NULL){
- vnet_state->queue[XMIT_QUEUE].used->flags |= VRING_NO_NOTIFY_FLAG;
- }
+ vnet_state->cur_queue->pfn = pfn;
- } else {
- PrintError("Illegal write length for page frame number\n");
+ vnet_state->cur_queue->ring_desc_addr = page_addr ;
+ vnet_state->cur_queue->ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
+ vnet_state->cur_queue->ring_used_addr = ( vnet_state->cur_queue->ring_avail_addr + \
+ sizeof(struct vring_avail) + \
+ (QUEUE_SIZE * sizeof(uint16_t)));
+
+ // round up to next page boundary.
+ vnet_state->cur_queue->ring_used_addr = (vnet_state->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
+
+ if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_desc_addr, (addr_t *)&(vnet_state->cur_queue->desc)) == -1) {
+ PrintError("Could not translate ring descriptor address\n");
return -1;
}
+
+ if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_avail_addr, (addr_t *)&(vnet_state->cur_queue->avail)) == -1) {
+ PrintError("Could not translate ring available address\n");
+ return -1;
+ }
+
+ if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_used_addr, (addr_t *)&(vnet_state->cur_queue->used)) == -1) {
+ PrintError("Could not translate ring used address\n");
+ return -1;
+ }
+
+ PrintDebug("VNET Bridge: RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
+ (void *)(vnet_state->cur_queue->ring_desc_addr),
+ (void *)(vnet_state->cur_queue->ring_avail_addr),
+ (void *)(vnet_state->cur_queue->ring_used_addr));
+
+ PrintDebug("VNET Bridge: RingDesc=%p, Avail=%p, Used=%p\n",
+ vnet_state->cur_queue->desc,
+ vnet_state->cur_queue->avail,
+ vnet_state->cur_queue->used);
+
+ if (vnet_state->queue[RECV_QUEUE].avail != NULL){
+ vnet_state->ready = 1;
+ }
+
+ //No notify when there is pkt tx from guest
+ if (vnet_state->queue[XMIT_QUEUE].used != NULL) {
+ vnet_state->queue[XMIT_QUEUE].used->flags |= VRING_NO_NOTIFY_FLAG;
+ }
+
break;
+ }
case VRING_Q_SEL_PORT:
vnet_state->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
struct virtio_vnet_state * vnet_state = NULL;
struct pci_device * pci_dev = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
- PrintDebug("VNET Bridge: Initializing VNET Bridge Control device: %s\n", name);
+ PrintDebug("VNET Bridge: Initializing VNET Bridge Control device: %s\n", dev_id);
if (pci_bus == NULL) {
PrintError("VNET Bridge device require a PCI Bus");
vnet_state->vm = vm;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnet_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, vnet_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
char * ip_str = v3_cfg_val(cfg, "IP");
char * port_str = v3_cfg_val(cfg, "port");
char * disk_tag = v3_cfg_val(cfg, "tag");
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
disk->ip_addr = v3_inet_addr(ip_str);
disk->port = atoi(port_str);
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, disk);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, disk);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"),
&blk_ops, frontend_cfg, disk) == -1) {
- PrintError("Could not connect %s to frontend\n", name);
+ PrintError("Could not connect %s to frontend\n", dev_id);
return -1;
}
static int nvram_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct nvram_internal * nvram_state = NULL;
struct vm_device * ide = v3_find_dev(vm, v3_cfg_val(cfg, "storage"));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
if (!ide) {
PrintError("Could not find IDE device\n");
nvram_state->ide = ide;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, nvram_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, nvram_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
static int debug_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct debug_state * state = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
PrintDebug("Creating OS Debug Device\n");
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
static int net_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
struct nic_state * state = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
state = (struct nic_state *)V3_Malloc(sizeof(struct nic_state));
PrintDebug("Creating VMNet Device\n");
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
int i = 0;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
PrintDebug("PCI internal at %p\n",(void *)pci_state);
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, pci_state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, pci_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
struct pt_dev_state * state = V3_Malloc(sizeof(struct pt_dev_state));
struct vm_device * dev = NULL;
struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
memset(state, 0, sizeof(struct pt_dev_state));
}
state->pci_bus = pci;
- strncpy(state->name, name, 32);
+ strncpy(state->name, dev_id, 32);
- dev = v3_allocate_device(name, &dev_ops, state);
+ dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
struct v3_southbridge * piix3 = (struct v3_southbridge *)V3_Malloc(sizeof(struct v3_southbridge));
struct vm_device * dev = NULL;
struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
if (!pci) {
PrintError("Could not find PCI device\n");
piix3->pci_bus = pci;
piix3->type = V3_SB_PIIX3;
- dev = v3_allocate_device(name, &dev_ops, piix3);
+ dev = v3_allocate_device(dev_id, &dev_ops, piix3);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
static int disk_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct disk_state * disk = NULL;
struct v3_cfg_file * file = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
char * filename = v3_cfg_val(cfg, "file");
v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
if (!filename) {
- PrintError("Missing filename (%s) for %s\n", filename, name);
+ PrintError("Missing filename (%s) for %s\n", filename, dev_id);
return -1;
}
PrintDebug("Registering RAMDISK at %p (size=%d)\n",
(void *)file->data, (uint32_t)file->size);
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, disk);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, disk);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"),
&blk_ops, frontend_cfg, disk) == -1) {
PrintError("Could not connect %s to frontend %s\n",
- name, v3_cfg_val(frontend_cfg, "tag"));
+ dev_id, v3_cfg_val(frontend_cfg, "tag"));
return -1;
}
static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct serial_state * state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
PrintDebug("UART: init_device\n");
init_serial_port(&(state->com1));
state->com4.irq_number = COM4_IRQ;
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
struct swap_state * swap = NULL;
v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
uint32_t capacity = atoi(v3_cfg_val(cfg, "size")) * 1024 * 1024;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
if (!frontend_cfg) {
PrintError("Initializing sym swap without a frontend device\n");
memset(swap->usage_map, 0, ((swap->capacity / 4096) / 8));
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, swap);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, swap);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"),
&blk_ops, frontend_cfg, swap) == -1) {
PrintError("Could not connect %s to frontend %s\n",
- name, v3_cfg_val(frontend_cfg, "tag"));
+ dev_id, v3_cfg_val(frontend_cfg, "tag"));
return -1;
}
static int swap_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, NULL);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, NULL);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
- if (v3_dev_add_blk_frontend(vm, name, connect_fn, NULL) == -1) {
- PrintError("Could not register %s as block frontend\n", name);
+ if (v3_dev_add_blk_frontend(vm, dev_id, connect_fn, NULL) == -1) {
+ PrintError("Could not register %s as block frontend\n", dev_id);
return -1;
}
}
-static int cons_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+static int cons_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct cons_state * state = (struct cons_state *)V3_Malloc(sizeof(struct cons_state));
v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
- struct vm_device * frontend = v3_find_dev(vm, v3_cfg_val(frontend_cfg, "id"));
- char * name = v3_cfg_val(cfg, "name");
+ struct vm_device * frontend = v3_find_dev(vm, v3_cfg_val(frontend_cfg, "tag"));
+ char * dev_id = v3_cfg_val(cfg, "ID");
state->server_fd = 0;
v3_lock_init(&(state->cons_lock));
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
static int blk_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct blk_state * blk = NULL;
v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
uint64_t capacity = atoi(v3_cfg_val(cfg, "size")) * 1024 * 1024;
if (!frontend_cfg) {
memset(blk->blk_space, 0, capacity);
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, blk);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, blk);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"),
&blk_ops, frontend_cfg, blk) == -1) {
PrintError("Could not connect %s to frontend %s\n",
- name, v3_cfg_val(frontend_cfg, "tag"));
+ dev_id, v3_cfg_val(frontend_cfg, "tag"));
return -1;
}
};
-static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){
- struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
-
+static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device * dest_dev){
+ struct vnet_nic_state * vnetnic = (struct vnet_nic_state *)private_data;
struct v3_vnet_pkt pkt;
+
pkt.size = len;
pkt.src_type = LINK_INTERFACE;
pkt.src_id = vnetnic->vnet_dev_id;
}
static int register_to_vnet(struct v3_vm_info * vm,
- struct vnet_nic_state *vnet_nic,
- char *dev_name,
- uchar_t mac[6]) {
-
+ struct vnet_nic_state * vnet_nic,
+ char * dev_name,
+ uint8_t mac[6]) {
+
PrintDebug("Vnet-nic: register Vnet-nic device %s, state %p to VNET\n", dev_name, vnet_nic);
return v3_vnet_add_dev(vm, mac, virtio_input, (void *)vnet_nic);
};
-static int str2mac(char *macstr, char mac[6]){
- char hex[2], *s = macstr;
+static int str2mac(char * macstr, uint8_t mac[6]){
+ uint8_t hex[2];
int i = 0;
+ char * s = macstr;
- while(s){
+ while (s) {
memcpy(hex, s, 2);
mac[i++] = (char)atox(hex);
- if (i == 6) return 0;
- s=strchr(s, ':');
- if(s) s++;
+
+ if (i == 6) {
+ return 0;
+ }
+
+ s = strchr(s, ':');
+
+ if (s) {
+ s++;
+ }
}
return -1;
static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct vnet_nic_state * vnetnic = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
char * macstr = NULL;
- char mac[6];
- int vnet_dev_id;
-
+ int vnet_dev_id = 0;
v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
+
macstr = v3_cfg_val(frontend_cfg, "mac");
if (macstr == NULL) {
- PrintDebug("Vnet-nic: No Mac specified\n");
- } else {
- str2mac(macstr, mac);
+ PrintDebug("Vnet-nic configuration error: No Mac specified\n");
+ return -1;
}
vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
memset(vnetnic, 0, sizeof(struct vnet_nic_state));
- struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnetnic);
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, vnetnic);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
+
+
vnetnic->net_ops.send = vnet_send;
- memcpy(vnetnic->mac, mac, 6);
+ str2mac(macstr, vnetnic->mac);
vnetnic->vm = vm;
if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"),
&(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) {
PrintError("Could not connect %s to frontend %s\n",
- name, v3_cfg_val(frontend_cfg, "tag"));
+ dev_id, v3_cfg_val(frontend_cfg, "tag"));
return -1;
}
PrintDebug("Vnet-nic: Connect %s to frontend %s\n",
- name, v3_cfg_val(frontend_cfg, "tag"));
+ dev_id, v3_cfg_val(frontend_cfg, "tag"));
- if ((vnet_dev_id = register_to_vnet(vm, vnetnic, name, vnetnic->mac)) == -1) {
- PrintError("Vnet-nic device %s (mac: %s) fails to registered to VNET\n", name, macstr);
+ if ((vnet_dev_id = register_to_vnet(vm, vnetnic, dev_id, vnetnic->mac)) == -1) {
+ PrintError("Vnet-nic device %s (mac: %s) fails to registered to VNET\n", dev_id, macstr);
+ return -1;
}
- vnetnic->vnet_dev_id = vnet_dev_id;
-
- PrintDebug("Vnet-nic device %s (mac: %s, %ld) registered to VNET\n", name, macstr, *((ulong_t *)vnetnic->mac));
+ vnetnic->vnet_dev_id = vnet_dev_id;
-//for temporary hack for vnet bridge test
-#if 1
- {
- uchar_t zeromac[6] = {0,0,0,0,0,0};
-
- if(!strcmp(name, "vnet_nic")){
- struct v3_vnet_route route;
-
- route.dst_id = vnet_dev_id;
- route.dst_type = LINK_INTERFACE;
- route.src_id = 0;
- route.src_type = LINK_EDGE;
- memcpy(route.dst_mac, zeromac, 6);
- route.dst_mac_qual = MAC_ANY;
- memcpy(route.src_mac, zeromac, 6);
- route.src_mac_qual = MAC_ANY;
- v3_vnet_add_route(route);
-
-
- route.dst_id = 0;
- route.dst_type = LINK_EDGE;
- route.src_id = vnet_dev_id;
- route.src_type = LINK_INTERFACE;
- memcpy(route.dst_mac, zeromac, 6);
- route.dst_mac_qual = MAC_ANY;
- memcpy(route.src_mac, zeromac, 6);
- route.src_mac_qual = MAC_ANY;
-
- v3_vnet_add_route(route);
- }
- }
-#endif
+ PrintDebug("Vnet-nic device %s (mac: %s, %ld) registered to VNET\n", dev_id, macstr, *((uint32_t *)vnetnic->mac));
-//for temporary hack for Linux bridge (w/o encapuslation) test
-#if 0
- {
- static int vnet_nic_guestid = -1;
- static int vnet_nic_dom0 = -1;
- uchar_t zeromac[6] = {0,0,0,0,0,0};
-
- if(!strcmp(name, "vnet_nic")){ //domu
- vnet_nic_guestid = vnet_dev_id;
- }
- if (!strcmp(name, "vnet_nic_dom0")){
- vnet_nic_dom0 = vnet_dev_id;
- }\r
-
- if(vnet_nic_guestid != -1 && vnet_nic_dom0 !=-1){
- struct v3_vnet_route route;
-
- route.src_id = vnet_nic_guestid;
- route.src_type = LINK_INTERFACE;
- route.dst_id = vnet_nic_dom0;
- route.dst_type = LINK_INTERFACE;
- memcpy(route.dst_mac, zeromac, 6);
- route.dst_mac_qual = MAC_ANY;
- memcpy(route.src_mac, zeromac, 6);
- route.src_mac_qual = MAC_ANY;
- v3_vnet_add_route(route);
-
-
- route.src_id = vnet_nic_dom0;
- route.src_type = LINK_INTERFACE;
- route.dst_id = vnet_nic_guestid;
- route.dst_type = LINK_INTERFACE;
- memcpy(route.dst_mac, zeromac, 6);
- route.dst_mac_qual = MAC_ANY;
- memcpy(route.src_mac, zeromac, 6);
- route.src_mac_qual = MAC_ANY;
-
- v3_vnet_add_route(route);
- }
- }
-#endif
return 0;
}
obj-$(CONFIG_INSTRUMENT_VMM) += vmm_instrument.o
obj-$(CONFIG_TELEMETRY) += vmm_telemetry.o
obj-$(CONFIG_SOCKET) += vmm_socket.o
-obj-$(CONFIG_CONSOLE) += vmm_console.o
obj-$(CONFIG_VNET) += vmm_vnet.o
+obj-$(CONFIG_FILE) += vmm_file.o
+
obj-$(CONFIG_SYMBIOTIC) += vmm_symbiotic.o vmm_symspy.o
obj-$(CONFIG_SYMCALL) += vmm_symcall.o
* *
* *
*/
-static int handle_4MB_shadow_pagefault_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
- pte32_t * shadow_pt, pde32_4MB_t * large_guest_pde);
+static int handle_4MB_shadow_pagefault_pde_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
+ pt_access_status_t shadow_pde_access, pde32_4MB_t * large_shadow_pde,
+ pde32_4MB_t * large_guest_pde);
+static int handle_4MB_shadow_pagefault_pte_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
+ pte32_t * shadow_pt, pde32_4MB_t * large_guest_pde);
static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
pte32_t * shadow_pt, pte32_t * guest_pt);
// Get the next shadow page level, allocate if not present
if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) {
+
+ if (info->use_large_pages && guest_pde->large_page) {
+ // Check underlying physical memory map to see if a large page is viable
+ addr_t guest_pa = BASE_TO_PAGE_ADDR_4MB(((pde32_4MB_t *)guest_pde)->page_base_addr);
+ addr_t host_pa;
+ if (v3_get_max_page_size(info, guest_pa, PAGE_SIZE_4MB) < PAGE_SIZE_4MB) {
+ PrintDebug("Underlying physical memory map doesn't allow use of a large page.\n");
+ // Fallthrough to small pages
+ } else if ((v3_gpa_to_hpa(info, guest_pa, &host_pa) != 0)
+ || (v3_compute_page_alignment(host_pa) < PAGE_SIZE_4MB)) {
+ PrintDebug("Host memory alignment doesn't allow use of a large page.\n");
+ // Fallthrough to small pages
+ } else if (handle_4MB_shadow_pagefault_pde_32(info, fault_addr, error_code, shadow_pde_access,
+ (pde32_4MB_t *)shadow_pde, (pde32_4MB_t *)guest_pde) == 0) {
+ return 0;
+ } else {
+ PrintError("Error handling large pagefault with large page\n");
+ return -1;
+ }
+ // Fallthrough to handle the region with small pages
+ }
+
struct shadow_page_data * shdw_page = create_new_shadow_pt(info);
shadow_pt = (pte32_t *)V3_VAddr((void *)shdw_page->page_pa);
return -1;
}
} else {
- if (handle_4MB_shadow_pagefault_32(info, fault_addr, error_code, shadow_pt, (pde32_4MB_t *)guest_pde) == -1) {
+ if (handle_4MB_shadow_pagefault_pte_32(info, fault_addr, error_code, shadow_pt, (pde32_4MB_t *)guest_pde) == -1) {
PrintError("Error handling large pagefault\n");
return -1;
}
return 0;
}
-
-
-static int handle_4MB_shadow_pagefault_32(struct guest_info * info,
+// Handle a 4MB page fault with small pages in the PTE
+static int handle_4MB_shadow_pagefault_pte_32(struct guest_info * info,
addr_t fault_addr, pf_error_t error_code,
pte32_t * shadow_pt, pde32_4MB_t * large_guest_pde)
{
return -1;
}
- PrintDebug("Returning from large page fault handler\n");
+ PrintDebug("Returning from large page->small page fault handler\n");
return 0;
}
+// Handle a 4MB page fault with a 4MB page in the PDE
+static int handle_4MB_shadow_pagefault_pde_32(struct guest_info * info,
+ addr_t fault_addr, pf_error_t error_code,
+ pt_access_status_t shadow_pde_access,
+ pde32_4MB_t * large_shadow_pde, pde32_4MB_t * large_guest_pde)
+{
+ addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_4MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_4MB(fault_addr);
+
+
+ PrintDebug("Handling 4MB fault with large page (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
+ PrintDebug("LargeShadowPDE=%p, LargeGuestPDE=%p\n", large_shadow_pde, large_guest_pde);
+
+ struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
+
+
+ if (shdw_reg == NULL) {
+ // Inject a machine check in the guest
+ PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
+ v3_raise_exception(info, MC_EXCEPTION);
+ return -1;
+ }
+
+ if (shadow_pde_access == PT_ACCESS_OK) {
+ // Inconsistent state...
+ // Guest Re-Entry will flush tables and everything should now workd
+ PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
+ return 0;
+ }
+
+
+ if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) {
+ // Get the guest physical address of the fault
+
+ if ((shdw_reg->flags.alloced == 1) &&
+ (shdw_reg->flags.read == 1)) {
+ addr_t shadow_pa = 0;
+
+ if (v3_gpa_to_hpa(info, guest_fault_pa, &shadow_pa) == -1) {
+ PrintError("could not translate page fault address (%p)\n", (void *)guest_fault_pa);
+ return -1;
+ }
+ PrintDebug("\tMapping shadow page (%p)\n", (void *)BASE_TO_PAGE_ADDR(shadow_pte->page_base_addr));
+ large_guest_pde->vmm_info = V3_LARGE_PG; /* For invalidations */
+ large_shadow_pde->page_base_addr = PAGE_BASE_ADDR_4MB(shadow_pa);
+ large_shadow_pde->large_page = 1;
+ large_shadow_pde->present = 1;
+ large_shadow_pde->user_page = 1;
+ if (shdw_reg->flags.write == 0) {
+ large_shadow_pde->writable = 0;
+ } else {
+ large_shadow_pde->writable = 1;
+ }
+ //set according to VMM policy
+ large_shadow_pde->write_through = large_guest_pde->write_through;
+ large_shadow_pde->cache_disable = large_guest_pde->cache_disable;
+ large_shadow_pde->global_page = large_guest_pde->global_page;
+ //
+ } else {
+ if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
+ PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
+ return -1;
+ }
+ }
+ } else if (shadow_pde_access == PT_ACCESS_WRITE_ERROR) {
+ if (shdw_reg->flags.write == 0) {
+ if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
+ PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
+ return -1;
+ }
+ }
+ } else {
+ PrintError("Error in large page fault handler...\n");
+ PrintError("This case should have been handled at the top level handler\n");
+ return -1;
+ }
+ PrintDebug("Returning from large page->large page fault handler\n");
+ return 0;
+}
/* If we start to optimize we should look up the guest pages in the cache... */
static inline int handle_shadow_invlpg_32(struct guest_info * info, addr_t vaddr) {
* *
*/
-static int handle_2MB_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
- pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde);
+static int handle_2MB_shadow_pagefault_pde_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
+ pt_access_status_t shadow_pde_access, pde64_2MB_t * shadow_pt,
+ pde64_2MB_t * large_guest_pde);
+static int handle_2MB_shadow_pagefault_pte_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
+ pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde);
static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
pte64_t * shadow_pt, pte64_t * guest_pt);
return 0;
}
-
static int handle_pde_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
pde64_t * shadow_pd, pde64_t * guest_pd) {
pt_access_status_t guest_pde_access;
return 0;
}
-
pte64_t * shadow_pt = NULL;
pte64_t * guest_pt = NULL;
- // Get the next shadow page level, allocate if not present
-
+ // get the next shadow page level, allocate if not present
if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) {
+ // Check if we can use large pages and the guest memory is properly aligned
+ // to potentially use a large page
+ if (info->use_large_pages && guest_pde->large_page) {
+ // Check underlying physical memory map to see if a large page is viable
+ addr_t guest_pa = BASE_TO_PAGE_ADDR_2MB(((pde64_2MB_t *)guest_pde)->page_base_addr);
+ addr_t host_pa;
+ if (v3_get_max_page_size(info, guest_pa, PAGE_SIZE_2MB) < PAGE_SIZE_2MB) {
+ PrintDebug("Underlying physical memory map doesn't allow use of a large page.\n");
+ // Fallthrough to small pages
+ } else if ((v3_gpa_to_hpa(info, guest_pa, &host_pa) != 0)
+ || (v3_compute_page_alignment(host_pa) < PAGE_SIZE_2MB)) {
+ PrintDebug("Host memory alignment doesn't allow use of a large page.\n");
+ // Fallthrough to small pages
+ } else if (handle_2MB_shadow_pagefault_pde_64(info, fault_addr, error_code, shadow_pde_access,
+ (pde64_2MB_t *)shadow_pde, (pde64_2MB_t *)guest_pde) == 0) {
+ return 0;
+ } else {
+ PrintError("Error handling large pagefault with large page\n");
+ return -1;
+ }
+ // Fallthrough to handle the region with small pages
+ }
+
struct shadow_page_data * shdw_page = create_new_shadow_pt(info);
shadow_pt = (pte64_t *)V3_VAddr((void *)shdw_page->page_pa);
return -1;
}
} else {
- if (handle_2MB_shadow_pagefault_64(info, fault_addr, error_code, shadow_pt, (pde64_2MB_t *)guest_pde) == -1) {
- PrintError("Error handling large pagefault\n");
+ if (handle_2MB_shadow_pagefault_pte_64(info, fault_addr, error_code, shadow_pt, (pde64_2MB_t *)guest_pde) == -1) {
+ PrintError("Error handling large pagefault with small page\n");
return -1;
}
}
}
+static int handle_2MB_shadow_pagefault_pde_64(struct guest_info * info,
+ addr_t fault_addr, pf_error_t error_code,
+ pt_access_status_t shadow_pde_access,
+ pde64_2MB_t * large_shadow_pde, pde64_2MB_t * large_guest_pde)
+{
+ addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_2MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_2MB(fault_addr);
+ // struct shadow_page_state * state = &(info->shdw_pg_state);
+
+ PrintDebug("Handling 2MB fault with large page (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
+ PrintDebug("LargeShadowPDE=%p, LargeGuestPDE=%p\n", large_shadow_pde, large_guest_pde);
+
+ struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
+
+ if (shdw_reg == NULL) {
+ // Inject a machine check in the guest
+ PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
+ v3_raise_exception(info, MC_EXCEPTION);
+ return 0;
+ }
+
+ if (shadow_pde_access == PT_ACCESS_OK) {
+ // Inconsistent state...
+ // Guest Re-Entry will flush tables and everything should now workd
+ PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
+ //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
+ return 0;
+ }
+
+
+ if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) {
+ // Get the guest physical address of the fault
+
+ if ((shdw_reg->flags.alloced == 1) ||
+ (shdw_reg->flags.read == 1)) {
+ addr_t shadow_pa = 0;
+
+ if (v3_gpa_to_hpa(info, guest_fault_pa, &shadow_pa) == -1) {
+ PrintError("could not translate page fault address (%p)\n", (void *)guest_fault_pa);
+ return -1;
+ }
+
+ large_guest_pde->vmm_info = V3_LARGE_PG; /* For invalidations */
+ large_shadow_pde->page_base_addr = PAGE_BASE_ADDR_2MB(shadow_pa);
+ large_shadow_pde->large_page = 1;
+ large_shadow_pde->present = 1;
+ large_shadow_pde->user_page = 1;
+
+ if (shdw_reg->flags.write == 0) {
+ large_shadow_pde->writable = 0;
+ } else {
+ large_shadow_pde->writable = 1;
+ }
+
+ //set according to VMM policy
+ large_shadow_pde->write_through = large_guest_pde->write_through;
+ large_shadow_pde->cache_disable = large_guest_pde->cache_disable;
+ large_shadow_pde->global_page = large_guest_pde->global_page;
+ //
+
+ } else {
+ if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
+ PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
+ return -1;
+ }
+ }
+ } else if (shadow_pde_access == PT_ACCESS_WRITE_ERROR) {
+ if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
+ PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
+ return -1;
+ }
+ } else {
+ PrintError("Error in large page fault handler...\n");
+ PrintError("This case should have been handled at the top level handler\n");
+ return -1;
+ }
+
+ // PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
+ PrintDebug("Returning from large page->large page fault handler\n");
+ return 0;
+}
-static int handle_2MB_shadow_pagefault_64(struct guest_info * info,
- addr_t fault_addr, pf_error_t error_code,
- pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde)
+static int handle_2MB_shadow_pagefault_pte_64(struct guest_info * info,
+ addr_t fault_addr, pf_error_t error_code,
+ pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde)
{
pt_access_status_t shadow_pte_access = v3_can_access_pte64(shadow_pt, fault_addr, error_code);
pte64_t * shadow_pte = (pte64_t *)&(shadow_pt[PTE64_INDEX(fault_addr)]);
}
// PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
- PrintDebug("Returning from large page fault handler\n");
+ PrintDebug("Returning from large page->small page fault handler\n");
return 0;
}
uint_t rep_num = 1;
ullong_t mask = 0;
addr_t inst_ptr;
- struct v3_segment * theseg = &(core->segments.es); // default is ES
+ struct v3_segment * theseg = &(core->segments.ds); // default is DS
// This is kind of hacky...
// direction can equal either 1 or -1
return cfg;
}
+
+static inline uint32_t get_alignment(char * align_str) {
+ // default is 4KB alignment
+ uint32_t alignment = PAGE_SIZE_4KB;
+
+ if (align_str != NULL) {
+ if (strcasecmp(align_str, "2MB") == 0) {
+ alignment = PAGE_SIZE_2MB;
+ } else if (strcasecmp(align_str, "4MB") == 0) {
+ alignment = PAGE_SIZE_4MB;
+ }
+ }
+
+#ifndef CONFIG_ALIGNED_PG_ALLOC
+ if (alignment != PAGE_SIZE_4KB) {
+ PrintError("Aligned page allocations are not supported in this host (requested alignment=%d)\n", alignment);
+ PrintError("Ignoring alignment request\n");
+ }
+#endif
+
+ return alignment;
+}
static int pre_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * vm_cfg) {
char * memory_str = v3_cfg_val(vm_cfg, "memory");
char * schedule_hz_str = v3_cfg_val(vm_cfg, "schedule_hz");
char * vm_class = v3_cfg_val(vm_cfg, "class");
+ char * align_str = v3_cfg_val(v3_cfg_subtree(vm_cfg, "memory"), "alignment");
uint32_t sched_hz = 100; // set the schedule frequency to 100 HZ
if (!memory_str) {
}
PrintDebug("Memory=%s\n", memory_str);
+ if (align_str) {
+ PrintDebug("Alignment=%s\n", align_str);
+ } else {
+ PrintDebug("Alignment defaulted to 4KB.\n");
+ }
// Amount of ram the Guest will have, always in MB
- vm->mem_size = (unsigned long)atoi(memory_str) * 1024UL * 1024UL;
-
+ vm->mem_size = atoi(memory_str) * 1024 * 1024;
+ vm->mem_align = get_alignment(align_str);
+
+ PrintDebug("Alignment computed as 0x%x\n", vm->mem_align);
+
if (strcasecmp(vm_class, "PC") == 0) {
vm->vm_class = V3_PC_VM;
} else {
info->shdw_pg_mode = SHADOW_PAGING;
}
+
if (info->shdw_pg_mode == NESTED_PAGING) {
PrintDebug("Guest Paging Mode: NESTED_PAGING\n");
if (strcasecmp(page_size, "4kb") == 0) { /* TODO: this may not be an ideal place for this */
PrintError("Guest paging mode incorrectly set.\n");
return -1;
}
+
+ if (strcasecmp(v3_cfg_val(pg_tree, "large_pages"), "true") == 0) {
+ info->use_large_pages = 1;
+ PrintDebug("Use of large pages in memory virtualization enabled.\n");
+ }
+
return 0;
}
while (device) {
- char * id = v3_cfg_val(device, "id");
+ char * dev_class = v3_cfg_val(device, "class");
- V3_Print("configuring device %s\n", id);
+ V3_Print("configuring device %s\n", dev_class);
- if (v3_create_device(vm, id, device) == -1) {
- PrintError("Error creating device %s\n", id);
+ if (v3_create_device(vm, dev_class, device) == -1) {
+ PrintError("Error creating device %s\n", dev_class);
return -1;
}
// Reference: AMD Software Developer Manual Vol.2 Ch.5 "Page Translation and Protection"
-static inline int handle_passthrough_pagefault_64(struct guest_info * info,
- addr_t fault_addr,
- pf_error_t error_code) {
+static inline int handle_passthrough_pagefault_64(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
pml4e64_t * pml = NULL;
pdpe64_t * pdpe = NULL;
pde64_t * pde = NULL;
int pde_index = PDE64_INDEX(fault_addr);
int pte_index = PTE64_INDEX(fault_addr);
- struct v3_mem_region * region = v3_get_mem_region(info->vm_info, info->cpu_id, fault_addr);
- struct v3_mem_region * base_reg = &(info->vm_info->mem_map.base_region);
-
- /* If the guest has been configured for 2MiB pages, then we must check for hooked regions of
- * memory which may overlap with the 2MiB page containing the faulting address (due to
- * potentially differing access policies in place for e.g. i/o devices and APIC). A 2MiB page
- * can be used if a) no region overlaps the page [or b) a region does overlap but fully contains
- * the page]. The [bracketed] text pertains to the #if 0'd code below, state D. TODO modify this
- * note if someone decides to enable this optimization. It can be tested with the SeaStar
- * mapping.
- *
- * Examples: (CAPS regions are returned by v3_get_next_mem_region; state A returns the base reg)
- *
- * |region| |region| 2MiB mapped (state A)
- * |reg| |REG| 2MiB mapped (state B)
- * |region| |reg| |REG| |region| |reg| 4KiB mapped (state C)
- * |reg| |reg| |--REGION---| [2MiB mapped (state D)]
- * |--------------------------------------------| RAM
- * ^ fault addr
- * |----|----|----|----|----|page|----|----|----| 2MB pages
- * >>>>>>>>>>>>>>>>>>>> search space
- */
- addr_t pg_start = 0UL, pg_end = 0UL; // 2MiB page containing the faulting address
- struct v3_mem_region * pg_next_reg = NULL; // next immediate mem reg after page start addr
- bool use_large_page = false;
+ struct v3_mem_region * region = v3_get_mem_region(core->vm_info, core->cpu_id, fault_addr);
+ int page_size = PAGE_SIZE_4KB;
if (region == NULL) {
PrintError("%s: invalid region, addr=%p\n", __FUNCTION__, (void *)fault_addr);
return -1;
}
- // set use_large_page here
- if (info->vm_info->paging_size == PAGING_2MB) {
-
- // guest page maps to a host page + offset (so when we shift, it aligns with a host page)
- pg_start = PAGE_ADDR_2MB(fault_addr);
- pg_end = (pg_start + PAGE_SIZE_2MB);
-
- PrintDebug("%s: page [%p,%p) contains address\n", __FUNCTION__, (void *)pg_start, (void *)pg_end);
-
- pg_next_reg = v3_get_next_mem_region(info->vm_info, info->cpu_id, pg_start);
-
- if (pg_next_reg == NULL) {
- PrintError("%s: Error: address not in base region, %p\n", __FUNCTION__, (void *)fault_addr);
- return -1;
- }
-
- if ((pg_next_reg->guest_start == base_reg->guest_start) &&
- (pg_next_reg->guest_end == base_reg->guest_end)) { // next region == base region
- use_large_page = 1; // State A
- } else {
-#if 0 // State B/C and D optimization
- use_large_page = (pg_next_reg->guest_end >= pg_end) &&
- ((pg_next_reg->guest_start >= pg_end) || (pg_next_reg->guest_start <= pg_start));
- PrintDebug("%s: region [%p,%p) %s partial overlap with page\n", __FUNCTION__,
- (void *)pg_next_reg->guest_start, (void *)pg_next_reg->guest_end,
- (use_large_page ? "does not have" : "has"));
-#else // State B/C
- use_large_page = (pg_next_reg->guest_start >= pg_end);
- PrintDebug("%s: region [%p,%p) %s overlap with page\n", __FUNCTION__,
- (void *)pg_next_reg->guest_start, (void *)pg_next_reg->guest_end,
- (use_large_page ? "does not have" : "has"));
-#endif
- }
+ /* Check if:
+ * 1. the guest is configured to use large pages and
+ * 2. the memory regions can be referenced by a large page
+ */
+ if ((core->use_large_pages == 1) ) {
+ page_size = v3_get_max_page_size(core, fault_addr, PAGE_SIZE_2MB);
}
- PrintDebug("%s: Address gets a 2MiB page? %s\n", __FUNCTION__, (use_large_page ? "yes" : "no"));
+ PrintDebug("Using page size of %dKB\n", page_size / 1024);
+
// Lookup the correct PML address based on the PAGING MODE
- if (info->shdw_pg_mode == SHADOW_PAGING) {
- pml = CR3_TO_PML4E64_VA(info->ctrl_regs.cr3);
+ if (core->shdw_pg_mode == SHADOW_PAGING) {
+ pml = CR3_TO_PML4E64_VA(core->ctrl_regs.cr3);
} else {
- pml = CR3_TO_PML4E64_VA(info->direct_map_pt);
+ pml = CR3_TO_PML4E64_VA(core->direct_map_pt);
}
//Fix up the PML entry
pml[pml_index].writable = 1;
pml[pml_index].user_page = 1;
- pml[pml_index].pdp_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pdpe));
+ pml[pml_index].pdp_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pdpe));
} else {
pdpe = V3_VAddr((void*)BASE_TO_PAGE_ADDR_4KB(pml[pml_index].pdp_base_addr));
}
pdpe[pdpe_index].writable = 1;
pdpe[pdpe_index].user_page = 1;
- pdpe[pdpe_index].pd_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pde));
+ pdpe[pdpe_index].pd_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pde));
} else {
pde = V3_VAddr((void*)BASE_TO_PAGE_ADDR_4KB(pdpe[pdpe_index].pd_base_addr));
}
// Fix up the 2MiB PDE and exit here
- if (use_large_page) {
-
+ if (page_size == PAGE_SIZE_2MB) {
pde2mb = (pde64_2MB_t *)pde; // all but these two lines are the same for PTE
pde2mb[pde_index].large_page = 1;
if (pde2mb[pde_index].present == 0) {
pde2mb[pde_index].user_page = 1;
- if ((region->flags.alloced == 1) && (region->flags.read == 1)) {
+ if ( (region->flags.alloced == 1) &&
+ (region->flags.read == 1)) {
// Full access
pde2mb[pde_index].present = 1;
pde2mb[pde_index].writable = 0;
}
- if (v3_gpa_to_hpa(info, fault_addr, &host_addr) == -1) {
+ if (v3_gpa_to_hpa(core, fault_addr, &host_addr) == -1) {
PrintError("Error Could not translate fault addr (%p)\n", (void *)fault_addr);
return -1;
}
pde2mb[pde_index].page_base_addr = PAGE_BASE_ADDR_2MB(host_addr);
} else {
- return region->unhandled(info, fault_addr, fault_addr, region, error_code);
+ return region->unhandled(core, fault_addr, fault_addr, region, error_code);
}
} else {
- // We fix all permissions on the first pass,
+ // We fix all permissions on the first pass,
// so we only get here if its an unhandled exception
- return region->unhandled(info, fault_addr, fault_addr, region, error_code);
+ return region->unhandled(core, fault_addr, fault_addr, region, error_code);
}
- }
- // Continue with the 4KiB page heirarchy
+ // All done
+ return 0;
+ }
+ // Continue with the 4KiB page heirarchy
+
// Fix up the PDE entry
if (pde[pde_index].present == 0) {
pte = (pte64_t *)create_generic_pt_page();
pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR_4KB(pde[pde_index].pt_base_addr));
}
-
// Fix up the PTE entry
if (pte[pte_index].present == 0) {
pte[pte_index].user_page = 1;
pte[pte_index].writable = 0;
}
- if (v3_gpa_to_hpa(info, fault_addr, &host_addr) == -1) {
+ if (v3_gpa_to_hpa(core, fault_addr, &host_addr) == -1) {
PrintError("Error Could not translate fault addr (%p)\n", (void *)fault_addr);
return -1;
}
pte[pte_index].page_base_addr = PAGE_BASE_ADDR_4KB(host_addr);
} else {
- return region->unhandled(info, fault_addr, fault_addr, region, error_code);
+ return region->unhandled(core, fault_addr, fault_addr, region, error_code);
}
} else {
// We fix all permissions on the first pass,
// so we only get here if its an unhandled exception
- return region->unhandled(info, fault_addr, fault_addr, region, error_code);
+ return region->unhandled(core, fault_addr, fault_addr, region, error_code);
}
return 0;
}
-static inline int invalidate_addr_64(struct guest_info * info, addr_t inv_addr) {
+static inline int invalidate_addr_64(struct guest_info * core, addr_t inv_addr) {
pml4e64_t * pml = NULL;
pdpe64_t * pdpe = NULL;
pde64_t * pde = NULL;
// Lookup the correct PDE address based on the PAGING MODE
- if (info->shdw_pg_mode == SHADOW_PAGING) {
- pml = CR3_TO_PML4E64_VA(info->ctrl_regs.cr3);
+ if (core->shdw_pg_mode == SHADOW_PAGING) {
+ pml = CR3_TO_PML4E64_VA(core->ctrl_regs.cr3);
} else {
- pml = CR3_TO_PML4E64_VA(info->direct_map_pt);
+ pml = CR3_TO_PML4E64_VA(core->direct_map_pt);
}
if (pml[pml_index].present == 0) {
--- /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) 2010, Peter Dinda <pdinda@northwestern.edu>
+ * Copyright (c) 2010, 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".
+ */
+
+
+#include <palacios/vmm_file.h>
+#include <palacios/vmm.h>
+#include <palacios/vmm_debug.h>
+#include <palacios/vmm_types.h>
+
+
+struct v3_file_hooks * file_hooks = 0;
+
+void V3_Init_File(struct v3_file_hooks * hooks) {
+ file_hooks = hooks;
+ PrintDebug("V3 file access inited\n");
+
+ return;
+}
return -1;
}
-
-
int v3_init_mem_map(struct v3_vm_info * vm) {
struct v3_mem_map * map = &(vm->mem_map);
addr_t mem_pages = vm->mem_size >> 12;
map->mem_regions.rb_node = NULL;
-
// There is an underlying region that contains all of the guest memory
// PrintDebug("Mapping %d pages of memory (%u bytes)\n", (int)mem_pages, (uint_t)info->mem_size);
// 2MB page alignment needed for 2MB hardware nested paging
map->base_region.guest_start = 0;
map->base_region.guest_end = mem_pages * PAGE_SIZE_4KB;
- map->base_region.host_addr = (addr_t)V3_AllocAlignedPages(mem_pages, PAGE_SIZE_2MB);
+
+#ifdef CONFIG_ALIGNED_PG_ALLOC
+ map->base_region.host_addr = (addr_t)V3_AllocAlignedPages(mem_pages, vm->mem_align);
+#else
+ map->base_region.host_addr = (addr_t)V3_AllocPages(mem_pages);
+#endif
map->base_region.flags.read = 1;
map->base_region.flags.write = 1;
-/* Search the "hooked" memory regions for a region that ends after the given address. If the
- * address is invalid, return NULL. Else, return the first region found or the base region if no
- * region ends after the given address.
+/* Given an address, find the successor region. If the address is within a region, return that
+ * region. Input is an address, because the address may not have a region associated with it.
+ *
+ * Returns a region following or touching the given address. If address is invalid, NULL is
+ * returned, else the base region is returned if no region exists at or after the given address.
*/
struct v3_mem_region * v3_get_next_mem_region( struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr) {
- struct rb_node * n = vm->mem_map.mem_regions.rb_node;
- struct v3_mem_region * reg = NULL;
-
- // Keep going to the right in the tree while the address is greater than the current region's
- // end address.
- while (n) {
- reg = rb_entry(n, struct v3_mem_region, tree_node);
- if (guest_addr >= reg->guest_end) { // reg is [start,end)
- n = n->rb_right;
- } else {
- if ((core_id == reg->core_id) || (reg->core_id == V3_MEM_CORE_ANY)) {
- return reg;
- } else {
- n = n->rb_right;
+ struct rb_node * current_n = vm->mem_map.mem_regions.rb_node;
+ struct rb_node * successor_n = NULL; /* left-most node greater than guest_addr */
+ struct v3_mem_region * current_r = NULL;
+
+ /* current_n tries to find the region containing guest_addr, going right when smaller and left when
+ * greater. Each time current_n becomes greater than guest_addr, update successor <- current_n.
+ * current_n becomes successively closer to guest_addr than the previous time it was greater
+ * than guest_addr.
+ */
+
+ /* | is address, ---- is region, + is intersection */
+ while (current_n) {
+ current_r = rb_entry(current_n, struct v3_mem_region, tree_node);
+ if (current_r->guest_start > guest_addr) { /* | ---- */
+ successor_n = current_n;
+ current_n = current_n->rb_left;
+ } else {
+ if (current_r->guest_end > guest_addr) {
+ return current_r; /* +--- or --+- */
}
- }
+ current_n = current_n->rb_right; /* ---- | */
+ }
}
- // There is no registered region, so we check if it's a valid address in the base region
+ /* Address does not have its own region. Check if it's a valid address in the base region */
if (guest_addr >= vm->mem_map.base_region.guest_end) {
PrintError("%s: Guest Address Exceeds Base Memory Size (ga=%p), (limit=%p)\n",
}
+// Determine if a given address can be handled by a large page of the requested size
+uint32_t v3_get_max_page_size(struct guest_info * core, addr_t fault_addr, uint32_t req_size) {
+ addr_t pg_start = 0UL, pg_end = 0UL; // large page containing the faulting addres
+ struct v3_mem_region * pg_next_reg = NULL; // next immediate mem reg after page start addr
+ uint32_t page_size = PAGE_SIZE_4KB;
+
+ /* If the guest has been configured for large pages, then we must check for hooked regions of
+ * memory which may overlap with the large page containing the faulting address (due to
+ * potentially differing access policies in place for e.g. i/o devices and APIC). A large page
+ * can be used if a) no region overlaps the page [or b) a region does overlap but fully contains
+ * the page]. The [bracketed] text pertains to the #if 0'd code below, state D. TODO modify this
+ * note if someone decides to enable this optimization. It can be tested with the SeaStar
+ * mapping.
+ *
+ * Examples: (CAPS regions are returned by v3_get_next_mem_region; state A returns the base reg)
+ *
+ * |region| |region| 2MiB mapped (state A)
+ * |reg| |REG| 2MiB mapped (state B)
+ * |region| |reg| |REG| |region| |reg| 4KiB mapped (state C)
+ * |reg| |reg| |--REGION---| [2MiB mapped (state D)]
+ * |--------------------------------------------| RAM
+ * ^ fault addr
+ * |----|----|----|----|----|page|----|----|----| 2MB pages
+ * >>>>>>>>>>>>>>>>>>>> search space
+ */
+
+
+ // guest page maps to a host page + offset (so when we shift, it aligns with a host page)
+ switch (req_size) {
+ case PAGE_SIZE_4KB:
+ return PAGE_SIZE_4KB;
+ case PAGE_SIZE_2MB:
+ pg_start = PAGE_ADDR_2MB(fault_addr);
+ pg_end = (pg_start + PAGE_SIZE_2MB);
+ break;
+ case PAGE_SIZE_4MB:
+ pg_start = PAGE_ADDR_4MB(fault_addr);
+ pg_end = (pg_start + PAGE_SIZE_4MB);
+ break;
+ case PAGE_SIZE_1GB:
+ pg_start = PAGE_ADDR_1GB(fault_addr);
+ pg_end = (pg_start + PAGE_SIZE_1GB);
+ break;
+ default:
+ PrintError("Invalid large page size requested.\n");
+ return -1;
+ }
+
+ //PrintDebug("%s: page [%p,%p) contains address\n", __FUNCTION__, (void *)pg_start, (void *)pg_end);
+
+ pg_next_reg = v3_get_next_mem_region(core->vm_info, core->cpu_id, pg_start);
+ if (pg_next_reg == NULL) {
+ PrintError("%s: Error: address not in base region, %p\n", __FUNCTION__, (void *)fault_addr);
+ return PAGE_SIZE_4KB;
+ }
+
+ if (pg_next_reg->flags.base == 1) {
+ page_size = req_size; // State A
+ //PrintDebug("%s: base region [%p,%p) contains page.\n", __FUNCTION__,
+ // (void *)pg_next_reg->guest_start, (void *)pg_next_reg->guest_end);
+ } else {
+#if 0 // State B/C and D optimization
+ if ((pg_next_reg->guest_end >= pg_end) &&
+ ((pg_next_reg->guest_start >= pg_end) || (pg_next_reg->guest_start <= pg_start))) {
+ page_size = req_size;
+ }
+
+ PrintDebug("%s: region [%p,%p) %s partially overlap with page\n", __FUNCTION__,
+ (void *)pg_next_reg->guest_start, (void *)pg_next_reg->guest_end,
+ (page_size == req_size) ? "does not" : "does");
+
+#else // State B/C
+ if (pg_next_reg->guest_start >= pg_end) {
+
+ page_size = req_size;
+ }
+
+ PrintDebug("%s: region [%p,%p) %s overlap with page\n", __FUNCTION__,
+ (void *)pg_next_reg->guest_start, (void *)pg_next_reg->guest_end,
+ (page_size == req_size) ? "does not" : "does");
+
+#endif
+ }
+
+ return page_size;
+}
+
+// For an address on a page of size page_size, compute the actual alignment
+// of the physical page it maps to
+uint32_t v3_compute_page_alignment(addr_t page_addr)
+{
+ if (PAGE_OFFSET_1GB(page_addr) == 0) {
+ return PAGE_SIZE_1GB;
+ } else if (PAGE_OFFSET_4MB(page_addr) == 0) {
+ return PAGE_SIZE_4MB;
+ } else if (PAGE_OFFSET_2MB(page_addr) == 0) {
+ return PAGE_SIZE_2MB;
+ } else if (PAGE_OFFSET_4KB(page_addr) == 0) {
+ return PAGE_SIZE_4KB;
+ } else {
+ PrintError("Non-page aligned address passed to %s.\n", __FUNCTION__);
+ return 0;
+ }
+}
void v3_print_mem_map(struct v3_vm_info * vm) {
struct rb_node * node = v3_rb_first(&(vm->mem_map.mem_regions));
int num;
v3_lock_t lock;
struct v3_vnet_pkt pkts[BRIDGE_BUF_SIZE];
- uint8_t datas[ETHERNET_PACKET_LEN*BRIDGE_BUF_SIZE];
+ uint8_t datas[ETHERNET_PACKET_LEN * BRIDGE_BUF_SIZE];
};
struct vnet_brg_dev {
struct v3_vm_info * vm;
int (*input)(struct v3_vm_info * vm, struct v3_vnet_pkt pkt[], uint16_t pkt_num, void * private_data);
- void (*xcall_input)(void *data);
- int (*polling_pkt)(struct v3_vm_info * vm, void *private_data);
+ void (*xcall_input)(void * data);
+ int (*polling_pkt)(struct v3_vm_info * vm, void * private_data);
int disabled;
int num_routes;
int num_devs;
- struct vnet_brg_dev *bridge;
+ struct vnet_brg_dev * bridge;
v3_lock_t lock;
#ifdef CONFIG_DEBUG_VNET
-static inline void mac_to_string(char mac[6], char * buf) {
+static inline void mac_to_string(uint8_t mac[6], char * buf) {
snprintf(buf, 100, "%d:%d:%d:%d:%d:%d",
mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
}
-static void print_route(struct vnet_route_info *route){
+static void print_route(struct vnet_route_info * route){
char str[50];
+ memset(str, 0, 50);
+
mac_to_string(route->route_def.src_mac, str);
PrintDebug("Src Mac (%s), src_qual (%d)\n",
str, route->route_def.src_mac_qual);
+
mac_to_string(route->route_def.dst_mac, str);
PrintDebug("Dst Mac (%s), dst_qual (%d)\n",
str, route->route_def.dst_mac_qual);
+
PrintDebug("Src dev id (%d), src type (%d)",
route->route_def.src_id,
route->route_def.src_type);
+
PrintDebug("Dst dev id (%d), dst type (%d)\n",
route->route_def.dst_id,
route->route_def.dst_type);
+
if (route->route_def.dst_type == LINK_INTERFACE) {
PrintDebug("dst_dev (%p), dst_dev_id (%d), dst_dev_input (%p), dst_dev_data (%p)\n",
- route->dst_dev,
- route->dst_dev->dev_id,
- route->dst_dev->input,
- route->dst_dev->private_data);
+ route->dst_dev,
+ route->dst_dev->dev_id,
+ route->dst_dev->input,
+ route->dst_dev->private_data);
}
}
-static void dump_routes(){
- struct vnet_route_info *route;
-
+static void dump_routes() {
+ struct vnet_route_info * route = NULL;
int i = 0;
+
PrintDebug("\n========Dump routes starts ============\n");
+
list_for_each_entry(route, &(vnet_state.routes), node) {
- PrintDebug("\nroute %d:\n", ++i);
-
+ PrintDebug("\nroute %d:\n", i++);
print_route(route);
}
+
PrintDebug("\n========Dump routes end ============\n");
}
list_for_each_entry(dev, &(vnet_state.devs), node) {
int dev_id = dev->dev_id;
- if (dev_id == idx)
+ if (dev_id == idx) {
return dev;
+ }
}
return NULL;
struct vnet_dev * dev = NULL;
list_for_each_entry(dev, &(vnet_state.devs), node) {
- if (!memcmp(dev->mac_addr, mac, 6))
+ if (memcmp(dev->mac_addr, mac, 6) == 0) {
return dev;
+ }
}
return NULL;
}
-int get_device_id_by_mac(char mac[6]){
-
- struct vnet_dev *dev = find_dev_by_mac(mac);
-
- if (dev == NULL)
+int get_device_id_by_mac(char mac[6]) {
+ struct vnet_dev * dev = find_dev_by_mac(mac);
+
+ if (dev == NULL) {
return -1;
-
+ }
+
return dev->dev_id;
}
int v3_vnet_add_route(struct v3_vnet_route route) {
struct vnet_route_info * new_route = NULL;
- unsigned long flags;
+ uint32_t flags = 0;
new_route = (struct vnet_route_info *)V3_Malloc(sizeof(struct vnet_route_info));
memset(new_route, 0, sizeof(struct vnet_route_info));
#if 0
static int flush_bridge_pkts(struct vnet_brg_dev *bridge){
- unsigned long flags;
- int num, start, send;
+ uint32_t flags;
+ int num;
+ int start;
+ int send;
struct v3_vnet_bridge_input_args args;
int cpu_id = bridge->vm->cores[0].cpu_id;
int current_core = V3_Get_CPU();
v3_unlock_irqrestore(bridge->recv_buf.lock, flags);
- if(bridge->disabled){
+ if (bridge->disabled) {
PrintDebug("VNET: In flush bridge pkts: Bridge is disabled\n");
return -1;
}
- if(num <= 2 && num > 0){
+ if (num <= 2 && num > 0) {
PrintDebug("VNET: In flush bridge pkts: %d\n", num);
}
- if(num > 0) {
+ if (num > 0) {
PrintDebug("VNET: In flush bridge pkts to bridge, cur_cpu %d, brige_core: %d\n", current_core, cpu_id);
- if (current_core == cpu_id){
- if ((start + num) < BRIDGE_BUF_SIZE){
+ if (current_core == cpu_id) {
+ if ((start + num) < BRIDGE_BUF_SIZE) {
bridge->input(bridge->vm, &(bridge->recv_buf.pkts[start]), num, bridge->private_data);
- }else {
+ } else {
bridge->input(bridge->vm, &(bridge->recv_buf.pkts[start]), (BRIDGE_BUF_SIZE - start), bridge->private_data);
send = num - (BRIDGE_BUF_SIZE - start);
bridge->input(bridge->vm, &(bridge->recv_buf.pkts[0]), send, bridge->private_data);
}
- }else {
+ } else {
args.vm = bridge->vm;
args.private_data = bridge->private_data;
- if ((start + num) < BRIDGE_BUF_SIZE){
+ if ((start + num) < BRIDGE_BUF_SIZE) {
args.pkt_num = num;
args.vnet_pkts = &(bridge->recv_buf.pkts[start]);
V3_Call_On_CPU(cpu_id, bridge->xcall_input, (void *)&args);
- }else {
+ } else {
args.pkt_num = BRIDGE_BUF_SIZE - start;
args.vnet_pkts = &(bridge->recv_buf.pkts[start]);
V3_Call_On_CPU(cpu_id, bridge->xcall_input, (void *)&args);
#endif
static int send_to_bridge(struct v3_vnet_pkt * pkt){
- struct vnet_brg_dev *bridge = vnet_state.bridge;
+ struct vnet_brg_dev * bridge = vnet_state.bridge;
if (bridge == NULL) {
PrintDebug("VNET: No bridge to sent data to links\n");
return -1;
}
- if(bridge->max_delayed_pkts <= 1){
- if(bridge->disabled){
+ if (bridge->max_delayed_pkts <= 1) {
+
+ if (bridge->disabled) {
PrintDebug("VNET: Bridge diabled\n");
return -1;
- }
+ }
-/*
- //avoid the cross-core call here
- int cpu_id = bridge->vm->cores[0].cpu_id;
- struct v3_vnet_bridge_input_args args;
-
- args.pkt_num = 1;
- args.vm = bridge->vm;
- args.vnet_pkts = pkt;
- args.private_data = bridge->private_data;
-
- V3_Call_On_CPU(cpu_id, bridge->xcall_input, (void *)&args);
-*/
bridge->input(bridge->vm, pkt, 1, bridge->private_data);
PrintDebug("VNET: sent one packet to the bridge\n");
- return 0;
- }
-
-/*
- unsigned long flags;
- int end, num=0;
- struct v3_vnet_pkt *buf;
-
- PrintDebug("VNET: send_to_bridge\n");
-
- flags = v3_lock_irqsave(bridge->recv_buf.lock);
-
- if(bridge->disabled && bridge->recv_buf.num >= BRIDGE_BUF_SIZE){
- PrintDebug("Bridge diabled and bridge receive buffer full\n");
- v3_unlock_irqrestore(bridge->recv_buf.lock, flags);//maybe should move this after copy
- num = bridge->recv_buf.num;
- goto exit;
}
-
- end = bridge->recv_buf.end;
- buf = &(bridge->recv_buf.pkts[end]);
-
- bridge->recv_buf.num ++;
- bridge->recv_buf.end ++;
- bridge->recv_buf.end %= BRIDGE_BUF_SIZE;
-
- num = bridge->recv_buf.num;
-
- v3_unlock_irqrestore(bridge->recv_buf.lock, flags);//maybe should move this after copy
- buf->size = pkt->size;
- buf->dst_id = pkt->dst_id;
- buf->src_id = pkt->src_id;
- buf->src_type = pkt->src_type;
- buf->dst_type = pkt->dst_type;
- memcpy(buf->header, pkt->header, ETHERNET_HEADER_LEN);
- memcpy(buf->data, pkt->data, pkt->size);
-
-exit:
-
- if (num >= bridge->max_delayed_pkts){
- flush_bridge_pkts(bridge);
- }
-*/
return 0;
}
int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
struct route_list * matched_routes = NULL;
- unsigned long flags;
- int i;
-
+ uint32_t flags = 0;
+ int i = 0;
+
#ifdef CONFIG_DEBUG_VNET
- {
+ {
struct eth_hdr * hdr = (struct eth_hdr *)(pkt->header);
char dest_str[100];
char src_str[100];
-
+ int cpu = V3_Get_CPU();
+
mac_to_string(hdr->src_mac, src_str);
mac_to_string(hdr->dst_mac, dest_str);
- int cpu = V3_Get_CPU();
PrintDebug("Vnet: on cpu %d, HandleDataOverLink. SRC(%s), DEST(%s), pkt size: %d\n", cpu, src_str, dest_str, pkt->size);
}
#endif
return 0;
}
-void v3_vnet_send_pkt_xcall(void * data){
+void v3_vnet_send_pkt_xcall(void * data) {
struct v3_vnet_pkt * pkt = (struct v3_vnet_pkt *)data;
v3_vnet_send_pkt(pkt, NULL);
}
-void v3_vnet_polling()
-{
- unsigned long flags;
- int num, start;
- struct v3_vnet_pkt *buf;
+void v3_vnet_polling() {
+ uint32_t flags = 0;
+ int num = 0;
+ int start = 0;
+ struct v3_vnet_pkt * buf = NULL;
PrintDebug("In vnet pollling: cpu %d\n", V3_Get_CPU());
PrintDebug("VNET: polling pkts %d\n", num);
- while(num > 0) {
+ while (num > 0) {
buf = &(vnet_state.in_buf.pkts[vnet_state.in_buf.start]);
v3_vnet_send_pkt(buf, NULL);
- vnet_state.in_buf.num --;
- vnet_state.in_buf.start ++;
+ vnet_state.in_buf.num--;
+ vnet_state.in_buf.start++;
vnet_state.in_buf.start %= BRIDGE_BUF_SIZE;
- num --;
+ num--;
}
v3_unlock_irqrestore(vnet_state.in_buf.lock, flags);
}
-int v3_vnet_rx(uchar_t *buf, uint16_t size, uint16_t src_id, uint8_t src_type){
- unsigned long flags;
- int end;
- struct v3_vnet_pkt *pkt;
+int v3_vnet_rx(uint8_t * buf, uint16_t size, uint16_t src_id, uint8_t src_type) {
+ uint32_t flags = 0;
+ int end = 0;
+ struct v3_vnet_pkt * pkt = NULL;
flags = v3_lock_irqsave(vnet_state.in_buf.lock);
end = vnet_state.in_buf.end;
pkt = &(vnet_state.in_buf.pkts[end]);
- if(vnet_state.in_buf.num > BRIDGE_BUF_SIZE){
+ if (vnet_state.in_buf.num > BRIDGE_BUF_SIZE){
PrintDebug("VNET: bridge rx: buffer full\n");
- goto exit;
+ v3_unlock_irqrestore(vnet_state.in_buf.lock, flags);
+ return 0;
}
- vnet_state.in_buf.num ++;
- vnet_state.in_buf.end ++;
+ vnet_state.in_buf.num++;
+ vnet_state.in_buf.end++;
vnet_state.in_buf.end %= BRIDGE_BUF_SIZE;
pkt->size = size;
memcpy(pkt->header, buf, ETHERNET_HEADER_LEN);
memcpy(pkt->data, buf, size);
-exit:
v3_unlock_irqrestore(vnet_state.in_buf.lock, flags);
}
-int v3_vnet_add_dev(struct v3_vm_info *vm, uint8_t mac[6],
+int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t mac[6],
int (*netif_input)(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, void * private_data),
void * priv_data){
struct vnet_dev * new_dev = NULL;
- unsigned long flags;
+ uint32_t flags = 0;
new_dev = (struct vnet_dev *)V3_Malloc(sizeof(struct vnet_dev));
}
PrintDebug("Vnet: Add Device: dev_id %d, input : %p, private_data %p\n",
- new_dev->dev_id, new_dev->input, new_dev->private_data);
+ new_dev->dev_id, new_dev->input, new_dev->private_data);
return new_dev->dev_id;
}
-void v3_vnet_heartbeat(struct guest_info *core){
+void v3_vnet_heartbeat(struct guest_info *core){
//static long last_time, cur_time;
- if(vnet_state.bridge == NULL)
+ if (vnet_state.bridge == NULL) {
return;
+ }
/*
if(vnet_state.bridge->max_delayed_pkts > 1){
if(V3_Get_CPU() != vnet_state.bridge->vm->cores[0].cpu_id){
int v3_vnet_add_bridge(struct v3_vm_info * vm,
int (*input)(struct v3_vm_info * vm, struct v3_vnet_pkt pkt[], uint16_t pkt_num, void * private_data),
- void (*xcall_input)(void *data),
+ void (*xcall_input)(void * data),
int (*poll_pkt)(struct v3_vm_info * vm, void * private_data),
uint16_t max_delayed_pkts,
long max_latency,
void * priv_data) {
- unsigned long flags;
+
+ uint32_t flags = 0;
int bridge_free = 0;
struct vnet_brg_dev * tmp_bridge = NULL;
*/
- tmp_bridge->max_delayed_pkts = (max_delayed_pkts<BRIDGE_BUF_SIZE)?max_delayed_pkts : BRIDGE_BUF_SIZE;
+ tmp_bridge->max_delayed_pkts = (max_delayed_pkts < BRIDGE_BUF_SIZE) ? max_delayed_pkts : BRIDGE_BUF_SIZE;
tmp_bridge->max_latency = max_latency;
// make this atomic to avoid possible race conditions
int v3_vnet_disable_bridge() {
- unsigned long flags;
+ uint32_t flags = 0;
flags = v3_lock_irqsave(vnet_state.lock);
int v3_vnet_enable_bridge() {
- unsigned long flags;
+ uint32_t flags = 0;
flags = v3_lock_irqsave(vnet_state.lock);
int V3_init_vnet() {
- int i;
+ int i = 0;
memset(&vnet_state, 0, sizeof(vnet_state));
vnet_state.in_buf.start = 0;
vnet_state.in_buf.end = 0;
vnet_state.in_buf.num = 0;
- if(v3_lock_init(&(vnet_state.in_buf.lock)) == -1){
+
+ if (v3_lock_init(&(vnet_state.in_buf.lock)) == -1){
PrintError("VNET: add bridge, error to initiate send buf lock\n");
}
- for(i = 0; i<BRIDGE_BUF_SIZE; i++){
- vnet_state.in_buf.pkts[i].data = &(vnet_state.in_buf.datas[i*ETHERNET_PACKET_LEN]);
+
+ for (i = 0; i < BRIDGE_BUF_SIZE; i++){
+ vnet_state.in_buf.pkts[i].data = &(vnet_state.in_buf.datas[i * ETHERNET_PACKET_LEN]);
}
+
PrintDebug("VNET: Receiving buffer initiated\n");
vnet_state.route_cache = v3_create_htable(0, &hash_fn, &hash_eq);
#include <palacios/vm_guest_mem.h>
#include <palacios/vmx.h>
+#ifndef CONFIG_DEBUG_VMX
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
static void vmx_save_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
static void vmx_restore_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
#include <palacios/vmm_direct_paging.h>
#include <palacios/vmm_ctrl_regs.h>
+#ifndef CONFIG_DEBUG_VMX
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
static v3_reg_t * get_reg_ptr(struct guest_info * info, struct vmx_exit_cr_qual * cr_qual);
static int handle_mov_to_cr0(struct guest_info * info, v3_reg_t * new_val, struct vmx_exit_info * exit_info);
static int handle_mov_to_cr3(struct guest_info * info, v3_reg_t * cr3_reg);
<vm class="PC">
<!-- Memory in MB -->
- <memory>256</memory>
+ <memory alignment="2MB">256</memory>
<!-- Basic VMM system flags -->
<telemetry>enable</telemetry>
<paging mode="shadow">
<strategy>VTLB</strategy>
+ <large_pages>true</large_pages>
</paging>
<!--
<paging mode="nested">
- <page_size>2MB</page_size>
+ <large_pages>true<large_pages/>
</paging>
-->
<schedule_hz>100</schedule_hz>
<!-- List of devices attached to guest -->
- <!-- The device 'ID' is the device name in the global device registry -->
- <!-- The device 'name' is the reference to the device instance associated with a VM -->
+ <!-- The device 'class' is the device name in the global device registry -->
+ <!-- The device 'id' is the reference to the device instance associated with a VM -->
<!-- The name can be used as a reference by other devices -->
<devices>
- <device id="8259A" name="PIC"/>
- <device id="KEYBOARD" name="keyboard"/>
- <device id="8254_PIT" name="PIT" />
- <device id="BOCHS_DEBUG" name="bochs debug"/>
- <device id="OS_DEBUG" name="os debug" />
- <device id="ICC_BUS" name="icc"/>
- <device id="LAPIC" name="apic">
+ <device class="8259A" id="PIC"/>
+ <device class="KEYBOARD" id="keyboard"/>
+ <device class="8254_PIT" id="PIT" />
+ <device class="BOCHS_DEBUG" id="bochs debug"/>
+ <device class="OS_DEBUG" id="os debug" />
+
+
+<!--
+ <device class="ICC_BUS" id="icc"/>
+ <device class="LAPIC" id="apic">
<bus>icc</bus>
</device>
- <device id="IOAPIC" name="ioapic">
+ <device class="IOAPIC" id="ioapic">
<bus>icc</bus>
</device>
-
+-->
<!--
- <device id="CGA_VIDEO" name="cga" passthrough="enable" />
- <device id="TELNET_CONSOLE" name="telnet console">
+ <device class="CGA_VIDEO" id="cga" passthrough="enable" />
+ <device class="TELNET_CONSOLE" id="telnet console">
<frontend tag="CGA_VIDEO" />
<port>19997</port>
</device>
-->
- <device id="PCI" name="pci0" />
+ <device class="PCI" id="pci0" />
- <device id="i440FX" name="northbridge">
+ <device class="i440FX" id="northbridge">
<bus>pci0</bus>
</device>
- <device id="PIIX3" name="southbridge">
+ <device class="PIIX3" id="southbridge">
<bus>pci0</bus>
</device>
- <device id="IDE" name="ide">
+ <device class="IDE" id="ide">
<bus>pci0</bus>
<controller>southbridge</controller>
</device>
<!--
- <device id="LNX_VIRTIO_SYM" name="sym_pci">
+ <device class="LNX_VIRTIO_SYM" id="sym_pci">
<bus>pci0</bus>
</device>
- <device id="LNX_VIRTIO_BLK" name="blk_virtio">
+ <device class="LNX_VIRTIO_BLK" id="blk_virtio">
<bus>pci0</bus>
</device>
- <device id="LNX_VIRTIO_BALLOON" name="balloon">
+ <device class="LNX_VIRTIO_BALLOON" id="balloon">
<bus>pci0</bus>
</device>
- <device id="PCI_PASSTHROUGH" name="e1000">
+ <device class="PCI_PASSTHROUGH" id="e1000">
<bus>pci0</bus>
<vendor_id>0x8086</vendor_id>
<device_id>0x100e</device_id>
<irq>59</irq>
</device>
- <device id="PCI_PASSTHROUGH" name="e1000-hw">
+ <device class="PCI_PASSTHROUGH" id="e1000-hw">
<bus>pci0</bus>
<vendor_id>0x8086</vendor_id>
<device_id>0x107c</device_id>
<!-- This is a Storage Backend that connects to a frontend -->
<!-- The frontend section is passed to the frontend when the backend connects -->
<!-- The file tag refers to an 'id' already listed in the file list section above -->
- <device id="RAMDISK" name="CD0">
+ <device class="RAMDISK" id="CD0">
<file>boot-cd</file>
<frontend tag="ide">
<model>V3Vee CDROM</model>
<!---
- <device id="SYM_SWAP" name="sym swap">
+ <device class="SYM_SWAP" id="sym swap">
<frontend tag="blk_virtio" />
<size>150</size>
</device>
- <device id="RAMDISK" name="HD0">
+ <device class="RAMDISK" id="HD0">
<file>harddisk</file>
<frontend tag="blk_virtio" />
</device>
-->
- <device id="NVRAM" name="nvram">
+ <device class="NVRAM" id="nvram">
<storage>ide</storage>
</device>
- <device id="GENERIC" name="generic">
+ <device class="GENERIC" id="generic">
<ports>
<start>0x00</start>
<end>0x07</end>