Merge latest xen-unstable into xen-ia64-unstable

This commit is contained in:
djm@kirby.fc.hp.com committed 2005-09-26 11:07:49 -06:00
commit 72f6940bc6
74 files changed
+4332 -3290

No files matched your search

+1 -1
View File
@@ -164,7 +164,7 @@ help:
uninstall: DESTDIR=
uninstall: D=$(DESTDIR)
uninstall:
[ -d $(D)/etc/xen ] && mv -f $(D)/etc/xen $(D)/etc/xen.old-`date +%s`
[ -d $(D)/etc/xen ] && mv -f $(D)/etc/xen $(D)/etc/xen.old-`date +%s` || true
rm -rf $(D)/etc/init.d/xend*
rm -rf $(D)/etc/hotplug/xen-backend.agent
rm -rf $(D)/var/run/xen* $(D)/var/lib/xen*
+3
View File
@@ -21,6 +21,9 @@ required if you wish to build from source.
\item [$\dag$] The \path{iproute2} package.
\item [$\dag$] The Linux bridge-utils\footnote{Available from {\tt
http://bridge.sourceforge.net}} (e.g., \path{/sbin/brctl})
\item [$\dag$] The Linux hotplug system\footnote{Available from {\tt
http://linux-hotplug.sourceforge.net/}} (e.g., \path{/sbin/hotplug}
and related scripts)
\item [$\dag$] An installation of Twisted~v1.3 or
above\footnote{Available from {\tt http://www.twistedmatrix.com}}.
There may be a binary package available for your distribution;
@@ -1394,9 +1394,7 @@ static void handle_vcpu_hotplug_event(struct xenbus_watch *watch, const char *no
return;
/* get the state value */
xenbus_transaction_start("cpu");
err = xenbus_scanf(dir, "availability", "%s", state);
xenbus_transaction_end(0);
if (err != 1) {
printk(KERN_ERR
@@ -324,7 +324,7 @@ static void shutdown_handler(struct xenbus_watch *watch, const char *node)
int err;
again:
err = xenbus_transaction_start("control");
err = xenbus_transaction_start();
if (err)
return;
str = (char *)xenbus_read("control", "shutdown", NULL);
@@ -337,7 +337,7 @@ static void shutdown_handler(struct xenbus_watch *watch, const char *node)
xenbus_write("control", "shutdown", "");
err = xenbus_transaction_end(0);
if (err == -ETIMEDOUT) {
if (err == -EAGAIN) {
kfree(str);
goto again;
}
@@ -366,7 +366,7 @@ static void sysrq_handler(struct xenbus_watch *watch, const char *node)
int err;
again:
err = xenbus_transaction_start("control");
err = xenbus_transaction_start();
if (err)
return;
if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) {
@@ -379,7 +379,7 @@ static void sysrq_handler(struct xenbus_watch *watch, const char *node)
xenbus_printf("control", "sysrq", "%c", '\0');
err = xenbus_transaction_end(0);
if (err == -ETIMEDOUT)
if (err == -EAGAIN)
goto again;
if (sysrq_key != '\0') {
@@ -80,8 +80,9 @@ static void frontend_changed(struct xenbus_watch *watch, const char *node)
return;
}
again:
/* Supply the information about the device the frontend needs */
err = xenbus_transaction_start(be->dev->nodename);
err = xenbus_transaction_start();
if (err) {
xenbus_dev_error(be->dev, err, "starting transaction");
return;
@@ -119,7 +120,15 @@ static void frontend_changed(struct xenbus_watch *watch, const char *node)
goto abort;
}
xenbus_transaction_end(0);
err = xenbus_transaction_end(0);
if (err == -EAGAIN)
goto again;
if (err) {
xenbus_dev_error(be->dev, err, "ending transaction",
ring_ref, evtchn);
goto abort;
}
xenbus_dev_ok(be->dev);
return;
@@ -572,7 +572,8 @@ static int talk_to_backend(struct xenbus_device *dev,
goto out;
}
err = xenbus_transaction_start(dev->nodename);
again:
err = xenbus_transaction_start();
if (err) {
xenbus_dev_error(dev, err, "starting transaction");
goto destroy_blkring;
@@ -603,6 +604,8 @@ static int talk_to_backend(struct xenbus_device *dev,
err = xenbus_transaction_end(0);
if (err) {
if (err == -EAGAIN)
goto again;
xenbus_dev_error(dev, err, "completing transaction");
goto destroy_blkring;
}
@@ -1122,7 +1122,8 @@ static int talk_to_backend(struct xenbus_device *dev,
goto out;
}
err = xenbus_transaction_start(dev->nodename);
again:
err = xenbus_transaction_start();
if (err) {
xenbus_dev_error(dev, err, "starting transaction");
goto destroy_ring;
@@ -1160,6 +1161,8 @@ static int talk_to_backend(struct xenbus_device *dev,
err = xenbus_transaction_end(0);
if (err) {
if (err == -EAGAIN)
goto again;
xenbus_dev_error(dev, err, "completing transaction");
goto destroy_ring;
}
@@ -93,7 +93,8 @@ static void frontend_changed(struct xenbus_watch *watch, const char *node)
* Tell the front-end that we are ready to go -
* unless something bad happens
*/
err = xenbus_transaction_start(be->dev->nodename);
again:
err = xenbus_transaction_start();
if (err) {
xenbus_dev_error(be->dev, err, "starting transaction");
return;
@@ -127,7 +128,14 @@ static void frontend_changed(struct xenbus_watch *watch, const char *node)
goto abort;
}
xenbus_transaction_end(0);
err = xenbus_transaction_end(0);
if (err == -EAGAIN)
goto again;
if (err) {
xenbus_dev_error(be->dev, err, "end of transaction");
goto abort;
}
xenbus_dev_ok(be->dev);
return;
abort:
@@ -331,7 +331,8 @@ static int talk_to_backend(struct xenbus_device *dev,
goto out;
}
err = xenbus_transaction_start(dev->nodename);
again:
err = xenbus_transaction_start();
if (err) {
xenbus_dev_error(dev, err, "starting transaction");
goto destroy_tpmring;
@@ -363,6 +364,8 @@ static int talk_to_backend(struct xenbus_device *dev,
}
err = xenbus_transaction_end(0);
if (err == -EAGAIN)
goto again;
if (err) {
xenbus_dev_error(dev, err, "completing transaction");
goto destroy_tpmring;
@@ -287,12 +287,11 @@ EXPORT_SYMBOL(xenbus_rm);
/* Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
* Transaction only applies to the given subtree.
* You can only have one transaction at any time.
*/
int xenbus_transaction_start(const char *subtree)
int xenbus_transaction_start(void)
{
return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
return xs_error(xs_single(XS_TRANSACTION_START, "", NULL));
}
EXPORT_SYMBOL(xenbus_transaction_start);
@@ -87,7 +87,7 @@ int xenbus_write(const char *dir, const char *node, const char *string);
int xenbus_mkdir(const char *dir, const char *node);
int xenbus_exists(const char *dir, const char *node);
int xenbus_rm(const char *dir, const char *node);
int xenbus_transaction_start(const char *subtree);
int xenbus_transaction_start(void);
int xenbus_transaction_end(int abort);
/* Single read and scanf: returns -errno or num scanned if > 0. */
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# CHECK-INSTALL
function error {
echo
echo ' *** Check for the hotplug scripts (hotplug) FAILED'
exit 1
}
which hotplug 1>/dev/null 2>&1 || error
+1 -15
View File
@@ -25,19 +25,13 @@ XEN_SCRIPTS += block-phy
XEN_SCRIPTS += block-file
XEN_SCRIPTS += block-enbd
# no 64-bit specifics in mem-map.sxp
# so place in /usr/lib, not /usr/lib64
XEN_BOOT_DIR = /usr/lib/xen/boot
XEN_BOOT = mem-map.sxp
XEN_HOTPLUG_DIR = /etc/hotplug
XEN_HOTPLUG_SCRIPTS = xen-backend.agent
all:
build:
install: all install-initd install-configs install-scripts install-boot \
install-hotplug
install: all install-initd install-configs install-scripts install-hotplug
install-initd:
[ -d $(DESTDIR)/etc/init.d ] || $(INSTALL_DIR) $(DESTDIR)/etc/init.d
@@ -62,14 +56,6 @@ install-scripts:
$(INSTALL_PROG) $$i $(DESTDIR)$(XEN_SCRIPT_DIR); \
done
install-boot:
[ -d $(DESTDIR)$(XEN_BOOT_DIR) ] || \
$(INSTALL_DIR) $(DESTDIR)$(XEN_BOOT_DIR)
for i in $(XEN_BOOT); \
do [ -a $(DESTDIR)$(XEN_BOOT_DIR)/$$i ] || \
$(INSTALL_PROG) $$i $(DESTDIR)$(XEN_BOOT_DIR); \
done
install-hotplug:
[ -d $(DESTDIR)$(XEN_HOTPLUG_DIR) ] || \
$(INSTALL_DIR) $(DESTDIR)$(XEN_HOTPLUG_DIR)
-10
View File
@@ -1,10 +0,0 @@
(memmap
(0000000000000000 000000000009f800 "AddressRangeMemory" WB)
(000000000009f800 00000000000a0000 "AddressRangeReserved" UC)
(00000000000a0000 00000000000bffff "AddressRangeIO" UC)
(00000000000f0000 0000000000100000 "AddressRangeReserved" UC)
(0000000000100000 0000000008000000 "AddressRangeMemory" WB)
(0000000007fff000 0000000008000000 "AddressRangeShared" WB)
(0000000008000000 0000000008003000 "AddressRangeNVS" UC)
(0000000008003000 000000000800d000 "AddressRangeACPI" WB)
(00000000fec00000 0000000100000000 "AddressRangeIO" UC))
-3
View File
@@ -60,9 +60,6 @@ disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ]
# New stuff
device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm'
# Advanced users only. Don't touch if you don't know what you're doing
memmap = '/usr/lib/xen/boot/mem-map.sxp'
#-----------------------------------------------------------------------------
# Disk image for
#cdrom=
+1 -1
View File
@@ -44,7 +44,7 @@ all: vmxloader
vmxloader: roms.h vmxloader.c acpi.h acpi_madt.c
${CC} ${CFLAGS} ${DEFINES} -c vmxloader.c -c acpi_madt.c
$(CC) -o vmxloader.tmp -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o acpi_madt.o
objcopy --change-addresses=0xC0000000 vmxloader.tmp vmxloader
objcopy vmxloader.tmp vmxloader
rm -f vmxloader.tmp
vmxassist.bin: vmxassist.ld ${OBJECTS}
+34 -23
View File
@@ -34,28 +34,39 @@ int acpi_madt_update(unsigned char* acpi_start);
/*
* C runtime start off
*/
asm(" \n\
.text \n\
.globl _start \n\
_start: \n\
cli \n\
movl $stack_top, %esp \n\
movl %esp, %ebp \n\
call main \n\
jmp halt \n\
\n\
.globl halt \n\
halt: \n\
sti \n\
jmp . \n\
\n\
.bss \n\
.align 8 \n\
.globl stack, stack_top \n\
stack: \n\
.skip 0x4000 \n\
stack_top: \n\
");
asm(
" .text \n"
" .globl _start \n"
"_start: \n"
" cld \n"
" cli \n"
" lgdt gdt_desr \n"
" movl $stack_top, %esp \n"
" movl %esp, %ebp \n"
" call main \n"
" jmp halt \n"
" \n"
"gdt_desr: \n"
" .word gdt_end - gdt - 1 \n"
" .long gdt \n"
" \n"
" .align 8 \n"
"gdt: \n"
" .quad 0x0000000000000000 \n"
" .quad 0x00CF92000000FFFF \n"
" .quad 0x00CF9A000000FFFF \n"
"gdt_end: \n"
" \n"
"halt: \n"
" sti \n"
" jmp . \n"
" \n"
" .bss \n"
" .align 8 \n"
"stack: \n"
" .skip 0x4000 \n"
"stack_top: \n"
);
void *
memcpy(void *dest, const void *src, unsigned n)
@@ -95,7 +106,7 @@ cirrus_check(void)
}
int
main()
main(void)
{
puts("VMXAssist Loader\n");
puts("Loading ROMBIOS ...\n");
+18 -6
View File
@@ -231,6 +231,8 @@ typedef struct CirrusVGAState {
int cirrus_linear_io_addr;
int cirrus_linear_bitblt_io_addr;
int cirrus_mmio_io_addr;
unsigned long cirrus_lfb_addr;
unsigned long cirrus_lfb_end;
uint32_t cirrus_addr_mask;
uint32_t linear_mmio_mask;
uint8_t cirrus_shadow_gr0;
@@ -2447,6 +2449,10 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
{
unsigned mode;
extern void unset_vram_mapping(unsigned long addr, unsigned long end);
extern void set_vram_mapping(unsigned long addr, unsigned long end);
extern int vga_accelerate;
if ((s->sr[0x17] & 0x44) == 0x44) {
goto generic_io;
} else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
@@ -2454,17 +2460,21 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
} else {
if ((s->gr[0x0B] & 0x14) == 0x14) {
goto generic_io;
} else if (s->gr[0x0B] & 0x02) {
goto generic_io;
}
mode = s->gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
} else if (s->gr[0x0B] & 0x02) {
goto generic_io;
}
mode = s->gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end)
set_vram_mapping(s->cirrus_lfb_addr, s->cirrus_lfb_end);
s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
} else {
generic_io:
if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end)
unset_vram_mapping(s->cirrus_lfb_addr, s->cirrus_lfb_end);
s->cirrus_linear_write[0] = cirrus_linear_writeb;
s->cirrus_linear_write[1] = cirrus_linear_writew;
s->cirrus_linear_write[2] = cirrus_linear_writel;
@@ -3058,6 +3068,8 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
/* XXX: add byte swapping apertures */
cpu_register_physical_memory(addr, s->vram_size,
s->cirrus_linear_io_addr);
s->cirrus_lfb_addr = addr;
s->cirrus_lfb_end = addr + VGA_RAM_SIZE;
cpu_register_physical_memory(addr + 0x1000000, 0x400000,
s->cirrus_linear_bitblt_io_addr);
}
+4 -3
View File
@@ -385,6 +385,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device,
unsigned long bios_offset, vga_bios_offset;
int bios_size, isa_bios_size;
PCIBus *pci_bus;
extern void * shared_vram;
linux_boot = (kernel_filename != NULL);
@@ -511,14 +512,14 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device,
if (cirrus_vga_enabled) {
if (pci_enabled) {
pci_cirrus_vga_init(pci_bus,
ds, phys_ram_base + ram_size, ram_size,
ds, shared_vram, ram_size,
vga_ram_size);
} else {
isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size,
isa_cirrus_vga_init(ds, shared_vram, ram_size,
vga_ram_size);
}
} else {
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_initialize(pci_bus, ds, shared_vram, ram_size,
vga_ram_size);
}
+4 -1
View File
@@ -1568,6 +1568,8 @@ void vga_update_display(void)
s->graphic_mode = graphic_mode;
full_update = 1;
}
full_update = 1;
switch(graphic_mode) {
case GMODE_TEXT:
vga_draw_text(s, full_update);
@@ -1848,6 +1850,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size)
{
int i, j, v, b;
extern void* shared_vram;
for(i = 0;i < 256; i++) {
v = 0;
@@ -1876,7 +1879,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
/* qemu's vga mem is not detached from phys_ram_base and can cause DM abort
* when guest write vga mem, so allocate a new one */
s->vram_ptr = qemu_mallocz(vga_ram_size);
s->vram_ptr = shared_vram;
s->vram_offset = vga_ram_offset;
s->vram_size = vga_ram_size;
+2
View File
@@ -54,6 +54,8 @@
#include "exec-all.h"
#include "vl.h"
void *shared_vram;
shared_iopage_t *shared_page = NULL;
extern int reset_requested;
+240 -7
View File
@@ -134,6 +134,7 @@ int pci_enabled = 1;
int prep_enabled = 0;
int rtc_utc = 1;
int cirrus_vga_enabled = 1;
int vga_accelerate = 1;
int graphic_width = 800;
int graphic_height = 600;
int graphic_depth = 15;
@@ -141,6 +142,12 @@ int full_screen = 0;
TextConsole *vga_console;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
int xc_handle;
unsigned long *vgapage_array;
unsigned long *freepage_array;
unsigned long free_pages;
void *vtop_table;
unsigned long toptab;
unsigned long vgaram_pages;
/***********************************************************/
/* x86 ISA bus support */
@@ -2162,6 +2169,7 @@ void help(void)
"-isa simulate an ISA-only system (default is PCI system)\n"
"-std-vga simulate a standard VGA card with VESA Bochs Extensions\n"
" (default is CL-GD5446 PCI VGA)\n"
"-vgaacc [0|1] 1 to accelerate CL-GD5446 speed, default is 1\n"
#endif
"-loadvm file start right away with a saved state (loadvm in monitor)\n"
"\n"
@@ -2251,6 +2259,7 @@ enum {
QEMU_OPTION_serial,
QEMU_OPTION_loadvm,
QEMU_OPTION_full_screen,
QEMU_OPTION_vgaacc,
};
typedef struct QEMUOption {
@@ -2327,6 +2336,7 @@ const QEMUOption qemu_options[] = {
{ "pci", 0, QEMU_OPTION_pci },
{ "nic-pcnet", 0, QEMU_OPTION_nic_pcnet },
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
{ "vgaacc", HAS_ARG, QEMU_OPTION_vgaacc },
{ NULL },
};
@@ -2343,6 +2353,177 @@ static uint8_t *signal_stack;
#define NET_IF_USER 1
#define NET_IF_DUMMY 2
#include <xg_private.h>
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
#ifdef __i386__
#define _LEVEL_3_ 0
#else
#define _LEVEL_3_ 1
#endif
#if _LEVEL_3_
#define L3_PROT (_PAGE_PRESENT)
#define L1_PAGETABLE_ENTRIES 512
#else
#define L1_PAGETABLE_ENTRIES 1024
#endif
inline int
get_vl2_table(unsigned long count, unsigned long start)
{
#if _LEVEL_3_
return ((start + (count << PAGE_SHIFT)) >> L3_PAGETABLE_SHIFT) & 0x3;
#else
return 0;
#endif
}
int
setup_mapping(int xc_handle, u32 dom, unsigned long toptab, unsigned long *mem_page_array, unsigned long *page_table_array, unsigned long v_start, unsigned long v_end)
{
l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
l2_pgentry_t *vl2tab[4], *vl2e=NULL, *vl2_table = NULL;
unsigned long l1tab;
unsigned long ppt_alloc = 0;
unsigned long count;
int i = 0;
#if _LEVEL_3_
l3_pgentry_t *vl3tab = NULL;
unsigned long l2tab;
if ( (vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
toptab >> PAGE_SHIFT)) == NULL )
goto error_out;
for (i = 0; i < 4 ; i++) {
l2tab = vl3tab[i] & PAGE_MASK;
vl2tab[i] = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l2tab >> PAGE_SHIFT);
if(vl2tab[i] == NULL)
goto error_out;
}
munmap(vl3tab, PAGE_SIZE);
vl3tab = NULL;
#else
if ( (vl2tab[0] = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
toptab >> PAGE_SHIFT)) == NULL )
goto error_out;
#endif
for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ )
{
if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
{
vl2_table = vl2tab[get_vl2_table(count, v_start)];
vl2e = &vl2_table[l2_table_offset(
v_start + (count << PAGE_SHIFT))];
l1tab = page_table_array[ppt_alloc++] << PAGE_SHIFT;
if ( vl1tab != NULL )
munmap(vl1tab, PAGE_SIZE);
if ( (vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l1tab >> PAGE_SHIFT)) == NULL )
{
goto error_out;
}
memset(vl1tab, 0, PAGE_SIZE);
vl1e = &vl1tab[l1_table_offset(v_start + (count<<PAGE_SHIFT))];
*vl2e = l1tab | L2_PROT;
}
*vl1e = (mem_page_array[count] << PAGE_SHIFT) | L1_PROT;
vl1e++;
}
error_out:
if(vl1tab) munmap(vl1tab, PAGE_SIZE);
for(i = 0; i < 4; i++)
if(vl2tab[i]) munmap(vl2tab[i], PAGE_SIZE);
return ppt_alloc;
}
void
unsetup_mapping(int xc_handle, u32 dom, unsigned long toptab, unsigned long v_start, unsigned long v_end)
{
l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
l2_pgentry_t *vl2tab[4], *vl2e=NULL, *vl2_table = NULL;
unsigned long l1tab;
unsigned long count;
int i = 0;
#if _LEVEL_3_
l3_pgentry_t *vl3tab = NULL;
unsigned long l2tab;
if ( (vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
toptab >> PAGE_SHIFT)) == NULL )
goto error_out;
for (i = 0; i < 4 ; i ++){
l2tab = vl3tab[i] & PAGE_MASK;
vl2tab[i] = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l2tab >> PAGE_SHIFT);
if(vl2tab[i] == NULL)
goto error_out;
}
munmap(vl3tab, PAGE_SIZE);
vl3tab = NULL;
#else
if ( (vl2tab[0] = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
toptab >> PAGE_SHIFT)) == NULL )
goto error_out;
#endif
for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ ){
if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
{
vl2_table = vl2tab[get_vl2_table(count, v_start)];
vl2e = &vl2_table[l2_table_offset(v_start + (count << PAGE_SHIFT))];
l1tab = *vl2e & PAGE_MASK;
if(l1tab == 0)
continue;
if ( vl1tab != NULL )
munmap(vl1tab, PAGE_SIZE);
if ( (vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l1tab >> PAGE_SHIFT)) == NULL )
{
goto error_out;
}
vl1e = &vl1tab[l1_table_offset(v_start + (count<<PAGE_SHIFT))];
*vl2e = 0;
}
*vl1e = 0;
vl1e++;
}
error_out:
if(vl1tab) munmap(vl1tab, PAGE_SIZE);
for(i = 0; i < 4; i++)
if(vl2tab[i]) munmap(vl2tab[i], PAGE_SIZE);
}
void set_vram_mapping(unsigned long addr, unsigned long end)
{
end = addr + VGA_RAM_SIZE;
setup_mapping(xc_handle, domid, toptab,
vgapage_array, freepage_array, addr, end);
}
void unset_vram_mapping(unsigned long addr, unsigned long end)
{
end = addr + VGA_RAM_SIZE;
/* FIXME Flush the shadow page */
unsetup_mapping(xc_handle, domid, toptab, addr, end);
}
int main(int argc, char **argv)
{
#ifdef CONFIG_GDBSTUB
@@ -2366,8 +2547,9 @@ int main(int argc, char **argv)
char serial_devices[MAX_SERIAL_PORTS][128];
int serial_device_index;
const char *loadvm = NULL;
unsigned long nr_pages, *page_array;
unsigned long nr_pages, extra_pages, ram_pages, *page_array;
extern void *shared_page;
extern void *shared_vram;
/* change the qemu-dm to daemon, just like bochs dm */
// daemon(0, 0);
@@ -2674,6 +2856,17 @@ int main(int argc, char **argv)
case QEMU_OPTION_cirrusvga:
cirrus_vga_enabled = 1;
break;
case QEMU_OPTION_vgaacc:
{
const char *p;
p = optarg;
vga_accelerate = strtol(p, (char **)&p, 0);
if (*p != '\0') {
fprintf(stderr, "qemu: invalid vgaacc option\n");
exit(1);
}
break;
}
case QEMU_OPTION_std_vga:
cirrus_vga_enabled = 0;
break;
@@ -2803,12 +2996,25 @@ int main(int argc, char **argv)
/* init the memory */
phys_ram_size = ram_size + vga_ram_size + bios_size;
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT)
ram_pages = ram_size/PAGE_SIZE;
vgaram_pages = (vga_ram_size -1)/PAGE_SIZE + 1;
free_pages = vgaram_pages / L1_PAGETABLE_ENTRIES;
extra_pages = vgaram_pages + free_pages;
nr_pages = ram_size/PAGE_SIZE;
xc_handle = xc_interface_open();
xc_dominfo_t info;
xc_domain_getinfo(xc_handle, domid, 1, &info);
nr_pages = info.nr_pages + extra_pages;
if ( xc_domain_setmaxmem(xc_handle, domid,
(nr_pages) * PAGE_SIZE/1024 ) != 0)
{
perror("set maxmem");
exit(-1);
}
if ( (page_array = (unsigned long *)
malloc(nr_pages * sizeof(unsigned long))) == NULL)
{
@@ -2816,6 +3022,12 @@ int main(int argc, char **argv)
exit(-1);
}
if (xc_domain_memory_increase_reservation(xc_handle, domid,
extra_pages , 0, 0, NULL) != 0) {
perror("increase reservation");
exit(-1);
}
if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages )
{
perror("xc_get_pfn_list");
@@ -2825,15 +3037,36 @@ int main(int argc, char **argv)
if ((phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
PROT_READ|PROT_WRITE,
page_array,
nr_pages - 1)) == 0) {
ram_pages - 1)) == 0) {
perror("xc_map_foreign_batch");
exit(-1);
}
shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
PROT_READ|PROT_WRITE,
page_array[nr_pages - 1]);
page_array[ram_pages - 1]);
vgapage_array = &page_array[nr_pages - vgaram_pages];
if ((shared_vram = xc_map_foreign_batch(xc_handle, domid,
PROT_READ|PROT_WRITE,
vgapage_array,
vgaram_pages)) == 0) {
perror("xc_map_foreign_batch vgaram ");
exit(-1);
}
memset(shared_vram, 0, vgaram_pages * PAGE_SIZE);
toptab = page_array[ram_pages] << PAGE_SHIFT;
vtop_table = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
PROT_READ|PROT_WRITE,
page_array[ram_pages]);
freepage_array = &page_array[nr_pages - extra_pages];
fprintf(logfile, "shared page at pfn:%lx, mfn: %lx\n", (nr_pages-1),
(page_array[nr_pages - 1]));
-166
View File
@@ -1,166 +0,0 @@
#ifndef __LINUX_BOOT_PARAMS_H__
#define __LINUX_BOOT_PARAMS_H__
#include <asm/types.h>
#define E820MAX 32
struct mem_map {
int nr_map;
struct entry {
u64 addr; /* start of memory segment */
u64 size; /* size of memory segment */
u32 type; /* type of memory segment */
#define E820_RAM 1
#define E820_RESERVED 2
#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
#define E820_NVS 4
#define E820_IO 16
#define E820_SHARED 17
#define E820_XENSTORE 18
u32 caching_attr; /* used by hypervisor */
#define MEMMAP_UC 0
#define MEMMAP_WC 1
#define MEMMAP_WT 4
#define MEMMAP_WP 5
#define MEMMAP_WB 6
}map[E820MAX];
};
struct e820entry {
u64 addr; /* start of memory segment */
u64 size; /* size of memory segment */
u32 type; /* type of memory segment */
}__attribute__((packed));
struct e820map {
u32 nr_map;
struct e820entry map[E820MAX];
}__attribute__((packed));
struct drive_info_struct { __u8 dummy[32]; };
struct sys_desc_table {
__u16 length;
__u8 table[318];
};
struct screen_info {
unsigned char orig_x; /* 0x00 */
unsigned char orig_y; /* 0x01 */
unsigned short dontuse1; /* 0x02 -- EXT_MEM_K sits here */
unsigned short orig_video_page; /* 0x04 */
unsigned char orig_video_mode; /* 0x06 */
unsigned char orig_video_cols; /* 0x07 */
unsigned short unused2; /* 0x08 */
unsigned short orig_video_ega_bx; /* 0x0a */
unsigned short unused3; /* 0x0c */
unsigned char orig_video_lines; /* 0x0e */
unsigned char orig_video_isVGA; /* 0x0f */
unsigned short orig_video_points; /* 0x10 */
/* VESA graphic mode -- linear frame buffer */
unsigned short lfb_width; /* 0x12 */
unsigned short lfb_height; /* 0x14 */
unsigned short lfb_depth; /* 0x16 */
unsigned int lfb_base; /* 0x18 */
unsigned int lfb_size; /* 0x1c */
unsigned short dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
unsigned short lfb_linelength; /* 0x24 */
unsigned char red_size; /* 0x26 */
unsigned char red_pos; /* 0x27 */
unsigned char green_size; /* 0x28 */
unsigned char green_pos; /* 0x29 */
unsigned char blue_size; /* 0x2a */
unsigned char blue_pos; /* 0x2b */
unsigned char rsvd_size; /* 0x2c */
unsigned char rsvd_pos; /* 0x2d */
unsigned short vesapm_seg; /* 0x2e */
unsigned short vesapm_off; /* 0x30 */
unsigned short pages; /* 0x32 */
/* 0x34 -- 0x3f reserved for future expansion */
};
struct screen_info_overlap {
__u8 reserved1[2]; /* 0x00 */
__u16 ext_mem_k; /* 0x02 */
__u8 reserved2[0x20 - 0x04]; /* 0x04 */
__u16 cl_magic; /* 0x20 */
#define CL_MAGIC_VALUE 0xA33F
__u16 cl_offset; /* 0x22 */
__u8 reserved3[0x40 - 0x24]; /* 0x24 */
};
struct apm_bios_info {
__u16 version;
__u16 cseg;
__u32 offset;
__u16 cseg_16;
__u16 dseg;
__u16 flags;
__u16 cseg_len;
__u16 cseg_16_len;
__u16 dseg_len;
};
struct linux_boot_params {
union { /* 0x00 */
struct screen_info info;
struct screen_info_overlap overlap;
} screen;
struct apm_bios_info apm_bios_info; /* 0x40 */
__u8 reserved4[0x80 - 0x54]; /* 0x54 */
struct drive_info_struct drive_info; /* 0x80 */
struct sys_desc_table sys_desc_table; /* 0xa0 */
__u32 alt_mem_k; /* 0x1e0 */
__u8 reserved5[4]; /* 0x1e4 */
__u8 e820_map_nr; /* 0x1e8 */
__u8 reserved6[8]; /* 0x1e9 */
__u8 setup_sects; /* 0x1f1 */
__u16 mount_root_rdonly; /* 0x1f2 */
__u16 syssize; /* 0x1f4 */
__u16 swapdev; /* 0x1f6 */
__u16 ramdisk_flags; /* 0x1f8 */
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
__u16 vid_mode; /* 0x1fa */
__u16 root_dev; /* 0x1fc */
__u8 reserved9[1]; /* 0x1fe */
__u8 aux_device_info; /* 0x1ff */
/* 2.00+ */
__u8 reserved10[2]; /* 0x200 */
__u8 header_magic[4]; /* 0x202 */
__u16 protocol_version; /* 0x206 */
__u8 reserved11[8]; /* 0x208 */
__u8 loader_type; /* 0x210 */
#define LOADER_TYPE_LOADLIN 1
#define LOADER_TYPE_BOOTSECT_LOADER 2
#define LOADER_TYPE_SYSLINUX 3
#define LOADER_TYPE_ETHERBOOT 4
#define LOADER_TYPE_UNKNOWN 0xFF
__u8 loader_flags; /* 0x211 */
__u8 reserved12[2]; /* 0x212 */
__u32 code32_start; /* 0x214 */
__u32 initrd_start; /* 0x218 */
__u32 initrd_size; /* 0x21c */
__u8 reserved13[4]; /* 0x220 */
/* 2.01+ */
__u16 heap_end_ptr; /* 0x224 */
__u8 reserved14[2]; /* 0x226 */
/* 2.02+ */
__u32 cmd_line_ptr; /* 0x228 */
/* 2.03+ */
__u32 ramdisk_max; /* 0x22c */
__u8 reserved15[0x2d0 - 0x230]; /* 0x230 */
struct e820entry e820_map[E820MAX]; /* 0x2d0 */
__u64 shared_info; /* 0x550 */
__u8 padding[0x800 - 0x558]; /* 0x558 */
__u8 cmd_line[0x800]; /* 0x800 */
} __attribute__((packed));
#endif /* __LINUX_BOOT_PARAMS_H__ */
+163 -308
View File
@@ -10,7 +10,8 @@
#include <unistd.h>
#include <zlib.h>
#include <xen/io/ioreq.h>
#include "linux_boot_params.h"
#define VMX_LOADER_ENTR_ADDR 0x00100000
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
@@ -18,13 +19,29 @@
#define L3_PROT (_PAGE_PRESENT)
#endif
#define E820MAX 128
#define E820_RAM 1
#define E820_RESERVED 2
#define E820_ACPI 3
#define E820_NVS 4
#define E820_IO 16
#define E820_SHARED_PAGE 17
#define E820_XENSTORE 18
#define E820_MAP_PAGE 0x00090000
#define E820_MAP_NR_OFFSET 0x000001E8
#define E820_MAP_OFFSET 0x000002D0
struct e820entry {
u64 addr;
u64 size;
u32 type;
} __attribute__((packed));
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
#define round_pgdown(_p) ((_p)&PAGE_MASK)
#define LINUX_BOOT_PARAMS_ADDR 0x00090000
#define LINUX_KERNEL_ENTR_ADDR 0x00100000
#define LINUX_PAGE_OFFSET 0xC0000000
static int
parseelfimage(
char *elfbase, unsigned long elfsize, struct domain_setup_info *dsi);
@@ -33,78 +50,70 @@ loadelfimage(
char *elfbase, int xch, u32 dom, unsigned long *parray,
struct domain_setup_info *dsi);
static void build_e820map(struct mem_map *mem_mapp, unsigned long mem_size)
static unsigned char build_e820map(void *e820_page, unsigned long mem_size)
{
int nr_map = 0;
struct e820entry *e820entry =
(struct e820entry *)(((unsigned char *)e820_page) + E820_MAP_OFFSET);
unsigned char nr_map = 0;
/* XXX: Doesn't work for > 4GB yet */
mem_mapp->map[nr_map].addr = 0x0;
mem_mapp->map[nr_map].size = 0x9F800;
mem_mapp->map[nr_map].type = E820_RAM;
mem_mapp->map[nr_map].caching_attr = MEMMAP_WB;
e820entry[nr_map].addr = 0x0;
e820entry[nr_map].size = 0x9F800;
e820entry[nr_map].type = E820_RAM;
nr_map++;
mem_mapp->map[nr_map].addr = 0x9F800;
mem_mapp->map[nr_map].size = 0x800;
mem_mapp->map[nr_map].type = E820_RESERVED;
mem_mapp->map[nr_map].caching_attr = MEMMAP_UC;
e820entry[nr_map].addr = 0x9F800;
e820entry[nr_map].size = 0x800;
e820entry[nr_map].type = E820_RESERVED;
nr_map++;
mem_mapp->map[nr_map].addr = 0xA0000;
mem_mapp->map[nr_map].size = 0x20000;
mem_mapp->map[nr_map].type = E820_IO;
mem_mapp->map[nr_map].caching_attr = MEMMAP_UC;
e820entry[nr_map].addr = 0xA0000;
e820entry[nr_map].size = 0x20000;
e820entry[nr_map].type = E820_IO;
nr_map++;
mem_mapp->map[nr_map].addr = 0xF0000;
mem_mapp->map[nr_map].size = 0x10000;
mem_mapp->map[nr_map].type = E820_RESERVED;
mem_mapp->map[nr_map].caching_attr = MEMMAP_UC;
e820entry[nr_map].addr = 0xF0000;
e820entry[nr_map].size = 0x10000;
e820entry[nr_map].type = E820_RESERVED;
nr_map++;
#define STATIC_PAGES 2 /* for ioreq_t and store_mfn */
/* Most of the ram goes here */
mem_mapp->map[nr_map].addr = 0x100000;
mem_mapp->map[nr_map].size = mem_size - 0x100000 - STATIC_PAGES*PAGE_SIZE;
mem_mapp->map[nr_map].type = E820_RAM;
mem_mapp->map[nr_map].caching_attr = MEMMAP_WB;
e820entry[nr_map].addr = 0x100000;
e820entry[nr_map].size = mem_size - 0x100000 - STATIC_PAGES*PAGE_SIZE;
e820entry[nr_map].type = E820_RAM;
nr_map++;
/* Statically allocated special pages */
/* Shared ioreq_t page */
mem_mapp->map[nr_map].addr = mem_size - PAGE_SIZE;
mem_mapp->map[nr_map].size = PAGE_SIZE;
mem_mapp->map[nr_map].type = E820_SHARED;
mem_mapp->map[nr_map].caching_attr = MEMMAP_WB;
e820entry[nr_map].addr = mem_size - PAGE_SIZE;
e820entry[nr_map].size = PAGE_SIZE;
e820entry[nr_map].type = E820_SHARED_PAGE;
nr_map++;
/* For xenstore */
mem_mapp->map[nr_map].addr = mem_size - 2*PAGE_SIZE;
mem_mapp->map[nr_map].size = PAGE_SIZE;
mem_mapp->map[nr_map].type = E820_XENSTORE;
mem_mapp->map[nr_map].caching_attr = MEMMAP_WB;
e820entry[nr_map].addr = mem_size - 2*PAGE_SIZE;
e820entry[nr_map].size = PAGE_SIZE;
e820entry[nr_map].type = E820_XENSTORE;
nr_map++;
mem_mapp->map[nr_map].addr = mem_size;
mem_mapp->map[nr_map].size = 0x3 * PAGE_SIZE;
mem_mapp->map[nr_map].type = E820_NVS;
mem_mapp->map[nr_map].caching_attr = MEMMAP_UC;
e820entry[nr_map].addr = mem_size;
e820entry[nr_map].size = 0x3 * PAGE_SIZE;
e820entry[nr_map].type = E820_NVS;
nr_map++;
mem_mapp->map[nr_map].addr = mem_size + 0x3 * PAGE_SIZE;
mem_mapp->map[nr_map].size = 0xA * PAGE_SIZE;
mem_mapp->map[nr_map].type = E820_ACPI;
mem_mapp->map[nr_map].caching_attr = MEMMAP_WB;
e820entry[nr_map].addr = mem_size + 0x3 * PAGE_SIZE;
e820entry[nr_map].size = 0xA * PAGE_SIZE;
e820entry[nr_map].type = E820_ACPI;
nr_map++;
mem_mapp->map[nr_map].addr = 0xFEC00000;
mem_mapp->map[nr_map].size = 0x1400000;
mem_mapp->map[nr_map].type = E820_IO;
mem_mapp->map[nr_map].caching_attr = MEMMAP_UC;
e820entry[nr_map].addr = 0xFEC00000;
e820entry[nr_map].size = 0x1400000;
e820entry[nr_map].type = E820_IO;
nr_map++;
mem_mapp->nr_map = nr_map;
return (*(((unsigned char *)e820_page) + E820_MAP_NR_OFFSET) = nr_map);
}
/*
@@ -112,19 +121,19 @@ static void build_e820map(struct mem_map *mem_mapp, unsigned long mem_size)
* vmxloader will use it to config ACPI MADT table
*/
#define VCPU_MAGIC 0x76637075 /* "vcpu" */
static int
set_nr_vcpus(int xc_handle, u32 dom, unsigned long *pfn_list,
static int
set_nr_vcpus(int xc_handle, u32 dom, unsigned long *pfn_list,
struct domain_setup_info *dsi, unsigned long vcpus)
{
char *va_map;
unsigned long *va_vcpus;
va_map = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
pfn_list[(0x9F000 - dsi->v_start) >> PAGE_SHIFT]);
pfn_list[(0x9F000 - dsi->v_start) >> PAGE_SHIFT]);
if ( va_map == NULL )
return -1;
va_vcpus = (unsigned long *)(va_map + 0x800);
*va_vcpus++ = VCPU_MAGIC;
*va_vcpus++ = vcpus;
@@ -164,24 +173,23 @@ static int zap_mmio_range(int xc_handle, u32 dom,
return 0;
}
static int zap_mmio_ranges(int xc_handle, u32 dom,
unsigned long l2tab,
struct mem_map *mem_mapp)
static int zap_mmio_ranges(int xc_handle, u32 dom, unsigned long l2tab,
unsigned char e820_map_nr, unsigned char *e820map)
{
int i;
unsigned int i;
struct e820entry *e820entry = (struct e820entry *)e820map;
l2_pgentry_32_t *vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l2tab >> PAGE_SHIFT);
if ( vl2tab == 0 )
return -1;
for ( i = 0; i < mem_mapp->nr_map; i++ )
for ( i = 0; i < e820_map_nr; i++ )
{
if ( (mem_mapp->map[i].type == E820_IO) &&
(mem_mapp->map[i].caching_attr == MEMMAP_UC) &&
if ( (e820entry[i].type == E820_IO) &&
(zap_mmio_range(xc_handle, dom, vl2tab,
mem_mapp->map[i].addr,
mem_mapp->map[i].size) == -1) )
e820entry[i].addr, e820entry[i].size) == -1))
return -1;
}
@@ -200,7 +208,7 @@ static int zap_mmio_range(int xc_handle, u32 dom,
unsigned long vl3e;
l1_pgentry_t *vl1tab;
l2_pgentry_t *vl2tab;
mmio_addr = mmio_range_start & PAGE_MASK;
for ( ; mmio_addr < mmio_range_end; mmio_addr += PAGE_SIZE )
{
@@ -239,22 +247,22 @@ static int zap_mmio_range(int xc_handle, u32 dom,
return 0;
}
static int zap_mmio_ranges(int xc_handle, u32 dom,
unsigned long l3tab,
struct mem_map *mem_mapp)
static int zap_mmio_ranges(int xc_handle, u32 dom, unsigned long l3tab,
unsigned char e820_map_nr, unsigned char *e820map)
{
int i;
unsigned int i;
struct e820entry *e820entry = (struct e820entry *)e820map;
l3_pgentry_t *vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l3tab >> PAGE_SHIFT);
if (vl3tab == 0)
return -1;
for (i = 0; i < mem_mapp->nr_map; i++) {
if ((mem_mapp->map[i].type == E820_IO)
&& (mem_mapp->map[i].caching_attr == MEMMAP_UC))
if (zap_mmio_range(xc_handle, dom, vl3tab,
mem_mapp->map[i].addr, mem_mapp->map[i].size) == -1)
return -1;
for ( i = 0; i < e820_map_nr; i++ ) {
if ( (e820entry[i].type == E820_IO) &&
(zap_mmio_range(xc_handle, dom, vl3tab,
e820entry[i].addr, e820entry[i].size) == -1) )
return -1;
}
munmap(vl3tab, PAGE_SIZE);
return 0;
@@ -265,18 +273,14 @@ static int zap_mmio_ranges(int xc_handle, u32 dom,
static int setup_guest(int xc_handle,
u32 dom, int memsize,
char *image, unsigned long image_size,
gzFile initrd_gfd, unsigned long initrd_len,
unsigned long nr_pages,
vcpu_guest_context_t *ctxt,
const char *cmdline,
unsigned long shared_info_frame,
unsigned int control_evtchn,
unsigned long flags,
unsigned int vcpus,
unsigned int store_evtchn,
unsigned long *store_mfn,
struct mem_map *mem_mapp
)
unsigned long *store_mfn)
{
l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
@@ -289,8 +293,8 @@ static int setup_guest(int xc_handle,
unsigned long l1tab;
unsigned long count, i;
shared_info_t *shared_info;
struct linux_boot_params * boot_paramsp;
__u16 * boot_gdtp;
void *e820_page;
unsigned char e820_map_nr;
xc_mmu_t *mmu = NULL;
int rc;
@@ -298,12 +302,6 @@ static int setup_guest(int xc_handle,
unsigned long ppt_alloc;
struct domain_setup_info dsi;
unsigned long vinitrd_start;
unsigned long vinitrd_end;
unsigned long vboot_params_start;
unsigned long vboot_params_end;
unsigned long vboot_gdt_start;
unsigned long vboot_gdt_end;
unsigned long vpt_start;
unsigned long vpt_end;
unsigned long v_end;
@@ -322,27 +320,8 @@ static int setup_guest(int xc_handle,
goto error_out;
}
/*
* Why do we need this? The number of page-table frames depends on the
* size of the bootstrap address space. But the size of the address space
* depends on the number of page-table frames (since each one is mapped
* read-only). We have a pair of simultaneous equations in two unknowns,
* which we solve by exhaustive search.
*/
vboot_params_start = LINUX_BOOT_PARAMS_ADDR;
vboot_params_end = vboot_params_start + PAGE_SIZE;
vboot_gdt_start = vboot_params_end;
vboot_gdt_end = vboot_gdt_start + PAGE_SIZE;
/* memsize is in megabytes */
v_end = memsize << 20;
/* leaving the top 4k untouched for IO requests page use */
vinitrd_end = v_end - PAGE_SIZE;
vinitrd_start = vinitrd_end - initrd_len;
vinitrd_start = vinitrd_start & (~(PAGE_SIZE - 1));
if(initrd_len == 0)
vinitrd_start = vinitrd_end = 0;
#ifdef __i386__
nr_pt_pages = 1 + ((memsize + 3) >> 2);
@@ -353,24 +332,17 @@ static int setup_guest(int xc_handle,
vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
printf("VIRTUAL MEMORY ARRANGEMENT:\n"
" Boot_params: %08lx->%08lx\n"
" boot_gdt: %08lx->%08lx\n"
" Loaded kernel: %08lx->%08lx\n"
" Init. ramdisk: %08lx->%08lx\n"
" Loaded VMX loader: %08lx->%08lx\n"
" Page tables: %08lx->%08lx\n"
" TOTAL: %08lx->%08lx\n",
vboot_params_start, vboot_params_end,
vboot_gdt_start, vboot_gdt_end,
dsi.v_kernstart, dsi.v_kernend,
vinitrd_start, vinitrd_end,
dsi.v_kernstart, dsi.v_kernend,
vpt_start, vpt_end,
dsi.v_start, v_end);
printf(" ENTRY ADDRESS: %08lx\n", dsi.v_kernentry);
printf(" INITRD LENGTH: %08lx\n", initrd_len);
if ( (v_end - dsi.v_start) > (nr_pages * PAGE_SIZE) )
{
printf("Initial guest OS requires too much space\n"
ERROR("Initial guest OS requires too much space\n"
"(%luMB is greater than %luMB limit)\n",
(v_end-dsi.v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
goto error_out;
@@ -390,23 +362,6 @@ static int setup_guest(int xc_handle,
loadelfimage(image, xc_handle, dom, page_array, &dsi);
/* Load the initial ramdisk image. */
if ( initrd_len != 0 )
{
for ( i = (vinitrd_start - dsi.v_start);
i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE )
{
char page[PAGE_SIZE];
if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
{
PERROR("Error reading initrd image, could not");
goto error_out;
}
xc_copy_to_domain_page(xc_handle, dom,
page_array[i>>PAGE_SHIFT], page);
}
}
if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL )
goto error_out;
@@ -428,15 +383,14 @@ static int setup_guest(int xc_handle,
l2tab = page_array[ppt_alloc++] << PAGE_SHIFT;
ctxt->ctrlreg[3] = l2tab;
/* Initialise the page tables. */
if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l2tab >> PAGE_SHIFT)) == NULL )
goto error_out;
memset(vl2tab, 0, PAGE_SIZE);
vl2e = &vl2tab[l2_table_offset(dsi.v_start)];
for ( count = 0; count < ((v_end-dsi.v_start)>>PAGE_SHIFT); count++ )
{
{
if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
{
l1tab = page_array[ppt_alloc++] << PAGE_SHIFT;
@@ -460,23 +414,35 @@ static int setup_guest(int xc_handle,
munmap(vl1tab, PAGE_SIZE);
munmap(vl2tab, PAGE_SIZE);
#else
/* here l3tab means pdpt, only 4 entry is used */
l3tab = page_array[ppt_alloc++] << PAGE_SHIFT;
ctxt->ctrlreg[3] = l3tab;
/* Initialise the page tables. */
if ( (vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
if ( (vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l3tab >> PAGE_SHIFT)) == NULL )
goto error_out;
memset(vl3tab, 0, PAGE_SIZE);
/* Fill in every PDPT entry. */
for ( i = 0; i < L3_PAGETABLE_ENTRIES_PAE; i++ )
{
l2tab = page_array[ppt_alloc++] << PAGE_SHIFT;
if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE,
l2tab >> PAGE_SHIFT)) == NULL )
goto error_out;
memset(vl2tab, 0, PAGE_SIZE);
munmap(vl2tab, PAGE_SIZE);
vl3tab[i] = l2tab | L3_PROT;
}
vl3e = &vl3tab[l3_table_offset(dsi.v_start)];
for ( count = 0; count < ((v_end-dsi.v_start)>>PAGE_SHIFT); count++ )
{
if (!(count % (1 << (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)))){
l2tab = page_array[ppt_alloc++] << PAGE_SHIFT;
if (!(count & (1 << (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)))){
l2tab = vl3tab[count >> (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)]
& PAGE_MASK;
if (vl2tab != NULL)
munmap(vl2tab, PAGE_SIZE);
@@ -486,8 +452,6 @@ static int setup_guest(int xc_handle,
l2tab >> PAGE_SHIFT)) == NULL )
goto error_out;
memset(vl2tab, 0, PAGE_SIZE);
*vl3e++ = l2tab | L3_PROT;
vl2e = &vl2tab[l2_table_offset(dsi.v_start + (count << PAGE_SHIFT))];
}
if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
@@ -519,103 +483,31 @@ static int setup_guest(int xc_handle,
for ( count = 0; count < nr_pages; count++ )
{
if ( xc_add_mmu_update(xc_handle, mmu,
(page_array[count] << PAGE_SHIFT) |
(page_array[count] << PAGE_SHIFT) |
MMU_MACHPHYS_UPDATE, count) )
goto error_out;
}
set_nr_vcpus(xc_handle, dom, page_array, &dsi, vcpus);
if ((boot_paramsp = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
page_array[(vboot_params_start-dsi.v_start)>>PAGE_SHIFT])) == 0)
goto error_out;
memset(boot_paramsp, 0, sizeof(*boot_paramsp));
strncpy((char *)boot_paramsp->cmd_line, cmdline, 0x800);
boot_paramsp->cmd_line[0x800-1] = '\0';
boot_paramsp->cmd_line_ptr = ((unsigned long) vboot_params_start) + offsetof(struct linux_boot_params, cmd_line);
boot_paramsp->setup_sects = 0;
boot_paramsp->mount_root_rdonly = 1;
boot_paramsp->swapdev = 0x0;
boot_paramsp->ramdisk_flags = 0x0;
boot_paramsp->root_dev = 0x0; /* We must tell kernel root dev by kernel command line. */
/* we don't have a ps/2 mouse now.
* 0xAA means a aux mouse is there.
* See detect_auxiliary_port() in pc_keyb.c.
*/
boot_paramsp->aux_device_info = 0x0;
boot_paramsp->header_magic[0] = 0x48; /* "H" */
boot_paramsp->header_magic[1] = 0x64; /* "d" */
boot_paramsp->header_magic[2] = 0x72; /* "r" */
boot_paramsp->header_magic[3] = 0x53; /* "S" */
boot_paramsp->protocol_version = 0x0203; /* 2.03 */
boot_paramsp->loader_type = 0x71; /* GRUB */
boot_paramsp->loader_flags = 0x1; /* loaded high */
boot_paramsp->code32_start = LINUX_KERNEL_ENTR_ADDR; /* 1MB */
boot_paramsp->initrd_start = vinitrd_start;
boot_paramsp->initrd_size = initrd_len;
i = ((memsize - 1) << 10) - 4;
boot_paramsp->alt_mem_k = i; /* alt_mem_k */
boot_paramsp->screen.overlap.ext_mem_k = i & 0xFFFF; /* ext_mem_k */
/*
* Stuff SCREAN_INFO
*/
boot_paramsp->screen.info.orig_x = 0;
boot_paramsp->screen.info.orig_y = 0;
boot_paramsp->screen.info.orig_video_page = 8;
boot_paramsp->screen.info.orig_video_mode = 3;
boot_paramsp->screen.info.orig_video_cols = 80;
boot_paramsp->screen.info.orig_video_ega_bx = 0;
boot_paramsp->screen.info.orig_video_lines = 25;
boot_paramsp->screen.info.orig_video_isVGA = 1;
boot_paramsp->screen.info.orig_video_points = 0x0010;
/* seems we may NOT stuff boot_paramsp->apm_bios_info */
/* seems we may NOT stuff boot_paramsp->drive_info */
/* seems we may NOT stuff boot_paramsp->sys_desc_table */
*((unsigned short *) &boot_paramsp->drive_info.dummy[0]) = 800;
boot_paramsp->drive_info.dummy[2] = 4;
boot_paramsp->drive_info.dummy[14] = 32;
/* memsize is in megabytes */
/* If you need to create a special e820map, comment this line
and use mem-map.sxp */
build_e820map(mem_mapp, memsize << 20);
*store_mfn = page_array[(v_end-2) >> PAGE_SHIFT];
#if defined (__i386__)
if (zap_mmio_ranges(xc_handle, dom, l2tab, mem_mapp) == -1)
#else
if (zap_mmio_ranges(xc_handle, dom, l3tab, mem_mapp) == -1)
#endif
goto error_out;
boot_paramsp->e820_map_nr = mem_mapp->nr_map;
for (i=0; i<mem_mapp->nr_map; i++) {
boot_paramsp->e820_map[i].addr = mem_mapp->map[i].addr;
boot_paramsp->e820_map[i].size = mem_mapp->map[i].size;
boot_paramsp->e820_map[i].type = mem_mapp->map[i].type;
if (mem_mapp->map[i].type == E820_SHARED)
shared_page_frame = (mem_mapp->map[i].addr >> PAGE_SHIFT);
}
munmap(boot_paramsp, PAGE_SIZE);
shared_page_frame = (v_end - PAGE_SIZE) >> PAGE_SHIFT;
if ((boot_gdtp = xc_map_foreign_range(
if ((e820_page = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
page_array[(vboot_gdt_start-dsi.v_start)>>PAGE_SHIFT])) == 0)
page_array[E820_MAP_PAGE >> PAGE_SHIFT])) == 0)
goto error_out;
memset(boot_gdtp, 0, PAGE_SIZE);
boot_gdtp[12*4 + 0] = boot_gdtp[13*4 + 0] = 0xffff; /* limit */
boot_gdtp[12*4 + 1] = boot_gdtp[13*4 + 1] = 0x0000; /* base */
boot_gdtp[12*4 + 2] = 0x9a00; boot_gdtp[13*4 + 2] = 0x9200; /* perms */
boot_gdtp[12*4 + 3] = boot_gdtp[13*4 + 3] = 0x00cf; /* granu + top of limit */
munmap(boot_gdtp, PAGE_SIZE);
memset(e820_page, 0, PAGE_SIZE);
e820_map_nr = build_e820map(e820_page, v_end);
#if defined (__i386__)
if (zap_mmio_ranges(xc_handle, dom, l2tab, e820_map_nr,
((unsigned char *)e820_page) + E820_MAP_OFFSET) == -1)
#else
if (zap_mmio_ranges(xc_handle, dom, l3tab, e820_map_nr,
((unsigned char *)e820_page) + E820_MAP_OFFSET) == -1)
#endif
goto error_out;
munmap(e820_page, PAGE_SIZE);
/* shared_info page starts its life empty. */
if ((shared_info = xc_map_foreign_range(
@@ -651,20 +543,21 @@ static int setup_guest(int xc_handle,
/*
* Initial register values:
*/
ctxt->user_regs.ds = 0x68;
ctxt->user_regs.es = 0x0;
ctxt->user_regs.fs = 0x0;
ctxt->user_regs.gs = 0x0;
ctxt->user_regs.ss = 0x68;
ctxt->user_regs.cs = 0x60;
ctxt->user_regs.ds = 0;
ctxt->user_regs.es = 0;
ctxt->user_regs.fs = 0;
ctxt->user_regs.gs = 0;
ctxt->user_regs.ss = 0;
ctxt->user_regs.cs = 0;
ctxt->user_regs.eip = dsi.v_kernentry;
ctxt->user_regs.edx = vboot_gdt_start;
ctxt->user_regs.eax = 0x800;
ctxt->user_regs.esp = vboot_gdt_end;
ctxt->user_regs.edx = 0;
ctxt->user_regs.eax = 0;
ctxt->user_regs.esp = 0;
ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot cpu */
ctxt->user_regs.ecx = mem_mapp->nr_map;
ctxt->user_regs.esi = vboot_params_start;
ctxt->user_regs.edi = vboot_params_start + 0x2d0;
ctxt->user_regs.ecx = 0;
ctxt->user_regs.esi = 0;
ctxt->user_regs.edi = 0;
ctxt->user_regs.ebp = 0;
ctxt->user_regs.eflags = 0;
@@ -684,9 +577,9 @@ static int vmx_identify(void)
int eax, ecx;
#ifdef __i386__
__asm__ __volatile__ ("pushl %%ebx; cpuid; popl %%ebx"
: "=a" (eax), "=c" (ecx)
: "0" (1)
__asm__ __volatile__ ("pushl %%ebx; cpuid; popl %%ebx"
: "=a" (eax), "=c" (ecx)
: "0" (1)
: "dx");
#elif defined __x86_64__
__asm__ __volatile__ ("pushq %%rbx; cpuid; popq %%rbx"
@@ -705,9 +598,6 @@ int xc_vmx_build(int xc_handle,
u32 domid,
int memsize,
const char *image_name,
struct mem_map *mem_mapp,
const char *ramdisk_name,
const char *cmdline,
unsigned int control_evtchn,
unsigned long flags,
unsigned int vcpus,
@@ -715,20 +605,18 @@ int xc_vmx_build(int xc_handle,
unsigned long *store_mfn)
{
dom0_op_t launch_op, op;
int initrd_fd = -1;
gzFile initrd_gfd = NULL;
int rc, i;
vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
unsigned long nr_pages;
char *image = NULL;
unsigned long image_size, initrd_size=0;
unsigned long image_size;
if ( vmx_identify() < 0 )
{
PERROR("CPU doesn't support VMX Extensions");
goto error_out;
}
if ( (nr_pages = xc_get_tot_pages(xc_handle, domid)) < 0 )
{
PERROR("Could not find total pages for domain");
@@ -738,32 +626,15 @@ int xc_vmx_build(int xc_handle,
if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL )
goto error_out;
if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) )
{
if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 )
{
PERROR("Could not open the initial ramdisk image");
goto error_out;
}
initrd_size = xc_get_filesz(initrd_fd);
if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL )
{
PERROR("Could not allocate decompression state for initrd");
goto error_out;
}
}
if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
{
{
PERROR("xc_vmx_build: ctxt mlock failed");
return 1;
}
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = (domid_t)domid;
if ( (xc_dom0_op(xc_handle, &op) < 0) ||
if ( (xc_dom0_op(xc_handle, &op) < 0) ||
((u16)op.u.getdomaininfo.domain != domid) )
{
PERROR("Could not get info on domain");
@@ -783,21 +654,14 @@ int xc_vmx_build(int xc_handle,
goto error_out;
}
if ( setup_guest(xc_handle, domid, memsize, image, image_size,
initrd_gfd, initrd_size, nr_pages,
ctxt, cmdline,
op.u.getdomaininfo.shared_info_frame,
control_evtchn, flags, vcpus, store_evtchn, store_mfn,
mem_mapp) < 0 )
if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn,
flags, vcpus, store_evtchn, store_mfn) < 0)
{
ERROR("Error constructing guest OS");
goto error_out;
}
if ( initrd_fd >= 0 )
close(initrd_fd);
if ( initrd_gfd )
gzclose(initrd_gfd);
free(image);
ctxt->flags = VGCF_VMX_GUEST;
@@ -813,15 +677,10 @@ int xc_vmx_build(int xc_handle,
/* No LDT. */
ctxt->ldt_ents = 0;
/* Use the default Xen-provided GDT. */
ctxt->gdt_ents = 0;
/* Ring 1 stack is the initial stack. */
/*
ctxt->kernel_ss = FLAT_KERNEL_DS;
ctxt->kernel_sp = vstartinfo_start;
*/
/* No debugging. */
memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
@@ -845,14 +704,10 @@ int xc_vmx_build(int xc_handle,
launch_op.cmd = DOM0_SETDOMAININFO;
rc = xc_dom0_op(xc_handle, &launch_op);
return rc;
error_out:
if ( initrd_gfd != NULL )
gzclose(initrd_gfd);
else if ( initrd_fd >= 0 )
close(initrd_fd);
free(image);
return -1;
@@ -864,7 +719,7 @@ static inline int is_loadable_phdr(Elf32_Phdr *phdr)
((phdr->p_flags & (PF_W|PF_X)) != 0));
}
static int parseelfimage(char *elfbase,
static int parseelfimage(char *elfbase,
unsigned long elfsize,
struct domain_setup_info *dsi)
{
@@ -899,11 +754,11 @@ static int parseelfimage(char *elfbase,
ERROR("ELF image has no section-header strings table (shstrtab).");
return -EINVAL;
}
shdr = (Elf32_Shdr *)(elfbase + ehdr->e_shoff +
shdr = (Elf32_Shdr *)(elfbase + ehdr->e_shoff +
(ehdr->e_shstrndx*ehdr->e_shentsize));
shstrtab = elfbase + shdr->sh_offset;
for ( h = 0; h < ehdr->e_phnum; h++ )
for ( h = 0; h < ehdr->e_phnum; h++ )
{
phdr = (Elf32_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
if ( !is_loadable_phdr(phdr) )
@@ -914,8 +769,8 @@ static int parseelfimage(char *elfbase,
kernend = phdr->p_paddr + phdr->p_memsz;
}
if ( (kernstart > kernend) ||
(ehdr->e_entry < kernstart) ||
if ( (kernstart > kernend) ||
(ehdr->e_entry < kernstart) ||
(ehdr->e_entry > kernend) )
{
ERROR("Malformed ELF image.");
@@ -924,9 +779,9 @@ static int parseelfimage(char *elfbase,
dsi->v_start = 0x00000000;
dsi->v_kernstart = kernstart - LINUX_PAGE_OFFSET;
dsi->v_kernend = kernend - LINUX_PAGE_OFFSET;
dsi->v_kernentry = LINUX_KERNEL_ENTR_ADDR;
dsi->v_kernstart = kernstart;
dsi->v_kernend = kernend;
dsi->v_kernentry = VMX_LOADER_ENTR_ADDR;
dsi->v_end = dsi->v_kernend;
@@ -945,18 +800,18 @@ loadelfimage(
char *va;
unsigned long pa, done, chunksz;
for ( h = 0; h < ehdr->e_phnum; h++ )
for ( h = 0; h < ehdr->e_phnum; h++ )
{
phdr = (Elf32_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
if ( !is_loadable_phdr(phdr) )
continue;
for ( done = 0; done < phdr->p_filesz; done += chunksz )
{
pa = (phdr->p_paddr + done) - dsi->v_start - LINUX_PAGE_OFFSET;
pa = (phdr->p_paddr + done) - dsi->v_start;
if ((va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE,
parray[pa>>PAGE_SHIFT])) == 0)
parray[pa >> PAGE_SHIFT])) == 0)
return -1;
chunksz = phdr->p_filesz - done;
if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
@@ -968,10 +823,10 @@ loadelfimage(
for ( ; done < phdr->p_memsz; done += chunksz )
{
pa = (phdr->p_paddr + done) - dsi->v_start - LINUX_PAGE_OFFSET;
pa = (phdr->p_paddr + done) - dsi->v_start;
if ((va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE,
parray[pa>>PAGE_SHIFT])) == 0)
parray[pa >> PAGE_SHIFT])) == 0)
return -1;
chunksz = phdr->p_memsz - done;
if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
-3
View File
@@ -57,9 +57,6 @@ int xc_vmx_build(int xc_handle,
uint32_t domid,
int memsize,
const char *image_name,
struct mem_map *memmap,
const char *ramdisk_name,
const char *cmdline,
unsigned int control_evtchn,
unsigned long flags,
unsigned int vcpus,
+18 -15
View File
@@ -28,25 +28,27 @@ unsigned long csum_page (void * page);
#define _PAGE_PSE 0x080
#define _PAGE_GLOBAL 0x100
#if defined(__i386__)
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 22
#define L1_PAGETABLE_SHIFT_PAE 12
#define L2_PAGETABLE_SHIFT_PAE 21
#define L3_PAGETABLE_SHIFT_PAE 30
#if defined(__i386__)
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 22
#elif defined(__x86_64__)
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 21
#define L3_PAGETABLE_SHIFT 30
#define L4_PAGETABLE_SHIFT 39
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 21
#define L3_PAGETABLE_SHIFT 30
#define L4_PAGETABLE_SHIFT 39
#endif
#if defined(__i386__)
#define ENTRIES_PER_L1_PAGETABLE 1024
#define ENTRIES_PER_L2_PAGETABLE 1024
#define L1_PAGETABLE_ENTRIES_PAE 512
#define L2_PAGETABLE_ENTRIES_PAE 512
#define L3_PAGETABLE_ENTRIES_PAE 4
#if defined(__i386__)
#define L1_PAGETABLE_ENTRIES 1024
#define L2_PAGETABLE_ENTRIES 1024
#elif defined(__x86_64__)
#define L1_PAGETABLE_ENTRIES 512
#define L2_PAGETABLE_ENTRIES 512
@@ -70,17 +72,18 @@ typedef unsigned long l3_pgentry_t;
typedef unsigned long l4_pgentry_t;
#endif
#if defined(__i386__)
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
#define l2_table_offset(_a) \
((_a) >> L2_PAGETABLE_SHIFT)
#define l1_table_offset_pae(_a) \
(((_a) >> L1_PAGETABLE_SHIFT_PAE) & (L1_PAGETABLE_ENTRIES_PAE - 1))
#define l2_table_offset_pae(_a) \
(((_a) >> L2_PAGETABLE_SHIFT_PAE) & (L2_PAGETABLE_ENTRIES_PAE - 1))
#define l3_table_offset_pae(_a) \
(((_a) >> L3_PAGETABLE_SHIFT_PAE) & (L3_PAGETABLE_ENTRIES_PAE - 1))
#if defined(__i386__)
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
#define l2_table_offset(_a) \
((_a) >> L2_PAGETABLE_SHIFT)
#elif defined(__x86_64__)
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
+7 -64
View File
@@ -17,7 +17,6 @@
#include <arpa/inet.h>
#include "xc_private.h"
#include "linux_boot_params.h"
/* Needed for Python versions earlier than 2.3. */
#ifndef PyMODINIT_FUNC
@@ -310,80 +309,24 @@ static PyObject *pyxc_vmx_build(PyObject *self,
XcObject *xc = (XcObject *)self;
u32 dom;
char *image, *ramdisk = NULL, *cmdline = "";
PyObject *memmap;
char *image;
int control_evtchn, store_evtchn;
int flags = 0, vcpus = 1;
int numItems, i;
int memsize;
struct mem_map mem_map;
unsigned long store_mfn = 0;
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
"memsize", "image", "memmap",
"ramdisk", "cmdline", "flags",
"vcpus", NULL };
"memsize", "image", "flags", "vcpus", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisO!|ssii", kwd_list,
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
&dom, &control_evtchn, &store_evtchn,
&memsize,
&image, &PyList_Type, &memmap,
&ramdisk, &cmdline, &flags, &vcpus) )
&memsize, &image, &flags, &vcpus) )
return NULL;
memset(&mem_map, 0, sizeof(mem_map));
/* Parse memmap */
/* get the number of lines passed to us */
numItems = PyList_Size(memmap) - 1; /* removing the line
containing "memmap" */
mem_map.nr_map = numItems;
/* should raise an error here. */
if (numItems < 0) return NULL; /* Not a list */
/* iterate over items of the list, grabbing ranges and parsing them */
for (i = 1; i <= numItems; i++) { // skip over "memmap"
PyObject *item, *f1, *f2, *f3, *f4;
int numFields;
unsigned long lf1, lf2, lf3, lf4;
char *sf1, *sf2;
/* grab the string object from the next element of the list */
item = PyList_GetItem(memmap, i); /* Can't fail */
/* get the number of lines passed to us */
numFields = PyList_Size(item);
if (numFields != 4)
return NULL;
f1 = PyList_GetItem(item, 0);
f2 = PyList_GetItem(item, 1);
f3 = PyList_GetItem(item, 2);
f4 = PyList_GetItem(item, 3);
/* Convert objects to strings/longs */
sf1 = PyString_AsString(f1);
sf2 = PyString_AsString(f2);
lf3 = PyLong_AsLong(f3);
lf4 = PyLong_AsLong(f4);
if ( sscanf(sf1, "%lx", &lf1) != 1 )
return NULL;
if ( sscanf(sf2, "%lx", &lf2) != 1 )
return NULL;
mem_map.map[i-1].addr = lf1;
mem_map.map[i-1].size = lf2 - lf1;
mem_map.map[i-1].type = lf3;
mem_map.map[i-1].caching_attr = lf4;
}
if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, &mem_map,
ramdisk, cmdline, control_evtchn, flags,
vcpus, store_evtchn, &store_mfn) != 0 )
if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, control_evtchn,
flags, vcpus, store_evtchn, &store_mfn) != 0 )
return PyErr_SetFromErrno(xc_error);
return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
}
+12 -8
View File
@@ -582,9 +582,8 @@ static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
}
#define xspy_transaction_start_doc "\n" \
"Start a transaction on a path.\n" \
"Start a transaction.\n" \
"Only one transaction can be active at a time.\n" \
" path [string]: xenstore path.\n" \
"\n" \
"Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
@@ -593,8 +592,8 @@ static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
static char *arg_spec = "s|";
static char *kwd_spec[] = { NULL };
static char *arg_spec = "";
char *path = NULL;
struct xs_handle *xh = xshandle(self);
@@ -606,7 +605,7 @@ static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_transaction_start(xh, path);
xsval = xs_transaction_start(xh);
Py_END_ALLOW_THREADS
if (!xsval) {
PyErr_SetFromErrno(PyExc_RuntimeError);
@@ -623,7 +622,7 @@ static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
"Attempts to commit the transaction unless abort is true.\n" \
" abort [int]: abort flag (default 0).\n" \
"\n" \
"Returns None on success.\n" \
"Returns True on success, False if you need to try again.\n" \
"Raises RuntimeError on error.\n" \
"\n"
@@ -646,11 +645,16 @@ static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
xsval = xs_transaction_end(xh, abort);
Py_END_ALLOW_THREADS
if (!xsval) {
if (errno == EAGAIN) {
Py_INCREF(Py_False);
val = Py_False;
goto exit;
}
PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
}
Py_INCREF(Py_None);
val = Py_None;
Py_INCREF(Py_True);
val = Py_True;
exit:
return val;
}
-41
View File
@@ -1,41 +0,0 @@
mem_caching_attr = {
'UC' : 0,
'WC' : 1,
'WT' : 4,
'WP' : 5,
'WB' : 6,
};
e820_mem_type = {
'AddressRangeMemory' : 1,
'AddressRangeReserved' : 2,
'AddressRangeACPI' : 3,
'AddressRangeNVS' : 4,
'AddressRangeIO' : 16,
'AddressRangeShared' : 17,
};
MT_COL = 2
MA_COL = 3
def strmap(row):
if (type(row) != type([])):
return row
row[MT_COL] = e820_mem_type[row[MT_COL]]
row[MA_COL] = mem_caching_attr[row[MA_COL]]
return row
def memmap_parse(memmap):
return map(strmap, memmap)
if __name__ == '__main__':
memmap = [ 'memmap',
[ '1', '2', 'AddressRangeMemory', 'UC'],
[ '1', '2', 'AddressRangeReserved', 'UC'],
[ '1', '2', 'AddressRangeACPI', 'WB'],
[ '1', '2', 'AddressRangeNVS', 'WB'],
[ '1', '2', 'AddressRangeIO', 'WB'],
[ '1', '2', 'AddressRangeShared', 'WB']]
print memmap_parse(memmap);
-451
View File
@@ -1,451 +0,0 @@
"""Temporary files.
This module provides generic, low- and high-level interfaces for
creating temporary files and directories. The interfaces listed
as "safe" just below can be used without fear of race conditions.
Those listed as "unsafe" cannot, and are provided for backward
compatibility only.
This module also provides some data items to the user:
TMP_MAX - maximum number of names that will be tried before
giving up.
template - the default prefix for all temporary names.
You may change this to control the default prefix.
tempdir - If this is set to a string before the first use of
any routine from this module, it will be considered as
another candidate location to store temporary files.
"""
__all__ = [
"NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
"mkstemp", "mkdtemp", # low level safe interfaces
"mktemp", # deprecated unsafe interface
"TMP_MAX", "gettempprefix", # constants
"tempdir", "gettempdir"
]
# Imports.
import os as _os
import errno as _errno
from random import Random as _Random
if _os.name == 'mac':
import Carbon.Folder as _Folder
import Carbon.Folders as _Folders
try:
import fcntl as _fcntl
# If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
# imported, and we don't get an ImportError then. Provoke
# an AttributeError instead in that case.
_fcntl.fcntl
except (ImportError, AttributeError):
def _set_cloexec(fd):
pass
else:
def _set_cloexec(fd):
flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
if flags >= 0:
# flags read successfully, modify
flags |= _fcntl.FD_CLOEXEC
_fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
try:
import thread as _thread
except ImportError:
import dummy_thread as _thread
_allocate_lock = _thread.allocate_lock
_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
if hasattr(_os, 'O_NOINHERIT'):
_text_openflags |= _os.O_NOINHERIT
if hasattr(_os, 'O_NOFOLLOW'):
_text_openflags |= _os.O_NOFOLLOW
_bin_openflags = _text_openflags
if hasattr(_os, 'O_BINARY'):
_bin_openflags |= _os.O_BINARY
if hasattr(_os, 'TMP_MAX'):
TMP_MAX = _os.TMP_MAX
else:
TMP_MAX = 10000
template = "tmp"
tempdir = None
# Internal routines.
_once_lock = _allocate_lock()
class _RandomNameSequence:
"""An instance of _RandomNameSequence generates an endless
sequence of unpredictable strings which can safely be incorporated
into file names. Each string is six characters long. Multiple
threads can safely use the same instance at the same time.
_RandomNameSequence is an iterator."""
characters = ("abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"0123456789-_")
def __init__(self):
self.mutex = _allocate_lock()
self.rng = _Random()
self.normcase = _os.path.normcase
def __iter__(self):
return self
def next(self):
m = self.mutex
c = self.characters
choose = self.rng.choice
m.acquire()
try:
letters = [choose(c) for dummy in "123456"]
finally:
m.release()
return self.normcase(''.join(letters))
def _candidate_tempdir_list():
"""Generate a list of candidate temporary directories which
_get_default_tempdir will try."""
dirlist = []
# First, try the environment.
for envname in 'TMPDIR', 'TEMP', 'TMP':
dirname = _os.getenv(envname)
if dirname: dirlist.append(dirname)
# Failing that, try OS-specific locations.
if _os.name == 'mac':
try:
fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
_Folders.kTemporaryFolderType, 1)
dirname = fsr.as_pathname()
dirlist.append(dirname)
except _Folder.error:
pass
elif _os.name == 'riscos':
dirname = _os.getenv('Wimp$ScrapDir')
if dirname: dirlist.append(dirname)
elif _os.name == 'nt':
dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
else:
dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
# As a last resort, the current directory.
try:
dirlist.append(_os.getcwd())
except (AttributeError, _os.error):
dirlist.append(_os.curdir)
return dirlist
def _get_default_tempdir():
"""Calculate the default directory to use for temporary files.
This routine should be called exactly once.
We determine whether or not a candidate temp dir is usable by
trying to create and write to a file in that directory. If this
is successful, the test file is deleted. To prevent denial of
service, the name of the test file must be randomized."""
namer = _RandomNameSequence()
dirlist = _candidate_tempdir_list()
flags = _text_openflags
for dir in dirlist:
if dir != _os.curdir:
dir = _os.path.normcase(_os.path.abspath(dir))
# Try only a few names per directory.
for seq in xrange(100):
name = namer.next()
filename = _os.path.join(dir, name)
try:
fd = _os.open(filename, flags, 0600)
fp = _os.fdopen(fd, 'w')
fp.write('blat')
fp.close()
_os.unlink(filename)
del fp, fd
return dir
except (OSError, IOError), e:
if e[0] != _errno.EEXIST:
break # no point trying more names in this directory
pass
raise IOError, (_errno.ENOENT,
("No usable temporary directory found in %s" % dirlist))
_name_sequence = None
def _get_candidate_names():
"""Common setup sequence for all user-callable interfaces."""
global _name_sequence
if _name_sequence is None:
_once_lock.acquire()
try:
if _name_sequence is None:
_name_sequence = _RandomNameSequence()
finally:
_once_lock.release()
return _name_sequence
def _mkstemp_inner(dir, pre, suf, flags):
"""Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
names = _get_candidate_names()
for seq in xrange(TMP_MAX):
name = names.next()
file = _os.path.join(dir, pre + name + suf)
try:
fd = _os.open(file, flags, 0600)
_set_cloexec(fd)
return (fd, file)
except OSError, e:
if e.errno == _errno.EEXIST:
continue # try again
raise
raise IOError, (_errno.EEXIST, "No usable temporary file name found")
# User visible interfaces.
def gettempprefix():
"""Accessor for tempdir.template."""
return template
tempdir = None
def gettempdir():
"""Accessor for tempdir.tempdir."""
global tempdir
if tempdir is None:
_once_lock.acquire()
try:
if tempdir is None:
tempdir = _get_default_tempdir()
finally:
_once_lock.release()
return tempdir
def mkstemp(suffix="", prefix=template, dir=None, text=False):
"""mkstemp([suffix, [prefix, [dir, [text]]]])
User-callable function to create and return a unique temporary
file. The return value is a pair (fd, name) where fd is the
file descriptor returned by os.open, and name is the filename.
If 'suffix' is specified, the file name will end with that suffix,
otherwise there will be no suffix.
If 'prefix' is specified, the file name will begin with that prefix,
otherwise a default prefix is used.
If 'dir' is specified, the file will be created in that directory,
otherwise a default directory is used.
If 'text' is specified and true, the file is opened in text
mode. Else (the default) the file is opened in binary mode. On
some operating systems, this makes no difference.
The file is readable and writable only by the creating user ID.
If the operating system uses permission bits to indicate whether a
file is executable, the file is executable by no one. The file
descriptor is not inherited by children of this process.
Caller is responsible for deleting the file when done with it.
"""
if dir is None:
dir = gettempdir()
if text:
flags = _text_openflags
else:
flags = _bin_openflags
return _mkstemp_inner(dir, prefix, suffix, flags)
def mkdtemp(suffix="", prefix=template, dir=None):
"""mkdtemp([suffix, [prefix, [dir]]])
User-callable function to create and return a unique temporary
directory. The return value is the pathname of the directory.
Arguments are as for mkstemp, except that the 'text' argument is
not accepted.
The directory is readable, writable, and searchable only by the
creating user.
Caller is responsible for deleting the directory when done with it.
"""
if dir is None:
dir = gettempdir()
names = _get_candidate_names()
for seq in xrange(TMP_MAX):
name = names.next()
file = _os.path.join(dir, prefix + name + suffix)
try:
_os.mkdir(file, 0700)
return file
except OSError, e:
if e.errno == _errno.EEXIST:
continue # try again
raise
raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
def mktemp(suffix="", prefix=template, dir=None):
"""mktemp([suffix, [prefix, [dir]]])
User-callable function to return a unique temporary file name. The
file is not created.
Arguments are as for mkstemp, except that the 'text' argument is
not accepted.
This function is unsafe and should not be used. The file name
refers to a file that did not exist at some point, but by the time
you get around to creating it, someone else may have beaten you to
the punch.
"""
## from warnings import warn as _warn
## _warn("mktemp is a potential security risk to your program",
## RuntimeWarning, stacklevel=2)
if dir is None:
dir = gettempdir()
names = _get_candidate_names()
for seq in xrange(TMP_MAX):
name = names.next()
file = _os.path.join(dir, prefix + name + suffix)
if not _os.path.exists(file):
return file
raise IOError, (_errno.EEXIST, "No usable temporary filename found")
class _TemporaryFileWrapper:
"""Temporary file wrapper
This class provides a wrapper around files opened for
temporary use. In particular, it seeks to automatically
remove the file when it is no longer needed.
"""
def __init__(self, file, name):
self.file = file
self.name = name
self.close_called = False
def __getattr__(self, name):
file = self.__dict__['file']
a = getattr(file, name)
if type(a) != type(0):
setattr(self, name, a)
return a
# NT provides delete-on-close as a primitive, so we don't need
# the wrapper to do anything special. We still use it so that
# file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
if _os.name != 'nt':
# Cache the unlinker so we don't get spurious errors at
# shutdown when the module-level "os" is None'd out. Note
# that this must be referenced as self.unlink, because the
# name TemporaryFileWrapper may also get None'd out before
# __del__ is called.
unlink = _os.unlink
def close(self):
if not self.close_called:
self.close_called = True
self.file.close()
self.unlink(self.name)
def __del__(self):
self.close()
def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
prefix=template, dir=None):
"""Create and return a temporary file.
Arguments:
'prefix', 'suffix', 'dir' -- as for mkstemp.
'mode' -- the mode argument to os.fdopen (default "w+b").
'bufsize' -- the buffer size argument to os.fdopen (default -1).
The file is created as mkstemp() would do it.
Returns a file object; the name of the file is accessible as
file.name. The file will be automatically deleted when it is
closed.
"""
if dir is None:
dir = gettempdir()
if 'b' in mode:
flags = _bin_openflags
else:
flags = _text_openflags
# Setting O_TEMPORARY in the flags causes the OS to delete
# the file when it is closed. This is only supported by Windows.
if _os.name == 'nt':
flags |= _os.O_TEMPORARY
(fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
file = _os.fdopen(fd, mode, bufsize)
return _TemporaryFileWrapper(file, name)
if _os.name != 'posix' or _os.sys.platform == 'cygwin':
# On non-POSIX and Cygwin systems, assume that we cannot unlink a file
# while it is open.
TemporaryFile = NamedTemporaryFile
else:
def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
prefix=template, dir=None):
"""Create and return a temporary file.
Arguments:
'prefix', 'suffix', 'directory' -- as for mkstemp.
'mode' -- the mode argument to os.fdopen (default "w+b").
'bufsize' -- the buffer size argument to os.fdopen (default -1).
The file is created as mkstemp() would do it.
Returns a file object. The file has no name, and will cease to
exist when it is closed.
"""
if dir is None:
dir = gettempdir()
if 'b' in mode:
flags = _bin_openflags
else:
flags = _text_openflags
(fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
try:
_os.unlink(name)
return _os.fdopen(fd, mode, bufsize)
except:
_os.close(fd)
raise
-43
View File
@@ -1,43 +0,0 @@
"""Xend interface to block control scripts.
"""
import os
import os.path
import sys
import string
import xen.util.process
from xen.xend import XendRoot
xroot = XendRoot.instance()
"""Where network control scripts live."""
SCRIPT_DIR = xroot.block_script_dir
def block(op, type, dets, script=None):
"""Call a block control script.
Xend calls this with op 'bind' when it is about to export a block device
(other than a raw partition). The script is called with unbind when a
device is no longer in use and should be removed.
@param op: operation (start, stop, status)
@param type: type of block device (determines the script used)
@param dets: arguments to the control script
@param script: block script name
"""
if op not in ['bind', 'unbind']:
raise ValueError('Invalid operation:' + op)
# Special case phy devices - they don't require any (un)binding
# Parallax also doesn't need script-based binding.
if (type == 'phy') or (type == 'parallax'):
return dets
if script is None:
script = xroot.get_block_script(type)
script = os.path.join(SCRIPT_DIR, script)
args = [op] + string.split(dets, ':')
args = ' '.join(args)
ret = xen.util.process.runscript(script + ' ' + args)
if len(ret):
return ret.splitlines()[0]
+1 -1
View File
@@ -252,7 +252,7 @@ class PrettyPrinter:
self.block = self.block.parent
def prettyprint(self, out=sys.stdout):
self.top.prettyprint(Line(out, self.width))
self.top.prettyprint(Line(out, self.width), self.width)
class SXPPrettyPrinter(PrettyPrinter):
"""An SXP prettyprinter.
-127
View File
@@ -1,127 +0,0 @@
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
#============================================================================
import os
import os.path
import errno
import dircache
import time
import sxp
import XendRoot
xroot = XendRoot.instance()
class XendDB:
"""Persistence for Xend. Stores data in files and directories.
"""
def __init__(self, path=None):
self.dbpath = xroot.get_dbroot()
if path:
self.dbpath = os.path.join(self.dbpath, path)
pass
def listdir(self, dpath):
try:
return dircache.listdir(dpath)
except:
return []
def filepath(self, path):
return os.path.join(self.dbpath, path)
def fetch(self, path):
fpath = self.filepath(path)
return self.fetchfile(fpath)
def fetchfile(self, fpath):
pin = sxp.Parser()
fin = file(fpath, "rb")
try:
while 1:
try:
buf = fin.read(1024)
except IOError, ex:
if ex.errno == errno.EINTR:
continue
else:
raise
pin.input(buf)
if buf == '':
pin.input_eof()
break
finally:
fin.close()
return pin.get_val()
def save(self, path, sxpr):
fpath = self.filepath(path)
return self.savefile(fpath, sxpr)
def savefile(self, fpath, sxpr):
backup = False
fdir = os.path.dirname(fpath)
if not os.path.isdir(fdir):
os.makedirs(fdir)
if os.path.exists(fpath):
backup = True
real_fpath = fpath
fpath += ".new."
fout = file(fpath, "wb+")
try:
try:
t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
fout.write("# %s %s\n" % (fpath, t))
sxp.show(sxpr, out=fout)
finally:
fout.close()
except:
if backup:
try:
os.unlink(fpath)
except:
pass
raise
if backup:
os.rename(fpath, real_fpath)
def fetchall(self, path):
dpath = self.filepath(path)
d = {}
for k in self.listdir(dpath):
try:
v = self.fetchfile(os.path.join(dpath, k))
d[k] = v
except:
pass
return d
def saveall(self, path, d):
for (k, v) in d.items():
self.save(os.path.join(path, k), v)
def delete(self, path):
dpath = self.filepath(path)
os.unlink(dpath)
def ls(self, path):
dpath = self.filepath(path)
return self.listdir(dpath)
+49 -83
View File
@@ -433,12 +433,11 @@ class XendDomain:
self.domain_shutdowns()
return val
def domain_sysrq(self, id, key):
"""Send a SysRq to a domain
"""
dominfo = self.domain_lookup(id)
val = dominfo.send_sysrq(key)
return val
"""Send a SysRq to the specified domain."""
return self.callInfo(id, XendDomainInfo.send_sysrq, key)
def domain_shutdowns(self):
"""Process pending domain shutdowns.
@@ -630,73 +629,45 @@ class XendDomain:
except Exception, ex:
raise XendError(str(ex))
def domain_device_create(self, id, devconfig):
"""Create a new device for a domain.
@param id: domain id
@param devconfig: device configuration
def domain_device_create(self, domid, devconfig):
"""Create a new device for the specified domain.
"""
dominfo = self.domain_lookup(id)
val = dominfo.device_create(devconfig)
dominfo.exportToDB()
return val
return self.callInfo(domid, XendDomainInfo.device_create, devconfig)
def domain_device_configure(self, id, devconfig, devid):
"""Configure an existing device for a domain.
@param id: domain id
@param devconfig: device configuration
@param devid: device id
def domain_device_configure(self, domid, devconfig, devid):
"""Configure an existing device in the specified domain.
@return: updated device configuration
"""
dominfo = self.domain_lookup(id)
val = dominfo.device_configure(devconfig, devid)
dominfo.exportToDB()
return val
return self.callInfo(domid, XendDomainInfo.device_configure,
devconfig, devid)
def domain_device_refresh(self, id, type, devid):
"""Refresh a device.
@param id: domain id
@param devid: device id
@param type: device type
"""
dominfo = self.domain_lookup(id)
val = dominfo.device_refresh(type, devid)
dominfo.exportToDB()
return val
def domain_device_destroy(self, id, type, devid):
"""Destroy a device.
@param id: domain id
@param devid: device id
@param type: device type
"""
dominfo = self.domain_lookup(id)
return dominfo.destroyDevice(type, devid)
def domain_device_refresh(self, domid, devtype, devid):
"""Refresh a device."""
return self.callInfo(domid, XendDomainInfo.device_refresh, devtype,
devid)
def domain_devtype_ls(self, id, type):
"""Get list of device sxprs for a domain.
def domain_device_destroy(self, domid, devtype, devid):
"""Destroy a device."""
return self.callInfo(domid, XendDomainInfo.destroyDevice, devtype,
devid)
@param id: domain
@param type: device type
@return: device sxprs
"""
dominfo = self.domain_lookup(id)
return dominfo.getDeviceSxprs(type)
def domain_devtype_get(self, id, type, devid):
def domain_devtype_ls(self, domid, devtype):
"""Get list of device sxprs for the specified domain."""
return self.callInfo(domid, XendDomainInfo.getDeviceSxprs, devtype)
def domain_devtype_get(self, domid, devtype, devid):
"""Get a device from a domain.
@param id: domain
@param type: device type
@param devid: device id
@return: device object (or None)
"""
dominfo = self.domain_lookup(id)
return dominfo.getDevice(type, devid)
return self.callInfo(domid, XendDomainInfo.getDevice, devtype, devid)
def domain_vif_limit_set(self, id, vif, credit, period):
"""Limit the vif's transmission rate
@@ -723,7 +694,7 @@ class XendDomain:
"""Set the memory limit for a domain.
@param id: domain
@param mem: memory limit (in MB)
@param mem: memory limit (in MiB)
@return: 0 on success, -1 on error
"""
dominfo = self.domain_lookup(id)
@@ -734,42 +705,37 @@ class XendDomain:
except Exception, ex:
raise XendError(str(ex))
def domain_mem_target_set(self, id, mem):
def domain_mem_target_set(self, domid, mem):
"""Set the memory target for a domain.
@param id: domain
@param mem: memory target (in MB)
@return: 0 on success, -1 on error
@param mem: memory target (in MiB)
"""
dominfo = self.domain_lookup(id)
return dominfo.setMemoryTarget(mem << 10)
self.callInfo(domid, XendDomainInfo.setMemoryTarget, mem << 10)
def domain_vcpu_hotplug(self, id, vcpu, state):
"""Enable or disable VCPU vcpu in DOM id
@param id: domain
def domain_vcpu_hotplug(self, domid, vcpu, state):
"""Enable or disable specified VCPU in specified domain
@param vcpu: target VCPU in domain
@param state: which state VCPU will become
@return: 0 on success, -1 on error
"""
self.callInfo(domid, XendDomainInfo.vcpu_hotplug, vcpu, state)
dominfo = self.domain_lookup(id)
return dominfo.vcpu_hotplug(vcpu, state)
def domain_dumpcore(self, id):
"""Save a core dump for a crashed domain.
def domain_dumpcore(self, domid):
"""Save a core dump for a crashed domain."""
self.callInfo(domid, XendDomainInfo.dumpCore)
## private:
def callInfo(self, domid, fn, *args, **kwargs):
self.refresh()
dominfo = self.domains.get(domid)
if dominfo:
return fn(dominfo, *args, **kwargs)
@param id: domain
"""
dominfo = self.domain_lookup(id)
corefile = "/var/xen/dump/%s.%s.core" % (dominfo.getName(),
dominfo.getDomid())
try:
xc.domain_dumpcore(dom=dominfo.getDomid(), corefile=corefile)
except Exception, ex:
log.warning("Dumpcore failed, id=%s name=%s: %s",
dominfo.getDomid(), dominfo.getName(), ex)
def instance():
"""Singleton constructor. Use this instead of the class constructor.
"""
+38 -35
View File
@@ -34,6 +34,7 @@ from xen.util.blkif import blkdev_uname_to_file
from xen.xend.server.channel import EventChannel
from xen.xend import image
from xen.xend import sxp
from xen.xend.XendBootloader import bootloader
from xen.xend.XendLogging import log
@@ -319,6 +320,7 @@ class XendDomainInfo:
try:
defaultInfo('name', lambda: "Domain-%d" % self.domid)
defaultInfo('ssidref', lambda: 0)
defaultInfo('restart_mode', lambda: RESTART_ONREBOOT)
defaultInfo('cpu_weight', lambda: 1.0)
defaultInfo('bootloader', lambda: None)
@@ -511,6 +513,19 @@ class XendDomainInfo:
self.info['backend'], 0)
def dumpCore(self):
"""Create a core dump for this domain. Nothrow guarantee."""
try:
corefile = "/var/xen/dump/%s.%s.core" % (self.info['name'],
self.domid)
xc.domain_dumpcore(dom = self.domid, corefile = corefile)
except Exception, exn:
log.error("XendDomainInfo.dumpCore failed: id = %s name = %s: %s",
self.domid, self.info['name'], str(exn))
def closeStoreChannel(self):
"""Close the store channel, if any. Nothrow guarantee."""
@@ -614,7 +629,7 @@ class XendDomainInfo:
sxpr.append(['maxmem', self.info['maxmem_KiB'] / 1024])
if self.infoIsSet('device'):
for (n, c) in self.info['device']:
for (_, c) in self.info['device']:
sxpr.append(['device', c])
def stateChar(name):
@@ -706,13 +721,6 @@ class XendDomainInfo:
"""
# todo - add support for scheduling params?
try:
if 'image' not in self.info:
raise VmError('Missing image in configuration')
self.image = ImageHandler.create(self,
self.info['image'],
self.info['device'])
self.initDomain()
# Create domain devices.
@@ -737,6 +745,14 @@ class XendDomainInfo:
self.domid = xc.domain_create(dom = self.domid or 0,
ssidref = self.info['ssidref'])
if 'image' not in self.info:
raise VmError('Missing image in configuration')
self.image = image.create(self,
self.info['image'],
self.info['device'])
if self.domid <= 0:
raise VmError('Creating domain failed: name=%s' %
self.info['name'])
@@ -839,20 +855,20 @@ class XendDomainInfo:
"""Release all vm devices.
"""
t = xstransact("%s/device" % self.path)
for n in controllerClasses.keys():
for d in t.list(n):
try:
t.remove(d)
except ex:
# Log and swallow any exceptions in removal -- there's
# nothing more we can do.
log.exception(
"Device release failed: %s; %s; %s; %s" %
(self.info['name'], n, d, str(ex)))
t.commit()
while True:
t = xstransact("%s/device" % self.path)
for n in controllerClasses.keys():
for d in t.list(n):
try:
t.remove(d)
except ex:
# Log and swallow any exceptions in removal --
# there's nothing more we can do.
log.exception(
"Device release failed: %s; %s; %s; %s" %
(self.info['name'], n, d, str(ex)))
if t.commit():
break
def eventChannel(self, path=None):
"""Create an event channel to the domain.
@@ -1084,19 +1100,6 @@ class XendDomainInfo:
return name in self.info and self.info[name] is not None
#============================================================================
# Register image handlers.
from image import \
addImageHandlerClass, \
ImageHandler, \
LinuxImageHandler, \
VmxImageHandler
addImageHandlerClass(LinuxImageHandler)
addImageHandlerClass(VmxImageHandler)
#============================================================================
# Register device controllers and their device config types.
+52 -78
View File
@@ -33,6 +33,15 @@ xc = xen.lowlevel.xc.new()
MAX_GUEST_CMDLINE = 1024
def create(vm, imageConfig, deviceConfig):
"""Create an image handler for a vm.
@return ImageHandler instance
"""
return findImageHandlerClass(imageConfig)(vm, imageConfig, deviceConfig)
class ImageHandler:
"""Abstract base class for image handlers.
@@ -48,81 +57,39 @@ class ImageHandler:
The method destroy() is called when the domain is destroyed.
The default is to do nothing.
"""
#======================================================================
# Class vars and methods.
"""Table of image handler classes for virtual machine images.
Indexed by image type.
"""
imageHandlerClasses = {}
def addImageHandlerClass(cls, h):
"""Add a handler class for an image type
@param h: handler: ImageHandler subclass
"""
cls.imageHandlerClasses[h.ostype] = h
addImageHandlerClass = classmethod(addImageHandlerClass)
def findImageHandlerClass(cls, image):
"""Find the image handler class for an image config.
@param image config
@return ImageHandler subclass or None
"""
ty = sxp.name(image)
if ty is None:
raise VmError('missing image type')
imageClass = cls.imageHandlerClasses.get(ty)
if imageClass is None:
raise VmError('unknown image type: ' + ty)
return imageClass
findImageHandlerClass = classmethod(findImageHandlerClass)
def create(cls, vm, imageConfig, deviceConfig):
"""Create an image handler for a vm.
@return ImageHandler instance
"""
imageClass = cls.findImageHandlerClass(imageConfig)
return imageClass(vm, imageConfig, deviceConfig)
create = classmethod(create)
#======================================================================
# Instance vars and methods.
ostype = None
kernel = None
ramdisk = None
cmdline = None
flags = 0
def __init__(self, vm, imageConfig, deviceConfig):
self.vm = vm
self.kernel = None
self.ramdisk = None
self.cmdline = None
self.flags = 0
self.configure(imageConfig, deviceConfig)
def configure(self, imageConfig, _):
"""Config actions common to all unix-like domains."""
self.kernel = sxp.child_value(imageConfig, "kernel")
def get_cfg(name, default = None):
return sxp.child_value(imageConfig, name, default)
self.kernel = get_cfg("kernel")
self.cmdline = ""
ip = sxp.child_value(imageConfig, "ip", None)
ip = get_cfg("ip")
if ip:
self.cmdline += " ip=" + ip
root = sxp.child_value(imageConfig, "root")
root = get_cfg("root")
if root:
self.cmdline += " root=" + root
args = sxp.child_value(imageConfig, "args")
args = get_cfg("args")
if args:
self.cmdline += " " + args
self.ramdisk = sxp.child_value(imageConfig, "ramdisk", '')
self.ramdisk = get_cfg("ramdisk", '')
self.vm.storeVm(("image/ostype", self.ostype),
("image/kernel", self.kernel),
@@ -130,7 +97,7 @@ class ImageHandler:
("image/ramdisk", self.ramdisk))
def handleBootloading():
def handleBootloading(self):
self.unlink(self.kernel)
self.unlink(self.ramdisk)
@@ -194,7 +161,6 @@ class ImageHandler:
if d.has_key('console_mfn'):
self.vm.setConsoleRef(d.get('console_mfn'))
addImageHandlerClass = ImageHandler.addImageHandlerClass
class LinuxImageHandler(ImageHandler):
@@ -238,22 +204,19 @@ class VmxImageHandler(ImageHandler):
def configure(self, imageConfig, deviceConfig):
ImageHandler.configure(self, imageConfig, deviceConfig)
self.memmap = sxp.child_value(imageConfig, 'memmap')
self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig)
self.device_model = sxp.child_value(imageConfig, 'device_model')
if not self.device_model:
raise VmError("vmx: missing device model")
self.display = sxp.child_value(imageConfig, 'display')
self.vm.storeVm(("image/memmap", self.memmap),
("image/dmargs", " ".join(self.dmargs)),
self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
("image/device-model", self.device_model),
("image/display", self.display))
self.device_channel = None
self.pid = 0
self.memmap_value = []
self.dmargs += self.configVNC(imageConfig)
@@ -261,7 +224,6 @@ class VmxImageHandler(ImageHandler):
def createImage(self):
"""Create a VM for the VMX environment.
"""
self.parseMemmap()
self.createDomain()
def buildDomain(self):
@@ -278,9 +240,6 @@ class VmxImageHandler(ImageHandler):
log.debug("control_evtchn = %d", self.device_channel.port2)
log.debug("store_evtchn = %d", store_evtchn)
log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024)
log.debug("memmap = %s", self.memmap_value)
log.debug("cmdline = %s", self.cmdline)
log.debug("ramdisk = %s", self.ramdisk)
log.debug("flags = %d", self.flags)
log.debug("vcpus = %d", self.vm.getVCpuCount())
@@ -289,9 +248,6 @@ class VmxImageHandler(ImageHandler):
control_evtchn = self.device_channel.port2,
store_evtchn = store_evtchn,
memsize = self.vm.getMemoryTarget() / 1024,
memmap = self.memmap_value,
cmdline = self.cmdline,
ramdisk = self.ramdisk,
flags = self.flags,
vcpus = self.vm.getVCpuCount())
if isinstance(ret, dict):
@@ -299,18 +255,11 @@ class VmxImageHandler(ImageHandler):
return 0
return ret
def parseMemmap(self):
if self.memmap is None:
return
memmap = sxp.parse(open(self.memmap))[0]
from xen.util.memmap import memmap_parse
self.memmap_value = memmap_parse(memmap)
# Return a list of cmd line args to the device models based on the
# xm config file
def parseDeviceModelArgs(self, imageConfig, deviceConfig):
dmargs = [ 'cdrom', 'boot', 'fda', 'fdb',
'localtime', 'serial', 'stdvga', 'isa', 'vcpus' ]
'localtime', 'serial', 'stdvga', 'isa', 'vcpus' ]
ret = []
for a in dmargs:
v = sxp.child_value(imageConfig, a)
@@ -439,3 +388,28 @@ class VmxImageHandler(ImageHandler):
return 16 * 1024
else:
return (1 + ((mem_mb + 3) >> 2)) * 4
"""Table of image handler classes for virtual machine images. Indexed by
image type.
"""
imageHandlerClasses = {}
for h in LinuxImageHandler, VmxImageHandler:
imageHandlerClasses[h.ostype] = h
def findImageHandlerClass(image):
"""Find the image handler class for an image config.
@param image config
@return ImageHandler subclass or None
"""
ty = sxp.name(image)
if ty is None:
raise VmError('missing image type')
imageClass = imageHandlerClasses.get(ty)
if imageClass is None:
raise VmError('unknown image type: ' + ty)
return imageClass
+15 -14
View File
@@ -126,20 +126,21 @@ class DevController:
compulsory to use it; subclasses may prefer to allocate IDs based upon
the device configuration instead.
"""
path = self.frontendMiscPath()
t = xstransact(path)
try:
result = t.read("nextDeviceID")
if result:
result = int(result)
else:
result = 1
t.write("nextDeviceID", str(result + 1))
t.commit()
return result
except:
t.abort()
raise
while True:
path = self.frontendMiscPath()
t = xstransact(path)
try:
result = t.read("nextDeviceID")
if result:
result = int(result)
else:
result = 1
t.write("nextDeviceID", str(result + 1))
if t.commit():
return result
except:
t.abort()
raise
## private:
+2 -2
View File
@@ -280,8 +280,8 @@ class XenStore:
(', while writing %s : %s' % (str(path),
str(data))))
def begin(self, path):
self.getxs().transaction_start(path)
def begin(self):
self.getxs().transaction_start()
def commit(self, abandon=False):
self.getxs().transaction_end(abort=abandon)
+13 -57
View File
@@ -14,16 +14,8 @@ class xstransact:
def __init__(self, path):
self.in_transaction = False
self.path = path.rstrip("/")
while True:
try:
xshandle().transaction_start(path)
self.in_transaction = True
return
except RuntimeError, ex:
if ex.args[0] == errno.ENOENT and path != "/":
path = "/".join(path.split("/")[0:-1]) or "/"
else:
raise
xshandle().transaction_start()
self.in_transaction = True
def __del__(self):
if self.in_transaction:
@@ -175,14 +167,8 @@ class xstransact:
t = cls(path)
try:
v = t.read(*args)
t.commit()
return v
except RuntimeError, ex:
t.abort()
if ex.args[0] == errno.ETIMEDOUT:
pass
else:
raise
return v
except:
t.abort()
raise
@@ -194,14 +180,8 @@ class xstransact:
t = cls(path)
try:
t.write(*args, **opts)
t.commit()
return
except RuntimeError, ex:
t.abort()
if ex.args[0] == errno.ETIMEDOUT:
pass
else:
raise
if t.commit():
return
except:
t.abort()
raise
@@ -217,14 +197,8 @@ class xstransact:
t = cls(path)
try:
t.remove(*args)
t.commit()
return
except RuntimeError, ex:
t.abort()
if ex.args[0] == errno.ETIMEDOUT:
pass
else:
raise
if t.commit():
return
except:
t.abort()
raise
@@ -236,14 +210,8 @@ class xstransact:
t = cls(path)
try:
v = t.list(*args)
t.commit()
return v
except RuntimeError, ex:
t.abort()
if ex.args[0] == errno.ETIMEDOUT:
pass
else:
raise
if t.commit():
return v
except:
t.abort()
raise
@@ -255,14 +223,8 @@ class xstransact:
t = cls(path)
try:
v = t.gather(*args)
t.commit()
return v
except RuntimeError, ex:
t.abort()
if ex.args[0] == errno.ETIMEDOUT:
pass
else:
raise
if t.commit():
return v
except:
t.abort()
raise
@@ -274,14 +236,8 @@ class xstransact:
t = cls(path)
try:
v = t.store(*args)
t.commit()
return v
except RuntimeError, ex:
t.abort()
if ex.args[0] == errno.ETIMEDOUT:
pass
else:
raise
if t.commit():
return v
except:
t.abort()
raise
+21 -55
View File
@@ -1,5 +1,6 @@
# (C) Copyright IBM Corp. 2005
# Copyright (C) 2004 Mike Wray
# Copyright (c) 2005 XenSource Ltd
#
# Authors:
# Sean Dague <sean at dague dot net>
@@ -169,12 +170,6 @@ def handle_xend_error(cmd, dom, ex):
#
#########################################################################
def xm_create(args):
from xen.xm import create
# ugly hack because the opt parser apparently wants
# the subcommand name just to throw it away!
create.main(["bogus"] + args)
def xm_save(args):
arg_check(args,2,"save")
@@ -196,13 +191,6 @@ def xm_restore(args):
if id is not None:
server.xend_domain_unpause(domid)
def xm_migrate(args):
# TODO: arg_check
from xen.xm import migrate
# ugly hack because the opt parser apparently wants
# the subcommand name just to throw it away!
migrate.main(["bogus"] + args)
def xm_list(args):
use_long = 0
show_vcpus = 0
@@ -290,14 +278,6 @@ def xm_show_vcpus(domsinfo):
def xm_vcpu_list(args):
xm_list(["-v"] + args)
def xm_destroy(args):
arg_check(args,1,"destroy")
from xen.xm import destroy
# ugly hack because the opt parser apparently wants
# the subcommand name just to throw it away!
destroy.main(["bogus"] + args)
def xm_reboot(args):
arg_check(args,1,"reboot")
from xen.xm import shutdown
@@ -305,20 +285,6 @@ def xm_reboot(args):
# the subcommand name just to throw it away!
shutdown.main(["bogus", "-R"] + args)
def xm_shutdown(args):
arg_check(args,1,"shutdown")
from xen.xm import shutdown
# ugly hack because the opt parser apparently wants
# the subcommand name just to throw it away!
shutdown.main(["bogus"] + args)
def xm_sysrq(args):
from xen.xm import sysrq
# ugly hack because the opt parser apparently wants
# the subcommand name just to throw it away!
sysrq.main(["bogus"] + args)
def xm_pause(args):
arg_check(args, 1, "pause")
dom = args[0]
@@ -333,6 +299,11 @@ def xm_unpause(args):
from xen.xend.XendClient import server
server.xend_domain_unpause(dom)
def xm_subcommand(command, args):
cmd = __import__(command, globals(), locals(), 'xen.xm')
cmd.main(["bogus"] + args)
#############################################################
def cpu_make_map(cpulist):
@@ -506,14 +477,6 @@ def xm_network_list(args):
sxp.show(x)
print
def xm_network_attach(args):
print "Not implemented"
def xm_network_detach(args):
print "Not implemented"
def xm_block_list(args):
arg_check(args,1,"block-list")
dom = args[0]
@@ -609,11 +572,8 @@ commands = {
# domain commands
"domid": xm_domid,
"domname": xm_domname,
"create": xm_create,
"destroy": xm_destroy,
"restore": xm_restore,
"save": xm_save,
"shutdown": xm_shutdown,
"reboot": xm_reboot,
"list": xm_list,
# memory commands
@@ -625,10 +585,7 @@ commands = {
"vcpu-enable": xm_vcpu_enable,
"vcpu-disable": xm_vcpu_disable,
"vcpu-list": xm_vcpu_list,
# migration
"migrate": xm_migrate,
# special
"sysrq": xm_sysrq,
"pause": xm_pause,
"unpause": xm_unpause,
# host commands
@@ -647,14 +604,24 @@ commands = {
# network
"network-limit": xm_network_limit,
"network-list": xm_network_list,
"network-attach": xm_network_attach,
"network-detach": xm_network_detach,
# vnet
"vnet-list": xm_vnet_list,
"vnet-create": xm_vnet_create,
"vnet-delete": xm_vnet_delete,
}
## The commands supported by a separate argument parser in xend.xm.
subcommands = [
'create',
'destroy',
'migrate',
'sysrq',
'shutdown'
]
for c in subcommands:
commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
aliases = {
"balloon": "mem-set",
"vif-list": "network-list",
@@ -669,6 +636,7 @@ help = {
"--long": longhelp
}
def xm_lookup_cmd(cmd):
if commands.has_key(cmd):
return commands[cmd]
@@ -688,9 +656,7 @@ def deprecated(old,new):
err('Option %s is the new replacement, see "xm help %s" for more info' % (new, new))
def usage(cmd=None):
if cmd == "full":
print fullhelp
elif help.has_key(cmd):
if help.has_key(cmd):
print help[cmd]
else:
print shorthelp
@@ -701,7 +667,7 @@ def main(argv=sys.argv):
usage()
if re.compile('-*help').match(argv[1]):
if len(argv) > 2 and help.has_key(argv[2]):
if len(argv) > 2:
usage(argv[2])
else:
usage()
+12 -4
View File
@@ -28,11 +28,11 @@ CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm
CLIENTS += xenstore-write
CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
all: libxenstore.so xenstored $(CLIENTS)
all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump
testcode: xs_test xenstored_test xs_random xs_dom0_test
xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o
xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o tdb.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
$(CLIENTS): libxenstore.so
@@ -42,7 +42,10 @@ $(CLIENTS): xenstore-%: xenstore_%.o
$(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c
$(COMPILE.c) -DCLIENT_$(*F) -o $@ $<
xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o
xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
xs_test: xs_test.o xs_lib.o utils.o
@@ -50,6 +53,11 @@ xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o
xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o
xs_crashme: xs_crashme.o xs_lib.o talloc.o utils.o
speedtest: speedtest.o xs.o xs_lib.o utils.o talloc.o
check-speed: speedtest xenstored_test $(TESTDIR)
$(TESTENV) time ./speedtest 100
xs_test.o xs_stress.o xenstored_core_test.o xenstored_watch_test.o xenstored_transaction_test.o xenstored_domain_test.o xs_random.o xs_test_lib.o talloc_test.o fake_libxc.o xs_crashme.o: CFLAGS=$(BASECFLAGS) $(TESTFLAGS)
xenstored_%_test.o: xenstored_%.c
@@ -98,7 +106,7 @@ RANDSEED=$(shell date +%s)
randomcheck: xs_random xenstored_test $(TESTDIR)
$(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 $(RANDSEED) && echo
$(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo
$(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
# $(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
crashme: xs_crashme xenstored_test $(TESTDIR)
rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace
+130
View File
@@ -0,0 +1,130 @@
/*
Xen Store Daemon Speed test
Copyright (C) 2005 Rusty Russell IBM Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "utils.h"
#include "xs.h"
#include "list.h"
#include "talloc.h"
static void do_command(const char *cmd)
{
int ret;
ret = system(cmd);
if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
barf_perror("Failed '%s': %i", cmd, ret);
}
static int start_daemon(void)
{
int fds[2], pid;
do_command(talloc_asprintf(NULL, "rm -rf testsuite/tmp/*"));
/* Start daemon. */
pipe(fds);
if ((pid = fork())) {
/* Child writes PID when its ready: we wait for that. */
char buffer[20];
close(fds[1]);
if (read(fds[0], buffer, sizeof(buffer)) < 0)
barf("Failed to summon daemon");
close(fds[0]);
} else {
dup2(fds[1], STDOUT_FILENO);
close(fds[0]);
#if 0
execlp("valgrind", "valgrind", "-q", "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
"--no-fork", "--trace-file=/tmp/trace", NULL);
#else
execlp("./xenstored_test", "xenstored_test", "--output-pid", "--no-fork", NULL);
// execlp("strace", "strace", "-o", "/tmp/out", "./xenstored_test", "--output-pid", "--no-fork", NULL);
#endif
exit(1);
}
return pid;
}
static void kill_daemon(int pid)
{
int saved_errno = errno;
kill(pid, SIGTERM);
errno = saved_errno;
}
#define NUM_ENTRIES 50
/* We create the given number of trees, each with NUM_ENTRIES, using
* transactions. */
int main(int argc, char *argv[])
{
int i, j, pid, print;
struct xs_handle *h;
if (argc != 2)
barf("Usage: speedtest <numdomains>");
pid = start_daemon();
h = xs_daemon_open();
print = atoi(argv[1]) / 76;
if (!print)
print = 1;
for (i = 0; i < atoi(argv[1]); i ++) {
char name[64];
if (i % print == 0)
write(1, ".", 1);
if (!xs_transaction_start(h, "/")) {
kill_daemon(pid);
barf_perror("Starting transaction");
}
sprintf(name, "/%i", i);
if (!xs_mkdir(h, name)) {
kill_daemon(pid);
barf_perror("Making directory %s", name);
}
for (j = 0; j < NUM_ENTRIES; j++) {
sprintf(name, "/%i/%i", i, j);
if (!xs_write(h, name, name, strlen(name))) {
kill_daemon(pid);
barf_perror("Making directory %s", name);
}
}
if (!xs_transaction_end(h, false)) {
kill_daemon(pid);
barf_perror("Ending transaction");
}
}
write(1, "\n", 1);
kill_daemon(pid);
wait(NULL);
return 0;
}
+2151
View File
File diff suppressed because it is too large. Load diff
+157
View File
@@ -0,0 +1,157 @@
#ifndef __TDB_H__
#define __TDB_H__
/*
Unix SMB/CIFS implementation.
trivial database library
Copyright (C) Andrew Tridgell 1999-2004
** NOTE! The following LGPL license applies to the tdb
** library. This does NOT imply that all of Samba is released
** under the LGPL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef __cplusplus
extern "C" {
#endif
/* flags to tdb_store() */
#define TDB_REPLACE 1
#define TDB_INSERT 2
#define TDB_MODIFY 3
/* flags for tdb_open() */
#define TDB_DEFAULT 0 /* just a readability place holder */
#define TDB_CLEAR_IF_FIRST 1
#define TDB_INTERNAL 2 /* don't store on disk */
#define TDB_NOLOCK 4 /* don't do any locking */
#define TDB_NOMMAP 8 /* don't use mmap */
#define TDB_CONVERT 16 /* convert endian (internal use) */
#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */
#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)
/* error codes */
enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
TDB_ERR_NOEXIST};
#ifndef u32
#define u32 unsigned
#endif
typedef struct TDB_DATA {
char *dptr;
size_t dsize;
} TDB_DATA;
typedef u32 tdb_len;
typedef u32 tdb_off;
/* this is stored at the front of every database */
struct tdb_header {
char magic_food[32]; /* for /etc/magic */
u32 version; /* version of the code */
u32 hash_size; /* number of hash entries */
tdb_off rwlocks;
tdb_off reserved[31];
};
struct tdb_lock_type {
u32 count;
u32 ltype;
};
struct tdb_traverse_lock {
struct tdb_traverse_lock *next;
u32 off;
u32 hash;
};
#ifndef PRINTF_ATTRIBUTE
#define PRINTF_ATTRIBUTE(a,b)
#endif
/* this is the context structure that is returned from a db open */
typedef struct tdb_context {
char *name; /* the name of the database */
void *map_ptr; /* where it is currently mapped */
int fd; /* open file descriptor for the database */
tdb_len map_size; /* how much space has been mapped */
int read_only; /* opened read-only */
struct tdb_lock_type *locked; /* array of chain locks */
enum TDB_ERROR ecode; /* error code for last tdb error */
struct tdb_header header; /* a cached copy of the header */
u32 flags; /* the flags passed to tdb_open */
struct tdb_traverse_lock travlocks; /* current traversal locks */
struct tdb_context *next; /* all tdbs to avoid multiple opens */
dev_t device; /* uniquely identifies this tdb */
ino_t inode; /* uniquely identifies this tdb */
void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */
u32 (*hash_fn)(TDB_DATA *key);
int open_flags; /* flags used in the open - needed by reopen */
} TDB_CONTEXT;
typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...);
typedef u32 (*tdb_hash_func)(TDB_DATA *key);
TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode);
TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
tdb_log_func log_fn,
tdb_hash_func hash_fn);
int tdb_reopen(TDB_CONTEXT *tdb);
int tdb_reopen_all(void);
void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func);
enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb);
const char *tdb_errorstr(TDB_CONTEXT *tdb);
TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf);
int tdb_close(TDB_CONTEXT *tdb);
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *);
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_lockall(TDB_CONTEXT *tdb);
void tdb_unlockall(TDB_CONTEXT *tdb);
/* Low level locking functions: use with care */
int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key);
TDB_CONTEXT *tdb_copy(TDB_CONTEXT *tdb, const char *outfile);
/* Debug functions. Not used in production. */
void tdb_dump_all(TDB_CONTEXT *tdb);
int tdb_printfreelist(TDB_CONTEXT *tdb);
extern TDB_DATA tdb_null;
#ifdef __cplusplus
}
#endif
#endif /* tdb.h */
+3
View File
@@ -6,6 +6,8 @@ rm /dir/test
# Create file and remove it
write /test contents
rm /test
expect tool
dir /
# Create directory and remove it.
mkdir /dir
@@ -15,3 +17,4 @@ rm /dir
mkdir /dir
write /dir/test contents
rm /dir
+38 -16
View File
@@ -1,21 +1,43 @@
# Test transaction timeouts. Take a second each.
# Test transaction clashes.
mkdir /test
write /test/entry1 contents
# Transactions can take as long as the want...
start /test
sleep 1100
rm /test/entry1
commit
dir /test
# ... as long as noone is waiting.
1 start /test
notimeout
2 mkdir /test/dir
1 mkdir /test/dir
expect 1:dir
1 dir /test
expect 1: commit failed: Connection timed out
# Start transaction, do read-only op, transaction succeeds
1 start
1 write /test/entry1 contents2
expect contents
read /test/entry1
1 commit
expect contents2
read /test/entry1
# Start transaction, abort other transaction, transaction succeeds.
1 start
1 write /test/entry1 contents3
start
write /test/entry1 contents
abort
1 commit
expect contents3
read /test/entry1
# Start transaction, do write op, transaction fails
1 start
1 write /test/entry1 contents4
write /test/entry1 contents
expect 1: commit failed: Resource temporarily unavailable
1 commit
expect contents
read /test/entry1
# Start transaction, do other transaction, transaction fails
1 start
1 write /test/entry1 contents4
start
write /test/entry1 contents5
commit
expect 1: commit failed: Resource temporarily unavailable
1 commit
expect contents5
read /test/entry1
+9 -9
View File
@@ -3,7 +3,7 @@
mkdir /test
# Simple transaction: create a file inside transaction.
1 start /test
1 start
1 write /test/entry1 contents
2 dir /test
expect 1:entry1
@@ -15,7 +15,7 @@ expect 2:contents
rm /test/entry1
# Create a file and abort transaction.
1 start /test
1 start
1 write /test/entry1 contents
2 dir /test
expect 1:entry1
@@ -25,7 +25,7 @@ expect 1:entry1
write /test/entry1 contents
# Delete in transaction, commit
1 start /test
1 start
1 rm /test/entry1
expect 2:entry1
2 dir /test
@@ -35,7 +35,7 @@ expect 2:entry1
# Delete in transaction, abort.
write /test/entry1 contents
1 start /test
1 start
1 rm /test/entry1
expect 2:entry1
2 dir /test
@@ -47,7 +47,7 @@ expect 2:entry1
# Events inside transactions don't trigger watches until (successful) commit.
mkdir /test/dir
1 watch /test token
2 start /test
2 start
2 mkdir /test/dir/sub
expect 1: waitwatch failed: Connection timed out
1 waitwatch
@@ -55,7 +55,7 @@ expect 1: waitwatch failed: Connection timed out
1 close
1 watch /test token
2 start /test
2 start
2 mkdir /test/dir/sub
2 abort
expect 1: waitwatch failed: Connection timed out
@@ -63,7 +63,7 @@ expect 1: waitwatch failed: Connection timed out
1 close
1 watch /test token
2 start /test
2 start
2 mkdir /test/dir/sub
2 commit
expect 1:/test/dir/sub:token
@@ -73,7 +73,7 @@ expect 1:/test/dir/sub:token
# Rm inside transaction works like rm outside: children get notified.
1 watch /test/dir/sub token
2 start /test
2 start
2 rm /test/dir
2 commit
expect 1:/test/dir/sub:token
@@ -83,7 +83,7 @@ expect 1:/test/dir/sub:token
# Multiple events from single transaction don't trigger assert
1 watch /test token
2 start /test
2 start
2 write /test/1 contents
2 write /test/2 contents
2 commit
+8 -8
View File
@@ -13,23 +13,23 @@ expect 0 READ
getperm /test
watch /test token
unwatch /test token
start /
start
commit
start /
start
abort
# These don't work
expect write failed: Read-only file system
expect write failed: Permission denied
write /test2 contents
expect write failed: Read-only file system
expect write failed: Permission denied
write /test contents
expect setperm failed: Read-only file system
expect setperm failed: Permission denied
setperm /test 100 NONE
expect setperm failed: Read-only file system
expect setperm failed: Permission denied
setperm /test 100 NONE
expect shutdown failed: Read-only file system
expect shutdown failed: Permission denied
shutdown
expect introduce failed: Read-only file system
expect introduce failed: Permission denied
introduce 1 100 7 /home
# Check that watches work like normal.
@@ -33,14 +33,6 @@ unwatch /dir/file token
expect *No such file or directory
unwatch /dir/file token
expect *Permission denied
start /dir/file
expect *No such file or directory
abort
expect *Permission denied
start /dir/file
expect *No such file or directory
commit
expect *Permission denied
introduce 2 100 7 /dir/file
# Now it exists
@@ -73,12 +65,4 @@ unwatch /dir/file token
expect *No such file or directory
unwatch /dir/file token
expect *Permission denied
start /dir/file
expect *No such file or directory
abort
expect *Permission denied
start /dir/file
expect *No such file or directory
commit
expect *Permission denied
introduce 2 100 7 /dir/file
@@ -1,13 +1,14 @@
# Test case where blocked connection gets sent watch.
mkdir /test
watch /test token
1 start /test
# This will block on above
noackwrite /test/entry contents
1 write /test/entry2 contents
1 commit
readack
expect /test/entry2:token
waitwatch
ackwatch token
# FIXME: We no longer block connections
# mkdir /test
# watch /test token
# 1 start
# # This will block on above
# noackwrite /test/entry contents
# 1 write /test/entry2 contents
# 1 commit
# readack
# expect /test/entry2:token
# waitwatch
# ackwatch token
+7 -4
View File
@@ -14,6 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <xs.h>
#include <errno.h>
static void
usage(const char *progname)
@@ -82,8 +83,8 @@ main(int argc, char **argv)
}
#endif
/* XXX maybe find longest common prefix */
success = xs_transaction_start(xsh, "/");
again:
success = xs_transaction_start(xsh);
if (!success)
errx(1, "couldn't start transaction");
@@ -145,8 +146,10 @@ main(int argc, char **argv)
out:
success = xs_transaction_end(xsh, ret ? true : false);
if (!success)
if (!success) {
if (ret == 0 && errno == EAGAIN)
goto again;
errx(1, "couldn't end transaction");
}
return ret;
}
+1 -1
View File
@@ -75,7 +75,7 @@ static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
XSD_ERROR(ENOSYS),
XSD_ERROR(EROFS),
XSD_ERROR(EBUSY),
XSD_ERROR(ETIMEDOUT),
XSD_ERROR(EAGAIN),
XSD_ERROR(EISCONN),
};
struct xsd_sockmsg
File diff suppressed because it is too large. Load diff
+35 -31
View File
@@ -28,6 +28,7 @@
#include "xs_lib.h"
#include "xenstored.h"
#include "list.h"
#include "tdb.h"
struct buffered_data
{
@@ -49,8 +50,6 @@ typedef int connreadfn_t(struct connection *, void *, unsigned int);
enum state
{
/* Blocked by transaction. */
BLOCKED,
/* Doing action, not listening */
BUSY,
/* Completed */
@@ -70,9 +69,6 @@ struct connection
/* Blocked on transaction? Busy? */
enum state state;
/* Node we are waiting for (if state == BLOCKED) */
char *blocked_by;
/* Is this a read-only connection? */
bool can_write;
@@ -103,9 +99,27 @@ struct connection
};
extern struct list_head connections;
/* Return length of string (including nul) at this offset. */
unsigned int get_string(const struct buffered_data *data,
unsigned int offset);
struct node {
const char *name;
/* Database I came from */
TDB_CONTEXT *tdb;
/* Parent (optional) */
struct node *parent;
/* Permissions. */
unsigned int num_perms;
struct xs_permissions *perms;
/* Contents. */
unsigned int datalen;
void *data;
/* Children, each nul-terminated. */
unsigned int childlen;
char *children;
};
/* Break input into vectors, return the number, fill in up to num of them. */
unsigned int get_strings(struct buffered_data *data,
@@ -114,9 +128,6 @@ unsigned int get_strings(struct buffered_data *data,
/* Is child node a child or equal to parent node? */
bool is_child(const char *child, const char *parent);
/* Create a new buffer with lifetime of context. */
struct buffered_data *new_buffer(void *ctx);
void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
const void *data, unsigned int len);
@@ -129,15 +140,22 @@ void send_error(struct connection *conn, int error);
/* Canonicalize this path if possible. */
char *canonicalize(struct connection *conn, const char *node);
/* Check permissions on this node. */
bool check_node_perms(struct connection *conn, const char *node,
enum xs_perm_type perm);
/* Check if node is an event node. */
bool check_event_node(const char *node);
/* Path to this node outside transaction. */
char *node_dir_outside_transaction(const char *node);
/* Get this node, checking we have permissions. */
struct node *get_node(struct connection *conn,
const char *name,
enum xs_perm_type perm);
/* Get TDB context for this connection */
TDB_CONTEXT *tdb_context(struct connection *conn);
/* Destructor for tdbs: required for transaction code */
int destroy_tdb(void *_tdb);
/* Replace the tdb: required for transaction code */
bool replace_tdb(const char *newname, TDB_CONTEXT *newtdb);
/* Fail due to excessive corruption, capitalist pigdogs! */
void __attribute__((noreturn)) corrupt(struct connection *conn,
@@ -145,23 +163,9 @@ void __attribute__((noreturn)) corrupt(struct connection *conn,
struct connection *new_connection(connwritefn_t *write, connreadfn_t *read);
void handle_input(struct connection *conn);
void handle_output(struct connection *conn);
/* Is this a valid node name? */
bool is_valid_nodename(const char *node);
/* Return a pointer to an open dir, self-closig and attached to pathname. */
DIR **talloc_opendir(const char *pathname);
/* Return a pointer to an fd, self-closing and attached to this pathname. */
int *talloc_open(const char *pathname, int flags, int mode);
/* Convenient talloc-style destructor for paths. */
int destroy_path(void *path);
/* Read entire contents of a talloced fd. */
void *read_all(int *fd, unsigned int *size);
/* Tracing infrastructure. */
void trace_create(const void *data, const char *type);
+2 -7
View File
@@ -309,16 +309,11 @@ void do_introduce(struct connection *conn, struct buffered_data *in)
return;
}
if (conn->id != 0) {
if (conn->id != 0 || !conn->can_write) {
send_error(conn, EACCES);
return;
}
if (!conn->can_write) {
send_error(conn, EROFS);
return;
}
/* Sanity check args. */
if ((atoi(vec[2]) <= 0) || !is_valid_nodename(vec[3])) {
send_error(conn, EINVAL);
@@ -386,7 +381,7 @@ void do_release(struct connection *conn, const char *domid_str)
talloc_free(domain->conn);
fire_watches(NULL, "@releaseDomain", false);
fire_watches(conn, "@releaseDomain", false);
send_ack(conn, XS_RELEASE);
}
+45 -205
View File
@@ -26,6 +26,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include "talloc.h"
#include "list.h"
#include "xenstored_transaction.h"
@@ -51,74 +52,26 @@ struct transaction
/* Global list of transactions. */
struct list_head list;
/* Generation when transaction started. */
unsigned int generation;
/* My owner (conn->transaction == me). */
struct connection *conn;
/* Subtree this transaction covers */
char *node;
/* Base for this transaction. */
char *divert;
/* TDB to work on, and filename */
TDB_CONTEXT *tdb;
char *tdb_name;
/* List of changed nodes. */
struct list_head changes;
/* Someone's waiting: time limit. */
struct timeval timeout;
/* We've timed out. */
bool destined_to_fail;
};
static LIST_HEAD(transactions);
static unsigned int generation;
bool within_transaction(struct transaction *trans, const char *node)
/* Return tdb context to use for this connection. */
TDB_CONTEXT *tdb_transaction_context(struct transaction *trans)
{
if (!trans)
return true;
return is_child(node, trans->node);
}
/* You are on notice: this transaction is blocking someone. */
static void start_transaction_timeout(struct transaction *trans)
{
if (timerisset(&trans->timeout))
return;
/* One second timeout. */
gettimeofday(&trans->timeout, NULL);
trans->timeout.tv_sec += 1;
}
struct transaction *transaction_covering_node(const char *node)
{
struct transaction *i;
list_for_each_entry(i, &transactions, list) {
if (i->destined_to_fail)
continue;
if (is_child(i->node, node) || is_child(node, i->node))
return i;
}
return NULL;
}
bool transaction_block(struct connection *conn, const char *node)
{
struct transaction *trans;
/* Transactions don't overlap, so we can't be blocked by
* others if we're in one. */
if (conn->transaction)
return false;
trans = transaction_covering_node(node);
if (trans) {
start_transaction_timeout(trans);
conn->state = BLOCKED;
conn->blocked_by = talloc_strdup(conn, node);
return true;
}
return false;
return trans->tdb;
}
/* Callers get a change node (which can fail) and only commit after they've
@@ -127,8 +80,11 @@ void add_change_node(struct transaction *trans, const char *node, bool recurse)
{
struct changed_node *i;
if (!trans)
if (!trans) {
/* They're changing the global database. */
generation++;
return;
}
list_for_each_entry(i, &trans->changes, list)
if (streq(i->node, node))
@@ -140,167 +96,47 @@ void add_change_node(struct transaction *trans, const char *node, bool recurse)
list_add_tail(&i->list, &trans->changes);
}
char *node_dir_inside_transaction(struct transaction *trans, const char *node)
{
return talloc_asprintf(node, "%s/%s", trans->divert,
node + strlen(trans->node));
}
void shortest_transaction_timeout(struct timeval *tv)
{
struct transaction *i;
list_for_each_entry(i, &transactions, list) {
if (!timerisset(&i->timeout))
continue;
if (!timerisset(tv) || timercmp(&i->timeout, tv, <))
*tv = i->timeout;
}
}
void check_transaction_timeout(void)
{
struct transaction *i;
struct timeval now;
gettimeofday(&now, NULL);
list_for_each_entry(i, &transactions, list) {
if (!timerisset(&i->timeout))
continue;
if (timercmp(&i->timeout, &now, <))
i->destined_to_fail = true;
}
}
static int destroy_transaction(void *_transaction)
{
struct transaction *trans = _transaction;
list_del(&trans->list);
trace_destroy(trans, "transaction");
return destroy_path(trans->divert);
if (trans->tdb)
tdb_close(trans->tdb);
unlink(trans->tdb_name);
return 0;
}
static bool copy_file(const char *src, const char *dst)
void do_transaction_start(struct connection *conn, struct buffered_data *in)
{
int *infd, *outfd;
void *data;
unsigned int size;
infd = talloc_open(src, O_RDONLY, 0);
if (!infd)
return false;
outfd = talloc_open(dst, O_WRONLY|O_CREAT|O_EXCL, 0640);
if (!outfd)
return false;
data = read_all(infd, &size);
if (!data)
return false;
return xs_write_all(*outfd, data, size);
}
static bool copy_dir(const char *src, const char *dst)
{
DIR **dir;
struct dirent *dirent;
if (mkdir(dst, 0750) != 0)
return false;
dir = talloc_opendir(src);
if (!dir)
return false;
while ((dirent = readdir(*dir)) != NULL) {
struct stat st;
char *newsrc, *newdst;
if (streq(dirent->d_name, ".") || streq(dirent->d_name, ".."))
continue;
newsrc = talloc_asprintf(src, "%s/%s", src, dirent->d_name);
newdst = talloc_asprintf(src, "%s/%s", dst, dirent->d_name);
if (stat(newsrc, &st) != 0)
return false;
if (S_ISDIR(st.st_mode)) {
if (!copy_dir(newsrc, newdst))
return false;
} else {
if (!copy_file(newsrc, newdst))
return false;
}
/* Free now so we don't run out of file descriptors */
talloc_free(newsrc);
talloc_free(newdst);
}
return true;
}
void do_transaction_start(struct connection *conn, const char *node)
{
struct transaction *transaction;
char *dir;
struct transaction *trans;
if (conn->transaction) {
send_error(conn, EBUSY);
return;
}
node = canonicalize(conn, node);
if (!check_node_perms(conn, node, XS_PERM_READ)) {
/* Attach transaction to input for autofree until it's complete */
trans = talloc(in, struct transaction);
INIT_LIST_HEAD(&trans->changes);
trans->conn = conn;
trans->generation = generation;
trans->tdb_name = talloc_asprintf(trans, "%s.%p",
xs_daemon_tdb(), trans);
trans->tdb = tdb_copy(tdb_context(conn), trans->tdb_name);
if (!trans->tdb) {
send_error(conn, errno);
return;
}
/* Make it close if we go away. */
talloc_steal(trans, trans->tdb);
if (transaction_block(conn, node))
return;
dir = node_dir_outside_transaction(node);
/* Attach transaction to node for autofree until it's complete */
transaction = talloc(node, struct transaction);
transaction->node = talloc_strdup(transaction, node);
transaction->divert = talloc_asprintf(transaction, "%s/%p",
xs_daemon_transactions(),
transaction);
INIT_LIST_HEAD(&transaction->changes);
transaction->conn = conn;
timerclear(&transaction->timeout);
transaction->destined_to_fail = false;
list_add_tail(&transaction->list, &transactions);
talloc_set_destructor(transaction, destroy_transaction);
trace_create(transaction, "transaction");
if (!copy_dir(dir, transaction->divert)) {
send_error(conn, errno);
return;
}
talloc_steal(conn, transaction);
conn->transaction = transaction;
send_ack(transaction->conn, XS_TRANSACTION_START);
}
static bool commit_transaction(struct transaction *trans)
{
char *tmp, *dir;
/* Move: orig -> .old, repl -> orig. Cleanup deletes .old. */
dir = node_dir_outside_transaction(trans->node);
tmp = talloc_asprintf(trans, "%s.old", dir);
if (rename(dir, tmp) != 0)
return false;
if (rename(trans->divert, dir) != 0)
corrupt(trans->conn, "Failed rename %s to %s",
trans->divert, dir);
trans->divert = tmp;
return true;
/* Now we own it. */
conn->transaction = talloc_steal(conn, trans);
list_add_tail(&trans->list, &transactions);
talloc_set_destructor(trans, destroy_transaction);
send_ack(conn, XS_TRANSACTION_START);
}
void do_transaction_end(struct connection *conn, const char *arg)
@@ -318,25 +154,29 @@ void do_transaction_end(struct connection *conn, const char *arg)
return;
}
/* Set to NULL so fire_watches sends events. */
/* Set to NULL so fire_watches sends events, tdb_context works. */
trans = conn->transaction;
conn->transaction = NULL;
/* Attach transaction to arg for auto-cleanup */
talloc_steal(arg, trans);
if (streq(arg, "T")) {
if (trans->destined_to_fail) {
send_error(conn, ETIMEDOUT);
/* FIXME: Merge, rather failing on any change. */
if (trans->generation != generation) {
send_error(conn, EAGAIN);
return;
}
if (!commit_transaction(trans)) {
if (!replace_tdb(trans->tdb_name, trans->tdb)) {
send_error(conn, errno);
return;
}
/* Don't close this: we won! */
trans->tdb = NULL;
/* Fire off the watches for everything that changed. */
list_for_each_entry(i, &trans->changes, list)
fire_watches(conn, i->node, i->recurse);
generation++;
}
send_ack(conn, XS_TRANSACTION_END);
}
+4 -19
View File
@@ -22,29 +22,14 @@
struct transaction;
void do_transaction_start(struct connection *conn, const char *node);
void do_transaction_start(struct connection *conn, struct buffered_data *node);
void do_transaction_end(struct connection *conn, const char *arg);
/* Is node covered by this transaction? */
bool within_transaction(struct transaction *trans, const char *node);
/* If a write op on this node blocked by another connections' transaction,
* mark conn, setup transaction timeout and return true.
*/
bool transaction_block(struct connection *conn, const char *node);
/* Return transaction which covers this node. */
struct transaction *transaction_covering_node(const char *node);
/* Return directory of node within transaction t. */
char *node_dir_inside_transaction(struct transaction *t, const char *node);
bool transaction_block(struct connection *conn);
/* This node was changed: can fail and longjmp. */
void add_change_node(struct transaction *trans, const char *node, bool recurse);
/* Get shortest timeout: leave tv unset if none. */
void shortest_transaction_timeout(struct timeval *tv);
/* Have any transactions timed out yet? */
void check_transaction_timeout(void);
/* Return tdb context to use for this connection. */
TDB_CONTEXT *tdb_transaction_context(struct transaction *trans);
#endif /* _XENSTORED_TRANSACTION_H */
+19 -60
View File
@@ -96,36 +96,38 @@ static int destroy_watch_event(void *_event)
}
static void add_event(struct connection *conn,
struct watch *watch, const char *node)
struct watch *watch,
const char *name)
{
struct watch_event *event;
/* Check read permission: no permission, no watch event.
* If it doesn't exist, we need permission to read parent.
*/
if (!check_node_perms(conn, node, XS_PERM_READ|XS_PERM_ENOENT_OK) &&
!check_event_node(node)) {
return;
if (!check_event_node(name)) {
/* Can this conn load node, or see that it doesn't exist? */
struct node *node;
node = get_node(conn, name, XS_PERM_READ);
if (!node && errno != ENOENT)
return;
}
if (watch->relative_path) {
node += strlen(watch->relative_path);
if (*node == '/') /* Could be "" */
node++;
name += strlen(watch->relative_path);
if (*name == '/') /* Could be "" */
name++;
}
event = talloc(watch, struct watch_event);
event->len = strlen(node) + 1 + strlen(watch->token) + 1;
event->len = strlen(name) + 1 + strlen(watch->token) + 1;
event->data = talloc_array(event, char, event->len);
strcpy(event->data, node);
strcpy(event->data + strlen(node) + 1, watch->token);
strcpy(event->data, name);
strcpy(event->data + strlen(name) + 1, watch->token);
talloc_set_destructor(event, destroy_watch_event);
list_add_tail(&event->list, &watch->events);
trace_create(event, "watch_event");
}
/* FIXME: we fail to fire on out of memory. Should drop connections. */
void fire_watches(struct connection *conn, const char *node, bool recurse)
void fire_watches(struct connection *conn, const char *name, bool recurse)
{
struct connection *i;
struct watch *watch;
@@ -137,9 +139,9 @@ void fire_watches(struct connection *conn, const char *node, bool recurse)
/* Create an event for each watch. */
list_for_each_entry(i, &connections, list) {
list_for_each_entry(watch, &i->watches, list) {
if (is_child(node, watch->node))
add_event(i, watch, node);
else if (recurse && is_child(watch->node, node))
if (is_child(name, watch->node))
add_event(i, watch, name);
else if (recurse && is_child(watch->node, name))
add_event(i, watch, watch->node);
else
continue;
@@ -156,49 +158,6 @@ static int destroy_watch(void *_watch)
return 0;
}
void shortest_watch_ack_timeout(struct timeval *tv)
{
(void)tv;
#if 0 /* FIXME */
struct watch *watch;
list_for_each_entry(watch, &watches, list) {
struct watch_event *i;
list_for_each_entry(i, &watch->events, list) {
if (!timerisset(&i->timeout))
continue;
if (!timerisset(tv) || timercmp(&i->timeout, tv, <))
*tv = i->timeout;
}
}
#endif
}
void check_watch_ack_timeout(void)
{
#if 0
struct watch *watch;
struct timeval now;
gettimeofday(&now, NULL);
list_for_each_entry(watch, &watches, list) {
struct watch_event *i, *tmp;
list_for_each_entry_safe(i, tmp, &watch->events, list) {
if (!timerisset(&i->timeout))
continue;
if (timercmp(&i->timeout, &now, <)) {
xprintf("Warning: timeout on watch event %s"
" token %s\n",
i->node, watch->token);
trace_watch_timeout(watch->conn, i->node,
watch->token);
timerclear(&i->timeout);
}
}
}
#endif
}
void do_watch(struct connection *conn, struct buffered_data *in)
{
struct watch *watch;
+2 -8
View File
@@ -32,15 +32,9 @@ bool is_watch_event(struct connection *conn, struct buffered_data *out);
/* Look through our watches: if any of them have an event, queue it. */
void queue_next_event(struct connection *conn);
/* Fire all watches: recurse means all the children are effected (ie. rm).
/* Fire all watches: recurse means all the children are affected (ie. rm).
*/
void fire_watches(struct connection *conn, const char *node, bool recurse);
/* Find shortest timeout: if any, reduce tv (may already be set). */
void shortest_watch_ack_timeout(struct timeval *tv);
/* Check for watches which may have timed out. */
void check_watch_ack_timeout(void);
void fire_watches(struct connection *conn, const char *name, bool recurse);
void dump_watches(struct connection *conn);
+2 -3
View File
@@ -497,13 +497,12 @@ bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
/* Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
* Transaction only applies to the given subtree.
* You can only have one transaction at any time.
* Returns false on failure.
*/
bool xs_transaction_start(struct xs_handle *h, const char *subtree)
bool xs_transaction_start(struct xs_handle *h)
{
return xs_bool(xs_single(h, XS_TRANSACTION_START, subtree, NULL));
return xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
}
/* End a transaction.
+3 -4
View File
@@ -109,16 +109,15 @@ bool xs_unwatch(struct xs_handle *h, const char *path, const char *token);
/* Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
* Transaction only applies to the given subtree.
* You can only have one transaction at any time.
* Returns false on failure.
*/
bool xs_transaction_start(struct xs_handle *h, const char *subtree);
bool xs_transaction_start(struct xs_handle *h);
/* End a transaction.
* If abandon is true, transaction is discarded instead of committed.
* Returns false on failure, which indicates an error: transactions will
* not fail spuriously.
* Returns false on failure: if errno == EAGAIN, you have to restart
* transaction.
*/
bool xs_transaction_end(struct xs_handle *h, bool abort);
+7 -18
View File
@@ -50,6 +50,13 @@ static const char *xs_daemon_path(void)
return buf;
}
const char *xs_daemon_tdb(void)
{
static char buf[PATH_MAX];
sprintf(buf, "%s/tdb", xs_daemon_rootdir());
return buf;
}
const char *xs_daemon_socket(void)
{
return xs_daemon_path();
@@ -66,24 +73,6 @@ const char *xs_daemon_socket_ro(void)
return buf;
}
const char *xs_daemon_store(void)
{
static char buf[PATH_MAX];
if (snprintf(buf, PATH_MAX, "%s/store",
xs_daemon_rootdir()) >= PATH_MAX)
return NULL;
return buf;
}
const char *xs_daemon_transactions(void)
{
static char buf[PATH_MAX];
if (snprintf(buf, PATH_MAX, "%s/transactions",
xs_daemon_rootdir()) >= PATH_MAX)
return NULL;
return buf;
}
const char *xs_domain_dev(void)
{
char *s = getenv("XENSTORED_PATH");
+2 -3
View File
@@ -36,7 +36,7 @@ enum xs_perm_type {
struct xs_permissions
{
domid_t id;
unsigned int id;
enum xs_perm_type perms;
};
@@ -46,9 +46,8 @@ struct xs_permissions
/* Path for various daemon things: env vars can override. */
const char *xs_daemon_socket(void);
const char *xs_daemon_socket_ro(void);
const char *xs_daemon_store(void);
const char *xs_daemon_transactions(void);
const char *xs_domain_dev(void);
const char *xs_daemon_tdb(void);
/* Simple write function: loops for you. */
bool xs_write_all(int fd, const void *data, unsigned int len);
+33 -85
View File
@@ -41,7 +41,7 @@ struct ops
struct xs_permissions *perms,
unsigned int num);
bool (*transaction_start)(void *h, const char *subtree);
bool (*transaction_start)(void *h);
bool (*transaction_end)(void *h, bool abort);
/* Create and destroy a new handle. */
@@ -53,7 +53,6 @@ struct file_ops_info
{
const char *base;
char *transact_base;
char *transact;
};
static void convert_to_dir(const char *dirname)
@@ -96,31 +95,6 @@ static char *path_to_name(struct file_ops_info *info, const char *path)
return filename;
}
/* Is child a subnode of parent, or equal? */
static bool is_child(const char *child, const char *parent)
{
unsigned int len = strlen(parent);
/* / should really be "" for this algorithm to work, but that's a
* usability nightmare. */
if (streq(parent, "/"))
return true;
if (strncmp(child, parent, len) != 0)
return false;
return child[len] == '/' || child[len] == '\0';
}
static bool write_ok(struct file_ops_info *info, const char *path)
{
if (info->transact && !is_child(path, info->transact)) {
errno = EROFS;
return false;
}
return true;
}
static char **file_directory(struct file_ops_info *info,
const char *path, unsigned int *num)
{
@@ -184,8 +158,10 @@ static void *file_read(struct file_ops_info *info,
ret = grab_file(filename, &size);
/* Directory exists, .DATA doesn't. */
if (!ret && errno == ENOENT && strends(filename, ".DATA"))
errno = EISDIR;
if (!ret && errno == ENOENT && strends(filename, ".DATA")) {
ret = strdup("");
size = 0;
}
*len = size;
return ret;
}
@@ -270,9 +246,6 @@ static bool file_set_perms(struct file_ops_info *info,
return false;
}
if (!write_ok(info, path))
return false;
/* Check non-perm file exists/ */
if (lstat(filename, &st) != 0)
return false;
@@ -338,9 +311,6 @@ static bool file_write(struct file_ops_info *info,
char *filename = filename_to_data(path_to_name(info, path));
int fd;
if (!write_ok(info, path))
return false;
make_dirs(parent_filename(filename));
fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0600);
if (fd < 0)
@@ -358,9 +328,6 @@ static bool file_mkdir(struct file_ops_info *info, const char *path)
{
char *dirname = path_to_name(info, path);
if (!write_ok(info, path))
return false;
make_dirs(parent_filename(dirname));
if (mkdir(dirname, 0700) != 0)
return (errno == EEXIST);
@@ -374,20 +341,12 @@ static bool file_rm(struct file_ops_info *info, const char *path)
char *filename = path_to_name(info, path);
struct stat st;
if (info->transact && streq(info->transact, path)) {
errno = EINVAL;
return false;
}
if (lstat(filename, &st) != 0) {
if (lstat(parent_filename(filename), &st) != 0)
return false;
return true;
}
if (!write_ok(info, path))
return false;
if (streq(path, "/")) {
errno = EINVAL;
return false;
@@ -398,28 +357,20 @@ static bool file_rm(struct file_ops_info *info, const char *path)
return true;
}
static bool file_transaction_start(struct file_ops_info *info,
const char *subtree)
static bool file_transaction_start(struct file_ops_info *info)
{
char *cmd;
char *filename = path_to_name(info, subtree);
struct stat st;
if (info->transact) {
if (info->transact_base) {
errno = EBUSY;
return false;
}
if (lstat(filename, &st) != 0)
return false;
cmd = talloc_asprintf(NULL, "cp -r %s %s.transact",
info->base, info->base);
info->transact_base = talloc_asprintf(NULL, "%s.transact", info->base);
cmd = talloc_asprintf(NULL, "cp -r %s %s",
info->base, info->transact_base);
do_command(cmd);
talloc_free(cmd);
info->transact_base = talloc_asprintf(NULL, "%s.transact", info->base);
info->transact = talloc_strdup(NULL, subtree);
return true;
}
@@ -427,7 +378,7 @@ static bool file_transaction_end(struct file_ops_info *info, bool abort)
{
char *old, *cmd;
if (!info->transact) {
if (!info->transact_base) {
errno = ENOENT;
return false;
}
@@ -448,9 +399,7 @@ static bool file_transaction_end(struct file_ops_info *info, bool abort)
success:
talloc_free(cmd);
talloc_free(info->transact);
talloc_free(info->transact_base);
info->transact = NULL;
info->transact_base = NULL;
return true;
}
@@ -461,7 +410,6 @@ static struct file_ops_info *file_handle(const char *dir)
info->base = dir;
info->transact_base = NULL;
info->transact = NULL;
return info;
}
@@ -898,11 +846,10 @@ static char *do_next_op(struct ops *ops, void *h, int state, bool verbose)
case 7: {
if (verbose)
printf("START %s\n", name);
ret = bool_to_errstring(ops->transaction_start(h, name));
ret = bool_to_errstring(ops->transaction_start(h));
if (streq(ret, "OK")) {
talloc_free(ret);
ret = talloc_asprintf(NULL, "OK:START-TRANSACT:%s",
name);
ret = talloc_asprintf(NULL, "OK:START-TRANSACT");
}
break;
@@ -978,6 +925,8 @@ static void setup_file_ops(const char *dir)
barf_perror("Creating directory %s/tool", dir);
if (!file_set_perms(h, talloc_strdup(h, "/"), &perm, 1))
barf_perror("Setting root perms in %s", dir);
if (!file_set_perms(h, talloc_strdup(h, "/tool"), &perm, 1))
barf_perror("Setting root perms in %s/tool", dir);
file_close(h);
}
@@ -1071,7 +1020,7 @@ static unsigned int try_simple(const bool *trymap,
goto out;
if (!data->fast) {
if (strstarts(ret, "OK:START-TRANSACT:")) {
if (streq(ret, "OK:START-TRANSACT")) {
void *pre = data->ops->handle(data->dir);
snapshot = dump(data->ops, pre);
@@ -1303,7 +1252,7 @@ static unsigned int try_diff(const bool *trymap,
void *_data)
{
void *fileh, *xsh;
char *transact = NULL;
bool transact = false;
struct ops *fail;
struct diff_data *data = _data;
unsigned int i, print;
@@ -1348,13 +1297,9 @@ static unsigned int try_diff(const bool *trymap,
goto out;
if (strstarts(file, "OK:START-TRANSACT:"))
transact = talloc_strdup(NULL,
file +
strlen("OK:START-TRANSACT:"));
else if (streq(file, "OK:STOP-TRANSACT")) {
talloc_free(transact);
transact = NULL;
}
transact = true;
else if (streq(file, "OK:STOP-TRANSACT"))
transact = false;
talloc_free(file);
talloc_free(xs);
@@ -1379,7 +1324,7 @@ static unsigned int try_diff(const bool *trymap,
fail = NULL;
if (!ops_equal(&xs_ops, xsh_pre, &file_ops, fileh_pre,
transact, &fail)) {
"/", &fail)) {
if (fail)
barf("%s failed during transact\n",
fail->name);
@@ -1456,9 +1401,6 @@ static unsigned int try_fail(const bool *trymap,
fileh = file_handle(data->dir);
xsh = xs_handle(data->dir);
sprintf(seed, "%i", data->seed);
free(xs_debug_command(xsh, "failtest", seed, strlen(seed)+1));
print = number / 76;
if (!print)
print = 1;
@@ -1491,8 +1433,12 @@ static unsigned int try_fail(const bool *trymap,
if (trymap && !trymap[i])
continue;
/* Turn on failure. */
sprintf(seed, "%i", data->seed + i);
free(xs_debug_command(xsh, "failtest",seed,strlen(seed)+1));
if (verbose)
printf("(%i) ", i);
printf("(%i) seed %s ", i, seed);
ret = do_next_op(&xs_ops, xsh, i + data->seed, verbose);
if (streq(ret, "FAILED:Connection reset by peer")
|| streq(ret, "FAILED:Bad file descriptor")
@@ -1549,8 +1495,6 @@ static unsigned int try_fail(const bool *trymap,
fail = NULL;
if (!ops_equal(&xs_ops, tmpxsh, &file_ops, tmpfileh, "/",
&fail)) {
xs_close(tmpxsh);
file_close(tmpfileh);
if (fail) {
if (verbose)
printf("%s failed\n", fail->name);
@@ -1561,10 +1505,16 @@ static unsigned int try_fail(const bool *trymap,
failed = 0;
if (verbose)
printf("(Looks like it succeeded)\n");
xs_close(tmpxsh);
file_close(tmpfileh);
goto try_applying;
}
if (verbose)
printf("Two backends not equal\n");
printf("Trees differ:\nXS:%s\nFILE:%s\n",
dump(&xs_ops, tmpxsh),
dump(&file_ops, tmpfileh));
xs_close(tmpxsh);
file_close(tmpfileh);
goto out;
}
@@ -1572,8 +1522,6 @@ static unsigned int try_fail(const bool *trymap,
if (!xsh)
file_transaction_end(fileh, true);
/* Turn failures back on. */
free(xs_debug_command(tmpxsh, "failtest", NULL, 0));
xs_close(tmpxsh);
file_close(tmpfileh);
}
+23 -23
View File
@@ -8,6 +8,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define NUM_HANDLES 2
#define DIR_FANOUT 3
@@ -36,24 +37,18 @@ static void work(unsigned int cycles, unsigned int childnum)
srandom(childnum);
for (i = 0; i < cycles; i++) {
unsigned int lockdepth, j, len;
char file[100] = "", lockdir[100];
unsigned int j, len;
char file[100] = "";
char *contents, tmp[100];
struct xs_handle *h = handles[random() % NUM_HANDLES];
lockdepth = random() % DIR_DEPTH;
for (j = 0; j < DIR_DEPTH; j++) {
if (j == lockdepth)
strcpy(lockdir, file);
for (j = 0; j < DIR_DEPTH; j++)
sprintf(file + strlen(file), "/%li",
random()%DIR_FANOUT);
}
if (streq(lockdir, ""))
strcpy(lockdir, "/");
if (!xs_transaction_start(h, lockdir))
barf_perror("%i: starting transaction %i on %s",
childnum, i, lockdir);
if (!xs_transaction_start(h))
barf_perror("%i: starting transaction %i",
childnum, i);
sprintf(file + strlen(file), "/count");
contents = xs_read(h, file, &len);
@@ -68,18 +63,23 @@ static void work(unsigned int cycles, unsigned int childnum)
/* Abandon 1 in 10 */
if (random() % 10 == 0) {
if (!xs_transaction_end(h, true))
barf_perror("%i: can't abort transact %s",
childnum, lockdir);
barf_perror("%i: can't abort transact",
childnum);
i--;
} else {
if (!xs_transaction_end(h, false))
barf_perror("%i: can't commit transact %s",
childnum, lockdir);
/* Offset when we print . so kids don't all
* print at once. */
if ((i + print/(childnum+1)) % print == 0)
write(STDOUT_FILENO, &id, 1);
if (!xs_transaction_end(h, false)) {
if (errno == EAGAIN) {
write(STDOUT_FILENO, "!", 1);
i--;
} else
barf_perror("%i: can't commit trans",
childnum);
} else {
/* Offset when we print . so kids don't all
* print at once. */
if ((i + print/(childnum+1)) % print == 0)
write(STDOUT_FILENO, &id, 1);
}
}
}
}
@@ -201,7 +201,7 @@ int main(int argc, char *argv[])
printf("\nCounting results...\n");
i = tally_counts();
if (i != (unsigned)atoi(argv[1]))
barf("Total counts %i not %s", i, atoi(argv[1]));
barf("Total counts %i not %s", i, argv[1]);
printf("Success!\n");
exit(0);
}
+82
View File
@@ -0,0 +1,82 @@
/* Simple program to dump out all records of TDB */
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
#include "xs_lib.h"
#include "tdb.h"
#include "talloc.h"
#include "utils.h"
struct record_hdr {
u32 num_perms;
u32 datalen;
u32 childlen;
struct xs_permissions perms[0];
};
static u32 total_size(struct record_hdr *hdr)
{
return sizeof(*hdr) + hdr->num_perms * sizeof(struct xs_permissions)
+ hdr->datalen + hdr->childlen;
}
static char perm_to_char(enum xs_perm_type perm)
{
return perm == XS_PERM_READ ? 'r' :
perm == XS_PERM_WRITE ? 'w' :
perm == XS_PERM_NONE ? '-' :
perm == (XS_PERM_READ|XS_PERM_WRITE) ? 'b' :
'?';
}
int main(int argc, char *argv[])
{
TDB_DATA key;
TDB_CONTEXT *tdb;
if (argc != 2)
barf("Usage: xs_tdb_dump <tdbfile>");
tdb = tdb_open(talloc_strdup(NULL, argv[1]), 0, 0, O_RDONLY, 0);
if (!tdb)
barf_perror("Could not open %s", argv[1]);
key = tdb_firstkey(tdb);
while (key.dptr) {
TDB_DATA data;
struct record_hdr *hdr;
data = tdb_fetch(tdb, key);
hdr = (void *)data.dptr;
if (data.dsize < sizeof(*hdr))
fprintf(stderr, "%.*s: BAD truncated\n",
key.dsize, key.dptr);
else if (data.dsize != total_size(hdr))
fprintf(stderr, "%.*s: BAD length %i for %i/%i/%i (%i)\n",
key.dsize, key.dptr, data.dsize,
hdr->num_perms, hdr->datalen,
hdr->childlen, total_size(hdr));
else {
unsigned int i;
char *p;
printf("%.*s: ", key.dsize, key.dptr);
for (i = 0; i < hdr->num_perms; i++)
printf("%s%c%i",
i == 0 ? "" : ",",
perm_to_char(hdr->perms[i].perms),
hdr->perms[i].id);
p = (void *)&hdr->perms[hdr->num_perms];
printf(" %.*s\n", hdr->datalen, p);
p += hdr->datalen;
for (i = 0; i < hdr->childlen; i += strlen(p+i)+1)
printf("\t-> %s\n", p+i);
}
key = tdb_nextkey(tdb, key);
}
return 0;
}
+3 -3
View File
@@ -562,9 +562,9 @@ static void do_unwatch(unsigned int handle, const char *node, const char *token)
failed(handle);
}
static void do_start(unsigned int handle, const char *node)
static void do_start(unsigned int handle)
{
if (!xs_transaction_start(handles[handle], node))
if (!xs_transaction_start(handles[handle]))
failed(handle);
}
@@ -791,7 +791,7 @@ static void do_command(unsigned int default_handle, char *line)
xs_daemon_close(handles[handle]);
handles[handle] = NULL;
} else if (streq(command, "start"))
do_start(handle, arg(line, 1));
do_start(handle);
else if (streq(command, "commit"))
do_end(handle, false);
else if (streq(command, "abort"))
+5 -9
View File
@@ -2273,8 +2273,7 @@ int do_mmu_update(
int update_grant_pte_mapping(
unsigned long pte_addr, l1_pgentry_t _nl1e,
struct domain *d, struct vcpu *v)
unsigned long pte_addr, l1_pgentry_t _nl1e, struct vcpu *v)
{
int rc = GNTST_okay;
void *va;
@@ -2282,6 +2281,7 @@ int update_grant_pte_mapping(
struct pfn_info *page;
u32 type_info;
l1_pgentry_t ol1e;
struct domain *d = v->domain;
ASSERT(spin_is_locked(&d->big_lock));
ASSERT(!shadow_mode_refcounts(d));
@@ -2319,8 +2319,6 @@ int update_grant_pte_mapping(
put_page_from_l1e(ol1e, d);
rc = (l1e_get_flags(ol1e) & _PAGE_PRESENT) ? GNTST_flush_all : GNTST_okay;
if ( unlikely(shadow_mode_enabled(d)) )
{
struct domain_mmap_cache sh_mapcache;
@@ -2415,10 +2413,10 @@ int clear_grant_pte_mapping(
int update_grant_va_mapping(
unsigned long va, l1_pgentry_t _nl1e, struct domain *d, struct vcpu *v)
unsigned long va, l1_pgentry_t _nl1e, struct vcpu *v)
{
int rc = GNTST_okay;
l1_pgentry_t *pl1e, ol1e;
struct domain *d = v->domain;
ASSERT(spin_is_locked(&d->big_lock));
ASSERT(!shadow_mode_refcounts(d));
@@ -2439,12 +2437,10 @@ int update_grant_va_mapping(
put_page_from_l1e(ol1e, d);
rc = (l1e_get_flags(ol1e) & _PAGE_PRESENT) ? GNTST_flush_one : GNTST_okay;
if ( unlikely(shadow_mode_enabled(d)) )
shadow_do_update_va_mapping(va, _nl1e, v);
return rc;
return GNTST_okay;
}
int clear_grant_va_mapping(unsigned long addr, unsigned long frame)
+118 -112
View File
@@ -37,19 +37,19 @@
#endif
#ifdef CONFIG_VMX
struct vmcs_struct *alloc_vmcs(void)
struct vmcs_struct *alloc_vmcs(void)
{
struct vmcs_struct *vmcs;
u32 vmx_msr_low, vmx_msr_high;
rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
vmcs_size = vmx_msr_high & 0x1fff;
vmcs = alloc_xenheap_pages(get_order_from_bytes(vmcs_size));
vmcs = alloc_xenheap_pages(get_order_from_bytes(vmcs_size));
memset((char *)vmcs, 0, vmcs_size); /* don't remove this */
vmcs->vmcs_revision_id = vmx_msr_low;
return vmcs;
}
}
void free_vmcs(struct vmcs_struct *vmcs)
{
@@ -65,7 +65,7 @@ static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
void *io_bitmap_a;
void *io_bitmap_b;
error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL,
error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL,
MONITOR_PIN_BASED_EXEC_CONTROLS);
error |= __vmwrite(VM_EXIT_CONTROLS, MONITOR_VM_EXIT_CONTROLS);
@@ -73,8 +73,8 @@ static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS);
/* need to use 0x1000 instead of PAGE_SIZE */
io_bitmap_a = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
io_bitmap_b = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
io_bitmap_a = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
io_bitmap_b = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
memset(io_bitmap_a, 0xff, 0x1000);
/* don't bother debug port access */
clear_bit(PC_DEBUG_PORT, io_bitmap_a);
@@ -89,8 +89,10 @@ static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
return error;
}
#define GUEST_SEGMENT_LIMIT 0xffffffff
#define HOST_SEGMENT_LIMIT 0xffffffff
#define GUEST_LAUNCH_DS 0x08
#define GUEST_LAUNCH_CS 0x10
#define GUEST_SEGMENT_LIMIT 0xffffffff
#define HOST_SEGMENT_LIMIT 0xffffffff
struct host_execution_env {
/* selectors */
@@ -110,72 +112,76 @@ struct host_execution_env {
unsigned long tr_base;
unsigned long ds_base;
unsigned long cs_base;
#ifdef __x86_64__
unsigned long fs_base;
unsigned long gs_base;
#endif
#ifdef __x86_64__
unsigned long fs_base;
unsigned long gs_base;
#endif
};
#define round_pgdown(_p) ((_p)&PAGE_MASK) /* coped from domain.c */
int vmx_setup_platform(struct vcpu *d, struct cpu_user_regs *regs)
static void vmx_setup_platform(struct vcpu *v, struct cpu_user_regs *regs)
{
int i;
unsigned int n;
unsigned long *p, mpfn, offset, addr;
struct e820entry *e820p;
unsigned char e820_map_nr;
struct e820entry *e820entry;
unsigned char *p;
unsigned long mpfn;
unsigned long gpfn = 0;
local_flush_tlb_pge();
regs->ebx = 0; /* Linux expects ebx to be 0 for boot proc */
n = regs->ecx;
if (n > 32) {
VMX_DBG_LOG(DBG_LEVEL_1, "Too many e820 entries: %d", n);
return -1;
mpfn = get_mfn_from_pfn(E820_MAP_PAGE >> PAGE_SHIFT);
if (mpfn == INVALID_MFN) {
printk("Can not find E820 memory map page for VMX domain.\n");
domain_crash();
}
addr = regs->edi;
offset = (addr & ~PAGE_MASK);
addr = round_pgdown(addr);
mpfn = get_mfn_from_pfn(addr >> PAGE_SHIFT);
p = map_domain_page(mpfn);
if (p == NULL) {
printk("Can not map E820 memory map page for VMX domain.\n");
domain_crash();
}
e820p = (struct e820entry *) ((unsigned long) p + offset);
e820_map_nr = *(p + E820_MAP_NR_OFFSET);
e820entry = (struct e820entry *)(p + E820_MAP_OFFSET);
#ifndef NDEBUG
print_e820_memory_map(e820p, n);
#endif
for ( i = 0; i < n; i++ )
for ( i = 0; i < e820_map_nr; i++ )
{
if ( e820p[i].type == E820_SHARED_PAGE )
if (e820entry[i].type == E820_SHARED_PAGE)
{
gpfn = (e820p[i].addr >> PAGE_SHIFT);
gpfn = (e820entry[i].addr >> PAGE_SHIFT);
break;
}
}
if ( gpfn == 0 )
{
unmap_domain_page(p);
return -1;
}
if ( gpfn == 0 ) {
printk("Can not get io request shared page"
" from E820 memory map for VMX domain.\n");
unmap_domain_page(p);
domain_crash();
}
unmap_domain_page(p);
unmap_domain_page(p);
if (v->vcpu_id)
return;
/* Initialise shared page */
mpfn = get_mfn_from_pfn(gpfn);
if (mpfn == INVALID_MFN) {
printk("Can not find io request shared page for VMX domain.\n");
domain_crash();
}
p = map_domain_page(mpfn);
d->domain->arch.vmx_platform.shared_page_va = (unsigned long)p;
if (p == NULL) {
printk("Can not map io request shared page for VMX domain.\n");
domain_crash();
}
v->domain->arch.vmx_platform.shared_page_va = (unsigned long)p;
VMX_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d->domain));
VMX_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(v->domain));
clear_bit(iopacket_port(d->domain),
&d->domain->shared_info->evtchn_mask[0]);
return 0;
clear_bit(iopacket_port(v->domain),
&v->domain->shared_info->evtchn_mask[0]);
}
void vmx_set_host_env(struct vcpu *v)
@@ -203,7 +209,7 @@ void vmx_set_host_env(struct vcpu *v)
error |= __vmwrite(HOST_TR_BASE, host_env.tr_base);
}
void vmx_do_launch(struct vcpu *v)
void vmx_do_launch(struct vcpu *v)
{
/* Update CR3, GDT, LDT, TR */
unsigned int error = 0;
@@ -217,7 +223,7 @@ void vmx_do_launch(struct vcpu *v)
error |= __vmwrite(GUEST_CR0, cr0);
cr0 &= ~X86_CR0_PG;
error |= __vmwrite(CR0_READ_SHADOW, cr0);
error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
MONITOR_CPU_BASED_EXEC_CONTROLS);
__asm__ __volatile__ ("mov %%cr4,%0" : "=r" (cr4) : );
@@ -247,7 +253,7 @@ void vmx_do_launch(struct vcpu *v)
error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
error |= __vmwrite(GUEST_LDTR_BASE, 0);
error |= __vmwrite(GUEST_LDTR_LIMIT, 0);
error |= __vmwrite(GUEST_TR_BASE, 0);
error |= __vmwrite(GUEST_TR_LIMIT, 0xff);
@@ -261,10 +267,8 @@ void vmx_do_launch(struct vcpu *v)
/*
* Initially set the same environement as host.
*/
static inline int
construct_init_vmcs_guest(struct cpu_user_regs *regs,
struct vcpu_guest_context *ctxt,
struct host_execution_env *host_env)
static inline int
construct_init_vmcs_guest(struct cpu_user_regs *regs)
{
int error = 0;
union vmcs_arbytes arbytes;
@@ -292,31 +296,37 @@ construct_init_vmcs_guest(struct cpu_user_regs *regs,
error |= __vmwrite(CR3_TARGET_COUNT, 0);
/* Guest Selectors */
error |= __vmwrite(GUEST_CS_SELECTOR, regs->cs);
error |= __vmwrite(GUEST_ES_SELECTOR, regs->es);
error |= __vmwrite(GUEST_SS_SELECTOR, regs->ss);
error |= __vmwrite(GUEST_DS_SELECTOR, regs->ds);
error |= __vmwrite(GUEST_FS_SELECTOR, regs->fs);
error |= __vmwrite(GUEST_GS_SELECTOR, regs->gs);
error |= __vmwrite(GUEST_ES_SELECTOR, GUEST_LAUNCH_DS);
error |= __vmwrite(GUEST_SS_SELECTOR, GUEST_LAUNCH_DS);
error |= __vmwrite(GUEST_DS_SELECTOR, GUEST_LAUNCH_DS);
error |= __vmwrite(GUEST_FS_SELECTOR, GUEST_LAUNCH_DS);
error |= __vmwrite(GUEST_GS_SELECTOR, GUEST_LAUNCH_DS);
error |= __vmwrite(GUEST_CS_SELECTOR, GUEST_LAUNCH_CS);
/* Guest segment bases */
error |= __vmwrite(GUEST_ES_BASE, 0);
error |= __vmwrite(GUEST_SS_BASE, 0);
error |= __vmwrite(GUEST_DS_BASE, 0);
error |= __vmwrite(GUEST_FS_BASE, 0);
error |= __vmwrite(GUEST_GS_BASE, 0);
error |= __vmwrite(GUEST_CS_BASE, 0);
/* Guest segment Limits */
error |= __vmwrite(GUEST_CS_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_ES_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_SS_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_DS_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_FS_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_GS_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_CS_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_IDTR_LIMIT, host_env->idtr_limit);
/* AR bytes */
/* Guest segment AR bytes */
arbytes.bytes = 0;
arbytes.fields.seg_type = 0x3; /* type = 3 */
arbytes.fields.s = 1; /* code or data, i.e. not system */
arbytes.fields.dpl = 0; /* DPL = 3 */
arbytes.fields.p = 1; /* segment present */
arbytes.fields.default_ops_size = 1; /* 32-bit */
arbytes.fields.g = 1;
arbytes.fields.g = 1;
arbytes.fields.null_bit = 0; /* not null */
error |= __vmwrite(GUEST_ES_AR_BYTES, arbytes.bytes);
@@ -328,35 +338,31 @@ construct_init_vmcs_guest(struct cpu_user_regs *regs,
arbytes.fields.seg_type = 0xb; /* type = 0xb */
error |= __vmwrite(GUEST_CS_AR_BYTES, arbytes.bytes);
error |= __vmwrite(GUEST_GDTR_BASE, regs->edx);
regs->edx = 0;
error |= __vmwrite(GUEST_GDTR_LIMIT, regs->eax);
regs->eax = 0;
/* Guest GDT */
error |= __vmwrite(GUEST_GDTR_BASE, 0);
error |= __vmwrite(GUEST_GDTR_LIMIT, 0);
/* Guest IDT */
error |= __vmwrite(GUEST_IDTR_BASE, 0);
error |= __vmwrite(GUEST_IDTR_LIMIT, 0);
/* Guest LDT & TSS */
arbytes.fields.s = 0; /* not code or data segement */
arbytes.fields.seg_type = 0x2; /* LTD */
arbytes.fields.default_ops_size = 0; /* 16-bit */
arbytes.fields.g = 0;
arbytes.fields.g = 0;
error |= __vmwrite(GUEST_LDTR_AR_BYTES, arbytes.bytes);
arbytes.fields.seg_type = 0xb; /* 32-bit TSS (busy) */
error |= __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes);
/* CR3 is set in vmx_final_setup_guest */
error |= __vmwrite(GUEST_ES_BASE, host_env->ds_base);
error |= __vmwrite(GUEST_CS_BASE, host_env->cs_base);
error |= __vmwrite(GUEST_SS_BASE, host_env->ds_base);
error |= __vmwrite(GUEST_DS_BASE, host_env->ds_base);
error |= __vmwrite(GUEST_FS_BASE, host_env->ds_base);
error |= __vmwrite(GUEST_GS_BASE, host_env->ds_base);
error |= __vmwrite(GUEST_IDTR_BASE, host_env->idtr_base);
error |= __vmwrite(GUEST_RSP, regs->esp);
error |= __vmwrite(GUEST_RSP, 0);
error |= __vmwrite(GUEST_RIP, regs->eip);
/* Guest EFLAGS */
eflags = regs->eflags & ~VMCS_EFLAGS_RESERVED_0; /* clear 0s */
eflags |= VMCS_EFLAGS_RESERVED_1; /* set 1s */
error |= __vmwrite(GUEST_RFLAGS, eflags);
error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
@@ -381,14 +387,14 @@ static inline int construct_vmcs_host(struct host_execution_env *host_env)
#if defined (__i386__)
error |= __vmwrite(HOST_FS_SELECTOR, host_env->ds_selector);
error |= __vmwrite(HOST_GS_SELECTOR, host_env->ds_selector);
error |= __vmwrite(HOST_FS_BASE, host_env->ds_base);
error |= __vmwrite(HOST_GS_BASE, host_env->ds_base);
error |= __vmwrite(HOST_FS_BASE, host_env->ds_base);
error |= __vmwrite(HOST_GS_BASE, host_env->ds_base);
#else
rdmsrl(MSR_FS_BASE, host_env->fs_base);
rdmsrl(MSR_GS_BASE, host_env->gs_base);
error |= __vmwrite(HOST_FS_BASE, host_env->fs_base);
error |= __vmwrite(HOST_GS_BASE, host_env->gs_base);
rdmsrl(MSR_FS_BASE, host_env->fs_base);
rdmsrl(MSR_GS_BASE, host_env->gs_base);
error |= __vmwrite(HOST_FS_BASE, host_env->fs_base);
error |= __vmwrite(HOST_GS_BASE, host_env->gs_base);
#endif
host_env->cs_selector = __HYPERVISOR_CS;
@@ -401,16 +407,16 @@ static inline int construct_vmcs_host(struct host_execution_env *host_env)
error |= __vmwrite(HOST_CR0, crn); /* same CR0 */
/* CR3 is set in vmx_final_setup_hostos */
__asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) : );
__asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) : );
error |= __vmwrite(HOST_CR4, crn);
error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler);
#ifdef __x86_64__
/* TBD: support cr8 for 64-bit guest */
__vmwrite(VIRTUAL_APIC_PAGE_ADDR, 0);
__vmwrite(TPR_THRESHOLD, 0);
__vmwrite(SECONDARY_VM_EXEC_CONTROL, 0);
#endif
#ifdef __x86_64__
/* TBD: support cr8 for 64-bit guest */
__vmwrite(VIRTUAL_APIC_PAGE_ADDR, 0);
__vmwrite(TPR_THRESHOLD, 0);
__vmwrite(SECONDARY_VM_EXEC_CONTROL, 0);
#endif
return error;
}
@@ -440,37 +446,37 @@ int construct_vmcs(struct arch_vmx_struct *arch_vmx,
if ((error = __vmpclear (vmcs_phys_ptr))) {
printk("construct_vmcs: VMCLEAR failed\n");
return -EINVAL;
return -EINVAL;
}
if ((error = load_vmcs(arch_vmx, vmcs_phys_ptr))) {
printk("construct_vmcs: load_vmcs failed: VMCS = %lx\n",
(unsigned long) vmcs_phys_ptr);
return -EINVAL;
return -EINVAL;
}
if ((error = construct_vmcs_controls(arch_vmx))) {
printk("construct_vmcs: construct_vmcs_controls failed\n");
return -EINVAL;
return -EINVAL;
}
/* host selectors */
if ((error = construct_vmcs_host(&host_env))) {
printk("construct_vmcs: construct_vmcs_host failed\n");
return -EINVAL;
return -EINVAL;
}
/* guest selectors */
if ((error = construct_init_vmcs_guest(regs, ctxt, &host_env))) {
if ((error = construct_init_vmcs_guest(regs))) {
printk("construct_vmcs: construct_vmcs_guest failed\n");
return -EINVAL;
}
return -EINVAL;
}
if ((error |= __vmwrite(EXCEPTION_BITMAP,
if ((error |= __vmwrite(EXCEPTION_BITMAP,
MONITOR_DEFAULT_EXCEPTION_BITMAP))) {
printk("construct_vmcs: setting Exception bitmap failed\n");
return -EINVAL;
return -EINVAL;
}
if (regs->eflags & EF_TF)
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
else
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
return 0;
@@ -491,7 +497,7 @@ int modify_vmcs(struct arch_vmx_struct *arch_vmx,
if ((error = load_vmcs(arch_vmx, vmcs_phys_ptr))) {
printk("modify_vmcs: load_vmcs failed: VMCS = %lx\n",
(unsigned long) vmcs_phys_ptr);
return -EINVAL;
return -EINVAL;
}
load_cpu_user_regs(regs);
@@ -500,23 +506,23 @@ int modify_vmcs(struct arch_vmx_struct *arch_vmx,
return 0;
}
int load_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
int load_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
{
int error;
if ((error = __vmptrld(phys_ptr))) {
clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return error;
}
set_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
set_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return 0;
}
int store_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
int store_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
{
/* take the current VMCS */
__vmptrst(phys_ptr);
clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return 0;
}
@@ -536,7 +542,7 @@ void vm_resume_fail(unsigned long eflags)
__vmx_bug(guest_cpu_user_regs());
}
void arch_vmx_do_resume(struct vcpu *v)
void arch_vmx_do_resume(struct vcpu *v)
{
u64 vmcs_phys_ptr = (u64) virt_to_phys(v->arch.arch_vmx.vmcs);
@@ -545,7 +551,7 @@ void arch_vmx_do_resume(struct vcpu *v)
reset_stack_and_jump(vmx_asm_do_resume);
}
void arch_vmx_do_launch(struct vcpu *v)
void arch_vmx_do_launch(struct vcpu *v)
{
u64 vmcs_phys_ptr = (u64) virt_to_phys(v->arch.arch_vmx.vmcs);
+240 -359
View File
@@ -24,10 +24,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define GRANT_DEBUG 0
#define GRANT_DEBUG_VERBOSE 0
#include <xen/config.h>
#include <xen/lib.h>
#include <xen/sched.h>
#include <xen/shadow.h>
@@ -68,262 +64,6 @@ put_maptrack_handle(
t->map_count--;
}
static int
__gnttab_activate_grant_ref(
struct domain *mapping_d, /* IN */
struct vcpu *mapping_ed,
struct domain *granting_d,
grant_ref_t ref,
u16 dev_hst_ro_flags,
u64 addr,
unsigned long *pframe ) /* OUT */
{
domid_t sdom;
u16 sflags;
active_grant_entry_t *act;
grant_entry_t *sha;
s16 rc = 1;
unsigned long frame = 0;
int retries = 0;
/*
* Objectives of this function:
* . Make the record ( granting_d, ref ) active, if not already.
* . Update shared grant entry of owner, indicating frame is mapped.
* . Increment the owner act->pin reference counts.
* . get_page on shared frame if new mapping.
* . get_page_type if this is first RW mapping of frame.
* . Add PTE to virtual address space of mapping_d, if necessary.
* Returns:
* . -ve: error
* . 1: ok
* . 0: ok and TLB invalidate of host_addr needed.
*
* On success, *pframe contains mfn.
*/
/*
* We bound the number of times we retry CMPXCHG on memory locations that
* we share with a guest OS. The reason is that the guest can modify that
* location at a higher rate than we can read-modify-CMPXCHG, so the guest
* could cause us to livelock. There are a few cases where it is valid for
* the guest to race our updates (e.g., to change the GTF_readonly flag),
* so we allow a few retries before failing.
*/
act = &granting_d->grant_table->active[ref];
sha = &granting_d->grant_table->shared[ref];
spin_lock(&granting_d->grant_table->lock);
if ( act->pin == 0 )
{
/* CASE 1: Activating a previously inactive entry. */
sflags = sha->flags;
sdom = sha->domid;
/* This loop attempts to set the access (reading/writing) flags
* in the grant table entry. It tries a cmpxchg on the field
* up to five times, and then fails under the assumption that
* the guest is misbehaving. */
for ( ; ; )
{
u32 scombo, prev_scombo, new_scombo;
if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
unlikely(sdom != mapping_d->domain_id) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
sflags, sdom, mapping_d->domain_id);
/* Merge two 16-bit values into a 32-bit combined update. */
/* NB. Endianness! */
prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
new_scombo = scombo | GTF_reading;
if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
{
new_scombo |= GTF_writing;
if ( unlikely(sflags & GTF_readonly) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Attempt to write-pin a r/o grant entry.\n");
}
/* NB. prev_scombo is updated in place to seen value. */
if ( unlikely(cmpxchg_user((u32 *)&sha->flags,
prev_scombo,
new_scombo)) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Fault while modifying shared flags and domid.\n");
/* Did the combined update work (did we see what we expected?). */
if ( likely(prev_scombo == scombo) )
break;
if ( retries++ == 4 )
PIN_FAIL(unlock_out, GNTST_general_error,
"Shared grant entry is unstable.\n");
/* Didn't see what we expected. Split out the seen flags & dom. */
/* NB. Endianness! */
sflags = (u16)prev_scombo;
sdom = (u16)(prev_scombo >> 16);
}
/* rmb(); */ /* not on x86 */
frame = __gpfn_to_mfn_foreign(granting_d, sha->frame);
if ( unlikely(!pfn_valid(frame)) ||
unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ?
get_page(&frame_table[frame], granting_d) :
get_page_and_type(&frame_table[frame], granting_d,
PGT_writable_page))) )
{
clear_bit(_GTF_writing, &sha->flags);
clear_bit(_GTF_reading, &sha->flags);
PIN_FAIL(unlock_out, GNTST_general_error,
"Could not pin the granted frame (%lx)!\n", frame);
}
if ( dev_hst_ro_flags & GNTMAP_device_map )
act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
GNTPIN_devr_inc : GNTPIN_devw_inc;
if ( dev_hst_ro_flags & GNTMAP_host_map )
act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
GNTPIN_hstr_inc : GNTPIN_hstw_inc;
act->domid = sdom;
act->frame = frame;
}
else
{
/* CASE 2: Active modications to an already active entry. */
/*
* A cheesy check for possible pin-count overflow.
* A more accurate check cannot be done with a single comparison.
*/
if ( (act->pin & 0x80808080U) != 0 )
PIN_FAIL(unlock_out, ENOSPC,
"Risk of counter overflow %08x\n", act->pin);
frame = act->frame;
if ( !(dev_hst_ro_flags & GNTMAP_readonly) &&
!((sflags = sha->flags) & GTF_writing) )
{
for ( ; ; )
{
u16 prev_sflags;
if ( unlikely(sflags & GTF_readonly) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Attempt to write-pin a r/o grant entry.\n");
prev_sflags = sflags;
/* NB. prev_sflags is updated in place to seen value. */
if ( unlikely(cmpxchg_user(&sha->flags, prev_sflags,
prev_sflags | GTF_writing)) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Fault while modifying shared flags.\n");
if ( likely(prev_sflags == sflags) )
break;
if ( retries++ == 4 )
PIN_FAIL(unlock_out, GNTST_general_error,
"Shared grant entry is unstable.\n");
sflags = prev_sflags;
}
if ( unlikely(!get_page_type(&frame_table[frame],
PGT_writable_page)) )
{
clear_bit(_GTF_writing, &sha->flags);
PIN_FAIL(unlock_out, GNTST_general_error,
"Attempt to write-pin a unwritable page.\n");
}
}
if ( dev_hst_ro_flags & GNTMAP_device_map )
act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
GNTPIN_devr_inc : GNTPIN_devw_inc;
if ( dev_hst_ro_flags & GNTMAP_host_map )
act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
GNTPIN_hstr_inc : GNTPIN_hstw_inc;
}
/*
* At this point:
* act->pin updated to reference count mappings.
* sha->flags updated to indicate to granting domain mapping done.
* frame contains the mfn.
*/
spin_unlock(&granting_d->grant_table->lock);
if ( (addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
{
/* Write update into the pagetable. */
l1_pgentry_t pte;
pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
if ( (dev_hst_ro_flags & GNTMAP_application_map) )
l1e_add_flags(pte,_PAGE_USER);
if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
l1e_add_flags(pte,_PAGE_RW);
if ( dev_hst_ro_flags & GNTMAP_contains_pte )
rc = update_grant_pte_mapping(addr, pte, mapping_d, mapping_ed);
else
rc = update_grant_va_mapping(addr, pte, mapping_d, mapping_ed);
/* IMPORTANT: rc indicates the degree of TLB flush that is required.
* GNTST_flush_one (1) or GNTST_flush_all (2). This is done in the
* outer gnttab_map_grant_ref. */
if ( rc < 0 )
{
/* Failure: undo and abort. */
spin_lock(&granting_d->grant_table->lock);
if ( dev_hst_ro_flags & GNTMAP_readonly )
{
act->pin -= GNTPIN_hstr_inc;
}
else
{
act->pin -= GNTPIN_hstw_inc;
if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
{
clear_bit(_GTF_writing, &sha->flags);
put_page_type(&frame_table[frame]);
}
}
if ( act->pin == 0 )
{
clear_bit(_GTF_reading, &sha->flags);
put_page(&frame_table[frame]);
}
spin_unlock(&granting_d->grant_table->lock);
}
}
*pframe = frame;
return rc;
unlock_out:
spin_unlock(&granting_d->grant_table->lock);
return rc;
}
/*
* Returns 0 if TLB flush / invalidate required by caller.
* va will indicate the address to be invalidated.
@@ -333,8 +73,7 @@ __gnttab_activate_grant_ref(
*/
static int
__gnttab_map_grant_ref(
gnttab_map_grant_ref_t *uop,
unsigned long *va)
gnttab_map_grant_ref_t *uop)
{
domid_t dom;
grant_ref_t ref;
@@ -344,7 +83,23 @@ __gnttab_map_grant_ref(
int handle;
u64 addr;
unsigned long frame = 0;
int rc;
int rc = GNTST_okay;
active_grant_entry_t *act;
/* Entry details from @rd's shared grant table. */
grant_entry_t *sha;
domid_t sdom;
u16 sflags;
/*
* We bound the number of times we retry CMPXCHG on memory locations that
* we share with a guest OS. The reason is that the guest can modify that
* location at a higher rate than we can read-modify-CMPXCHG, so the guest
* could cause us to livelock. There are a few cases where it is valid for
* the guest to race our updates (e.g., to change the GTF_readonly flag),
* so we allow a few retries before failing.
*/
int retries = 0;
led = current;
ld = led->domain;
@@ -359,17 +114,6 @@ __gnttab_map_grant_ref(
return -EFAULT; /* don't set status */
}
if ( (dev_hst_ro_flags & GNTMAP_host_map) &&
( (addr == 0) ||
(!(dev_hst_ro_flags & GNTMAP_contains_pte) &&
unlikely(!__addr_ok(addr))) ) )
{
DPRINTK("Bad virtual address (%"PRIx64") or flags (%"PRIx16").\n",
addr, dev_hst_ro_flags);
(void)__put_user(GNTST_bad_virt_addr, &uop->handle);
return GNTST_bad_gntref;
}
if ( unlikely(ref >= NR_GRANT_ENTRIES) ||
unlikely((dev_hst_ro_flags &
(GNTMAP_device_map|GNTMAP_host_map)) == 0) )
@@ -379,7 +123,8 @@ __gnttab_map_grant_ref(
return GNTST_bad_gntref;
}
if (acm_pre_grant_map_ref(dom)) {
if ( acm_pre_grant_map_ref(dom) )
{
(void)__put_user(GNTST_permission_denied, &uop->handle);
return GNTST_permission_denied;
}
@@ -432,65 +177,242 @@ __gnttab_map_grant_ref(
handle = get_maptrack_handle(ld->grant_table);
}
#if GRANT_DEBUG_VERBOSE
DPRINTK("Mapping grant ref (%hu) for domain (%hu) with flags (%x)\n",
ref, dom, dev_hst_ro_flags);
#endif
act = &rd->grant_table->active[ref];
sha = &rd->grant_table->shared[ref];
if ( (rc = __gnttab_activate_grant_ref(ld, led, rd, ref, dev_hst_ro_flags,
addr, &frame)) >= 0 )
spin_lock(&rd->grant_table->lock);
if ( act->pin == 0 )
{
/* CASE 1: Activating a previously inactive entry. */
sflags = sha->flags;
sdom = sha->domid;
/* This loop attempts to set the access (reading/writing) flags
* in the grant table entry. It tries a cmpxchg on the field
* up to five times, and then fails under the assumption that
* the guest is misbehaving. */
for ( ; ; )
{
u32 scombo, prev_scombo, new_scombo;
if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
unlikely(sdom != led->domain->domain_id) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
sflags, sdom, led->domain->domain_id);
/* Merge two 16-bit values into a 32-bit combined update. */
/* NB. Endianness! */
prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
new_scombo = scombo | GTF_reading;
if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
{
new_scombo |= GTF_writing;
if ( unlikely(sflags & GTF_readonly) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Attempt to write-pin a r/o grant entry.\n");
}
/* NB. prev_scombo is updated in place to seen value. */
if ( unlikely(cmpxchg_user((u32 *)&sha->flags,
prev_scombo,
new_scombo)) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Fault while modifying shared flags and domid.\n");
/* Did the combined update work (did we see what we expected?). */
if ( likely(prev_scombo == scombo) )
break;
if ( retries++ == 4 )
PIN_FAIL(unlock_out, GNTST_general_error,
"Shared grant entry is unstable.\n");
/* Didn't see what we expected. Split out the seen flags & dom. */
/* NB. Endianness! */
sflags = (u16)prev_scombo;
sdom = (u16)(prev_scombo >> 16);
}
/* rmb(); */ /* not on x86 */
frame = __gpfn_to_mfn_foreign(rd, sha->frame);
if ( unlikely(!pfn_valid(frame)) ||
unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ?
get_page(&frame_table[frame], rd) :
get_page_and_type(&frame_table[frame], rd,
PGT_writable_page))) )
{
clear_bit(_GTF_writing, &sha->flags);
clear_bit(_GTF_reading, &sha->flags);
PIN_FAIL(unlock_out, GNTST_general_error,
"Could not pin the granted frame (%lx)!\n", frame);
}
if ( dev_hst_ro_flags & GNTMAP_device_map )
act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
GNTPIN_devr_inc : GNTPIN_devw_inc;
if ( dev_hst_ro_flags & GNTMAP_host_map )
act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
GNTPIN_hstr_inc : GNTPIN_hstw_inc;
act->domid = sdom;
act->frame = frame;
}
else
{
/* CASE 2: Active modications to an already active entry. */
/*
* Only make the maptrack live _after_ writing the pte, in case we
* overwrite the same frame number, causing a maptrack walk to find it
* A cheesy check for possible pin-count overflow.
* A more accurate check cannot be done with a single comparison.
*/
ld->grant_table->maptrack[handle].domid = dom;
if ( (act->pin & 0x80808080U) != 0 )
PIN_FAIL(unlock_out, ENOSPC,
"Risk of counter overflow %08x\n", act->pin);
ld->grant_table->maptrack[handle].ref_and_flags
= (ref << MAPTRACK_REF_SHIFT) |
(dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK);
sflags = sha->flags;
frame = act->frame;
(void)__put_user((u64)frame << PAGE_SHIFT, &uop->dev_bus_addr);
if ( !(dev_hst_ro_flags & GNTMAP_readonly) &&
!(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
{
for ( ; ; )
{
u16 prev_sflags;
if ( unlikely(sflags & GTF_readonly) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Attempt to write-pin a r/o grant entry.\n");
if ( ( dev_hst_ro_flags & GNTMAP_host_map ) &&
!( dev_hst_ro_flags & GNTMAP_contains_pte) )
*va = addr;
prev_sflags = sflags;
(void)__put_user(handle, &uop->handle);
/* NB. prev_sflags is updated in place to seen value. */
if ( unlikely(cmpxchg_user(&sha->flags, prev_sflags,
prev_sflags | GTF_writing)) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Fault while modifying shared flags.\n");
if ( likely(prev_sflags == sflags) )
break;
if ( retries++ == 4 )
PIN_FAIL(unlock_out, GNTST_general_error,
"Shared grant entry is unstable.\n");
sflags = prev_sflags;
}
if ( unlikely(!get_page_type(&frame_table[frame],
PGT_writable_page)) )
{
clear_bit(_GTF_writing, &sha->flags);
PIN_FAIL(unlock_out, GNTST_general_error,
"Attempt to write-pin a unwritable page.\n");
}
}
if ( dev_hst_ro_flags & GNTMAP_device_map )
act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
GNTPIN_devr_inc : GNTPIN_devw_inc;
if ( dev_hst_ro_flags & GNTMAP_host_map )
act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
GNTPIN_hstr_inc : GNTPIN_hstw_inc;
}
else
/*
* At this point:
* act->pin updated to reference count mappings.
* sha->flags updated to indicate to granting domain mapping done.
* frame contains the mfn.
*/
spin_unlock(&rd->grant_table->lock);
if ( dev_hst_ro_flags & GNTMAP_host_map )
{
(void)__put_user(rc, &uop->handle);
put_maptrack_handle(ld->grant_table, handle);
/* Write update into the pagetable. */
l1_pgentry_t pte;
pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
if ( (dev_hst_ro_flags & GNTMAP_application_map) )
l1e_add_flags(pte,_PAGE_USER);
if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
l1e_add_flags(pte,_PAGE_RW);
if ( dev_hst_ro_flags & GNTMAP_contains_pte )
rc = update_grant_pte_mapping(addr, pte, led);
else
rc = update_grant_va_mapping(addr, pte, led);
if ( rc < 0 )
{
/* Failure: undo and abort. */
spin_lock(&rd->grant_table->lock);
if ( dev_hst_ro_flags & GNTMAP_readonly )
{
act->pin -= GNTPIN_hstr_inc;
}
else
{
act->pin -= GNTPIN_hstw_inc;
if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
{
clear_bit(_GTF_writing, &sha->flags);
put_page_type(&frame_table[frame]);
}
}
if ( act->pin == 0 )
{
clear_bit(_GTF_reading, &sha->flags);
put_page(&frame_table[frame]);
}
spin_unlock(&rd->grant_table->lock);
}
}
ld->grant_table->maptrack[handle].domid = dom;
ld->grant_table->maptrack[handle].ref_and_flags =
(ref << MAPTRACK_REF_SHIFT) |
(dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK);
(void)__put_user((u64)frame << PAGE_SHIFT, &uop->dev_bus_addr);
(void)__put_user(handle, &uop->handle);
put_domain(rd);
return rc;
unlock_out:
spin_unlock(&rd->grant_table->lock);
(void)__put_user(rc, &uop->handle);
put_maptrack_handle(ld->grant_table, handle);
return rc;
}
static long
gnttab_map_grant_ref(
gnttab_map_grant_ref_t *uop, unsigned int count)
{
int i, rc, flush = 0;
unsigned long va = 0;
int i;
for ( i = 0; i < count; i++ )
if ( (rc =__gnttab_map_grant_ref(&uop[i], &va)) >= 0 )
flush += rc;
if ( flush == 1 )
flush_tlb_one_mask(current->domain->cpumask, va);
else if ( flush != 0 )
flush_tlb_mask(current->domain->cpumask);
(void)__gnttab_map_grant_ref(&uop[i]);
return 0;
}
static int
__gnttab_unmap_grant_ref(
gnttab_unmap_grant_ref_t *uop,
unsigned long *va)
gnttab_unmap_grant_ref_t *uop)
{
domid_t dom;
grant_ref_t ref;
@@ -500,7 +422,7 @@ __gnttab_unmap_grant_ref(
grant_entry_t *sha;
grant_mapping_t *map;
u16 flags;
s16 rc = 1;
s16 rc = 0;
u64 addr, dev_bus_addr;
unsigned long frame;
@@ -541,11 +463,6 @@ __gnttab_unmap_grant_ref(
return GNTST_bad_domain;
}
#if GRANT_DEBUG_VERBOSE
DPRINTK("Unmapping grant ref (%hu) for domain (%hu) with handle (%hu)\n",
ref, dom, handle);
#endif
act = &rd->grant_table->active[ref];
sha = &rd->grant_table->shared[ref];
@@ -566,8 +483,6 @@ __gnttab_unmap_grant_ref(
map->ref_and_flags &= ~GNTMAP_device_map;
(void)__put_user(0, &uop->dev_bus_addr);
/* Frame is now unmapped for device access. */
}
if ( (addr != 0) &&
@@ -589,10 +504,6 @@ __gnttab_unmap_grant_ref(
act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_hstr_inc
: GNTPIN_hstw_inc;
rc = 0;
if ( !( flags & GNTMAP_contains_pte) )
*va = addr;
}
if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0)
@@ -632,17 +543,12 @@ static long
gnttab_unmap_grant_ref(
gnttab_unmap_grant_ref_t *uop, unsigned int count)
{
int i, flush = 0;
unsigned long va = 0;
int i;
for ( i = 0; i < count; i++ )
if ( __gnttab_unmap_grant_ref(&uop[i], &va) == 0 )
flush++;
(void)__gnttab_unmap_grant_ref(&uop[i]);
if ( flush == 1 )
flush_tlb_one_mask(current->domain->cpumask, va);
else if ( flush != 0 )
flush_tlb_mask(current->domain->cpumask);
flush_tlb_mask(current->domain->cpumask);
return 0;
}
@@ -703,9 +609,9 @@ gnttab_setup_table(
return 0;
}
#if GRANT_DEBUG
static int
gnttab_dump_table(gnttab_dump_table_t *uop)
gnttab_dump_table(
gnttab_dump_table_t *uop)
{
grant_table_t *gt;
gnttab_dump_table_t op;
@@ -716,6 +622,8 @@ gnttab_dump_table(gnttab_dump_table_t *uop)
grant_mapping_t *maptrack;
int i;
if ( !IS_PRIV(current->domain) )
return -EPERM;
if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
{
@@ -724,9 +632,7 @@ gnttab_dump_table(gnttab_dump_table_t *uop)
}
if ( op.dom == DOMID_SELF )
{
op.dom = current->domain->domain_id;
}
if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
{
@@ -750,14 +656,11 @@ gnttab_dump_table(gnttab_dump_table_t *uop)
for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
{
sha_copy = gt->shared[i];
sha_copy = gt->shared[i];
if ( sha_copy.flags )
{
DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) "
"dom:(%hu) frame:(%x)\n",
op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
}
}
spin_lock(&gt->lock);
@@ -765,28 +668,22 @@ gnttab_dump_table(gnttab_dump_table_t *uop)
for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
{
act = &gt->active[i];
if ( act->pin )
{
DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) "
"dom:(%hu) frame:(%lx)\n",
op.dom, i, act->pin, act->domid, act->frame);
}
}
for ( i = 0; i < gt->maptrack_limit; i++ )
{
maptrack = &gt->maptrack[i];
if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK )
{
DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) "
"dom:(%hu)\n",
op.dom, i,
maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT,
maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK,
maptrack->domid);
}
}
spin_unlock(&gt->lock);
@@ -794,10 +691,10 @@ gnttab_dump_table(gnttab_dump_table_t *uop)
put_domain(d);
return 0;
}
#endif
static long
gnttab_transfer(gnttab_transfer_t *uop, unsigned int count)
gnttab_transfer(
gnttab_transfer_t *uop, unsigned int count)
{
struct domain *d = current->domain;
struct domain *e;
@@ -810,10 +707,7 @@ gnttab_transfer(gnttab_transfer_t *uop, unsigned int count)
for ( i = 0; i < count; i++ )
{
gnttab_transfer_t *gop = &uop[i];
#if GRANT_DEBUG
printk("gnttab_transfer: i=%d mfn=%lx domid=%d gref=%08x\n",
i, gop->mfn, gop->domid, gop->handle);
#endif
page = &frame_table[gop->mfn];
if ( unlikely(IS_XEN_HEAP_FRAME(page)))
@@ -956,11 +850,9 @@ do_grant_table_op(
case GNTTABOP_setup_table:
rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
break;
#if GRANT_DEBUG
case GNTTABOP_dump_table:
rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
break;
#endif
case GNTTABOP_transfer:
if (unlikely(!array_access_ok(
uop, count, sizeof(gnttab_transfer_t))))
@@ -1002,12 +894,6 @@ gnttab_check_unmap(
lgt = ld->grant_table;
#if GRANT_DEBUG_VERBOSE
if ( ld->domain_id != 0 )
DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
rd->domain_id, ld->domain_id, frame, readonly);
#endif
/* Fast exit if we're not mapping anything using grant tables */
if ( lgt->map_count == 0 )
return 0;
@@ -1098,11 +984,6 @@ gnttab_prepare_for_transfer(
int retries = 0;
unsigned long target_pfn;
#if GRANT_DEBUG_VERBOSE
DPRINTK("gnttab_prepare_for_transfer rd(%hu) ld(%hu) ref(%hu).\n",
rd->domain_id, ld->domain_id, ref);
#endif
if ( unlikely((rgt = rd->grant_table) == NULL) ||
unlikely(ref >= NR_GRANT_ENTRIES) )
{
+5
View File
@@ -11,6 +11,11 @@
#define E820_NVS 4
#define E820_IO 16
#define E820_SHARED_PAGE 17
#define E820_XENSTORE 18
#define E820_MAP_PAGE 0x00090000
#define E820_MAP_NR_OFFSET 0x000001E8
#define E820_MAP_OFFSET 0x000002D0
#ifndef __ASSEMBLY__
struct e820entry {
+2 -4
View File
@@ -380,11 +380,9 @@ extern int __sync_lazy_execstate(void);
* hold a reference to the page.
*/
int update_grant_va_mapping(
unsigned long va, l1_pgentry_t _nl1e,
struct domain *d, struct vcpu *v);
unsigned long va, l1_pgentry_t _nl1e, struct vcpu *v);
int update_grant_pte_mapping(
unsigned long pte_addr, l1_pgentry_t _nl1e,
struct domain *d, struct vcpu *v);
unsigned long pte_addr, l1_pgentry_t _nl1e, struct vcpu *v);
int clear_grant_va_mapping(unsigned long addr, unsigned long frame);
int clear_grant_pte_mapping(
unsigned long addr, unsigned long frame, struct domain *d);
-1
View File
@@ -93,7 +93,6 @@ struct virtual_platform_def {
extern void handle_mmio(unsigned long, unsigned long);
extern void vmx_wait_io(void);
extern int vmx_setup_platform(struct vcpu *, struct cpu_user_regs *);
extern void vmx_io_assist(struct vcpu *v);
// XXX - think about this -- maybe use bit 30 of the mfn to signify an MMIO frame.
-4
View File
@@ -110,8 +110,4 @@ gnttab_prepare_for_transfer(
void
gnttab_release_dev_mappings(grant_table_t *gt);
/* Extra GNTST_ values, for internal use only. */
#define GNTST_flush_all (2) /* Success, need to flush entire TLB. */
#define GNTST_flush_one (1) /* Success, need to flush a vaddr. */
#endif /* __XEN_GRANT_H__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.