- bnc#801663 - performance of mirror lvm unsuitable for production
block-dmmd - Update to Xen 4.3.0-rc2 - Consolidate all xend and traditional qemu patches into one patch file. Rename '.diff' patches to '.patch' and reoder others. xend-traditional-qemu.patch - Create a xend-tools package for the legacy xend toolstack files - Update to Xen 4.3.0-rc1 c/s 27068 - bnc#818183 - VUL-0: xen: CVE-2013-2007: XSA-51: qga set umask 0077 when daemonizing CVE-2013-2007-xsa51-1.patch CVE-2013-2007-xsa51-2.patch - bnc#808269 - Fully Virtualized Windows VM install is failed on Ivy Bridge platforms with Xen kernel 26754-hvm-Improve-APIC-INIT-SIPI-emulation.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=241
This commit is contained in:
parent
d766d613df
commit
0a0dc9a60d
@ -1,234 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1347371120 -7200
|
||||
# Node ID 51c2d7c83cbc2a0357ce112a463f91d354dcdba9
|
||||
# Parent e4cb8411161043c726f699252cc761e77853e820
|
||||
x86: allow early use of fixmaps
|
||||
|
||||
As a prerequisite for adding an EHCI debug port based console
|
||||
implementation, set up the page tables needed for (a sub-portion of)
|
||||
the fixmaps together with other boot time page table construction.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/boot/head.S
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/boot/head.S
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/boot/head.S
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <public/xen.h>
|
||||
#include <asm/asm_defns.h>
|
||||
#include <asm/desc.h>
|
||||
+#include <asm/fixmap.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
@@ -136,6 +137,9 @@ __start:
|
||||
add $8,%edx
|
||||
add $(1<<L2_PAGETABLE_SHIFT),%eax
|
||||
loop 1b
|
||||
+ /* Initialise L2 fixmap page directory entry. */
|
||||
+ mov $(sym_phys(l1_fixmap)+7),%eax
|
||||
+ mov %eax,sym_phys(l2_fixmap) + l2_table_offset(FIXADDR_TOP-1)*8
|
||||
/* Initialise L3 identity-map page directory entries. */
|
||||
mov $sym_phys(l3_identmap),%edi
|
||||
mov $(sym_phys(l2_identmap)+7),%eax
|
||||
@@ -144,9 +148,11 @@ __start:
|
||||
add $8,%edi
|
||||
add $PAGE_SIZE,%eax
|
||||
loop 1b
|
||||
- /* Initialise L3 xen-map page directory entry. */
|
||||
+ /* Initialise L3 xen-map and fixmap page directory entries. */
|
||||
mov $(sym_phys(l2_xenmap)+7),%eax
|
||||
mov %eax,sym_phys(l3_xenmap) + l3_table_offset(XEN_VIRT_START)*8
|
||||
+ mov $(sym_phys(l2_fixmap)+7),%eax
|
||||
+ mov %eax,sym_phys(l3_xenmap) + l3_table_offset(FIXADDR_TOP-1)*8
|
||||
/* Initialise L3 boot-map page directory entry. */
|
||||
mov $(sym_phys(l2_bootmap)+7),%eax
|
||||
mov %eax,sym_phys(l3_bootmap) + 0*8
|
||||
@@ -172,6 +178,9 @@ __start:
|
||||
add $(1<<L2_PAGETABLE_SHIFT),%eax
|
||||
cmp $(16<<20)+0xe3,%eax
|
||||
jne 1b
|
||||
+ /* Initialise L2 fixmap page directory entry. */
|
||||
+ mov $(sym_phys(l1_fixmap)+7),%eax
|
||||
+ mov %eax,sym_phys(idle_pg_table_l2) + l2_table_offset(FIXADDR_TOP-1)*8
|
||||
#endif
|
||||
|
||||
/* Initialize 4kB mappings of first 2MB or 4MB of memory. */
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/efi/boot.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/efi/boot.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/efi/boot.c
|
||||
@@ -17,6 +17,9 @@
|
||||
#include <xen/vga.h>
|
||||
#include <asm/e820.h>
|
||||
#include <asm/edd.h>
|
||||
+#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
|
||||
+#include <asm/fixmap.h>
|
||||
+#undef __ASSEMBLY__
|
||||
#include <asm/mm.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -1123,14 +1126,19 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||||
slot &= L2_PAGETABLE_ENTRIES - 1;
|
||||
l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE);
|
||||
}
|
||||
+ /* Initialise L2 fixmap page directory entry. */
|
||||
+ l2_fixmap[l2_table_offset(FIXADDR_TOP - 1)] =
|
||||
+ l2e_from_paddr((UINTN)l1_fixmap, __PAGE_HYPERVISOR);
|
||||
/* Initialise L3 identity-map page directory entries. */
|
||||
for ( i = 0; i < ARRAY_SIZE(l2_identmap) / L2_PAGETABLE_ENTRIES; ++i )
|
||||
l3_identmap[i] = l3e_from_paddr((UINTN)(l2_identmap +
|
||||
i * L2_PAGETABLE_ENTRIES),
|
||||
__PAGE_HYPERVISOR);
|
||||
- /* Initialise L3 xen-map page directory entry. */
|
||||
+ /* Initialise L3 xen-map and fixmap page directory entries. */
|
||||
l3_xenmap[l3_table_offset(XEN_VIRT_START)] =
|
||||
l3e_from_paddr((UINTN)l2_xenmap, __PAGE_HYPERVISOR);
|
||||
+ l3_xenmap[l3_table_offset(FIXADDR_TOP - 1)] =
|
||||
+ l3e_from_paddr((UINTN)l2_fixmap, __PAGE_HYPERVISOR);
|
||||
/* Initialise L3 boot-map page directory entries. */
|
||||
l3_bootmap[l3_table_offset(xen_phys_start)] =
|
||||
l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/mm.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/mm.c
|
||||
@@ -131,6 +131,10 @@
|
||||
l1_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
|
||||
l1_identmap[L1_PAGETABLE_ENTRIES];
|
||||
|
||||
+/* Mapping of the fixmap space needed early. */
|
||||
+l1_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
|
||||
+ l1_fixmap[L1_PAGETABLE_ENTRIES];
|
||||
+
|
||||
#define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
|
||||
|
||||
/*
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/x86_64/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/x86_64/mm.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/x86_64/mm.c
|
||||
@@ -65,6 +65,10 @@ l3_pgentry_t __attribute__ ((__section__
|
||||
l2_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
|
||||
l2_xenmap[L2_PAGETABLE_ENTRIES];
|
||||
|
||||
+/* Enough page directories to map the early fixmap space. */
|
||||
+l2_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
|
||||
+ l2_fixmap[L2_PAGETABLE_ENTRIES];
|
||||
+
|
||||
/* Enough page directories to map into the bottom 1GB. */
|
||||
l3_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
|
||||
l3_bootmap[L3_PAGETABLE_ENTRIES];
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/config.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/config.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/config.h
|
||||
@@ -317,7 +317,7 @@ extern unsigned char boot_edid_info[128]
|
||||
#define MACHPHYS_MBYTES 16 /* 1 MB needed per 1 GB memory */
|
||||
#define FRAMETABLE_MBYTES (MACHPHYS_MBYTES * 6)
|
||||
|
||||
-#define IOREMAP_VIRT_END 0UL
|
||||
+#define IOREMAP_VIRT_END _AC(0,UL)
|
||||
#define IOREMAP_VIRT_START (IOREMAP_VIRT_END - (IOREMAP_MBYTES<<20))
|
||||
#define DIRECTMAP_VIRT_END IOREMAP_VIRT_START
|
||||
#define DIRECTMAP_VIRT_START (DIRECTMAP_VIRT_END - (DIRECTMAP_MBYTES<<20))
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/fixmap.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/fixmap.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/fixmap.h
|
||||
@@ -13,12 +13,17 @@
|
||||
#define _ASM_FIXMAP_H
|
||||
|
||||
#include <xen/config.h>
|
||||
+#include <asm/page.h>
|
||||
+
|
||||
+#define FIXADDR_TOP (IOREMAP_VIRT_END - PAGE_SIZE)
|
||||
+
|
||||
+#ifndef __ASSEMBLY__
|
||||
+
|
||||
#include <xen/pfn.h>
|
||||
#include <xen/kexec.h>
|
||||
#include <xen/iommu.h>
|
||||
#include <asm/apicdef.h>
|
||||
#include <asm/acpi.h>
|
||||
-#include <asm/page.h>
|
||||
#include <asm/amd-iommu.h>
|
||||
#include <asm/msi.h>
|
||||
#include <acpi/apei.h>
|
||||
@@ -68,7 +73,6 @@ enum fixed_addresses {
|
||||
__end_of_fixed_addresses
|
||||
};
|
||||
|
||||
-#define FIXADDR_TOP (IOREMAP_VIRT_END - PAGE_SIZE)
|
||||
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
|
||||
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
|
||||
|
||||
@@ -92,4 +96,6 @@ static inline unsigned long virt_to_fix(
|
||||
return __virt_to_fix(vaddr);
|
||||
}
|
||||
|
||||
+#endif /* __ASSEMBLY__ */
|
||||
+
|
||||
#endif
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/page.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/page.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/page.h
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __X86_PAGE_H__
|
||||
#define __X86_PAGE_H__
|
||||
|
||||
+#include <xen/const.h>
|
||||
+
|
||||
/*
|
||||
* It is important that the masks are signed quantities. This ensures that
|
||||
* the compiler sign-extends a 32-bit mask to 64 bits if that is required.
|
||||
@@ -306,13 +308,15 @@ extern l2_pgentry_t idle_pg_table_l2[
|
||||
extern l2_pgentry_t *compat_idle_pg_table_l2;
|
||||
extern unsigned int m2p_compat_vstart;
|
||||
extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES],
|
||||
+ l2_fixmap[L2_PAGETABLE_ENTRIES],
|
||||
l2_bootmap[L2_PAGETABLE_ENTRIES];
|
||||
extern l3_pgentry_t l3_xenmap[L3_PAGETABLE_ENTRIES],
|
||||
l3_identmap[L3_PAGETABLE_ENTRIES],
|
||||
l3_bootmap[L3_PAGETABLE_ENTRIES];
|
||||
#endif
|
||||
extern l2_pgentry_t l2_identmap[4*L2_PAGETABLE_ENTRIES];
|
||||
-extern l1_pgentry_t l1_identmap[L1_PAGETABLE_ENTRIES];
|
||||
+extern l1_pgentry_t l1_identmap[L1_PAGETABLE_ENTRIES],
|
||||
+ l1_fixmap[L1_PAGETABLE_ENTRIES];
|
||||
void paging_init(void);
|
||||
void setup_idle_pagetable(void);
|
||||
#endif /* !defined(__ASSEMBLY__) */
|
||||
Index: xen-4.2.2-testing/xen/include/xen/const.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ xen-4.2.2-testing/xen/include/xen/const.h
|
||||
@@ -0,0 +1,24 @@
|
||||
+/* const.h: Macros for dealing with constants. */
|
||||
+
|
||||
+#ifndef __XEN_CONST_H__
|
||||
+#define __XEN_CONST_H__
|
||||
+
|
||||
+/* Some constant macros are used in both assembler and
|
||||
+ * C code. Therefore we cannot annotate them always with
|
||||
+ * 'UL' and other type specifiers unilaterally. We
|
||||
+ * use the following macros to deal with this.
|
||||
+ *
|
||||
+ * Similarly, _AT() will cast an expression with a type in C, but
|
||||
+ * leave it unchanged in asm.
|
||||
+ */
|
||||
+
|
||||
+#ifdef __ASSEMBLY__
|
||||
+#define _AC(X,Y) X
|
||||
+#define _AT(T,X) X
|
||||
+#else
|
||||
+#define __AC(X,Y) (X##Y)
|
||||
+#define _AC(X,Y) __AC(X,Y)
|
||||
+#define _AT(T,X) ((T)(X))
|
||||
+#endif
|
||||
+
|
||||
+#endif /* __XEN_CONST_H__ */
|
@ -1,144 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1347371236 -7200
|
||||
# Node ID 776a23fa0e938e4cf3307fc2e3b3f1a9488a5927
|
||||
# Parent 51c2d7c83cbc2a0357ce112a463f91d354dcdba9
|
||||
console: prepare for non-COMn port support
|
||||
|
||||
Widen SERHND_IDX (and use it where needed), introduce a flush low level
|
||||
driver method, and remove unnecessary peeking of the common code at the
|
||||
(driver specific) serial port identification string in the "console="
|
||||
command line option value.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/xen/arch/x86/smpboot.c
|
||||
+++ b/xen/arch/x86/smpboot.c
|
||||
@@ -1017,7 +1017,7 @@ void __init smp_intr_init(void)
|
||||
* Also ensure serial interrupts are high priority. We do not
|
||||
* want them to be blocked by unacknowledged guest-bound interrupts.
|
||||
*/
|
||||
- for ( seridx = 0; seridx < 2; seridx++ )
|
||||
+ for ( seridx = 0; seridx <= SERHND_IDX; seridx++ )
|
||||
{
|
||||
if ( (irq = serial_irq(seridx)) < 0 )
|
||||
continue;
|
||||
--- a/xen/drivers/char/console.c
|
||||
+++ b/xen/drivers/char/console.c
|
||||
@@ -539,6 +539,7 @@ void printk(const char *fmt, ...)
|
||||
void __init console_init_preirq(void)
|
||||
{
|
||||
char *p;
|
||||
+ int sh;
|
||||
|
||||
serial_init_preirq();
|
||||
|
||||
@@ -551,8 +552,9 @@ void __init console_init_preirq(void)
|
||||
vga_init();
|
||||
else if ( !strncmp(p, "none", 4) )
|
||||
continue;
|
||||
- else if ( strncmp(p, "com", 3) ||
|
||||
- (sercon_handle = serial_parse_handle(p)) == -1 )
|
||||
+ else if ( (sh = serial_parse_handle(p)) >= 0 )
|
||||
+ sercon_handle = sh;
|
||||
+ else
|
||||
{
|
||||
char *q = strchr(p, ',');
|
||||
if ( q != NULL )
|
||||
--- a/xen/drivers/char/serial.c
|
||||
+++ b/xen/drivers/char/serial.c
|
||||
@@ -22,9 +22,11 @@ size_param("serial_tx_buffer", serial_tx
|
||||
#define mask_serial_rxbuf_idx(_i) ((_i)&(serial_rxbufsz-1))
|
||||
#define mask_serial_txbuf_idx(_i) ((_i)&(serial_txbufsz-1))
|
||||
|
||||
-static struct serial_port com[2] = {
|
||||
- { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED },
|
||||
- { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED }
|
||||
+static struct serial_port com[SERHND_IDX + 1] = {
|
||||
+ [0 ... SERHND_IDX] = {
|
||||
+ .rx_lock = SPIN_LOCK_UNLOCKED,
|
||||
+ .tx_lock = SPIN_LOCK_UNLOCKED
|
||||
+ }
|
||||
};
|
||||
|
||||
void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
|
||||
@@ -81,6 +83,8 @@ void serial_tx_interrupt(struct serial_p
|
||||
port->driver->putc(
|
||||
port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
|
||||
}
|
||||
+ if ( i && port->driver->flush )
|
||||
+ port->driver->flush(port);
|
||||
}
|
||||
|
||||
spin_unlock(&port->tx_lock);
|
||||
@@ -175,6 +179,9 @@ void serial_putc(int handle, char c)
|
||||
|
||||
__serial_putc(port, c);
|
||||
|
||||
+ if ( port->driver->flush )
|
||||
+ port->driver->flush(port);
|
||||
+
|
||||
spin_unlock_irqrestore(&port->tx_lock, flags);
|
||||
}
|
||||
|
||||
@@ -206,6 +213,9 @@ void serial_puts(int handle, const char
|
||||
__serial_putc(port, c);
|
||||
}
|
||||
|
||||
+ if ( port->driver->flush )
|
||||
+ port->driver->flush(port);
|
||||
+
|
||||
spin_unlock_irqrestore(&port->tx_lock, flags);
|
||||
}
|
||||
|
||||
@@ -261,10 +271,10 @@ int __init serial_parse_handle(char *con
|
||||
switch ( conf[3] )
|
||||
{
|
||||
case '1':
|
||||
- handle = 0;
|
||||
+ handle = SERHND_COM1;
|
||||
break;
|
||||
case '2':
|
||||
- handle = 1;
|
||||
+ handle = SERHND_COM2;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
@@ -365,6 +375,8 @@ void serial_start_sync(int handle)
|
||||
port->driver->putc(
|
||||
port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
|
||||
}
|
||||
+ if ( port->driver->flush )
|
||||
+ port->driver->flush(port);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&port->tx_lock, flags);
|
||||
--- a/xen/include/xen/serial.h
|
||||
+++ b/xen/include/xen/serial.h
|
||||
@@ -60,6 +60,8 @@ struct uart_driver {
|
||||
int (*tx_empty)(struct serial_port *);
|
||||
/* Put a character onto the serial line. */
|
||||
void (*putc)(struct serial_port *, char);
|
||||
+ /* Flush accumulated characters. */
|
||||
+ void (*flush)(struct serial_port *);
|
||||
/* Get a character from the serial line: returns 0 if none available. */
|
||||
int (*getc)(struct serial_port *, char *);
|
||||
/* Get IRQ number for this port's serial line: returns -1 if none. */
|
||||
@@ -67,10 +69,12 @@ struct uart_driver {
|
||||
};
|
||||
|
||||
/* 'Serial handles' are composed from the following fields. */
|
||||
-#define SERHND_IDX (1<<0) /* COM1 or COM2? */
|
||||
-#define SERHND_HI (1<<1) /* Mux/demux each transferred char by MSB. */
|
||||
-#define SERHND_LO (1<<2) /* Ditto, except that the MSB is cleared. */
|
||||
-#define SERHND_COOKED (1<<3) /* Newline/carriage-return translation? */
|
||||
+#define SERHND_IDX (3<<0) /* COM1 or COM2? */
|
||||
+# define SERHND_COM1 (0<<0)
|
||||
+# define SERHND_COM2 (1<<0)
|
||||
+#define SERHND_HI (1<<2) /* Mux/demux each transferred char by MSB. */
|
||||
+#define SERHND_LO (1<<3) /* Ditto, except that the MSB is cleared. */
|
||||
+#define SERHND_COOKED (1<<4) /* Newline/carriage-return translation? */
|
||||
|
||||
/* Two-stage initialisation (before/after IRQ-subsystem initialisation). */
|
||||
void serial_init_preirq(void);
|
File diff suppressed because it is too large
Load Diff
@ -1,142 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1347371512 -7200
|
||||
# Node ID e1380b5311ccee14eb47d7badb75339933d42249
|
||||
# Parent 0d0c55a1975db9c6cac2e9259b5ebea7a7bdbaec
|
||||
serial: avoid fully initializing unused consoles
|
||||
|
||||
Defer calling the drivers' post-IRQ initialization functions (generally
|
||||
doing allocation of transmit buffers) until it is known that the
|
||||
respective console is actually going to be used.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/xen/drivers/char/ehci-dbgp.c
|
||||
+++ b/xen/drivers/char/ehci-dbgp.c
|
||||
@@ -1391,7 +1391,8 @@ static int ehci_dbgp_check_release(struc
|
||||
printk(XENLOG_INFO "Releasing EHCI debug port at %02x:%02x.%u\n",
|
||||
dbgp->bus, dbgp->slot, dbgp->func);
|
||||
|
||||
- kill_timer(&dbgp->timer);
|
||||
+ if ( dbgp->timer.function )
|
||||
+ kill_timer(&dbgp->timer);
|
||||
dbgp->ehci_debug = NULL;
|
||||
|
||||
ctrl = readl(&ehci_debug->control);
|
||||
--- a/xen/drivers/char/serial.c
|
||||
+++ b/xen/drivers/char/serial.c
|
||||
@@ -29,6 +29,8 @@ static struct serial_port com[SERHND_IDX
|
||||
}
|
||||
};
|
||||
|
||||
+static bool_t __read_mostly post_irq;
|
||||
+
|
||||
void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
|
||||
{
|
||||
char c;
|
||||
@@ -263,14 +265,12 @@ char serial_getc(int handle)
|
||||
|
||||
int __init serial_parse_handle(char *conf)
|
||||
{
|
||||
- int handle;
|
||||
+ int handle, flags = 0;
|
||||
|
||||
if ( !strncmp(conf, "dbgp", 4) && (!conf[4] || conf[4] == ',') )
|
||||
{
|
||||
- if ( !com[SERHND_DBGP].driver )
|
||||
- goto fail;
|
||||
-
|
||||
- return SERHND_DBGP | SERHND_COOKED;
|
||||
+ handle = SERHND_DBGP;
|
||||
+ goto common;
|
||||
}
|
||||
|
||||
if ( strncmp(conf, "com", 3) )
|
||||
@@ -288,17 +288,25 @@ int __init serial_parse_handle(char *con
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- if ( !com[handle].driver )
|
||||
- goto fail;
|
||||
-
|
||||
if ( conf[4] == 'H' )
|
||||
- handle |= SERHND_HI;
|
||||
+ flags |= SERHND_HI;
|
||||
else if ( conf[4] == 'L' )
|
||||
- handle |= SERHND_LO;
|
||||
+ flags |= SERHND_LO;
|
||||
|
||||
- handle |= SERHND_COOKED;
|
||||
+ common:
|
||||
+ if ( !com[handle].driver )
|
||||
+ goto fail;
|
||||
+
|
||||
+ if ( !post_irq )
|
||||
+ com[handle].state = serial_parsed;
|
||||
+ else if ( com[handle].state != serial_initialized )
|
||||
+ {
|
||||
+ if ( com[handle].driver->init_postirq )
|
||||
+ com[handle].driver->init_postirq(&com[handle]);
|
||||
+ com[handle].state = serial_initialized;
|
||||
+ }
|
||||
|
||||
- return handle;
|
||||
+ return handle | flags | SERHND_COOKED;
|
||||
|
||||
fail:
|
||||
return -1;
|
||||
@@ -450,8 +458,13 @@ void __init serial_init_postirq(void)
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < ARRAY_SIZE(com); i++ )
|
||||
- if ( com[i].driver && com[i].driver->init_postirq )
|
||||
- com[i].driver->init_postirq(&com[i]);
|
||||
+ if ( com[i].state == serial_parsed )
|
||||
+ {
|
||||
+ if ( com[i].driver->init_postirq )
|
||||
+ com[i].driver->init_postirq(&com[i]);
|
||||
+ com[i].state = serial_initialized;
|
||||
+ }
|
||||
+ post_irq = 1;
|
||||
}
|
||||
|
||||
void __init serial_endboot(void)
|
||||
@@ -475,7 +488,7 @@ void serial_suspend(void)
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < ARRAY_SIZE(com); i++ )
|
||||
- if ( com[i].driver && com[i].driver->suspend )
|
||||
+ if ( com[i].state == serial_initialized && com[i].driver->suspend )
|
||||
com[i].driver->suspend(&com[i]);
|
||||
}
|
||||
|
||||
@@ -483,7 +496,7 @@ void serial_resume(void)
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < ARRAY_SIZE(com); i++ )
|
||||
- if ( com[i].driver && com[i].driver->resume )
|
||||
+ if ( com[i].state == serial_initialized && com[i].driver->resume )
|
||||
com[i].driver->resume(&com[i]);
|
||||
}
|
||||
|
||||
--- a/xen/include/xen/serial.h
|
||||
+++ b/xen/include/xen/serial.h
|
||||
@@ -25,10 +25,17 @@ extern unsigned int serial_txbufsz;
|
||||
|
||||
struct uart_driver;
|
||||
|
||||
+enum serial_port_state {
|
||||
+ serial_unused,
|
||||
+ serial_parsed,
|
||||
+ serial_initialized
|
||||
+};
|
||||
+
|
||||
struct serial_port {
|
||||
/* Uart-driver parameters. */
|
||||
struct uart_driver *driver;
|
||||
void *uart;
|
||||
+ enum serial_port_state state;
|
||||
/* Number of characters the port can hold for transmit. */
|
||||
int tx_fifo_size;
|
||||
/* Transmit data buffer (interrupt-driven uart). */
|
@ -1,56 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1347371733 -7200
|
||||
# Node ID ee12dc357fbecbb0517798f395d14bf1764c6766
|
||||
# Parent 5fb5b3b70e34ef278d06aff27878b4b8e6d9145f
|
||||
ns16550: PCI initialization adjustments
|
||||
|
||||
Besides single-port serial cards, also accept multi-port ones and such
|
||||
providing mixed functionality (e.g. also having a parallel port).
|
||||
|
||||
Reading PCI_INTERRUPT_PIN before ACPI gets enabled generally produces
|
||||
an incorrect IRQ (below 16, whereas after enabling ACPI it frequently
|
||||
would end up at a higher one), so this is useful (almost) only when a
|
||||
system already boots in ACPI mode.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/xen/drivers/char/ns16550.c
|
||||
+++ b/xen/drivers/char/ns16550.c
|
||||
@@ -449,7 +449,6 @@ static int __init check_existence(struct
|
||||
static int
|
||||
pci_uart_config (struct ns16550 *uart, int skip_amt, int bar_idx)
|
||||
{
|
||||
- uint16_t class;
|
||||
uint32_t bar, len;
|
||||
int b, d, f;
|
||||
|
||||
@@ -460,9 +459,15 @@ pci_uart_config (struct ns16550 *uart, i
|
||||
{
|
||||
for ( f = 0; f < 0x8; f++ )
|
||||
{
|
||||
- class = pci_conf_read16(0, b, d, f, PCI_CLASS_DEVICE);
|
||||
- if ( class != 0x700 )
|
||||
+ switch ( pci_conf_read16(0, b, d, f, PCI_CLASS_DEVICE) )
|
||||
+ {
|
||||
+ case 0x0700: /* single port serial */
|
||||
+ case 0x0702: /* multi port serial */
|
||||
+ case 0x0780: /* other (e.g serial+parallel) */
|
||||
+ break;
|
||||
+ default:
|
||||
continue;
|
||||
+ }
|
||||
|
||||
bar = pci_conf_read32(0, b, d, f,
|
||||
PCI_BASE_ADDRESS_0 + bar_idx*4);
|
||||
@@ -485,7 +490,8 @@ pci_uart_config (struct ns16550 *uart, i
|
||||
uart->bar = bar;
|
||||
uart->bar_idx = bar_idx;
|
||||
uart->io_base = bar & 0xfffe;
|
||||
- uart->irq = 0;
|
||||
+ uart->irq = pci_conf_read8(0, b, d, f, PCI_INTERRUPT_PIN) ?
|
||||
+ pci_conf_read8(0, b, d, f, PCI_INTERRUPT_LINE) : 0;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1347371805 -7200
|
||||
# Node ID b22f184e1a3cac03abeed92ec4b74235fd0881f4
|
||||
# Parent ee12dc357fbecbb0517798f395d14bf1764c6766
|
||||
ns16550: command line parsing adjustments
|
||||
|
||||
Allow intermediate parts of the command line options to be absent
|
||||
(expressed by two immediately succeeding commas).
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/docs/misc/xen-command-line.markdown
|
||||
+++ b/docs/misc/xen-command-line.markdown
|
||||
@@ -199,7 +199,7 @@ If set, override Xen's calculation of th
|
||||
If set, override Xen's default choice for the platform timer.
|
||||
|
||||
### com1,com2
|
||||
-> `= <baud>[/<clock_hz>][,DPS[,<io-base>[,<irq>[,<port-bdf>[,<bridge-bdf>]]]] | pci | amt ] `
|
||||
+> `= <baud>[/<clock_hz>][,[DPS][,[<io-base>|pci|amt][,[<irq>][,[<port-bdf>][,[<bridge-bdf>]]]]]]`
|
||||
|
||||
Both option `com1` and `com2` follow the same format.
|
||||
|
||||
--- a/xen/drivers/char/ns16550.c
|
||||
+++ b/xen/drivers/char/ns16550.c
|
||||
@@ -536,26 +536,23 @@ static void __init ns16550_parse_port_co
|
||||
else if ( (baud = simple_strtoul(conf, &conf, 10)) != 0 )
|
||||
uart->baud = baud;
|
||||
|
||||
- if ( *conf == '/')
|
||||
+ if ( *conf == '/' )
|
||||
{
|
||||
conf++;
|
||||
uart->clock_hz = simple_strtoul(conf, &conf, 0) << 4;
|
||||
}
|
||||
|
||||
- if ( *conf != ',' )
|
||||
- goto config_parsed;
|
||||
- conf++;
|
||||
-
|
||||
- uart->data_bits = simple_strtoul(conf, &conf, 10);
|
||||
+ if ( *conf == ',' && *++conf != ',' )
|
||||
+ {
|
||||
+ uart->data_bits = simple_strtoul(conf, &conf, 10);
|
||||
|
||||
- uart->parity = parse_parity_char(*conf);
|
||||
- conf++;
|
||||
+ uart->parity = parse_parity_char(*conf);
|
||||
|
||||
- uart->stop_bits = simple_strtoul(conf, &conf, 10);
|
||||
+ uart->stop_bits = simple_strtoul(conf + 1, &conf, 10);
|
||||
+ }
|
||||
|
||||
- if ( *conf == ',' )
|
||||
+ if ( *conf == ',' && *++conf != ',' )
|
||||
{
|
||||
- conf++;
|
||||
if ( strncmp(conf, "pci", 3) == 0 )
|
||||
{
|
||||
if ( pci_uart_config(uart, 1/* skip AMT */, uart - ns16550_com) )
|
||||
@@ -572,24 +569,21 @@ static void __init ns16550_parse_port_co
|
||||
{
|
||||
uart->io_base = simple_strtoul(conf, &conf, 0);
|
||||
}
|
||||
+ }
|
||||
|
||||
- if ( *conf == ',' )
|
||||
- {
|
||||
- conf++;
|
||||
- uart->irq = simple_strtoul(conf, &conf, 10);
|
||||
- if ( *conf == ',' )
|
||||
- {
|
||||
- conf++;
|
||||
- uart->ps_bdf_enable = 1;
|
||||
- parse_pci_bdf(&conf, &uart->ps_bdf[0]);
|
||||
- if ( *conf == ',' )
|
||||
- {
|
||||
- conf++;
|
||||
- uart->pb_bdf_enable = 1;
|
||||
- parse_pci_bdf(&conf, &uart->pb_bdf[0]);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ if ( *conf == ',' && *++conf != ',' )
|
||||
+ uart->irq = simple_strtol(conf, &conf, 10);
|
||||
+
|
||||
+ if ( *conf == ',' && *++conf != ',' )
|
||||
+ {
|
||||
+ uart->ps_bdf_enable = 1;
|
||||
+ parse_pci_bdf(&conf, &uart->ps_bdf[0]);
|
||||
+ }
|
||||
+
|
||||
+ if ( *conf == ',' && *++conf != ',' )
|
||||
+ {
|
||||
+ uart->pb_bdf_enable = 1;
|
||||
+ parse_pci_bdf(&conf, &uart->pb_bdf[0]);
|
||||
}
|
||||
|
||||
config_parsed:
|
@ -1,70 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1347437974 -7200
|
||||
# Node ID 8c0aa97d529a55de2ab96be1a5a6e9ed6a9c6bf0
|
||||
# Parent ac8f4afccd6c6786a3fd5691e8b0c9b38c47e994
|
||||
x86-64/EFI: allow chaining of config files
|
||||
|
||||
Namely when making use the CONFIG_XEN_COMPAT_* options in the legacy
|
||||
Linux kernels, newer kernels may not be compatible with older
|
||||
hypervisors, so trying to boot such a combination makes little sense.
|
||||
Booting older kernels on newer hypervisors, however, has to always
|
||||
work.
|
||||
|
||||
With the way xen.efi looks for its configuration file, allowing
|
||||
individual configuration files to refer only to compatible kernels,
|
||||
and referring from an older- to a newer-hypervisor one (the kernels
|
||||
of which will, as said, necessarily be compatible with the older
|
||||
hypervisor) allows to greatly reduce redundancy at least in
|
||||
development environments where one frequently wants multiple
|
||||
hypervisors and kernles to be installed in parallel.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/docs/misc/efi.markdown
|
||||
+++ b/docs/misc/efi.markdown
|
||||
@@ -75,6 +75,13 @@ Specifies an XSM module to load.
|
||||
|
||||
Specifies a CPU microcode blob to load.
|
||||
|
||||
+###`chain=<filename>`
|
||||
+
|
||||
+Specifies an alternate configuration file to use in case the specified section
|
||||
+(and in particular its `kernel=` setting) can't be found in the default (or
|
||||
+specified) configuration file. This is only meaningful in the [global] section
|
||||
+and really not meant to be used together with the `-cfg=` command line option.
|
||||
+
|
||||
Filenames must be specified relative to the location of the EFI binary.
|
||||
|
||||
Extra options to be passed to Xen can also be specified on the command line,
|
||||
--- a/xen/arch/x86/efi/boot.c
|
||||
+++ b/xen/arch/x86/efi/boot.c
|
||||
@@ -797,7 +797,26 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||||
else
|
||||
section.s = get_value(&cfg, "global", "default");
|
||||
|
||||
- name.s = get_value(&cfg, section.s, "kernel");
|
||||
+ for ( ; ; )
|
||||
+ {
|
||||
+ name.s = get_value(&cfg, section.s, "kernel");
|
||||
+ if ( name.s )
|
||||
+ break;
|
||||
+ name.s = get_value(&cfg, "global", "chain");
|
||||
+ if ( !name.s )
|
||||
+ break;
|
||||
+ efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
|
||||
+ cfg.addr = 0;
|
||||
+ if ( !read_file(dir_handle, s2w(&name), &cfg) )
|
||||
+ {
|
||||
+ PrintStr(L"Chained configuration file '");
|
||||
+ PrintStr(name.w);
|
||||
+ efi_bs->FreePool(name.w);
|
||||
+ blexit(L"'not found\r\n");
|
||||
+ }
|
||||
+ pre_parse(&cfg);
|
||||
+ efi_bs->FreePool(name.w);
|
||||
+ }
|
||||
if ( !name.s )
|
||||
blexit(L"No Dom0 kernel image specified\r\n");
|
||||
split_value(name.s);
|
@ -1,630 +0,0 @@
|
||||
References: bnc#780401
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1347869399 -7200
|
||||
# Node ID 51408c3528030309e8f064bf6a3c96b37de7dc96
|
||||
# Parent 12fa949b90603f057d458e370284471412afb0ba
|
||||
xenpm: make argument parsing and error handling more consistent
|
||||
|
||||
Specifically, what values are or aren't accepted as CPU identifier, and
|
||||
how the values get interpreted should be consistent across sub-commands
|
||||
(intended behavior now: non-negative values are okay, and along with
|
||||
omitting the argument, specifying "all" will also be accepted).
|
||||
|
||||
For error handling, error messages should get consistently issued to
|
||||
stderr, and the tool should now (hopefully) produce an exit code of
|
||||
zero only in the (partial) success case (there may still be a small
|
||||
number of questionable cases).
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/tools/misc/xenpm.c
|
||||
+++ b/tools/misc/xenpm.c
|
||||
@@ -36,7 +36,7 @@
|
||||
#define CPUFREQ_TURBO_ENABLED 1
|
||||
|
||||
static xc_interface *xc_handle;
|
||||
-static int max_cpu_nr;
|
||||
+static unsigned int max_cpu_nr;
|
||||
|
||||
/* help message */
|
||||
void show_help(void)
|
||||
@@ -77,6 +77,33 @@ void help_func(int argc, char *argv[])
|
||||
show_help();
|
||||
}
|
||||
|
||||
+static void parse_cpuid(const char *arg, int *cpuid)
|
||||
+{
|
||||
+ if ( sscanf(arg, "%d", cpuid) != 1 || *cpuid < 0 )
|
||||
+ {
|
||||
+ if ( strcasecmp(arg, "all") )
|
||||
+ {
|
||||
+ fprintf(stderr, "Invalid CPU identifier: '%s'\n", arg);
|
||||
+ exit(EINVAL);
|
||||
+ }
|
||||
+ *cpuid = -1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void parse_cpuid_and_int(int argc, char *argv[],
|
||||
+ int *cpuid, int *val, const char *what)
|
||||
+{
|
||||
+ if ( argc > 1 )
|
||||
+ parse_cpuid(argv[0], cpuid);
|
||||
+
|
||||
+ if ( argc == 0 || sscanf(argv[argc > 1], "%d", val) != 1 )
|
||||
+ {
|
||||
+ fprintf(stderr, argc ? "Invalid %s '%s'\n" : "Missing %s\n",
|
||||
+ what, argv[argc > 1]);
|
||||
+ exit(EINVAL);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
|
||||
{
|
||||
int i;
|
||||
@@ -166,7 +193,8 @@ static int show_cxstat_by_cpuid(xc_inter
|
||||
if ( ret )
|
||||
{
|
||||
if ( ret == -ENODEV )
|
||||
- printf("Either xen cpuidle is disabled or no valid information is registered!\n");
|
||||
+ fprintf(stderr,
|
||||
+ "Either Xen cpuidle is disabled or no valid information is registered!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -181,11 +209,8 @@ void cxstat_func(int argc, char *argv[])
|
||||
{
|
||||
int cpuid = -1;
|
||||
|
||||
- if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
|
||||
- cpuid = -1;
|
||||
-
|
||||
- if ( cpuid >= max_cpu_nr )
|
||||
- cpuid = -1;
|
||||
+ if ( argc > 0 )
|
||||
+ parse_cpuid(argv[0], &cpuid);
|
||||
|
||||
show_max_cstate(xc_handle);
|
||||
|
||||
@@ -294,11 +319,8 @@ void pxstat_func(int argc, char *argv[])
|
||||
{
|
||||
int cpuid = -1;
|
||||
|
||||
- if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
|
||||
- cpuid = -1;
|
||||
-
|
||||
- if ( cpuid >= max_cpu_nr )
|
||||
- cpuid = -1;
|
||||
+ if ( argc > 0 )
|
||||
+ parse_cpuid(argv[0], &cpuid);
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
@@ -338,10 +360,10 @@ static void signal_int_handler(int signo
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if ( gettimeofday(&tv, NULL) == -1 )
|
||||
+ if ( gettimeofday(&tv, NULL) )
|
||||
{
|
||||
fprintf(stderr, "failed to get timeofday\n");
|
||||
- goto out ;
|
||||
+ goto out;
|
||||
}
|
||||
usec_end = tv.tv_sec * 1000000UL + tv.tv_usec;
|
||||
|
||||
@@ -541,7 +563,7 @@ void start_gather_func(int argc, char *a
|
||||
printf("Timeout set to %d seconds\n", timeout);
|
||||
}
|
||||
|
||||
- if ( gettimeofday(&tv, NULL) == -1 )
|
||||
+ if ( gettimeofday(&tv, NULL) )
|
||||
{
|
||||
fprintf(stderr, "failed to get timeofday\n");
|
||||
return ;
|
||||
@@ -766,11 +788,8 @@ void cpufreq_para_func(int argc, char *a
|
||||
{
|
||||
int cpuid = -1;
|
||||
|
||||
- if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
|
||||
- cpuid = -1;
|
||||
-
|
||||
- if ( cpuid >= max_cpu_nr )
|
||||
- cpuid = -1;
|
||||
+ if ( argc > 0 )
|
||||
+ parse_cpuid(argv[0], &cpuid);
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
@@ -788,26 +807,22 @@ void scaling_max_freq_func(int argc, cha
|
||||
{
|
||||
int cpuid = -1, freq = -1;
|
||||
|
||||
- if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 ||
|
||||
- sscanf(argv[0], "%d", &cpuid) != 1)) ||
|
||||
- (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) ||
|
||||
- argc == 0 )
|
||||
- {
|
||||
- fprintf(stderr, "failed to set scaling max freq\n");
|
||||
- return ;
|
||||
- }
|
||||
+ parse_cpuid_and_int(argc, argv, &cpuid, &freq, "frequency");
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < max_cpu_nr; i++ )
|
||||
if ( xc_set_cpufreq_para(xc_handle, i, SCALING_MAX_FREQ, freq) )
|
||||
- fprintf(stderr, "[CPU%d] failed to set scaling max freq\n", i);
|
||||
+ fprintf(stderr,
|
||||
+ "[CPU%d] failed to set scaling max freq (%d - %s)\n",
|
||||
+ i, errno, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_MAX_FREQ, freq) )
|
||||
- fprintf(stderr, "failed to set scaling max freq\n");
|
||||
+ fprintf(stderr, "failed to set scaling max freq (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -815,26 +830,22 @@ void scaling_min_freq_func(int argc, cha
|
||||
{
|
||||
int cpuid = -1, freq = -1;
|
||||
|
||||
- if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 ||
|
||||
- sscanf(argv[0], "%d", &cpuid) != 1) ) ||
|
||||
- (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) ||
|
||||
- argc == 0 )
|
||||
- {
|
||||
- fprintf(stderr, "failed to set scaling min freq\n");
|
||||
- return ;
|
||||
- }
|
||||
+ parse_cpuid_and_int(argc, argv, &cpuid, &freq, "frequency");
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < max_cpu_nr; i++ )
|
||||
if ( xc_set_cpufreq_para(xc_handle, i, SCALING_MIN_FREQ, freq) )
|
||||
- fprintf(stderr, "[CPU%d] failed to set scaling min freq\n", i);
|
||||
+ fprintf(stderr,
|
||||
+ "[CPU%d] failed to set scaling min freq (%d - %s)\n",
|
||||
+ i, errno, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_MIN_FREQ, freq) )
|
||||
- fprintf(stderr, "failed to set scaling min freq\n");
|
||||
+ fprintf(stderr, "failed to set scaling min freq (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,26 +853,22 @@ void scaling_speed_func(int argc, char *
|
||||
{
|
||||
int cpuid = -1, speed = -1;
|
||||
|
||||
- if ( (argc >= 2 && (sscanf(argv[1], "%d", &speed) != 1 ||
|
||||
- sscanf(argv[0], "%d", &cpuid) != 1) ) ||
|
||||
- (argc == 1 && sscanf(argv[0], "%d", &speed) != 1 ) ||
|
||||
- argc == 0 )
|
||||
- {
|
||||
- fprintf(stderr, "failed to set scaling speed\n");
|
||||
- return ;
|
||||
- }
|
||||
+ parse_cpuid_and_int(argc, argv, &cpuid, &speed, "speed");
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < max_cpu_nr; i++ )
|
||||
if ( xc_set_cpufreq_para(xc_handle, i, SCALING_SETSPEED, speed) )
|
||||
- fprintf(stderr, "[CPU%d] failed to set scaling speed\n", i);
|
||||
+ fprintf(stderr,
|
||||
+ "[CPU%d] failed to set scaling speed (%d - %s)\n",
|
||||
+ i, errno, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_SETSPEED, speed) )
|
||||
- fprintf(stderr, "failed to set scaling speed\n");
|
||||
+ fprintf(stderr, "failed to set scaling speed (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,14 +876,7 @@ void scaling_sampling_rate_func(int argc
|
||||
{
|
||||
int cpuid = -1, rate = -1;
|
||||
|
||||
- if ( (argc >= 2 && (sscanf(argv[1], "%d", &rate) != 1 ||
|
||||
- sscanf(argv[0], "%d", &cpuid) != 1) ) ||
|
||||
- (argc == 1 && sscanf(argv[0], "%d", &rate) != 1 ) ||
|
||||
- argc == 0 )
|
||||
- {
|
||||
- fprintf(stderr, "failed to set scaling sampling rate\n");
|
||||
- return ;
|
||||
- }
|
||||
+ parse_cpuid_and_int(argc, argv, &cpuid, &rate, "rate");
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
@@ -884,12 +884,14 @@ void scaling_sampling_rate_func(int argc
|
||||
for ( i = 0; i < max_cpu_nr; i++ )
|
||||
if ( xc_set_cpufreq_para(xc_handle, i, SAMPLING_RATE, rate) )
|
||||
fprintf(stderr,
|
||||
- "[CPU%d] failed to set scaling sampling rate\n", i);
|
||||
+ "[CPU%d] failed to set scaling sampling rate (%d - %s)\n",
|
||||
+ i, errno, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( xc_set_cpufreq_para(xc_handle, cpuid, SAMPLING_RATE, rate) )
|
||||
- fprintf(stderr, "failed to set scaling sampling rate\n");
|
||||
+ fprintf(stderr, "failed to set scaling sampling rate (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -897,14 +899,7 @@ void scaling_up_threshold_func(int argc,
|
||||
{
|
||||
int cpuid = -1, threshold = -1;
|
||||
|
||||
- if ( (argc >= 2 && (sscanf(argv[1], "%d", &threshold) != 1 ||
|
||||
- sscanf(argv[0], "%d", &cpuid) != 1) ) ||
|
||||
- (argc == 1 && sscanf(argv[0], "%d", &threshold) != 1 ) ||
|
||||
- argc == 0 )
|
||||
- {
|
||||
- fprintf(stderr, "failed to set up scaling threshold\n");
|
||||
- return ;
|
||||
- }
|
||||
+ parse_cpuid_and_int(argc, argv, &cpuid, &threshold, "threshold");
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
@@ -912,57 +907,49 @@ void scaling_up_threshold_func(int argc,
|
||||
for ( i = 0; i < max_cpu_nr; i++ )
|
||||
if ( xc_set_cpufreq_para(xc_handle, i, UP_THRESHOLD, threshold) )
|
||||
fprintf(stderr,
|
||||
- "[CPU%d] failed to set up scaling threshold\n", i);
|
||||
+ "[CPU%d] failed to set up scaling threshold (%d - %s)\n",
|
||||
+ i, errno, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( xc_set_cpufreq_para(xc_handle, cpuid, UP_THRESHOLD, threshold) )
|
||||
- fprintf(stderr, "failed to set up scaling threshold\n");
|
||||
+ fprintf(stderr, "failed to set up scaling threshold (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void scaling_governor_func(int argc, char *argv[])
|
||||
{
|
||||
int cpuid = -1;
|
||||
- char *name = NULL;
|
||||
+ char *name;
|
||||
|
||||
if ( argc >= 2 )
|
||||
{
|
||||
- name = strdup(argv[1]);
|
||||
- if ( name == NULL )
|
||||
- goto out;
|
||||
- if ( sscanf(argv[0], "%d", &cpuid) != 1 )
|
||||
- {
|
||||
- free(name);
|
||||
- goto out;
|
||||
- }
|
||||
+ parse_cpuid(argv[0], &cpuid);
|
||||
+ name = argv[1];
|
||||
}
|
||||
else if ( argc > 0 )
|
||||
+ name = argv[0];
|
||||
+ else
|
||||
{
|
||||
- name = strdup(argv[0]);
|
||||
- if ( name == NULL )
|
||||
- goto out;
|
||||
+ fprintf(stderr, "Missing argument(s)\n");
|
||||
+ exit(EINVAL);
|
||||
}
|
||||
- else
|
||||
- goto out;
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < max_cpu_nr; i++ )
|
||||
if ( xc_set_cpufreq_gov(xc_handle, i, name) )
|
||||
- fprintf(stderr, "[CPU%d] failed to set governor name\n", i);
|
||||
+ fprintf(stderr, "[CPU%d] failed to set governor name (%d - %s)\n",
|
||||
+ i, errno, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( xc_set_cpufreq_gov(xc_handle, cpuid, name) )
|
||||
- fprintf(stderr, "failed to set governor name\n");
|
||||
+ fprintf(stderr, "failed to set governor name (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
-
|
||||
- free(name);
|
||||
- return ;
|
||||
-out:
|
||||
- fprintf(stderr, "failed to set governor name\n");
|
||||
}
|
||||
|
||||
void cpu_topology_func(int argc, char *argv[])
|
||||
@@ -971,7 +958,7 @@ void cpu_topology_func(int argc, char *a
|
||||
DECLARE_HYPERCALL_BUFFER(uint32_t, cpu_to_socket);
|
||||
DECLARE_HYPERCALL_BUFFER(uint32_t, cpu_to_node);
|
||||
xc_topologyinfo_t info = { 0 };
|
||||
- int i;
|
||||
+ int i, rc = ENOMEM;
|
||||
|
||||
cpu_to_core = xc_hypercall_buffer_alloc(xc_handle, cpu_to_core, sizeof(*cpu_to_core) * MAX_NR_CPU);
|
||||
cpu_to_socket = xc_hypercall_buffer_alloc(xc_handle, cpu_to_socket, sizeof(*cpu_to_socket) * MAX_NR_CPU);
|
||||
@@ -990,7 +977,9 @@ void cpu_topology_func(int argc, char *a
|
||||
|
||||
if ( xc_topologyinfo(xc_handle, &info) )
|
||||
{
|
||||
- printf("Can not get Xen CPU topology: %d\n", errno);
|
||||
+ rc = errno;
|
||||
+ fprintf(stderr, "Cannot get Xen CPU topology (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1005,116 +994,95 @@ void cpu_topology_func(int argc, char *a
|
||||
printf("CPU%d\t %d\t %d\t %d\n",
|
||||
i, cpu_to_core[i], cpu_to_socket[i], cpu_to_node[i]);
|
||||
}
|
||||
+ rc = 0;
|
||||
out:
|
||||
xc_hypercall_buffer_free(xc_handle, cpu_to_core);
|
||||
xc_hypercall_buffer_free(xc_handle, cpu_to_socket);
|
||||
xc_hypercall_buffer_free(xc_handle, cpu_to_node);
|
||||
+ if ( rc )
|
||||
+ exit(rc);
|
||||
}
|
||||
|
||||
void set_sched_smt_func(int argc, char *argv[])
|
||||
{
|
||||
- int value, rc;
|
||||
+ int value;
|
||||
|
||||
- if (argc != 1){
|
||||
- show_help();
|
||||
- exit(-1);
|
||||
+ if ( argc != 1 ) {
|
||||
+ fprintf(stderr, "Missing or invalid argument(s)\n");
|
||||
+ exit(EINVAL);
|
||||
}
|
||||
|
||||
- if ( !strncmp(argv[0], "disable", sizeof("disable")) )
|
||||
- {
|
||||
+ if ( !strcasecmp(argv[0], "disable") )
|
||||
value = 0;
|
||||
- }
|
||||
- else if ( !strncmp(argv[0], "enable", sizeof("enable")) )
|
||||
- {
|
||||
+ else if ( !strcasecmp(argv[0], "enable") )
|
||||
value = 1;
|
||||
- }
|
||||
else
|
||||
{
|
||||
- show_help();
|
||||
- exit(-1);
|
||||
+ fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
||||
+ exit(EINVAL);
|
||||
}
|
||||
|
||||
- rc = xc_set_sched_opt_smt(xc_handle, value);
|
||||
- printf("%s sched_smt_power_savings %s\n", argv[0],
|
||||
- rc? "failed":"succeeded" );
|
||||
-
|
||||
- return;
|
||||
+ if ( !xc_set_sched_opt_smt(xc_handle, value) )
|
||||
+ printf("%s sched_smt_power_savings succeeded\n", argv[0]);
|
||||
+ else
|
||||
+ fprintf(stderr, "%s sched_smt_power_savings failed (%d - %s)\n",
|
||||
+ argv[0], errno, strerror(errno));
|
||||
}
|
||||
|
||||
void set_vcpu_migration_delay_func(int argc, char *argv[])
|
||||
{
|
||||
int value;
|
||||
- int rc;
|
||||
-
|
||||
- if (argc != 1){
|
||||
- show_help();
|
||||
- exit(-1);
|
||||
- }
|
||||
-
|
||||
- value = atoi(argv[0]);
|
||||
|
||||
- if (value < 0)
|
||||
- {
|
||||
- printf("Please try non-negative vcpu migration delay\n");
|
||||
- exit(-1);
|
||||
+ if ( argc != 1 || (value = atoi(argv[0])) < 0 ) {
|
||||
+ fprintf(stderr, "Missing or invalid argument(s)\n");
|
||||
+ exit(EINVAL);
|
||||
}
|
||||
|
||||
- rc = xc_set_vcpu_migration_delay(xc_handle, value);
|
||||
- printf("%s to set vcpu migration delay to %d us\n",
|
||||
- rc? "Fail":"Succeed", value );
|
||||
-
|
||||
- return;
|
||||
+ if ( !xc_set_vcpu_migration_delay(xc_handle, value) )
|
||||
+ printf("set vcpu migration delay to %d us succeeded\n", value);
|
||||
+ else
|
||||
+ fprintf(stderr, "set vcpu migration delay failed (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
|
||||
void get_vcpu_migration_delay_func(int argc, char *argv[])
|
||||
{
|
||||
uint32_t value;
|
||||
- int rc;
|
||||
|
||||
- if (argc != 0){
|
||||
- show_help();
|
||||
- exit(-1);
|
||||
- }
|
||||
+ if ( argc )
|
||||
+ fprintf(stderr, "Ignoring argument(s)\n");
|
||||
|
||||
- rc = xc_get_vcpu_migration_delay(xc_handle, &value);
|
||||
- if (!rc)
|
||||
- {
|
||||
- printf("Schduler vcpu migration delay is %d us\n", value);
|
||||
- }
|
||||
+ if ( !xc_get_vcpu_migration_delay(xc_handle, &value) )
|
||||
+ printf("Scheduler vcpu migration delay is %d us\n", value);
|
||||
else
|
||||
- {
|
||||
- printf("Failed to get scheduler vcpu migration delay, errno=%d\n", errno);
|
||||
- }
|
||||
-
|
||||
- return;
|
||||
+ fprintf(stderr,
|
||||
+ "Failed to get scheduler vcpu migration delay (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
|
||||
void set_max_cstate_func(int argc, char *argv[])
|
||||
{
|
||||
- int value, rc;
|
||||
+ int value;
|
||||
|
||||
if ( argc != 1 || sscanf(argv[0], "%d", &value) != 1 || value < 0 )
|
||||
{
|
||||
- show_help();
|
||||
- exit(-1);
|
||||
+ fprintf(stderr, "Missing or invalid argument(s)\n");
|
||||
+ exit(EINVAL);
|
||||
}
|
||||
|
||||
- rc = xc_set_cpuidle_max_cstate(xc_handle, (uint32_t)value);
|
||||
- printf("set max_cstate to C%d %s\n", value,
|
||||
- rc? "failed":"succeeded" );
|
||||
-
|
||||
- return;
|
||||
+ if ( !xc_set_cpuidle_max_cstate(xc_handle, (uint32_t)value) )
|
||||
+ printf("set max_cstate to C%d succeeded\n", value);
|
||||
+ else
|
||||
+ fprintf(stderr, "set max_cstate to C%d failed (%d - %s)\n",
|
||||
+ value, errno, strerror(errno));
|
||||
}
|
||||
|
||||
void enable_turbo_mode(int argc, char *argv[])
|
||||
{
|
||||
int cpuid = -1;
|
||||
|
||||
- if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
|
||||
- cpuid = -1;
|
||||
-
|
||||
- if ( cpuid >= max_cpu_nr )
|
||||
- cpuid = -1;
|
||||
+ if ( argc > 0 )
|
||||
+ parse_cpuid(argv[0], &cpuid);
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
@@ -1122,21 +1090,22 @@ void enable_turbo_mode(int argc, char *a
|
||||
* only make effects on dbs governor */
|
||||
int i;
|
||||
for ( i = 0; i < max_cpu_nr; i++ )
|
||||
- xc_enable_turbo(xc_handle, i);
|
||||
+ if ( xc_enable_turbo(xc_handle, i) )
|
||||
+ fprintf(stderr,
|
||||
+ "[CPU%d] failed to enable turbo mode (%d - %s)\n",
|
||||
+ i, errno, strerror(errno));
|
||||
}
|
||||
- else
|
||||
- xc_enable_turbo(xc_handle, cpuid);
|
||||
+ else if ( xc_enable_turbo(xc_handle, cpuid) )
|
||||
+ fprintf(stderr, "failed to enable turbo mode (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
|
||||
void disable_turbo_mode(int argc, char *argv[])
|
||||
{
|
||||
int cpuid = -1;
|
||||
|
||||
- if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
|
||||
- cpuid = -1;
|
||||
-
|
||||
- if ( cpuid >= max_cpu_nr )
|
||||
- cpuid = -1;
|
||||
+ if ( argc > 0 )
|
||||
+ parse_cpuid(argv[0], &cpuid);
|
||||
|
||||
if ( cpuid < 0 )
|
||||
{
|
||||
@@ -1144,10 +1113,14 @@ void disable_turbo_mode(int argc, char *
|
||||
* only make effects on dbs governor */
|
||||
int i;
|
||||
for ( i = 0; i < max_cpu_nr; i++ )
|
||||
- xc_disable_turbo(xc_handle, i);
|
||||
+ if ( xc_disable_turbo(xc_handle, i) )
|
||||
+ fprintf(stderr,
|
||||
+ "[CPU%d] failed to disable turbo mode (%d - %s)\n",
|
||||
+ i, errno, strerror(errno));
|
||||
}
|
||||
- else
|
||||
- xc_disable_turbo(xc_handle, cpuid);
|
||||
+ else if ( xc_disable_turbo(xc_handle, cpuid) )
|
||||
+ fprintf(stderr, "failed to disable turbo mode (%d - %s)\n",
|
||||
+ errno, strerror(errno));
|
||||
}
|
||||
|
||||
struct {
|
||||
@@ -1191,15 +1164,17 @@ int main(int argc, char *argv[])
|
||||
if ( !xc_handle )
|
||||
{
|
||||
fprintf(stderr, "failed to get the handler\n");
|
||||
- return 0;
|
||||
+ return EIO;
|
||||
}
|
||||
|
||||
ret = xc_physinfo(xc_handle, &physinfo);
|
||||
if ( ret )
|
||||
{
|
||||
- fprintf(stderr, "failed to get the processor information\n");
|
||||
+ ret = errno;
|
||||
+ fprintf(stderr, "failed to get processor information (%d - %s)\n",
|
||||
+ ret, strerror(ret));
|
||||
xc_interface_close(xc_handle);
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
max_cpu_nr = physinfo.nr_cpus;
|
||||
|
||||
@@ -1214,14 +1189,18 @@ int main(int argc, char *argv[])
|
||||
for ( i = 0; i < nr_matches; i++ )
|
||||
fprintf(stderr, " %s", main_options[matches_main_options[i]].name);
|
||||
fprintf(stderr, "\n");
|
||||
+ ret = EINVAL;
|
||||
}
|
||||
else if ( nr_matches == 1 )
|
||||
/* dispatch to the corresponding function handler */
|
||||
main_options[matches_main_options[0]].function(argc - 2, argv + 2);
|
||||
else
|
||||
+ {
|
||||
show_help();
|
||||
+ ret = EINVAL;
|
||||
+ }
|
||||
|
||||
xc_interface_close(xc_handle);
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
@ -1,128 +0,0 @@
|
||||
References: FATE#313605
|
||||
|
||||
# HG changeset patch
|
||||
# User Jiongxi Li <jiongxi.li@intel.com>
|
||||
# Date 1347912248 -3600
|
||||
# Node ID ec60de627945f17ec2ce5c14e1224b59403875f7
|
||||
# Parent 62de66cec48a1716bb700912da451a26296b8d1e
|
||||
xen: enable APIC-Register Virtualization
|
||||
|
||||
Add APIC register virtualization support
|
||||
- APIC read doesn't cause VM-Exit
|
||||
- APIC write becomes trap-like
|
||||
|
||||
Signed-off-by: Gang Wei <gang.wei@intel.com>
|
||||
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
|
||||
Signed-off-by: Jiongxi Li <jiongxi.li@intel.com>
|
||||
|
||||
--- a/xen/arch/x86/hvm/vlapic.c
|
||||
+++ b/xen/arch/x86/hvm/vlapic.c
|
||||
@@ -822,6 +822,12 @@ static int vlapic_write(struct vcpu *v,
|
||||
return rc;
|
||||
}
|
||||
|
||||
+int vlapic_apicv_write(struct vcpu *v, unsigned int offset)
|
||||
+{
|
||||
+ uint32_t val = vlapic_get_reg(vcpu_vlapic(v), offset);
|
||||
+ return vlapic_reg_write(v, offset, val);
|
||||
+}
|
||||
+
|
||||
int hvm_x2apic_msr_write(struct vcpu *v, unsigned int msr, uint64_t msr_content)
|
||||
{
|
||||
struct vlapic *vlapic = vcpu_vlapic(v);
|
||||
--- a/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
@@ -89,6 +89,7 @@ static void __init vmx_display_features(
|
||||
P(cpu_has_vmx_vnmi, "Virtual NMI");
|
||||
P(cpu_has_vmx_msr_bitmap, "MSR direct-access bitmap");
|
||||
P(cpu_has_vmx_unrestricted_guest, "Unrestricted Guest");
|
||||
+ P(cpu_has_vmx_apic_reg_virt, "APIC Register Virtualization");
|
||||
#undef P
|
||||
|
||||
if ( !printed )
|
||||
@@ -186,6 +187,14 @@ static int vmx_init_vmcs_config(void)
|
||||
if ( opt_unrestricted_guest_enabled )
|
||||
opt |= SECONDARY_EXEC_UNRESTRICTED_GUEST;
|
||||
|
||||
+ /*
|
||||
+ * "APIC Register Virtualization"
|
||||
+ * can be set only when "use TPR shadow" is set
|
||||
+ */
|
||||
+ if ( _vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW )
|
||||
+ opt |= SECONDARY_EXEC_APIC_REGISTER_VIRT;
|
||||
+
|
||||
+
|
||||
_vmx_secondary_exec_control = adjust_vmx_controls(
|
||||
"Secondary Exec Control", min, opt,
|
||||
MSR_IA32_VMX_PROCBASED_CTLS2, &mismatch);
|
||||
--- a/xen/arch/x86/hvm/vmx/vmx.c
|
||||
+++ b/xen/arch/x86/hvm/vmx/vmx.c
|
||||
@@ -2279,6 +2279,16 @@ static void vmx_idtv_reinject(unsigned l
|
||||
}
|
||||
}
|
||||
|
||||
+static int vmx_handle_apic_write(void)
|
||||
+{
|
||||
+ unsigned long exit_qualification = __vmread(EXIT_QUALIFICATION);
|
||||
+ unsigned int offset = exit_qualification & 0xfff;
|
||||
+
|
||||
+ ASSERT(cpu_has_vmx_apic_reg_virt);
|
||||
+
|
||||
+ return vlapic_apicv_write(current, offset);
|
||||
+}
|
||||
+
|
||||
void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
{
|
||||
unsigned int exit_reason, idtv_info, intr_info = 0, vector = 0;
|
||||
@@ -2741,6 +2751,11 @@ void vmx_vmexit_handler(struct cpu_user_
|
||||
break;
|
||||
}
|
||||
|
||||
+ case EXIT_REASON_APIC_WRITE:
|
||||
+ if ( vmx_handle_apic_write() )
|
||||
+ hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
+ break;
|
||||
+
|
||||
case EXIT_REASON_ACCESS_GDTR_OR_IDTR:
|
||||
case EXIT_REASON_ACCESS_LDTR_OR_TR:
|
||||
case EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED:
|
||||
--- a/xen/include/asm-x86/hvm/vlapic.h
|
||||
+++ b/xen/include/asm-x86/hvm/vlapic.h
|
||||
@@ -103,6 +103,8 @@ void vlapic_EOI_set(struct vlapic *vlapi
|
||||
|
||||
int vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high);
|
||||
|
||||
+int vlapic_apicv_write(struct vcpu *v, unsigned int offset);
|
||||
+
|
||||
struct vlapic *vlapic_lowest_prio(
|
||||
struct domain *d, struct vlapic *source,
|
||||
int short_hand, uint8_t dest, uint8_t dest_mode);
|
||||
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
@@ -182,6 +182,7 @@ extern u32 vmx_vmentry_control;
|
||||
#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
|
||||
#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
|
||||
#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
|
||||
+#define SECONDARY_EXEC_APIC_REGISTER_VIRT 0x00000100
|
||||
#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
|
||||
#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
|
||||
extern u32 vmx_secondary_exec_control;
|
||||
@@ -230,6 +231,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr
|
||||
SECONDARY_EXEC_UNRESTRICTED_GUEST)
|
||||
#define cpu_has_vmx_ple \
|
||||
(vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING)
|
||||
+#define cpu_has_vmx_apic_reg_virt \
|
||||
+ (vmx_secondary_exec_control & SECONDARY_EXEC_APIC_REGISTER_VIRT)
|
||||
|
||||
/* GUEST_INTERRUPTIBILITY_INFO flags. */
|
||||
#define VMX_INTR_SHADOW_STI 0x00000001
|
||||
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
|
||||
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
|
||||
@@ -129,6 +129,7 @@ void vmx_update_cpu_exec_control(struct
|
||||
#define EXIT_REASON_INVVPID 53
|
||||
#define EXIT_REASON_WBINVD 54
|
||||
#define EXIT_REASON_XSETBV 55
|
||||
+#define EXIT_REASON_APIC_WRITE 56
|
||||
#define EXIT_REASON_INVPCID 58
|
||||
|
||||
/*
|
@ -1,505 +0,0 @@
|
||||
References: FATE#313605
|
||||
|
||||
# HG changeset patch
|
||||
# User Jiongxi Li <jiongxi.li@intel.com>
|
||||
# Date 1347912311 -3600
|
||||
# Node ID 713b8849b11afa05f1dde157a3f5086fa3aaad08
|
||||
# Parent ec60de627945f17ec2ce5c14e1224b59403875f7
|
||||
xen: enable Virtual-interrupt delivery
|
||||
|
||||
Virtual interrupt delivery avoids Xen to inject vAPIC interrupts
|
||||
manually, which is fully taken care of by the hardware. This needs
|
||||
some special awareness into existing interrupr injection path:
|
||||
For pending interrupt from vLAPIC, instead of direct injection, we may
|
||||
need update architecture specific indicators before resuming to guest.
|
||||
Before returning to guest, RVI should be updated if any pending IRRs
|
||||
EOI exit bitmap controls whether an EOI write should cause VM-Exit. If
|
||||
set, a trap-like induced EOI VM-Exit is triggered. The approach here
|
||||
is to manipulate EOI exit bitmap based on value of TMR. Level
|
||||
triggered irq requires a hook in vLAPIC EOI write, so that vIOAPIC EOI
|
||||
is triggered and emulated
|
||||
|
||||
Signed-off-by: Gang Wei <gang.wei@intel.com>
|
||||
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
|
||||
Signed-off-by: Jiongxi Li <jiongxi.li@intel.com>
|
||||
Committed-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/xen/arch/x86/hvm/vlapic.c
|
||||
+++ b/xen/arch/x86/hvm/vlapic.c
|
||||
@@ -145,6 +145,9 @@ int vlapic_set_irq(struct vlapic *vlapic
|
||||
if ( trig )
|
||||
vlapic_set_vector(vec, &vlapic->regs->data[APIC_TMR]);
|
||||
|
||||
+ if ( hvm_funcs.update_eoi_exit_bitmap )
|
||||
+ hvm_funcs.update_eoi_exit_bitmap(vlapic_vcpu(vlapic), vec ,trig);
|
||||
+
|
||||
/* We may need to wake up target vcpu, besides set pending bit here */
|
||||
return !vlapic_test_and_set_irr(vec, vlapic);
|
||||
}
|
||||
@@ -410,6 +413,14 @@ void vlapic_EOI_set(struct vlapic *vlapi
|
||||
hvm_dpci_msi_eoi(current->domain, vector);
|
||||
}
|
||||
|
||||
+void vlapic_handle_EOI_induced_exit(struct vlapic *vlapic, int vector)
|
||||
+{
|
||||
+ if ( vlapic_test_and_clear_vector(vector, &vlapic->regs->data[APIC_TMR]) )
|
||||
+ vioapic_update_EOI(vlapic_domain(vlapic), vector);
|
||||
+
|
||||
+ hvm_dpci_msi_eoi(current->domain, vector);
|
||||
+}
|
||||
+
|
||||
int vlapic_ipi(
|
||||
struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high)
|
||||
{
|
||||
@@ -996,6 +1007,14 @@ void vlapic_adjust_i8259_target(struct d
|
||||
pt_adjust_global_vcpu_target(v);
|
||||
}
|
||||
|
||||
+int vlapic_virtual_intr_delivery_enabled(void)
|
||||
+{
|
||||
+ if ( hvm_funcs.virtual_intr_delivery_enabled )
|
||||
+ return hvm_funcs.virtual_intr_delivery_enabled();
|
||||
+ else
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int vlapic_has_pending_irq(struct vcpu *v)
|
||||
{
|
||||
struct vlapic *vlapic = vcpu_vlapic(v);
|
||||
@@ -1008,6 +1027,9 @@ int vlapic_has_pending_irq(struct vcpu *
|
||||
if ( irr == -1 )
|
||||
return -1;
|
||||
|
||||
+ if ( vlapic_virtual_intr_delivery_enabled() )
|
||||
+ return irr;
|
||||
+
|
||||
isr = vlapic_find_highest_isr(vlapic);
|
||||
isr = (isr != -1) ? isr : 0;
|
||||
if ( (isr & 0xf0) >= (irr & 0xf0) )
|
||||
@@ -1020,6 +1042,9 @@ int vlapic_ack_pending_irq(struct vcpu *
|
||||
{
|
||||
struct vlapic *vlapic = vcpu_vlapic(v);
|
||||
|
||||
+ if ( vlapic_virtual_intr_delivery_enabled() )
|
||||
+ return 1;
|
||||
+
|
||||
vlapic_set_vector(vector, &vlapic->regs->data[APIC_ISR]);
|
||||
vlapic_clear_irr(vector, vlapic);
|
||||
|
||||
--- a/xen/arch/x86/hvm/vmx/intr.c
|
||||
+++ b/xen/arch/x86/hvm/vmx/intr.c
|
||||
@@ -209,6 +209,7 @@ void vmx_intr_assist(void)
|
||||
struct vcpu *v = current;
|
||||
unsigned int tpr_threshold = 0;
|
||||
enum hvm_intblk intblk;
|
||||
+ int pt_vector = -1;
|
||||
|
||||
/* Block event injection when single step with MTF. */
|
||||
if ( unlikely(v->arch.hvm_vcpu.single_step) )
|
||||
@@ -219,7 +220,7 @@ void vmx_intr_assist(void)
|
||||
}
|
||||
|
||||
/* Crank the handle on interrupt state. */
|
||||
- pt_update_irq(v);
|
||||
+ pt_vector = pt_update_irq(v);
|
||||
|
||||
do {
|
||||
intack = hvm_vcpu_has_pending_irq(v);
|
||||
@@ -230,16 +231,34 @@ void vmx_intr_assist(void)
|
||||
goto out;
|
||||
|
||||
intblk = hvm_interrupt_blocked(v, intack);
|
||||
- if ( intblk == hvm_intblk_tpr )
|
||||
+ if ( cpu_has_vmx_virtual_intr_delivery )
|
||||
+ {
|
||||
+ /* Set "Interrupt-window exiting" for ExtINT */
|
||||
+ if ( (intblk != hvm_intblk_none) &&
|
||||
+ ( (intack.source == hvm_intsrc_pic) ||
|
||||
+ ( intack.source == hvm_intsrc_vector) ) )
|
||||
+ {
|
||||
+ enable_intr_window(v, intack);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ( __vmread(VM_ENTRY_INTR_INFO) & INTR_INFO_VALID_MASK )
|
||||
+ {
|
||||
+ if ( (intack.source == hvm_intsrc_pic) ||
|
||||
+ (intack.source == hvm_intsrc_nmi) ||
|
||||
+ (intack.source == hvm_intsrc_mce) )
|
||||
+ enable_intr_window(v, intack);
|
||||
+
|
||||
+ goto out;
|
||||
+ }
|
||||
+ } else if ( intblk == hvm_intblk_tpr )
|
||||
{
|
||||
ASSERT(vlapic_enabled(vcpu_vlapic(v)));
|
||||
ASSERT(intack.source == hvm_intsrc_lapic);
|
||||
tpr_threshold = intack.vector >> 4;
|
||||
goto out;
|
||||
- }
|
||||
-
|
||||
- if ( (intblk != hvm_intblk_none) ||
|
||||
- (__vmread(VM_ENTRY_INTR_INFO) & INTR_INFO_VALID_MASK) )
|
||||
+ } else if ( (intblk != hvm_intblk_none) ||
|
||||
+ (__vmread(VM_ENTRY_INTR_INFO) & INTR_INFO_VALID_MASK) )
|
||||
{
|
||||
enable_intr_window(v, intack);
|
||||
goto out;
|
||||
@@ -256,6 +275,44 @@ void vmx_intr_assist(void)
|
||||
{
|
||||
hvm_inject_hw_exception(TRAP_machine_check, HVM_DELIVER_NO_ERROR_CODE);
|
||||
}
|
||||
+ else if ( cpu_has_vmx_virtual_intr_delivery &&
|
||||
+ intack.source != hvm_intsrc_pic &&
|
||||
+ intack.source != hvm_intsrc_vector )
|
||||
+ {
|
||||
+ unsigned long status = __vmread(GUEST_INTR_STATUS);
|
||||
+
|
||||
+ /*
|
||||
+ * Set eoi_exit_bitmap for periodic timer interrup to cause EOI-induced VM
|
||||
+ * exit, then pending periodic time interrups have the chance to be injected
|
||||
+ * for compensation
|
||||
+ */
|
||||
+ if (pt_vector != -1)
|
||||
+ vmx_set_eoi_exit_bitmap(v, pt_vector);
|
||||
+
|
||||
+ /* we need update the RVI field */
|
||||
+ status &= ~(unsigned long)0x0FF;
|
||||
+ status |= (unsigned long)0x0FF &
|
||||
+ intack.vector;
|
||||
+ __vmwrite(GUEST_INTR_STATUS, status);
|
||||
+ if (v->arch.hvm_vmx.eoi_exitmap_changed) {
|
||||
+#ifdef __i386__
|
||||
+#define UPDATE_EOI_EXITMAP(v, e) { \
|
||||
+ if (test_and_clear_bit(e, &v->arch.hvm_vmx.eoi_exitmap_changed)) { \
|
||||
+ __vmwrite(EOI_EXIT_BITMAP##e, v->arch.hvm_vmx.eoi_exit_bitmap[e]); \
|
||||
+ __vmwrite(EOI_EXIT_BITMAP##e##_HIGH, v->arch.hvm_vmx.eoi_exit_bitmap[e] >> 32);}}
|
||||
+#else
|
||||
+#define UPDATE_EOI_EXITMAP(v, e) { \
|
||||
+ if (test_and_clear_bit(e, &v->arch.hvm_vmx.eoi_exitmap_changed)) { \
|
||||
+ __vmwrite(EOI_EXIT_BITMAP##e, v->arch.hvm_vmx.eoi_exit_bitmap[e]);}}
|
||||
+#endif
|
||||
+ UPDATE_EOI_EXITMAP(v, 0);
|
||||
+ UPDATE_EOI_EXITMAP(v, 1);
|
||||
+ UPDATE_EOI_EXITMAP(v, 2);
|
||||
+ UPDATE_EOI_EXITMAP(v, 3);
|
||||
+ }
|
||||
+
|
||||
+ pt_intr_post(v, intack);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
HVMTRACE_2D(INJ_VIRQ, intack.vector, /*fake=*/ 0);
|
||||
@@ -265,11 +322,16 @@ void vmx_intr_assist(void)
|
||||
|
||||
/* Is there another IRQ to queue up behind this one? */
|
||||
intack = hvm_vcpu_has_pending_irq(v);
|
||||
- if ( unlikely(intack.source != hvm_intsrc_none) )
|
||||
- enable_intr_window(v, intack);
|
||||
+ if ( !cpu_has_vmx_virtual_intr_delivery ||
|
||||
+ intack.source == hvm_intsrc_pic ||
|
||||
+ intack.source == hvm_intsrc_vector )
|
||||
+ {
|
||||
+ if ( unlikely(intack.source != hvm_intsrc_none) )
|
||||
+ enable_intr_window(v, intack);
|
||||
+ }
|
||||
|
||||
out:
|
||||
- if ( cpu_has_vmx_tpr_shadow )
|
||||
+ if ( !cpu_has_vmx_virtual_intr_delivery && cpu_has_vmx_tpr_shadow )
|
||||
__vmwrite(TPR_THRESHOLD, tpr_threshold);
|
||||
}
|
||||
|
||||
--- a/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
@@ -90,6 +90,7 @@ static void __init vmx_display_features(
|
||||
P(cpu_has_vmx_msr_bitmap, "MSR direct-access bitmap");
|
||||
P(cpu_has_vmx_unrestricted_guest, "Unrestricted Guest");
|
||||
P(cpu_has_vmx_apic_reg_virt, "APIC Register Virtualization");
|
||||
+ P(cpu_has_vmx_virtual_intr_delivery, "Virtual Interrupt Delivery");
|
||||
#undef P
|
||||
|
||||
if ( !printed )
|
||||
@@ -188,11 +189,12 @@ static int vmx_init_vmcs_config(void)
|
||||
opt |= SECONDARY_EXEC_UNRESTRICTED_GUEST;
|
||||
|
||||
/*
|
||||
- * "APIC Register Virtualization"
|
||||
+ * "APIC Register Virtualization" and "Virtual Interrupt Delivery"
|
||||
* can be set only when "use TPR shadow" is set
|
||||
*/
|
||||
if ( _vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW )
|
||||
- opt |= SECONDARY_EXEC_APIC_REGISTER_VIRT;
|
||||
+ opt |= SECONDARY_EXEC_APIC_REGISTER_VIRT |
|
||||
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
|
||||
|
||||
|
||||
_vmx_secondary_exec_control = adjust_vmx_controls(
|
||||
@@ -787,6 +789,22 @@ static int construct_vmcs(struct vcpu *v
|
||||
__vmwrite(IO_BITMAP_A, virt_to_maddr((char *)hvm_io_bitmap + 0));
|
||||
__vmwrite(IO_BITMAP_B, virt_to_maddr((char *)hvm_io_bitmap + PAGE_SIZE));
|
||||
|
||||
+ if ( cpu_has_vmx_virtual_intr_delivery )
|
||||
+ {
|
||||
+ /* EOI-exit bitmap */
|
||||
+ v->arch.hvm_vmx.eoi_exit_bitmap[0] = (uint64_t)0;
|
||||
+ __vmwrite(EOI_EXIT_BITMAP0, v->arch.hvm_vmx.eoi_exit_bitmap[0]);
|
||||
+ v->arch.hvm_vmx.eoi_exit_bitmap[1] = (uint64_t)0;
|
||||
+ __vmwrite(EOI_EXIT_BITMAP1, v->arch.hvm_vmx.eoi_exit_bitmap[1]);
|
||||
+ v->arch.hvm_vmx.eoi_exit_bitmap[2] = (uint64_t)0;
|
||||
+ __vmwrite(EOI_EXIT_BITMAP2, v->arch.hvm_vmx.eoi_exit_bitmap[2]);
|
||||
+ v->arch.hvm_vmx.eoi_exit_bitmap[3] = (uint64_t)0;
|
||||
+ __vmwrite(EOI_EXIT_BITMAP3, v->arch.hvm_vmx.eoi_exit_bitmap[3]);
|
||||
+
|
||||
+ /* Initialise Guest Interrupt Status (RVI and SVI) to 0 */
|
||||
+ __vmwrite(GUEST_INTR_STATUS, 0);
|
||||
+ }
|
||||
+
|
||||
/* Host data selectors. */
|
||||
__vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
|
||||
__vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
|
||||
@@ -1028,6 +1046,30 @@ int vmx_add_host_load_msr(u32 msr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void vmx_set_eoi_exit_bitmap(struct vcpu *v, u8 vector)
|
||||
+{
|
||||
+ int index, offset, changed;
|
||||
+
|
||||
+ index = vector >> 6;
|
||||
+ offset = vector & 63;
|
||||
+ changed = !test_and_set_bit(offset,
|
||||
+ (uint64_t *)&v->arch.hvm_vmx.eoi_exit_bitmap[index]);
|
||||
+ if (changed)
|
||||
+ set_bit(index, &v->arch.hvm_vmx.eoi_exitmap_changed);
|
||||
+}
|
||||
+
|
||||
+void vmx_clear_eoi_exit_bitmap(struct vcpu *v, u8 vector)
|
||||
+{
|
||||
+ int index, offset, changed;
|
||||
+
|
||||
+ index = vector >> 6;
|
||||
+ offset = vector & 63;
|
||||
+ changed = test_and_clear_bit(offset,
|
||||
+ (uint64_t *)&v->arch.hvm_vmx.eoi_exit_bitmap[index]);
|
||||
+ if (changed)
|
||||
+ set_bit(index, &v->arch.hvm_vmx.eoi_exitmap_changed);
|
||||
+}
|
||||
+
|
||||
int vmx_create_vmcs(struct vcpu *v)
|
||||
{
|
||||
struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
|
||||
--- a/xen/arch/x86/hvm/vmx/vmx.c
|
||||
+++ b/xen/arch/x86/hvm/vmx/vmx.c
|
||||
@@ -1507,6 +1507,22 @@ static void vmx_set_info_guest(struct vc
|
||||
vmx_vmcs_exit(v);
|
||||
}
|
||||
|
||||
+static void vmx_update_eoi_exit_bitmap(struct vcpu *v, u8 vector, u8 trig)
|
||||
+{
|
||||
+ if ( cpu_has_vmx_virtual_intr_delivery )
|
||||
+ {
|
||||
+ if (trig)
|
||||
+ vmx_set_eoi_exit_bitmap(v, vector);
|
||||
+ else
|
||||
+ vmx_clear_eoi_exit_bitmap(v, vector);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int vmx_virtual_intr_delivery_enabled(void)
|
||||
+{
|
||||
+ return cpu_has_vmx_virtual_intr_delivery;
|
||||
+}
|
||||
+
|
||||
static struct hvm_function_table __read_mostly vmx_function_table = {
|
||||
.name = "VMX",
|
||||
.cpu_up_prepare = vmx_cpu_up_prepare,
|
||||
@@ -1553,7 +1569,9 @@ static struct hvm_function_table __read_
|
||||
.nhvm_vmcx_guest_intercepts_trap = nvmx_intercepts_exception,
|
||||
.nhvm_vcpu_vmexit_trap = nvmx_vmexit_trap,
|
||||
.nhvm_intr_blocked = nvmx_intr_blocked,
|
||||
- .nhvm_domain_relinquish_resources = nvmx_domain_relinquish_resources
|
||||
+ .nhvm_domain_relinquish_resources = nvmx_domain_relinquish_resources,
|
||||
+ .update_eoi_exit_bitmap = vmx_update_eoi_exit_bitmap,
|
||||
+ .virtual_intr_delivery_enabled = vmx_virtual_intr_delivery_enabled
|
||||
};
|
||||
|
||||
struct hvm_function_table * __init start_vmx(void)
|
||||
@@ -2289,6 +2307,17 @@ static int vmx_handle_apic_write(void)
|
||||
return vlapic_apicv_write(current, offset);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * When "Virtual Interrupt Delivery" is enabled, this function is used
|
||||
+ * to handle EOI-induced VM exit
|
||||
+ */
|
||||
+void vmx_handle_EOI_induced_exit(struct vlapic *vlapic, int vector)
|
||||
+{
|
||||
+ ASSERT(cpu_has_vmx_virtual_intr_delivery);
|
||||
+
|
||||
+ vlapic_handle_EOI_induced_exit(vlapic, vector);
|
||||
+}
|
||||
+
|
||||
void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
{
|
||||
unsigned int exit_reason, idtv_info, intr_info = 0, vector = 0;
|
||||
@@ -2689,6 +2718,16 @@ void vmx_vmexit_handler(struct cpu_user_
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
break;
|
||||
|
||||
+ case EXIT_REASON_EOI_INDUCED:
|
||||
+ {
|
||||
+ int vector;
|
||||
+ exit_qualification = __vmread(EXIT_QUALIFICATION);
|
||||
+ vector = exit_qualification & 0xff;
|
||||
+
|
||||
+ vmx_handle_EOI_induced_exit(vcpu_vlapic(current), vector);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
case EXIT_REASON_IO_INSTRUCTION:
|
||||
exit_qualification = __vmread(EXIT_QUALIFICATION);
|
||||
if ( exit_qualification & 0x10 )
|
||||
--- a/xen/arch/x86/hvm/vpt.c
|
||||
+++ b/xen/arch/x86/hvm/vpt.c
|
||||
@@ -212,7 +212,7 @@ static void pt_timer_fn(void *data)
|
||||
pt_unlock(pt);
|
||||
}
|
||||
|
||||
-void pt_update_irq(struct vcpu *v)
|
||||
+int pt_update_irq(struct vcpu *v)
|
||||
{
|
||||
struct list_head *head = &v->arch.hvm_vcpu.tm_list;
|
||||
struct periodic_time *pt, *temp, *earliest_pt = NULL;
|
||||
@@ -245,7 +245,7 @@ void pt_update_irq(struct vcpu *v)
|
||||
if ( earliest_pt == NULL )
|
||||
{
|
||||
spin_unlock(&v->arch.hvm_vcpu.tm_lock);
|
||||
- return;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
earliest_pt->irq_issued = 1;
|
||||
@@ -263,6 +263,17 @@ void pt_update_irq(struct vcpu *v)
|
||||
hvm_isa_irq_deassert(v->domain, irq);
|
||||
hvm_isa_irq_assert(v->domain, irq);
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * If periodic timer interrut is handled by lapic, its vector in
|
||||
+ * IRR is returned and used to set eoi_exit_bitmap for virtual
|
||||
+ * interrupt delivery case. Otherwise return -1 to do nothing.
|
||||
+ */
|
||||
+ if ( vlapic_accept_pic_intr(v) &&
|
||||
+ (&v->domain->arch.hvm_domain)->vpic[0].int_output )
|
||||
+ return -1;
|
||||
+ else
|
||||
+ return pt_irq_vector(earliest_pt, hvm_intsrc_lapic);
|
||||
}
|
||||
|
||||
static struct periodic_time *is_pt_irq(
|
||||
--- a/xen/include/asm-x86/hvm/hvm.h
|
||||
+++ b/xen/include/asm-x86/hvm/hvm.h
|
||||
@@ -180,6 +180,10 @@ struct hvm_function_table {
|
||||
|
||||
enum hvm_intblk (*nhvm_intr_blocked)(struct vcpu *v);
|
||||
void (*nhvm_domain_relinquish_resources)(struct domain *d);
|
||||
+
|
||||
+ /* Virtual interrupt delivery */
|
||||
+ void (*update_eoi_exit_bitmap)(struct vcpu *v, u8 vector, u8 trig);
|
||||
+ int (*virtual_intr_delivery_enabled)(void);
|
||||
};
|
||||
|
||||
extern struct hvm_function_table hvm_funcs;
|
||||
--- a/xen/include/asm-x86/hvm/vlapic.h
|
||||
+++ b/xen/include/asm-x86/hvm/vlapic.h
|
||||
@@ -100,6 +100,7 @@ int vlapic_accept_pic_intr(struct vcpu *
|
||||
void vlapic_adjust_i8259_target(struct domain *d);
|
||||
|
||||
void vlapic_EOI_set(struct vlapic *vlapic);
|
||||
+void vlapic_handle_EOI_induced_exit(struct vlapic *vlapic, int vector);
|
||||
|
||||
int vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high);
|
||||
|
||||
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
@@ -110,6 +110,9 @@ struct arch_vmx_struct {
|
||||
unsigned int host_msr_count;
|
||||
struct vmx_msr_entry *host_msr_area;
|
||||
|
||||
+ uint32_t eoi_exitmap_changed;
|
||||
+ uint64_t eoi_exit_bitmap[4];
|
||||
+
|
||||
unsigned long host_cr0;
|
||||
|
||||
/* Is the guest in real mode? */
|
||||
@@ -183,6 +186,7 @@ extern u32 vmx_vmentry_control;
|
||||
#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
|
||||
#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
|
||||
#define SECONDARY_EXEC_APIC_REGISTER_VIRT 0x00000100
|
||||
+#define SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY 0x00000200
|
||||
#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
|
||||
#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
|
||||
extern u32 vmx_secondary_exec_control;
|
||||
@@ -233,6 +237,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr
|
||||
(vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING)
|
||||
#define cpu_has_vmx_apic_reg_virt \
|
||||
(vmx_secondary_exec_control & SECONDARY_EXEC_APIC_REGISTER_VIRT)
|
||||
+#define cpu_has_vmx_virtual_intr_delivery \
|
||||
+ (vmx_secondary_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)
|
||||
|
||||
/* GUEST_INTERRUPTIBILITY_INFO flags. */
|
||||
#define VMX_INTR_SHADOW_STI 0x00000001
|
||||
@@ -251,6 +257,7 @@ enum vmcs_field {
|
||||
GUEST_GS_SELECTOR = 0x0000080a,
|
||||
GUEST_LDTR_SELECTOR = 0x0000080c,
|
||||
GUEST_TR_SELECTOR = 0x0000080e,
|
||||
+ GUEST_INTR_STATUS = 0x00000810,
|
||||
HOST_ES_SELECTOR = 0x00000c00,
|
||||
HOST_CS_SELECTOR = 0x00000c02,
|
||||
HOST_SS_SELECTOR = 0x00000c04,
|
||||
@@ -278,6 +285,14 @@ enum vmcs_field {
|
||||
APIC_ACCESS_ADDR_HIGH = 0x00002015,
|
||||
EPT_POINTER = 0x0000201a,
|
||||
EPT_POINTER_HIGH = 0x0000201b,
|
||||
+ EOI_EXIT_BITMAP0 = 0x0000201c,
|
||||
+ EOI_EXIT_BITMAP0_HIGH = 0x0000201d,
|
||||
+ EOI_EXIT_BITMAP1 = 0x0000201e,
|
||||
+ EOI_EXIT_BITMAP1_HIGH = 0x0000201f,
|
||||
+ EOI_EXIT_BITMAP2 = 0x00002020,
|
||||
+ EOI_EXIT_BITMAP2_HIGH = 0x00002021,
|
||||
+ EOI_EXIT_BITMAP3 = 0x00002022,
|
||||
+ EOI_EXIT_BITMAP3_HIGH = 0x00002023,
|
||||
GUEST_PHYSICAL_ADDRESS = 0x00002400,
|
||||
GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
|
||||
VMCS_LINK_POINTER = 0x00002800,
|
||||
@@ -398,6 +413,8 @@ int vmx_write_guest_msr(u32 msr, u64 val
|
||||
int vmx_add_guest_msr(u32 msr);
|
||||
int vmx_add_host_load_msr(u32 msr);
|
||||
void vmx_vmcs_switch(struct vmcs_struct *from, struct vmcs_struct *to);
|
||||
+void vmx_set_eoi_exit_bitmap(struct vcpu *v, u8 vector);
|
||||
+void vmx_clear_eoi_exit_bitmap(struct vcpu *v, u8 vector);
|
||||
|
||||
#endif /* ASM_X86_HVM_VMX_VMCS_H__ */
|
||||
|
||||
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
|
||||
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
|
||||
@@ -119,6 +119,7 @@ void vmx_update_cpu_exec_control(struct
|
||||
#define EXIT_REASON_MCE_DURING_VMENTRY 41
|
||||
#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
|
||||
#define EXIT_REASON_APIC_ACCESS 44
|
||||
+#define EXIT_REASON_EOI_INDUCED 45
|
||||
#define EXIT_REASON_ACCESS_GDTR_OR_IDTR 46
|
||||
#define EXIT_REASON_ACCESS_LDTR_OR_TR 47
|
||||
#define EXIT_REASON_EPT_VIOLATION 48
|
||||
--- a/xen/include/asm-x86/hvm/vpt.h
|
||||
+++ b/xen/include/asm-x86/hvm/vpt.h
|
||||
@@ -141,7 +141,7 @@ struct pl_time { /* platform time */
|
||||
|
||||
void pt_save_timer(struct vcpu *v);
|
||||
void pt_restore_timer(struct vcpu *v);
|
||||
-void pt_update_irq(struct vcpu *v);
|
||||
+int pt_update_irq(struct vcpu *v);
|
||||
void pt_intr_post(struct vcpu *v, struct hvm_intack intack);
|
||||
void pt_migrate(struct vcpu *v);
|
||||
|
@ -1,128 +0,0 @@
|
||||
References: FATE#313605
|
||||
|
||||
# HG changeset patch
|
||||
# User Jiongxi Li <jiongxi.li@intel.com>
|
||||
# Date 1347912362 -3600
|
||||
# Node ID c2578dd96b8318e108fff0f340411135dedaa47d
|
||||
# Parent 713b8849b11afa05f1dde157a3f5086fa3aaad08
|
||||
xen: add virtual x2apic support for apicv
|
||||
|
||||
basically to benefit from apicv, we need clear MSR bitmap for
|
||||
corresponding x2apic MSRs:
|
||||
0x800 - 0x8ff: no read intercept for apicv register virtualization
|
||||
TPR,EOI,SELF-IPI: no write intercept for virtual interrupt
|
||||
delivery
|
||||
|
||||
Signed-off-by: Jiongxi Li <jiongxi.li@intel.com>
|
||||
Committed-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
@@ -658,7 +658,7 @@ static void vmx_set_host_env(struct vcpu
|
||||
(unsigned long)&get_cpu_info()->guest_cpu_user_regs.error_code);
|
||||
}
|
||||
|
||||
-void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr)
|
||||
+void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type)
|
||||
{
|
||||
unsigned long *msr_bitmap = v->arch.hvm_vmx.msr_bitmap;
|
||||
|
||||
@@ -673,14 +673,18 @@ void vmx_disable_intercept_for_msr(struc
|
||||
*/
|
||||
if ( msr <= 0x1fff )
|
||||
{
|
||||
- __clear_bit(msr, msr_bitmap + 0x000/BYTES_PER_LONG); /* read-low */
|
||||
- __clear_bit(msr, msr_bitmap + 0x800/BYTES_PER_LONG); /* write-low */
|
||||
+ if (type & MSR_TYPE_R)
|
||||
+ __clear_bit(msr, msr_bitmap + 0x000/BYTES_PER_LONG); /* read-low */
|
||||
+ if (type & MSR_TYPE_W)
|
||||
+ __clear_bit(msr, msr_bitmap + 0x800/BYTES_PER_LONG); /* write-low */
|
||||
}
|
||||
else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) )
|
||||
{
|
||||
msr &= 0x1fff;
|
||||
- __clear_bit(msr, msr_bitmap + 0x400/BYTES_PER_LONG); /* read-high */
|
||||
- __clear_bit(msr, msr_bitmap + 0xc00/BYTES_PER_LONG); /* write-high */
|
||||
+ if (type & MSR_TYPE_R)
|
||||
+ __clear_bit(msr, msr_bitmap + 0x400/BYTES_PER_LONG); /* read-high */
|
||||
+ if (type & MSR_TYPE_W)
|
||||
+ __clear_bit(msr, msr_bitmap + 0xc00/BYTES_PER_LONG); /* write-high */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,13 +780,25 @@ static int construct_vmcs(struct vcpu *v
|
||||
v->arch.hvm_vmx.msr_bitmap = msr_bitmap;
|
||||
__vmwrite(MSR_BITMAP, virt_to_maddr(msr_bitmap));
|
||||
|
||||
- vmx_disable_intercept_for_msr(v, MSR_FS_BASE);
|
||||
- vmx_disable_intercept_for_msr(v, MSR_GS_BASE);
|
||||
- vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_CS);
|
||||
- vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_ESP);
|
||||
- vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_EIP);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_FS_BASE, MSR_TYPE_R | MSR_TYPE_W);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_GS_BASE, MSR_TYPE_R | MSR_TYPE_W);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_CS, MSR_TYPE_R | MSR_TYPE_W);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_ESP, MSR_TYPE_R | MSR_TYPE_W);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_EIP, MSR_TYPE_R | MSR_TYPE_W);
|
||||
if ( cpu_has_vmx_pat && paging_mode_hap(d) )
|
||||
- vmx_disable_intercept_for_msr(v, MSR_IA32_CR_PAT);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_CR_PAT, MSR_TYPE_R | MSR_TYPE_W);
|
||||
+ if ( cpu_has_vmx_apic_reg_virt )
|
||||
+ {
|
||||
+ int msr;
|
||||
+ for (msr = MSR_IA32_APICBASE_MSR; msr <= MSR_IA32_APICBASE_MSR + 0xff; msr++)
|
||||
+ vmx_disable_intercept_for_msr(v, msr, MSR_TYPE_R);
|
||||
+ }
|
||||
+ if ( cpu_has_vmx_virtual_intr_delivery )
|
||||
+ {
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_APICTPR_MSR, MSR_TYPE_W);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_APICEOI_MSR, MSR_TYPE_W);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_APICSELF_MSR, MSR_TYPE_W);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* I/O access bitmap. */
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmx.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/vmx/vmx.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmx.c
|
||||
@@ -2041,7 +2041,7 @@ static int vmx_msr_write_intercept(unsig
|
||||
for ( ; (rc == 0) && lbr->count; lbr++ )
|
||||
for ( i = 0; (rc == 0) && (i < lbr->count); i++ )
|
||||
if ( (rc = vmx_add_guest_msr(lbr->base + i)) == 0 )
|
||||
- vmx_disable_intercept_for_msr(v, lbr->base + i);
|
||||
+ vmx_disable_intercept_for_msr(v, lbr->base + i, MSR_TYPE_R | MSR_TYPE_W);
|
||||
}
|
||||
|
||||
if ( (rc < 0) ||
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
@@ -407,7 +407,9 @@ enum vmcs_field {
|
||||
|
||||
#define VMCS_VPID_WIDTH 16
|
||||
|
||||
-void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr);
|
||||
+#define MSR_TYPE_R 1
|
||||
+#define MSR_TYPE_W 2
|
||||
+void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type);
|
||||
int vmx_read_guest_msr(u32 msr, u64 *val);
|
||||
int vmx_write_guest_msr(u32 msr, u64 val);
|
||||
int vmx_add_guest_msr(u32 msr);
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/msr-index.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/msr-index.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/msr-index.h
|
||||
@@ -293,6 +293,9 @@
|
||||
#define MSR_IA32_APICBASE_ENABLE (1<<11)
|
||||
#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
|
||||
#define MSR_IA32_APICBASE_MSR 0x800
|
||||
+#define MSR_IA32_APICTPR_MSR 0x808
|
||||
+#define MSR_IA32_APICEOI_MSR 0x80b
|
||||
+#define MSR_IA32_APICSELF_MSR 0x83f
|
||||
|
||||
#define MSR_IA32_UCODE_WRITE 0x00000079
|
||||
#define MSR_IA32_UCODE_REV 0x0000008b
|
@ -1,43 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Daniel De Graaf <dgdegra@tycho.nsa.gov>
|
||||
# Date 1348653367 -7200
|
||||
# Node ID 8278d7d8fa485996f51134c5265fceaf239adf6a
|
||||
# Parent b83f414ccf7a6e4e077a10bc422cf3f6c7d30566
|
||||
x86: check remote MMIO remap permissions
|
||||
|
||||
When a domain is mapping pages from a different pg_owner domain, the
|
||||
iomem_access checks are currently only applied to the pg_owner domain,
|
||||
potentially allowing a domain with a more restrictive iomem_access
|
||||
policy to have the pages mapped into its page tables. To catch this,
|
||||
also check the owner of the page tables. The current domain does not
|
||||
need to be checked because the ability to manipulate a domain's page
|
||||
tables implies full access to the target domain, so checking that
|
||||
domain's permission is sufficient.
|
||||
|
||||
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
|
||||
Committed-by: Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/mm.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/mm.c
|
||||
@@ -884,6 +884,19 @@ get_page_from_l1e(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if ( pg_owner != l1e_owner &&
|
||||
+ !iomem_access_permitted(l1e_owner, mfn, mfn) )
|
||||
+ {
|
||||
+ if ( mfn != (PADDR_MASK >> PAGE_SHIFT) ) /* INVALID_MFN? */
|
||||
+ {
|
||||
+ MEM_LOG("Dom%u attempted to map I/O space %08lx in dom%u to dom%u",
|
||||
+ curr->domain->domain_id, mfn, pg_owner->domain_id,
|
||||
+ l1e_owner->domain_id);
|
||||
+ return -EPERM;
|
||||
+ }
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
if ( !(l1f & _PAGE_RW) ||
|
||||
!rangeset_contains_singleton(mmio_ro_ranges, mfn) )
|
||||
return 0;
|
@ -1,129 +0,0 @@
|
||||
References: FATE#313633
|
||||
|
||||
# HG changeset patch
|
||||
# User Liu, Jinsong <jinsong.liu@intel.com>
|
||||
# Date 1348654362 -7200
|
||||
# Node ID c47ef9592fb39325e33f8406b4bd736cc84482e5
|
||||
# Parent 5d63c633a60b9a1d695594f9c17cf933240bec81
|
||||
x86: Implement TSC adjust feature for HVM guest
|
||||
|
||||
IA32_TSC_ADJUST MSR is maintained separately for each logical
|
||||
processor. A logical processor maintains and uses the IA32_TSC_ADJUST
|
||||
MSR as follows:
|
||||
1). On RESET, the value of the IA32_TSC_ADJUST MSR is 0;
|
||||
2). If an execution of WRMSR to the IA32_TIME_STAMP_COUNTER MSR adds
|
||||
(or subtracts) value X from the TSC, the logical processor also
|
||||
adds (or subtracts) value X from the IA32_TSC_ADJUST MSR;
|
||||
3). If an execution of WRMSR to the IA32_TSC_ADJUST MSR adds (or
|
||||
subtracts) value X from that MSR, the logical processor also adds
|
||||
(or subtracts) value X from the TSC.
|
||||
|
||||
This patch provides tsc adjust support for hvm guest, with it guest OS
|
||||
would be happy when sync tsc.
|
||||
|
||||
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
|
||||
Committed-by: Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/hvm.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/hvm.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/hvm.c
|
||||
@@ -244,6 +244,7 @@ int hvm_set_guest_pat(struct vcpu *v, u6
|
||||
void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc)
|
||||
{
|
||||
uint64_t tsc;
|
||||
+ uint64_t delta_tsc;
|
||||
|
||||
if ( v->domain->arch.vtsc )
|
||||
{
|
||||
@@ -255,10 +256,22 @@ void hvm_set_guest_tsc(struct vcpu *v, u
|
||||
rdtscll(tsc);
|
||||
}
|
||||
|
||||
- v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - tsc;
|
||||
+ delta_tsc = guest_tsc - tsc;
|
||||
+ v->arch.hvm_vcpu.msr_tsc_adjust += delta_tsc
|
||||
+ - v->arch.hvm_vcpu.cache_tsc_offset;
|
||||
+ v->arch.hvm_vcpu.cache_tsc_offset = delta_tsc;
|
||||
+
|
||||
hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
|
||||
}
|
||||
|
||||
+void hvm_set_guest_tsc_adjust(struct vcpu *v, u64 tsc_adjust)
|
||||
+{
|
||||
+ v->arch.hvm_vcpu.cache_tsc_offset += tsc_adjust
|
||||
+ - v->arch.hvm_vcpu.msr_tsc_adjust;
|
||||
+ hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
|
||||
+ v->arch.hvm_vcpu.msr_tsc_adjust = tsc_adjust;
|
||||
+}
|
||||
+
|
||||
u64 hvm_get_guest_tsc(struct vcpu *v)
|
||||
{
|
||||
uint64_t tsc;
|
||||
@@ -277,6 +290,11 @@ u64 hvm_get_guest_tsc(struct vcpu *v)
|
||||
return tsc + v->arch.hvm_vcpu.cache_tsc_offset;
|
||||
}
|
||||
|
||||
+u64 hvm_get_guest_tsc_adjust(struct vcpu *v)
|
||||
+{
|
||||
+ return v->arch.hvm_vcpu.msr_tsc_adjust;
|
||||
+}
|
||||
+
|
||||
void hvm_migrate_timers(struct vcpu *v)
|
||||
{
|
||||
rtc_migrate_timers(v);
|
||||
@@ -2798,6 +2816,10 @@ int hvm_msr_read_intercept(unsigned int
|
||||
*msr_content = hvm_get_guest_tsc(v);
|
||||
break;
|
||||
|
||||
+ case MSR_IA32_TSC_ADJUST:
|
||||
+ *msr_content = hvm_get_guest_tsc_adjust(v);
|
||||
+ break;
|
||||
+
|
||||
case MSR_TSC_AUX:
|
||||
*msr_content = hvm_msr_tsc_aux(v);
|
||||
break;
|
||||
@@ -2911,6 +2933,10 @@ int hvm_msr_write_intercept(unsigned int
|
||||
hvm_set_guest_tsc(v, msr_content);
|
||||
break;
|
||||
|
||||
+ case MSR_IA32_TSC_ADJUST:
|
||||
+ hvm_set_guest_tsc_adjust(v, msr_content);
|
||||
+ break;
|
||||
+
|
||||
case MSR_TSC_AUX:
|
||||
v->arch.hvm_vcpu.msr_tsc_aux = (uint32_t)msr_content;
|
||||
if ( cpu_has_rdtscp
|
||||
@@ -3482,6 +3508,8 @@ void hvm_vcpu_reset_state(struct vcpu *v
|
||||
v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset;
|
||||
hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
|
||||
|
||||
+ v->arch.hvm_vcpu.msr_tsc_adjust = 0;
|
||||
+
|
||||
paging_update_paging_modes(v);
|
||||
|
||||
v->arch.flags |= TF_kernel_mode;
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/hvm/vcpu.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/hvm/vcpu.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/hvm/vcpu.h
|
||||
@@ -137,6 +137,7 @@ struct hvm_vcpu {
|
||||
struct hvm_vcpu_asid n1asid;
|
||||
|
||||
u32 msr_tsc_aux;
|
||||
+ u64 msr_tsc_adjust;
|
||||
|
||||
/* VPMU */
|
||||
struct vpmu_struct vpmu;
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/msr-index.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/msr-index.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/msr-index.h
|
||||
@@ -286,6 +286,7 @@
|
||||
#define MSR_IA32_PLATFORM_ID 0x00000017
|
||||
#define MSR_IA32_EBL_CR_POWERON 0x0000002a
|
||||
#define MSR_IA32_EBC_FREQUENCY_ID 0x0000002c
|
||||
+#define MSR_IA32_TSC_ADJUST 0x0000003b
|
||||
|
||||
#define MSR_IA32_APICBASE 0x0000001b
|
||||
#define MSR_IA32_APICBASE_BSP (1<<8)
|
@ -1,104 +0,0 @@
|
||||
References: FATE#313633
|
||||
|
||||
# HG changeset patch
|
||||
# User Liu, Jinsong <jinsong.liu@intel.com>
|
||||
# Date 1348654418 -7200
|
||||
# Node ID 56fb977ce6eb4626a02d4a7a34e85009bb8ee3e0
|
||||
# Parent c47ef9592fb39325e33f8406b4bd736cc84482e5
|
||||
x86: Save/restore TSC adjust during HVM guest migration
|
||||
|
||||
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
|
||||
Committed-by: Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
--- a/tools/misc/xen-hvmctx.c
|
||||
+++ b/tools/misc/xen-hvmctx.c
|
||||
@@ -390,6 +390,13 @@ static void dump_vmce_vcpu(void)
|
||||
printf(" VMCE_VCPU: caps %" PRIx64 "\n", p.caps);
|
||||
}
|
||||
|
||||
+static void dump_tsc_adjust(void)
|
||||
+{
|
||||
+ HVM_SAVE_TYPE(TSC_ADJUST) p;
|
||||
+ READ(p);
|
||||
+ printf(" TSC_ADJUST: tsc_adjust %" PRIx64 "\n", p.tsc_adjust);
|
||||
+}
|
||||
+
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int entry, domid;
|
||||
@@ -457,6 +464,7 @@ int main(int argc, char **argv)
|
||||
case HVM_SAVE_CODE(VIRIDIAN_DOMAIN): dump_viridian_domain(); break;
|
||||
case HVM_SAVE_CODE(VIRIDIAN_VCPU): dump_viridian_vcpu(); break;
|
||||
case HVM_SAVE_CODE(VMCE_VCPU): dump_vmce_vcpu(); break;
|
||||
+ case HVM_SAVE_CODE(TSC_ADJUST): dump_tsc_adjust(); break;
|
||||
case HVM_SAVE_CODE(END): break;
|
||||
default:
|
||||
printf(" ** Don't understand type %u: skipping\n",
|
||||
--- a/xen/arch/x86/hvm/hvm.c
|
||||
+++ b/xen/arch/x86/hvm/hvm.c
|
||||
@@ -610,6 +610,46 @@ void hvm_domain_destroy(struct domain *d
|
||||
hvm_destroy_cacheattr_region_list(d);
|
||||
}
|
||||
|
||||
+static int hvm_save_tsc_adjust(struct domain *d, hvm_domain_context_t *h)
|
||||
+{
|
||||
+ struct vcpu *v;
|
||||
+ struct hvm_tsc_adjust ctxt;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ for_each_vcpu ( d, v )
|
||||
+ {
|
||||
+ ctxt.tsc_adjust = v->arch.hvm_vcpu.msr_tsc_adjust;
|
||||
+ err = hvm_save_entry(TSC_ADJUST, v->vcpu_id, h, &ctxt);
|
||||
+ if ( err )
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int hvm_load_tsc_adjust(struct domain *d, hvm_domain_context_t *h)
|
||||
+{
|
||||
+ unsigned int vcpuid = hvm_load_instance(h);
|
||||
+ struct vcpu *v;
|
||||
+ struct hvm_tsc_adjust ctxt;
|
||||
+
|
||||
+ if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
|
||||
+ {
|
||||
+ dprintk(XENLOG_G_ERR, "HVM restore: dom%d has no vcpu%u\n",
|
||||
+ d->domain_id, vcpuid);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if ( hvm_load_entry(TSC_ADJUST, h, &ctxt) != 0 )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ v->arch.hvm_vcpu.msr_tsc_adjust = ctxt.tsc_adjust;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+HVM_REGISTER_SAVE_RESTORE(TSC_ADJUST, hvm_save_tsc_adjust,
|
||||
+ hvm_load_tsc_adjust, 1, HVMSR_PER_VCPU);
|
||||
+
|
||||
static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
{
|
||||
struct vcpu *v;
|
||||
--- a/xen/include/public/arch-x86/hvm/save.h
|
||||
+++ b/xen/include/public/arch-x86/hvm/save.h
|
||||
@@ -581,9 +581,15 @@ struct hvm_vmce_vcpu {
|
||||
|
||||
DECLARE_HVM_SAVE_TYPE(VMCE_VCPU, 18, struct hvm_vmce_vcpu);
|
||||
|
||||
+struct hvm_tsc_adjust {
|
||||
+ uint64_t tsc_adjust;
|
||||
+};
|
||||
+
|
||||
+DECLARE_HVM_SAVE_TYPE(TSC_ADJUST, 19, struct hvm_tsc_adjust);
|
||||
+
|
||||
/*
|
||||
* Largest type-code in use
|
||||
*/
|
||||
-#define HVM_SAVE_CODE_MAX 18
|
||||
+#define HVM_SAVE_CODE_MAX 19
|
||||
|
||||
#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
|
@ -1,39 +0,0 @@
|
||||
References: FATE#313633
|
||||
|
||||
# HG changeset patch
|
||||
# User Liu, Jinsong <jinsong.liu@intel.com>
|
||||
# Date 1348654470 -7200
|
||||
# Node ID 3aa66543a51ba77cb73e8c874e2416d065426a22
|
||||
# Parent 56fb977ce6eb4626a02d4a7a34e85009bb8ee3e0
|
||||
x86: Expose TSC adjust to HVM guest
|
||||
|
||||
Intel latest SDM (17.13.3) release a new MSR CPUID.7.0.EBX[1]=1
|
||||
indicates TSC_ADJUST MSR 0x3b is supported.
|
||||
|
||||
This patch expose it to hvm guest.
|
||||
|
||||
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
|
||||
Committed-by: Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
--- a/tools/libxc/xc_cpufeature.h
|
||||
+++ b/tools/libxc/xc_cpufeature.h
|
||||
@@ -128,6 +128,7 @@
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx) */
|
||||
#define X86_FEATURE_FSGSBASE 0 /* {RD,WR}{FS,GS}BASE instructions */
|
||||
+#define X86_FEATURE_TSC_ADJUST 1 /* Tsc thread offset */
|
||||
#define X86_FEATURE_BMI1 3 /* 1st group bit manipulation extensions */
|
||||
#define X86_FEATURE_HLE 4 /* Hardware Lock Elision */
|
||||
#define X86_FEATURE_AVX2 5 /* AVX2 instructions */
|
||||
--- a/tools/libxc/xc_cpuid_x86.c
|
||||
+++ b/tools/libxc/xc_cpuid_x86.c
|
||||
@@ -362,7 +362,8 @@ static void xc_cpuid_hvm_policy(
|
||||
|
||||
case 0x00000007: /* Intel-defined CPU features */
|
||||
if ( input[1] == 0 ) {
|
||||
- regs[1] &= (bitmaskof(X86_FEATURE_BMI1) |
|
||||
+ regs[1] &= (bitmaskof(X86_FEATURE_TSC_ADJUST) |
|
||||
+ bitmaskof(X86_FEATURE_BMI1) |
|
||||
bitmaskof(X86_FEATURE_HLE) |
|
||||
bitmaskof(X86_FEATURE_AVX2) |
|
||||
bitmaskof(X86_FEATURE_SMEP) |
|
@ -1,61 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1349172840 -7200
|
||||
# Node ID 87bf99fad7a9f018530d13213f57610621838085
|
||||
# Parent 5fbdbf585f5f2ee9a3e3c75a8a9f9f2cc6eda65c
|
||||
x86/Intel: add further support for Ivy Bridge CPU models
|
||||
|
||||
And some initial Haswell ones at once.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Nakajima, Jun" <jun.nakajima@intel.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/acpi/cpu_idle.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/acpi/cpu_idle.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/acpi/cpu_idle.c
|
||||
@@ -105,11 +105,15 @@ static void do_get_hw_residencies(void *
|
||||
|
||||
switch ( c->x86_model )
|
||||
{
|
||||
- /* Ivy bridge */
|
||||
- case 0x3A:
|
||||
/* Sandy bridge */
|
||||
case 0x2A:
|
||||
case 0x2D:
|
||||
+ /* Ivy bridge */
|
||||
+ case 0x3A:
|
||||
+ case 0x3E:
|
||||
+ /* Haswell */
|
||||
+ case 0x3C:
|
||||
+ case 0x45:
|
||||
GET_PC2_RES(hw_res->pc2);
|
||||
GET_CC7_RES(hw_res->cc7);
|
||||
/* fall through */
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmx.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/vmx/vmx.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmx.c
|
||||
@@ -1825,7 +1825,9 @@ static const struct lbr_info *last_branc
|
||||
/* Sandy Bridge */
|
||||
case 42: case 45:
|
||||
/* Ivy Bridge */
|
||||
- case 58:
|
||||
+ case 58: case 62:
|
||||
+ /* Haswell */
|
||||
+ case 60: case 69:
|
||||
return nh_lbr;
|
||||
break;
|
||||
/* Atom */
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vpmu_core2.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/vmx/vpmu_core2.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vpmu_core2.c
|
||||
@@ -747,6 +747,7 @@ int vmx_vpmu_initialise(struct vcpu *v,
|
||||
case 46:
|
||||
case 47:
|
||||
case 58:
|
||||
+ case 62:
|
||||
ret = core2_vpmu_initialise(v, vpmu_flags);
|
||||
if ( !ret )
|
||||
vpmu->arch_vpmu_ops = &core2_vpmu_ops;
|
@ -1,76 +0,0 @@
|
||||
changeset: 26077:33348baecf37
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:34:59 2012 +0100
|
||||
files: stubdom/grub.patches/70compiler_warnings.diff
|
||||
description:
|
||||
stubdom: fix compile errors in grub
|
||||
|
||||
Building xen.rpm in SLES11 started to fail due to these compiler
|
||||
warnings:
|
||||
|
||||
[ 1436s] ../grub-upstream/netboot/fsys_tftp.c:213: warning: operation on 'block' may be undefined
|
||||
[ 1437s] ../grub-upstream/netboot/main.c:444: warning: operation on 'block' may be undefined
|
||||
|
||||
[ 1234s] E: xen sequence-point ../grub-upstream/netboot/fsys_tftp.c:213
|
||||
[ 1234s] E: xen sequence-point ../grub-upstream/netboot/main.c:444
|
||||
|
||||
The reason for this is that the assignment is done twice:
|
||||
tp.u.ack.block = ((uint16_t)( (((uint16_t)((block = prevblock)) & (uint16_t)0x00ffU) << 8) | (((uint16_t)((block = prevblock)) & (uint16_t)0xff00U) >> 8)));
|
||||
|
||||
Fix this package build error by adding another patch for grub, which
|
||||
moves the assignment out of the macro usage.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 8dcab28b8081 -r 33348baecf37 stubdom/grub.patches/70compiler_warnings.diff
|
||||
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
|
||||
+++ b/stubdom/grub.patches/70compiler_warnings.diff Thu Oct 18 09:34:59 2012 +0100
|
||||
@@ -0,0 +1,45 @@
|
||||
+[ 1436s] ../grub-upstream/netboot/fsys_tftp.c:213: warning: operation on 'block' may be undefined
|
||||
+[ 1437s] ../grub-upstream/netboot/main.c:444: warning: operation on 'block' may be undefined
|
||||
+
|
||||
+[ 1234s] E: xen sequence-point ../grub-upstream/netboot/fsys_tftp.c:213
|
||||
+[ 1234s] E: xen sequence-point ../grub-upstream/netboot/main.c:444
|
||||
+
|
||||
+---
|
||||
+ netboot/fsys_tftp.c | 5 ++++-
|
||||
+ netboot/main.c | 5 ++++-
|
||||
+ 2 files changed, 8 insertions(+), 2 deletions(-)
|
||||
+
|
||||
+Index: grub-0.97/netboot/fsys_tftp.c
|
||||
+===================================================================
|
||||
+--- grub-0.97.orig/netboot/fsys_tftp.c
|
||||
++++ grub-0.97/netboot/fsys_tftp.c
|
||||
+@@ -209,8 +209,11 @@ buf_fill (int abort)
|
||||
+ break;
|
||||
+
|
||||
+ if ((block || bcounter) && (block != prevblock + (unsigned short) 1))
|
||||
++ {
|
||||
++ block = prevblock;
|
||||
+ /* Block order should be continuous */
|
||||
+- tp.u.ack.block = htons (block = prevblock);
|
||||
++ tp.u.ack.block = htons (block);
|
||||
++ }
|
||||
+
|
||||
+ /* Should be continuous. */
|
||||
+ tp.opcode = abort ? htons (TFTP_ERROR) : htons (TFTP_ACK);
|
||||
+Index: grub-0.97/netboot/main.c
|
||||
+===================================================================
|
||||
+--- grub-0.97.orig/netboot/main.c
|
||||
++++ grub-0.97/netboot/main.c
|
||||
+@@ -440,8 +440,11 @@ tftp (const char *name, int (*fnc) (unsi
|
||||
+ break;
|
||||
+
|
||||
+ if ((block || bcounter) && (block != prevblock + 1))
|
||||
++ {
|
||||
++ block = prevblock;
|
||||
+ /* Block order should be continuous */
|
||||
+- tp.u.ack.block = htons (block = prevblock);
|
||||
++ tp.u.ack.block = htons (block);
|
||||
++ }
|
||||
+
|
||||
+ /* Should be continuous. */
|
||||
+ tp.opcode = htons (TFTP_ACK);
|
@ -1,187 +0,0 @@
|
||||
changeset: 26078:019ca95dfa34
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:00 2012 +0100
|
||||
files: Makefile README install.sh tools/hotplug/Linux/Makefile tools/hotplug/Linux/xen-backend.agent
|
||||
description:
|
||||
hotplug/Linux: remove hotplug support, rely on udev instead
|
||||
|
||||
Hotplug has been replaced by udev since several years. Remove the
|
||||
hotplug related files and install udev unconditionally.
|
||||
|
||||
This makes it possible to remove udev from rpm BuildRequires which
|
||||
reduces the buildtime dependency chain. For openSuSE:Factory it was
|
||||
done just now:
|
||||
http://lists.opensuse.org/opensuse-buildservice/2012-10/msg00085.html
|
||||
|
||||
The patch by itself will have no practical impact unless someone
|
||||
attempts to build and run a Xen dom0 on a really old base system. e.g.
|
||||
circa SLES9/2007 or earlier
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 33348baecf37 -r 019ca95dfa34 Makefile
|
||||
--- a/Makefile Thu Oct 18 09:34:59 2012 +0100
|
||||
+++ b/Makefile Thu Oct 18 09:35:00 2012 +0100
|
||||
@@ -223,7 +223,6 @@ uninstall:
|
||||
$(MAKE) -C xen uninstall
|
||||
rm -rf $(D)$(CONFIG_DIR)/init.d/xendomains $(D)$(CONFIG_DIR)/init.d/xend
|
||||
rm -rf $(D)$(CONFIG_DIR)/init.d/xencommons $(D)$(CONFIG_DIR)/init.d/xen-watchdog
|
||||
- rm -rf $(D)$(CONFIG_DIR)/hotplug/xen-backend.agent
|
||||
rm -f $(D)$(CONFIG_DIR)/udev/rules.d/xen-backend.rules
|
||||
rm -f $(D)$(CONFIG_DIR)/udev/rules.d/xend.rules
|
||||
rm -f $(D)$(SYSCONFIG_DIR)/xendomains
|
||||
diff -r 33348baecf37 -r 019ca95dfa34 README
|
||||
--- a/README Thu Oct 18 09:34:59 2012 +0100
|
||||
+++ b/README Thu Oct 18 09:35:00 2012 +0100
|
||||
@@ -54,7 +54,7 @@ provided by your OS distributor:
|
||||
* pkg-config
|
||||
* bridge-utils package (/sbin/brctl)
|
||||
* iproute package (/sbin/ip)
|
||||
- * hotplug or udev
|
||||
+ * udev
|
||||
* GNU bison and GNU flex
|
||||
* GNU gettext
|
||||
* 16-bit x86 assembler, loader and compiler (dev86 rpm or bin86 & bcc debs)
|
||||
@@ -120,9 +120,9 @@ 4. To rebuild an existing tree without m
|
||||
|
||||
make install and make dist differ in that make install does the
|
||||
right things for your local machine (installing the appropriate
|
||||
- version of hotplug or udev scripts, for example), but make dist
|
||||
- includes all versions of those scripts, so that you can copy the dist
|
||||
- directory to another machine and install from that distribution.
|
||||
+ version of udev scripts, for example), but make dist includes all
|
||||
+ versions of those scripts, so that you can copy the dist directory
|
||||
+ to another machine and install from that distribution.
|
||||
|
||||
Python Runtime Libraries
|
||||
========================
|
||||
diff -r 33348baecf37 -r 019ca95dfa34 install.sh
|
||||
--- a/install.sh Thu Oct 18 09:34:59 2012 +0100
|
||||
+++ b/install.sh Thu Oct 18 09:35:00 2012 +0100
|
||||
@@ -27,20 +27,6 @@ echo "Installing Xen from '$src' to '$ds
|
||||
echo "Installing Xen from '$src' to '$dst'..."
|
||||
(cd $src; tar -cf - * ) | tar -C "$tmp" -xf -
|
||||
|
||||
-[ -x "$(which udevinfo)" ] && \
|
||||
- UDEV_VERSION=$(udevinfo -V | sed -e 's/^[^0-9]* \([0-9]\{1,\}\)[^0-9]\{0,\}/\1/')
|
||||
-
|
||||
-[ -z "$UDEV_VERSION" -a -x /sbin/udevadm ] && \
|
||||
- UDEV_VERSION=$(/sbin/udevadm info -V | awk '{print $NF}')
|
||||
-
|
||||
-if [ -n "$UDEV_VERSION" ] && [ $UDEV_VERSION -ge 059 ]; then
|
||||
- echo " - installing for udev-based system"
|
||||
- rm -rf "$tmp/etc/hotplug"
|
||||
-else
|
||||
- echo " - installing for hotplug-based system"
|
||||
- rm -rf "$tmp/etc/udev"
|
||||
-fi
|
||||
-
|
||||
echo " - modifying permissions"
|
||||
chmod -R a+rX "$tmp"
|
||||
|
||||
diff -r 33348baecf37 -r 019ca95dfa34 tools/hotplug/Linux/Makefile
|
||||
--- a/tools/hotplug/Linux/Makefile Thu Oct 18 09:34:59 2012 +0100
|
||||
+++ b/tools/hotplug/Linux/Makefile Thu Oct 18 09:35:00 2012 +0100
|
||||
@@ -27,31 +27,8 @@ XEN_SCRIPT_DATA += block-common.sh vtpm-
|
||||
XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh vtpm-hotplug-common.sh
|
||||
XEN_SCRIPT_DATA += vtpm-migration.sh vtpm-impl
|
||||
|
||||
-XEN_HOTPLUG_DIR = $(CONFIG_DIR)/hotplug
|
||||
-XEN_HOTPLUG_SCRIPTS = xen-backend.agent
|
||||
-
|
||||
-UDEVVER = 0
|
||||
-ifeq ($(shell [ -x /sbin/udevadm ] && echo 1),1)
|
||||
-UDEVVER = $(shell /sbin/udevadm info -V | sed -e 's/^[^0-9]* \([0-9]\{1,\}\)[^0-9]\{0,\}/\1/' )
|
||||
-endif
|
||||
-ifeq ($(shell [ -x /usr/bin/udevinfo ] && echo 1),1)
|
||||
-UDEVVER = $(shell /usr/bin/udevinfo -V | sed -e 's/^[^0-9]* \([0-9]\{1,\}\)[^0-9]\{0,\}/\1/' )
|
||||
-endif
|
||||
-
|
||||
UDEV_RULES_DIR = $(CONFIG_DIR)/udev
|
||||
UDEV_RULES = xen-backend.rules xend.rules
|
||||
-
|
||||
-DI = $(if $(DISTDIR),$(shell readlink -f $(DISTDIR)),)
|
||||
-DE = $(if $(DESTDIR),$(shell readlink -f $(DESTDIR)),)
|
||||
-ifeq ($(findstring $(DI),$(DE)),$(DI))
|
||||
-HOTPLUGS=install-hotplug install-udev
|
||||
-else
|
||||
-ifeq ($(shell [ $(UDEVVER) -ge 059 ] && echo 1),1)
|
||||
-HOTPLUGS=install-udev
|
||||
-else
|
||||
-HOTPLUGS=install-hotplug
|
||||
-endif
|
||||
-endif
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
@@ -60,7 +37,7 @@ build:
|
||||
build:
|
||||
|
||||
.PHONY: install
|
||||
-install: all install-initd install-scripts $(HOTPLUGS)
|
||||
+install: all install-initd install-scripts install-udev
|
||||
|
||||
# See docs/misc/distro_mapping.txt for INITD_DIR location
|
||||
.PHONY: install-initd
|
||||
@@ -87,15 +64,6 @@ install-scripts:
|
||||
$(INSTALL_DATA) $$i $(DESTDIR)$(XEN_SCRIPT_DIR); \
|
||||
done
|
||||
|
||||
-.PHONY: install-hotplug
|
||||
-install-hotplug:
|
||||
- [ -d $(DESTDIR)$(XEN_HOTPLUG_DIR) ] || \
|
||||
- $(INSTALL_DIR) $(DESTDIR)$(XEN_HOTPLUG_DIR)
|
||||
- set -e; for i in $(XEN_HOTPLUG_SCRIPTS); \
|
||||
- do \
|
||||
- $(INSTALL_PROG) $$i $(DESTDIR)$(XEN_HOTPLUG_DIR); \
|
||||
- done
|
||||
-
|
||||
.PHONY: install-udev
|
||||
install-udev:
|
||||
[ -d $(DESTDIR)$(UDEV_RULES_DIR) ] || \
|
||||
diff -r 33348baecf37 -r 019ca95dfa34 tools/hotplug/Linux/xen-backend.agent
|
||||
--- a/tools/hotplug/Linux/xen-backend.agent Thu Oct 18 09:34:59 2012 +0100
|
||||
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
|
||||
@@ -1,39 +0,0 @@
|
||||
-#! /bin/bash
|
||||
-
|
||||
-PATH=/etc/xen/scripts:$PATH
|
||||
-
|
||||
-. /etc/xen/scripts/locking.sh
|
||||
-
|
||||
-claim_lock xenbus_hotplug_global
|
||||
-
|
||||
-case "$XENBUS_TYPE" in
|
||||
- tap)
|
||||
- /etc/xen/scripts/blktap "$ACTION"
|
||||
- ;;
|
||||
- vbd)
|
||||
- /etc/xen/scripts/block "$ACTION"
|
||||
- ;;
|
||||
- vtpm)
|
||||
- /etc/xen/scripts/vtpm "$ACTION"
|
||||
- ;;
|
||||
- vif)
|
||||
- [ -n "$script" ] && $script "$ACTION"
|
||||
- ;;
|
||||
- vscsi)
|
||||
- /etc/xen/scripts/vscsi "$ACTION"
|
||||
- ;;
|
||||
-esac
|
||||
-
|
||||
-case "$ACTION" in
|
||||
- add)
|
||||
- ;;
|
||||
- remove)
|
||||
- /etc/xen/scripts/xen-hotplug-cleanup
|
||||
- ;;
|
||||
- online)
|
||||
- ;;
|
||||
- offline)
|
||||
- ;;
|
||||
-esac
|
||||
-
|
||||
-release_lock xenbus_hotplug_global
|
@ -1,36 +0,0 @@
|
||||
changeset: 26079:b3b03536789a
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:01 2012 +0100
|
||||
files: tools/hotplug/Linux/locking.sh
|
||||
description:
|
||||
hotplug/Linux: close lockfd after lock attempt
|
||||
|
||||
When a HVM guest is shutdown some of the 'remove' events can not claim
|
||||
the lock for some reason. Instead they try to grab the lock in a busy
|
||||
loop, until udev reaps the xen-hotplug-cleanup helper.
|
||||
After analyzing the resulting logfile its not obvious what the cause is.
|
||||
The only explanation is that bash (?) gets confused if the same lockfd
|
||||
is opened again and again. Closing it in each iteration seem to fix the
|
||||
issue.
|
||||
|
||||
This was observed with sles11sp2 (bash 3.2) and 4.2 xend.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <Ian.campbell@citrix.com>
|
||||
[ ijc -- added the comment ]
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 019ca95dfa34 -r b3b03536789a tools/hotplug/Linux/locking.sh
|
||||
--- a/tools/hotplug/Linux/locking.sh Thu Oct 18 09:35:00 2012 +0100
|
||||
+++ b/tools/hotplug/Linux/locking.sh Thu Oct 18 09:35:01 2012 +0100
|
||||
@@ -59,6 +59,9 @@ claim_lock()
|
||||
print "y\n" if $fd_inum eq $file_inum;
|
||||
' "$_lockfile" )
|
||||
if [ x$rightfile = xy ]; then break; fi
|
||||
+ # Some versions of bash appear to be buggy if the same
|
||||
+ # $_lockfile is opened repeatedly. Close the current fd here.
|
||||
+ eval "exec $_lockfd<&-"
|
||||
done
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
changeset: 26081:02064298ebcb
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:03 2012 +0100
|
||||
files: stubdom/Makefile
|
||||
description:
|
||||
stubdom: fix rpmlint warning spurious-executable-perm
|
||||
|
||||
[ 1758s] xen-tools.x86_64: E: spurious-executable-perm (Badness: 50) /usr/lib/xen/boot/xenstore-stubdom.gz
|
||||
[ 1758s] The file is installed with executable permissions, but was identified as one
|
||||
[ 1758s] that probably should not be executable. Verify if the executable bits are
|
||||
[ 1758s] desired, and remove if not. NOTE: example scripts should be packaged under
|
||||
[ 1758s] %docdir/examples, which will avoid this warning.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 25b2f53d2583 -r 02064298ebcb stubdom/Makefile
|
||||
--- a/stubdom/Makefile Thu Oct 18 09:35:02 2012 +0100
|
||||
+++ b/stubdom/Makefile Thu Oct 18 09:35:03 2012 +0100
|
||||
@@ -396,7 +396,7 @@ install-grub: pv-grub
|
||||
|
||||
install-xenstore: xenstore-stubdom
|
||||
$(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/boot"
|
||||
- $(INSTALL_PROG) mini-os-$(XEN_TARGET_ARCH)-xenstore/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/xenstore-stubdom.gz"
|
||||
+ $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-xenstore/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/xenstore-stubdom.gz"
|
||||
|
||||
#######
|
||||
# clean
|
@ -1,30 +0,0 @@
|
||||
changeset: 26082:8cf26ace9ca0
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:03 2012 +0100
|
||||
files: tools/blktap2/vhd/lib/Makefile
|
||||
description:
|
||||
blktap2/libvhd: fix rpmlint warning spurious-executable-perm
|
||||
|
||||
[ 1758s] xen-devel.x86_64: E: spurious-executable-perm (Badness: 50) /usr/lib64/libvhd.a
|
||||
[ 1758s] The file is installed with executable permissions, but was identified as one
|
||||
[ 1758s] that probably should not be executable. Verify if the executable bits are
|
||||
[ 1758s] desired, and remove if not. NOTE: example scripts should be packaged under
|
||||
[ 1758s] %docdir/examples, which will avoid this warning.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 02064298ebcb -r 8cf26ace9ca0 tools/blktap2/vhd/lib/Makefile
|
||||
--- a/tools/blktap2/vhd/lib/Makefile Thu Oct 18 09:35:03 2012 +0100
|
||||
+++ b/tools/blktap2/vhd/lib/Makefile Thu Oct 18 09:35:03 2012 +0100
|
||||
@@ -68,7 +68,7 @@ libvhd.so.$(LIBVHD-MAJOR).$(LIBVHD-MINOR
|
||||
|
||||
install: all
|
||||
$(INSTALL_DIR) -p $(DESTDIR)$(INST-DIR)
|
||||
- $(INSTALL_PROG) libvhd.a $(DESTDIR)$(INST-DIR)
|
||||
+ $(INSTALL_DATA) libvhd.a $(DESTDIR)$(INST-DIR)
|
||||
$(INSTALL_PROG) libvhd.so.$(LIBVHD-MAJOR).$(LIBVHD-MINOR) $(DESTDIR)$(INST-DIR)
|
||||
ln -sf libvhd.so.$(LIBVHD-MAJOR).$(LIBVHD-MINOR) $(DESTDIR)$(INST-DIR)/libvhd.so.$(LIBVHD-MAJOR)
|
||||
ln -sf libvhd.so.$(LIBVHD-MAJOR) $(DESTDIR)$(INST-DIR)/libvhd.so
|
@ -1,51 +0,0 @@
|
||||
changeset: 26083:3fbeb019d522
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:04 2012 +0100
|
||||
files: tools/blktap/lib/Makefile
|
||||
description:
|
||||
blktap: fix rpmlint warning spurious-executable-perm
|
||||
|
||||
[ 1758s] xen-devel.x86_64: E: spurious-executable-perm (Badness: 50) /usr/lib64/libblktap.a
|
||||
[ 1758s] The file is installed with executable permissions, but was identified as one
|
||||
[ 1758s] that probably should not be executable. Verify if the executable bits are
|
||||
[ 1758s] desired, and remove if not. NOTE: example scripts should be packaged under
|
||||
[ 1758s] %docdir/examples, which will avoid this warning.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 8cf26ace9ca0 -r 3fbeb019d522 tools/blktap/lib/Makefile
|
||||
--- a/tools/blktap/lib/Makefile Thu Oct 18 09:35:03 2012 +0100
|
||||
+++ b/tools/blktap/lib/Makefile Thu Oct 18 09:35:04 2012 +0100
|
||||
@@ -23,23 +23,25 @@ OBJS_PIC = $(SRCS:.c=.opic)
|
||||
OBJS_PIC = $(SRCS:.c=.opic)
|
||||
IBINS :=
|
||||
|
||||
-LIB = libblktap.a libblktap.so.$(MAJOR).$(MINOR)
|
||||
+LIB = libblktap.a
|
||||
+LIB_SO = libblktap.so.$(MAJOR).$(MINOR)
|
||||
|
||||
.PHONY: all
|
||||
-all: $(LIB)
|
||||
+all: $(LIB) $(LIB_SO)
|
||||
|
||||
.PHONY: install
|
||||
install: all
|
||||
$(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
|
||||
$(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)
|
||||
- $(INSTALL_PROG) $(LIB) $(DESTDIR)$(LIBDIR)
|
||||
+ $(INSTALL_PROG) $(LIB_SO) $(DESTDIR)$(LIBDIR)
|
||||
+ $(INSTALL_DATA) $(LIB) $(DESTDIR)$(LIBDIR)
|
||||
ln -sf libblktap.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libblktap.so.$(MAJOR)
|
||||
ln -sf libblktap.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libblktap.so
|
||||
$(INSTALL_DATA) blktaplib.h $(DESTDIR)$(INCLUDEDIR)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
- rm -rf *.a *.so* *.o *.opic *.rpm $(LIB) *~ $(DEPS) xen TAGS
|
||||
+ rm -rf *.a *.so* *.o *.opic *.rpm $(LIB) $(LIB_SO) *~ $(DEPS) xen TAGS
|
||||
|
||||
libblktap.so.$(MAJOR).$(MINOR): $(OBJS_PIC)
|
||||
$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,$(SONAME) $(SHLIB_LDFLAGS) \
|
@ -1,34 +0,0 @@
|
||||
changeset: 26084:fe9a0eb9aaaa
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:05 2012 +0100
|
||||
files: tools/hotplug/common/Makefile
|
||||
description:
|
||||
hotplug: install hotplugpath.sh as data file
|
||||
|
||||
rpmlint complains a script helper which is only sourced:
|
||||
|
||||
[ 1875s] xen-tools.i586: W: script-without-shebang /etc/xen/scripts/hotplugpath.sh
|
||||
[ 1875s] This text file has executable bits set or is located in a path dedicated for
|
||||
[ 1875s] executables, but lacks a shebang and cannot thus be executed. If the file is
|
||||
[ 1875s] meant to be an executable script, add the shebang, otherwise remove the
|
||||
[ 1875s] executable bits or move the file elsewhere.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 3fbeb019d522 -r fe9a0eb9aaaa tools/hotplug/common/Makefile
|
||||
--- a/tools/hotplug/common/Makefile Thu Oct 18 09:35:04 2012 +0100
|
||||
+++ b/tools/hotplug/common/Makefile Thu Oct 18 09:35:05 2012 +0100
|
||||
@@ -6,8 +6,8 @@ HOTPLUGPATH="hotplugpath.sh"
|
||||
# OS-independent hotplug scripts go in this directory
|
||||
|
||||
# Xen scripts to go there.
|
||||
-XEN_SCRIPTS = $(HOTPLUGPATH)
|
||||
-XEN_SCRIPT_DATA =
|
||||
+XEN_SCRIPTS =
|
||||
+XEN_SCRIPT_DATA = $(HOTPLUGPATH)
|
||||
|
||||
genpath-target = $(call buildmakevars2file,$(HOTPLUGPATH))
|
||||
$(eval $(genpath-target))
|
@ -1,33 +0,0 @@
|
||||
changeset: 26085:e32f4301f384
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:06 2012 +0100
|
||||
files: stubdom/Makefile
|
||||
description:
|
||||
stubdom: install stubdompath.sh as data file
|
||||
|
||||
rpmlint complains a script helper which is only sourced:
|
||||
|
||||
[ 1875s] xen-tools.i586: W: script-without-shebang /usr/lib/xen/bin/stubdompath.sh
|
||||
[ 1875s] This text file has executable bits set or is located in a path dedicated for
|
||||
[ 1875s] executables, but lacks a shebang and cannot thus be executed. If the file is
|
||||
[ 1875s] meant to be an executable script, add the shebang, otherwise remove the
|
||||
[ 1875s] executable bits or move the file elsewhere.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r fe9a0eb9aaaa -r e32f4301f384 stubdom/Makefile
|
||||
--- a/stubdom/Makefile Thu Oct 18 09:35:05 2012 +0100
|
||||
+++ b/stubdom/Makefile Thu Oct 18 09:35:06 2012 +0100
|
||||
@@ -386,7 +386,8 @@ install-readme:
|
||||
|
||||
install-ioemu: ioemu-stubdom
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(LIBEXEC)"
|
||||
- $(INSTALL_PROG) stubdompath.sh stubdom-dm "$(DESTDIR)$(LIBEXEC)"
|
||||
+ $(INSTALL_PROG) stubdom-dm "$(DESTDIR)$(LIBEXEC)"
|
||||
+ $(INSTALL_DATA) stubdompath.sh "$(DESTDIR)$(LIBEXEC)"
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(XENFIRMWAREDIR)"
|
||||
$(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-ioemu/mini-os.gz "$(DESTDIR)$(XENFIRMWAREDIR)/ioemu-stubdom.gz"
|
||||
|
@ -1,21 +0,0 @@
|
||||
changeset: 26086:ba6b1db89ec8
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:07 2012 +0100
|
||||
files: tools/hotplug/Linux/init.d/sysconfig.xendomains
|
||||
description:
|
||||
hotplug/Linux: correct sysconfig tag in xendomains
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r e32f4301f384 -r ba6b1db89ec8 tools/hotplug/Linux/init.d/sysconfig.xendomains
|
||||
--- a/tools/hotplug/Linux/init.d/sysconfig.xendomains Thu Oct 18 09:35:06 2012 +0100
|
||||
+++ b/tools/hotplug/Linux/init.d/sysconfig.xendomains Thu Oct 18 09:35:07 2012 +0100
|
||||
@@ -1,4 +1,4 @@
|
||||
-## Path: System/xen
|
||||
+## Path: System/Virtualization
|
||||
## Description: xen domain start/stop on boot
|
||||
## Type: string
|
||||
## Default:
|
@ -1,36 +0,0 @@
|
||||
changeset: 26087:6239ace16749
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Thu Oct 18 09:35:07 2012 +0100
|
||||
files: tools/hotplug/Linux/Makefile
|
||||
description:
|
||||
hotplug/Linux: install sysconfig files as data files
|
||||
|
||||
rpmlint complains about wrong permissions of config files:
|
||||
|
||||
[ 455s] xen-tools.i586: W: script-without-shebang /var/adm/fillup-templates/sysconfig.xendomains
|
||||
[ 455s] xen-tools.i586: W: script-without-shebang /var/adm/fillup-templates/sysconfig.xencommons
|
||||
[ 455s] This text file has executable bits set or is located in a path dedicated for
|
||||
[ 455s] executables, but lacks a shebang and cannot thus be executed. If the file is
|
||||
[ 455s] meant to be an executable script, add the shebang, otherwise remove the
|
||||
[ 455s] executable bits or move the file elsewhere.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r ba6b1db89ec8 -r 6239ace16749 tools/hotplug/Linux/Makefile
|
||||
--- a/tools/hotplug/Linux/Makefile Thu Oct 18 09:35:07 2012 +0100
|
||||
+++ b/tools/hotplug/Linux/Makefile Thu Oct 18 09:35:07 2012 +0100
|
||||
@@ -46,9 +46,9 @@ install-initd:
|
||||
[ -d $(DESTDIR)$(SYSCONFIG_DIR) ] || $(INSTALL_DIR) $(DESTDIR)$(SYSCONFIG_DIR)
|
||||
$(INSTALL_PROG) $(XEND_INITD) $(DESTDIR)$(INITD_DIR)
|
||||
$(INSTALL_PROG) $(XENDOMAINS_INITD) $(DESTDIR)$(INITD_DIR)
|
||||
- $(INSTALL_PROG) $(XENDOMAINS_SYSCONFIG) $(DESTDIR)$(SYSCONFIG_DIR)/xendomains
|
||||
+ $(INSTALL_DATA) $(XENDOMAINS_SYSCONFIG) $(DESTDIR)$(SYSCONFIG_DIR)/xendomains
|
||||
$(INSTALL_PROG) $(XENCOMMONS_INITD) $(DESTDIR)$(INITD_DIR)
|
||||
- $(INSTALL_PROG) $(XENCOMMONS_SYSCONFIG) $(DESTDIR)$(SYSCONFIG_DIR)/xencommons
|
||||
+ $(INSTALL_DATA) $(XENCOMMONS_SYSCONFIG) $(DESTDIR)$(SYSCONFIG_DIR)/xencommons
|
||||
$(INSTALL_PROG) init.d/xen-watchdog $(DESTDIR)$(INITD_DIR)
|
||||
|
||||
.PHONY: install-scripts
|
@ -1,90 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Charles Arnold <carnold@suse.com>
|
||||
# Date 1351249508 -3600
|
||||
# Node ID 6f9e46917eb8771914041b98f714e8f485fca5ef
|
||||
# Parent 03af0abd2b72dfab3f2e50dd502108de8603f741
|
||||
pygrub: Add option to list grub entries
|
||||
|
||||
The argument to "--entry" allows 2 syntaxes, either directly the entry
|
||||
number in menu.lst, or the whole string behind the "title" key word.
|
||||
This poses the following issue:
|
||||
|
||||
From Dom0 there is no way to guess the number and, or the complete
|
||||
title string because this string contains the kernel version, which
|
||||
will change with a kernel update.
|
||||
|
||||
This patch adds [-l|--list-entries] as an argument to pygrub.
|
||||
|
||||
Signed-off-by: Charles Arnold <carnold@suse.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 03af0abd2b72 -r 6f9e46917eb8 tools/pygrub/src/pygrub
|
||||
--- a/tools/pygrub/src/pygrub Fri Oct 26 12:03:12 2012 +0100
|
||||
+++ b/tools/pygrub/src/pygrub Fri Oct 26 12:05:08 2012 +0100
|
||||
@@ -595,7 +595,17 @@ def run_grub(file, entry, fs, cfg_args):
|
||||
sel = g.run()
|
||||
|
||||
g = Grub(file, fs)
|
||||
- if interactive:
|
||||
+
|
||||
+ if list_entries:
|
||||
+ for i in range(len(g.cf.images)):
|
||||
+ img = g.cf.images[i]
|
||||
+ print "title: %s" % img.title
|
||||
+ print " root: %s" % img.root
|
||||
+ print " kernel: %s" % img.kernel[1]
|
||||
+ print " args: %s" % img.args
|
||||
+ print " initrd: %s" % img.initrd[1]
|
||||
+
|
||||
+ if interactive and not list_entries:
|
||||
curses.wrapper(run_main)
|
||||
else:
|
||||
sel = g.cf.default
|
||||
@@ -702,7 +712,7 @@ if __name__ == "__main__":
|
||||
sel = None
|
||||
|
||||
def usage():
|
||||
- print >> sys.stderr, "Usage: %s [-q|--quiet] [-i|--interactive] [-n|--not-really] [--output=] [--kernel=] [--ramdisk=] [--args=] [--entry=] [--output-directory=] [--output-format=sxp|simple|simple0] <image>" %(sys.argv[0],)
|
||||
+ print >> sys.stderr, "Usage: %s [-q|--quiet] [-i|--interactive] [-l|--list-entries] [-n|--not-really] [--output=] [--kernel=] [--ramdisk=] [--args=] [--entry=] [--output-directory=] [--output-format=sxp|simple|simple0] <image>" %(sys.argv[0],)
|
||||
|
||||
def copy_from_image(fs, file_to_read, file_type, output_directory,
|
||||
not_really):
|
||||
@@ -736,8 +746,8 @@ if __name__ == "__main__":
|
||||
dataoff += len(data)
|
||||
|
||||
try:
|
||||
- opts, args = getopt.gnu_getopt(sys.argv[1:], 'qinh::',
|
||||
- ["quiet", "interactive", "not-really", "help",
|
||||
+ opts, args = getopt.gnu_getopt(sys.argv[1:], 'qilnh::',
|
||||
+ ["quiet", "interactive", "list-entries", "not-really", "help",
|
||||
"output=", "output-format=", "output-directory=",
|
||||
"entry=", "kernel=",
|
||||
"ramdisk=", "args=", "isconfig", "debug"])
|
||||
@@ -753,6 +763,7 @@ if __name__ == "__main__":
|
||||
output = None
|
||||
entry = None
|
||||
interactive = True
|
||||
+ list_entries = False
|
||||
isconfig = False
|
||||
debug = False
|
||||
not_really = False
|
||||
@@ -771,6 +782,8 @@ if __name__ == "__main__":
|
||||
interactive = False
|
||||
elif o in ("-i", "--interactive"):
|
||||
interactive = True
|
||||
+ elif o in ("-l", "--list-entries"):
|
||||
+ list_entries = True
|
||||
elif o in ("-n", "--not-really"):
|
||||
not_really = True
|
||||
elif o in ("-h", "--help"):
|
||||
@@ -855,6 +868,9 @@ if __name__ == "__main__":
|
||||
fs = None
|
||||
continue
|
||||
|
||||
+ if list_entries:
|
||||
+ sys.exit(0)
|
||||
+
|
||||
# Did looping through partitions find us a kernel?
|
||||
if not fs:
|
||||
raise RuntimeError, "Unable to find partition containing kernel"
|
@ -1,643 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1352368421 -3600
|
||||
# Node ID 92163b114076029842d0f2d1dbfaa445976c71a3
|
||||
# Parent aa2074529eb0183257b6f5f29821b0cd6dfd991a
|
||||
x86/ACPI: invalidate BGRT if necessary
|
||||
|
||||
Since the image pointed to may live in boot services memory (which we
|
||||
add to the global memory pool long before ACPI tables get looked at),
|
||||
we should prevent Dom0 from trying to retrieve the image data in that
|
||||
case.
|
||||
|
||||
The alternatives would be to
|
||||
- not add boot services memory to the global pool at all, or
|
||||
- defer adding boot services memory until Dom0 indicates it is safe to
|
||||
do so, or
|
||||
- find and parse the BGRT table in xen/arch/x86/efi/boot.c, and avoid
|
||||
adding that specific region to the E820 table.
|
||||
None of these are really attractive, and as Xen commonly prints to the
|
||||
video console anyway (without trying to avoid any regions on the
|
||||
screen), the invalidation would need to be done conditionally anyway.
|
||||
|
||||
(xen/include/acpi/actbl3.h is a verbatim copy from Linux 3.7-rc4)
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/xen/arch/x86/acpi/boot.c
|
||||
+++ b/xen/arch/x86/acpi/boot.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <xen/init.h>
|
||||
#include <xen/acpi.h>
|
||||
#include <xen/irq.h>
|
||||
+#include <xen/mm.h>
|
||||
#include <xen/dmi.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/page.h>
|
||||
@@ -285,6 +286,27 @@ static int __init acpi_parse_hpet(struct
|
||||
#define acpi_parse_hpet NULL
|
||||
#endif
|
||||
|
||||
+static int __init acpi_invalidate_bgrt(struct acpi_table_header *table)
|
||||
+{
|
||||
+ struct acpi_table_bgrt *bgrt_tbl =
|
||||
+ container_of(table, struct acpi_table_bgrt, header);
|
||||
+
|
||||
+ if (table->length < sizeof(*bgrt_tbl))
|
||||
+ return -1;
|
||||
+
|
||||
+ if (bgrt_tbl->version == 1 && bgrt_tbl->image_address
|
||||
+ && !page_is_ram_type(PFN_DOWN(bgrt_tbl->image_address),
|
||||
+ RAM_TYPE_CONVENTIONAL))
|
||||
+ return 0;
|
||||
+
|
||||
+ printk(KERN_INFO PREFIX "BGRT: invalidating v%d image at %#"PRIx64"\n",
|
||||
+ bgrt_tbl->version, bgrt_tbl->image_address);
|
||||
+ bgrt_tbl->image_address = 0;
|
||||
+ bgrt_tbl->status &= ~1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_ACPI_SLEEP
|
||||
#define acpi_fadt_copy_address(dst, src, len) do { \
|
||||
if (fadt->header.revision >= FADT2_REVISION_ID) \
|
||||
@@ -833,5 +855,7 @@ int __init acpi_boot_init(void)
|
||||
|
||||
erst_init();
|
||||
|
||||
+ acpi_table_parse(ACPI_SIG_BGRT, acpi_invalidate_bgrt);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
--- a/xen/include/acpi/actbl.h
|
||||
+++ b/xen/include/acpi/actbl.h
|
||||
@@ -314,6 +314,7 @@ enum acpi_prefered_pm_profiles {
|
||||
|
||||
#include <acpi/actbl1.h>
|
||||
#include <acpi/actbl2.h>
|
||||
+#include <acpi/actbl3.h>
|
||||
|
||||
/*
|
||||
* Sizes of the various flavors of FADT. We need to look closely
|
||||
--- /dev/null
|
||||
+++ b/xen/include/acpi/actbl3.h
|
||||
@@ -0,0 +1,557 @@
|
||||
+/******************************************************************************
|
||||
+ *
|
||||
+ * Name: actbl3.h - ACPI Table Definitions
|
||||
+ *
|
||||
+ *****************************************************************************/
|
||||
+
|
||||
+/*
|
||||
+ * Copyright (C) 2000 - 2012, Intel Corp.
|
||||
+ * All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions, and the following disclaimer,
|
||||
+ * without modification.
|
||||
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
+ * substantially similar to the "NO WARRANTY" disclaimer below
|
||||
+ * ("Disclaimer") and any redistribution must be conditioned upon
|
||||
+ * including a substantially similar Disclaimer requirement for further
|
||||
+ * binary redistribution.
|
||||
+ * 3. Neither the names of the above-listed copyright holders nor the names
|
||||
+ * of any contributors may be used to endorse or promote products derived
|
||||
+ * from this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, this software may be distributed under the terms of the
|
||||
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
||||
+ * Software Foundation.
|
||||
+ *
|
||||
+ * NO WARRANTY
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGES.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __ACTBL3_H__
|
||||
+#define __ACTBL3_H__
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * Additional ACPI Tables (3)
|
||||
+ *
|
||||
+ * These tables are not consumed directly by the ACPICA subsystem, but are
|
||||
+ * included here to support device drivers and the AML disassembler.
|
||||
+ *
|
||||
+ * The tables in this file are fully defined within the ACPI specification.
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+/*
|
||||
+ * Values for description table header signatures for tables defined in this
|
||||
+ * file. Useful because they make it more difficult to inadvertently type in
|
||||
+ * the wrong signature.
|
||||
+ */
|
||||
+#define ACPI_SIG_BGRT "BGRT" /* Boot Graphics Resource Table */
|
||||
+#define ACPI_SIG_DRTM "DRTM" /* Dynamic Root of Trust for Measurement table */
|
||||
+#define ACPI_SIG_FPDT "FPDT" /* Firmware Performance Data Table */
|
||||
+#define ACPI_SIG_GTDT "GTDT" /* Generic Timer Description Table */
|
||||
+#define ACPI_SIG_MPST "MPST" /* Memory Power State Table */
|
||||
+#define ACPI_SIG_PCCT "PCCT" /* Platform Communications Channel Table */
|
||||
+#define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */
|
||||
+#define ACPI_SIG_RASF "RASF" /* RAS Feature table */
|
||||
+
|
||||
+#define ACPI_SIG_S3PT "S3PT" /* S3 Performance (sub)Table */
|
||||
+#define ACPI_SIG_PCCS "PCC" /* PCC Shared Memory Region */
|
||||
+
|
||||
+/* Reserved table signatures */
|
||||
+
|
||||
+#define ACPI_SIG_CSRT "CSRT" /* Core System Resources Table */
|
||||
+#define ACPI_SIG_MATR "MATR" /* Memory Address Translation Table */
|
||||
+#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */
|
||||
+#define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */
|
||||
+
|
||||
+/*
|
||||
+ * All tables must be byte-packed to match the ACPI specification, since
|
||||
+ * the tables are provided by the system BIOS.
|
||||
+ */
|
||||
+#pragma pack(1)
|
||||
+
|
||||
+/*
|
||||
+ * Note: C bitfields are not used for this reason:
|
||||
+ *
|
||||
+ * "Bitfields are great and easy to read, but unfortunately the C language
|
||||
+ * does not specify the layout of bitfields in memory, which means they are
|
||||
+ * essentially useless for dealing with packed data in on-disk formats or
|
||||
+ * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me,
|
||||
+ * this decision was a design error in C. Ritchie could have picked an order
|
||||
+ * and stuck with it." Norman Ramsey.
|
||||
+ * See http://stackoverflow.com/a/1053662/41661
|
||||
+ */
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * BGRT - Boot Graphics Resource Table (ACPI 5.0)
|
||||
+ * Version 1
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+struct acpi_table_bgrt {
|
||||
+ struct acpi_table_header header; /* Common ACPI table header */
|
||||
+ u16 version;
|
||||
+ u8 status;
|
||||
+ u8 image_type;
|
||||
+ u64 image_address;
|
||||
+ u32 image_offset_x;
|
||||
+ u32 image_offset_y;
|
||||
+};
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * DRTM - Dynamic Root of Trust for Measurement table
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+struct acpi_table_drtm {
|
||||
+ struct acpi_table_header header; /* Common ACPI table header */
|
||||
+ u64 entry_base_address;
|
||||
+ u64 entry_length;
|
||||
+ u32 entry_address32;
|
||||
+ u64 entry_address64;
|
||||
+ u64 exit_address;
|
||||
+ u64 log_area_address;
|
||||
+ u32 log_area_length;
|
||||
+ u64 arch_dependent_address;
|
||||
+ u32 flags;
|
||||
+};
|
||||
+
|
||||
+/* 1) Validated Tables List */
|
||||
+
|
||||
+struct acpi_drtm_vtl_list {
|
||||
+ u32 validated_table_list_count;
|
||||
+};
|
||||
+
|
||||
+/* 2) Resources List */
|
||||
+
|
||||
+struct acpi_drtm_resource_list {
|
||||
+ u32 resource_list_count;
|
||||
+};
|
||||
+
|
||||
+/* 3) Platform-specific Identifiers List */
|
||||
+
|
||||
+struct acpi_drtm_id_list {
|
||||
+ u32 id_list_count;
|
||||
+};
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * FPDT - Firmware Performance Data Table (ACPI 5.0)
|
||||
+ * Version 1
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+struct acpi_table_fpdt {
|
||||
+ struct acpi_table_header header; /* Common ACPI table header */
|
||||
+};
|
||||
+
|
||||
+/* FPDT subtable header */
|
||||
+
|
||||
+struct acpi_fpdt_header {
|
||||
+ u16 type;
|
||||
+ u8 length;
|
||||
+ u8 revision;
|
||||
+};
|
||||
+
|
||||
+/* Values for Type field above */
|
||||
+
|
||||
+enum acpi_fpdt_type {
|
||||
+ ACPI_FPDT_TYPE_BOOT = 0,
|
||||
+ ACPI_FPDT_TYPE_S3PERF = 1,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * FPDT subtables
|
||||
+ */
|
||||
+
|
||||
+/* 0: Firmware Basic Boot Performance Record */
|
||||
+
|
||||
+struct acpi_fpdt_boot {
|
||||
+ struct acpi_fpdt_header header;
|
||||
+ u8 reserved[4];
|
||||
+ u64 reset_end;
|
||||
+ u64 load_start;
|
||||
+ u64 startup_start;
|
||||
+ u64 exit_services_entry;
|
||||
+ u64 exit_services_exit;
|
||||
+};
|
||||
+
|
||||
+/* 1: S3 Performance Table Pointer Record */
|
||||
+
|
||||
+struct acpi_fpdt_s3pt_ptr {
|
||||
+ struct acpi_fpdt_header header;
|
||||
+ u8 reserved[4];
|
||||
+ u64 address;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * S3PT - S3 Performance Table. This table is pointed to by the
|
||||
+ * FPDT S3 Pointer Record above.
|
||||
+ */
|
||||
+struct acpi_table_s3pt {
|
||||
+ u8 signature[4]; /* "S3PT" */
|
||||
+ u32 length;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * S3PT Subtables
|
||||
+ */
|
||||
+struct acpi_s3pt_header {
|
||||
+ u16 type;
|
||||
+ u8 length;
|
||||
+ u8 revision;
|
||||
+};
|
||||
+
|
||||
+/* Values for Type field above */
|
||||
+
|
||||
+enum acpi_s3pt_type {
|
||||
+ ACPI_S3PT_TYPE_RESUME = 0,
|
||||
+ ACPI_S3PT_TYPE_SUSPEND = 1,
|
||||
+};
|
||||
+
|
||||
+struct acpi_s3pt_resume {
|
||||
+ struct acpi_s3pt_header header;
|
||||
+ u32 resume_count;
|
||||
+ u64 full_resume;
|
||||
+ u64 average_resume;
|
||||
+};
|
||||
+
|
||||
+struct acpi_s3pt_suspend {
|
||||
+ struct acpi_s3pt_header header;
|
||||
+ u64 suspend_start;
|
||||
+ u64 suspend_end;
|
||||
+};
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * GTDT - Generic Timer Description Table (ACPI 5.0)
|
||||
+ * Version 1
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+struct acpi_table_gtdt {
|
||||
+ struct acpi_table_header header; /* Common ACPI table header */
|
||||
+ u64 address;
|
||||
+ u32 flags;
|
||||
+ u32 secure_pl1_interrupt;
|
||||
+ u32 secure_pl1_flags;
|
||||
+ u32 non_secure_pl1_interrupt;
|
||||
+ u32 non_secure_pl1_flags;
|
||||
+ u32 virtual_timer_interrupt;
|
||||
+ u32 virtual_timer_flags;
|
||||
+ u32 non_secure_pl2_interrupt;
|
||||
+ u32 non_secure_pl2_flags;
|
||||
+};
|
||||
+
|
||||
+/* Values for Flags field above */
|
||||
+
|
||||
+#define ACPI_GTDT_MAPPED_BLOCK_PRESENT 1
|
||||
+
|
||||
+/* Values for all "TimerFlags" fields above */
|
||||
+
|
||||
+#define ACPI_GTDT_INTERRUPT_MODE 1
|
||||
+#define ACPI_GTDT_INTERRUPT_POLARITY 2
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * MPST - Memory Power State Table (ACPI 5.0)
|
||||
+ * Version 1
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+#define ACPI_MPST_CHANNEL_INFO \
|
||||
+ u16 reserved1; \
|
||||
+ u8 channel_id; \
|
||||
+ u8 reserved2; \
|
||||
+ u16 power_node_count;
|
||||
+
|
||||
+/* Main table */
|
||||
+
|
||||
+struct acpi_table_mpst {
|
||||
+ struct acpi_table_header header; /* Common ACPI table header */
|
||||
+ ACPI_MPST_CHANNEL_INFO /* Platform Communication Channel */
|
||||
+};
|
||||
+
|
||||
+/* Memory Platform Communication Channel Info */
|
||||
+
|
||||
+struct acpi_mpst_channel {
|
||||
+ ACPI_MPST_CHANNEL_INFO /* Platform Communication Channel */
|
||||
+};
|
||||
+
|
||||
+/* Memory Power Node Structure */
|
||||
+
|
||||
+struct acpi_mpst_power_node {
|
||||
+ u8 flags;
|
||||
+ u8 reserved1;
|
||||
+ u16 node_id;
|
||||
+ u32 length;
|
||||
+ u64 range_address;
|
||||
+ u64 range_length;
|
||||
+ u8 num_power_states;
|
||||
+ u8 num_physical_components;
|
||||
+ u16 reserved2;
|
||||
+};
|
||||
+
|
||||
+/* Values for Flags field above */
|
||||
+
|
||||
+#define ACPI_MPST_ENABLED 1
|
||||
+#define ACPI_MPST_POWER_MANAGED 2
|
||||
+#define ACPI_MPST_HOT_PLUG_CAPABLE 4
|
||||
+
|
||||
+/* Memory Power State Structure (follows POWER_NODE above) */
|
||||
+
|
||||
+struct acpi_mpst_power_state {
|
||||
+ u8 power_state;
|
||||
+ u8 info_index;
|
||||
+};
|
||||
+
|
||||
+/* Physical Component ID Structure (follows POWER_STATE above) */
|
||||
+
|
||||
+struct acpi_mpst_component {
|
||||
+ u16 component_id;
|
||||
+};
|
||||
+
|
||||
+/* Memory Power State Characteristics Structure (follows all POWER_NODEs) */
|
||||
+
|
||||
+struct acpi_mpst_data_hdr {
|
||||
+ u16 characteristics_count;
|
||||
+};
|
||||
+
|
||||
+struct acpi_mpst_power_data {
|
||||
+ u8 revision;
|
||||
+ u8 flags;
|
||||
+ u16 reserved1;
|
||||
+ u32 average_power;
|
||||
+ u32 power_saving;
|
||||
+ u64 exit_latency;
|
||||
+ u64 reserved2;
|
||||
+};
|
||||
+
|
||||
+/* Values for Flags field above */
|
||||
+
|
||||
+#define ACPI_MPST_PRESERVE 1
|
||||
+#define ACPI_MPST_AUTOENTRY 2
|
||||
+#define ACPI_MPST_AUTOEXIT 4
|
||||
+
|
||||
+/* Shared Memory Region (not part of an ACPI table) */
|
||||
+
|
||||
+struct acpi_mpst_shared {
|
||||
+ u32 signature;
|
||||
+ u16 pcc_command;
|
||||
+ u16 pcc_status;
|
||||
+ u16 command_register;
|
||||
+ u16 status_register;
|
||||
+ u16 power_state_id;
|
||||
+ u16 power_node_id;
|
||||
+ u64 energy_consumed;
|
||||
+ u64 average_power;
|
||||
+};
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * PCCT - Platform Communications Channel Table (ACPI 5.0)
|
||||
+ * Version 1
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+struct acpi_table_pcct {
|
||||
+ struct acpi_table_header header; /* Common ACPI table header */
|
||||
+ u32 flags;
|
||||
+ u32 latency;
|
||||
+ u32 reserved;
|
||||
+};
|
||||
+
|
||||
+/* Values for Flags field above */
|
||||
+
|
||||
+#define ACPI_PCCT_DOORBELL 1
|
||||
+
|
||||
+/*
|
||||
+ * PCCT subtables
|
||||
+ */
|
||||
+
|
||||
+/* 0: Generic Communications Subspace */
|
||||
+
|
||||
+struct acpi_pcct_subspace {
|
||||
+ struct acpi_subtable_header header;
|
||||
+ u8 reserved[6];
|
||||
+ u64 base_address;
|
||||
+ u64 length;
|
||||
+ struct acpi_generic_address doorbell_register;
|
||||
+ u64 preserve_mask;
|
||||
+ u64 write_mask;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * PCC memory structures (not part of the ACPI table)
|
||||
+ */
|
||||
+
|
||||
+/* Shared Memory Region */
|
||||
+
|
||||
+struct acpi_pcct_shared_memory {
|
||||
+ u32 signature;
|
||||
+ u16 command;
|
||||
+ u16 status;
|
||||
+};
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * PMTT - Platform Memory Topology Table (ACPI 5.0)
|
||||
+ * Version 1
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+struct acpi_table_pmtt {
|
||||
+ struct acpi_table_header header; /* Common ACPI table header */
|
||||
+ u32 reserved;
|
||||
+};
|
||||
+
|
||||
+/* Common header for PMTT subtables that follow main table */
|
||||
+
|
||||
+struct acpi_pmtt_header {
|
||||
+ u8 type;
|
||||
+ u8 reserved1;
|
||||
+ u16 length;
|
||||
+ u16 flags;
|
||||
+ u16 reserved2;
|
||||
+};
|
||||
+
|
||||
+/* Values for Type field above */
|
||||
+
|
||||
+#define ACPI_PMTT_TYPE_SOCKET 0
|
||||
+#define ACPI_PMTT_TYPE_CONTROLLER 1
|
||||
+#define ACPI_PMTT_TYPE_DIMM 2
|
||||
+#define ACPI_PMTT_TYPE_RESERVED 3 /* 0x03-0xFF are reserved */
|
||||
+
|
||||
+/* Values for Flags field above */
|
||||
+
|
||||
+#define ACPI_PMTT_TOP_LEVEL 0x0001
|
||||
+#define ACPI_PMTT_PHYSICAL 0x0002
|
||||
+#define ACPI_PMTT_MEMORY_TYPE 0x000C
|
||||
+
|
||||
+/*
|
||||
+ * PMTT subtables, correspond to Type in struct acpi_pmtt_header
|
||||
+ */
|
||||
+
|
||||
+/* 0: Socket Structure */
|
||||
+
|
||||
+struct acpi_pmtt_socket {
|
||||
+ struct acpi_pmtt_header header;
|
||||
+ u16 socket_id;
|
||||
+ u16 reserved;
|
||||
+};
|
||||
+
|
||||
+/* 1: Memory Controller subtable */
|
||||
+
|
||||
+struct acpi_pmtt_controller {
|
||||
+ struct acpi_pmtt_header header;
|
||||
+ u32 read_latency;
|
||||
+ u32 write_latency;
|
||||
+ u32 read_bandwidth;
|
||||
+ u32 write_bandwidth;
|
||||
+ u16 access_width;
|
||||
+ u16 alignment;
|
||||
+ u16 reserved;
|
||||
+ u16 domain_count;
|
||||
+};
|
||||
+
|
||||
+/* 1a: Proximity Domain substructure */
|
||||
+
|
||||
+struct acpi_pmtt_domain {
|
||||
+ u32 proximity_domain;
|
||||
+};
|
||||
+
|
||||
+/* 2: Physical Component Identifier (DIMM) */
|
||||
+
|
||||
+struct acpi_pmtt_physical_component {
|
||||
+ struct acpi_pmtt_header header;
|
||||
+ u16 component_id;
|
||||
+ u16 reserved;
|
||||
+ u32 memory_size;
|
||||
+ u32 bios_handle;
|
||||
+};
|
||||
+
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * RASF - RAS Feature Table (ACPI 5.0)
|
||||
+ * Version 1
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+struct acpi_table_rasf {
|
||||
+ struct acpi_table_header header; /* Common ACPI table header */
|
||||
+ u8 channel_id[12];
|
||||
+};
|
||||
+
|
||||
+/* RASF Platform Communication Channel Shared Memory Region */
|
||||
+
|
||||
+struct acpi_rasf_shared_memory {
|
||||
+ u32 signature;
|
||||
+ u16 command;
|
||||
+ u16 status;
|
||||
+ u64 requested_address;
|
||||
+ u64 requested_length;
|
||||
+ u64 actual_address;
|
||||
+ u64 actual_length;
|
||||
+ u16 flags;
|
||||
+ u8 speed;
|
||||
+};
|
||||
+
|
||||
+/* Masks for Flags and Speed fields above */
|
||||
+
|
||||
+#define ACPI_RASF_SCRUBBER_RUNNING 1
|
||||
+#define ACPI_RASF_SPEED (7<<1)
|
||||
+
|
||||
+/* Channel Commands */
|
||||
+
|
||||
+enum acpi_rasf_commands {
|
||||
+ ACPI_RASF_GET_RAS_CAPABILITIES = 1,
|
||||
+ ACPI_RASF_GET_PATROL_PARAMETERS = 2,
|
||||
+ ACPI_RASF_START_PATROL_SCRUBBER = 3,
|
||||
+ ACPI_RASF_STOP_PATROL_SCRUBBER = 4
|
||||
+};
|
||||
+
|
||||
+/* Channel Command flags */
|
||||
+
|
||||
+#define ACPI_RASF_GENERATE_SCI (1<<15)
|
||||
+
|
||||
+/* Status values */
|
||||
+
|
||||
+enum acpi_rasf_status {
|
||||
+ ACPI_RASF_SUCCESS = 0,
|
||||
+ ACPI_RASF_NOT_VALID = 1,
|
||||
+ ACPI_RASF_NOT_SUPPORTED = 2,
|
||||
+ ACPI_RASF_BUSY = 3,
|
||||
+ ACPI_RASF_FAILED = 4,
|
||||
+ ACPI_RASF_ABORTED = 5,
|
||||
+ ACPI_RASF_INVALID_DATA = 6
|
||||
+};
|
||||
+
|
||||
+/* Status flags */
|
||||
+
|
||||
+#define ACPI_RASF_COMMAND_COMPLETE (1)
|
||||
+#define ACPI_RASF_SCI_DOORBELL (1<<1)
|
||||
+#define ACPI_RASF_ERROR (1<<2)
|
||||
+#define ACPI_RASF_STATUS (0x1F<<3)
|
||||
+
|
||||
+/* Reset to default packing */
|
||||
+
|
||||
+#pragma pack()
|
||||
+
|
||||
+#endif /* __ACTBL3_H__ */
|
@ -1,178 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1352709367 -3600
|
||||
# Node ID fdb69dd527cd01a46f87efb380050559dcf12d37
|
||||
# Parent 286ef4ced2164f4e9bf52fd0c52248182e69a6e6
|
||||
IOMMU: don't immediately disable bus mastering on faults
|
||||
|
||||
Instead, give the owning domain at least a small opportunity of fixing
|
||||
things up, and allow for rare faults to not bring down the device at
|
||||
all.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
Acked-by: Dario Faggioli <dario.faggioli@citrix.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/amd/iommu_init.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/amd/iommu_init.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/amd/iommu_init.c
|
||||
@@ -564,7 +564,7 @@ static hw_irq_controller iommu_msi_type
|
||||
|
||||
static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[])
|
||||
{
|
||||
- u16 domain_id, device_id, bdf, cword;
|
||||
+ u16 domain_id, device_id, bdf;
|
||||
u32 code;
|
||||
u64 *addr;
|
||||
int count = 0;
|
||||
@@ -615,18 +615,10 @@ static void parse_event_log_entry(struct
|
||||
"fault address = 0x%"PRIx64"\n",
|
||||
event_str[code-1], domain_id, device_id, *addr);
|
||||
|
||||
- /* Tell the device to stop DMAing; we can't rely on the guest to
|
||||
- * control it for us. */
|
||||
for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
|
||||
if ( get_dma_requestor_id(iommu->seg, bdf) == device_id )
|
||||
- {
|
||||
- cword = pci_conf_read16(iommu->seg, PCI_BUS(bdf),
|
||||
- PCI_SLOT(bdf), PCI_FUNC(bdf),
|
||||
- PCI_COMMAND);
|
||||
- pci_conf_write16(iommu->seg, PCI_BUS(bdf), PCI_SLOT(bdf),
|
||||
- PCI_FUNC(bdf), PCI_COMMAND,
|
||||
- cword & ~PCI_COMMAND_MASTER);
|
||||
- }
|
||||
+ pci_check_disable_device(iommu->seg, PCI_BUS(bdf),
|
||||
+ PCI_DEVFN2(bdf));
|
||||
}
|
||||
else
|
||||
{
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/iommu.c
|
||||
@@ -218,6 +218,7 @@ static int device_assigned(u16 seg, u8 b
|
||||
static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
|
||||
{
|
||||
struct hvm_iommu *hd = domain_hvm_iommu(d);
|
||||
+ struct pci_dev *pdev;
|
||||
int rc = 0;
|
||||
|
||||
if ( !iommu_enabled || !hd->platform_ops )
|
||||
@@ -231,6 +232,10 @@ static int assign_device(struct domain *
|
||||
return -EXDEV;
|
||||
|
||||
spin_lock(&pcidevs_lock);
|
||||
+ pdev = pci_get_pdev(seg, bus, devfn);
|
||||
+ if ( pdev )
|
||||
+ pdev->fault.count = 0;
|
||||
+
|
||||
if ( (rc = hd->platform_ops->assign_device(d, seg, bus, devfn)) )
|
||||
goto done;
|
||||
|
||||
@@ -382,6 +387,8 @@ int deassign_device(struct domain *d, u1
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ pdev->fault.count = 0;
|
||||
+
|
||||
if ( !has_arch_pdevs(d) && need_iommu(d) )
|
||||
{
|
||||
d->need_iommu = 0;
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/pci.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
@@ -637,6 +637,36 @@ int __init pci_device_detect(u16 seg, u8
|
||||
return 1;
|
||||
}
|
||||
|
||||
+void pci_check_disable_device(u16 seg, u8 bus, u8 devfn)
|
||||
+{
|
||||
+ struct pci_dev *pdev;
|
||||
+ s_time_t now = NOW();
|
||||
+ u16 cword;
|
||||
+
|
||||
+ spin_lock(&pcidevs_lock);
|
||||
+ pdev = pci_get_pdev(seg, bus, devfn);
|
||||
+ if ( pdev )
|
||||
+ {
|
||||
+ if ( now < pdev->fault.time ||
|
||||
+ now - pdev->fault.time > MILLISECS(10) )
|
||||
+ pdev->fault.count >>= 1;
|
||||
+ pdev->fault.time = now;
|
||||
+ if ( ++pdev->fault.count < PT_FAULT_THRESHOLD )
|
||||
+ pdev = NULL;
|
||||
+ }
|
||||
+ spin_unlock(&pcidevs_lock);
|
||||
+
|
||||
+ if ( !pdev )
|
||||
+ return;
|
||||
+
|
||||
+ /* Tell the device to stop DMAing; we can't rely on the guest to
|
||||
+ * control it for us. */
|
||||
+ cword = pci_conf_read16(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
+ PCI_COMMAND);
|
||||
+ pci_conf_write16(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
+ PCI_COMMAND, cword & ~PCI_COMMAND_MASTER);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* scan pci devices to add all existed PCI devices to alldevs_list,
|
||||
* and setup pci hierarchy in array bus2bridge.
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/vtd/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
@@ -936,7 +936,7 @@ static void __do_iommu_page_fault(struct
|
||||
while (1)
|
||||
{
|
||||
u8 fault_reason;
|
||||
- u16 source_id, cword;
|
||||
+ u16 source_id;
|
||||
u32 data;
|
||||
u64 guest_addr;
|
||||
int type;
|
||||
@@ -969,14 +969,8 @@ static void __do_iommu_page_fault(struct
|
||||
iommu_page_fault_do_one(iommu, type, fault_reason,
|
||||
source_id, guest_addr);
|
||||
|
||||
- /* Tell the device to stop DMAing; we can't rely on the guest to
|
||||
- * control it for us. */
|
||||
- cword = pci_conf_read16(iommu->intel->drhd->segment,
|
||||
- PCI_BUS(source_id), PCI_SLOT(source_id),
|
||||
- PCI_FUNC(source_id), PCI_COMMAND);
|
||||
- pci_conf_write16(iommu->intel->drhd->segment, PCI_BUS(source_id),
|
||||
- PCI_SLOT(source_id), PCI_FUNC(source_id),
|
||||
- PCI_COMMAND, cword & ~PCI_COMMAND_MASTER);
|
||||
+ pci_check_disable_device(iommu->intel->drhd->segment,
|
||||
+ PCI_BUS(source_id), PCI_DEVFN2(source_id));
|
||||
|
||||
fault_index++;
|
||||
if ( fault_index > cap_num_fault_regs(iommu->cap) )
|
||||
Index: xen-4.2.2-testing/xen/include/xen/pci.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/pci.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/pci.h
|
||||
@@ -65,6 +65,11 @@ struct pci_dev {
|
||||
const u8 devfn;
|
||||
struct pci_dev_info info;
|
||||
struct arch_pci_dev arch;
|
||||
+ struct {
|
||||
+ s_time_t time;
|
||||
+ unsigned int count;
|
||||
+#define PT_FAULT_THRESHOLD 10
|
||||
+ } fault;
|
||||
u64 vf_rlen[6];
|
||||
};
|
||||
|
||||
@@ -107,6 +112,7 @@ void arch_pci_ro_device(int seg, int bdf
|
||||
struct pci_dev *pci_get_pdev(int seg, int bus, int devfn);
|
||||
struct pci_dev *pci_get_pdev_by_domain(
|
||||
struct domain *, int seg, int bus, int devfn);
|
||||
+void pci_check_disable_device(u16 seg, u8 bus, u8 devfn);
|
||||
|
||||
uint8_t pci_conf_read8(
|
||||
unsigned int seg, unsigned int bus, unsigned int dev, unsigned int func,
|
@ -1,85 +0,0 @@
|
||||
# HG changeset patch
|
||||
# Parent 8b93ac0c93f3fb8a140b4688ba71841ac927d4e3
|
||||
xenstore-chmod: handle arbitrary number of perms rather than MAX_PERMS constant
|
||||
|
||||
Constant MAX_PERMS 16 is too small to use in some occasions, e.g. if
|
||||
there are more than 16 domU(s) on one hypervisor (it's easy to
|
||||
achieve) and one wants to do xenstore-chmod PATH to all domU(s). So,
|
||||
remove MAX_PERMS limitation and make it as arbitrary number of perms.
|
||||
|
||||
Signed-off-by: Chunyan Liu <cyliu@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
diff -r 8b93ac0c93f3 tools/xenstore/xenstore_client.c
|
||||
--- a/tools/xenstore/xenstore_client.c Tue Nov 13 11:19:17 2012 +0000
|
||||
+++ b/tools/xenstore/xenstore_client.c Mon Nov 26 11:33:38 2012 +0800
|
||||
@@ -25,7 +25,6 @@
|
||||
#define PATH_SEP '/'
|
||||
#define MAX_PATH_LEN 256
|
||||
|
||||
-#define MAX_PERMS 16
|
||||
|
||||
enum mode {
|
||||
MODE_unknown,
|
||||
@@ -407,44 +406,41 @@ perform(enum mode mode, int optind, int
|
||||
output("%s\n", list[i]);
|
||||
}
|
||||
free(list);
|
||||
- optind++;
|
||||
- break;
|
||||
- }
|
||||
- case MODE_ls: {
|
||||
- do_ls(xsh, argv[optind], 0, prefix);
|
||||
- optind++;
|
||||
- break;
|
||||
+ optind++;
|
||||
+ break;
|
||||
+ }
|
||||
+ case MODE_ls: {
|
||||
+ do_ls(xsh, argv[optind], 0, prefix);
|
||||
+ optind++;
|
||||
+ break;
|
||||
}
|
||||
case MODE_chmod: {
|
||||
- struct xs_permissions perms[MAX_PERMS];
|
||||
- int nperms = 0;
|
||||
/* save path pointer: */
|
||||
char *path = argv[optind++];
|
||||
- for (; argv[optind]; optind++, nperms++)
|
||||
+ int nperms = argc - optind;
|
||||
+ struct xs_permissions perms[nperms];
|
||||
+ int i;
|
||||
+ for (i = 0; argv[optind]; optind++, i++)
|
||||
{
|
||||
- if (MAX_PERMS <= nperms)
|
||||
- errx(1, "Too many permissions specified. "
|
||||
- "Maximum per invocation is %d.", MAX_PERMS);
|
||||
-
|
||||
- perms[nperms].id = atoi(argv[optind]+1);
|
||||
+ perms[i].id = atoi(argv[optind]+1);
|
||||
|
||||
switch (argv[optind][0])
|
||||
{
|
||||
case 'n':
|
||||
- perms[nperms].perms = XS_PERM_NONE;
|
||||
+ perms[i].perms = XS_PERM_NONE;
|
||||
break;
|
||||
case 'r':
|
||||
- perms[nperms].perms = XS_PERM_READ;
|
||||
+ perms[i].perms = XS_PERM_READ;
|
||||
break;
|
||||
case 'w':
|
||||
- perms[nperms].perms = XS_PERM_WRITE;
|
||||
+ perms[i].perms = XS_PERM_WRITE;
|
||||
break;
|
||||
case 'b':
|
||||
- perms[nperms].perms = XS_PERM_READ | XS_PERM_WRITE;
|
||||
+ perms[i].perms = XS_PERM_READ | XS_PERM_WRITE;
|
||||
break;
|
||||
default:
|
||||
errx(1, "Invalid permission specification: '%c'",
|
||||
- argv[optind][0]);
|
||||
+ argv[optind][0]);
|
||||
}
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1354884272 -3600
|
||||
# Node ID b62bd62b26836fafe19cf41fec194bcf33e2ead6
|
||||
# Parent cb542e58da25211843eb79998ea8568ebe9c8056
|
||||
x86/EFI: add code interfacing with the secure boot shim
|
||||
|
||||
... to validate the kernel image (which is required to be in PE
|
||||
format, as is e.g. the case for the Linux bzImage when built with
|
||||
CONFIG_EFI_STUB).
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/xen/arch/x86/efi/boot.c
|
||||
+++ b/xen/arch/x86/efi/boot.c
|
||||
@@ -24,6 +24,18 @@
|
||||
#include <asm/msr.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
+#define SHIM_LOCK_PROTOCOL_GUID \
|
||||
+ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
|
||||
+
|
||||
+typedef EFI_STATUS
|
||||
+(/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) (
|
||||
+ IN VOID *Buffer,
|
||||
+ IN UINT32 Size);
|
||||
+
|
||||
+typedef struct {
|
||||
+ EFI_SHIM_LOCK_VERIFY Verify;
|
||||
+} EFI_SHIM_LOCK_PROTOCOL;
|
||||
+
|
||||
extern char start[];
|
||||
extern u32 cpuid_ext_features;
|
||||
|
||||
@@ -628,12 +640,14 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||||
static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
|
||||
static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
|
||||
+ static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
|
||||
EFI_LOADED_IMAGE *loaded_image;
|
||||
EFI_STATUS status;
|
||||
unsigned int i, argc;
|
||||
CHAR16 **argv, *file_name, *cfg_file_name = NULL;
|
||||
UINTN cols, rows, depth, size, map_key, info_size, gop_mode = ~0;
|
||||
EFI_HANDLE *handles = NULL;
|
||||
+ EFI_SHIM_LOCK_PROTOCOL *shim_lock;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
|
||||
EFI_FILE_HANDLE dir_handle;
|
||||
@@ -823,6 +837,11 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||||
read_file(dir_handle, s2w(&name), &kernel);
|
||||
efi_bs->FreePool(name.w);
|
||||
|
||||
+ if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
|
||||
+ (void **)&shim_lock)) &&
|
||||
+ shim_lock->Verify(kernel.ptr, kernel.size) != EFI_SUCCESS )
|
||||
+ blexit(L"Dom0 kernel image could not be verified\r\n");
|
||||
+
|
||||
name.s = get_value(&cfg, section.s, "ramdisk");
|
||||
if ( name.s )
|
||||
{
|
@ -1,275 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1357559364 -3600
|
||||
# Node ID 62dd78a4e3fc9d190840549f13b4d613f2d19c41
|
||||
# Parent 64b36dde26bc3c4fc80312cc9eeb0e511f0cf94b
|
||||
IOMMU: adjust (re)assign operation parameters
|
||||
|
||||
... to use a (struct pci_dev *, devfn) pair.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
||||
@@ -333,34 +333,31 @@ void amd_iommu_disable_domain_device(str
|
||||
disable_ats_device(iommu->seg, bus, devfn);
|
||||
}
|
||||
|
||||
-static int reassign_device( struct domain *source, struct domain *target,
|
||||
- u16 seg, u8 bus, u8 devfn)
|
||||
+static int reassign_device(struct domain *source, struct domain *target,
|
||||
+ u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
- struct pci_dev *pdev;
|
||||
struct amd_iommu *iommu;
|
||||
int bdf;
|
||||
struct hvm_iommu *t = domain_hvm_iommu(target);
|
||||
|
||||
- ASSERT(spin_is_locked(&pcidevs_lock));
|
||||
- pdev = pci_get_pdev_by_domain(source, seg, bus, devfn);
|
||||
- if ( !pdev )
|
||||
- return -ENODEV;
|
||||
-
|
||||
- bdf = PCI_BDF2(bus, devfn);
|
||||
- iommu = find_iommu_for_device(seg, bdf);
|
||||
+ bdf = PCI_BDF2(pdev->bus, pdev->devfn);
|
||||
+ iommu = find_iommu_for_device(pdev->seg, bdf);
|
||||
if ( !iommu )
|
||||
{
|
||||
AMD_IOMMU_DEBUG("Fail to find iommu."
|
||||
" %04x:%02x:%x02.%x cannot be assigned to dom%d\n",
|
||||
- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
target->domain_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
amd_iommu_disable_domain_device(source, iommu, bdf);
|
||||
|
||||
- list_move(&pdev->domain_list, &target->arch.pdev_list);
|
||||
- pdev->domain = target;
|
||||
+ if ( devfn == pdev->devfn )
|
||||
+ {
|
||||
+ list_move(&pdev->domain_list, &target->arch.pdev_list);
|
||||
+ pdev->domain = target;
|
||||
+ }
|
||||
|
||||
/* IO page tables might be destroyed after pci-detach the last device
|
||||
* In this case, we have to re-allocate root table for next pci-attach.*/
|
||||
@@ -369,17 +366,18 @@ static int reassign_device( struct domai
|
||||
|
||||
amd_iommu_setup_domain_device(target, iommu, bdf);
|
||||
AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n",
|
||||
- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
source->domain_id, target->domain_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int amd_iommu_assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
|
||||
+static int amd_iommu_assign_device(struct domain *d, u8 devfn,
|
||||
+ struct pci_dev *pdev)
|
||||
{
|
||||
- struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(seg);
|
||||
- int bdf = (bus << 8) | devfn;
|
||||
- int req_id = get_dma_requestor_id(seg, bdf);
|
||||
+ struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(pdev->seg);
|
||||
+ int bdf = PCI_BDF2(pdev->bus, devfn);
|
||||
+ int req_id = get_dma_requestor_id(pdev->seg, bdf);
|
||||
|
||||
if ( ivrs_mappings[req_id].unity_map_enable )
|
||||
{
|
||||
@@ -391,7 +389,7 @@ static int amd_iommu_assign_device(struc
|
||||
ivrs_mappings[req_id].read_permission);
|
||||
}
|
||||
|
||||
- return reassign_device(dom0, d, seg, bus, devfn);
|
||||
+ return reassign_device(dom0, d, devfn, pdev);
|
||||
}
|
||||
|
||||
static void deallocate_next_page_table(struct page_info* pg, int level)
|
||||
@@ -456,12 +454,6 @@ static void amd_iommu_domain_destroy(str
|
||||
amd_iommu_flush_all_pages(d);
|
||||
}
|
||||
|
||||
-static int amd_iommu_return_device(
|
||||
- struct domain *s, struct domain *t, u16 seg, u8 bus, u8 devfn)
|
||||
-{
|
||||
- return reassign_device(s, t, seg, bus, devfn);
|
||||
-}
|
||||
-
|
||||
static int amd_iommu_add_device(struct pci_dev *pdev)
|
||||
{
|
||||
struct amd_iommu *iommu;
|
||||
@@ -601,7 +593,7 @@ const struct iommu_ops amd_iommu_ops = {
|
||||
.teardown = amd_iommu_domain_destroy,
|
||||
.map_page = amd_iommu_map_page,
|
||||
.unmap_page = amd_iommu_unmap_page,
|
||||
- .reassign_device = amd_iommu_return_device,
|
||||
+ .reassign_device = reassign_device,
|
||||
.get_device_group_id = amd_iommu_group_id,
|
||||
.update_ire_from_apic = amd_iommu_ioapic_update_ire,
|
||||
.update_ire_from_msi = amd_iommu_msi_msg_update_ire,
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/iommu.c
|
||||
@@ -232,11 +232,16 @@ static int assign_device(struct domain *
|
||||
return -EXDEV;
|
||||
|
||||
spin_lock(&pcidevs_lock);
|
||||
- pdev = pci_get_pdev(seg, bus, devfn);
|
||||
- if ( pdev )
|
||||
- pdev->fault.count = 0;
|
||||
+ pdev = pci_get_pdev_by_domain(dom0, seg, bus, devfn);
|
||||
+ if ( !pdev )
|
||||
+ {
|
||||
+ rc = pci_get_pdev(seg, bus, devfn) ? -EBUSY : -ENODEV;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ pdev->fault.count = 0;
|
||||
|
||||
- if ( (rc = hd->platform_ops->assign_device(d, seg, bus, devfn)) )
|
||||
+ if ( (rc = hd->platform_ops->assign_device(d, devfn, pdev)) )
|
||||
goto done;
|
||||
|
||||
if ( has_arch_pdevs(d) && !need_iommu(d) )
|
||||
@@ -367,18 +372,11 @@ int deassign_device(struct domain *d, u1
|
||||
return -EINVAL;
|
||||
|
||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||
- pdev = pci_get_pdev(seg, bus, devfn);
|
||||
+ pdev = pci_get_pdev_by_domain(d, seg, bus, devfn);
|
||||
if ( !pdev )
|
||||
return -ENODEV;
|
||||
|
||||
- if ( pdev->domain != d )
|
||||
- {
|
||||
- dprintk(XENLOG_ERR VTDPREFIX,
|
||||
- "d%d: deassign a device not owned\n", d->domain_id);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- ret = hd->platform_ops->reassign_device(d, dom0, seg, bus, devfn);
|
||||
+ ret = hd->platform_ops->reassign_device(d, dom0, devfn, pdev);
|
||||
if ( ret )
|
||||
{
|
||||
dprintk(XENLOG_ERR VTDPREFIX,
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/vtd/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
@@ -1689,17 +1689,10 @@ out:
|
||||
static int reassign_device_ownership(
|
||||
struct domain *source,
|
||||
struct domain *target,
|
||||
- u16 seg, u8 bus, u8 devfn)
|
||||
+ u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
- struct pci_dev *pdev;
|
||||
int ret;
|
||||
|
||||
- ASSERT(spin_is_locked(&pcidevs_lock));
|
||||
- pdev = pci_get_pdev_by_domain(source, seg, bus, devfn);
|
||||
-
|
||||
- if (!pdev)
|
||||
- return -ENODEV;
|
||||
-
|
||||
/*
|
||||
* Devices assigned to untrusted domains (here assumed to be any domU)
|
||||
* can attempt to send arbitrary LAPIC/MSI messages. We are unprotected
|
||||
@@ -1708,16 +1701,19 @@ static int reassign_device_ownership(
|
||||
if ( (target != dom0) && !iommu_intremap )
|
||||
untrusted_msi = 1;
|
||||
|
||||
- ret = domain_context_unmap(source, seg, bus, devfn);
|
||||
+ ret = domain_context_unmap(source, pdev->seg, pdev->bus, devfn);
|
||||
if ( ret )
|
||||
return ret;
|
||||
|
||||
- ret = domain_context_mapping(target, seg, bus, devfn);
|
||||
+ ret = domain_context_mapping(target, pdev->seg, pdev->bus, devfn);
|
||||
if ( ret )
|
||||
return ret;
|
||||
|
||||
- list_move(&pdev->domain_list, &target->arch.pdev_list);
|
||||
- pdev->domain = target;
|
||||
+ if ( devfn == pdev->devfn )
|
||||
+ {
|
||||
+ list_move(&pdev->domain_list, &target->arch.pdev_list);
|
||||
+ pdev->domain = target;
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2222,36 +2218,26 @@ int __init intel_vtd_setup(void)
|
||||
}
|
||||
|
||||
static int intel_iommu_assign_device(
|
||||
- struct domain *d, u16 seg, u8 bus, u8 devfn)
|
||||
+ struct domain *d, u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
struct acpi_rmrr_unit *rmrr;
|
||||
int ret = 0, i;
|
||||
- struct pci_dev *pdev;
|
||||
- u16 bdf;
|
||||
+ u16 bdf, seg;
|
||||
+ u8 bus;
|
||||
|
||||
if ( list_empty(&acpi_drhd_units) )
|
||||
return -ENODEV;
|
||||
|
||||
- ASSERT(spin_is_locked(&pcidevs_lock));
|
||||
- pdev = pci_get_pdev(seg, bus, devfn);
|
||||
- if (!pdev)
|
||||
- return -ENODEV;
|
||||
-
|
||||
- if (pdev->domain != dom0)
|
||||
- {
|
||||
- dprintk(XENLOG_ERR VTDPREFIX,
|
||||
- "IOMMU: assign a assigned device\n");
|
||||
- return -EBUSY;
|
||||
- }
|
||||
-
|
||||
- ret = reassign_device_ownership(dom0, d, seg, bus, devfn);
|
||||
+ ret = reassign_device_ownership(dom0, d, devfn, pdev);
|
||||
if ( ret )
|
||||
goto done;
|
||||
|
||||
/* FIXME: Because USB RMRR conflicts with guest bios region,
|
||||
* ignore USB RMRR temporarily.
|
||||
*/
|
||||
- if ( is_usb_device(seg, bus, devfn) )
|
||||
+ seg = pdev->seg;
|
||||
+ bus = pdev->bus;
|
||||
+ if ( is_usb_device(seg, bus, pdev->devfn) )
|
||||
{
|
||||
ret = 0;
|
||||
goto done;
|
||||
Index: xen-4.2.2-testing/xen/include/xen/iommu.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/iommu.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/iommu.h
|
||||
@@ -123,13 +123,13 @@ struct iommu_ops {
|
||||
int (*add_device)(struct pci_dev *pdev);
|
||||
int (*enable_device)(struct pci_dev *pdev);
|
||||
int (*remove_device)(struct pci_dev *pdev);
|
||||
- int (*assign_device)(struct domain *d, u16 seg, u8 bus, u8 devfn);
|
||||
+ int (*assign_device)(struct domain *, u8 devfn, struct pci_dev *);
|
||||
void (*teardown)(struct domain *d);
|
||||
int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn,
|
||||
unsigned int flags);
|
||||
int (*unmap_page)(struct domain *d, unsigned long gfn);
|
||||
int (*reassign_device)(struct domain *s, struct domain *t,
|
||||
- u16 seg, u8 bus, u8 devfn);
|
||||
+ u8 devfn, struct pci_dev *);
|
||||
int (*get_device_group_id)(u16 seg, u8 bus, u8 devfn);
|
||||
void (*update_ire_from_apic)(unsigned int apic, unsigned int reg, unsigned int value);
|
||||
void (*update_ire_from_msi)(struct msi_desc *msi_desc, struct msi_msg *msg);
|
@ -1,366 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1357559482 -3600
|
||||
# Node ID 75cc4943b1ff509c4074800a23ff51d773233b8a
|
||||
# Parent 62dd78a4e3fc9d190840549f13b4d613f2d19c41
|
||||
IOMMU: adjust add/remove operation parameters
|
||||
|
||||
... to use a (struct pci_dev *, devfn) pair.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
||||
@@ -83,14 +83,14 @@ static void disable_translation(u32 *dte
|
||||
}
|
||||
|
||||
static void amd_iommu_setup_domain_device(
|
||||
- struct domain *domain, struct amd_iommu *iommu, int bdf)
|
||||
+ struct domain *domain, struct amd_iommu *iommu,
|
||||
+ u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
void *dte;
|
||||
unsigned long flags;
|
||||
int req_id, valid = 1;
|
||||
int dte_i = 0;
|
||||
- u8 bus = PCI_BUS(bdf);
|
||||
- u8 devfn = PCI_DEVFN2(bdf);
|
||||
+ u8 bus = pdev->bus;
|
||||
|
||||
struct hvm_iommu *hd = domain_hvm_iommu(domain);
|
||||
|
||||
@@ -103,7 +103,7 @@ static void amd_iommu_setup_domain_devic
|
||||
dte_i = 1;
|
||||
|
||||
/* get device-table entry */
|
||||
- req_id = get_dma_requestor_id(iommu->seg, bdf);
|
||||
+ req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn));
|
||||
dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
@@ -115,7 +115,7 @@ static void amd_iommu_setup_domain_devic
|
||||
(u32 *)dte, page_to_maddr(hd->root_table), hd->domain_id,
|
||||
hd->paging_mode, valid);
|
||||
|
||||
- if ( pci_ats_device(iommu->seg, bus, devfn) &&
|
||||
+ if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
|
||||
iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )
|
||||
iommu_dte_set_iotlb((u32 *)dte, dte_i);
|
||||
|
||||
@@ -132,32 +132,31 @@ static void amd_iommu_setup_domain_devic
|
||||
|
||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||
|
||||
- if ( pci_ats_device(iommu->seg, bus, devfn) &&
|
||||
- !pci_ats_enabled(iommu->seg, bus, devfn) )
|
||||
+ if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
|
||||
+ !pci_ats_enabled(iommu->seg, bus, pdev->devfn) )
|
||||
{
|
||||
- struct pci_dev *pdev;
|
||||
+ if ( devfn == pdev->devfn )
|
||||
+ enable_ats_device(iommu->seg, bus, devfn);
|
||||
|
||||
- enable_ats_device(iommu->seg, bus, devfn);
|
||||
-
|
||||
- ASSERT(spin_is_locked(&pcidevs_lock));
|
||||
- pdev = pci_get_pdev(iommu->seg, bus, devfn);
|
||||
-
|
||||
- ASSERT( pdev != NULL );
|
||||
amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
-static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev)
|
||||
+static int __init amd_iommu_setup_dom0_device(u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
int bdf = PCI_BDF2(pdev->bus, pdev->devfn);
|
||||
struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
|
||||
|
||||
- if ( likely(iommu != NULL) )
|
||||
- amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
|
||||
- else
|
||||
+ if ( unlikely(!iommu) )
|
||||
+ {
|
||||
AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n",
|
||||
pdev->seg, pdev->bus,
|
||||
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
|
||||
+ PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
int __init amd_iov_detect(void)
|
||||
@@ -296,16 +295,16 @@ static void __init amd_iommu_dom0_init(s
|
||||
}
|
||||
|
||||
void amd_iommu_disable_domain_device(struct domain *domain,
|
||||
- struct amd_iommu *iommu, int bdf)
|
||||
+ struct amd_iommu *iommu,
|
||||
+ u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
void *dte;
|
||||
unsigned long flags;
|
||||
int req_id;
|
||||
- u8 bus = PCI_BUS(bdf);
|
||||
- u8 devfn = PCI_DEVFN2(bdf);
|
||||
+ u8 bus = pdev->bus;
|
||||
|
||||
BUG_ON ( iommu->dev_table.buffer == NULL );
|
||||
- req_id = get_dma_requestor_id(iommu->seg, bdf);
|
||||
+ req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn));
|
||||
dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
@@ -313,7 +312,7 @@ void amd_iommu_disable_domain_device(str
|
||||
{
|
||||
disable_translation((u32 *)dte);
|
||||
|
||||
- if ( pci_ats_device(iommu->seg, bus, devfn) &&
|
||||
+ if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
|
||||
iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )
|
||||
iommu_dte_set_iotlb((u32 *)dte, 0);
|
||||
|
||||
@@ -328,7 +327,8 @@ void amd_iommu_disable_domain_device(str
|
||||
|
||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||
|
||||
- if ( pci_ats_device(iommu->seg, bus, devfn) &&
|
||||
+ if ( devfn == pdev->devfn &&
|
||||
+ pci_ats_device(iommu->seg, bus, devfn) &&
|
||||
pci_ats_enabled(iommu->seg, bus, devfn) )
|
||||
disable_ats_device(iommu->seg, bus, devfn);
|
||||
}
|
||||
@@ -351,7 +351,7 @@ static int reassign_device(struct domain
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
- amd_iommu_disable_domain_device(source, iommu, bdf);
|
||||
+ amd_iommu_disable_domain_device(source, iommu, devfn, pdev);
|
||||
|
||||
if ( devfn == pdev->devfn )
|
||||
{
|
||||
@@ -364,7 +364,7 @@ static int reassign_device(struct domain
|
||||
if ( t->root_table == NULL )
|
||||
allocate_domain_resources(t);
|
||||
|
||||
- amd_iommu_setup_domain_device(target, iommu, bdf);
|
||||
+ amd_iommu_setup_domain_device(target, iommu, devfn, pdev);
|
||||
AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n",
|
||||
pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
source->domain_id, target->domain_id);
|
||||
@@ -454,7 +454,7 @@ static void amd_iommu_domain_destroy(str
|
||||
amd_iommu_flush_all_pages(d);
|
||||
}
|
||||
|
||||
-static int amd_iommu_add_device(struct pci_dev *pdev)
|
||||
+static int amd_iommu_add_device(u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
struct amd_iommu *iommu;
|
||||
u16 bdf;
|
||||
@@ -467,16 +467,16 @@ static int amd_iommu_add_device(struct p
|
||||
{
|
||||
AMD_IOMMU_DEBUG("Fail to find iommu."
|
||||
" %04x:%02x:%02x.%u cannot be assigned to dom%d\n",
|
||||
- pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
|
||||
- PCI_FUNC(pdev->devfn), pdev->domain->domain_id);
|
||||
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
+ pdev->domain->domain_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
- amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
|
||||
+ amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int amd_iommu_remove_device(struct pci_dev *pdev)
|
||||
+static int amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
struct amd_iommu *iommu;
|
||||
u16 bdf;
|
||||
@@ -489,12 +489,12 @@ static int amd_iommu_remove_device(struc
|
||||
{
|
||||
AMD_IOMMU_DEBUG("Fail to find iommu."
|
||||
" %04x:%02x:%02x.%u cannot be removed from dom%d\n",
|
||||
- pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
|
||||
- PCI_FUNC(pdev->devfn), pdev->domain->domain_id);
|
||||
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
+ pdev->domain->domain_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
- amd_iommu_disable_domain_device(pdev->domain, iommu, bdf);
|
||||
+ amd_iommu_disable_domain_device(pdev->domain, iommu, devfn, pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/iommu.c
|
||||
@@ -167,7 +167,7 @@ int iommu_add_device(struct pci_dev *pde
|
||||
if ( !iommu_enabled || !hd->platform_ops )
|
||||
return 0;
|
||||
|
||||
- return hd->platform_ops->add_device(pdev);
|
||||
+ return hd->platform_ops->add_device(pdev->devfn, pdev);
|
||||
}
|
||||
|
||||
int iommu_enable_device(struct pci_dev *pdev)
|
||||
@@ -197,7 +197,7 @@ int iommu_remove_device(struct pci_dev *
|
||||
if ( !iommu_enabled || !hd->platform_ops )
|
||||
return 0;
|
||||
|
||||
- return hd->platform_ops->remove_device(pdev);
|
||||
+ return hd->platform_ops->remove_device(pdev->devfn, pdev);
|
||||
}
|
||||
|
||||
/*
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/pci.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
@@ -715,7 +715,7 @@ int __init scan_pci_devices(void)
|
||||
|
||||
struct setup_dom0 {
|
||||
struct domain *d;
|
||||
- void (*handler)(struct pci_dev *);
|
||||
+ int (*handler)(u8 devfn, struct pci_dev *);
|
||||
};
|
||||
|
||||
static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg)
|
||||
@@ -734,7 +734,7 @@ static int __init _setup_dom0_pci_device
|
||||
|
||||
pdev->domain = ctxt->d;
|
||||
list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list);
|
||||
- ctxt->handler(pdev);
|
||||
+ ctxt->handler(devfn, pdev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -742,7 +742,7 @@ static int __init _setup_dom0_pci_device
|
||||
}
|
||||
|
||||
void __init setup_dom0_pci_devices(
|
||||
- struct domain *d, void (*handler)(struct pci_dev *))
|
||||
+ struct domain *d, int (*handler)(u8 devfn, struct pci_dev *))
|
||||
{
|
||||
struct setup_dom0 ctxt = { .d = d, .handler = handler };
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/vtd/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
@@ -52,7 +52,7 @@ int nr_iommus;
|
||||
|
||||
static struct tasklet vtd_fault_tasklet;
|
||||
|
||||
-static void setup_dom0_device(struct pci_dev *);
|
||||
+static int setup_dom0_device(u8 devfn, struct pci_dev *);
|
||||
static void setup_dom0_rmrr(struct domain *d);
|
||||
|
||||
static int domain_iommu_domid(struct domain *d,
|
||||
@@ -1904,7 +1904,7 @@ static int rmrr_identity_mapping(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int intel_iommu_add_device(struct pci_dev *pdev)
|
||||
+static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
struct acpi_rmrr_unit *rmrr;
|
||||
u16 bdf;
|
||||
@@ -1915,8 +1915,7 @@ static int intel_iommu_add_device(struct
|
||||
if ( !pdev->domain )
|
||||
return -EINVAL;
|
||||
|
||||
- ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus,
|
||||
- pdev->devfn);
|
||||
+ ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
|
||||
if ( ret )
|
||||
{
|
||||
dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n",
|
||||
@@ -1928,7 +1927,7 @@ static int intel_iommu_add_device(struct
|
||||
{
|
||||
if ( rmrr->segment == pdev->seg &&
|
||||
PCI_BUS(bdf) == pdev->bus &&
|
||||
- PCI_DEVFN2(bdf) == pdev->devfn )
|
||||
+ PCI_DEVFN2(bdf) == devfn )
|
||||
{
|
||||
ret = rmrr_identity_mapping(pdev->domain, rmrr);
|
||||
if ( ret )
|
||||
@@ -1953,7 +1952,7 @@ static int intel_iommu_enable_device(str
|
||||
return ret >= 0 ? 0 : ret;
|
||||
}
|
||||
|
||||
-static int intel_iommu_remove_device(struct pci_dev *pdev)
|
||||
+static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
struct acpi_rmrr_unit *rmrr;
|
||||
u16 bdf;
|
||||
@@ -1971,19 +1970,22 @@ static int intel_iommu_remove_device(str
|
||||
{
|
||||
if ( rmrr->segment == pdev->seg &&
|
||||
PCI_BUS(bdf) == pdev->bus &&
|
||||
- PCI_DEVFN2(bdf) == pdev->devfn )
|
||||
+ PCI_DEVFN2(bdf) == devfn )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
- return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus,
|
||||
- pdev->devfn);
|
||||
+ return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus, devfn);
|
||||
}
|
||||
|
||||
-static void __init setup_dom0_device(struct pci_dev *pdev)
|
||||
+static int __init setup_dom0_device(u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
- domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, pdev->devfn);
|
||||
- pci_vtd_quirk(pdev);
|
||||
+ int err;
|
||||
+
|
||||
+ err = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
|
||||
+ if ( !err && devfn == pdev->devfn )
|
||||
+ pci_vtd_quirk(pdev);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
void clear_fault_bits(struct iommu *iommu)
|
||||
Index: xen-4.2.2-testing/xen/include/xen/iommu.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/iommu.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/iommu.h
|
||||
@@ -120,9 +120,9 @@ bool_t pt_irq_need_timer(uint32_t flags)
|
||||
struct iommu_ops {
|
||||
int (*init)(struct domain *d);
|
||||
void (*dom0_init)(struct domain *d);
|
||||
- int (*add_device)(struct pci_dev *pdev);
|
||||
+ int (*add_device)(u8 devfn, struct pci_dev *);
|
||||
int (*enable_device)(struct pci_dev *pdev);
|
||||
- int (*remove_device)(struct pci_dev *pdev);
|
||||
+ int (*remove_device)(u8 devfn, struct pci_dev *);
|
||||
int (*assign_device)(struct domain *, u8 devfn, struct pci_dev *);
|
||||
void (*teardown)(struct domain *d);
|
||||
int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn,
|
||||
Index: xen-4.2.2-testing/xen/include/xen/pci.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/pci.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/pci.h
|
||||
@@ -101,7 +101,8 @@ struct pci_dev *pci_lock_pdev(int seg, i
|
||||
struct pci_dev *pci_lock_domain_pdev(
|
||||
struct domain *, int seg, int bus, int devfn);
|
||||
|
||||
-void setup_dom0_pci_devices(struct domain *, void (*)(struct pci_dev *));
|
||||
+void setup_dom0_pci_devices(struct domain *,
|
||||
+ int (*)(u8 devfn, struct pci_dev *));
|
||||
void pci_release_devices(struct domain *d);
|
||||
int pci_add_segment(u16 seg);
|
||||
const unsigned long *pci_get_ro_map(u16 seg);
|
@ -1,193 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1357559549 -3600
|
||||
# Node ID afb598bd0f5436bea15b7ef842e8ad5c6adefa1a
|
||||
# Parent 75cc4943b1ff509c4074800a23ff51d773233b8a
|
||||
VT-d: adjust context map/unmap parameters
|
||||
|
||||
... to use a (struct pci_dev *, devfn) pair.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/vtd/extern.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/vtd/extern.h
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/vtd/extern.h
|
||||
@@ -95,7 +95,7 @@ void free_pgtable_maddr(u64 maddr);
|
||||
void *map_vtd_domain_page(u64 maddr);
|
||||
void unmap_vtd_domain_page(void *va);
|
||||
int domain_context_mapping_one(struct domain *domain, struct iommu *iommu,
|
||||
- u8 bus, u8 devfn);
|
||||
+ u8 bus, u8 devfn, const struct pci_dev *);
|
||||
int domain_context_unmap_one(struct domain *domain, struct iommu *iommu,
|
||||
u8 bus, u8 devfn);
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/vtd/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
@@ -1308,7 +1308,7 @@ static void __init intel_iommu_dom0_init
|
||||
int domain_context_mapping_one(
|
||||
struct domain *domain,
|
||||
struct iommu *iommu,
|
||||
- u8 bus, u8 devfn)
|
||||
+ u8 bus, u8 devfn, const struct pci_dev *pdev)
|
||||
{
|
||||
struct hvm_iommu *hd = domain_hvm_iommu(domain);
|
||||
struct context_entry *context, *context_entries;
|
||||
@@ -1325,11 +1325,9 @@ int domain_context_mapping_one(
|
||||
if ( context_present(*context) )
|
||||
{
|
||||
int res = 0;
|
||||
- struct pci_dev *pdev = NULL;
|
||||
|
||||
- /* First try to get domain ownership from device structure. If that's
|
||||
+ /* Try to get domain ownership from device structure. If that's
|
||||
* not available, try to read it from the context itself. */
|
||||
- pdev = pci_get_pdev(seg, bus, devfn);
|
||||
if ( pdev )
|
||||
{
|
||||
if ( pdev->domain != domain )
|
||||
@@ -1448,13 +1446,12 @@ int domain_context_mapping_one(
|
||||
}
|
||||
|
||||
static int domain_context_mapping(
|
||||
- struct domain *domain, u16 seg, u8 bus, u8 devfn)
|
||||
+ struct domain *domain, u8 devfn, const struct pci_dev *pdev)
|
||||
{
|
||||
struct acpi_drhd_unit *drhd;
|
||||
int ret = 0;
|
||||
u32 type;
|
||||
- u8 secbus;
|
||||
- struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
|
||||
+ u8 seg = pdev->seg, bus = pdev->bus, secbus;
|
||||
|
||||
drhd = acpi_find_matched_drhd_unit(pdev);
|
||||
if ( !drhd )
|
||||
@@ -1475,8 +1472,9 @@ static int domain_context_mapping(
|
||||
dprintk(VTDPREFIX, "d%d:PCIe: map %04x:%02x:%02x.%u\n",
|
||||
domain->domain_id, seg, bus,
|
||||
PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
- ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
|
||||
- if ( !ret && ats_device(pdev, drhd) > 0 )
|
||||
+ ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
|
||||
+ pdev);
|
||||
+ if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 )
|
||||
enable_ats_device(seg, bus, devfn);
|
||||
|
||||
break;
|
||||
@@ -1487,14 +1485,16 @@ static int domain_context_mapping(
|
||||
domain->domain_id, seg, bus,
|
||||
PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
|
||||
- ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
|
||||
+ ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
|
||||
+ pdev);
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
if ( find_upstream_bridge(seg, &bus, &devfn, &secbus) < 1 )
|
||||
break;
|
||||
|
||||
- ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
|
||||
+ ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
|
||||
+ pci_get_pdev(seg, bus, devfn));
|
||||
|
||||
/*
|
||||
* Devices behind PCIe-to-PCI/PCIx bridge may generate different
|
||||
@@ -1503,7 +1503,8 @@ static int domain_context_mapping(
|
||||
*/
|
||||
if ( !ret && pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE &&
|
||||
(secbus != pdev->bus || pdev->devfn != 0) )
|
||||
- ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0);
|
||||
+ ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0,
|
||||
+ pci_get_pdev(seg, secbus, 0));
|
||||
|
||||
break;
|
||||
|
||||
@@ -1576,18 +1577,15 @@ int domain_context_unmap_one(
|
||||
}
|
||||
|
||||
static int domain_context_unmap(
|
||||
- struct domain *domain, u16 seg, u8 bus, u8 devfn)
|
||||
+ struct domain *domain, u8 devfn, const struct pci_dev *pdev)
|
||||
{
|
||||
struct acpi_drhd_unit *drhd;
|
||||
struct iommu *iommu;
|
||||
int ret = 0;
|
||||
u32 type;
|
||||
- u8 tmp_bus, tmp_devfn, secbus;
|
||||
- struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
|
||||
+ u8 seg = pdev->seg, bus = pdev->bus, tmp_bus, tmp_devfn, secbus;
|
||||
int found = 0;
|
||||
|
||||
- BUG_ON(!pdev);
|
||||
-
|
||||
drhd = acpi_find_matched_drhd_unit(pdev);
|
||||
if ( !drhd )
|
||||
return -ENODEV;
|
||||
@@ -1607,7 +1605,7 @@ static int domain_context_unmap(
|
||||
domain->domain_id, seg, bus,
|
||||
PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
ret = domain_context_unmap_one(domain, iommu, bus, devfn);
|
||||
- if ( !ret && ats_device(pdev, drhd) > 0 )
|
||||
+ if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 )
|
||||
disable_ats_device(seg, bus, devfn);
|
||||
|
||||
break;
|
||||
@@ -1701,11 +1699,11 @@ static int reassign_device_ownership(
|
||||
if ( (target != dom0) && !iommu_intremap )
|
||||
untrusted_msi = 1;
|
||||
|
||||
- ret = domain_context_unmap(source, pdev->seg, pdev->bus, devfn);
|
||||
+ ret = domain_context_unmap(source, devfn, pdev);
|
||||
if ( ret )
|
||||
return ret;
|
||||
|
||||
- ret = domain_context_mapping(target, pdev->seg, pdev->bus, devfn);
|
||||
+ ret = domain_context_mapping(target, devfn, pdev);
|
||||
if ( ret )
|
||||
return ret;
|
||||
|
||||
@@ -1915,7 +1913,7 @@ static int intel_iommu_add_device(u8 dev
|
||||
if ( !pdev->domain )
|
||||
return -EINVAL;
|
||||
|
||||
- ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
|
||||
+ ret = domain_context_mapping(pdev->domain, devfn, pdev);
|
||||
if ( ret )
|
||||
{
|
||||
dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n",
|
||||
@@ -1975,14 +1973,14 @@ static int intel_iommu_remove_device(u8
|
||||
}
|
||||
}
|
||||
|
||||
- return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus, devfn);
|
||||
+ return domain_context_unmap(pdev->domain, devfn, pdev);
|
||||
}
|
||||
|
||||
static int __init setup_dom0_device(u8 devfn, struct pci_dev *pdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
- err = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
|
||||
+ err = domain_context_mapping(pdev->domain, devfn, pdev);
|
||||
if ( !err && devfn == pdev->devfn )
|
||||
pci_vtd_quirk(pdev);
|
||||
return err;
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/vtd/quirks.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/vtd/quirks.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/vtd/quirks.c
|
||||
@@ -319,7 +319,7 @@ static void map_me_phantom_function(stru
|
||||
/* map or unmap ME phantom function */
|
||||
if ( map )
|
||||
domain_context_mapping_one(domain, drhd->iommu, 0,
|
||||
- PCI_DEVFN(dev, 7));
|
||||
+ PCI_DEVFN(dev, 7), NULL);
|
||||
else
|
||||
domain_context_unmap_one(domain, drhd->iommu, 0,
|
||||
PCI_DEVFN(dev, 7));
|
@ -1,84 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1357559599 -3600
|
||||
# Node ID 2a2c63f641ee3bda4ad552eb0b3ea479d37590cc
|
||||
# Parent afb598bd0f5436bea15b7ef842e8ad5c6adefa1a
|
||||
AMD IOMMU: adjust flush function parameters
|
||||
|
||||
... to use a (struct pci_dev *, devfn) pair.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
--- a/xen/drivers/passthrough/amd/iommu_cmd.c
|
||||
+++ b/xen/drivers/passthrough/amd/iommu_cmd.c
|
||||
@@ -287,12 +287,12 @@ void invalidate_iommu_all(struct amd_iom
|
||||
send_iommu_command(iommu, cmd);
|
||||
}
|
||||
|
||||
-void amd_iommu_flush_iotlb(struct pci_dev *pdev,
|
||||
+void amd_iommu_flush_iotlb(u8 devfn, const struct pci_dev *pdev,
|
||||
uint64_t gaddr, unsigned int order)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct amd_iommu *iommu;
|
||||
- unsigned int bdf, req_id, queueid, maxpend;
|
||||
+ unsigned int req_id, queueid, maxpend;
|
||||
struct pci_ats_dev *ats_pdev;
|
||||
|
||||
if ( !ats_enabled )
|
||||
@@ -305,8 +305,8 @@ void amd_iommu_flush_iotlb(struct pci_de
|
||||
if ( !pci_ats_enabled(ats_pdev->seg, ats_pdev->bus, ats_pdev->devfn) )
|
||||
return;
|
||||
|
||||
- bdf = PCI_BDF2(ats_pdev->bus, ats_pdev->devfn);
|
||||
- iommu = find_iommu_for_device(ats_pdev->seg, bdf);
|
||||
+ iommu = find_iommu_for_device(ats_pdev->seg,
|
||||
+ PCI_BDF2(ats_pdev->bus, ats_pdev->devfn));
|
||||
|
||||
if ( !iommu )
|
||||
{
|
||||
@@ -319,7 +319,7 @@ void amd_iommu_flush_iotlb(struct pci_de
|
||||
if ( !iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )
|
||||
return;
|
||||
|
||||
- req_id = get_dma_requestor_id(iommu->seg, bdf);
|
||||
+ req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(ats_pdev->bus, devfn));
|
||||
queueid = req_id;
|
||||
maxpend = ats_pdev->ats_queue_depth & 0xff;
|
||||
|
||||
@@ -339,7 +339,7 @@ static void amd_iommu_flush_all_iotlbs(s
|
||||
return;
|
||||
|
||||
for_each_pdev( d, pdev )
|
||||
- amd_iommu_flush_iotlb(pdev, gaddr, order);
|
||||
+ amd_iommu_flush_iotlb(pdev->devfn, pdev, gaddr, order);
|
||||
}
|
||||
|
||||
/* Flush iommu cache after p2m changes. */
|
||||
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
||||
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
||||
@@ -138,7 +138,7 @@ static void amd_iommu_setup_domain_devic
|
||||
if ( devfn == pdev->devfn )
|
||||
enable_ats_device(iommu->seg, bus, devfn);
|
||||
|
||||
- amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
|
||||
+ amd_iommu_flush_iotlb(devfn, pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
|
||||
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
|
||||
@@ -78,8 +78,8 @@ void iommu_dte_set_guest_cr3(u32 *dte, u
|
||||
void amd_iommu_flush_all_pages(struct domain *d);
|
||||
void amd_iommu_flush_pages(struct domain *d, unsigned long gfn,
|
||||
unsigned int order);
|
||||
-void amd_iommu_flush_iotlb(struct pci_dev *pdev, uint64_t gaddr,
|
||||
- unsigned int order);
|
||||
+void amd_iommu_flush_iotlb(u8 devfn, const struct pci_dev *pdev,
|
||||
+ uint64_t gaddr, unsigned int order);
|
||||
void amd_iommu_flush_device(struct amd_iommu *iommu, uint16_t bdf);
|
||||
void amd_iommu_flush_intremap(struct amd_iommu *iommu, uint16_t bdf);
|
||||
void amd_iommu_flush_all_caches(struct amd_iommu *iommu);
|
@ -1,232 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1357559679 -3600
|
||||
# Node ID 11fa145c880ee814aaf56a7f47f47ee3e5560c7c
|
||||
# Parent 2a2c63f641ee3bda4ad552eb0b3ea479d37590cc
|
||||
IOMMU/PCI: consolidate pdev_type() and cache its result for a given device
|
||||
|
||||
Add an "unknown" device types as well as one for PCI-to-PCIe bridges
|
||||
(the latter of which other IOMMU code with or without this patch
|
||||
doesn't appear to handle properly).
|
||||
|
||||
Make sure we don't mistake a device for which we can't access its
|
||||
config space as a legacy PCI device (after all we in fact don't know
|
||||
how to deal with such a device, and hence shouldn't try to).
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/pci.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
@@ -144,7 +144,7 @@ static struct pci_dev *alloc_pdev(struct
|
||||
spin_lock_init(&pdev->msix_table_lock);
|
||||
|
||||
/* update bus2bridge */
|
||||
- switch ( pdev_type(pseg->nr, bus, devfn) )
|
||||
+ switch ( pdev->type = pdev_type(pseg->nr, bus, devfn) )
|
||||
{
|
||||
u8 sec_bus, sub_bus;
|
||||
|
||||
@@ -184,7 +184,7 @@ static struct pci_dev *alloc_pdev(struct
|
||||
static void free_pdev(struct pci_seg *pseg, struct pci_dev *pdev)
|
||||
{
|
||||
/* update bus2bridge */
|
||||
- switch ( pdev_type(pseg->nr, pdev->bus, pdev->devfn) )
|
||||
+ switch ( pdev->type )
|
||||
{
|
||||
u8 dev, func, sec_bus, sub_bus;
|
||||
|
||||
@@ -202,6 +202,9 @@ static void free_pdev(struct pci_seg *ps
|
||||
pseg->bus2bridge[sec_bus] = pseg->bus2bridge[pdev->bus];
|
||||
spin_unlock(&pseg->bus2bridge_lock);
|
||||
break;
|
||||
+
|
||||
+ default:
|
||||
+ break;
|
||||
}
|
||||
|
||||
list_del(&pdev->alldevs_list);
|
||||
@@ -563,20 +566,30 @@ void pci_release_devices(struct domain *
|
||||
|
||||
#define PCI_CLASS_BRIDGE_PCI 0x0604
|
||||
|
||||
-int pdev_type(u16 seg, u8 bus, u8 devfn)
|
||||
+enum pdev_type pdev_type(u16 seg, u8 bus, u8 devfn)
|
||||
{
|
||||
u16 class_device, creg;
|
||||
u8 d = PCI_SLOT(devfn), f = PCI_FUNC(devfn);
|
||||
int pos = pci_find_cap_offset(seg, bus, d, f, PCI_CAP_ID_EXP);
|
||||
|
||||
class_device = pci_conf_read16(seg, bus, d, f, PCI_CLASS_DEVICE);
|
||||
- if ( class_device == PCI_CLASS_BRIDGE_PCI )
|
||||
+ switch ( class_device )
|
||||
{
|
||||
+ case PCI_CLASS_BRIDGE_PCI:
|
||||
if ( !pos )
|
||||
return DEV_TYPE_LEGACY_PCI_BRIDGE;
|
||||
creg = pci_conf_read16(seg, bus, d, f, pos + PCI_EXP_FLAGS);
|
||||
- return ((creg & PCI_EXP_FLAGS_TYPE) >> 4) == PCI_EXP_TYPE_PCI_BRIDGE ?
|
||||
- DEV_TYPE_PCIe2PCI_BRIDGE : DEV_TYPE_PCIe_BRIDGE;
|
||||
+ switch ( (creg & PCI_EXP_FLAGS_TYPE) >> 4 )
|
||||
+ {
|
||||
+ case PCI_EXP_TYPE_PCI_BRIDGE:
|
||||
+ return DEV_TYPE_PCIe2PCI_BRIDGE;
|
||||
+ case PCI_EXP_TYPE_PCIE_BRIDGE:
|
||||
+ return DEV_TYPE_PCI2PCIe_BRIDGE;
|
||||
+ }
|
||||
+ return DEV_TYPE_PCIe_BRIDGE;
|
||||
+
|
||||
+ case 0x0000: case 0xffff:
|
||||
+ return DEV_TYPE_PCI_UNKNOWN;
|
||||
}
|
||||
|
||||
return pos ? DEV_TYPE_PCIe_ENDPOINT : DEV_TYPE_PCI;
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/vtd/intremap.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/vtd/intremap.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/vtd/intremap.c
|
||||
@@ -426,7 +426,6 @@ void io_apic_write_remap_rte(
|
||||
|
||||
static void set_msi_source_id(struct pci_dev *pdev, struct iremap_entry *ire)
|
||||
{
|
||||
- int type;
|
||||
u16 seg;
|
||||
u8 bus, devfn, secbus;
|
||||
int ret;
|
||||
@@ -437,8 +436,7 @@ static void set_msi_source_id(struct pci
|
||||
seg = pdev->seg;
|
||||
bus = pdev->bus;
|
||||
devfn = pdev->devfn;
|
||||
- type = pdev_type(seg, bus, devfn);
|
||||
- switch ( type )
|
||||
+ switch ( pdev->type )
|
||||
{
|
||||
case DEV_TYPE_PCIe_BRIDGE:
|
||||
case DEV_TYPE_PCIe2PCI_BRIDGE:
|
||||
@@ -470,7 +468,7 @@ static void set_msi_source_id(struct pci
|
||||
default:
|
||||
dprintk(XENLOG_WARNING VTDPREFIX,
|
||||
"d%d: unknown(%u): %04x:%02x:%02x.%u\n",
|
||||
- pdev->domain->domain_id, type,
|
||||
+ pdev->domain->domain_id, pdev->type,
|
||||
seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
break;
|
||||
}
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/vtd/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/vtd/iommu.c
|
||||
@@ -1450,7 +1450,6 @@ static int domain_context_mapping(
|
||||
{
|
||||
struct acpi_drhd_unit *drhd;
|
||||
int ret = 0;
|
||||
- u32 type;
|
||||
u8 seg = pdev->seg, bus = pdev->bus, secbus;
|
||||
|
||||
drhd = acpi_find_matched_drhd_unit(pdev);
|
||||
@@ -1459,8 +1458,7 @@ static int domain_context_mapping(
|
||||
|
||||
ASSERT(spin_is_locked(&pcidevs_lock));
|
||||
|
||||
- type = pdev_type(seg, bus, devfn);
|
||||
- switch ( type )
|
||||
+ switch ( pdev->type )
|
||||
{
|
||||
case DEV_TYPE_PCIe_BRIDGE:
|
||||
case DEV_TYPE_PCIe2PCI_BRIDGE:
|
||||
@@ -1510,7 +1508,7 @@ static int domain_context_mapping(
|
||||
|
||||
default:
|
||||
dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): %04x:%02x:%02x.%u\n",
|
||||
- domain->domain_id, type,
|
||||
+ domain->domain_id, pdev->type,
|
||||
seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
@@ -1582,7 +1580,6 @@ static int domain_context_unmap(
|
||||
struct acpi_drhd_unit *drhd;
|
||||
struct iommu *iommu;
|
||||
int ret = 0;
|
||||
- u32 type;
|
||||
u8 seg = pdev->seg, bus = pdev->bus, tmp_bus, tmp_devfn, secbus;
|
||||
int found = 0;
|
||||
|
||||
@@ -1591,8 +1588,7 @@ static int domain_context_unmap(
|
||||
return -ENODEV;
|
||||
iommu = drhd->iommu;
|
||||
|
||||
- type = pdev_type(seg, bus, devfn);
|
||||
- switch ( type )
|
||||
+ switch ( pdev->type )
|
||||
{
|
||||
case DEV_TYPE_PCIe_BRIDGE:
|
||||
case DEV_TYPE_PCIe2PCI_BRIDGE:
|
||||
@@ -1639,7 +1635,7 @@ static int domain_context_unmap(
|
||||
|
||||
default:
|
||||
dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): %04x:%02x:%02x.%u\n",
|
||||
- domain->domain_id, type,
|
||||
+ domain->domain_id, pdev->type,
|
||||
seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
Index: xen-4.2.2-testing/xen/include/xen/pci.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/pci.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/pci.h
|
||||
@@ -63,6 +63,17 @@ struct pci_dev {
|
||||
const u16 seg;
|
||||
const u8 bus;
|
||||
const u8 devfn;
|
||||
+
|
||||
+ enum pdev_type {
|
||||
+ DEV_TYPE_PCI_UNKNOWN,
|
||||
+ DEV_TYPE_PCIe_ENDPOINT,
|
||||
+ DEV_TYPE_PCIe_BRIDGE, // PCIe root port, switch
|
||||
+ DEV_TYPE_PCIe2PCI_BRIDGE, // PCIe-to-PCI/PCIx bridge
|
||||
+ DEV_TYPE_PCI2PCIe_BRIDGE, // PCI/PCIx-to-PCIe bridge
|
||||
+ DEV_TYPE_LEGACY_PCI_BRIDGE, // Legacy PCI bridge
|
||||
+ DEV_TYPE_PCI,
|
||||
+ } type;
|
||||
+
|
||||
struct pci_dev_info info;
|
||||
struct arch_pci_dev arch;
|
||||
struct {
|
||||
@@ -84,18 +95,10 @@ struct pci_dev {
|
||||
|
||||
extern spinlock_t pcidevs_lock;
|
||||
|
||||
-enum {
|
||||
- DEV_TYPE_PCIe_ENDPOINT,
|
||||
- DEV_TYPE_PCIe_BRIDGE, // PCIe root port, switch
|
||||
- DEV_TYPE_PCIe2PCI_BRIDGE, // PCIe-to-PCI/PCIx bridge
|
||||
- DEV_TYPE_LEGACY_PCI_BRIDGE, // Legacy PCI bridge
|
||||
- DEV_TYPE_PCI,
|
||||
-};
|
||||
-
|
||||
bool_t pci_known_segment(u16 seg);
|
||||
int pci_device_detect(u16 seg, u8 bus, u8 dev, u8 func);
|
||||
int scan_pci_devices(void);
|
||||
-int pdev_type(u16 seg, u8 bus, u8 devfn);
|
||||
+enum pdev_type pdev_type(u16 seg, u8 bus, u8 devfn);
|
||||
int find_upstream_bridge(u16 seg, u8 *bus, u8 *devfn, u8 *secbus);
|
||||
struct pci_dev *pci_lock_pdev(int seg, int bus, int devfn);
|
||||
struct pci_dev *pci_lock_domain_pdev(
|
||||
Index: xen-4.2.2-testing/xen/include/xen/pci_regs.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/pci_regs.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/pci_regs.h
|
||||
@@ -371,6 +371,9 @@
|
||||
#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */
|
||||
#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
|
||||
#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */
|
||||
+#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIE Bridge */
|
||||
+#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */
|
||||
+#define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */
|
||||
#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
|
||||
#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
|
||||
#define PCI_EXP_DEVCAP 4 /* Device capabilities */
|
@ -1,377 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1357559742 -3600
|
||||
# Node ID c9a01b396cb4eaedef30e9a6ed615115a9f8bfc5
|
||||
# Parent 11fa145c880ee814aaf56a7f47f47ee3e5560c7c
|
||||
IOMMU: add phantom function support
|
||||
|
||||
Apart from generating device context entries for the base function,
|
||||
all phantom functions also need context entries to be generated for
|
||||
them.
|
||||
|
||||
In order to distinguish different use cases, a variant of
|
||||
pci_get_pdev() is being introduced that, even when passed a phantom
|
||||
function number, would return the underlying actual device.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/amd/iommu_cmd.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/amd/iommu_cmd.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/amd/iommu_cmd.c
|
||||
@@ -339,7 +339,15 @@ static void amd_iommu_flush_all_iotlbs(s
|
||||
return;
|
||||
|
||||
for_each_pdev( d, pdev )
|
||||
- amd_iommu_flush_iotlb(pdev->devfn, pdev, gaddr, order);
|
||||
+ {
|
||||
+ u8 devfn = pdev->devfn;
|
||||
+
|
||||
+ do {
|
||||
+ amd_iommu_flush_iotlb(devfn, pdev, gaddr, order);
|
||||
+ devfn += pdev->phantom_stride;
|
||||
+ } while ( devfn != pdev->devfn &&
|
||||
+ PCI_SLOT(devfn) == PCI_SLOT(pdev->devfn) );
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Flush iommu cache after p2m changes. */
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/amd/iommu_init.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/amd/iommu_init.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/amd/iommu_init.c
|
||||
@@ -692,7 +692,7 @@ void parse_ppr_log_entry(struct amd_iomm
|
||||
devfn = PCI_DEVFN2(device_id);
|
||||
|
||||
spin_lock(&pcidevs_lock);
|
||||
- pdev = pci_get_pdev(iommu->seg, bus, devfn);
|
||||
+ pdev = pci_get_real_pdev(iommu->seg, bus, devfn);
|
||||
spin_unlock(&pcidevs_lock);
|
||||
|
||||
if ( pdev )
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/amd/iommu_map.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/amd/iommu_map.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/amd/iommu_map.c
|
||||
@@ -612,7 +612,6 @@ static int update_paging_mode(struct dom
|
||||
for_each_pdev( d, pdev )
|
||||
{
|
||||
bdf = (pdev->bus << 8) | pdev->devfn;
|
||||
- req_id = get_dma_requestor_id(pdev->seg, bdf);
|
||||
iommu = find_iommu_for_device(pdev->seg, bdf);
|
||||
if ( !iommu )
|
||||
{
|
||||
@@ -621,16 +620,21 @@ static int update_paging_mode(struct dom
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
- device_entry = iommu->dev_table.buffer +
|
||||
- (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
|
||||
+ do {
|
||||
+ req_id = get_dma_requestor_id(pdev->seg, bdf);
|
||||
+ device_entry = iommu->dev_table.buffer +
|
||||
+ (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
|
||||
|
||||
- /* valid = 0 only works for dom0 passthrough mode */
|
||||
- amd_iommu_set_root_page_table((u32 *)device_entry,
|
||||
- page_to_maddr(hd->root_table),
|
||||
- hd->domain_id,
|
||||
- hd->paging_mode, 1);
|
||||
+ /* valid = 0 only works for dom0 passthrough mode */
|
||||
+ amd_iommu_set_root_page_table((u32 *)device_entry,
|
||||
+ page_to_maddr(hd->root_table),
|
||||
+ hd->domain_id,
|
||||
+ hd->paging_mode, 1);
|
||||
|
||||
- amd_iommu_flush_device(iommu, req_id);
|
||||
+ amd_iommu_flush_device(iommu, req_id);
|
||||
+ bdf += pdev->phantom_stride;
|
||||
+ } while ( PCI_DEVFN2(bdf) != pdev->devfn &&
|
||||
+ PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) );
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/iommu.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/iommu.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/iommu.c
|
||||
@@ -157,6 +157,8 @@ void __init iommu_dom0_init(struct domai
|
||||
int iommu_add_device(struct pci_dev *pdev)
|
||||
{
|
||||
struct hvm_iommu *hd;
|
||||
+ int rc;
|
||||
+ u8 devfn;
|
||||
|
||||
if ( !pdev->domain )
|
||||
return -EINVAL;
|
||||
@@ -167,7 +169,20 @@ int iommu_add_device(struct pci_dev *pde
|
||||
if ( !iommu_enabled || !hd->platform_ops )
|
||||
return 0;
|
||||
|
||||
- return hd->platform_ops->add_device(pdev->devfn, pdev);
|
||||
+ rc = hd->platform_ops->add_device(pdev->devfn, pdev);
|
||||
+ if ( rc || !pdev->phantom_stride )
|
||||
+ return rc;
|
||||
+
|
||||
+ for ( devfn = pdev->devfn ; ; )
|
||||
+ {
|
||||
+ devfn += pdev->phantom_stride;
|
||||
+ if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
|
||||
+ return 0;
|
||||
+ rc = hd->platform_ops->add_device(devfn, pdev);
|
||||
+ if ( rc )
|
||||
+ printk(XENLOG_WARNING "IOMMU: add %04x:%02x:%02x.%u failed (%d)\n",
|
||||
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), rc);
|
||||
+ }
|
||||
}
|
||||
|
||||
int iommu_enable_device(struct pci_dev *pdev)
|
||||
@@ -190,6 +205,8 @@ int iommu_enable_device(struct pci_dev *
|
||||
int iommu_remove_device(struct pci_dev *pdev)
|
||||
{
|
||||
struct hvm_iommu *hd;
|
||||
+ u8 devfn;
|
||||
+
|
||||
if ( !pdev->domain )
|
||||
return -EINVAL;
|
||||
|
||||
@@ -197,6 +214,22 @@ int iommu_remove_device(struct pci_dev *
|
||||
if ( !iommu_enabled || !hd->platform_ops )
|
||||
return 0;
|
||||
|
||||
+ for ( devfn = pdev->devfn ; pdev->phantom_stride; )
|
||||
+ {
|
||||
+ int rc;
|
||||
+
|
||||
+ devfn += pdev->phantom_stride;
|
||||
+ if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
|
||||
+ break;
|
||||
+ rc = hd->platform_ops->remove_device(devfn, pdev);
|
||||
+ if ( !rc )
|
||||
+ continue;
|
||||
+
|
||||
+ printk(XENLOG_ERR "IOMMU: remove %04x:%02x:%02x.%u failed (%d)\n",
|
||||
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
return hd->platform_ops->remove_device(pdev->devfn, pdev);
|
||||
}
|
||||
|
||||
@@ -244,6 +277,18 @@ static int assign_device(struct domain *
|
||||
if ( (rc = hd->platform_ops->assign_device(d, devfn, pdev)) )
|
||||
goto done;
|
||||
|
||||
+ for ( ; pdev->phantom_stride; rc = 0 )
|
||||
+ {
|
||||
+ devfn += pdev->phantom_stride;
|
||||
+ if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
|
||||
+ break;
|
||||
+ rc = hd->platform_ops->assign_device(d, devfn, pdev);
|
||||
+ if ( rc )
|
||||
+ printk(XENLOG_G_WARNING "d%d: assign %04x:%02x:%02x.%u failed (%d)\n",
|
||||
+ d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
+ rc);
|
||||
+ }
|
||||
+
|
||||
if ( has_arch_pdevs(d) && !need_iommu(d) )
|
||||
{
|
||||
d->need_iommu = 1;
|
||||
@@ -376,6 +421,21 @@ int deassign_device(struct domain *d, u1
|
||||
if ( !pdev )
|
||||
return -ENODEV;
|
||||
|
||||
+ while ( pdev->phantom_stride )
|
||||
+ {
|
||||
+ devfn += pdev->phantom_stride;
|
||||
+ if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) )
|
||||
+ break;
|
||||
+ ret = hd->platform_ops->reassign_device(d, dom0, devfn, pdev);
|
||||
+ if ( !ret )
|
||||
+ continue;
|
||||
+
|
||||
+ printk(XENLOG_G_ERR "d%d: deassign %04x:%02x:%02x.%u failed (%d)\n",
|
||||
+ d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ devfn = pdev->devfn;
|
||||
ret = hd->platform_ops->reassign_device(d, dom0, devfn, pdev);
|
||||
if ( ret )
|
||||
{
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/pci.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
@@ -146,6 +146,8 @@ static struct pci_dev *alloc_pdev(struct
|
||||
/* update bus2bridge */
|
||||
switch ( pdev->type = pdev_type(pseg->nr, bus, devfn) )
|
||||
{
|
||||
+ int pos;
|
||||
+ u16 cap;
|
||||
u8 sec_bus, sub_bus;
|
||||
|
||||
case DEV_TYPE_PCIe_BRIDGE:
|
||||
@@ -169,6 +171,20 @@ static struct pci_dev *alloc_pdev(struct
|
||||
break;
|
||||
|
||||
case DEV_TYPE_PCIe_ENDPOINT:
|
||||
+ pos = pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn),
|
||||
+ PCI_FUNC(devfn), PCI_CAP_ID_EXP);
|
||||
+ BUG_ON(!pos);
|
||||
+ cap = pci_conf_read16(pseg->nr, bus, PCI_SLOT(devfn),
|
||||
+ PCI_FUNC(devfn), pos + PCI_EXP_DEVCAP);
|
||||
+ if ( cap & PCI_EXP_DEVCAP_PHANTOM )
|
||||
+ {
|
||||
+ pdev->phantom_stride = 8 >> MASK_EXTR(cap,
|
||||
+ PCI_EXP_DEVCAP_PHANTOM);
|
||||
+ if ( PCI_FUNC(devfn) >= pdev->phantom_stride )
|
||||
+ pdev->phantom_stride = 0;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
case DEV_TYPE_PCI:
|
||||
break;
|
||||
|
||||
@@ -266,6 +282,27 @@ struct pci_dev *pci_get_pdev(int seg, in
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+struct pci_dev *pci_get_real_pdev(int seg, int bus, int devfn)
|
||||
+{
|
||||
+ struct pci_dev *pdev;
|
||||
+ int stride;
|
||||
+
|
||||
+ if ( seg < 0 || bus < 0 || devfn < 0 )
|
||||
+ return NULL;
|
||||
+
|
||||
+ for ( pdev = pci_get_pdev(seg, bus, devfn), stride = 4;
|
||||
+ !pdev && stride; stride >>= 1 )
|
||||
+ {
|
||||
+ if ( !(devfn & (8 - stride)) )
|
||||
+ continue;
|
||||
+ pdev = pci_get_pdev(seg, bus, devfn & ~(8 - stride));
|
||||
+ if ( pdev && stride != pdev->phantom_stride )
|
||||
+ pdev = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return pdev;
|
||||
+}
|
||||
+
|
||||
struct pci_dev *pci_get_pdev_by_domain(
|
||||
struct domain *d, int seg, int bus, int devfn)
|
||||
{
|
||||
@@ -464,8 +501,19 @@ int pci_add_device(u16 seg, u8 bus, u8 d
|
||||
|
||||
out:
|
||||
spin_unlock(&pcidevs_lock);
|
||||
- printk(XENLOG_DEBUG "PCI add %s %04x:%02x:%02x.%u\n", pdev_type,
|
||||
- seg, bus, slot, func);
|
||||
+ if ( !ret )
|
||||
+ {
|
||||
+ printk(XENLOG_DEBUG "PCI add %s %04x:%02x:%02x.%u\n", pdev_type,
|
||||
+ seg, bus, slot, func);
|
||||
+ while ( pdev->phantom_stride )
|
||||
+ {
|
||||
+ func += pdev->phantom_stride;
|
||||
+ if ( PCI_SLOT(func) )
|
||||
+ break;
|
||||
+ printk(XENLOG_DEBUG "PCI phantom %04x:%02x:%02x.%u\n",
|
||||
+ seg, bus, slot, func);
|
||||
+ }
|
||||
+ }
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -657,7 +705,7 @@ void pci_check_disable_device(u16 seg, u
|
||||
u16 cword;
|
||||
|
||||
spin_lock(&pcidevs_lock);
|
||||
- pdev = pci_get_pdev(seg, bus, devfn);
|
||||
+ pdev = pci_get_real_pdev(seg, bus, devfn);
|
||||
if ( pdev )
|
||||
{
|
||||
if ( now < pdev->fault.time ||
|
||||
@@ -674,6 +722,7 @@ void pci_check_disable_device(u16 seg, u
|
||||
|
||||
/* Tell the device to stop DMAing; we can't rely on the guest to
|
||||
* control it for us. */
|
||||
+ devfn = pdev->devfn;
|
||||
cword = pci_conf_read16(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
PCI_COMMAND);
|
||||
pci_conf_write16(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
@@ -731,6 +780,27 @@ struct setup_dom0 {
|
||||
int (*handler)(u8 devfn, struct pci_dev *);
|
||||
};
|
||||
|
||||
+static void setup_one_dom0_device(const struct setup_dom0 *ctxt,
|
||||
+ struct pci_dev *pdev)
|
||||
+{
|
||||
+ u8 devfn = pdev->devfn;
|
||||
+
|
||||
+ do {
|
||||
+ int err = ctxt->handler(devfn, pdev);
|
||||
+
|
||||
+ if ( err )
|
||||
+ {
|
||||
+ printk(XENLOG_ERR "setup %04x:%02x:%02x.%u for d%d failed (%d)\n",
|
||||
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
+ ctxt->d->domain_id, err);
|
||||
+ if ( devfn == pdev->devfn )
|
||||
+ return;
|
||||
+ }
|
||||
+ devfn += pdev->phantom_stride;
|
||||
+ } while ( devfn != pdev->devfn &&
|
||||
+ PCI_SLOT(devfn) == PCI_SLOT(pdev->devfn) );
|
||||
+}
|
||||
+
|
||||
static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg)
|
||||
{
|
||||
struct setup_dom0 *ctxt = arg;
|
||||
@@ -747,7 +817,7 @@ static int __init _setup_dom0_pci_device
|
||||
|
||||
pdev->domain = ctxt->d;
|
||||
list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list);
|
||||
- ctxt->handler(devfn, pdev);
|
||||
+ setup_one_dom0_device(ctxt, pdev);
|
||||
}
|
||||
}
|
||||
|
||||
Index: xen-4.2.2-testing/xen/include/xen/lib.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/lib.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/lib.h
|
||||
@@ -58,6 +58,9 @@ do {
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]) + __must_be_array(x))
|
||||
|
||||
+#define MASK_EXTR(v, m) (((v) & (m)) / ((m) & -(m)))
|
||||
+#define MASK_INSR(v, m) (((v) * ((m) & -(m))) & (m))
|
||||
+
|
||||
#define reserve_bootmem(_p,_l) ((void)0)
|
||||
|
||||
struct domain;
|
||||
Index: xen-4.2.2-testing/xen/include/xen/pci.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/pci.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/pci.h
|
||||
@@ -64,6 +64,8 @@ struct pci_dev {
|
||||
const u8 bus;
|
||||
const u8 devfn;
|
||||
|
||||
+ u8 phantom_stride;
|
||||
+
|
||||
enum pdev_type {
|
||||
DEV_TYPE_PCI_UNKNOWN,
|
||||
DEV_TYPE_PCIe_ENDPOINT,
|
||||
@@ -114,6 +116,7 @@ int pci_remove_device(u16 seg, u8 bus, u
|
||||
int pci_ro_device(int seg, int bus, int devfn);
|
||||
void arch_pci_ro_device(int seg, int bdf);
|
||||
struct pci_dev *pci_get_pdev(int seg, int bus, int devfn);
|
||||
+struct pci_dev *pci_get_real_pdev(int seg, int bus, int devfn);
|
||||
struct pci_dev *pci_get_pdev_by_domain(
|
||||
struct domain *, int seg, int bus, int devfn);
|
||||
void pci_check_disable_device(u16 seg, u8 bus, u8 devfn);
|
@ -1,42 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1357559812 -3600
|
||||
# Node ID b514b7118958327605e33dd387944832bc8d734a
|
||||
# Parent c9a01b396cb4eaedef30e9a6ed615115a9f8bfc5
|
||||
VT-d: relax source qualifier for MSI of phantom functions
|
||||
|
||||
With ordinary requests allowed to come from phantom functions, the
|
||||
remapping tables ought to be set up to allow for MSI triggers to come
|
||||
from other than the "real" device too.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
--- a/xen/drivers/passthrough/vtd/intremap.c
|
||||
+++ b/xen/drivers/passthrough/vtd/intremap.c
|
||||
@@ -438,13 +438,22 @@ static void set_msi_source_id(struct pci
|
||||
devfn = pdev->devfn;
|
||||
switch ( pdev->type )
|
||||
{
|
||||
+ unsigned int sq;
|
||||
+
|
||||
case DEV_TYPE_PCIe_BRIDGE:
|
||||
case DEV_TYPE_PCIe2PCI_BRIDGE:
|
||||
case DEV_TYPE_LEGACY_PCI_BRIDGE:
|
||||
break;
|
||||
|
||||
case DEV_TYPE_PCIe_ENDPOINT:
|
||||
- set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16, PCI_BDF2(bus, devfn));
|
||||
+ switch ( pdev->phantom_stride )
|
||||
+ {
|
||||
+ case 1: sq = SQ_13_IGNORE_3; break;
|
||||
+ case 2: sq = SQ_13_IGNORE_2; break;
|
||||
+ case 4: sq = SQ_13_IGNORE_1; break;
|
||||
+ default: sq = SQ_ALL_16; break;
|
||||
+ }
|
||||
+ set_ire_sid(ire, SVT_VERIFY_SID_SQ, sq, PCI_BDF2(bus, devfn));
|
||||
break;
|
||||
|
||||
case DEV_TYPE_PCI:
|
@ -1,112 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1357559889 -3600
|
||||
# Node ID 23c4bbc0111dd807561b2c62cbc5798220943a0d
|
||||
# Parent b514b7118958327605e33dd387944832bc8d734a
|
||||
IOMMU: add option to specify devices behaving like ones using phantom functions
|
||||
|
||||
At least certain Marvell SATA controllers are known to issue bus master
|
||||
requests with a non-zero function as origin, despite themselves being
|
||||
single function devices.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
Index: xen-4.2.2-testing/docs/misc/xen-command-line.markdown
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/docs/misc/xen-command-line.markdown
|
||||
+++ xen-4.2.2-testing/docs/misc/xen-command-line.markdown
|
||||
@@ -679,6 +679,16 @@ Defaults to booting secondary processors
|
||||
|
||||
Default: `on`
|
||||
|
||||
+### pci-phantom
|
||||
+> `=[<seg>:]<bus>:<device>,<stride>`
|
||||
+
|
||||
+Mark a group of PCI devices as using phantom functions without actually
|
||||
+advertising so, so the IOMMU can create translation contexts for them.
|
||||
+
|
||||
+All numbers specified must be hexadecimal ones.
|
||||
+
|
||||
+This option can be specified more than once (up to 8 times at present).
|
||||
+
|
||||
### ple\_gap
|
||||
> `= <integer>`
|
||||
|
||||
Index: xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/drivers/passthrough/pci.c
|
||||
+++ xen-4.2.2-testing/xen/drivers/passthrough/pci.c
|
||||
@@ -123,6 +123,49 @@ const unsigned long *pci_get_ro_map(u16
|
||||
return pseg ? pseg->ro_map : NULL;
|
||||
}
|
||||
|
||||
+static struct phantom_dev {
|
||||
+ u16 seg;
|
||||
+ u8 bus, slot, stride;
|
||||
+} phantom_devs[8];
|
||||
+static unsigned int nr_phantom_devs;
|
||||
+
|
||||
+static void __init parse_phantom_dev(char *str) {
|
||||
+ const char *s = str;
|
||||
+ struct phantom_dev phantom;
|
||||
+
|
||||
+ if ( !s || !*s || nr_phantom_devs >= ARRAY_SIZE(phantom_devs) )
|
||||
+ return;
|
||||
+
|
||||
+ phantom.seg = simple_strtol(s, &s, 16);
|
||||
+ if ( *s != ':' )
|
||||
+ return;
|
||||
+
|
||||
+ phantom.bus = simple_strtol(s + 1, &s, 16);
|
||||
+ if ( *s == ',' )
|
||||
+ {
|
||||
+ phantom.slot = phantom.bus;
|
||||
+ phantom.bus = phantom.seg;
|
||||
+ phantom.seg = 0;
|
||||
+ }
|
||||
+ else if ( *s == ':' )
|
||||
+ phantom.slot = simple_strtol(s + 1, &s, 16);
|
||||
+ else
|
||||
+ return;
|
||||
+
|
||||
+ if ( *s != ',' )
|
||||
+ return;
|
||||
+ switch ( phantom.stride = simple_strtol(s + 1, &s, 0) )
|
||||
+ {
|
||||
+ case 1: case 2: case 4:
|
||||
+ if ( *s )
|
||||
+ default:
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ phantom_devs[nr_phantom_devs++] = phantom;
|
||||
+}
|
||||
+custom_param("pci-phantom", parse_phantom_dev);
|
||||
+
|
||||
static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 bus, u8 devfn)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
@@ -183,6 +226,20 @@ static struct pci_dev *alloc_pdev(struct
|
||||
if ( PCI_FUNC(devfn) >= pdev->phantom_stride )
|
||||
pdev->phantom_stride = 0;
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for ( i = 0; i < nr_phantom_devs; ++i )
|
||||
+ if ( phantom_devs[i].seg == pseg->nr &&
|
||||
+ phantom_devs[i].bus == bus &&
|
||||
+ phantom_devs[i].slot == PCI_SLOT(devfn) &&
|
||||
+ phantom_devs[i].stride > PCI_FUNC(devfn) )
|
||||
+ {
|
||||
+ pdev->phantom_stride = phantom_devs[i].stride;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
break;
|
||||
|
||||
case DEV_TYPE_PCI:
|
@ -1,99 +0,0 @@
|
||||
fate#313584: pass bios information to XEN HVM guest
|
||||
|
||||
# HG changeset patch
|
||||
# User Ross Philipson <ross.philipson@citrix.com>
|
||||
# Date 1357838188 0
|
||||
# Node ID 07bf59a7ce837bd795e2df2f28166cfe41990d3d
|
||||
# Parent 19fd1237ff0dfa3d97a896d6ed6fbbd33f816a9f
|
||||
HVM xenstore strings and firmware passthrough header
|
||||
|
||||
Add public HVM definitions header for xenstore strings used in
|
||||
HVMLOADER. In addition this header describes the use of the firmware
|
||||
passthrough values set using xenstore.
|
||||
|
||||
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
|
||||
Committed-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
diff -r 19fd1237ff0d -r 07bf59a7ce83 xen/include/public/hvm/hvm_xs_strings.h
|
||||
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
|
||||
+++ b/xen/include/public/hvm/hvm_xs_strings.h Thu Jan 10 17:16:28 2013 +0000
|
||||
@@ -0,0 +1,79 @@
|
||||
+/******************************************************************************
|
||||
+ * hvm/hvm_xs_strings.h
|
||||
+ *
|
||||
+ * HVM xenstore strings used in HVMLOADER.
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
+ * of this software and associated documentation files (the "Software"), to
|
||||
+ * deal in the Software without restriction, including without limitation the
|
||||
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
+ * sell copies of the Software, and to permit persons to whom the Software is
|
||||
+ * furnished to do so, subject to the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be included in
|
||||
+ * all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
+ * DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__
|
||||
+#define __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__
|
||||
+
|
||||
+#define HVM_XS_HVMLOADER "hvmloader"
|
||||
+#define HVM_XS_BIOS "hvmloader/bios"
|
||||
+#define HVM_XS_GENERATION_ID_ADDRESS "hvmloader/generation-id-address"
|
||||
+
|
||||
+/* The following values allow additional ACPI tables to be added to the
|
||||
+ * virtual ACPI BIOS that hvmloader constructs. The values specify the guest
|
||||
+ * physical address and length of a block of ACPI tables to add. The format of
|
||||
+ * the block is simply concatenated raw tables (which specify their own length
|
||||
+ * in the ACPI header).
|
||||
+ */
|
||||
+#define HVM_XS_ACPI_PT_ADDRESS "hvmloader/acpi/address"
|
||||
+#define HVM_XS_ACPI_PT_LENGTH "hvmloader/acpi/length"
|
||||
+
|
||||
+/* Any number of SMBIOS types can be passed through to an HVM guest using
|
||||
+ * the following xenstore values. The values specify the guest physical
|
||||
+ * address and length of a block of SMBIOS structures for hvmloader to use.
|
||||
+ * The block is formatted in the following way:
|
||||
+ *
|
||||
+ * <length><struct><length><struct>...
|
||||
+ *
|
||||
+ * Each length separator is a 32b integer indicating the length of the next
|
||||
+ * SMBIOS structure. For DMTF defined types (0 - 121), the passed in struct
|
||||
+ * will replace the default structure in hvmloader. In addition, any
|
||||
+ * OEM/vendortypes (128 - 255) will all be added.
|
||||
+ */
|
||||
+#define HVM_XS_SMBIOS_PT_ADDRESS "hvmloader/smbios/address"
|
||||
+#define HVM_XS_SMBIOS_PT_LENGTH "hvmloader/smbios/length"
|
||||
+
|
||||
+/* Set to 1 to enable SMBIOS default portable battery (type 22) values. */
|
||||
+#define HVM_XS_SMBIOS_DEFAULT_BATTERY "hvmloader/smbios/default_battery"
|
||||
+
|
||||
+/* The following xenstore values are used to override some of the default
|
||||
+ * string values in the SMBIOS table constructed in hvmloader.
|
||||
+ */
|
||||
+#define HVM_XS_BIOS_STRINGS "bios-strings"
|
||||
+#define HVM_XS_BIOS_VENDOR "bios-strings/bios-vendor"
|
||||
+#define HVM_XS_BIOS_VERSION "bios-strings/bios-version"
|
||||
+#define HVM_XS_SYSTEM_MANUFACTURER "bios-strings/system-manufacturer"
|
||||
+#define HVM_XS_SYSTEM_PRODUCT_NAME "bios-strings/system-product-name"
|
||||
+#define HVM_XS_SYSTEM_VERSION "bios-strings/system-version"
|
||||
+#define HVM_XS_SYSTEM_SERIAL_NUMBER "bios-strings/system-serial-number"
|
||||
+#define HVM_XS_ENCLOSURE_MANUFACTURER "bios-strings/enclosure-manufacturer"
|
||||
+#define HVM_XS_ENCLOSURE_SERIAL_NUMBER "bios-strings/enclosure-serial-number"
|
||||
+#define HVM_XS_BATTERY_MANUFACTURER "bios-strings/battery-manufacturer"
|
||||
+#define HVM_XS_BATTERY_DEVICE_NAME "bios-strings/battery-device-name"
|
||||
+
|
||||
+/* 1 to 99 OEM strings can be set in xenstore using values of the form
|
||||
+ * below. These strings will be loaded into the SMBIOS type 11 structure.
|
||||
+ */
|
||||
+#define HVM_XS_OEM_STRINGS "bios-strings/oem-%02d"
|
||||
+
|
||||
+#endif /* __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__ */
|
@ -1,282 +0,0 @@
|
||||
fate#313584: pass bios information to XEN HVM guest
|
||||
|
||||
# HG changeset patch
|
||||
# User Ross Philipson <ross.philipson@citrix.com>
|
||||
# Date 1357838241 0
|
||||
# Node ID cabf395a6c849cc65e56f1640b18db0c3e0faf5d
|
||||
# Parent 07bf59a7ce837bd795e2df2f28166cfe41990d3d
|
||||
HVM firmware passthrough control tools support
|
||||
|
||||
Xen control tools support for loading the firmware passthrough blocks
|
||||
during domain construction. SMBIOS and ACPI blocks are passed in using
|
||||
the new xc_hvm_build_args structure. Each block is read and loaded
|
||||
into the new domain address space behind the HVMLOADER image. The base
|
||||
address for the two blocks is returned as an out parameter to the
|
||||
caller via the args structure.
|
||||
|
||||
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
|
||||
Committed-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
diff -r 07bf59a7ce83 -r cabf395a6c84 tools/libxc/xc_hvm_build_arm.c
|
||||
--- a/tools/libxc/xc_hvm_build_arm.c Thu Jan 10 17:16:28 2013 +0000
|
||||
+++ b/tools/libxc/xc_hvm_build_arm.c Thu Jan 10 17:17:21 2013 +0000
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <xenguest.h>
|
||||
|
||||
int xc_hvm_build(xc_interface *xch, uint32_t domid,
|
||||
- const struct xc_hvm_build_args *hvm_args)
|
||||
+ struct xc_hvm_build_args *hvm_args)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
diff -r 07bf59a7ce83 -r cabf395a6c84 tools/libxc/xc_hvm_build_x86.c
|
||||
--- a/tools/libxc/xc_hvm_build_x86.c Thu Jan 10 17:16:28 2013 +0000
|
||||
+++ b/tools/libxc/xc_hvm_build_x86.c Thu Jan 10 17:17:21 2013 +0000
|
||||
@@ -49,6 +49,40 @@
|
||||
#define NR_SPECIAL_PAGES 8
|
||||
#define special_pfn(x) (0xff000u - NR_SPECIAL_PAGES + (x))
|
||||
|
||||
+static int modules_init(struct xc_hvm_build_args *args,
|
||||
+ uint64_t vend, struct elf_binary *elf,
|
||||
+ uint64_t *mstart_out, uint64_t *mend_out)
|
||||
+{
|
||||
+#define MODULE_ALIGN 1UL << 7
|
||||
+#define MB_ALIGN 1UL << 20
|
||||
+#define MKALIGN(x, a) (((uint64_t)(x) + (a) - 1) & ~(uint64_t)((a) - 1))
|
||||
+ uint64_t total_len = 0, offset1 = 0;
|
||||
+
|
||||
+ if ( (args->acpi_module.length == 0)&&(args->smbios_module.length == 0) )
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Find the total length for the firmware modules with a reasonable large
|
||||
+ * alignment size to align each the modules.
|
||||
+ */
|
||||
+ total_len = MKALIGN(args->acpi_module.length, MODULE_ALIGN);
|
||||
+ offset1 = total_len;
|
||||
+ total_len += MKALIGN(args->smbios_module.length, MODULE_ALIGN);
|
||||
+
|
||||
+ /* Want to place the modules 1Mb+change behind the loader image. */
|
||||
+ *mstart_out = MKALIGN(elf->pend, MB_ALIGN) + (MB_ALIGN);
|
||||
+ *mend_out = *mstart_out + total_len;
|
||||
+
|
||||
+ if ( *mend_out > vend )
|
||||
+ return -1;
|
||||
+
|
||||
+ if ( args->acpi_module.length != 0 )
|
||||
+ args->acpi_module.guest_addr_out = *mstart_out;
|
||||
+ if ( args->smbios_module.length != 0 )
|
||||
+ args->smbios_module.guest_addr_out = *mstart_out + offset1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void build_hvm_info(void *hvm_info_page, uint64_t mem_size,
|
||||
uint64_t mmio_start, uint64_t mmio_size)
|
||||
{
|
||||
@@ -86,9 +120,8 @@ static void build_hvm_info(void *hvm_inf
|
||||
hvm_info->checksum = -sum;
|
||||
}
|
||||
|
||||
-static int loadelfimage(
|
||||
- xc_interface *xch,
|
||||
- struct elf_binary *elf, uint32_t dom, unsigned long *parray)
|
||||
+static int loadelfimage(xc_interface *xch, struct elf_binary *elf,
|
||||
+ uint32_t dom, unsigned long *parray)
|
||||
{
|
||||
privcmd_mmap_entry_t *entries = NULL;
|
||||
unsigned long pfn_start = elf->pstart >> PAGE_SHIFT;
|
||||
@@ -126,6 +159,66 @@ static int loadelfimage(
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static int loadmodules(xc_interface *xch,
|
||||
+ struct xc_hvm_build_args *args,
|
||||
+ uint64_t mstart, uint64_t mend,
|
||||
+ uint32_t dom, unsigned long *parray)
|
||||
+{
|
||||
+ privcmd_mmap_entry_t *entries = NULL;
|
||||
+ unsigned long pfn_start;
|
||||
+ unsigned long pfn_end;
|
||||
+ size_t pages;
|
||||
+ uint32_t i;
|
||||
+ uint8_t *dest;
|
||||
+ int rc = -1;
|
||||
+
|
||||
+ if ( (mstart == 0)||(mend == 0) )
|
||||
+ return 0;
|
||||
+
|
||||
+ pfn_start = (unsigned long)(mstart >> PAGE_SHIFT);
|
||||
+ pfn_end = (unsigned long)((mend + PAGE_SIZE - 1) >> PAGE_SHIFT);
|
||||
+ pages = pfn_end - pfn_start;
|
||||
+
|
||||
+ /* Map address space for module list. */
|
||||
+ entries = calloc(pages, sizeof(privcmd_mmap_entry_t));
|
||||
+ if ( entries == NULL )
|
||||
+ goto error_out;
|
||||
+
|
||||
+ for ( i = 0; i < pages; i++ )
|
||||
+ entries[i].mfn = parray[(mstart >> PAGE_SHIFT) + i];
|
||||
+
|
||||
+ dest = xc_map_foreign_ranges(
|
||||
+ xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT,
|
||||
+ entries, pages);
|
||||
+ if ( dest == NULL )
|
||||
+ goto error_out;
|
||||
+
|
||||
+ /* Zero the range so padding is clear between modules */
|
||||
+ memset(dest, 0, pages << PAGE_SHIFT);
|
||||
+
|
||||
+ /* Load modules into range */
|
||||
+ if ( args->acpi_module.length != 0 )
|
||||
+ {
|
||||
+ memcpy(dest,
|
||||
+ args->acpi_module.data,
|
||||
+ args->acpi_module.length);
|
||||
+ }
|
||||
+ if ( args->smbios_module.length != 0 )
|
||||
+ {
|
||||
+ memcpy(dest + (args->smbios_module.guest_addr_out - mstart),
|
||||
+ args->smbios_module.data,
|
||||
+ args->smbios_module.length);
|
||||
+ }
|
||||
+
|
||||
+ munmap(dest, pages << PAGE_SHIFT);
|
||||
+ rc = 0;
|
||||
+
|
||||
+ error_out:
|
||||
+ free(entries);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Check whether there exists mmio hole in the specified memory range.
|
||||
* Returns 1 if exists, else returns 0.
|
||||
@@ -140,7 +233,7 @@ static int check_mmio_hole(uint64_t star
|
||||
}
|
||||
|
||||
static int setup_guest(xc_interface *xch,
|
||||
- uint32_t dom, const struct xc_hvm_build_args *args,
|
||||
+ uint32_t dom, struct xc_hvm_build_args *args,
|
||||
char *image, unsigned long image_size)
|
||||
{
|
||||
xen_pfn_t *page_array = NULL;
|
||||
@@ -153,6 +246,7 @@ static int setup_guest(xc_interface *xch
|
||||
uint32_t *ident_pt;
|
||||
struct elf_binary elf;
|
||||
uint64_t v_start, v_end;
|
||||
+ uint64_t m_start = 0, m_end = 0;
|
||||
int rc;
|
||||
xen_capabilities_info_t caps;
|
||||
unsigned long stat_normal_pages = 0, stat_2mb_pages = 0,
|
||||
@@ -178,11 +272,19 @@ static int setup_guest(xc_interface *xch
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
+ if ( modules_init(args, v_end, &elf, &m_start, &m_end) != 0 )
|
||||
+ {
|
||||
+ ERROR("Insufficient space to load modules.");
|
||||
+ goto error_out;
|
||||
+ }
|
||||
+
|
||||
IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
|
||||
" Loader: %016"PRIx64"->%016"PRIx64"\n"
|
||||
+ " Modules: %016"PRIx64"->%016"PRIx64"\n"
|
||||
" TOTAL: %016"PRIx64"->%016"PRIx64"\n"
|
||||
" ENTRY ADDRESS: %016"PRIx64"\n",
|
||||
elf.pstart, elf.pend,
|
||||
+ m_start, m_end,
|
||||
v_start, v_end,
|
||||
elf_uval(&elf, elf.ehdr, e_entry));
|
||||
|
||||
@@ -337,6 +439,9 @@ static int setup_guest(xc_interface *xch
|
||||
if ( loadelfimage(xch, &elf, dom, page_array) != 0 )
|
||||
goto error_out;
|
||||
|
||||
+ if ( loadmodules(xch, args, m_start, m_end, dom, page_array) != 0 )
|
||||
+ goto error_out;
|
||||
+
|
||||
if ( (hvm_info_page = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||
HVM_INFO_PFN)) == NULL )
|
||||
@@ -413,7 +518,7 @@ static int setup_guest(xc_interface *xch
|
||||
* Create a domain for a virtualized Linux, using files/filenames.
|
||||
*/
|
||||
int xc_hvm_build(xc_interface *xch, uint32_t domid,
|
||||
- const struct xc_hvm_build_args *hvm_args)
|
||||
+ struct xc_hvm_build_args *hvm_args)
|
||||
{
|
||||
struct xc_hvm_build_args args = *hvm_args;
|
||||
void *image;
|
||||
@@ -441,6 +546,15 @@ int xc_hvm_build(xc_interface *xch, uint
|
||||
|
||||
sts = setup_guest(xch, domid, &args, image, image_size);
|
||||
|
||||
+ if (!sts)
|
||||
+ {
|
||||
+ /* Return module load addresses to caller */
|
||||
+ hvm_args->acpi_module.guest_addr_out =
|
||||
+ args.acpi_module.guest_addr_out;
|
||||
+ hvm_args->smbios_module.guest_addr_out =
|
||||
+ args.smbios_module.guest_addr_out;
|
||||
+ }
|
||||
+
|
||||
free(image);
|
||||
|
||||
return sts;
|
||||
@@ -461,6 +575,7 @@ int xc_hvm_build_target_mem(xc_interface
|
||||
{
|
||||
struct xc_hvm_build_args args = {};
|
||||
|
||||
+ memset(&args, 0, sizeof(struct xc_hvm_build_args));
|
||||
args.mem_size = (uint64_t)memsize << 20;
|
||||
args.mem_target = (uint64_t)target << 20;
|
||||
args.image_file_name = image_name;
|
||||
diff -r 07bf59a7ce83 -r cabf395a6c84 tools/libxc/xenguest.h
|
||||
--- a/tools/libxc/xenguest.h Thu Jan 10 17:16:28 2013 +0000
|
||||
+++ b/tools/libxc/xenguest.h Thu Jan 10 17:17:21 2013 +0000
|
||||
@@ -211,11 +211,23 @@ int xc_linux_build_mem(xc_interface *xch
|
||||
unsigned int console_evtchn,
|
||||
unsigned long *console_mfn);
|
||||
|
||||
+struct xc_hvm_firmware_module {
|
||||
+ uint8_t *data;
|
||||
+ uint32_t length;
|
||||
+ uint64_t guest_addr_out;
|
||||
+};
|
||||
+
|
||||
struct xc_hvm_build_args {
|
||||
uint64_t mem_size; /* Memory size in bytes. */
|
||||
uint64_t mem_target; /* Memory target in bytes. */
|
||||
uint64_t mmio_size; /* Size of the MMIO hole in bytes. */
|
||||
const char *image_file_name; /* File name of the image to load. */
|
||||
+
|
||||
+ /* Extra ACPI tables passed to HVMLOADER */
|
||||
+ struct xc_hvm_firmware_module acpi_module;
|
||||
+
|
||||
+ /* Extra SMBIOS structures passed to HVMLOADER */
|
||||
+ struct xc_hvm_firmware_module smbios_module;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -228,7 +240,7 @@ struct xc_hvm_build_args {
|
||||
* are optional.
|
||||
*/
|
||||
int xc_hvm_build(xc_interface *xch, uint32_t domid,
|
||||
- const struct xc_hvm_build_args *hvm_args);
|
||||
+ struct xc_hvm_build_args *hvm_args);
|
||||
|
||||
int xc_hvm_build_target_mem(xc_interface *xch,
|
||||
uint32_t domid,
|
||||
diff -r 07bf59a7ce83 -r cabf395a6c84 tools/libxc/xg_private.c
|
||||
--- a/tools/libxc/xg_private.c Thu Jan 10 17:16:28 2013 +0000
|
||||
+++ b/tools/libxc/xg_private.c Thu Jan 10 17:17:21 2013 +0000
|
||||
@@ -192,7 +192,7 @@ unsigned long csum_page(void *page)
|
||||
__attribute__((weak))
|
||||
int xc_hvm_build(xc_interface *xch,
|
||||
uint32_t domid,
|
||||
- const struct xc_hvm_build_args *hvm_args)
|
||||
+ struct xc_hvm_build_args *hvm_args)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
@ -1,645 +0,0 @@
|
||||
fate#313584: pass bios information to XEN HVM guest
|
||||
|
||||
# HG changeset patch
|
||||
# User Ross Philipson <ross.philipson@citrix.com>
|
||||
# Date 1357838290 0
|
||||
# Node ID a7ce196f40444fafbe8f13b2d80e4885d4321806
|
||||
# Parent cabf395a6c849cc65e56f1640b18db0c3e0faf5d
|
||||
HVM firmware passthrough SMBIOS processing
|
||||
|
||||
Passthrough support for the SMBIOS structures including three new DMTF
|
||||
defined types and support for OEM defined tables. Passed in SMBIOS
|
||||
types override the default internal values. Default values can be
|
||||
enabled for the new type 22 portable battery using a xenstore
|
||||
flag. All other new DMTF defined and OEM structures will only be added
|
||||
to the SMBIOS table if passthrough values are present.
|
||||
|
||||
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
|
||||
Committed-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
diff -r cabf395a6c84 -r a7ce196f4044 tools/firmware/hvmloader/smbios.c
|
||||
--- a/tools/firmware/hvmloader/smbios.c Thu Jan 10 17:17:21 2013 +0000
|
||||
+++ b/tools/firmware/hvmloader/smbios.c Thu Jan 10 17:18:10 2013 +0000
|
||||
@@ -26,16 +26,38 @@
|
||||
#include "smbios_types.h"
|
||||
#include "util.h"
|
||||
#include "hypercall.h"
|
||||
+#include <xen/hvm/hvm_xs_strings.h>
|
||||
|
||||
+/* SBMIOS handle base values */
|
||||
+#define SMBIOS_HANDLE_TYPE0 0x0000
|
||||
+#define SMBIOS_HANDLE_TYPE1 0x0100
|
||||
+#define SMBIOS_HANDLE_TYPE2 0x0200
|
||||
+#define SMBIOS_HANDLE_TYPE3 0x0300
|
||||
+#define SMBIOS_HANDLE_TYPE4 0x0400
|
||||
+#define SMBIOS_HANDLE_TYPE11 0x0B00
|
||||
+#define SMBIOS_HANDLE_TYPE16 0x1000
|
||||
+#define SMBIOS_HANDLE_TYPE17 0x1100
|
||||
+#define SMBIOS_HANDLE_TYPE19 0x1300
|
||||
+#define SMBIOS_HANDLE_TYPE20 0x1400
|
||||
+#define SMBIOS_HANDLE_TYPE22 0x1600
|
||||
+#define SMBIOS_HANDLE_TYPE32 0x2000
|
||||
+#define SMBIOS_HANDLE_TYPE39 0x2700
|
||||
+#define SMBIOS_HANDLE_TYPE127 0x7f00
|
||||
+
|
||||
+static void
|
||||
+smbios_pt_init(void);
|
||||
+static void*
|
||||
+get_smbios_pt_struct(uint8_t type, uint32_t *length_out);
|
||||
+static void
|
||||
+get_cpu_manufacturer(char *buf, int len);
|
||||
static int
|
||||
write_smbios_tables(void *ep, void *start,
|
||||
uint32_t vcpus, uint64_t memsize,
|
||||
uint8_t uuid[16], char *xen_version,
|
||||
uint32_t xen_major_version, uint32_t xen_minor_version,
|
||||
unsigned *nr_structs, unsigned *max_struct_size);
|
||||
-
|
||||
-static void
|
||||
-get_cpu_manufacturer(char *buf, int len);
|
||||
+static uint64_t
|
||||
+get_memsize(void);
|
||||
static void
|
||||
smbios_entry_point_init(void *start,
|
||||
uint16_t max_structure_size,
|
||||
@@ -49,6 +71,8 @@ static void *
|
||||
smbios_type_1_init(void *start, const char *xen_version,
|
||||
uint8_t uuid[16]);
|
||||
static void *
|
||||
+smbios_type_2_init(void *start);
|
||||
+static void *
|
||||
smbios_type_3_init(void *start);
|
||||
static void *
|
||||
smbios_type_4_init(void *start, unsigned int cpu_number,
|
||||
@@ -64,10 +88,73 @@ smbios_type_19_init(void *start, uint32_
|
||||
static void *
|
||||
smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance);
|
||||
static void *
|
||||
+smbios_type_22_init(void *start);
|
||||
+static void *
|
||||
smbios_type_32_init(void *start);
|
||||
static void *
|
||||
+smbios_type_39_init(void *start);
|
||||
+static void *
|
||||
+smbios_type_vendor_oem_init(void *start);
|
||||
+static void *
|
||||
smbios_type_127_init(void *start);
|
||||
|
||||
+static uint32_t *smbios_pt_addr = NULL;
|
||||
+static uint32_t smbios_pt_length = 0;
|
||||
+
|
||||
+static void
|
||||
+smbios_pt_init(void)
|
||||
+{
|
||||
+ const char *s;
|
||||
+
|
||||
+ s = xenstore_read(HVM_XS_SMBIOS_PT_ADDRESS, NULL);
|
||||
+ if ( s == NULL )
|
||||
+ goto reset;
|
||||
+
|
||||
+ smbios_pt_addr = (uint32_t*)(uint32_t)strtoll(s, NULL, 0);
|
||||
+ if ( smbios_pt_addr == NULL )
|
||||
+ goto reset;
|
||||
+
|
||||
+ s = xenstore_read(HVM_XS_SMBIOS_PT_LENGTH, NULL);
|
||||
+ if ( s == NULL )
|
||||
+ goto reset;
|
||||
+
|
||||
+ smbios_pt_length = (uint32_t)strtoll(s, NULL, 0);
|
||||
+ if ( smbios_pt_length == 0 )
|
||||
+ goto reset;
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+reset:
|
||||
+ smbios_pt_addr = NULL;
|
||||
+ smbios_pt_length = 0;
|
||||
+}
|
||||
+
|
||||
+static void*
|
||||
+get_smbios_pt_struct(uint8_t type, uint32_t *length_out)
|
||||
+{
|
||||
+ uint32_t *sep = smbios_pt_addr;
|
||||
+ uint32_t total = 0;
|
||||
+ uint8_t *ptr;
|
||||
+
|
||||
+ if ( sep == NULL )
|
||||
+ return NULL;
|
||||
+
|
||||
+ while ( total < smbios_pt_length )
|
||||
+ {
|
||||
+ ptr = (uint8_t*)(sep + 1);
|
||||
+ if ( ptr[0] == type )
|
||||
+ {
|
||||
+ *length_out = *sep;
|
||||
+ return ptr;
|
||||
+ }
|
||||
+
|
||||
+ total += (*sep + sizeof(uint32_t));
|
||||
+ sep = (uint32_t*)(ptr + *sep);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
get_cpu_manufacturer(char *buf, int len)
|
||||
{
|
||||
@@ -97,6 +184,8 @@ write_smbios_tables(void *ep, void *star
|
||||
char cpu_manufacturer[15];
|
||||
int i, nr_mem_devs;
|
||||
|
||||
+ smbios_pt_init();
|
||||
+
|
||||
get_cpu_manufacturer(cpu_manufacturer, 15);
|
||||
|
||||
p = (char *)start;
|
||||
@@ -112,6 +201,7 @@ write_smbios_tables(void *ep, void *star
|
||||
do_struct(smbios_type_0_init(p, xen_version, xen_major_version,
|
||||
xen_minor_version));
|
||||
do_struct(smbios_type_1_init(p, xen_version, uuid));
|
||||
+ do_struct(smbios_type_2_init(p));
|
||||
do_struct(smbios_type_3_init(p));
|
||||
for ( cpu_num = 1; cpu_num <= vcpus; cpu_num++ )
|
||||
do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer));
|
||||
@@ -130,7 +220,10 @@ write_smbios_tables(void *ep, void *star
|
||||
do_struct(smbios_type_20_init(p, dev_memsize, i));
|
||||
}
|
||||
|
||||
+ do_struct(smbios_type_22_init(p));
|
||||
do_struct(smbios_type_32_init(p));
|
||||
+ do_struct(smbios_type_39_init(p));
|
||||
+ do_struct(smbios_type_vendor_oem_init(p));
|
||||
do_struct(smbios_type_127_init(p));
|
||||
|
||||
#undef do_struct
|
||||
@@ -289,12 +382,22 @@ smbios_type_0_init(void *start, const ch
|
||||
struct smbios_type_0 *p = (struct smbios_type_0 *)start;
|
||||
static const char *smbios_release_date = __SMBIOS_DATE__;
|
||||
const char *s;
|
||||
+ void *pts;
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ pts = get_smbios_pt_struct(0, &length);
|
||||
+ if ( (pts != NULL)&&(length > 0) )
|
||||
+ {
|
||||
+ memcpy(start, pts, length);
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE0;
|
||||
+ return (start + length);
|
||||
+ }
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
p->header.type = 0;
|
||||
p->header.length = sizeof(struct smbios_type_0);
|
||||
- p->header.handle = 0;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE0;
|
||||
|
||||
p->vendor_str = 1;
|
||||
p->version_str = 2;
|
||||
@@ -315,11 +418,11 @@ smbios_type_0_init(void *start, const ch
|
||||
p->embedded_controller_minor = 0xff;
|
||||
|
||||
start += sizeof(struct smbios_type_0);
|
||||
- s = xenstore_read("bios-strings/bios-vendor", "Xen");
|
||||
+ s = xenstore_read(HVM_XS_BIOS_VENDOR, "Xen");
|
||||
strcpy((char *)start, s);
|
||||
start += strlen(s) + 1;
|
||||
|
||||
- s = xenstore_read("bios-strings/bios-version", xen_version);
|
||||
+ s = xenstore_read(HVM_XS_BIOS_VERSION, xen_version);
|
||||
strcpy((char *)start, s);
|
||||
start += strlen(s) + 1;
|
||||
|
||||
@@ -338,12 +441,22 @@ smbios_type_1_init(void *start, const ch
|
||||
char uuid_str[37];
|
||||
struct smbios_type_1 *p = (struct smbios_type_1 *)start;
|
||||
const char *s;
|
||||
+ void *pts;
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ pts = get_smbios_pt_struct(1, &length);
|
||||
+ if ( (pts != NULL)&&(length > 0) )
|
||||
+ {
|
||||
+ memcpy(start, pts, length);
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE1;
|
||||
+ return (start + length);
|
||||
+ }
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
p->header.type = 1;
|
||||
p->header.length = sizeof(struct smbios_type_1);
|
||||
- p->header.handle = 0x100;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE1;
|
||||
|
||||
p->manufacturer_str = 1;
|
||||
p->product_name_str = 2;
|
||||
@@ -358,20 +471,20 @@ smbios_type_1_init(void *start, const ch
|
||||
|
||||
start += sizeof(struct smbios_type_1);
|
||||
|
||||
- s = xenstore_read("bios-strings/system-manufacturer", "Xen");
|
||||
+ s = xenstore_read(HVM_XS_SYSTEM_MANUFACTURER, "Xen");
|
||||
strcpy((char *)start, s);
|
||||
start += strlen(s) + 1;
|
||||
|
||||
- s = xenstore_read("bios-strings/system-product-name", "HVM domU");
|
||||
+ s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU");
|
||||
strcpy((char *)start, s);
|
||||
start += strlen(s) + 1;
|
||||
|
||||
- s = xenstore_read("bios-strings/system-version", xen_version);
|
||||
+ s = xenstore_read(HVM_XS_SYSTEM_VERSION, xen_version);
|
||||
strcpy((char *)start, s);
|
||||
start += strlen(s) + 1;
|
||||
|
||||
uuid_to_string(uuid_str, uuid);
|
||||
- s = xenstore_read("bios-strings/system-serial-number", uuid_str);
|
||||
+ s = xenstore_read(HVM_XS_SYSTEM_SERIAL_NUMBER, uuid_str);
|
||||
strcpy((char *)start, s);
|
||||
start += strlen(s) + 1;
|
||||
|
||||
@@ -380,17 +493,58 @@ smbios_type_1_init(void *start, const ch
|
||||
return start+1;
|
||||
}
|
||||
|
||||
+/* Type 2 -- System Board */
|
||||
+static void *
|
||||
+smbios_type_2_init(void *start)
|
||||
+{
|
||||
+ struct smbios_type_2 *p = (struct smbios_type_2 *)start;
|
||||
+ uint8_t *ptr;
|
||||
+ void *pts;
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ pts = get_smbios_pt_struct(2, &length);
|
||||
+ if ( (pts != NULL)&&(length > 0) )
|
||||
+ {
|
||||
+ memcpy(start, pts, length);
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE2;
|
||||
+
|
||||
+ /* Set current chassis handle if present */
|
||||
+ if ( p->header.length > 13 )
|
||||
+ {
|
||||
+ ptr = ((uint8_t*)start) + 11;
|
||||
+ if ( *((uint16_t*)ptr) != 0 )
|
||||
+ *((uint16_t*)ptr) = SMBIOS_HANDLE_TYPE3;
|
||||
+ }
|
||||
+
|
||||
+ return (start + length);
|
||||
+ }
|
||||
+
|
||||
+ /* Only present when passed in */
|
||||
+ return start;
|
||||
+}
|
||||
+
|
||||
/* Type 3 -- System Enclosure */
|
||||
static void *
|
||||
smbios_type_3_init(void *start)
|
||||
{
|
||||
struct smbios_type_3 *p = (struct smbios_type_3 *)start;
|
||||
+ const char *s;
|
||||
+ void *pts;
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ pts = get_smbios_pt_struct(3, &length);
|
||||
+ if ( (pts != NULL)&&(length > 0) )
|
||||
+ {
|
||||
+ memcpy(start, pts, length);
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE3;
|
||||
+ return (start + length);
|
||||
+ }
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
p->header.type = 3;
|
||||
p->header.length = sizeof(struct smbios_type_3);
|
||||
- p->header.handle = 0x300;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE3;
|
||||
|
||||
p->manufacturer_str = 1;
|
||||
p->type = 0x01; /* other */
|
||||
@@ -404,8 +558,19 @@ smbios_type_3_init(void *start)
|
||||
|
||||
start += sizeof(struct smbios_type_3);
|
||||
|
||||
- strcpy((char *)start, "Xen");
|
||||
- start += strlen("Xen") + 1;
|
||||
+ s = xenstore_read(HVM_XS_ENCLOSURE_MANUFACTURER, "Xen");
|
||||
+ strcpy((char *)start, s);
|
||||
+ start += strlen(s) + 1;
|
||||
+
|
||||
+ /* No internal defaults for this if the value is not set */
|
||||
+ s = xenstore_read(HVM_XS_ENCLOSURE_SERIAL_NUMBER, NULL);
|
||||
+ if ( (s != NULL)&&(*s != '\0') )
|
||||
+ {
|
||||
+ strcpy((char *)start, s);
|
||||
+ start += strlen(s) + 1;
|
||||
+ p->serial_number_str = 2;
|
||||
+ }
|
||||
+
|
||||
*((uint8_t *)start) = 0;
|
||||
return start+1;
|
||||
}
|
||||
@@ -423,7 +588,7 @@ smbios_type_4_init(
|
||||
|
||||
p->header.type = 4;
|
||||
p->header.length = sizeof(struct smbios_type_4);
|
||||
- p->header.handle = 0x400 + cpu_number;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE4 + cpu_number;
|
||||
|
||||
p->socket_designation_str = 1;
|
||||
p->processor_type = 0x03; /* CPU */
|
||||
@@ -465,13 +630,23 @@ static void *
|
||||
smbios_type_11_init(void *start)
|
||||
{
|
||||
struct smbios_type_11 *p = (struct smbios_type_11 *)start;
|
||||
- char path[20] = "bios-strings/oem-XX";
|
||||
+ char path[20];
|
||||
const char *s;
|
||||
int i;
|
||||
+ void *pts;
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ pts = get_smbios_pt_struct(11, &length);
|
||||
+ if ( (pts != NULL)&&(length > 0) )
|
||||
+ {
|
||||
+ memcpy(start, pts, length);
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE11;
|
||||
+ return (start + length);
|
||||
+ }
|
||||
|
||||
p->header.type = 11;
|
||||
p->header.length = sizeof(struct smbios_type_11);
|
||||
- p->header.handle = 0xB00;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE11;
|
||||
|
||||
p->count = 0;
|
||||
|
||||
@@ -480,8 +655,7 @@ smbios_type_11_init(void *start)
|
||||
/* Pull out as many oem-* strings we find in xenstore */
|
||||
for ( i = 1; i < 100; i++ )
|
||||
{
|
||||
- path[(sizeof path) - 3] = '0' + ((i < 10) ? i : i / 10);
|
||||
- path[(sizeof path) - 2] = (i < 10) ? '\0' : '0' + (i % 10);
|
||||
+ snprintf(path, sizeof(path), HVM_XS_OEM_STRINGS, i);
|
||||
if ( ((s = xenstore_read(path, NULL)) == NULL) || (*s == '\0') )
|
||||
break;
|
||||
strcpy((char *)start, s);
|
||||
@@ -510,7 +684,7 @@ smbios_type_16_init(void *start, uint32_
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
p->header.type = 16;
|
||||
- p->header.handle = 0x1000;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE16;
|
||||
p->header.length = sizeof(struct smbios_type_16);
|
||||
|
||||
p->location = 0x01; /* other */
|
||||
@@ -536,7 +710,7 @@ smbios_type_17_init(void *start, uint32_
|
||||
|
||||
p->header.type = 17;
|
||||
p->header.length = sizeof(struct smbios_type_17);
|
||||
- p->header.handle = 0x1100 + instance;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE17 + instance;
|
||||
|
||||
p->physical_memory_array_handle = 0x1000;
|
||||
p->total_width = 64;
|
||||
@@ -571,7 +745,7 @@ smbios_type_19_init(void *start, uint32_
|
||||
|
||||
p->header.type = 19;
|
||||
p->header.length = sizeof(struct smbios_type_19);
|
||||
- p->header.handle = 0x1300 + instance;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE19 + instance;
|
||||
|
||||
p->starting_address = instance << 24;
|
||||
p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
|
||||
@@ -593,7 +767,7 @@ smbios_type_20_init(void *start, uint32_
|
||||
|
||||
p->header.type = 20;
|
||||
p->header.length = sizeof(struct smbios_type_20);
|
||||
- p->header.handle = 0x1400 + instance;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE20 + instance;
|
||||
|
||||
p->starting_address = instance << 24;
|
||||
p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
|
||||
@@ -609,6 +783,71 @@ smbios_type_20_init(void *start, uint32_
|
||||
return start+2;
|
||||
}
|
||||
|
||||
+/* Type 22 -- Portable Battery */
|
||||
+static void *
|
||||
+smbios_type_22_init(void *start)
|
||||
+{
|
||||
+ struct smbios_type_22 *p = (struct smbios_type_22 *)start;
|
||||
+ static const char *smbios_release_date = __SMBIOS_DATE__;
|
||||
+ const char *s;
|
||||
+ void *pts;
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ pts = get_smbios_pt_struct(22, &length);
|
||||
+ if ( (pts != NULL)&&(length > 0) )
|
||||
+ {
|
||||
+ memcpy(start, pts, length);
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE22;
|
||||
+ return (start + length);
|
||||
+ }
|
||||
+
|
||||
+ s = xenstore_read(HVM_XS_SMBIOS_DEFAULT_BATTERY, "0");
|
||||
+ if ( strncmp(s, "1", 1) != 0 )
|
||||
+ return start;
|
||||
+
|
||||
+ memset(p, 0, sizeof(*p));
|
||||
+
|
||||
+ p->header.type = 22;
|
||||
+ p->header.length = sizeof(struct smbios_type_22);
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE22;
|
||||
+
|
||||
+ p->location_str = 1;
|
||||
+ p->manufacturer_str = 2;
|
||||
+ p->manufacturer_date_str = 3;
|
||||
+ p->serial_number_str = 0;
|
||||
+ p->device_name_str = 4;
|
||||
+ p->device_chemistry = 0x2; /* unknown */
|
||||
+ p->device_capacity = 0; /* unknown */
|
||||
+ p->device_voltage = 0; /* unknown */
|
||||
+ p->sbds_version_number = 0;
|
||||
+ p->max_error = 0xff; /* unknown */
|
||||
+ p->sbds_serial_number = 0;
|
||||
+ p->sbds_manufacturer_date = 0;
|
||||
+ p->sbds_device_chemistry = 0;
|
||||
+ p->design_capacity_multiplier = 0;
|
||||
+ p->oem_specific = 0;
|
||||
+
|
||||
+ start += sizeof(struct smbios_type_22);
|
||||
+
|
||||
+ strcpy((char *)start, "Primary");
|
||||
+ start += strlen("Primary") + 1;
|
||||
+
|
||||
+ s = xenstore_read(HVM_XS_BATTERY_MANUFACTURER, "Xen");
|
||||
+ strcpy((char *)start, s);
|
||||
+ start += strlen(s) + 1;
|
||||
+
|
||||
+ strcpy((char *)start, smbios_release_date);
|
||||
+ start += strlen(smbios_release_date) + 1;
|
||||
+
|
||||
+ s = xenstore_read(HVM_XS_BATTERY_DEVICE_NAME, "XEN-VBAT");
|
||||
+ strcpy((char *)start, s);
|
||||
+ start += strlen(s) + 1;
|
||||
+
|
||||
+ *((uint8_t *)start) = 0;
|
||||
+
|
||||
+ return start+1;
|
||||
+}
|
||||
+
|
||||
/* Type 32 -- System Boot Information */
|
||||
static void *
|
||||
smbios_type_32_init(void *start)
|
||||
@@ -619,7 +858,7 @@ smbios_type_32_init(void *start)
|
||||
|
||||
p->header.type = 32;
|
||||
p->header.length = sizeof(struct smbios_type_32);
|
||||
- p->header.handle = 0x2000;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE32;
|
||||
memset(p->reserved, 0, 6);
|
||||
p->boot_status = 0; /* no errors detected */
|
||||
|
||||
@@ -628,6 +867,58 @@ smbios_type_32_init(void *start)
|
||||
return start+2;
|
||||
}
|
||||
|
||||
+/* Type 39 -- Power Supply */
|
||||
+static void *
|
||||
+smbios_type_39_init(void *start)
|
||||
+{
|
||||
+ struct smbios_type_39 *p = (struct smbios_type_39 *)start;
|
||||
+ void *pts;
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ pts = get_smbios_pt_struct(39, &length);
|
||||
+ if ( (pts != NULL)&&(length > 0) )
|
||||
+ {
|
||||
+ memcpy(start, pts, length);
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE39;
|
||||
+ return (start + length);
|
||||
+ }
|
||||
+
|
||||
+ /* Only present when passed in */
|
||||
+ return start;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+smbios_type_vendor_oem_init(void *start)
|
||||
+{
|
||||
+ uint32_t *sep = smbios_pt_addr;
|
||||
+ uint32_t total = 0;
|
||||
+ uint8_t *ptr;
|
||||
+
|
||||
+ if ( sep == NULL )
|
||||
+ return start;
|
||||
+
|
||||
+ while ( total < smbios_pt_length )
|
||||
+ {
|
||||
+ ptr = (uint8_t*)(sep + 1);
|
||||
+ if ( ptr[0] >= 128 )
|
||||
+ {
|
||||
+ /* Vendor/OEM table, copy it in. Note the handle values cannot
|
||||
+ * be changed since it is unknown what is in each of these tables
|
||||
+ * but they could contain handle references to other tables. This
|
||||
+ * means a slight risk of collision with the tables above but that
|
||||
+ * would have to be dealt with on a case by case basis.
|
||||
+ */
|
||||
+ memcpy(start, ptr, *sep);
|
||||
+ start += *sep;
|
||||
+ }
|
||||
+
|
||||
+ total += (*sep + sizeof(uint32_t));
|
||||
+ sep = (uint32_t*)(ptr + *sep);
|
||||
+ }
|
||||
+
|
||||
+ return start;
|
||||
+}
|
||||
+
|
||||
/* Type 127 -- End of Table */
|
||||
static void *
|
||||
smbios_type_127_init(void *start)
|
||||
@@ -638,7 +929,7 @@ smbios_type_127_init(void *start)
|
||||
|
||||
p->header.type = 127;
|
||||
p->header.length = sizeof(struct smbios_type_127);
|
||||
- p->header.handle = 0x7f00;
|
||||
+ p->header.handle = SMBIOS_HANDLE_TYPE127;
|
||||
|
||||
start += sizeof(struct smbios_type_127);
|
||||
*((uint16_t *)start) = 0;
|
||||
diff -r cabf395a6c84 -r a7ce196f4044 tools/firmware/hvmloader/smbios_types.h
|
||||
--- a/tools/firmware/hvmloader/smbios_types.h Thu Jan 10 17:17:21 2013 +0000
|
||||
+++ b/tools/firmware/hvmloader/smbios_types.h Thu Jan 10 17:18:10 2013 +0000
|
||||
@@ -84,6 +84,15 @@ struct smbios_type_1 {
|
||||
uint8_t family_str;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
+/* SMBIOS type 2 - Base Board Information */
|
||||
+struct smbios_type_2 {
|
||||
+ struct smbios_structure_header header;
|
||||
+ uint8_t manufacturer_str;
|
||||
+ uint8_t product_name_str;
|
||||
+ uint8_t version_str;
|
||||
+ uint8_t serial_number_str;
|
||||
+} __attribute__ ((packed));
|
||||
+
|
||||
/* SMBIOS type 3 - System Enclosure */
|
||||
struct smbios_type_3 {
|
||||
struct smbios_structure_header header;
|
||||
@@ -173,6 +182,26 @@ struct smbios_type_20 {
|
||||
uint8_t interleaved_data_depth;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
+/* SMBIOS type 22 - Portable battery */
|
||||
+struct smbios_type_22 {
|
||||
+ struct smbios_structure_header header;
|
||||
+ uint8_t location_str;
|
||||
+ uint8_t manufacturer_str;
|
||||
+ uint8_t manufacturer_date_str;
|
||||
+ uint8_t serial_number_str;
|
||||
+ uint8_t device_name_str;
|
||||
+ uint8_t device_chemistry;
|
||||
+ uint16_t device_capacity;
|
||||
+ uint16_t device_voltage;
|
||||
+ uint8_t sbds_version_number;
|
||||
+ uint8_t max_error;
|
||||
+ uint16_t sbds_serial_number;
|
||||
+ uint16_t sbds_manufacturer_date;
|
||||
+ uint8_t sbds_device_chemistry;
|
||||
+ uint8_t design_capacity_multiplier;
|
||||
+ uint32_t oem_specific;
|
||||
+} __attribute__ ((packed));
|
||||
+
|
||||
/* SMBIOS type 32 - System Boot Information */
|
||||
struct smbios_type_32 {
|
||||
struct smbios_structure_header header;
|
||||
@@ -180,6 +209,24 @@ struct smbios_type_32 {
|
||||
uint8_t boot_status;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
+/* SMBIOS type 39 - Power Supply */
|
||||
+struct smbios_type_39 {
|
||||
+ struct smbios_structure_header header;
|
||||
+ uint8_t power_unit_group;
|
||||
+ uint8_t location_str;
|
||||
+ uint8_t device_name_str;
|
||||
+ uint8_t manufacturer_str;
|
||||
+ uint8_t serial_number_str;
|
||||
+ uint8_t asset_tag_number_str;
|
||||
+ uint8_t model_part_number_str;
|
||||
+ uint8_t revision_level_str;
|
||||
+ uint16_t max_capacity;
|
||||
+ uint16_t characteristics;
|
||||
+ uint16_t input_voltage_probe_handle;
|
||||
+ uint16_t cooling_device_handle;
|
||||
+ uint16_t input_current_probe_handle;
|
||||
+} __attribute__ ((packed));
|
||||
+
|
||||
/* SMBIOS type 127 -- End-of-table */
|
||||
struct smbios_type_127 {
|
||||
struct smbios_structure_header header;
|
@ -1,101 +0,0 @@
|
||||
fate#313584: pass bios information to XEN HVM guest
|
||||
|
||||
# HG changeset patch
|
||||
# User Ross Philipson <ross.philipson@citrix.com>
|
||||
# Date 1357838323 0
|
||||
# Node ID b9c38bea15b117552ecb51809779c7cfef82dd44
|
||||
# Parent a7ce196f40444fafbe8f13b2d80e4885d4321806
|
||||
HVM firmware passthrough ACPI processing
|
||||
|
||||
ACPI table passthrough support allowing additional static tables and
|
||||
SSDTs (AML code) to be loaded. These additional tables are added at
|
||||
the end of the secondary table list in the RSDT/XSDT tables.
|
||||
|
||||
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
|
||||
Committed-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
diff -r a7ce196f4044 -r b9c38bea15b1 tools/firmware/hvmloader/acpi/build.c
|
||||
--- a/tools/firmware/hvmloader/acpi/build.c Thu Jan 10 17:18:10 2013 +0000
|
||||
+++ b/tools/firmware/hvmloader/acpi/build.c Thu Jan 10 17:18:43 2013 +0000
|
||||
@@ -23,6 +23,9 @@
|
||||
#include "ssdt_pm.h"
|
||||
#include "../config.h"
|
||||
#include "../util.h"
|
||||
+#include <xen/hvm/hvm_xs_strings.h>
|
||||
+
|
||||
+#define ACPI_MAX_SECONDARY_TABLES 16
|
||||
|
||||
#define align16(sz) (((sz) + 15) & ~15)
|
||||
#define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
|
||||
@@ -198,6 +201,52 @@ static struct acpi_20_waet *construct_wa
|
||||
return waet;
|
||||
}
|
||||
|
||||
+static int construct_passthrough_tables(unsigned long *table_ptrs,
|
||||
+ int nr_tables)
|
||||
+{
|
||||
+ const char *s;
|
||||
+ uint8_t *acpi_pt_addr;
|
||||
+ uint32_t acpi_pt_length;
|
||||
+ struct acpi_header *header;
|
||||
+ int nr_added;
|
||||
+ int nr_max = (ACPI_MAX_SECONDARY_TABLES - nr_tables - 1);
|
||||
+ uint32_t total = 0;
|
||||
+ uint8_t *buffer;
|
||||
+
|
||||
+ s = xenstore_read(HVM_XS_ACPI_PT_ADDRESS, NULL);
|
||||
+ if ( s == NULL )
|
||||
+ return 0;
|
||||
+
|
||||
+ acpi_pt_addr = (uint8_t*)(uint32_t)strtoll(s, NULL, 0);
|
||||
+ if ( acpi_pt_addr == NULL )
|
||||
+ return 0;
|
||||
+
|
||||
+ s = xenstore_read(HVM_XS_ACPI_PT_LENGTH, NULL);
|
||||
+ if ( s == NULL )
|
||||
+ return 0;
|
||||
+
|
||||
+ acpi_pt_length = (uint32_t)strtoll(s, NULL, 0);
|
||||
+
|
||||
+ for ( nr_added = 0; nr_added < nr_max; nr_added++ )
|
||||
+ {
|
||||
+ if ( (acpi_pt_length - total) < sizeof(struct acpi_header) )
|
||||
+ break;
|
||||
+
|
||||
+ header = (struct acpi_header*)acpi_pt_addr;
|
||||
+
|
||||
+ buffer = mem_alloc(header->length, 16);
|
||||
+ if ( buffer == NULL )
|
||||
+ break;
|
||||
+ memcpy(buffer, header, header->length);
|
||||
+
|
||||
+ table_ptrs[nr_tables++] = (unsigned long)buffer;
|
||||
+ total += header->length;
|
||||
+ acpi_pt_addr += header->length;
|
||||
+ }
|
||||
+
|
||||
+ return nr_added;
|
||||
+}
|
||||
+
|
||||
static int construct_secondary_tables(unsigned long *table_ptrs,
|
||||
struct acpi_info *info)
|
||||
{
|
||||
@@ -293,6 +342,9 @@ static int construct_secondary_tables(un
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Load any additional tables passed through. */
|
||||
+ nr_tables += construct_passthrough_tables(table_ptrs, nr_tables);
|
||||
+
|
||||
table_ptrs[nr_tables] = 0;
|
||||
return nr_tables;
|
||||
}
|
||||
@@ -327,7 +379,7 @@ void acpi_build_tables(struct acpi_confi
|
||||
struct acpi_10_fadt *fadt_10;
|
||||
struct acpi_20_facs *facs;
|
||||
unsigned char *dsdt;
|
||||
- unsigned long secondary_tables[16];
|
||||
+ unsigned long secondary_tables[ACPI_MAX_SECONDARY_TABLES];
|
||||
int nr_secondaries, i;
|
||||
unsigned long vm_gid_addr;
|
||||
|
@ -1,103 +0,0 @@
|
||||
commit 5420f26507fc5c9853eb1076401a8658d72669da
|
||||
Author: Jim Fehlig <jfehlig@suse.com>
|
||||
Date: Fri Jan 11 12:22:26 2013 +0000
|
||||
|
||||
libxl: Set vfb and vkb devid if not done so by the caller
|
||||
|
||||
Other devices set a sensible devid if the caller has not done so.
|
||||
Do the same for vfb and vkb. While at it, factor out the common code
|
||||
used to determine a sensible devid, so it can be used by other
|
||||
libxl__device_*_add functions.
|
||||
|
||||
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
Index: xen-4.2.2-testing/tools/libxl/libxl.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/tools/libxl/libxl.c
|
||||
+++ xen-4.2.2-testing/tools/libxl/libxl.c
|
||||
@@ -1710,6 +1710,26 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
+/* common function to get next device id */
|
||||
+static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
|
||||
+{
|
||||
+ char *dompath, **l;
|
||||
+ unsigned int nb;
|
||||
+ int nextid = -1;
|
||||
+
|
||||
+ if (!(dompath = libxl__xs_get_dompath(gc, domid)))
|
||||
+ return nextid;
|
||||
+
|
||||
+ l = libxl__xs_directory(gc, XBT_NULL,
|
||||
+ GCSPRINTF("%s/device/%s", dompath, device), &nb);
|
||||
+ if (l == NULL || nb == 0)
|
||||
+ nextid = 0;
|
||||
+ else
|
||||
+ nextid = strtoul(l[nb - 1], NULL, 10) + 1;
|
||||
+
|
||||
+ return nextid;
|
||||
+}
|
||||
+
|
||||
/******************************************************************************/
|
||||
|
||||
int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk)
|
||||
@@ -2549,8 +2569,7 @@ void libxl__device_nic_add(libxl__egc *e
|
||||
flexarray_t *front;
|
||||
flexarray_t *back;
|
||||
libxl__device *device;
|
||||
- char *dompath, **l;
|
||||
- unsigned int nb, rc;
|
||||
+ unsigned int rc;
|
||||
|
||||
rc = libxl__device_nic_setdefault(gc, nic, domid);
|
||||
if (rc) goto out;
|
||||
@@ -2567,17 +2586,10 @@ void libxl__device_nic_add(libxl__egc *e
|
||||
}
|
||||
|
||||
if (nic->devid == -1) {
|
||||
- if (!(dompath = libxl__xs_get_dompath(gc, domid))) {
|
||||
+ if ((nic->devid = libxl__device_nextid(gc, domid, "vif") < 0)) {
|
||||
rc = ERROR_FAIL;
|
||||
goto out_free;
|
||||
}
|
||||
- if (!(l = libxl__xs_directory(gc, XBT_NULL,
|
||||
- libxl__sprintf(gc, "%s/device/vif", dompath), &nb)) ||
|
||||
- nb == 0) {
|
||||
- nic->devid = 0;
|
||||
- } else {
|
||||
- nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
|
||||
- }
|
||||
}
|
||||
|
||||
GCNEW(device);
|
||||
@@ -2964,6 +2976,13 @@ int libxl__device_vkb_add(libxl__gc *gc,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
+ if (vkb->devid == -1) {
|
||||
+ if ((vkb->devid = libxl__device_nextid(gc, domid, "vkb") < 0)) {
|
||||
+ rc = ERROR_FAIL;
|
||||
+ goto out_free;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
rc = libxl__device_from_vkb(gc, domid, vkb, &device);
|
||||
if (rc != 0) goto out_free;
|
||||
|
||||
@@ -3065,6 +3084,13 @@ int libxl__device_vfb_add(libxl__gc *gc,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
+ if (vfb->devid == -1) {
|
||||
+ if ((vfb->devid = libxl__device_nextid(gc, domid, "vfb") < 0)) {
|
||||
+ rc = ERROR_FAIL;
|
||||
+ goto out_free;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
rc = libxl__device_from_vfb(gc, domid, vfb, &device);
|
||||
if (rc != 0) goto out_free;
|
||||
|
@ -1,59 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Ian Campbell <Ian.Campbell@citrix.com>
|
||||
# Date 1357906947 0
|
||||
# Node ID ba2d73234d73fc0faa027cd9bdfd3ac90642733c
|
||||
# Parent 84d87ca765be81c215ef3b67d2ed71acfba73553
|
||||
libxc: x86: ensure that the initial mapping fits into the guest's memory
|
||||
|
||||
In particular we need to check that adding 512KB of slack and
|
||||
rounding up to a 4MB boundary do not overflow the guest's memory
|
||||
allocation. Otherwise we run off the end of the p2m when building the
|
||||
guest's initial page tables and populate them with garbage.
|
||||
|
||||
Wei noticed this when build tiny (2MB) mini-os domains.
|
||||
|
||||
Reported-by: Wei Liu <Wei.Liu2@citrix.com>
|
||||
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: Jan Beulich <jbeulich@suse.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -871,7 +871,8 @@ int xc_dom_build_image(struct xc_dom_ima
|
||||
goto err;
|
||||
if ( dom->arch_hooks->count_pgtables )
|
||||
{
|
||||
- dom->arch_hooks->count_pgtables(dom);
|
||||
+ if ( dom->arch_hooks->count_pgtables(dom) != 0 )
|
||||
+ goto err;
|
||||
if ( (dom->pgtables > 0) &&
|
||||
(xc_dom_alloc_segment(dom, &dom->pgtables_seg, "page tables", 0,
|
||||
dom->pgtables * page_size) != 0) )
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -82,6 +82,7 @@ static int count_pgtables(struct xc_dom_
|
||||
{
|
||||
int pages, extra_pages;
|
||||
xen_vaddr_t try_virt_end;
|
||||
+ xen_pfn_t try_pfn_end;
|
||||
|
||||
extra_pages = dom->alloc_bootstack ? 1 : 0;
|
||||
extra_pages += dom->extra_pages;
|
||||
@@ -91,6 +92,17 @@ static int count_pgtables(struct xc_dom_
|
||||
{
|
||||
try_virt_end = round_up(dom->virt_alloc_end + pages * PAGE_SIZE_X86,
|
||||
bits_to_mask(22)); /* 4MB alignment */
|
||||
+
|
||||
+ try_pfn_end = (try_virt_end - dom->parms.virt_base) >> PAGE_SHIFT_X86;
|
||||
+
|
||||
+ if ( try_pfn_end > dom->total_pages )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
|
||||
+ "%s: not enough memory for initial mapping (%#"PRIpfn" > %#"PRIpfn")",
|
||||
+ __FUNCTION__, try_pfn_end, dom->total_pages);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
dom->pg_l4 =
|
||||
nr_page_tables(dom, dom->parms.virt_base, try_virt_end, l4_bits);
|
||||
dom->pg_l3 =
|
@ -1,56 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Bamvor Jian Zhang <bjzhang@suse.com>
|
||||
# Date 1357906948 0
|
||||
# Node ID 2ad5792b4274d76ced39515cbd3f84898b181768
|
||||
# Parent ba2d73234d73fc0faa027cd9bdfd3ac90642733c
|
||||
fix wrong path while calling pygrub and libxl-save-helper
|
||||
|
||||
in current xen x86_64, the default libexec directory is /usr/lib/xen/bin,
|
||||
while the private binder is /usr/lib64/xen/bin. but some commands(pygrub,
|
||||
libxl-save-helper) located in private binder directory is called from
|
||||
libexec directory which lead to the following error:
|
||||
1, for pygrub bootloader:
|
||||
|
||||
libxl: debug: libxl_bootloader.c:429:bootloader_disk_attached_cb: /usr/lib/xen/bin/pygrub doesn't exist, falling back to config path
|
||||
|
||||
2, for libxl-save-helper:
|
||||
|
||||
libxl: cannot execute /usr/lib/xen/bin/libxl-save-helper: No such file or directory
|
||||
libxl: error: libxl_utils.c:363:libxl_read_exactly: file/stream truncated reading ipc msg header from domain 3 save/restore helper stdout pipe
|
||||
libxl: error: libxl_exec.c:118:libxl_report_child_exitstatus: domain 3 save/restore helper [10222] exited with error status 255
|
||||
|
||||
there are two ways to fix above error. the first one is make such command
|
||||
store in the /usr/lib/xen/bin and /usr/lib64/xen/bin(symbol link to
|
||||
previous), e.g. qemu-dm. The second way is using private binder dir
|
||||
instead of libexec dir. e.g. xenconsole.
|
||||
For these cases, the latter one is suitable.
|
||||
|
||||
Signed-off-by: Bamvor Jian Zhang <bjzhang@suse.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
Index: xen-4.2.1-testing/tools/libxl/libxl_bootloader.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/libxl/libxl_bootloader.c
|
||||
+++ xen-4.2.1-testing/tools/libxl/libxl_bootloader.c
|
||||
@@ -419,7 +419,7 @@ static void bootloader_disk_attached_cb(
|
||||
const char *bltmp;
|
||||
struct stat st;
|
||||
|
||||
- bltmp = libxl__abs_path(gc, bootloader, libxl__libexec_path());
|
||||
+ bltmp = libxl__abs_path(gc, bootloader, libxl__private_bindir_path());
|
||||
/* Check to see if the file exists in this location; if not,
|
||||
* fall back to checking the path */
|
||||
LOG(DEBUG, "Checking for bootloader in libexec path: %s", bltmp);
|
||||
Index: xen-4.2.1-testing/tools/libxl/libxl_save_callout.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/libxl/libxl_save_callout.c
|
||||
+++ xen-4.2.1-testing/tools/libxl/libxl_save_callout.c
|
||||
@@ -172,7 +172,7 @@ static void run_helper(libxl__egc *egc,
|
||||
shs->stdout_what = GCSPRINTF("domain %"PRIu32" save/restore helper"
|
||||
" stdout pipe", domid);
|
||||
|
||||
- *arg++ = getenv("LIBXL_SAVE_HELPER") ?: LIBEXEC "/" "libxl-save-helper";
|
||||
+ *arg++ = getenv("LIBXL_SAVE_HELPER") ?: PRIVATE_BINDIR "/" "libxl-save-helper";
|
||||
*arg++ = mode_arg;
|
||||
const char **stream_fd_arg = arg++;
|
||||
for (i=0; i<num_argnums; i++)
|
@ -1,34 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1358427591 -3600
|
||||
# Node ID 76598d4bf61ef0c575deba539ff99078c80e651e
|
||||
# Parent 0dee85c061addb7124d77c5f6cfe2ea7bc03b760
|
||||
x86: handle both NMI kinds if they occur simultaneously
|
||||
|
||||
We shouldn't assume PCI SERR excludes IOCHK.
|
||||
|
||||
Once at it, also remove the doubly redundant range restriction on
|
||||
"reason" - the variable already is "unsigned char".
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/traps.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/traps.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/traps.c
|
||||
@@ -3369,10 +3369,10 @@ void do_nmi(struct cpu_user_regs *regs)
|
||||
reason = inb(0x61);
|
||||
if ( reason & 0x80 )
|
||||
pci_serr_error(regs);
|
||||
- else if ( reason & 0x40 )
|
||||
+ if ( reason & 0x40 )
|
||||
io_check_error(regs);
|
||||
- else if ( !nmi_watchdog )
|
||||
- unknown_nmi_error(regs, (unsigned char)(reason&0xff));
|
||||
+ if ( !(reason & 0xc0) && !nmi_watchdog )
|
||||
+ unknown_nmi_error(regs, reason);
|
||||
}
|
||||
}
|
||||
|
@ -1,94 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Paolo Bonzini <pbonzini@redhat.com>
|
||||
# Date 1358505311 -3600
|
||||
# Node ID 3b59a6c3e9b0fb5009bdfff97c8493bb9f0bec54
|
||||
# Parent 025f202f3022c30d1ec3b6ffcb72861c43a32cf7
|
||||
x86: find a better location for the real-mode trampoline
|
||||
|
||||
On some machines, the location at 0x40e does not point to the beginning
|
||||
of the EBDA. Rather, it points to the beginning of the BIOS-reserved
|
||||
area of the EBDA, while the option ROMs place their data below that
|
||||
segment.
|
||||
|
||||
For this reason, 0x413 is actually a better source than 0x40e to get
|
||||
the location of the real-mode trampoline. Xen was already using it
|
||||
as a second source, and this patch keeps that working. However, just
|
||||
in case, let's also fetch the information from the multiboot structure,
|
||||
where the boot loader should have placed it. This way we don't
|
||||
necessarily trust one of the BIOS or the multiboot loader more than
|
||||
the other.
|
||||
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
|
||||
Retain the previous code, thus using the multiboot value only if it's
|
||||
sane but lower than the BDA computed one. Also use the full 32-bit
|
||||
mem_lower value and prefer MBI_MEMLIMITS over open coding it (requiring
|
||||
a slight adjustment to multiboot.h to make its constants actually
|
||||
usable in assembly code, which previously they were only meant to be).
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
Committed-by: Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
--- a/xen/arch/x86/boot/head.S
|
||||
+++ b/xen/arch/x86/boot/head.S
|
||||
@@ -88,6 +88,20 @@ __start:
|
||||
movzwl 0x413,%eax /* use base memory size on failure */
|
||||
shl $10-4,%eax
|
||||
1:
|
||||
+ /*
|
||||
+ * Compare the value in the BDA with the information from the
|
||||
+ * multiboot structure (if available) and use the smallest.
|
||||
+ */
|
||||
+ testb $MBI_MEMLIMITS,(%ebx)
|
||||
+ jz 2f /* not available? BDA value will be fine */
|
||||
+ mov 4(%ebx),%edx
|
||||
+ cmp $0x100,%edx /* is the multiboot value too small? */
|
||||
+ jb 2f /* if so, do not use it */
|
||||
+ shl $10-4,%edx
|
||||
+ cmp %eax,%edx /* compare with BDA value */
|
||||
+ cmovb %edx,%eax /* and use the smaller */
|
||||
+
|
||||
+2: /* Reserve 64kb for the trampoline */
|
||||
sub $0x1000,%eax
|
||||
|
||||
/* From arch/x86/smpboot.c: start_eip had better be page-aligned! */
|
||||
--- a/xen/include/xen/multiboot.h
|
||||
+++ b/xen/include/xen/multiboot.h
|
||||
@@ -18,6 +18,7 @@
|
||||
#ifndef __MULTIBOOT_H__
|
||||
#define __MULTIBOOT_H__
|
||||
|
||||
+#include "const.h"
|
||||
|
||||
/*
|
||||
* Multiboot header structure.
|
||||
@@ -31,17 +32,17 @@
|
||||
/* The magic number passed by a Multiboot-compliant boot loader. */
|
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
|
||||
|
||||
-#define MBI_MEMLIMITS (1u<< 0)
|
||||
-#define MBI_BOOTDEV (1u<< 1)
|
||||
-#define MBI_CMDLINE (1u<< 2)
|
||||
-#define MBI_MODULES (1u<< 3)
|
||||
-#define MBI_AOUT_SYMS (1u<< 4)
|
||||
-#define MBI_ELF_SYMS (1u<< 5)
|
||||
-#define MBI_MEMMAP (1u<< 6)
|
||||
-#define MBI_DRIVES (1u<< 7)
|
||||
-#define MBI_BIOSCONFIG (1u<< 8)
|
||||
-#define MBI_LOADERNAME (1u<< 9)
|
||||
-#define MBI_APM (1u<<10)
|
||||
+#define MBI_MEMLIMITS (_AC(1,u) << 0)
|
||||
+#define MBI_BOOTDEV (_AC(1,u) << 1)
|
||||
+#define MBI_CMDLINE (_AC(1,u) << 2)
|
||||
+#define MBI_MODULES (_AC(1,u) << 3)
|
||||
+#define MBI_AOUT_SYMS (_AC(1,u) << 4)
|
||||
+#define MBI_ELF_SYMS (_AC(1,u) << 5)
|
||||
+#define MBI_MEMMAP (_AC(1,u) << 6)
|
||||
+#define MBI_DRIVES (_AC(1,u) << 7)
|
||||
+#define MBI_BIOSCONFIG (_AC(1,u) << 8)
|
||||
+#define MBI_LOADERNAME (_AC(1,u) << 9)
|
||||
+#define MBI_APM (_AC(1,u) << 10)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
@ -1,137 +0,0 @@
|
||||
References: bnc#787169
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1360831377 -3600
|
||||
# Node ID 788f4551580d476e13ea907e373e58806a32179e
|
||||
# Parent e68f14b9e73925e9d404e517ba510f73fe472e4e
|
||||
AMD IOMMU: handle MSI for phantom functions
|
||||
|
||||
With ordinary requests allowed to come from phantom functions, the
|
||||
remapping tables ought to be set up to also allow for MSI triggers to
|
||||
come from other than the "real" device too.
|
||||
|
||||
It is not clear to me whether the alias-ID handling also needs
|
||||
adjustment for this to work properly, or whether firmware can be
|
||||
expected to properly express this through a device alias range
|
||||
descriptor (or multiple device alias ones).
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
--- a/xen/drivers/passthrough/amd/iommu_intr.c
|
||||
+++ b/xen/drivers/passthrough/amd/iommu_intr.c
|
||||
@@ -284,33 +284,32 @@ void amd_iommu_ioapic_update_ire(
|
||||
}
|
||||
|
||||
static void update_intremap_entry_from_msi_msg(
|
||||
- struct amd_iommu *iommu, struct pci_dev *pdev,
|
||||
- struct msi_desc *msi_desc, struct msi_msg *msg)
|
||||
+ struct amd_iommu *iommu, u16 bdf,
|
||||
+ int *remap_index, const struct msi_msg *msg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32* entry;
|
||||
- u16 bdf, req_id, alias_id;
|
||||
+ u16 req_id, alias_id;
|
||||
u8 delivery_mode, dest, vector, dest_mode;
|
||||
spinlock_t *lock;
|
||||
int offset;
|
||||
|
||||
- bdf = (pdev->bus << 8) | pdev->devfn;
|
||||
- req_id = get_dma_requestor_id(pdev->seg, bdf);
|
||||
- alias_id = get_intremap_requestor_id(pdev->seg, bdf);
|
||||
+ req_id = get_dma_requestor_id(iommu->seg, bdf);
|
||||
+ alias_id = get_intremap_requestor_id(iommu->seg, bdf);
|
||||
|
||||
if ( msg == NULL )
|
||||
{
|
||||
lock = get_intremap_lock(iommu->seg, req_id);
|
||||
spin_lock_irqsave(lock, flags);
|
||||
- free_intremap_entry(iommu->seg, req_id, msi_desc->remap_index);
|
||||
+ free_intremap_entry(iommu->seg, req_id, *remap_index);
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
|
||||
if ( ( req_id != alias_id ) &&
|
||||
- get_ivrs_mappings(pdev->seg)[alias_id].intremap_table != NULL )
|
||||
+ get_ivrs_mappings(iommu->seg)[alias_id].intremap_table != NULL )
|
||||
{
|
||||
lock = get_intremap_lock(iommu->seg, alias_id);
|
||||
spin_lock_irqsave(lock, flags);
|
||||
- free_intremap_entry(iommu->seg, alias_id, msi_desc->remap_index);
|
||||
+ free_intremap_entry(iommu->seg, alias_id, *remap_index);
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
}
|
||||
goto done;
|
||||
@@ -324,7 +323,10 @@ static void update_intremap_entry_from_m
|
||||
vector = (msg->data >> MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK;
|
||||
dest = (msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff;
|
||||
offset = get_intremap_offset(vector, delivery_mode);
|
||||
- msi_desc->remap_index = offset;
|
||||
+ if ( *remap_index < 0)
|
||||
+ *remap_index = offset;
|
||||
+ else
|
||||
+ BUG_ON(*remap_index != offset);
|
||||
|
||||
entry = (u32*)get_intremap_entry(iommu->seg, req_id, offset);
|
||||
update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
|
||||
@@ -339,7 +341,7 @@ static void update_intremap_entry_from_m
|
||||
|
||||
lock = get_intremap_lock(iommu->seg, alias_id);
|
||||
if ( ( req_id != alias_id ) &&
|
||||
- get_ivrs_mappings(pdev->seg)[alias_id].intremap_table != NULL )
|
||||
+ get_ivrs_mappings(iommu->seg)[alias_id].intremap_table != NULL )
|
||||
{
|
||||
spin_lock_irqsave(lock, flags);
|
||||
entry = (u32*)get_intremap_entry(iommu->seg, alias_id, offset);
|
||||
@@ -362,27 +364,44 @@ void amd_iommu_msi_msg_update_ire(
|
||||
struct msi_desc *msi_desc, struct msi_msg *msg)
|
||||
{
|
||||
struct pci_dev *pdev = msi_desc->dev;
|
||||
+ int bdf = PCI_BDF2(pdev->bus, pdev->devfn);
|
||||
struct amd_iommu *iommu = NULL;
|
||||
|
||||
if ( !iommu_intremap )
|
||||
return;
|
||||
|
||||
- iommu = find_iommu_for_device(pdev->seg, (pdev->bus << 8) | pdev->devfn);
|
||||
-
|
||||
+ iommu = find_iommu_for_device(pdev->seg, bdf);
|
||||
if ( !iommu )
|
||||
{
|
||||
- AMD_IOMMU_DEBUG("Fail to find iommu for MSI device id = 0x%x\n",
|
||||
- (pdev->bus << 8) | pdev->devfn);
|
||||
+ AMD_IOMMU_DEBUG("Fail to find iommu for MSI device id = 0x%x\n", bdf);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( msi_desc->remap_index >= 0 )
|
||||
- update_intremap_entry_from_msi_msg(iommu, pdev, msi_desc, NULL);
|
||||
+ {
|
||||
+ do {
|
||||
+ update_intremap_entry_from_msi_msg(iommu, bdf,
|
||||
+ &msi_desc->remap_index, NULL);
|
||||
+ if ( !pdev || !pdev->phantom_stride )
|
||||
+ break;
|
||||
+ bdf += pdev->phantom_stride;
|
||||
+ } while ( PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) );
|
||||
+
|
||||
+ msi_desc->remap_index = -1;
|
||||
+ if ( pdev )
|
||||
+ bdf = PCI_BDF2(pdev->bus, pdev->devfn);
|
||||
+ }
|
||||
|
||||
if ( !msg )
|
||||
return;
|
||||
|
||||
- update_intremap_entry_from_msi_msg(iommu, pdev, msi_desc, msg);
|
||||
+ do {
|
||||
+ update_intremap_entry_from_msi_msg(iommu, bdf, &msi_desc->remap_index,
|
||||
+ msg);
|
||||
+ if ( !pdev || !pdev->phantom_stride )
|
||||
+ break;
|
||||
+ bdf += pdev->phantom_stride;
|
||||
+ } while ( PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) );
|
||||
}
|
||||
|
||||
void amd_iommu_read_msi_from_ire(
|
@ -1,26 +0,0 @@
|
||||
changeset: 26547:8285d20a6f5b
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Fri Feb 15 13:32:11 2013 +0000
|
||||
files: tools/libxc/xtl_logger_stdio.c
|
||||
description:
|
||||
tools/xc: fix logic error in stdiostream_progress
|
||||
|
||||
Setting XTL_STDIOSTREAM_HIDE_PROGRESS should disable progress reporting.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 0141aeb86b79 -r 8285d20a6f5b tools/libxc/xtl_logger_stdio.c
|
||||
--- a/tools/libxc/xtl_logger_stdio.c Fri Feb 15 13:32:10 2013 +0000
|
||||
+++ b/tools/libxc/xtl_logger_stdio.c Fri Feb 15 13:32:11 2013 +0000
|
||||
@@ -89,7 +89,7 @@ static void stdiostream_progress(struct
|
||||
int newpel, extra_erase;
|
||||
xentoollog_level this_level;
|
||||
|
||||
- if (!(lg->flags & XTL_STDIOSTREAM_HIDE_PROGRESS))
|
||||
+ if (lg->flags & XTL_STDIOSTREAM_HIDE_PROGRESS)
|
||||
return;
|
||||
|
||||
if (percent < lg->progress_last_percent) {
|
@ -1,62 +0,0 @@
|
||||
changeset: 26548:e7d9bac5c11d
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Fri Feb 15 13:32:11 2013 +0000
|
||||
files: tools/libxc/xtl_logger_stdio.c
|
||||
description:
|
||||
tools/xc: handle tty output differently in stdiostream_progress
|
||||
|
||||
If the output goes to a tty, rewind the cursor and print everything in a
|
||||
single line as it was done up to now. If the output goes to a file or
|
||||
pipe print a newline after each progress output. This will fix logging
|
||||
of progress messages from xc_save to xend.log.
|
||||
|
||||
To support XTL_STDIOSTREAM_SHOW_PID or XTL_STDIOSTREAM_SHOW_DATE print
|
||||
the output via vmessage if the output is not a tty.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r 8285d20a6f5b -r e7d9bac5c11d tools/libxc/xtl_logger_stdio.c
|
||||
--- a/tools/libxc/xtl_logger_stdio.c Fri Feb 15 13:32:11 2013 +0000
|
||||
+++ b/tools/libxc/xtl_logger_stdio.c Fri Feb 15 13:32:11 2013 +0000
|
||||
@@ -81,6 +81,17 @@ static void stdiostream_vmessage(xentool
|
||||
fflush(lg->f);
|
||||
}
|
||||
|
||||
+static void stdiostream_message(struct xentoollog_logger *logger_in,
|
||||
+ xentoollog_level level,
|
||||
+ const char *context,
|
||||
+ const char *format, ...)
|
||||
+{
|
||||
+ va_list al;
|
||||
+ va_start(al,format);
|
||||
+ stdiostream_vmessage(logger_in, level, -1, context, format, al);
|
||||
+ va_end(al);
|
||||
+}
|
||||
+
|
||||
static void stdiostream_progress(struct xentoollog_logger *logger_in,
|
||||
const char *context,
|
||||
const char *doing_what, int percent,
|
||||
@@ -105,11 +116,18 @@ static void stdiostream_progress(struct
|
||||
if (this_level < lg->min_level)
|
||||
return;
|
||||
|
||||
+ lg->progress_last_percent = percent;
|
||||
+
|
||||
+ if (isatty(fileno(lg->f)) <= 0) {
|
||||
+ stdiostream_message(logger_in, this_level, context,
|
||||
+ "%s: %lu/%lu %3d%%",
|
||||
+ doing_what, done, total, percent);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (lg->progress_erase_len)
|
||||
putc('\r', lg->f);
|
||||
|
||||
- lg->progress_last_percent = percent;
|
||||
-
|
||||
newpel = fprintf(lg->f, "%s%s" "%s: %lu/%lu %3d%%%s",
|
||||
context?context:"", context?": ":"",
|
||||
doing_what, done, total, percent,
|
@ -1,36 +0,0 @@
|
||||
changeset: 26549:d2991367ecd2
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Fri Feb 15 13:32:12 2013 +0000
|
||||
files: tools/libxc/xenguest.h
|
||||
description:
|
||||
tools/xc: turn XCFLAGS_* into shifts
|
||||
|
||||
to make it clear that these are bits and to make it easier to use in
|
||||
xend code.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r e7d9bac5c11d -r d2991367ecd2 tools/libxc/xenguest.h
|
||||
--- a/tools/libxc/xenguest.h Fri Feb 15 13:32:11 2013 +0000
|
||||
+++ b/tools/libxc/xenguest.h Fri Feb 15 13:32:12 2013 +0000
|
||||
@@ -23,11 +23,12 @@
|
||||
#ifndef XENGUEST_H
|
||||
#define XENGUEST_H
|
||||
|
||||
-#define XCFLAGS_LIVE 1
|
||||
-#define XCFLAGS_DEBUG 2
|
||||
-#define XCFLAGS_HVM 4
|
||||
-#define XCFLAGS_STDVGA 8
|
||||
-#define XCFLAGS_CHECKPOINT_COMPRESS 16
|
||||
+#define XCFLAGS_LIVE (1 << 0)
|
||||
+#define XCFLAGS_DEBUG (1 << 1)
|
||||
+#define XCFLAGS_HVM (1 << 2)
|
||||
+#define XCFLAGS_STDVGA (1 << 3)
|
||||
+#define XCFLAGS_CHECKPOINT_COMPRESS (1 << 4)
|
||||
+
|
||||
#define X86_64_B_SIZE 64
|
||||
#define X86_32_B_SIZE 32
|
||||
|
@ -1,58 +0,0 @@
|
||||
changeset: 26550:e6c373fcb73e
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Fri Feb 15 13:32:13 2013 +0000
|
||||
files: tools/xcutils/xc_save.c
|
||||
description:
|
||||
tools/xc: restore logging in xc_save
|
||||
|
||||
Prior to xen-4.1 the helper xc_save would print some progress during
|
||||
migration. With the new xc_interface_open API no more messages were
|
||||
printed because no logger was configured.
|
||||
|
||||
Restore previous behaviour by providing a logger. The progress in
|
||||
xc_domain_save will be disabled because it generates alot of output and
|
||||
fills up xend.log quickly.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
diff -r d2991367ecd2 -r e6c373fcb73e tools/xcutils/xc_save.c
|
||||
--- a/tools/xcutils/xc_save.c Fri Feb 15 13:32:12 2013 +0000
|
||||
+++ b/tools/xcutils/xc_save.c Fri Feb 15 13:32:13 2013 +0000
|
||||
@@ -166,17 +166,15 @@ static int switch_qemu_logdirty(int domi
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
- unsigned int maxit, max_f;
|
||||
+ unsigned int maxit, max_f, lflags;
|
||||
int io_fd, ret, port;
|
||||
struct save_callbacks callbacks;
|
||||
+ xentoollog_level lvl;
|
||||
+ xentoollog_logger *l;
|
||||
|
||||
if (argc != 6)
|
||||
errx(1, "usage: %s iofd domid maxit maxf flags", argv[0]);
|
||||
|
||||
- si.xch = xc_interface_open(0,0,0);
|
||||
- if (!si.xch)
|
||||
- errx(1, "failed to open control interface");
|
||||
-
|
||||
io_fd = atoi(argv[1]);
|
||||
si.domid = atoi(argv[2]);
|
||||
maxit = atoi(argv[3]);
|
||||
@@ -185,6 +183,13 @@ main(int argc, char **argv)
|
||||
|
||||
si.suspend_evtchn = -1;
|
||||
|
||||
+ lvl = si.flags & XCFLAGS_DEBUG ? XTL_DEBUG: XTL_DETAIL;
|
||||
+ lflags = XTL_STDIOSTREAM_HIDE_PROGRESS;
|
||||
+ l = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, lvl, lflags);
|
||||
+ si.xch = xc_interface_open(l, 0, 0);
|
||||
+ if (!si.xch)
|
||||
+ errx(1, "failed to open control interface");
|
||||
+
|
||||
si.xce = xc_evtchn_open(NULL, 0);
|
||||
if (si.xce == NULL)
|
||||
warnx("failed to open event channel handle");
|
@ -1,111 +0,0 @@
|
||||
changeset: 26551:48f9436959dd
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Fri Feb 15 13:32:13 2013 +0000
|
||||
files: tools/libxc/xc_domain_restore.c tools/libxc/xc_domain_save.c tools/xcutils/xc_restore.c tools/xcutils/xc_save.c
|
||||
description:
|
||||
tools/xc: log pid in xc_save/xc_restore output
|
||||
|
||||
If several migrations log their output to xend.log its not clear which
|
||||
line belongs to a which guest. Print entry/exit of xc_save and
|
||||
xc_restore and also request to print pid with each log call.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
|
||||
Index: xen-4.2.1-testing/tools/libxc/xc_domain_restore.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/libxc/xc_domain_restore.c
|
||||
+++ xen-4.2.1-testing/tools/libxc/xc_domain_restore.c
|
||||
@@ -1382,6 +1382,8 @@ int xc_domain_restore(xc_interface *xch,
|
||||
struct restore_ctx *ctx = &_ctx;
|
||||
struct domain_info_context *dinfo = &ctx->dinfo;
|
||||
|
||||
+ DPRINTF("%s: starting restore of new domid %u", __func__, dom);
|
||||
+
|
||||
pagebuf_init(&pagebuf);
|
||||
memset(&tailbuf, 0, sizeof(tailbuf));
|
||||
tailbuf.ishvm = hvm;
|
||||
@@ -1408,7 +1410,7 @@ int xc_domain_restore(xc_interface *xch,
|
||||
PERROR("read: p2m_size");
|
||||
goto out;
|
||||
}
|
||||
- DPRINTF("xc_domain_restore start: p2m_size = %lx\n", dinfo->p2m_size);
|
||||
+ DPRINTF("%s: p2m_size = %lx\n", __func__, dinfo->p2m_size);
|
||||
|
||||
if ( !get_platform_info(xch, dom,
|
||||
&ctx->max_mfn, &ctx->hvirt_start, &ctx->pt_levels, &dinfo->guest_width) )
|
||||
@@ -2215,7 +2217,7 @@ int xc_domain_restore(xc_interface *xch,
|
||||
|
||||
fcntl(io_fd, F_SETFL, orig_io_fd_flags);
|
||||
|
||||
- DPRINTF("Restore exit with rc=%d\n", rc);
|
||||
+ DPRINTF("Restore exit of domid %u with rc=%d\n", dom, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
Index: xen-4.2.1-testing/tools/libxc/xc_domain_save.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/libxc/xc_domain_save.c
|
||||
+++ xen-4.2.1-testing/tools/libxc/xc_domain_save.c
|
||||
@@ -897,6 +897,8 @@ int xc_domain_save(xc_interface *xch, in
|
||||
|
||||
int completed = 0;
|
||||
|
||||
+ DPRINTF("%s: starting save of domid %u", __func__, dom);
|
||||
+
|
||||
if ( hvm && !callbacks->switch_qemu_logdirty )
|
||||
{
|
||||
ERROR("No switch_qemu_logdirty callback provided.");
|
||||
@@ -2112,7 +2114,7 @@ int xc_domain_save(xc_interface *xch, in
|
||||
free(pfn_err);
|
||||
free(to_fix);
|
||||
|
||||
- DPRINTF("Save exit rc=%d\n",rc);
|
||||
+ DPRINTF("Save exit of domid %u with rc=%d\n", dom, rc);
|
||||
|
||||
return !!rc;
|
||||
}
|
||||
Index: xen-4.2.1-testing/tools/xcutils/xc_restore.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/xcutils/xc_restore.c
|
||||
+++ xen-4.2.1-testing/tools/xcutils/xc_restore.c
|
||||
@@ -19,17 +19,22 @@ int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
unsigned int domid, store_evtchn, console_evtchn;
|
||||
- unsigned int hvm, pae, apic;
|
||||
+ unsigned int hvm, pae, apic, lflags;
|
||||
xc_interface *xch;
|
||||
int io_fd, ret;
|
||||
int superpages;
|
||||
unsigned long store_mfn, console_mfn;
|
||||
+ xentoollog_level lvl;
|
||||
+ xentoollog_logger *l;
|
||||
|
||||
if ( (argc != 8) && (argc != 9) )
|
||||
errx(1, "usage: %s iofd domid store_evtchn "
|
||||
"console_evtchn hvm pae apic [superpages]", argv[0]);
|
||||
|
||||
- xch = xc_interface_open(0,0,0);
|
||||
+ lvl = XTL_DETAIL;
|
||||
+ lflags = XTL_STDIOSTREAM_SHOW_PID | XTL_STDIOSTREAM_HIDE_PROGRESS;
|
||||
+ l = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, lvl, lflags);
|
||||
+ xch = xc_interface_open(l, 0, 0);
|
||||
if ( !xch )
|
||||
errx(1, "failed to open control interface");
|
||||
|
||||
Index: xen-4.2.1-testing/tools/xcutils/xc_save.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/xcutils/xc_save.c
|
||||
+++ xen-4.2.1-testing/tools/xcutils/xc_save.c
|
||||
@@ -184,7 +184,7 @@ main(int argc, char **argv)
|
||||
si.suspend_evtchn = -1;
|
||||
|
||||
lvl = si.flags & XCFLAGS_DEBUG ? XTL_DEBUG: XTL_DETAIL;
|
||||
- lflags = XTL_STDIOSTREAM_HIDE_PROGRESS;
|
||||
+ lflags = XTL_STDIOSTREAM_SHOW_PID | XTL_STDIOSTREAM_HIDE_PROGRESS;
|
||||
l = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, lvl, lflags);
|
||||
si.xch = xc_interface_open(l, 0, 0);
|
||||
if (!si.xch)
|
@ -1,46 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Ross Philipson <ross.philipson@citrix.com>
|
||||
# Date 1360935136 0
|
||||
# Node ID 3124ab7855fd7d4e0f3ea125cb21b60d693e8800
|
||||
# Parent 71c15ae0998378b5c117bbd27a48015757685706
|
||||
libxl: switch to using the new xc_hvm_build() libxc API.
|
||||
|
||||
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
Index: xen-4.2.2-testing/tools/libxl/libxl_dom.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/tools/libxl/libxl_dom.c
|
||||
+++ xen-4.2.2-testing/tools/libxl/libxl_dom.c
|
||||
@@ -546,17 +546,24 @@ int libxl__build_hvm(libxl__gc *gc, uint
|
||||
libxl__domain_build_state *state)
|
||||
{
|
||||
libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
+ struct xc_hvm_build_args args = {};
|
||||
int ret, rc = ERROR_FAIL;
|
||||
const char *firmware = libxl__domain_firmware(gc, info);
|
||||
|
||||
if (!firmware)
|
||||
goto out;
|
||||
- ret = xc_hvm_build_target_mem(
|
||||
- ctx->xch,
|
||||
- domid,
|
||||
- (info->max_memkb - info->video_memkb) / 1024,
|
||||
- (info->target_memkb - info->video_memkb) / 1024,
|
||||
- firmware);
|
||||
+
|
||||
+ memset(&args, 0, sizeof(struct xc_hvm_build_args));
|
||||
+ /* The params from the configuration file are in Mb, which are then
|
||||
+ * multiplied by 1 Kb. This was then divided off when calling
|
||||
+ * the old xc_hvm_build_target_mem() which then turned them to bytes.
|
||||
+ * Do all this in one step here...
|
||||
+ */
|
||||
+ args.mem_size = (uint64_t)(info->max_memkb - info->video_memkb) << 10;
|
||||
+ args.mem_target = (uint64_t)(info->target_memkb - info->video_memkb) << 10;
|
||||
+ args.image_file_name = firmware;
|
||||
+
|
||||
+ ret = xc_hvm_build(ctx->xch, domid, &args);
|
||||
if (ret) {
|
||||
LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "hvm building failed");
|
||||
goto out;
|
@ -1,314 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Ross Philipson <ross.philipson@citrix.com>
|
||||
# Date 1360935136 0
|
||||
# Node ID 17a228e37ec0913ff86b8b5f2d88f1b8e92146f1
|
||||
# Parent 3124ab7855fd7d4e0f3ea125cb21b60d693e8800
|
||||
libxl: HVM firmware passthrough support
|
||||
|
||||
This patch introduces support for two new parameters in libxl:
|
||||
|
||||
smbios_firmware=<path_to_smbios_structures_file>
|
||||
acpi_firmware=<path_to_acpi_tables_file>
|
||||
|
||||
The changes are primarily in the domain building code where the firmware files
|
||||
are read and passed to libxc for loading into the new guest. After the domain
|
||||
building call to libxc, the addresses for the loaded blobs are returned and
|
||||
written to xenstore.
|
||||
|
||||
LIBXL_HAVE_FIRMWARE_PASSTHROUGH is defined in libxl.h to allow users to
|
||||
determine if the feature is present.
|
||||
|
||||
This patch also updates the xl.cfg man page with descriptions of the two new
|
||||
parameters for firmware passthrough.
|
||||
|
||||
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
Index: xen-4.2.2-testing/docs/man/xl.cfg.pod.5
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/docs/man/xl.cfg.pod.5
|
||||
+++ xen-4.2.2-testing/docs/man/xl.cfg.pod.5
|
||||
@@ -637,6 +637,25 @@ of Xen) within a Xen guest or to support
|
||||
which uses hardware virtualisation extensions (e.g. Windows XP
|
||||
compatibility mode on more modern Windows OS).
|
||||
|
||||
+=item B<acpi_firmware="STRING">
|
||||
+
|
||||
+Specify a path to a file that contains extra ACPI firmware tables to pass in to
|
||||
+a guest. The file can contain several tables in their binary AML form
|
||||
+concatenated together. Each table self describes its length so no additional
|
||||
+information is needed. These tables will be added to the ACPI table set in the
|
||||
+guest. Note that existing tables cannot be overridden by this feature. For
|
||||
+example this cannot be used to override tables like DSDT, FADT, etc.
|
||||
+
|
||||
+=item B<smbios_firmware="STRING">
|
||||
+
|
||||
+Specify a path to a file that contains extra SMBIOS firmware structures to pass
|
||||
+in to a guest. The file can contain a set DMTF predefined structures which will
|
||||
+override the internal defaults. Not all predefined structures can be overridden,
|
||||
+only the following types: 0, 1, 2, 3, 11, 22, 39. The file can also contain any
|
||||
+number of vendor defined SMBIOS structures (type 128 - 255). Since SMBIOS
|
||||
+structures do not present their overall size, each entry in the file must be
|
||||
+preceded by a 32b integer indicating the size of the next structure.
|
||||
+
|
||||
=back
|
||||
|
||||
=head3 Guest Virtual Time Controls
|
||||
Index: xen-4.2.2-testing/tools/libxl/libxl.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/tools/libxl/libxl.h
|
||||
+++ xen-4.2.2-testing/tools/libxl/libxl.h
|
||||
@@ -68,6 +68,13 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
+ * LIBXL_HAVE_FIRMWARE_PASSTHROUGH indicates the feature for
|
||||
+ * passing in SMBIOS and ACPI firmware to HVM guests is present
|
||||
+ * in the library.
|
||||
+ */
|
||||
+#define LIBXL_HAVE_FIRMWARE_PASSTHROUGH 1
|
||||
+
|
||||
+/*
|
||||
* libxl ABI compatibility
|
||||
*
|
||||
* The only guarantee which libxl makes regarding ABI compatibility
|
||||
Index: xen-4.2.2-testing/tools/libxl/libxl_dom.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/tools/libxl/libxl_dom.c
|
||||
+++ xen-4.2.2-testing/tools/libxl/libxl_dom.c
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <xc_dom.h>
|
||||
#include <xen/hvm/hvm_info_table.h>
|
||||
+#include <xen/hvm/hvm_xs_strings.h>
|
||||
|
||||
libxl_domain_type libxl__domain_type(libxl__gc *gc, uint32_t domid)
|
||||
{
|
||||
@@ -514,11 +515,61 @@ static int hvm_build_set_params(xc_inter
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const char *libxl__domain_firmware(libxl__gc *gc,
|
||||
- libxl_domain_build_info *info)
|
||||
+static int hvm_build_set_xs_values(libxl__gc *gc,
|
||||
+ uint32_t domid,
|
||||
+ struct xc_hvm_build_args *args)
|
||||
+{
|
||||
+ char *path = NULL;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (args->smbios_module.guest_addr_out) {
|
||||
+ path = GCSPRINTF("/local/domain/%d/"HVM_XS_SMBIOS_PT_ADDRESS, domid);
|
||||
+
|
||||
+ ret = libxl__xs_write(gc, XBT_NULL, path, "0x%"PRIx64,
|
||||
+ args->smbios_module.guest_addr_out);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+
|
||||
+ path = GCSPRINTF("/local/domain/%d/"HVM_XS_SMBIOS_PT_LENGTH, domid);
|
||||
+
|
||||
+ ret = libxl__xs_write(gc, XBT_NULL, path, "0x%x",
|
||||
+ args->smbios_module.length);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (args->acpi_module.guest_addr_out) {
|
||||
+ path = GCSPRINTF("/local/domain/%d/"HVM_XS_ACPI_PT_ADDRESS, domid);
|
||||
+
|
||||
+ ret = libxl__xs_write(gc, XBT_NULL, path, "0x%"PRIx64,
|
||||
+ args->acpi_module.guest_addr_out);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+
|
||||
+ path = GCSPRINTF("/local/domain/%d/"HVM_XS_ACPI_PT_LENGTH, domid);
|
||||
+
|
||||
+ ret = libxl__xs_write(gc, XBT_NULL, path, "0x%x",
|
||||
+ args->acpi_module.length);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ LOG(ERROR, "failed to write firmware xenstore value, err: %d", ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int libxl__domain_firmware(libxl__gc *gc,
|
||||
+ libxl_domain_build_info *info,
|
||||
+ struct xc_hvm_build_args *args)
|
||||
{
|
||||
libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
const char *firmware;
|
||||
+ int e, rc = ERROR_FAIL;
|
||||
+ int datalen = 0;
|
||||
+ void *data;
|
||||
|
||||
if (info->u.hvm.firmware)
|
||||
firmware = info->u.hvm.firmware;
|
||||
@@ -532,13 +583,52 @@ static const char *libxl__domain_firmwar
|
||||
firmware = "hvmloader";
|
||||
break;
|
||||
default:
|
||||
- LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "invalid device model version %d",
|
||||
- info->device_model_version);
|
||||
- return NULL;
|
||||
+ LOG(ERROR, "invalid device model version %d",
|
||||
+ info->device_model_version);
|
||||
+ return ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
- return libxl__abs_path(gc, firmware, libxl__xenfirmwaredir_path());
|
||||
+ args->image_file_name = libxl__abs_path(gc, firmware,
|
||||
+ libxl__xenfirmwaredir_path());
|
||||
+
|
||||
+ if (info->u.hvm.smbios_firmware) {
|
||||
+ data = NULL;
|
||||
+ e = libxl_read_file_contents(ctx, info->u.hvm.smbios_firmware,
|
||||
+ &data, &datalen);
|
||||
+ if (e) {
|
||||
+ LOGEV(ERROR, e, "failed to read SMBIOS firmware file %s",
|
||||
+ info->u.hvm.smbios_firmware);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ libxl__ptr_add(gc, data);
|
||||
+ if (datalen) {
|
||||
+ /* Only accept non-empty files */
|
||||
+ args->smbios_module.data = data;
|
||||
+ args->smbios_module.length = (uint32_t)datalen;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (info->u.hvm.acpi_firmware) {
|
||||
+ data = NULL;
|
||||
+ e = libxl_read_file_contents(ctx, info->u.hvm.acpi_firmware,
|
||||
+ &data, &datalen);
|
||||
+ if (e) {
|
||||
+ LOGEV(ERROR, e, "failed to read ACPI firmware file %s",
|
||||
+ info->u.hvm.acpi_firmware);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ libxl__ptr_add(gc, data);
|
||||
+ if (datalen) {
|
||||
+ /* Only accept non-empty files */
|
||||
+ args->acpi_module.data = data;
|
||||
+ args->acpi_module.length = (uint32_t)datalen;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+out:
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
int libxl__build_hvm(libxl__gc *gc, uint32_t domid,
|
||||
@@ -548,10 +638,6 @@ int libxl__build_hvm(libxl__gc *gc, uint
|
||||
libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
struct xc_hvm_build_args args = {};
|
||||
int ret, rc = ERROR_FAIL;
|
||||
- const char *firmware = libxl__domain_firmware(gc, info);
|
||||
-
|
||||
- if (!firmware)
|
||||
- goto out;
|
||||
|
||||
memset(&args, 0, sizeof(struct xc_hvm_build_args));
|
||||
/* The params from the configuration file are in Mb, which are then
|
||||
@@ -561,22 +647,34 @@ int libxl__build_hvm(libxl__gc *gc, uint
|
||||
*/
|
||||
args.mem_size = (uint64_t)(info->max_memkb - info->video_memkb) << 10;
|
||||
args.mem_target = (uint64_t)(info->target_memkb - info->video_memkb) << 10;
|
||||
- args.image_file_name = firmware;
|
||||
+
|
||||
+ if (libxl__domain_firmware(gc, info, &args)) {
|
||||
+ LOG(ERROR, "initializing domain firmware failed");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
ret = xc_hvm_build(ctx->xch, domid, &args);
|
||||
if (ret) {
|
||||
- LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "hvm building failed");
|
||||
+ LOGEV(ERROR, ret, "hvm building failed");
|
||||
goto out;
|
||||
}
|
||||
+
|
||||
ret = hvm_build_set_params(ctx->xch, domid, info, state->store_port,
|
||||
&state->store_mfn, state->console_port,
|
||||
&state->console_mfn, state->store_domid,
|
||||
state->console_domid);
|
||||
if (ret) {
|
||||
- LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "hvm build set params failed");
|
||||
+ LOGEV(ERROR, ret, "hvm build set params failed");
|
||||
goto out;
|
||||
}
|
||||
- rc = 0;
|
||||
+
|
||||
+ ret = hvm_build_set_xs_values(gc, domid, &args);
|
||||
+ if (ret) {
|
||||
+ LOG(ERROR, "hvm build set xenstore values failed (ret=%d)", ret);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
@@ -638,7 +736,7 @@ int libxl__toolstack_restore(uint32_t do
|
||||
|
||||
memcpy(&count, ptr, sizeof(count));
|
||||
ptr += sizeof(count);
|
||||
-
|
||||
+
|
||||
if (size < sizeof(version) + sizeof(count) +
|
||||
count * (sizeof(struct libxl__physmap_info))) {
|
||||
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "wrong size");
|
||||
@@ -852,7 +950,7 @@ static void switch_logdirty_xswatch(libx
|
||||
rc = libxl__xs_rm_checked(gc, t, lds->ret_path);
|
||||
if (rc) goto out;
|
||||
|
||||
- rc = libxl__xs_transaction_commit(gc, &t);
|
||||
+ rc = libxl__xs_transaction_commit(gc, &t);
|
||||
if (!rc) break;
|
||||
if (rc<0) goto out;
|
||||
}
|
||||
@@ -1324,7 +1422,7 @@ void libxl__xc_domain_save_done(libxl__e
|
||||
if (type == LIBXL_DOMAIN_TYPE_HVM) {
|
||||
rc = libxl__domain_suspend_device_model(gc, dss);
|
||||
if (rc) goto out;
|
||||
-
|
||||
+
|
||||
libxl__domain_save_device_model(egc, dss, domain_suspend_done);
|
||||
return;
|
||||
}
|
||||
Index: xen-4.2.2-testing/tools/libxl/libxl_types.idl
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/tools/libxl/libxl_types.idl
|
||||
+++ xen-4.2.2-testing/tools/libxl/libxl_types.idl
|
||||
@@ -301,6 +301,8 @@ libxl_domain_build_info = Struct("domain
|
||||
("vpt_align", libxl_defbool),
|
||||
("timer_mode", libxl_timer_mode),
|
||||
("nested_hvm", libxl_defbool),
|
||||
+ ("smbios_firmware", string),
|
||||
+ ("acpi_firmware", string),
|
||||
("nographic", libxl_defbool),
|
||||
("vga", libxl_vga_interface_info),
|
||||
("vnc", libxl_vnc_info),
|
||||
Index: xen-4.2.2-testing/tools/libxl/xl_cmdimpl.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/tools/libxl/xl_cmdimpl.c
|
||||
+++ xen-4.2.2-testing/tools/libxl/xl_cmdimpl.c
|
||||
@@ -863,6 +863,11 @@ static void parse_config_data(const char
|
||||
}
|
||||
|
||||
xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
|
||||
+
|
||||
+ xlu_cfg_replace_string(config, "smbios_firmware",
|
||||
+ &b_info->u.hvm.smbios_firmware, 0);
|
||||
+ xlu_cfg_replace_string(config, "acpi_firmware",
|
||||
+ &b_info->u.hvm.acpi_firmware, 0);
|
||||
break;
|
||||
case LIBXL_DOMAIN_TYPE_PV:
|
||||
{
|
@ -1,320 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Ross Philipson <ross.philipson@citrix.com>
|
||||
# Date 1360935137 0
|
||||
# Node ID 6a9549a15108669408123e5e39f52ad09dea1c10
|
||||
# Parent 17a228e37ec0913ff86b8b5f2d88f1b8e92146f1
|
||||
libxl: Cleanup, use LOG* and GCSPRINTF macro in libxl_dom.c
|
||||
|
||||
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
Index: xen-4.2.2-testing/tools/libxl/libxl_dom.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/tools/libxl/libxl_dom.c
|
||||
+++ xen-4.2.2-testing/tools/libxl/libxl_dom.c
|
||||
@@ -32,8 +32,7 @@ libxl_domain_type libxl__domain_type(lib
|
||||
|
||||
ret = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
|
||||
if (ret != 1 || info.domain != domid) {
|
||||
- LIBXL__LOG(CTX, LIBXL__LOG_ERROR,
|
||||
- "unable to get domain type for domid=%"PRIu32, domid);
|
||||
+ LOG(ERROR, "unable to get domain type for domid=%"PRIu32, domid);
|
||||
return LIBXL_DOMAIN_TYPE_INVALID;
|
||||
}
|
||||
if (info.flags & XEN_DOMINF_hvm_guest)
|
||||
@@ -317,20 +316,19 @@ int libxl__build_post(libxl__gc *gc, uin
|
||||
|
||||
ents = libxl__calloc(gc, 12 + (info->max_vcpus * 2) + 2, sizeof(char *));
|
||||
ents[0] = "memory/static-max";
|
||||
- ents[1] = libxl__sprintf(gc, "%"PRId64, info->max_memkb);
|
||||
+ ents[1] = GCSPRINTF("%"PRId64, info->max_memkb);
|
||||
ents[2] = "memory/target";
|
||||
- ents[3] = libxl__sprintf(gc, "%"PRId64,
|
||||
- info->target_memkb - info->video_memkb);
|
||||
+ ents[3] = GCSPRINTF("%"PRId64, info->target_memkb - info->video_memkb);
|
||||
ents[4] = "memory/videoram";
|
||||
- ents[5] = libxl__sprintf(gc, "%"PRId64, info->video_memkb);
|
||||
+ ents[5] = GCSPRINTF("%"PRId64, info->video_memkb);
|
||||
ents[6] = "domid";
|
||||
- ents[7] = libxl__sprintf(gc, "%d", domid);
|
||||
+ ents[7] = GCSPRINTF("%d", domid);
|
||||
ents[8] = "store/port";
|
||||
- ents[9] = libxl__sprintf(gc, "%"PRIu32, state->store_port);
|
||||
+ ents[9] = GCSPRINTF("%"PRIu32, state->store_port);
|
||||
ents[10] = "store/ring-ref";
|
||||
- ents[11] = libxl__sprintf(gc, "%lu", state->store_mfn);
|
||||
+ ents[11] = GCSPRINTF("%lu", state->store_mfn);
|
||||
for (i = 0; i < info->max_vcpus; i++) {
|
||||
- ents[12+(i*2)] = libxl__sprintf(gc, "cpu/%d/availability", i);
|
||||
+ ents[12+(i*2)] = GCSPRINTF("cpu/%d/availability", i);
|
||||
ents[12+(i*2)+1] = libxl_bitmap_test(&info->avail_vcpus, i)
|
||||
? "online" : "offline";
|
||||
}
|
||||
@@ -339,7 +337,7 @@ int libxl__build_post(libxl__gc *gc, uin
|
||||
if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
|
||||
hvm_ents = libxl__calloc(gc, 3, sizeof(char *));
|
||||
hvm_ents[0] = "hvmloader/generation-id-address";
|
||||
- hvm_ents[1] = libxl__sprintf(gc, "0x%lx", state->vm_generationid_addr);
|
||||
+ hvm_ents[1] = GCSPRINTF("0x%lx", state->vm_generationid_addr);
|
||||
}
|
||||
|
||||
dom_path = libxl__xs_get_dompath(gc, domid);
|
||||
@@ -347,7 +345,7 @@ int libxl__build_post(libxl__gc *gc, uin
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
- vm_path = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(gc, "%s/vm", dom_path), NULL);
|
||||
+ vm_path = xs_read(ctx->xsh, XBT_NULL, GCSPRINTF("%s/vm", dom_path), NULL);
|
||||
retry_transaction:
|
||||
t = xs_transaction_start(ctx->xsh);
|
||||
|
||||
@@ -378,7 +376,7 @@ int libxl__build_pv(libxl__gc *gc, uint3
|
||||
|
||||
dom = xc_dom_allocate(ctx->xch, state->pv_cmdline, info->u.pv.features);
|
||||
if (!dom) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_allocate failed");
|
||||
+ LOGE(ERROR, "xc_dom_allocate failed");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
@@ -388,13 +386,13 @@ int libxl__build_pv(libxl__gc *gc, uint3
|
||||
state->pv_kernel.data,
|
||||
state->pv_kernel.size);
|
||||
if ( ret != 0) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_kernel_mem failed");
|
||||
+ LOGE(ERROR, "xc_dom_kernel_mem failed");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
ret = xc_dom_kernel_file(dom, state->pv_kernel.path);
|
||||
if ( ret != 0) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_kernel_file failed");
|
||||
+ LOGE(ERROR, "xc_dom_kernel_file failed");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -402,12 +400,12 @@ int libxl__build_pv(libxl__gc *gc, uint3
|
||||
if ( state->pv_ramdisk.path && strlen(state->pv_ramdisk.path) ) {
|
||||
if (state->pv_ramdisk.mapped) {
|
||||
if ( (ret = xc_dom_ramdisk_mem(dom, state->pv_ramdisk.data, state->pv_ramdisk.size)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_ramdisk_mem failed");
|
||||
+ LOGE(ERROR, "xc_dom_ramdisk_mem failed");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if ( (ret = xc_dom_ramdisk_file(dom, state->pv_ramdisk.path)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_ramdisk_file failed");
|
||||
+ LOGE(ERROR, "xc_dom_ramdisk_file failed");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -420,31 +418,31 @@ int libxl__build_pv(libxl__gc *gc, uint3
|
||||
dom->xenstore_domid = state->store_domid;
|
||||
|
||||
if ( (ret = xc_dom_boot_xen_init(dom, ctx->xch, domid)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_boot_xen_init failed");
|
||||
+ LOGE(ERROR, "xc_dom_boot_xen_init failed");
|
||||
goto out;
|
||||
}
|
||||
if ( (ret = xc_dom_parse_image(dom)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_parse_image failed");
|
||||
+ LOGE(ERROR, "xc_dom_parse_image failed");
|
||||
goto out;
|
||||
}
|
||||
if ( (ret = xc_dom_mem_init(dom, info->target_memkb / 1024)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_mem_init failed");
|
||||
+ LOGE(ERROR, "xc_dom_mem_init failed");
|
||||
goto out;
|
||||
}
|
||||
if ( (ret = xc_dom_boot_mem_init(dom)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_boot_mem_init failed");
|
||||
+ LOGE(ERROR, "xc_dom_boot_mem_init failed");
|
||||
goto out;
|
||||
}
|
||||
if ( (ret = xc_dom_build_image(dom)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_build_image failed");
|
||||
+ LOGE(ERROR, "xc_dom_build_image failed");
|
||||
goto out;
|
||||
}
|
||||
if ( (ret = xc_dom_boot_image(dom)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_boot_image failed");
|
||||
+ LOGE(ERROR, "xc_dom_boot_image failed");
|
||||
goto out;
|
||||
}
|
||||
if ( (ret = xc_dom_gnttab_init(dom)) != 0 ) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xc_dom_gnttab_init failed");
|
||||
+ LOGE(ERROR, "xc_dom_gnttab_init failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -683,8 +681,7 @@ int libxl__qemu_traditional_cmd(libxl__g
|
||||
const char *cmd)
|
||||
{
|
||||
char *path = NULL;
|
||||
- path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/command",
|
||||
- domid);
|
||||
+ path = GCSPRINTF("/local/domain/0/device-model/%d/command", domid);
|
||||
return libxl__xs_write(gc, XBT_NULL, path, "%s", cmd);
|
||||
}
|
||||
|
||||
@@ -701,8 +698,7 @@ struct libxl__physmap_info {
|
||||
static inline char *restore_helper(libxl__gc *gc, uint32_t domid,
|
||||
uint64_t phys_offset, char *node)
|
||||
{
|
||||
- return libxl__sprintf(gc,
|
||||
- "/local/domain/0/device-model/%d/physmap/%"PRIx64"/%s",
|
||||
+ return GCSPRINTF("/local/domain/0/device-model/%d/physmap/%"PRIx64"/%s",
|
||||
domid, phys_offset, node);
|
||||
}
|
||||
|
||||
@@ -712,7 +708,6 @@ int libxl__toolstack_restore(uint32_t do
|
||||
libxl__save_helper_state *shs = user;
|
||||
libxl__domain_create_state *dcs = CONTAINER_OF(shs, *dcs, shs);
|
||||
STATE_AO_GC(dcs->ao);
|
||||
- libxl_ctx *ctx = CTX;
|
||||
int i, ret;
|
||||
const uint8_t *ptr = buf;
|
||||
uint32_t count = 0, version = 0;
|
||||
@@ -722,7 +717,7 @@ int libxl__toolstack_restore(uint32_t do
|
||||
LOG(DEBUG,"domain=%"PRIu32" toolstack data size=%"PRIu32, domid, size);
|
||||
|
||||
if (size < sizeof(version) + sizeof(count)) {
|
||||
- LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "wrong size");
|
||||
+ LOG(ERROR, "wrong size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -730,7 +725,7 @@ int libxl__toolstack_restore(uint32_t do
|
||||
ptr += sizeof(version);
|
||||
|
||||
if (version != TOOLSTACK_SAVE_VERSION) {
|
||||
- LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "wrong version");
|
||||
+ LOG(ERROR, "wrong version");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -739,7 +734,7 @@ int libxl__toolstack_restore(uint32_t do
|
||||
|
||||
if (size < sizeof(version) + sizeof(count) +
|
||||
count * (sizeof(struct libxl__physmap_info))) {
|
||||
- LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "wrong size");
|
||||
+ LOG(ERROR, "wrong size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -988,15 +983,13 @@ static void switch_logdirty_done(libxl__
|
||||
int libxl__domain_suspend_device_model(libxl__gc *gc,
|
||||
libxl__domain_suspend_state *dss)
|
||||
{
|
||||
- libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
int ret = 0;
|
||||
uint32_t const domid = dss->domid;
|
||||
const char *const filename = dss->dm_savefile;
|
||||
|
||||
switch (libxl__device_model_version_running(gc, domid)) {
|
||||
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: {
|
||||
- LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
|
||||
- "Saving device model state to %s", filename);
|
||||
+ LOG(DEBUG, "Saving device model state to %s", filename);
|
||||
libxl__qemu_traditional_cmd(gc, domid, "save");
|
||||
libxl__wait_for_device_model(gc, domid, "paused", NULL, NULL, NULL);
|
||||
break;
|
||||
@@ -1172,8 +1165,7 @@ int libxl__domain_suspend_common_callbac
|
||||
static inline char *physmap_path(libxl__gc *gc, uint32_t domid,
|
||||
char *phys_offset, char *node)
|
||||
{
|
||||
- return libxl__sprintf(gc,
|
||||
- "/local/domain/0/device-model/%d/physmap/%s/%s",
|
||||
+ return GCSPRINTF("/local/domain/0/device-model/%d/physmap/%s/%s",
|
||||
domid, phys_offset, node);
|
||||
}
|
||||
|
||||
@@ -1190,7 +1182,7 @@ int libxl__toolstack_save(uint32_t domid
|
||||
char **entries = NULL;
|
||||
struct libxl__physmap_info *pi;
|
||||
|
||||
- entries = libxl__xs_directory(gc, 0, libxl__sprintf(gc,
|
||||
+ entries = libxl__xs_directory(gc, 0, GCSPRINTF(
|
||||
"/local/domain/0/device-model/%d/physmap", domid), &num);
|
||||
count = num;
|
||||
|
||||
@@ -1331,7 +1323,7 @@ void libxl__domain_suspend(libxl__egc *e
|
||||
char *path;
|
||||
char *addr;
|
||||
|
||||
- path = libxl__sprintf(gc, "%s/hvmloader/generation-id-address",
|
||||
+ path = GCSPRINTF("%s/hvmloader/generation-id-address",
|
||||
libxl__xs_get_dompath(gc, domid));
|
||||
addr = libxl__xs_read(gc, XBT_NULL, path);
|
||||
|
||||
@@ -1545,10 +1537,7 @@ static void domain_suspend_done(libxl__e
|
||||
|
||||
char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid)
|
||||
{
|
||||
- char *s = libxl__sprintf(gc, LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid));
|
||||
- if (!s)
|
||||
- LIBXL__LOG(libxl__gc_owner(gc), LIBXL__LOG_ERROR, "cannot allocate for uuid");
|
||||
- return s;
|
||||
+ return GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid));
|
||||
}
|
||||
|
||||
static const char *userdata_path(libxl__gc *gc, uint32_t domid,
|
||||
@@ -1556,34 +1545,27 @@ static const char *userdata_path(libxl__
|
||||
const char *wh)
|
||||
{
|
||||
libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
- char *path, *uuid_string;
|
||||
+ char *uuid_string;
|
||||
libxl_dominfo info;
|
||||
int rc;
|
||||
|
||||
rc = libxl_domain_info(ctx, &info, domid);
|
||||
if (rc) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to find domain info"
|
||||
- " for domain %"PRIu32, domid);
|
||||
+ LOGE(ERROR, "unable to find domain info for domain %"PRIu32, domid);
|
||||
return NULL;
|
||||
}
|
||||
- uuid_string = libxl__sprintf(gc, LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info.uuid));
|
||||
+ uuid_string = GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info.uuid));
|
||||
|
||||
- path = libxl__sprintf(gc, "/var/lib/xen/"
|
||||
- "userdata-%s.%u.%s.%s",
|
||||
- wh, domid, uuid_string, userdata_userid);
|
||||
- if (!path)
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to allocate for"
|
||||
- " userdata path");
|
||||
- return path;
|
||||
+ return GCSPRINTF("/var/lib/xen/userdata-%s.%u.%s.%s",
|
||||
+ wh, domid, uuid_string, userdata_userid);
|
||||
}
|
||||
|
||||
static int userdata_delete(libxl__gc *gc, const char *path)
|
||||
{
|
||||
- libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
int r;
|
||||
r = unlink(path);
|
||||
if (r) {
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "remove failed for %s", path);
|
||||
+ LOGE(ERROR, "remove failed for %s", path);
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
@@ -1591,7 +1573,6 @@ static int userdata_delete(libxl__gc *gc
|
||||
|
||||
void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid)
|
||||
{
|
||||
- libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
const char *pattern;
|
||||
glob_t gl;
|
||||
int r, i;
|
||||
@@ -1607,7 +1588,7 @@ void libxl__userdata_destroyall(libxl__g
|
||||
if (r == GLOB_NOMATCH)
|
||||
goto out;
|
||||
if (r)
|
||||
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "glob failed for %s", pattern);
|
||||
+ LOGE(ERROR, "glob failed for %s", pattern);
|
||||
|
||||
for (i=0; i<gl.gl_pathc; i++) {
|
||||
userdata_delete(gc, gl.gl_pathv[i]);
|
@ -1,108 +0,0 @@
|
||||
References: FATE#313605
|
||||
|
||||
# HG changeset patch
|
||||
# User Jiongxi Li <jiongxi.li@intel.com>
|
||||
# Date 1361176078 -3600
|
||||
# Node ID 4c3355d776e115f979fd2abc135bb77ba710f0d4
|
||||
# Parent 217a4fc4cd46e8de06f2f43eed727838891e9398
|
||||
x86/VMX: fix live migration while enabling APICV
|
||||
|
||||
SVI should be restored in case guest is processing virtual interrupt
|
||||
while saveing a domain state. Otherwise SVI would be missed when
|
||||
virtual interrupt delivery is enabled.
|
||||
|
||||
Signed-off-by: Jiongxi Li <jiongxi.li@intel.com>
|
||||
Acked-by: Eddie Dong <eddie.dong@intel.com>
|
||||
Acked-by: Jun Nakajima <jun.nakajima@intel.com>
|
||||
Committed-by: Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
--- a/xen/arch/x86/hvm/vlapic.c
|
||||
+++ b/xen/arch/x86/hvm/vlapic.c
|
||||
@@ -1194,6 +1194,9 @@ static int lapic_load_regs(struct domain
|
||||
if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 )
|
||||
return -EINVAL;
|
||||
|
||||
+ if ( hvm_funcs.process_isr )
|
||||
+ hvm_funcs.process_isr(vlapic_find_highest_isr(s), v);
|
||||
+
|
||||
vlapic_adjust_i8259_target(d);
|
||||
lapic_rearm(s);
|
||||
return 0;
|
||||
--- a/xen/arch/x86/hvm/vmx/intr.c
|
||||
+++ b/xen/arch/x86/hvm/vmx/intr.c
|
||||
@@ -290,8 +290,8 @@ void vmx_intr_assist(void)
|
||||
vmx_set_eoi_exit_bitmap(v, pt_vector);
|
||||
|
||||
/* we need update the RVI field */
|
||||
- status &= ~(unsigned long)0x0FF;
|
||||
- status |= (unsigned long)0x0FF &
|
||||
+ status &= ~VMX_GUEST_INTR_STATUS_SUBFIELD_BITMASK;
|
||||
+ status |= VMX_GUEST_INTR_STATUS_SUBFIELD_BITMASK &
|
||||
intack.vector;
|
||||
__vmwrite(GUEST_INTR_STATUS, status);
|
||||
if (v->arch.hvm_vmx.eoi_exitmap_changed) {
|
||||
--- a/xen/arch/x86/hvm/vmx/vmx.c
|
||||
+++ b/xen/arch/x86/hvm/vmx/vmx.c
|
||||
@@ -1523,6 +1523,29 @@ static int vmx_virtual_intr_delivery_ena
|
||||
return cpu_has_vmx_virtual_intr_delivery;
|
||||
}
|
||||
|
||||
+static void vmx_process_isr(int isr, struct vcpu *v)
|
||||
+{
|
||||
+ unsigned long status;
|
||||
+ u8 old;
|
||||
+
|
||||
+ if ( !cpu_has_vmx_virtual_intr_delivery )
|
||||
+ return;
|
||||
+
|
||||
+ if ( isr < 0 )
|
||||
+ isr = 0;
|
||||
+
|
||||
+ vmx_vmcs_enter(v);
|
||||
+ status = __vmread(GUEST_INTR_STATUS);
|
||||
+ old = status >> VMX_GUEST_INTR_STATUS_SVI_OFFSET;
|
||||
+ if ( isr != old )
|
||||
+ {
|
||||
+ status &= VMX_GUEST_INTR_STATUS_SUBFIELD_BITMASK;
|
||||
+ status |= isr << VMX_GUEST_INTR_STATUS_SVI_OFFSET;
|
||||
+ __vmwrite(GUEST_INTR_STATUS, status);
|
||||
+ }
|
||||
+ vmx_vmcs_exit(v);
|
||||
+}
|
||||
+
|
||||
static struct hvm_function_table __read_mostly vmx_function_table = {
|
||||
.name = "VMX",
|
||||
.cpu_up_prepare = vmx_cpu_up_prepare,
|
||||
@@ -1571,7 +1594,8 @@ static struct hvm_function_table __read_
|
||||
.nhvm_intr_blocked = nvmx_intr_blocked,
|
||||
.nhvm_domain_relinquish_resources = nvmx_domain_relinquish_resources,
|
||||
.update_eoi_exit_bitmap = vmx_update_eoi_exit_bitmap,
|
||||
- .virtual_intr_delivery_enabled = vmx_virtual_intr_delivery_enabled
|
||||
+ .virtual_intr_delivery_enabled = vmx_virtual_intr_delivery_enabled,
|
||||
+ .process_isr = vmx_process_isr,
|
||||
};
|
||||
|
||||
struct hvm_function_table * __init start_vmx(void)
|
||||
--- a/xen/include/asm-x86/hvm/hvm.h
|
||||
+++ b/xen/include/asm-x86/hvm/hvm.h
|
||||
@@ -184,6 +184,7 @@ struct hvm_function_table {
|
||||
/* Virtual interrupt delivery */
|
||||
void (*update_eoi_exit_bitmap)(struct vcpu *v, u8 vector, u8 trig);
|
||||
int (*virtual_intr_delivery_enabled)(void);
|
||||
+ void (*process_isr)(int isr, struct vcpu *v);
|
||||
};
|
||||
|
||||
extern struct hvm_function_table hvm_funcs;
|
||||
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
@@ -246,6 +246,10 @@ extern bool_t cpu_has_vmx_ins_outs_instr
|
||||
#define VMX_INTR_SHADOW_SMI 0x00000004
|
||||
#define VMX_INTR_SHADOW_NMI 0x00000008
|
||||
|
||||
+/* Guest interrupt status */
|
||||
+#define VMX_GUEST_INTR_STATUS_SUBFIELD_BITMASK 0x0FF
|
||||
+#define VMX_GUEST_INTR_STATUS_SVI_OFFSET 8
|
||||
+
|
||||
/* VMCS field encodings. */
|
||||
enum vmcs_field {
|
||||
VIRTUAL_PROCESSOR_ID = 0x00000000,
|
@ -1,248 +0,0 @@
|
||||
References: FATE#313605
|
||||
|
||||
# HG changeset patch
|
||||
# User Jiongxi Li <jiongxi.li@intel.com>
|
||||
# Date 1361176458 -3600
|
||||
# Node ID 45d59b822ed187c535b127679e32853b148ed411
|
||||
# Parent 4c3355d776e115f979fd2abc135bb77ba710f0d4
|
||||
x86/VMX: fix VMCS setting for x2APIC mode guest while enabling APICV
|
||||
|
||||
The "APIC-register virtualization" and "virtual-interrupt deliver"
|
||||
VM-execution control has no effect on the behavior of RDMSR/WRMSR if
|
||||
the "virtualize x2APIC mode" VM-execution control is 0.
|
||||
When guest uses x2APIC mode, we should enable "virtualize x2APIC mode"
|
||||
for APICV first.
|
||||
|
||||
Signed-off-by: Jiongxi Li <jiongxi.li@intel.com>
|
||||
Acked-by: Eddie Dong <eddie.dong@intel.com>
|
||||
Acked-by: Jun Nakajima <jun.nakajima@intel.com>
|
||||
Committed-by: Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmcs.c
|
||||
@@ -194,7 +194,8 @@ static int vmx_init_vmcs_config(void)
|
||||
*/
|
||||
if ( _vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW )
|
||||
opt |= SECONDARY_EXEC_APIC_REGISTER_VIRT |
|
||||
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
|
||||
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
|
||||
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
|
||||
|
||||
|
||||
_vmx_secondary_exec_control = adjust_vmx_controls(
|
||||
@@ -673,19 +674,59 @@ void vmx_disable_intercept_for_msr(struc
|
||||
*/
|
||||
if ( msr <= 0x1fff )
|
||||
{
|
||||
- if (type & MSR_TYPE_R)
|
||||
- __clear_bit(msr, msr_bitmap + 0x000/BYTES_PER_LONG); /* read-low */
|
||||
- if (type & MSR_TYPE_W)
|
||||
- __clear_bit(msr, msr_bitmap + 0x800/BYTES_PER_LONG); /* write-low */
|
||||
+ if ( type & MSR_TYPE_R )
|
||||
+ clear_bit(msr, msr_bitmap + 0x000/BYTES_PER_LONG); /* read-low */
|
||||
+ if ( type & MSR_TYPE_W )
|
||||
+ clear_bit(msr, msr_bitmap + 0x800/BYTES_PER_LONG); /* write-low */
|
||||
}
|
||||
else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) )
|
||||
{
|
||||
msr &= 0x1fff;
|
||||
- if (type & MSR_TYPE_R)
|
||||
- __clear_bit(msr, msr_bitmap + 0x400/BYTES_PER_LONG); /* read-high */
|
||||
- if (type & MSR_TYPE_W)
|
||||
- __clear_bit(msr, msr_bitmap + 0xc00/BYTES_PER_LONG); /* write-high */
|
||||
+ if ( type & MSR_TYPE_R )
|
||||
+ clear_bit(msr, msr_bitmap + 0x400/BYTES_PER_LONG); /* read-high */
|
||||
+ if ( type & MSR_TYPE_W )
|
||||
+ clear_bit(msr, msr_bitmap + 0xc00/BYTES_PER_LONG); /* write-high */
|
||||
}
|
||||
+ else
|
||||
+ HVM_DBG_LOG(DBG_LEVEL_0,
|
||||
+ "msr %x is out of the control range"
|
||||
+ "0x00000000-0x00001fff and 0xc0000000-0xc0001fff"
|
||||
+ "RDMSR or WRMSR will cause a VM exit", msr);
|
||||
+}
|
||||
+
|
||||
+void vmx_enable_intercept_for_msr(struct vcpu *v, u32 msr, int type)
|
||||
+{
|
||||
+ unsigned long *msr_bitmap = v->arch.hvm_vmx.msr_bitmap;
|
||||
+
|
||||
+ /* VMX MSR bitmap supported? */
|
||||
+ if ( msr_bitmap == NULL )
|
||||
+ return;
|
||||
+
|
||||
+ /*
|
||||
+ * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
|
||||
+ * have the write-low and read-high bitmap offsets the wrong way round.
|
||||
+ * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
|
||||
+ */
|
||||
+ if ( msr <= 0x1fff )
|
||||
+ {
|
||||
+ if ( type & MSR_TYPE_R )
|
||||
+ set_bit(msr, msr_bitmap + 0x000/BYTES_PER_LONG); /* read-low */
|
||||
+ if ( type & MSR_TYPE_W )
|
||||
+ set_bit(msr, msr_bitmap + 0x800/BYTES_PER_LONG); /* write-low */
|
||||
+ }
|
||||
+ else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) )
|
||||
+ {
|
||||
+ msr &= 0x1fff;
|
||||
+ if ( type & MSR_TYPE_R )
|
||||
+ set_bit(msr, msr_bitmap + 0x400/BYTES_PER_LONG); /* read-high */
|
||||
+ if ( type & MSR_TYPE_W )
|
||||
+ set_bit(msr, msr_bitmap + 0xc00/BYTES_PER_LONG); /* write-high */
|
||||
+ }
|
||||
+ else
|
||||
+ HVM_DBG_LOG(DBG_LEVEL_0,
|
||||
+ "msr %x is out of the control range"
|
||||
+ "0x00000000-0x00001fff and 0xc0000000-0xc0001fff"
|
||||
+ "RDMSR or WRMSR will cause a VM exit", msr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -751,6 +792,10 @@ static int construct_vmcs(struct vcpu *v
|
||||
vmentry_ctl &= ~VM_ENTRY_LOAD_GUEST_PAT;
|
||||
}
|
||||
|
||||
+ /* Disable Virtualize x2APIC mode by default. */
|
||||
+ v->arch.hvm_vmx.secondary_exec_control &=
|
||||
+ ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
|
||||
+
|
||||
/* Do not enable Monitor Trap Flag unless start single step debug */
|
||||
v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG;
|
||||
|
||||
@@ -787,18 +832,6 @@ static int construct_vmcs(struct vcpu *v
|
||||
vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_EIP, MSR_TYPE_R | MSR_TYPE_W);
|
||||
if ( cpu_has_vmx_pat && paging_mode_hap(d) )
|
||||
vmx_disable_intercept_for_msr(v, MSR_IA32_CR_PAT, MSR_TYPE_R | MSR_TYPE_W);
|
||||
- if ( cpu_has_vmx_apic_reg_virt )
|
||||
- {
|
||||
- int msr;
|
||||
- for (msr = MSR_IA32_APICBASE_MSR; msr <= MSR_IA32_APICBASE_MSR + 0xff; msr++)
|
||||
- vmx_disable_intercept_for_msr(v, msr, MSR_TYPE_R);
|
||||
- }
|
||||
- if ( cpu_has_vmx_virtual_intr_delivery )
|
||||
- {
|
||||
- vmx_disable_intercept_for_msr(v, MSR_IA32_APICTPR_MSR, MSR_TYPE_W);
|
||||
- vmx_disable_intercept_for_msr(v, MSR_IA32_APICEOI_MSR, MSR_TYPE_W);
|
||||
- vmx_disable_intercept_for_msr(v, MSR_IA32_APICSELF_MSR, MSR_TYPE_W);
|
||||
- }
|
||||
}
|
||||
|
||||
/* I/O access bitmap. */
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmx.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/vmx/vmx.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/vmx/vmx.c
|
||||
@@ -2012,18 +2012,63 @@ static void vmx_install_vlapic_mapping(s
|
||||
|
||||
void vmx_vlapic_msr_changed(struct vcpu *v)
|
||||
{
|
||||
+ int virtualize_x2apic_mode;
|
||||
struct vlapic *vlapic = vcpu_vlapic(v);
|
||||
|
||||
- if ( !cpu_has_vmx_virtualize_apic_accesses )
|
||||
+ virtualize_x2apic_mode = ( (cpu_has_vmx_apic_reg_virt ||
|
||||
+ cpu_has_vmx_virtual_intr_delivery) &&
|
||||
+ cpu_has_vmx_virtualize_x2apic_mode );
|
||||
+
|
||||
+ if ( !cpu_has_vmx_virtualize_apic_accesses &&
|
||||
+ !virtualize_x2apic_mode )
|
||||
return;
|
||||
|
||||
vmx_vmcs_enter(v);
|
||||
v->arch.hvm_vmx.secondary_exec_control &=
|
||||
- ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
||||
+ ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
|
||||
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
|
||||
if ( !vlapic_hw_disabled(vlapic) &&
|
||||
(vlapic_base_address(vlapic) == APIC_DEFAULT_PHYS_BASE) )
|
||||
- v->arch.hvm_vmx.secondary_exec_control |=
|
||||
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
||||
+ {
|
||||
+ unsigned int msr;
|
||||
+
|
||||
+ if ( virtualize_x2apic_mode && vlapic_x2apic_mode(vlapic) )
|
||||
+ {
|
||||
+ v->arch.hvm_vmx.secondary_exec_control |=
|
||||
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
|
||||
+ if ( cpu_has_vmx_apic_reg_virt )
|
||||
+ {
|
||||
+ for ( msr = MSR_IA32_APICBASE_MSR;
|
||||
+ msr <= MSR_IA32_APICBASE_MSR + 0xff; msr++ )
|
||||
+ vmx_disable_intercept_for_msr(v, msr, MSR_TYPE_R);
|
||||
+
|
||||
+ vmx_enable_intercept_for_msr(v, MSR_IA32_APICPPR_MSR,
|
||||
+ MSR_TYPE_R);
|
||||
+ vmx_enable_intercept_for_msr(v, MSR_IA32_APICTMICT_MSR,
|
||||
+ MSR_TYPE_R);
|
||||
+ vmx_enable_intercept_for_msr(v, MSR_IA32_APICTMCCT_MSR,
|
||||
+ MSR_TYPE_R);
|
||||
+ }
|
||||
+ if ( cpu_has_vmx_virtual_intr_delivery )
|
||||
+ {
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_APICTPR_MSR,
|
||||
+ MSR_TYPE_W);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_APICEOI_MSR,
|
||||
+ MSR_TYPE_W);
|
||||
+ vmx_disable_intercept_for_msr(v, MSR_IA32_APICSELF_MSR,
|
||||
+ MSR_TYPE_W);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ v->arch.hvm_vmx.secondary_exec_control |=
|
||||
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
||||
+ for ( msr = MSR_IA32_APICBASE_MSR;
|
||||
+ msr <= MSR_IA32_APICBASE_MSR + 0xff; msr++ )
|
||||
+ vmx_enable_intercept_for_msr(v, msr,
|
||||
+ MSR_TYPE_R | MSR_TYPE_W);
|
||||
+ }
|
||||
+ }
|
||||
vmx_update_secondary_exec_control(v);
|
||||
vmx_vmcs_exit(v);
|
||||
}
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||||
@@ -182,6 +182,7 @@ extern u32 vmx_vmentry_control;
|
||||
#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
|
||||
#define SECONDARY_EXEC_ENABLE_EPT 0x00000002
|
||||
#define SECONDARY_EXEC_ENABLE_RDTSCP 0x00000008
|
||||
+#define SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE 0x00000010
|
||||
#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
|
||||
#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
|
||||
#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
|
||||
@@ -239,6 +240,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr
|
||||
(vmx_secondary_exec_control & SECONDARY_EXEC_APIC_REGISTER_VIRT)
|
||||
#define cpu_has_vmx_virtual_intr_delivery \
|
||||
(vmx_secondary_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)
|
||||
+#define cpu_has_vmx_virtualize_x2apic_mode \
|
||||
+ (vmx_secondary_exec_control & SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)
|
||||
|
||||
/* GUEST_INTERRUPTIBILITY_INFO flags. */
|
||||
#define VMX_INTR_SHADOW_STI 0x00000001
|
||||
@@ -414,6 +417,7 @@ enum vmcs_field {
|
||||
#define MSR_TYPE_R 1
|
||||
#define MSR_TYPE_W 2
|
||||
void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type);
|
||||
+void vmx_enable_intercept_for_msr(struct vcpu *v, u32 msr, int type);
|
||||
int vmx_read_guest_msr(u32 msr, u64 *val);
|
||||
int vmx_write_guest_msr(u32 msr, u64 val);
|
||||
int vmx_add_guest_msr(u32 msr);
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/msr-index.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/msr-index.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/msr-index.h
|
||||
@@ -295,7 +295,10 @@
|
||||
#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
|
||||
#define MSR_IA32_APICBASE_MSR 0x800
|
||||
#define MSR_IA32_APICTPR_MSR 0x808
|
||||
+#define MSR_IA32_APICPPR_MSR 0x80a
|
||||
#define MSR_IA32_APICEOI_MSR 0x80b
|
||||
+#define MSR_IA32_APICTMICT_MSR 0x838
|
||||
+#define MSR_IA32_APICTMCCT_MSR 0x839
|
||||
#define MSR_IA32_APICSELF_MSR 0x83f
|
||||
|
||||
#define MSR_IA32_UCODE_WRITE 0x00000079
|
@ -1,43 +0,0 @@
|
||||
changeset: 26675:3eb62c576a1a
|
||||
user: Olaf Hering <olaf@aepfle.de>
|
||||
date: Wed Feb 27 14:16:36 2013 +0000
|
||||
files: tools/libxc/xtl_logger_stdio.c
|
||||
description:
|
||||
tools/xentoollog: update tty detection in stdiostream_progress
|
||||
|
||||
As suggested by IanJ:
|
||||
Check isatty only once to preserve the errno of ->progress users, and to
|
||||
reduce the noice in strace output.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
|
||||
diff -r 4b25c1e6cfbb -r 3eb62c576a1a tools/libxc/xtl_logger_stdio.c
|
||||
--- a/tools/libxc/xtl_logger_stdio.c Wed Feb 27 11:16:47 2013 +0000
|
||||
+++ b/tools/libxc/xtl_logger_stdio.c Wed Feb 27 14:16:36 2013 +0000
|
||||
@@ -35,6 +35,7 @@ struct xentoollog_logger_stdiostream {
|
||||
xentoollog_level min_level;
|
||||
unsigned flags;
|
||||
int progress_erase_len, progress_last_percent;
|
||||
+ int tty;
|
||||
};
|
||||
|
||||
static void progress_erase(xentoollog_logger_stdiostream *lg) {
|
||||
@@ -118,7 +119,7 @@ static void stdiostream_progress(struct
|
||||
|
||||
lg->progress_last_percent = percent;
|
||||
|
||||
- if (isatty(fileno(lg->f)) <= 0) {
|
||||
+ if (!lg->tty) {
|
||||
stdiostream_message(logger_in, this_level, context,
|
||||
"%s: %lu/%lu %3d%%",
|
||||
doing_what, done, total, percent);
|
||||
@@ -166,6 +167,7 @@ xentoollog_logger_stdiostream *xtl_creat
|
||||
newlogger.f = f;
|
||||
newlogger.min_level = min_level;
|
||||
newlogger.flags = flags;
|
||||
+ newlogger.tty = isatty(fileno(newlogger.f)) > 0;
|
||||
|
||||
if (newlogger.flags & XTL_STDIOSTREAM_SHOW_DATE) tzset();
|
||||
|
@ -1,144 +0,0 @@
|
||||
# Commit 9aa356bc9f7533c3cb7f02c823f532532876d444
|
||||
# Date 2013-04-19 12:29:01 +0200
|
||||
# Author Ben Guthro <benjamin.guthro@citrix.com>
|
||||
# Committer Jan Beulich <jbeulich@suse.com>
|
||||
x86/S3: Fix cpu pool scheduling after suspend/resume
|
||||
|
||||
This review is another S3 scheduler problem with the system_state
|
||||
variable introduced with the following changeset:
|
||||
http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=269f543ea750ed567d18f2e819e5d5ce58eda5c5
|
||||
|
||||
Specifically, the cpu_callback function that takes the CPU down during
|
||||
suspend, and back up during resume. We were seeing situations where,
|
||||
after S3, only CPU0 was in cpupool0. Guest performance suffered
|
||||
greatly, since all vcpus were only on a single pcpu. Guests under high
|
||||
CPU load showed the problem much more quickly than an idle guest.
|
||||
|
||||
Removing this if condition forces the CPUs to go through the expected
|
||||
online/offline state, and be properly scheduled after S3.
|
||||
|
||||
This also includes a necessary partial change proposed earlier by
|
||||
Tomasz Wroblewski here:
|
||||
http://lists.xen.org/archives/html/xen-devel/2013-01/msg02206.html
|
||||
|
||||
It should also resolve the issues discussed in this thread:
|
||||
http://lists.xen.org/archives/html/xen-devel/2012-11/msg01801.html
|
||||
|
||||
Signed-off-by: Ben Guthro <benjamin.guthro@citrix.com>
|
||||
Acked-by: Juergen Gross <juergen.gross@ts.fujitsu.com>
|
||||
|
||||
--- a/xen/common/cpupool.c
|
||||
+++ b/xen/common/cpupool.c
|
||||
@@ -41,16 +41,28 @@ static struct cpupool *alloc_cpupool_str
|
||||
{
|
||||
struct cpupool *c = xzalloc(struct cpupool);
|
||||
|
||||
- if ( c && zalloc_cpumask_var(&c->cpu_valid) )
|
||||
- return c;
|
||||
- xfree(c);
|
||||
- return NULL;
|
||||
+ if ( !c || !zalloc_cpumask_var(&c->cpu_valid) )
|
||||
+ {
|
||||
+ xfree(c);
|
||||
+ c = NULL;
|
||||
+ }
|
||||
+ else if ( !zalloc_cpumask_var(&c->cpu_suspended) )
|
||||
+ {
|
||||
+ free_cpumask_var(c->cpu_valid);
|
||||
+ xfree(c);
|
||||
+ c = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return c;
|
||||
}
|
||||
|
||||
static void free_cpupool_struct(struct cpupool *c)
|
||||
{
|
||||
if ( c )
|
||||
+ {
|
||||
+ free_cpumask_var(c->cpu_suspended);
|
||||
free_cpumask_var(c->cpu_valid);
|
||||
+ }
|
||||
xfree(c);
|
||||
}
|
||||
|
||||
@@ -417,14 +429,32 @@ void cpupool_rm_domain(struct domain *d)
|
||||
|
||||
/*
|
||||
* called to add a new cpu to pool admin
|
||||
- * we add a hotplugged cpu to the cpupool0 to be able to add it to dom0
|
||||
+ * we add a hotplugged cpu to the cpupool0 to be able to add it to dom0,
|
||||
+ * unless we are resuming from S3, in which case we put the cpu back
|
||||
+ * in the cpupool it was in prior to suspend.
|
||||
*/
|
||||
static void cpupool_cpu_add(unsigned int cpu)
|
||||
{
|
||||
spin_lock(&cpupool_lock);
|
||||
cpumask_clear_cpu(cpu, &cpupool_locked_cpus);
|
||||
cpumask_set_cpu(cpu, &cpupool_free_cpus);
|
||||
- cpupool_assign_cpu_locked(cpupool0, cpu);
|
||||
+
|
||||
+ if ( system_state == SYS_STATE_resume )
|
||||
+ {
|
||||
+ struct cpupool **c;
|
||||
+
|
||||
+ for_each_cpupool(c)
|
||||
+ {
|
||||
+ if ( cpumask_test_cpu(cpu, (*c)->cpu_suspended ) )
|
||||
+ {
|
||||
+ cpupool_assign_cpu_locked(*c, cpu);
|
||||
+ cpumask_clear_cpu(cpu, (*c)->cpu_suspended);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ( cpumask_test_cpu(cpu, &cpupool_free_cpus) )
|
||||
+ cpupool_assign_cpu_locked(cpupool0, cpu);
|
||||
spin_unlock(&cpupool_lock);
|
||||
}
|
||||
|
||||
@@ -436,7 +466,7 @@ static void cpupool_cpu_add(unsigned int
|
||||
static int cpupool_cpu_remove(unsigned int cpu)
|
||||
{
|
||||
int ret = 0;
|
||||
-
|
||||
+
|
||||
spin_lock(&cpupool_lock);
|
||||
if ( !cpumask_test_cpu(cpu, cpupool0->cpu_valid))
|
||||
ret = -EBUSY;
|
||||
@@ -633,9 +663,14 @@ static int cpu_callback(
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
int rc = 0;
|
||||
|
||||
- if ( (system_state == SYS_STATE_suspend) ||
|
||||
- (system_state == SYS_STATE_resume) )
|
||||
- goto out;
|
||||
+ if ( system_state == SYS_STATE_suspend )
|
||||
+ {
|
||||
+ struct cpupool **c;
|
||||
+
|
||||
+ for_each_cpupool(c)
|
||||
+ if ( cpumask_test_cpu(cpu, (*c)->cpu_valid ) )
|
||||
+ cpumask_set_cpu(cpu, (*c)->cpu_suspended);
|
||||
+ }
|
||||
|
||||
switch ( action )
|
||||
{
|
||||
@@ -650,7 +685,6 @@ static int cpu_callback(
|
||||
break;
|
||||
}
|
||||
|
||||
-out:
|
||||
return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
|
||||
}
|
||||
|
||||
--- a/xen/include/xen/sched-if.h
|
||||
+++ b/xen/include/xen/sched-if.h
|
||||
@@ -199,6 +199,7 @@ struct cpupool
|
||||
{
|
||||
int cpupool_id;
|
||||
cpumask_var_t cpu_valid; /* all cpus assigned to pool */
|
||||
+ cpumask_var_t cpu_suspended; /* cpus in S3 that should be in this pool */
|
||||
struct cpupool *next;
|
||||
unsigned int n_dom;
|
||||
struct scheduler *sched;
|
@ -1,142 +0,0 @@
|
||||
References: FATE#314499, FATE#314509
|
||||
|
||||
# Commit 9be8a4447103d92843fcfeaad8be42408c90e9a9
|
||||
# Date 2013-04-22 13:58:01 +0200
|
||||
# Author Jan Beulich <jbeulich@suse.com>
|
||||
# Committer Jan Beulich <jbeulich@suse.com>
|
||||
x86/EFI: pass boot services variable info to runtime code
|
||||
|
||||
EFI variables can be flagged as being accessible only within boot services.
|
||||
This makes it awkward for us to figure out how much space they use at
|
||||
runtime. In theory we could figure this out by simply comparing the results
|
||||
from QueryVariableInfo() to the space used by all of our variables, but
|
||||
that fails if the platform doesn't garbage collect on every boot. Thankfully,
|
||||
calling QueryVariableInfo() while still inside boot services gives a more
|
||||
reliable answer. This patch passes that information from the EFI boot stub
|
||||
up to the efi platform code.
|
||||
|
||||
Based on a similarly named Linux patch by Matthew Garrett <matthew.garrett@nebula.com>.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
|
||||
--- a/xen/arch/x86/efi/boot.c
|
||||
+++ b/xen/arch/x86/efi/boot.c
|
||||
@@ -1128,6 +1128,23 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||||
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
|
||||
dmi_efi_get_table((void *)(long)efi.smbios);
|
||||
|
||||
+ /* Get snapshot of variable store parameters. */
|
||||
+ status = efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
|
||||
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
+ EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
+ &efi_boot_max_var_store_size,
|
||||
+ &efi_boot_remain_var_store_size,
|
||||
+ &efi_boot_max_var_size);
|
||||
+ if ( EFI_ERROR(status) )
|
||||
+ {
|
||||
+ efi_boot_max_var_store_size = 0;
|
||||
+ efi_boot_remain_var_store_size = 0;
|
||||
+ efi_boot_max_var_size = status;
|
||||
+ PrintStr(L"Warning: Could not query variable store: ");
|
||||
+ DisplayUint(status, 0);
|
||||
+ PrintStr(newline);
|
||||
+ }
|
||||
+
|
||||
/* Allocate space for trampoline (in first Mb). */
|
||||
cfg.addr = 0x100000;
|
||||
cfg.size = trampoline_end - trampoline_start;
|
||||
--- a/xen/arch/x86/efi/efi.h
|
||||
+++ b/xen/arch/x86/efi/efi.h
|
||||
@@ -22,5 +22,8 @@ extern void *efi_memmap;
|
||||
|
||||
extern l4_pgentry_t *efi_l4_pgtable;
|
||||
|
||||
+extern UINT64 efi_boot_max_var_store_size, efi_boot_remain_var_store_size,
|
||||
+ efi_boot_max_var_size;
|
||||
+
|
||||
unsigned long efi_rs_enter(void);
|
||||
void efi_rs_leave(unsigned long);
|
||||
--- a/xen/arch/x86/efi/runtime.c
|
||||
+++ b/xen/arch/x86/efi/runtime.c
|
||||
@@ -28,6 +28,10 @@ UINTN __read_mostly efi_memmap_size;
|
||||
UINTN __read_mostly efi_mdesc_size;
|
||||
void *__read_mostly efi_memmap;
|
||||
|
||||
+UINT64 __read_mostly efi_boot_max_var_store_size;
|
||||
+UINT64 __read_mostly efi_boot_remain_var_store_size;
|
||||
+UINT64 __read_mostly efi_boot_max_var_size;
|
||||
+
|
||||
struct efi __read_mostly efi = {
|
||||
.acpi = EFI_INVALID_TABLE_ADDR,
|
||||
.acpi20 = EFI_INVALID_TABLE_ADDR,
|
||||
@@ -446,6 +450,35 @@ int efi_runtime_call(struct xenpf_efi_ru
|
||||
break;
|
||||
|
||||
case XEN_EFI_query_variable_info:
|
||||
+ if ( op->misc & ~XEN_EFI_VARINFO_BOOT_SNAPSHOT )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if ( op->misc & XEN_EFI_VARINFO_BOOT_SNAPSHOT )
|
||||
+ {
|
||||
+ if ( (op->u.query_variable_info.attr
|
||||
+ & ~EFI_VARIABLE_APPEND_WRITE) !=
|
||||
+ (EFI_VARIABLE_NON_VOLATILE |
|
||||
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
+ EFI_VARIABLE_RUNTIME_ACCESS) )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ op->u.query_variable_info.max_store_size =
|
||||
+ efi_boot_max_var_store_size;
|
||||
+ op->u.query_variable_info.remain_store_size =
|
||||
+ efi_boot_remain_var_store_size;
|
||||
+ if ( efi_boot_max_var_store_size )
|
||||
+ {
|
||||
+ op->u.query_variable_info.max_size = efi_boot_max_var_size;
|
||||
+ status = EFI_SUCCESS;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ op->u.query_variable_info.max_size = 0;
|
||||
+ status = efi_boot_max_var_size;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
cr3 = efi_rs_enter();
|
||||
if ( (efi_rs->Hdr.Revision >> 16) < 2 )
|
||||
{
|
||||
@@ -462,6 +495,9 @@ int efi_runtime_call(struct xenpf_efi_ru
|
||||
|
||||
case XEN_EFI_query_capsule_capabilities:
|
||||
case XEN_EFI_update_capsule:
|
||||
+ if ( op->misc )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
cr3 = efi_rs_enter();
|
||||
if ( (efi_rs->Hdr.Revision >> 16) < 2 )
|
||||
{
|
||||
--- a/xen/include/efi/efiapi.h
|
||||
+++ b/xen/include/efi/efiapi.h
|
||||
@@ -213,6 +213,10 @@ VOID
|
||||
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
|
||||
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
|
||||
#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
|
||||
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
|
||||
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
|
||||
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
|
||||
+#define EFI_VARIABLE_APPEND_WRITE 0x00000040
|
||||
|
||||
// Variable size limitation
|
||||
#define EFI_MAXIMUM_VARIABLE_SIZE 1024
|
||||
--- a/xen/include/public/platform.h
|
||||
+++ b/xen/include/public/platform.h
|
||||
@@ -184,6 +184,7 @@ struct xenpf_efi_runtime_call {
|
||||
struct xenpf_efi_guid vendor_guid;
|
||||
} get_next_variable_name;
|
||||
|
||||
+#define XEN_EFI_VARINFO_BOOT_SNAPSHOT 0x00000001
|
||||
struct {
|
||||
uint32_t attr;
|
||||
uint64_t max_store_size;
|
@ -1,23 +0,0 @@
|
||||
# Commit a7ac9597a7fc6ca934957eb78b41e26638281953
|
||||
# Date 2013-04-29 11:27:54 +0200
|
||||
# Author Jan Beulich <jbeulich@suse.com>
|
||||
# Committer Jan Beulich <jbeulich@suse.com>
|
||||
x86/EFI: fix runtime call status for compat mode Dom0
|
||||
|
||||
The top two bits (indicating error/warning classification) need to
|
||||
remain the top two bits.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Keir Fraser <keir@xen.org>
|
||||
|
||||
--- a/xen/arch/x86/efi/runtime.c
|
||||
+++ b/xen/arch/x86/efi/runtime.c
|
||||
@@ -513,7 +513,7 @@ int efi_runtime_call(struct xenpf_efi_ru
|
||||
#ifndef COMPAT
|
||||
op->status = status;
|
||||
#else
|
||||
- op->status = (status & 0x3fffffff) | (status >> 62);
|
||||
+ op->status = (status & 0x3fffffff) | ((status >> 32) & 0xc0000000);
|
||||
#endif
|
||||
|
||||
return rc;
|
@ -1,13 +0,0 @@
|
||||
Index: xen-4.2.2-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/tools/python/xen/xend/XendDomainInfo.py
|
||||
+++ xen-4.2.2-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
@@ -2985,7 +2985,7 @@ class XendDomainInfo:
|
||||
|
||||
self.guest_bitsize = self.image.getBitSize()
|
||||
# Make sure there's enough RAM available for the domain
|
||||
- balloon.free(memory + shadow + vtd_mem, self)
|
||||
+ balloon.free(memory + shadow + vtd_mem + 512, self)
|
||||
|
||||
# Set up the shadow memory
|
||||
shadow_cur = xc.shadow_mem_control(self.domid, shadow / 1024)
|
@ -1,262 +0,0 @@
|
||||
x86: make vcpu_destroy_pagetables() preemptible
|
||||
|
||||
... as it may take significant amounts of time.
|
||||
|
||||
The function, being moved to mm.c as the better home for it anyway, and
|
||||
to avoid having to make a new helper function there non-static, is
|
||||
given a "preemptible" parameter temporarily (until, in a subsequent
|
||||
patch, its other caller is also being made capable of dealing with
|
||||
preemption).
|
||||
|
||||
This is part of CVE-2013-1918 / XSA-45.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/domain.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/domain.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/domain.c
|
||||
@@ -73,8 +73,6 @@ void (*dead_idle) (void) __read_mostly =
|
||||
static void paravirt_ctxt_switch_from(struct vcpu *v);
|
||||
static void paravirt_ctxt_switch_to(struct vcpu *v);
|
||||
|
||||
-static void vcpu_destroy_pagetables(struct vcpu *v);
|
||||
-
|
||||
static void default_idle(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
@@ -1058,7 +1056,7 @@ void arch_vcpu_reset(struct vcpu *v)
|
||||
if ( !is_hvm_vcpu(v) )
|
||||
{
|
||||
destroy_gdt(v);
|
||||
- vcpu_destroy_pagetables(v);
|
||||
+ vcpu_destroy_pagetables(v, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2069,63 +2067,6 @@ static int relinquish_memory(
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void vcpu_destroy_pagetables(struct vcpu *v)
|
||||
-{
|
||||
- struct domain *d = v->domain;
|
||||
- unsigned long pfn;
|
||||
-
|
||||
-#ifdef __x86_64__
|
||||
- if ( is_pv_32on64_vcpu(v) )
|
||||
- {
|
||||
- pfn = l4e_get_pfn(*(l4_pgentry_t *)
|
||||
- __va(pagetable_get_paddr(v->arch.guest_table)));
|
||||
-
|
||||
- if ( pfn != 0 )
|
||||
- {
|
||||
- if ( paging_mode_refcounts(d) )
|
||||
- put_page(mfn_to_page(pfn));
|
||||
- else
|
||||
- put_page_and_type(mfn_to_page(pfn));
|
||||
- }
|
||||
-
|
||||
- l4e_write(
|
||||
- (l4_pgentry_t *)__va(pagetable_get_paddr(v->arch.guest_table)),
|
||||
- l4e_empty());
|
||||
-
|
||||
- v->arch.cr3 = 0;
|
||||
- return;
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
- pfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
- if ( pfn != 0 )
|
||||
- {
|
||||
- if ( paging_mode_refcounts(d) )
|
||||
- put_page(mfn_to_page(pfn));
|
||||
- else
|
||||
- put_page_and_type(mfn_to_page(pfn));
|
||||
- v->arch.guest_table = pagetable_null();
|
||||
- }
|
||||
-
|
||||
-#ifdef __x86_64__
|
||||
- /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */
|
||||
- pfn = pagetable_get_pfn(v->arch.guest_table_user);
|
||||
- if ( pfn != 0 )
|
||||
- {
|
||||
- if ( !is_pv_32bit_vcpu(v) )
|
||||
- {
|
||||
- if ( paging_mode_refcounts(d) )
|
||||
- put_page(mfn_to_page(pfn));
|
||||
- else
|
||||
- put_page_and_type(mfn_to_page(pfn));
|
||||
- }
|
||||
- v->arch.guest_table_user = pagetable_null();
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
- v->arch.cr3 = 0;
|
||||
-}
|
||||
-
|
||||
int domain_relinquish_resources(struct domain *d)
|
||||
{
|
||||
int ret;
|
||||
@@ -2143,7 +2084,11 @@ int domain_relinquish_resources(struct d
|
||||
|
||||
/* Drop the in-use references to page-table bases. */
|
||||
for_each_vcpu ( d, v )
|
||||
- vcpu_destroy_pagetables(v);
|
||||
+ {
|
||||
+ ret = vcpu_destroy_pagetables(v, 1);
|
||||
+ if ( ret )
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
if ( !is_hvm_domain(d) )
|
||||
{
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/mm.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
@@ -2825,6 +2825,82 @@ static void put_superpage(unsigned long
|
||||
|
||||
#endif
|
||||
|
||||
+static int put_old_guest_table(struct vcpu *v)
|
||||
+{
|
||||
+ int rc;
|
||||
+
|
||||
+ if ( !v->arch.old_guest_table )
|
||||
+ return 0;
|
||||
+
|
||||
+ switch ( rc = put_page_and_type_preemptible(v->arch.old_guest_table, 1) )
|
||||
+ {
|
||||
+ case -EINTR:
|
||||
+ case -EAGAIN:
|
||||
+ return -EAGAIN;
|
||||
+ }
|
||||
+
|
||||
+ v->arch.old_guest_table = NULL;
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+int vcpu_destroy_pagetables(struct vcpu *v, bool_t preemptible)
|
||||
+{
|
||||
+ unsigned long mfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
+ struct page_info *page;
|
||||
+ int rc = put_old_guest_table(v);
|
||||
+
|
||||
+ if ( rc )
|
||||
+ return rc;
|
||||
+
|
||||
+#ifdef __x86_64__
|
||||
+ if ( is_pv_32on64_vcpu(v) )
|
||||
+ mfn = l4e_get_pfn(*(l4_pgentry_t *)mfn_to_virt(mfn));
|
||||
+#endif
|
||||
+
|
||||
+ if ( mfn )
|
||||
+ {
|
||||
+ page = mfn_to_page(mfn);
|
||||
+ if ( paging_mode_refcounts(v->domain) )
|
||||
+ put_page(page);
|
||||
+ else
|
||||
+ rc = put_page_and_type_preemptible(page, preemptible);
|
||||
+ }
|
||||
+
|
||||
+#ifdef __x86_64__
|
||||
+ if ( is_pv_32on64_vcpu(v) )
|
||||
+ {
|
||||
+ if ( !rc )
|
||||
+ l4e_write(
|
||||
+ (l4_pgentry_t *)__va(pagetable_get_paddr(v->arch.guest_table)),
|
||||
+ l4e_empty());
|
||||
+ }
|
||||
+ else
|
||||
+#endif
|
||||
+ if ( !rc )
|
||||
+ {
|
||||
+ v->arch.guest_table = pagetable_null();
|
||||
+
|
||||
+#ifdef __x86_64__
|
||||
+ /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */
|
||||
+ mfn = pagetable_get_pfn(v->arch.guest_table_user);
|
||||
+ if ( mfn )
|
||||
+ {
|
||||
+ page = mfn_to_page(mfn);
|
||||
+ if ( paging_mode_refcounts(v->domain) )
|
||||
+ put_page(page);
|
||||
+ else
|
||||
+ rc = put_page_and_type_preemptible(page, preemptible);
|
||||
+ }
|
||||
+ if ( !rc )
|
||||
+ v->arch.guest_table_user = pagetable_null();
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ v->arch.cr3 = 0;
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
|
||||
int new_guest_cr3(unsigned long mfn)
|
||||
{
|
||||
@@ -3011,12 +3087,21 @@ long do_mmuext_op(
|
||||
unsigned int foreigndom)
|
||||
{
|
||||
struct mmuext_op op;
|
||||
- int rc = 0, i = 0, okay;
|
||||
unsigned long type;
|
||||
- unsigned int done = 0;
|
||||
+ unsigned int i = 0, done = 0;
|
||||
struct vcpu *curr = current;
|
||||
struct domain *d = curr->domain;
|
||||
struct domain *pg_owner;
|
||||
+ int okay, rc = put_old_guest_table(curr);
|
||||
+
|
||||
+ if ( unlikely(rc) )
|
||||
+ {
|
||||
+ if ( likely(rc == -EAGAIN) )
|
||||
+ rc = hypercall_create_continuation(
|
||||
+ __HYPERVISOR_mmuext_op, "hihi", uops, count, pdone,
|
||||
+ foreigndom);
|
||||
+ return rc;
|
||||
+ }
|
||||
|
||||
if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
|
||||
{
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/x86_64/compat/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/x86_64/compat/mm.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/x86_64/compat/mm.c
|
||||
@@ -365,7 +365,7 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm
|
||||
: mcs->call.args[1];
|
||||
unsigned int left = arg1 & ~MMU_UPDATE_PREEMPTED;
|
||||
|
||||
- BUG_ON(left == arg1);
|
||||
+ BUG_ON(left == arg1 && left != i);
|
||||
BUG_ON(left > count);
|
||||
guest_handle_add_offset(nat_ops, i - left);
|
||||
guest_handle_subtract_offset(cmp_uops, left);
|
||||
Index: xen-4.2.1-testing/xen/include/asm-x86/domain.h
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/include/asm-x86/domain.h
|
||||
+++ xen-4.2.1-testing/xen/include/asm-x86/domain.h
|
||||
@@ -464,6 +464,7 @@ struct arch_vcpu
|
||||
pagetable_t guest_table_user; /* (MFN) x86/64 user-space pagetable */
|
||||
#endif
|
||||
pagetable_t guest_table; /* (MFN) guest notion of cr3 */
|
||||
+ struct page_info *old_guest_table; /* partially destructed pagetable */
|
||||
/* guest_table holds a ref to the page, and also a type-count unless
|
||||
* shadow refcounts are in use */
|
||||
pagetable_t shadow_table[4]; /* (MFN) shadow(s) of guest */
|
||||
Index: xen-4.2.1-testing/xen/include/asm-x86/mm.h
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/include/asm-x86/mm.h
|
||||
+++ xen-4.2.1-testing/xen/include/asm-x86/mm.h
|
||||
@@ -605,6 +605,7 @@ void audit_domains(void);
|
||||
int new_guest_cr3(unsigned long pfn);
|
||||
void make_cr3(struct vcpu *v, unsigned long mfn);
|
||||
void update_cr3(struct vcpu *v);
|
||||
+int vcpu_destroy_pagetables(struct vcpu *, bool_t preemptible);
|
||||
void propagate_page_fault(unsigned long addr, u16 error_code);
|
||||
void *do_page_walk(struct vcpu *v, unsigned long addr);
|
||||
|
@ -1,173 +0,0 @@
|
||||
x86: make new_guest_cr3() preemptible
|
||||
|
||||
... as it may take significant amounts of time.
|
||||
|
||||
This is part of CVE-2013-1918 / XSA-45.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/mm.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
@@ -2906,44 +2906,69 @@ int new_guest_cr3(unsigned long mfn)
|
||||
{
|
||||
struct vcpu *curr = current;
|
||||
struct domain *d = curr->domain;
|
||||
- int okay;
|
||||
+ int rc;
|
||||
unsigned long old_base_mfn;
|
||||
|
||||
#ifdef __x86_64__
|
||||
if ( is_pv_32on64_domain(d) )
|
||||
{
|
||||
- okay = paging_mode_refcounts(d)
|
||||
- ? 0 /* Old code was broken, but what should it be? */
|
||||
- : mod_l4_entry(
|
||||
+ rc = paging_mode_refcounts(d)
|
||||
+ ? -EINVAL /* Old code was broken, but what should it be? */
|
||||
+ : mod_l4_entry(
|
||||
__va(pagetable_get_paddr(curr->arch.guest_table)),
|
||||
l4e_from_pfn(
|
||||
mfn,
|
||||
(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED)),
|
||||
- pagetable_get_pfn(curr->arch.guest_table), 0, 0, curr) == 0;
|
||||
- if ( unlikely(!okay) )
|
||||
+ pagetable_get_pfn(curr->arch.guest_table), 0, 1, curr);
|
||||
+ switch ( rc )
|
||||
{
|
||||
+ case 0:
|
||||
+ break;
|
||||
+ case -EINTR:
|
||||
+ case -EAGAIN:
|
||||
+ return -EAGAIN;
|
||||
+ default:
|
||||
MEM_LOG("Error while installing new compat baseptr %lx", mfn);
|
||||
- return 0;
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
invalidate_shadow_ldt(curr, 0);
|
||||
write_ptbase(curr);
|
||||
|
||||
- return 1;
|
||||
+ return 0;
|
||||
}
|
||||
#endif
|
||||
- okay = paging_mode_refcounts(d)
|
||||
- ? get_page_from_pagenr(mfn, d)
|
||||
- : !get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d, 0, 0);
|
||||
- if ( unlikely(!okay) )
|
||||
+ rc = put_old_guest_table(curr);
|
||||
+ if ( unlikely(rc) )
|
||||
+ return rc;
|
||||
+
|
||||
+ old_base_mfn = pagetable_get_pfn(curr->arch.guest_table);
|
||||
+ /*
|
||||
+ * This is particularly important when getting restarted after the
|
||||
+ * previous attempt got preempted in the put-old-MFN phase.
|
||||
+ */
|
||||
+ if ( old_base_mfn == mfn )
|
||||
{
|
||||
- MEM_LOG("Error while installing new baseptr %lx", mfn);
|
||||
+ write_ptbase(curr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- invalidate_shadow_ldt(curr, 0);
|
||||
+ rc = paging_mode_refcounts(d)
|
||||
+ ? (get_page_from_pagenr(mfn, d) ? 0 : -EINVAL)
|
||||
+ : get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d, 0, 1);
|
||||
+ switch ( rc )
|
||||
+ {
|
||||
+ case 0:
|
||||
+ break;
|
||||
+ case -EINTR:
|
||||
+ case -EAGAIN:
|
||||
+ return -EAGAIN;
|
||||
+ default:
|
||||
+ MEM_LOG("Error while installing new baseptr %lx", mfn);
|
||||
+ return rc;
|
||||
+ }
|
||||
|
||||
- old_base_mfn = pagetable_get_pfn(curr->arch.guest_table);
|
||||
+ invalidate_shadow_ldt(curr, 0);
|
||||
|
||||
curr->arch.guest_table = pagetable_from_pfn(mfn);
|
||||
update_cr3(curr);
|
||||
@@ -2952,13 +2977,25 @@ int new_guest_cr3(unsigned long mfn)
|
||||
|
||||
if ( likely(old_base_mfn != 0) )
|
||||
{
|
||||
+ struct page_info *page = mfn_to_page(old_base_mfn);
|
||||
+
|
||||
if ( paging_mode_refcounts(d) )
|
||||
- put_page(mfn_to_page(old_base_mfn));
|
||||
+ put_page(page);
|
||||
else
|
||||
- put_page_and_type(mfn_to_page(old_base_mfn));
|
||||
+ switch ( rc = put_page_and_type_preemptible(page, 1) )
|
||||
+ {
|
||||
+ case -EINTR:
|
||||
+ rc = -EAGAIN;
|
||||
+ case -EAGAIN:
|
||||
+ curr->arch.old_guest_table = page;
|
||||
+ break;
|
||||
+ default:
|
||||
+ BUG_ON(rc);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
- return 1;
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
static struct domain *get_pg_owner(domid_t domid)
|
||||
@@ -3256,8 +3293,13 @@ long do_mmuext_op(
|
||||
}
|
||||
|
||||
case MMUEXT_NEW_BASEPTR:
|
||||
- okay = (!paging_mode_translate(d)
|
||||
- && new_guest_cr3(op.arg1.mfn));
|
||||
+ if ( paging_mode_translate(d) )
|
||||
+ okay = 0;
|
||||
+ else
|
||||
+ {
|
||||
+ rc = new_guest_cr3(op.arg1.mfn);
|
||||
+ okay = !rc;
|
||||
+ }
|
||||
break;
|
||||
|
||||
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/traps.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/traps.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/traps.c
|
||||
@@ -2407,12 +2407,23 @@ static int emulate_privileged_op(struct
|
||||
#endif
|
||||
}
|
||||
page = get_page_from_gfn(v->domain, gfn, NULL, P2M_ALLOC);
|
||||
- rc = page ? new_guest_cr3(page_to_mfn(page)) : 0;
|
||||
if ( page )
|
||||
+ {
|
||||
+ rc = new_guest_cr3(page_to_mfn(page));
|
||||
put_page(page);
|
||||
+ }
|
||||
+ else
|
||||
+ rc = -EINVAL;
|
||||
domain_unlock(v->domain);
|
||||
- if ( rc == 0 ) /* not okay */
|
||||
+ switch ( rc )
|
||||
+ {
|
||||
+ case 0:
|
||||
+ break;
|
||||
+ case -EAGAIN: /* retry after preemption */
|
||||
+ goto skip;
|
||||
+ default: /* not okay */
|
||||
goto fail;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
|
@ -1,76 +0,0 @@
|
||||
x86: make MMUEXT_NEW_USER_BASEPTR preemptible
|
||||
|
||||
... as it may take significant amounts of time.
|
||||
|
||||
This is part of CVE-2013-1918 / XSA-45.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/mm.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
@@ -3313,29 +3313,56 @@ long do_mmuext_op(
|
||||
break;
|
||||
}
|
||||
|
||||
+ old_mfn = pagetable_get_pfn(curr->arch.guest_table_user);
|
||||
+ /*
|
||||
+ * This is particularly important when getting restarted after the
|
||||
+ * previous attempt got preempted in the put-old-MFN phase.
|
||||
+ */
|
||||
+ if ( old_mfn == op.arg1.mfn )
|
||||
+ break;
|
||||
+
|
||||
if ( op.arg1.mfn != 0 )
|
||||
{
|
||||
if ( paging_mode_refcounts(d) )
|
||||
okay = get_page_from_pagenr(op.arg1.mfn, d);
|
||||
else
|
||||
- okay = !get_page_and_type_from_pagenr(
|
||||
- op.arg1.mfn, PGT_root_page_table, d, 0, 0);
|
||||
+ {
|
||||
+ rc = get_page_and_type_from_pagenr(
|
||||
+ op.arg1.mfn, PGT_root_page_table, d, 0, 1);
|
||||
+ okay = !rc;
|
||||
+ }
|
||||
if ( unlikely(!okay) )
|
||||
{
|
||||
- MEM_LOG("Error while installing new mfn %lx", op.arg1.mfn);
|
||||
+ if ( rc == -EINTR )
|
||||
+ rc = -EAGAIN;
|
||||
+ else if ( rc != -EAGAIN )
|
||||
+ MEM_LOG("Error while installing new mfn %lx",
|
||||
+ op.arg1.mfn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- old_mfn = pagetable_get_pfn(curr->arch.guest_table_user);
|
||||
curr->arch.guest_table_user = pagetable_from_pfn(op.arg1.mfn);
|
||||
|
||||
if ( old_mfn != 0 )
|
||||
{
|
||||
+ struct page_info *page = mfn_to_page(old_mfn);
|
||||
+
|
||||
if ( paging_mode_refcounts(d) )
|
||||
- put_page(mfn_to_page(old_mfn));
|
||||
+ put_page(page);
|
||||
else
|
||||
- put_page_and_type(mfn_to_page(old_mfn));
|
||||
+ switch ( rc = put_page_and_type_preemptible(page, 1) )
|
||||
+ {
|
||||
+ case -EINTR:
|
||||
+ rc = -EAGAIN;
|
||||
+ case -EAGAIN:
|
||||
+ curr->arch.old_guest_table = page;
|
||||
+ okay = 0;
|
||||
+ break;
|
||||
+ default:
|
||||
+ BUG_ON(rc);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
break;
|
@ -1,218 +0,0 @@
|
||||
x86: make vcpu_reset() preemptible
|
||||
|
||||
... as dropping the old page tables may take significant amounts of
|
||||
time.
|
||||
|
||||
This is part of CVE-2013-1918 / XSA-45.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/domain.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/domain.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/domain.c
|
||||
@@ -1051,17 +1051,16 @@ int arch_set_info_guest(
|
||||
#undef c
|
||||
}
|
||||
|
||||
-void arch_vcpu_reset(struct vcpu *v)
|
||||
+int arch_vcpu_reset(struct vcpu *v)
|
||||
{
|
||||
if ( !is_hvm_vcpu(v) )
|
||||
{
|
||||
destroy_gdt(v);
|
||||
- vcpu_destroy_pagetables(v, 0);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- vcpu_end_shutdown_deferral(v);
|
||||
+ return vcpu_destroy_pagetables(v);
|
||||
}
|
||||
+
|
||||
+ vcpu_end_shutdown_deferral(v);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2085,7 +2084,7 @@ int domain_relinquish_resources(struct d
|
||||
/* Drop the in-use references to page-table bases. */
|
||||
for_each_vcpu ( d, v )
|
||||
{
|
||||
- ret = vcpu_destroy_pagetables(v, 1);
|
||||
+ ret = vcpu_destroy_pagetables(v);
|
||||
if ( ret )
|
||||
return ret;
|
||||
}
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/hvm.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/hvm.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/hvm.c
|
||||
@@ -3577,8 +3577,11 @@ static void hvm_s3_suspend(struct domain
|
||||
|
||||
for_each_vcpu ( d, v )
|
||||
{
|
||||
+ int rc;
|
||||
+
|
||||
vlapic_reset(vcpu_vlapic(v));
|
||||
- vcpu_reset(v);
|
||||
+ rc = vcpu_reset(v);
|
||||
+ ASSERT(!rc);
|
||||
}
|
||||
|
||||
vpic_reset(d);
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/hvm/vlapic.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/hvm/vlapic.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/hvm/vlapic.c
|
||||
@@ -255,10 +255,13 @@ static void vlapic_init_sipi_action(unsi
|
||||
{
|
||||
case APIC_DM_INIT: {
|
||||
bool_t fpu_initialised;
|
||||
+ int rc;
|
||||
+
|
||||
domain_lock(target->domain);
|
||||
/* Reset necessary VCPU state. This does not include FPU state. */
|
||||
fpu_initialised = target->fpu_initialised;
|
||||
- vcpu_reset(target);
|
||||
+ rc = vcpu_reset(target);
|
||||
+ ASSERT(!rc);
|
||||
target->fpu_initialised = fpu_initialised;
|
||||
vlapic_reset(vcpu_vlapic(target));
|
||||
domain_unlock(target->domain);
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/mm.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/mm.c
|
||||
@@ -2844,7 +2844,7 @@ static int put_old_guest_table(struct vc
|
||||
return rc;
|
||||
}
|
||||
|
||||
-int vcpu_destroy_pagetables(struct vcpu *v, bool_t preemptible)
|
||||
+int vcpu_destroy_pagetables(struct vcpu *v)
|
||||
{
|
||||
unsigned long mfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
struct page_info *page;
|
||||
@@ -2864,7 +2864,7 @@ int vcpu_destroy_pagetables(struct vcpu
|
||||
if ( paging_mode_refcounts(v->domain) )
|
||||
put_page(page);
|
||||
else
|
||||
- rc = put_page_and_type_preemptible(page, preemptible);
|
||||
+ rc = put_page_and_type_preemptible(page, 1);
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
@@ -2890,7 +2890,7 @@ int vcpu_destroy_pagetables(struct vcpu
|
||||
if ( paging_mode_refcounts(v->domain) )
|
||||
put_page(page);
|
||||
else
|
||||
- rc = put_page_and_type_preemptible(page, preemptible);
|
||||
+ rc = put_page_and_type_preemptible(page, 1);
|
||||
}
|
||||
if ( !rc )
|
||||
v->arch.guest_table_user = pagetable_null();
|
||||
Index: xen-4.2.2-testing/xen/common/domain.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/common/domain.c
|
||||
+++ xen-4.2.2-testing/xen/common/domain.c
|
||||
@@ -779,14 +779,18 @@ void domain_unpause_by_systemcontroller(
|
||||
domain_unpause(d);
|
||||
}
|
||||
|
||||
-void vcpu_reset(struct vcpu *v)
|
||||
+int vcpu_reset(struct vcpu *v)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
+ int rc;
|
||||
|
||||
vcpu_pause(v);
|
||||
domain_lock(d);
|
||||
|
||||
- arch_vcpu_reset(v);
|
||||
+ set_bit(_VPF_in_reset, &v->pause_flags);
|
||||
+ rc = arch_vcpu_reset(v);
|
||||
+ if ( rc )
|
||||
+ goto out_unlock;
|
||||
|
||||
set_bit(_VPF_down, &v->pause_flags);
|
||||
|
||||
@@ -802,9 +806,13 @@ void vcpu_reset(struct vcpu *v)
|
||||
#endif
|
||||
cpumask_clear(v->cpu_affinity_tmp);
|
||||
clear_bit(_VPF_blocked, &v->pause_flags);
|
||||
+ clear_bit(_VPF_in_reset, &v->pause_flags);
|
||||
|
||||
+ out_unlock:
|
||||
domain_unlock(v->domain);
|
||||
vcpu_unpause(v);
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
|
||||
Index: xen-4.2.2-testing/xen/common/domctl.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/common/domctl.c
|
||||
+++ xen-4.2.2-testing/xen/common/domctl.c
|
||||
@@ -307,8 +307,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
|
||||
|
||||
if ( guest_handle_is_null(op->u.vcpucontext.ctxt) )
|
||||
{
|
||||
- vcpu_reset(v);
|
||||
- ret = 0;
|
||||
+ ret = vcpu_reset(v);
|
||||
+ if ( ret == -EAGAIN )
|
||||
+ ret = hypercall_create_continuation(
|
||||
+ __HYPERVISOR_domctl, "h", u_domctl);
|
||||
goto svc_out;
|
||||
}
|
||||
|
||||
Index: xen-4.2.2-testing/xen/include/asm-x86/mm.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/asm-x86/mm.h
|
||||
+++ xen-4.2.2-testing/xen/include/asm-x86/mm.h
|
||||
@@ -605,7 +605,7 @@ void audit_domains(void);
|
||||
int new_guest_cr3(unsigned long pfn);
|
||||
void make_cr3(struct vcpu *v, unsigned long mfn);
|
||||
void update_cr3(struct vcpu *v);
|
||||
-int vcpu_destroy_pagetables(struct vcpu *, bool_t preemptible);
|
||||
+int vcpu_destroy_pagetables(struct vcpu *);
|
||||
void propagate_page_fault(unsigned long addr, u16 error_code);
|
||||
void *do_page_walk(struct vcpu *v, unsigned long addr);
|
||||
|
||||
Index: xen-4.2.2-testing/xen/include/xen/domain.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/domain.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/domain.h
|
||||
@@ -13,7 +13,7 @@ typedef union {
|
||||
struct vcpu *alloc_vcpu(
|
||||
struct domain *d, unsigned int vcpu_id, unsigned int cpu_id);
|
||||
struct vcpu *alloc_dom0_vcpu0(void);
|
||||
-void vcpu_reset(struct vcpu *v);
|
||||
+int vcpu_reset(struct vcpu *);
|
||||
|
||||
struct xen_domctl_getdomaininfo;
|
||||
void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info);
|
||||
@@ -67,7 +67,7 @@ void arch_dump_vcpu_info(struct vcpu *v)
|
||||
|
||||
void arch_dump_domain_info(struct domain *d);
|
||||
|
||||
-void arch_vcpu_reset(struct vcpu *v);
|
||||
+int arch_vcpu_reset(struct vcpu *);
|
||||
|
||||
extern spinlock_t vcpu_alloc_lock;
|
||||
bool_t domctl_lock_acquire(void);
|
||||
Index: xen-4.2.2-testing/xen/include/xen/sched.h
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/include/xen/sched.h
|
||||
+++ xen-4.2.2-testing/xen/include/xen/sched.h
|
||||
@@ -644,6 +644,9 @@ static inline struct domain *next_domain
|
||||
/* VCPU is blocked due to missing mem_sharing ring. */
|
||||
#define _VPF_mem_sharing 6
|
||||
#define VPF_mem_sharing (1UL<<_VPF_mem_sharing)
|
||||
+ /* VCPU is being reset. */
|
||||
+#define _VPF_in_reset 7
|
||||
+#define VPF_in_reset (1UL<<_VPF_in_reset)
|
||||
|
||||
static inline int vcpu_runnable(struct vcpu *v)
|
||||
{
|
@ -1,212 +0,0 @@
|
||||
x86: make arch_set_info_guest() preemptible
|
||||
|
||||
.. as the root page table validation (and the dropping of an eventual
|
||||
old one) can require meaningful amounts of time.
|
||||
|
||||
This is part of CVE-2013-1918 / XSA-45.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
Index: xen-4.2.2-testing/xen/arch/x86/domain.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/arch/x86/domain.c
|
||||
+++ xen-4.2.2-testing/xen/arch/x86/domain.c
|
||||
@@ -858,6 +858,9 @@ int arch_set_info_guest(
|
||||
|
||||
if ( !v->is_initialised )
|
||||
{
|
||||
+ if ( !compat && !(flags & VGCF_in_kernel) && !c.nat->ctrlreg[1] )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
v->arch.pv_vcpu.ldt_base = c(ldt_base);
|
||||
v->arch.pv_vcpu.ldt_ents = c(ldt_ents);
|
||||
}
|
||||
@@ -955,24 +958,44 @@ int arch_set_info_guest(
|
||||
if ( rc != 0 )
|
||||
return rc;
|
||||
|
||||
+ set_bit(_VPF_in_reset, &v->pause_flags);
|
||||
+
|
||||
if ( !compat )
|
||||
- {
|
||||
cr3_gfn = xen_cr3_to_pfn(c.nat->ctrlreg[3]);
|
||||
- cr3_page = get_page_from_gfn(d, cr3_gfn, NULL, P2M_ALLOC);
|
||||
-
|
||||
- if ( !cr3_page )
|
||||
- {
|
||||
- destroy_gdt(v);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
- if ( !paging_mode_refcounts(d)
|
||||
- && !get_page_type(cr3_page, PGT_base_page_table) )
|
||||
- {
|
||||
- put_page(cr3_page);
|
||||
- destroy_gdt(v);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
+#ifdef CONFIG_COMPAT
|
||||
+ else
|
||||
+ cr3_gfn = compat_cr3_to_pfn(c.cmp->ctrlreg[3]);
|
||||
+#endif
|
||||
+ cr3_page = get_page_from_gfn(d, cr3_gfn, NULL, P2M_ALLOC);
|
||||
|
||||
+ if ( !cr3_page )
|
||||
+ rc = -EINVAL;
|
||||
+ else if ( paging_mode_refcounts(d) )
|
||||
+ /* nothing */;
|
||||
+ else if ( cr3_page == v->arch.old_guest_table )
|
||||
+ {
|
||||
+ v->arch.old_guest_table = NULL;
|
||||
+ put_page(cr3_page);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /*
|
||||
+ * Since v->arch.guest_table{,_user} are both NULL, this effectively
|
||||
+ * is just a call to put_old_guest_table().
|
||||
+ */
|
||||
+ if ( !compat )
|
||||
+ rc = vcpu_destroy_pagetables(v);
|
||||
+ if ( !rc )
|
||||
+ rc = get_page_type_preemptible(cr3_page,
|
||||
+ !compat ? PGT_root_page_table
|
||||
+ : PGT_l3_page_table);
|
||||
+ if ( rc == -EINTR )
|
||||
+ rc = -EAGAIN;
|
||||
+ }
|
||||
+ if ( rc )
|
||||
+ /* handled below */;
|
||||
+ else if ( !compat )
|
||||
+ {
|
||||
v->arch.guest_table = pagetable_from_page(cr3_page);
|
||||
#ifdef __x86_64__
|
||||
if ( c.nat->ctrlreg[1] )
|
||||
@@ -980,56 +1003,44 @@ int arch_set_info_guest(
|
||||
cr3_gfn = xen_cr3_to_pfn(c.nat->ctrlreg[1]);
|
||||
cr3_page = get_page_from_gfn(d, cr3_gfn, NULL, P2M_ALLOC);
|
||||
|
||||
- if ( !cr3_page ||
|
||||
- (!paging_mode_refcounts(d)
|
||||
- && !get_page_type(cr3_page, PGT_base_page_table)) )
|
||||
+ if ( !cr3_page )
|
||||
+ rc = -EINVAL;
|
||||
+ else if ( !paging_mode_refcounts(d) )
|
||||
{
|
||||
- if (cr3_page)
|
||||
- put_page(cr3_page);
|
||||
- cr3_page = pagetable_get_page(v->arch.guest_table);
|
||||
- v->arch.guest_table = pagetable_null();
|
||||
- if ( paging_mode_refcounts(d) )
|
||||
- put_page(cr3_page);
|
||||
- else
|
||||
- put_page_and_type(cr3_page);
|
||||
- destroy_gdt(v);
|
||||
- return -EINVAL;
|
||||
+ rc = get_page_type_preemptible(cr3_page, PGT_root_page_table);
|
||||
+ switch ( rc )
|
||||
+ {
|
||||
+ case -EINTR:
|
||||
+ rc = -EAGAIN;
|
||||
+ case -EAGAIN:
|
||||
+ v->arch.old_guest_table =
|
||||
+ pagetable_get_page(v->arch.guest_table);
|
||||
+ v->arch.guest_table = pagetable_null();
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
-
|
||||
- v->arch.guest_table_user = pagetable_from_page(cr3_page);
|
||||
- }
|
||||
- else if ( !(flags & VGCF_in_kernel) )
|
||||
- {
|
||||
- destroy_gdt(v);
|
||||
- return -EINVAL;
|
||||
+ if ( !rc )
|
||||
+ v->arch.guest_table_user = pagetable_from_page(cr3_page);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
l4_pgentry_t *l4tab;
|
||||
|
||||
- cr3_gfn = compat_cr3_to_pfn(c.cmp->ctrlreg[3]);
|
||||
- cr3_page = get_page_from_gfn(d, cr3_gfn, NULL, P2M_ALLOC);
|
||||
-
|
||||
- if ( !cr3_page)
|
||||
- {
|
||||
- destroy_gdt(v);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- if (!paging_mode_refcounts(d)
|
||||
- && !get_page_type(cr3_page, PGT_l3_page_table) )
|
||||
- {
|
||||
- put_page(cr3_page);
|
||||
- destroy_gdt(v);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
l4tab = __va(pagetable_get_paddr(v->arch.guest_table));
|
||||
*l4tab = l4e_from_pfn(page_to_mfn(cr3_page),
|
||||
_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED);
|
||||
#endif
|
||||
}
|
||||
+ if ( rc )
|
||||
+ {
|
||||
+ if ( cr3_page )
|
||||
+ put_page(cr3_page);
|
||||
+ destroy_gdt(v);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ clear_bit(_VPF_in_reset, &v->pause_flags);
|
||||
|
||||
if ( v->vcpu_id == 0 )
|
||||
update_domain_wallclock_time(d);
|
||||
Index: xen-4.2.2-testing/xen/common/compat/domain.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/common/compat/domain.c
|
||||
+++ xen-4.2.2-testing/xen/common/compat/domain.c
|
||||
@@ -50,6 +50,10 @@ int compat_vcpu_op(int cmd, int vcpuid,
|
||||
rc = v->is_initialised ? -EEXIST : arch_set_info_guest(v, cmp_ctxt);
|
||||
domain_unlock(d);
|
||||
|
||||
+ if ( rc == -EAGAIN )
|
||||
+ rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih",
|
||||
+ cmd, vcpuid, arg);
|
||||
+
|
||||
xfree(cmp_ctxt);
|
||||
break;
|
||||
}
|
||||
Index: xen-4.2.2-testing/xen/common/domain.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/common/domain.c
|
||||
+++ xen-4.2.2-testing/xen/common/domain.c
|
||||
@@ -849,6 +849,11 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
|
||||
domain_unlock(d);
|
||||
|
||||
free_vcpu_guest_context(ctxt);
|
||||
+
|
||||
+ if ( rc == -EAGAIN )
|
||||
+ rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih",
|
||||
+ cmd, vcpuid, arg);
|
||||
+
|
||||
break;
|
||||
|
||||
case VCPUOP_up: {
|
||||
Index: xen-4.2.2-testing/xen/common/domctl.c
|
||||
===================================================================
|
||||
--- xen-4.2.2-testing.orig/xen/common/domctl.c
|
||||
+++ xen-4.2.2-testing/xen/common/domctl.c
|
||||
@@ -339,6 +339,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
|
||||
domain_pause(d);
|
||||
ret = arch_set_info_guest(v, c);
|
||||
domain_unpause(d);
|
||||
+
|
||||
+ if ( ret == -EAGAIN )
|
||||
+ ret = hypercall_create_continuation(
|
||||
+ __HYPERVISOR_domctl, "h", u_domctl);
|
||||
}
|
||||
|
||||
svc_out:
|
@ -1,131 +0,0 @@
|
||||
x86: make page table unpinning preemptible
|
||||
|
||||
... as it may take significant amounts of time.
|
||||
|
||||
Since we can't re-invoke the operation in a second attempt, the
|
||||
continuation logic must be slightly tweaked so that we make sure
|
||||
do_mmuext_op() gets run one more time even when the preempted unpin
|
||||
operation was the last one in a batch.
|
||||
|
||||
This is part of CVE-2013-1918 / XSA-45.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/mm.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
@@ -3140,6 +3140,14 @@ long do_mmuext_op(
|
||||
return rc;
|
||||
}
|
||||
|
||||
+ if ( unlikely(count == MMU_UPDATE_PREEMPTED) &&
|
||||
+ likely(guest_handle_is_null(uops)) )
|
||||
+ {
|
||||
+ /* See the curr->arch.old_guest_table related
|
||||
+ * hypercall_create_continuation() below. */
|
||||
+ return (int)foreigndom;
|
||||
+ }
|
||||
+
|
||||
if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
|
||||
{
|
||||
count &= ~MMU_UPDATE_PREEMPTED;
|
||||
@@ -3163,7 +3171,7 @@ long do_mmuext_op(
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
- if ( hypercall_preempt_check() )
|
||||
+ if ( curr->arch.old_guest_table || hypercall_preempt_check() )
|
||||
{
|
||||
rc = -EAGAIN;
|
||||
break;
|
||||
@@ -3283,7 +3291,17 @@ long do_mmuext_op(
|
||||
break;
|
||||
}
|
||||
|
||||
- put_page_and_type(page);
|
||||
+ switch ( rc = put_page_and_type_preemptible(page, 1) )
|
||||
+ {
|
||||
+ case -EINTR:
|
||||
+ case -EAGAIN:
|
||||
+ curr->arch.old_guest_table = page;
|
||||
+ rc = 0;
|
||||
+ break;
|
||||
+ default:
|
||||
+ BUG_ON(rc);
|
||||
+ break;
|
||||
+ }
|
||||
put_page(page);
|
||||
|
||||
/* A page is dirtied when its pin status is cleared. */
|
||||
@@ -3604,9 +3622,27 @@ long do_mmuext_op(
|
||||
}
|
||||
|
||||
if ( rc == -EAGAIN )
|
||||
+ {
|
||||
+ ASSERT(i < count);
|
||||
rc = hypercall_create_continuation(
|
||||
__HYPERVISOR_mmuext_op, "hihi",
|
||||
uops, (count - i) | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
|
||||
+ }
|
||||
+ else if ( curr->arch.old_guest_table )
|
||||
+ {
|
||||
+ XEN_GUEST_HANDLE(void) null;
|
||||
+
|
||||
+ ASSERT(rc || i == count);
|
||||
+ set_xen_guest_handle(null, NULL);
|
||||
+ /*
|
||||
+ * In order to have a way to communicate the final return value to
|
||||
+ * our continuation, we pass this in place of "foreigndom", building
|
||||
+ * on the fact that this argument isn't needed anymore.
|
||||
+ */
|
||||
+ rc = hypercall_create_continuation(
|
||||
+ __HYPERVISOR_mmuext_op, "hihi", null,
|
||||
+ MMU_UPDATE_PREEMPTED, null, rc);
|
||||
+ }
|
||||
|
||||
put_pg_owner(pg_owner);
|
||||
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/x86_64/compat/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/x86_64/compat/mm.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/x86_64/compat/mm.c
|
||||
@@ -268,6 +268,13 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm
|
||||
int rc = 0;
|
||||
XEN_GUEST_HANDLE(mmuext_op_t) nat_ops;
|
||||
|
||||
+ if ( unlikely(count == MMU_UPDATE_PREEMPTED) &&
|
||||
+ likely(guest_handle_is_null(cmp_uops)) )
|
||||
+ {
|
||||
+ set_xen_guest_handle(nat_ops, NULL);
|
||||
+ return do_mmuext_op(nat_ops, count, pdone, foreigndom);
|
||||
+ }
|
||||
+
|
||||
preempt_mask = count & MMU_UPDATE_PREEMPTED;
|
||||
count ^= preempt_mask;
|
||||
|
||||
@@ -370,12 +377,18 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm
|
||||
guest_handle_add_offset(nat_ops, i - left);
|
||||
guest_handle_subtract_offset(cmp_uops, left);
|
||||
left = 1;
|
||||
- BUG_ON(!hypercall_xlat_continuation(&left, 0x01, nat_ops, cmp_uops));
|
||||
- BUG_ON(left != arg1);
|
||||
- if (!test_bit(_MCSF_in_multicall, &mcs->flags))
|
||||
- regs->_ecx += count - i;
|
||||
+ if ( arg1 != MMU_UPDATE_PREEMPTED )
|
||||
+ {
|
||||
+ BUG_ON(!hypercall_xlat_continuation(&left, 0x01, nat_ops,
|
||||
+ cmp_uops));
|
||||
+ if ( !test_bit(_MCSF_in_multicall, &mcs->flags) )
|
||||
+ regs->_ecx += count - i;
|
||||
+ else
|
||||
+ mcs->compat_call.args[1] += count - i;
|
||||
+ }
|
||||
else
|
||||
- mcs->compat_call.args[1] += count - i;
|
||||
+ BUG_ON(hypercall_xlat_continuation(&left, 0));
|
||||
+ BUG_ON(left != arg1);
|
||||
}
|
||||
else
|
||||
BUG_ON(err > 0);
|
@ -1,257 +0,0 @@
|
||||
x86: make page table handling error paths preemptible
|
||||
|
||||
... as they may take significant amounts of time.
|
||||
|
||||
This requires cloning the tweaked continuation logic from
|
||||
do_mmuext_op() to do_mmu_update().
|
||||
|
||||
Note that in mod_l[34]_entry() a negative "preemptible" value gets
|
||||
passed to put_page_from_l[34]e() now, telling the callee to store the
|
||||
respective page in current->arch.old_guest_table (for a hypercall
|
||||
continuation to pick up), rather than carrying out the put right away.
|
||||
This is going to be made a little more explicit by a subsequent cleanup
|
||||
patch.
|
||||
|
||||
This is part of CVE-2013-1918 / XSA-45.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
Index: xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/arch/x86/mm.c
|
||||
+++ xen-4.2.1-testing/xen/arch/x86/mm.c
|
||||
@@ -1258,7 +1258,16 @@ static int put_page_from_l3e(l3_pgentry_
|
||||
#endif
|
||||
|
||||
if ( unlikely(partial > 0) )
|
||||
+ {
|
||||
+ ASSERT(preemptible >= 0);
|
||||
return __put_page_type(l3e_get_page(l3e), preemptible);
|
||||
+ }
|
||||
+
|
||||
+ if ( preemptible < 0 )
|
||||
+ {
|
||||
+ current->arch.old_guest_table = l3e_get_page(l3e);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
return put_page_and_type_preemptible(l3e_get_page(l3e), preemptible);
|
||||
}
|
||||
@@ -1271,7 +1280,17 @@ static int put_page_from_l4e(l4_pgentry_
|
||||
(l4e_get_pfn(l4e) != pfn) )
|
||||
{
|
||||
if ( unlikely(partial > 0) )
|
||||
+ {
|
||||
+ ASSERT(preemptible >= 0);
|
||||
return __put_page_type(l4e_get_page(l4e), preemptible);
|
||||
+ }
|
||||
+
|
||||
+ if ( preemptible < 0 )
|
||||
+ {
|
||||
+ current->arch.old_guest_table = l4e_get_page(l4e);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
return put_page_and_type_preemptible(l4e_get_page(l4e), preemptible);
|
||||
}
|
||||
return 1;
|
||||
@@ -1566,12 +1585,17 @@ static int alloc_l3_table(struct page_in
|
||||
if ( rc < 0 && rc != -EAGAIN && rc != -EINTR )
|
||||
{
|
||||
MEM_LOG("Failure in alloc_l3_table: entry %d", i);
|
||||
+ if ( i )
|
||||
+ {
|
||||
+ page->nr_validated_ptes = i;
|
||||
+ page->partial_pte = 0;
|
||||
+ current->arch.old_guest_table = page;
|
||||
+ }
|
||||
while ( i-- > 0 )
|
||||
{
|
||||
if ( !is_guest_l3_slot(i) )
|
||||
continue;
|
||||
unadjust_guest_l3e(pl3e[i], d);
|
||||
- put_page_from_l3e(pl3e[i], pfn, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1601,22 +1625,24 @@ static int alloc_l4_table(struct page_in
|
||||
page->nr_validated_ptes = i;
|
||||
page->partial_pte = partial ?: 1;
|
||||
}
|
||||
- else if ( rc == -EINTR )
|
||||
+ else if ( rc < 0 )
|
||||
{
|
||||
+ if ( rc != -EINTR )
|
||||
+ MEM_LOG("Failure in alloc_l4_table: entry %d", i);
|
||||
if ( i )
|
||||
{
|
||||
page->nr_validated_ptes = i;
|
||||
page->partial_pte = 0;
|
||||
- rc = -EAGAIN;
|
||||
+ if ( rc == -EINTR )
|
||||
+ rc = -EAGAIN;
|
||||
+ else
|
||||
+ {
|
||||
+ if ( current->arch.old_guest_table )
|
||||
+ page->nr_validated_ptes++;
|
||||
+ current->arch.old_guest_table = page;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
- else if ( rc < 0 )
|
||||
- {
|
||||
- MEM_LOG("Failure in alloc_l4_table: entry %d", i);
|
||||
- while ( i-- > 0 )
|
||||
- if ( is_guest_l4_slot(d, i) )
|
||||
- put_page_from_l4e(pl4e[i], pfn, 0, 0);
|
||||
- }
|
||||
if ( rc < 0 )
|
||||
return rc;
|
||||
|
||||
@@ -2064,7 +2090,7 @@ static int mod_l3_entry(l3_pgentry_t *pl
|
||||
pae_flush_pgd(pfn, pgentry_ptr_to_slot(pl3e), nl3e);
|
||||
}
|
||||
|
||||
- put_page_from_l3e(ol3e, pfn, 0, 0);
|
||||
+ put_page_from_l3e(ol3e, pfn, 0, -preemptible);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2127,7 +2153,7 @@ static int mod_l4_entry(l4_pgentry_t *pl
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
- put_page_from_l4e(ol4e, pfn, 0, 0);
|
||||
+ put_page_from_l4e(ol4e, pfn, 0, -preemptible);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2285,7 +2311,15 @@ static int alloc_page_type(struct page_i
|
||||
PRtype_info ": caf=%08lx taf=%" PRtype_info,
|
||||
page_to_mfn(page), get_gpfn_from_mfn(page_to_mfn(page)),
|
||||
type, page->count_info, page->u.inuse.type_info);
|
||||
- page->u.inuse.type_info = 0;
|
||||
+ if ( page != current->arch.old_guest_table )
|
||||
+ page->u.inuse.type_info = 0;
|
||||
+ else
|
||||
+ {
|
||||
+ ASSERT((page->u.inuse.type_info &
|
||||
+ (PGT_count_mask | PGT_validated)) == 1);
|
||||
+ get_page_light(page);
|
||||
+ page->u.inuse.type_info |= PGT_partial;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3235,21 +3269,17 @@ long do_mmuext_op(
|
||||
}
|
||||
|
||||
if ( (rc = xsm_memory_pin_page(d, pg_owner, page)) != 0 )
|
||||
- {
|
||||
- put_page_and_type(page);
|
||||
okay = 0;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if ( unlikely(test_and_set_bit(_PGT_pinned,
|
||||
- &page->u.inuse.type_info)) )
|
||||
+ else if ( unlikely(test_and_set_bit(_PGT_pinned,
|
||||
+ &page->u.inuse.type_info)) )
|
||||
{
|
||||
MEM_LOG("Mfn %lx already pinned", page_to_mfn(page));
|
||||
- put_page_and_type(page);
|
||||
okay = 0;
|
||||
- break;
|
||||
}
|
||||
|
||||
+ if ( unlikely(!okay) )
|
||||
+ goto pin_drop;
|
||||
+
|
||||
/* A page is dirtied when its pin status is set. */
|
||||
paging_mark_dirty(pg_owner, page_to_mfn(page));
|
||||
|
||||
@@ -3263,7 +3293,13 @@ long do_mmuext_op(
|
||||
&page->u.inuse.type_info));
|
||||
spin_unlock(&pg_owner->page_alloc_lock);
|
||||
if ( drop_ref )
|
||||
- put_page_and_type(page);
|
||||
+ {
|
||||
+ pin_drop:
|
||||
+ if ( type == PGT_l1_page_table )
|
||||
+ put_page_and_type(page);
|
||||
+ else
|
||||
+ curr->arch.old_guest_table = page;
|
||||
+ }
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -3669,11 +3705,28 @@ long do_mmu_update(
|
||||
void *va;
|
||||
unsigned long gpfn, gmfn, mfn;
|
||||
struct page_info *page;
|
||||
- int rc = 0, i = 0;
|
||||
- unsigned int cmd, done = 0, pt_dom;
|
||||
- struct vcpu *v = current;
|
||||
+ unsigned int cmd, i = 0, done = 0, pt_dom;
|
||||
+ struct vcpu *curr = current, *v = curr;
|
||||
struct domain *d = v->domain, *pt_owner = d, *pg_owner;
|
||||
struct domain_mmap_cache mapcache;
|
||||
+ int rc = put_old_guest_table(curr);
|
||||
+
|
||||
+ if ( unlikely(rc) )
|
||||
+ {
|
||||
+ if ( likely(rc == -EAGAIN) )
|
||||
+ rc = hypercall_create_continuation(
|
||||
+ __HYPERVISOR_mmu_update, "hihi", ureqs, count, pdone,
|
||||
+ foreigndom);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ if ( unlikely(count == MMU_UPDATE_PREEMPTED) &&
|
||||
+ likely(guest_handle_is_null(ureqs)) )
|
||||
+ {
|
||||
+ /* See the curr->arch.old_guest_table related
|
||||
+ * hypercall_create_continuation() below. */
|
||||
+ return (int)foreigndom;
|
||||
+ }
|
||||
|
||||
if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
|
||||
{
|
||||
@@ -3722,7 +3775,7 @@ long do_mmu_update(
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
- if ( hypercall_preempt_check() )
|
||||
+ if ( curr->arch.old_guest_table || hypercall_preempt_check() )
|
||||
{
|
||||
rc = -EAGAIN;
|
||||
break;
|
||||
@@ -3903,9 +3956,27 @@ long do_mmu_update(
|
||||
}
|
||||
|
||||
if ( rc == -EAGAIN )
|
||||
+ {
|
||||
+ ASSERT(i < count);
|
||||
rc = hypercall_create_continuation(
|
||||
__HYPERVISOR_mmu_update, "hihi",
|
||||
ureqs, (count - i) | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
|
||||
+ }
|
||||
+ else if ( curr->arch.old_guest_table )
|
||||
+ {
|
||||
+ XEN_GUEST_HANDLE(void) null;
|
||||
+
|
||||
+ ASSERT(rc || i == count);
|
||||
+ set_xen_guest_handle(null, NULL);
|
||||
+ /*
|
||||
+ * In order to have a way to communicate the final return value to
|
||||
+ * our continuation, we pass this in place of "foreigndom", building
|
||||
+ * on the fact that this argument isn't needed anymore.
|
||||
+ */
|
||||
+ rc = hypercall_create_continuation(
|
||||
+ __HYPERVISOR_mmu_update, "hihi", null,
|
||||
+ MMU_UPDATE_PREEMPTED, null, rc);
|
||||
+ }
|
||||
|
||||
put_pg_owner(pg_owner);
|
||||
|
@ -1,406 +0,0 @@
|
||||
x86: cleanup after making various page table manipulation operations preemptible
|
||||
|
||||
This drops the "preemptible" parameters from various functions where
|
||||
now they can't (or shouldn't, validated by assertions) be run in non-
|
||||
preemptible mode anymore, to prove that manipulations of at least L3
|
||||
and L4 page tables and page table entries are now always preemptible,
|
||||
i.e. the earlier patches actually fulfill their purpose of fixing the
|
||||
resulting security issue.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
--- a/xen/arch/x86/domain.c
|
||||
+++ b/xen/arch/x86/domain.c
|
||||
@@ -1986,7 +1986,7 @@ static int relinquish_memory(
|
||||
}
|
||||
|
||||
if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
|
||||
- ret = put_page_and_type_preemptible(page, 1);
|
||||
+ ret = put_page_and_type_preemptible(page);
|
||||
switch ( ret )
|
||||
{
|
||||
case 0:
|
||||
--- a/xen/arch/x86/mm.c
|
||||
+++ b/xen/arch/x86/mm.c
|
||||
@@ -1044,7 +1044,7 @@ get_page_from_l2e(
|
||||
define_get_linear_pagetable(l3);
|
||||
static int
|
||||
get_page_from_l3e(
|
||||
- l3_pgentry_t l3e, unsigned long pfn, struct domain *d, int partial, int preemptible)
|
||||
+ l3_pgentry_t l3e, unsigned long pfn, struct domain *d, int partial)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -1058,7 +1058,7 @@ get_page_from_l3e(
|
||||
}
|
||||
|
||||
rc = get_page_and_type_from_pagenr(
|
||||
- l3e_get_pfn(l3e), PGT_l2_page_table, d, partial, preemptible);
|
||||
+ l3e_get_pfn(l3e), PGT_l2_page_table, d, partial, 1);
|
||||
if ( unlikely(rc == -EINVAL) && get_l3_linear_pagetable(l3e, pfn, d) )
|
||||
rc = 0;
|
||||
|
||||
@@ -1069,7 +1069,7 @@ get_page_from_l3e(
|
||||
define_get_linear_pagetable(l4);
|
||||
static int
|
||||
get_page_from_l4e(
|
||||
- l4_pgentry_t l4e, unsigned long pfn, struct domain *d, int partial, int preemptible)
|
||||
+ l4_pgentry_t l4e, unsigned long pfn, struct domain *d, int partial)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -1083,7 +1083,7 @@ get_page_from_l4e(
|
||||
}
|
||||
|
||||
rc = get_page_and_type_from_pagenr(
|
||||
- l4e_get_pfn(l4e), PGT_l3_page_table, d, partial, preemptible);
|
||||
+ l4e_get_pfn(l4e), PGT_l3_page_table, d, partial, 1);
|
||||
if ( unlikely(rc == -EINVAL) && get_l4_linear_pagetable(l4e, pfn, d) )
|
||||
rc = 0;
|
||||
|
||||
@@ -1237,8 +1237,10 @@ static int put_page_from_l2e(l2_pgentry_
|
||||
static int __put_page_type(struct page_info *, int preemptible);
|
||||
|
||||
static int put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn,
|
||||
- int partial, int preemptible)
|
||||
+ int partial, bool_t defer)
|
||||
{
|
||||
+ struct page_info *pg;
|
||||
+
|
||||
if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) || (l3e_get_pfn(l3e) == pfn) )
|
||||
return 1;
|
||||
|
||||
@@ -1257,41 +1259,45 @@ static int put_page_from_l3e(l3_pgentry_
|
||||
}
|
||||
#endif
|
||||
|
||||
+ pg = l3e_get_page(l3e);
|
||||
+
|
||||
if ( unlikely(partial > 0) )
|
||||
{
|
||||
- ASSERT(preemptible >= 0);
|
||||
- return __put_page_type(l3e_get_page(l3e), preemptible);
|
||||
+ ASSERT(!defer);
|
||||
+ return __put_page_type(pg, 1);
|
||||
}
|
||||
|
||||
- if ( preemptible < 0 )
|
||||
+ if ( defer )
|
||||
{
|
||||
- current->arch.old_guest_table = l3e_get_page(l3e);
|
||||
+ current->arch.old_guest_table = pg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
- return put_page_and_type_preemptible(l3e_get_page(l3e), preemptible);
|
||||
+ return put_page_and_type_preemptible(pg);
|
||||
}
|
||||
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
static int put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn,
|
||||
- int partial, int preemptible)
|
||||
+ int partial, bool_t defer)
|
||||
{
|
||||
if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) &&
|
||||
(l4e_get_pfn(l4e) != pfn) )
|
||||
{
|
||||
+ struct page_info *pg = l4e_get_page(l4e);
|
||||
+
|
||||
if ( unlikely(partial > 0) )
|
||||
{
|
||||
- ASSERT(preemptible >= 0);
|
||||
- return __put_page_type(l4e_get_page(l4e), preemptible);
|
||||
+ ASSERT(!defer);
|
||||
+ return __put_page_type(pg, 1);
|
||||
}
|
||||
|
||||
- if ( preemptible < 0 )
|
||||
+ if ( defer )
|
||||
{
|
||||
- current->arch.old_guest_table = l4e_get_page(l4e);
|
||||
+ current->arch.old_guest_table = pg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
- return put_page_and_type_preemptible(l4e_get_page(l4e), preemptible);
|
||||
+ return put_page_and_type_preemptible(pg);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1509,7 +1515,7 @@ static int alloc_l2_table(struct page_in
|
||||
return rc > 0 ? 0 : rc;
|
||||
}
|
||||
|
||||
-static int alloc_l3_table(struct page_info *page, int preemptible)
|
||||
+static int alloc_l3_table(struct page_info *page)
|
||||
{
|
||||
struct domain *d = page_get_owner(page);
|
||||
unsigned long pfn = page_to_mfn(page);
|
||||
@@ -1556,11 +1562,10 @@ static int alloc_l3_table(struct page_in
|
||||
rc = get_page_and_type_from_pagenr(l3e_get_pfn(pl3e[i]),
|
||||
PGT_l2_page_table |
|
||||
PGT_pae_xen_l2,
|
||||
- d, partial, preemptible);
|
||||
+ d, partial, 1);
|
||||
}
|
||||
else if ( !is_guest_l3_slot(i) ||
|
||||
- (rc = get_page_from_l3e(pl3e[i], pfn, d,
|
||||
- partial, preemptible)) > 0 )
|
||||
+ (rc = get_page_from_l3e(pl3e[i], pfn, d, partial)) > 0 )
|
||||
continue;
|
||||
|
||||
if ( rc == -EAGAIN )
|
||||
@@ -1604,7 +1609,7 @@ static int alloc_l3_table(struct page_in
|
||||
}
|
||||
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
-static int alloc_l4_table(struct page_info *page, int preemptible)
|
||||
+static int alloc_l4_table(struct page_info *page)
|
||||
{
|
||||
struct domain *d = page_get_owner(page);
|
||||
unsigned long pfn = page_to_mfn(page);
|
||||
@@ -1616,8 +1621,7 @@ static int alloc_l4_table(struct page_in
|
||||
i++, partial = 0 )
|
||||
{
|
||||
if ( !is_guest_l4_slot(d, i) ||
|
||||
- (rc = get_page_from_l4e(pl4e[i], pfn, d,
|
||||
- partial, preemptible)) > 0 )
|
||||
+ (rc = get_page_from_l4e(pl4e[i], pfn, d, partial)) > 0 )
|
||||
continue;
|
||||
|
||||
if ( rc == -EAGAIN )
|
||||
@@ -1662,7 +1666,7 @@ static int alloc_l4_table(struct page_in
|
||||
return rc > 0 ? 0 : rc;
|
||||
}
|
||||
#else
|
||||
-#define alloc_l4_table(page, preemptible) (-EINVAL)
|
||||
+#define alloc_l4_table(page) (-EINVAL)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1714,7 +1718,7 @@ static int free_l2_table(struct page_inf
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int free_l3_table(struct page_info *page, int preemptible)
|
||||
+static int free_l3_table(struct page_info *page)
|
||||
{
|
||||
struct domain *d = page_get_owner(page);
|
||||
unsigned long pfn = page_to_mfn(page);
|
||||
@@ -1727,7 +1731,7 @@ static int free_l3_table(struct page_inf
|
||||
do {
|
||||
if ( is_guest_l3_slot(i) )
|
||||
{
|
||||
- rc = put_page_from_l3e(pl3e[i], pfn, partial, preemptible);
|
||||
+ rc = put_page_from_l3e(pl3e[i], pfn, partial, 0);
|
||||
if ( rc < 0 )
|
||||
break;
|
||||
partial = 0;
|
||||
@@ -1754,7 +1758,7 @@ static int free_l3_table(struct page_inf
|
||||
}
|
||||
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
-static int free_l4_table(struct page_info *page, int preemptible)
|
||||
+static int free_l4_table(struct page_info *page)
|
||||
{
|
||||
struct domain *d = page_get_owner(page);
|
||||
unsigned long pfn = page_to_mfn(page);
|
||||
@@ -1764,7 +1768,7 @@ static int free_l4_table(struct page_inf
|
||||
|
||||
do {
|
||||
if ( is_guest_l4_slot(d, i) )
|
||||
- rc = put_page_from_l4e(pl4e[i], pfn, partial, preemptible);
|
||||
+ rc = put_page_from_l4e(pl4e[i], pfn, partial, 0);
|
||||
if ( rc < 0 )
|
||||
break;
|
||||
partial = 0;
|
||||
@@ -1784,7 +1788,7 @@ static int free_l4_table(struct page_inf
|
||||
return rc > 0 ? 0 : rc;
|
||||
}
|
||||
#else
|
||||
-#define free_l4_table(page, preemptible) (-EINVAL)
|
||||
+#define free_l4_table(page) (-EINVAL)
|
||||
#endif
|
||||
|
||||
int page_lock(struct page_info *page)
|
||||
@@ -2023,7 +2027,6 @@ static int mod_l3_entry(l3_pgentry_t *pl
|
||||
l3_pgentry_t nl3e,
|
||||
unsigned long pfn,
|
||||
int preserve_ad,
|
||||
- int preemptible,
|
||||
struct vcpu *vcpu)
|
||||
{
|
||||
l3_pgentry_t ol3e;
|
||||
@@ -2063,7 +2066,7 @@ static int mod_l3_entry(l3_pgentry_t *pl
|
||||
return rc ? 0 : -EFAULT;
|
||||
}
|
||||
|
||||
- rc = get_page_from_l3e(nl3e, pfn, d, 0, preemptible);
|
||||
+ rc = get_page_from_l3e(nl3e, pfn, d, 0);
|
||||
if ( unlikely(rc < 0) )
|
||||
return rc;
|
||||
rc = 0;
|
||||
@@ -2090,7 +2093,7 @@ static int mod_l3_entry(l3_pgentry_t *pl
|
||||
pae_flush_pgd(pfn, pgentry_ptr_to_slot(pl3e), nl3e);
|
||||
}
|
||||
|
||||
- put_page_from_l3e(ol3e, pfn, 0, -preemptible);
|
||||
+ put_page_from_l3e(ol3e, pfn, 0, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2101,7 +2104,6 @@ static int mod_l4_entry(l4_pgentry_t *pl
|
||||
l4_pgentry_t nl4e,
|
||||
unsigned long pfn,
|
||||
int preserve_ad,
|
||||
- int preemptible,
|
||||
struct vcpu *vcpu)
|
||||
{
|
||||
struct domain *d = vcpu->domain;
|
||||
@@ -2134,7 +2136,7 @@ static int mod_l4_entry(l4_pgentry_t *pl
|
||||
return rc ? 0 : -EFAULT;
|
||||
}
|
||||
|
||||
- rc = get_page_from_l4e(nl4e, pfn, d, 0, preemptible);
|
||||
+ rc = get_page_from_l4e(nl4e, pfn, d, 0);
|
||||
if ( unlikely(rc < 0) )
|
||||
return rc;
|
||||
rc = 0;
|
||||
@@ -2153,7 +2155,7 @@ static int mod_l4_entry(l4_pgentry_t *pl
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
- put_page_from_l4e(ol4e, pfn, 0, -preemptible);
|
||||
+ put_page_from_l4e(ol4e, pfn, 0, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2275,10 +2277,12 @@ static int alloc_page_type(struct page_i
|
||||
rc = alloc_l2_table(page, type, preemptible);
|
||||
break;
|
||||
case PGT_l3_page_table:
|
||||
- rc = alloc_l3_table(page, preemptible);
|
||||
+ ASSERT(preemptible);
|
||||
+ rc = alloc_l3_table(page);
|
||||
break;
|
||||
case PGT_l4_page_table:
|
||||
- rc = alloc_l4_table(page, preemptible);
|
||||
+ ASSERT(preemptible);
|
||||
+ rc = alloc_l4_table(page);
|
||||
break;
|
||||
case PGT_seg_desc_page:
|
||||
rc = alloc_segdesc_page(page);
|
||||
@@ -2372,10 +2376,12 @@ int free_page_type(struct page_info *pag
|
||||
if ( !(type & PGT_partial) )
|
||||
page->nr_validated_ptes = L3_PAGETABLE_ENTRIES;
|
||||
#endif
|
||||
- rc = free_l3_table(page, preemptible);
|
||||
+ ASSERT(preemptible);
|
||||
+ rc = free_l3_table(page);
|
||||
break;
|
||||
case PGT_l4_page_table:
|
||||
- rc = free_l4_table(page, preemptible);
|
||||
+ ASSERT(preemptible);
|
||||
+ rc = free_l4_table(page);
|
||||
break;
|
||||
default:
|
||||
MEM_LOG("type %lx pfn %lx\n", type, page_to_mfn(page));
|
||||
@@ -2866,7 +2872,7 @@ static int put_old_guest_table(struct vc
|
||||
if ( !v->arch.old_guest_table )
|
||||
return 0;
|
||||
|
||||
- switch ( rc = put_page_and_type_preemptible(v->arch.old_guest_table, 1) )
|
||||
+ switch ( rc = put_page_and_type_preemptible(v->arch.old_guest_table) )
|
||||
{
|
||||
case -EINTR:
|
||||
case -EAGAIN:
|
||||
@@ -2898,7 +2904,7 @@ int vcpu_destroy_pagetables(struct vcpu
|
||||
if ( paging_mode_refcounts(v->domain) )
|
||||
put_page(page);
|
||||
else
|
||||
- rc = put_page_and_type_preemptible(page, 1);
|
||||
+ rc = put_page_and_type_preemptible(page);
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
@@ -2924,7 +2930,7 @@ int vcpu_destroy_pagetables(struct vcpu
|
||||
if ( paging_mode_refcounts(v->domain) )
|
||||
put_page(page);
|
||||
else
|
||||
- rc = put_page_and_type_preemptible(page, 1);
|
||||
+ rc = put_page_and_type_preemptible(page);
|
||||
}
|
||||
if ( !rc )
|
||||
v->arch.guest_table_user = pagetable_null();
|
||||
@@ -2953,7 +2959,7 @@ int new_guest_cr3(unsigned long mfn)
|
||||
l4e_from_pfn(
|
||||
mfn,
|
||||
(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED)),
|
||||
- pagetable_get_pfn(curr->arch.guest_table), 0, 1, curr);
|
||||
+ pagetable_get_pfn(curr->arch.guest_table), 0, curr);
|
||||
switch ( rc )
|
||||
{
|
||||
case 0:
|
||||
@@ -3016,7 +3022,7 @@ int new_guest_cr3(unsigned long mfn)
|
||||
if ( paging_mode_refcounts(d) )
|
||||
put_page(page);
|
||||
else
|
||||
- switch ( rc = put_page_and_type_preemptible(page, 1) )
|
||||
+ switch ( rc = put_page_and_type_preemptible(page) )
|
||||
{
|
||||
case -EINTR:
|
||||
rc = -EAGAIN;
|
||||
@@ -3327,7 +3333,7 @@ long do_mmuext_op(
|
||||
break;
|
||||
}
|
||||
|
||||
- switch ( rc = put_page_and_type_preemptible(page, 1) )
|
||||
+ switch ( rc = put_page_and_type_preemptible(page) )
|
||||
{
|
||||
case -EINTR:
|
||||
case -EAGAIN:
|
||||
@@ -3405,7 +3411,7 @@ long do_mmuext_op(
|
||||
if ( paging_mode_refcounts(d) )
|
||||
put_page(page);
|
||||
else
|
||||
- switch ( rc = put_page_and_type_preemptible(page, 1) )
|
||||
+ switch ( rc = put_page_and_type_preemptible(page) )
|
||||
{
|
||||
case -EINTR:
|
||||
rc = -EAGAIN;
|
||||
@@ -3882,12 +3888,12 @@ long do_mmu_update(
|
||||
break;
|
||||
case PGT_l3_page_table:
|
||||
rc = mod_l3_entry(va, l3e_from_intpte(req.val), mfn,
|
||||
- cmd == MMU_PT_UPDATE_PRESERVE_AD, 1, v);
|
||||
+ cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
|
||||
break;
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
case PGT_l4_page_table:
|
||||
rc = mod_l4_entry(va, l4e_from_intpte(req.val), mfn,
|
||||
- cmd == MMU_PT_UPDATE_PRESERVE_AD, 1, v);
|
||||
+ cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
|
||||
break;
|
||||
#endif
|
||||
case PGT_writable_page:
|
||||
--- a/xen/include/asm-x86/mm.h
|
||||
+++ b/xen/include/asm-x86/mm.h
|
||||
@@ -384,15 +384,10 @@ static inline void put_page_and_type(str
|
||||
put_page(page);
|
||||
}
|
||||
|
||||
-static inline int put_page_and_type_preemptible(struct page_info *page,
|
||||
- int preemptible)
|
||||
+static inline int put_page_and_type_preemptible(struct page_info *page)
|
||||
{
|
||||
- int rc = 0;
|
||||
+ int rc = put_page_type_preemptible(page);
|
||||
|
||||
- if ( preemptible )
|
||||
- rc = put_page_type_preemptible(page);
|
||||
- else
|
||||
- put_page_type(page);
|
||||
if ( likely(rc == 0) )
|
||||
put_page(page);
|
||||
return rc;
|
@ -1,112 +0,0 @@
|
||||
References: bnc#81???? CVE-2013-1922 XSA-48
|
||||
|
||||
Add -f FMT / --format FMT arg to qemu-nbd
|
||||
|
||||
From: "Daniel P. Berrange" <berrange@redhat.com>
|
||||
|
||||
Currently the qemu-nbd program will auto-detect the format of
|
||||
any disk it is given. This behaviour is known to be insecure.
|
||||
For example, if qemu-nbd initially exposes a 'raw' file to an
|
||||
unprivileged app, and that app runs
|
||||
|
||||
'qemu-img create -f qcow2 -o backing_file=/etc/shadow /dev/nbd0'
|
||||
|
||||
then the next time the app is started, the qemu-nbd will now
|
||||
detect it as a 'qcow2' file and expose /etc/shadow to the
|
||||
unprivileged app.
|
||||
|
||||
The only way to avoid this is to explicitly tell qemu-nbd what
|
||||
disk format to use on the command line, completely disabling
|
||||
auto-detection. This patch adds a '-f' / '--format' arg for
|
||||
this purpose, mirroring what is already available via qemu-img
|
||||
and qemu commands.
|
||||
|
||||
qemu-nbd --format raw -p 9000 evil.img
|
||||
|
||||
will now always use raw, regardless of what format 'evil.img'
|
||||
looks like it contains
|
||||
|
||||
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
|
||||
[Use errx, not err. - Paolo]
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
|
||||
|
||||
[ This is a security issue, CVE-2013-1922 / XSA-48. ]
|
||||
|
||||
--- a/tools/qemu-xen-dir-remote/qemu-nbd.c
|
||||
+++ b/tools/qemu-xen-dir-remote/qemu-nbd.c
|
||||
@@ -247,6 +247,7 @@ out:
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
+ BlockDriver *drv;
|
||||
off_t dev_offset = 0;
|
||||
off_t offset = 0;
|
||||
uint32_t nbdflags = 0;
|
||||
@@ -256,7 +257,7 @@ int main(int argc, char **argv)
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
off_t fd_size;
|
||||
- const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
|
||||
+ const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:t";
|
||||
struct option lopt[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
@@ -271,6 +272,7 @@ int main(int argc, char **argv)
|
||||
{ "snapshot", 0, NULL, 's' },
|
||||
{ "nocache", 0, NULL, 'n' },
|
||||
{ "shared", 1, NULL, 'e' },
|
||||
+ { "format", 1, NULL, 'f' },
|
||||
{ "persistent", 0, NULL, 't' },
|
||||
{ "verbose", 0, NULL, 'v' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
@@ -292,6 +294,7 @@ int main(int argc, char **argv)
|
||||
int max_fd;
|
||||
int persistent = 0;
|
||||
pthread_t client_thread;
|
||||
+ const char *fmt = NULL;
|
||||
|
||||
/* The client thread uses SIGTERM to interrupt the server. A signal
|
||||
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
|
||||
@@ -368,6 +371,9 @@ int main(int argc, char **argv)
|
||||
errx(EXIT_FAILURE, "Shared device number must be greater than 0\n");
|
||||
}
|
||||
break;
|
||||
+ case 'f':
|
||||
+ fmt = optarg;
|
||||
+ break;
|
||||
case 't':
|
||||
persistent = 1;
|
||||
break;
|
||||
@@ -478,9 +484,19 @@ int main(int argc, char **argv)
|
||||
bdrv_init();
|
||||
atexit(bdrv_close_all);
|
||||
|
||||
+ if (fmt) {
|
||||
+ drv = bdrv_find_format(fmt);
|
||||
+ if (!drv) {
|
||||
+ errx(EXIT_FAILURE, "Unknown file format '%s'", fmt);
|
||||
+ }
|
||||
+ } else {
|
||||
+ drv = NULL;
|
||||
+ }
|
||||
+
|
||||
bs = bdrv_new("hda");
|
||||
srcpath = argv[optind];
|
||||
- if ((ret = bdrv_open(bs, srcpath, flags, NULL)) < 0) {
|
||||
+ ret = bdrv_open(bs, srcpath, flags, drv);
|
||||
+ if (ret < 0) {
|
||||
errno = -ret;
|
||||
err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
|
||||
}
|
||||
--- a/tools/qemu-xen-dir-remote/qemu-nbd.texi
|
||||
+++ b/tools/qemu-xen-dir-remote/qemu-nbd.texi
|
||||
@@ -36,6 +36,8 @@ Export Qemu disk image using NBD protoco
|
||||
disconnect the specified device
|
||||
@item -e, --shared=@var{num}
|
||||
device can be shared by @var{num} clients (default @samp{1})
|
||||
+@item -f, --format=@var{fmt}
|
||||
+ force block driver for format @var{fmt} instead of auto-detecting
|
||||
@item -t, --persistent
|
||||
don't exit on the last connection
|
||||
@item -v, --verbose
|
@ -1,57 +0,0 @@
|
||||
References: bnc#8161663 CVE-2013-1952 XSA-49
|
||||
|
||||
VT-d: don't permit SVT_NO_VERIFY entries for known device types
|
||||
|
||||
Only in cases where we don't know what to do we should leave the IRTE
|
||||
blank (suppressing all validation), but we should always log a warning
|
||||
in those cases (as being insecure).
|
||||
|
||||
This is CVE-2013-1952 / XSA-49.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
||||
|
||||
Index: xen-4.2.1-testing/xen/drivers/passthrough/vtd/intremap.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/drivers/passthrough/vtd/intremap.c
|
||||
+++ xen-4.2.1-testing/xen/drivers/passthrough/vtd/intremap.c
|
||||
@@ -440,12 +440,9 @@ static void set_msi_source_id(struct pci
|
||||
{
|
||||
unsigned int sq;
|
||||
|
||||
+ case DEV_TYPE_PCIe_ENDPOINT:
|
||||
case DEV_TYPE_PCIe_BRIDGE:
|
||||
case DEV_TYPE_PCIe2PCI_BRIDGE:
|
||||
- case DEV_TYPE_LEGACY_PCI_BRIDGE:
|
||||
- break;
|
||||
-
|
||||
- case DEV_TYPE_PCIe_ENDPOINT:
|
||||
switch ( pdev->phantom_stride )
|
||||
{
|
||||
case 1: sq = SQ_13_IGNORE_3; break;
|
||||
@@ -457,6 +454,8 @@ static void set_msi_source_id(struct pci
|
||||
break;
|
||||
|
||||
case DEV_TYPE_PCI:
|
||||
+ case DEV_TYPE_LEGACY_PCI_BRIDGE:
|
||||
+ case DEV_TYPE_PCI2PCIe_BRIDGE:
|
||||
ret = find_upstream_bridge(seg, &bus, &devfn, &secbus);
|
||||
if ( ret == 0 ) /* integrated PCI device */
|
||||
{
|
||||
@@ -468,10 +467,15 @@ static void set_msi_source_id(struct pci
|
||||
if ( pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE )
|
||||
set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16,
|
||||
(bus << 8) | pdev->bus);
|
||||
- else if ( pdev_type(seg, bus, devfn) == DEV_TYPE_LEGACY_PCI_BRIDGE )
|
||||
+ else
|
||||
set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16,
|
||||
PCI_BDF2(bus, devfn));
|
||||
}
|
||||
+ else
|
||||
+ dprintk(XENLOG_WARNING VTDPREFIX,
|
||||
+ "d%d: no upstream bridge for %04x:%02x:%02x.%u\n",
|
||||
+ pdev->domain->domain_id,
|
||||
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
break;
|
||||
|
||||
default:
|
@ -1,157 +0,0 @@
|
||||
From 9ca313aa0824f2d350a7a6c9b1ef6c47e0408f1d Mon Sep 17 00:00:00 2001
|
||||
From: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
|
||||
Date: Sat, 23 Aug 2008 23:27:37 +0000
|
||||
Subject: [PATCH] VNC: Support for ExtendedKeyEvent client message
|
||||
|
||||
This patch adds support for the ExtendedKeyEvent client message. This message
|
||||
allows a client to send raw scan codes directly to the server. If the client
|
||||
and server are using the same keymap, then it's unnecessary to use the '-k'
|
||||
option with QEMU when this extension is supported.
|
||||
|
||||
This is extension is currently only implemented by gtk-vnc based clients
|
||||
(gvncviewer, virt-manager, vinagre, etc.).
|
||||
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
|
||||
|
||||
|
||||
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5076 c046a42c-6fe2-441c-8c8c-71466251a162
|
||||
---
|
||||
vnc.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
|
||||
1 files changed, 50 insertions(+), 9 deletions(-)
|
||||
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
@@ -1285,35 +1285,22 @@ static void press_key_altgr_down(VncStat
|
||||
}
|
||||
}
|
||||
|
||||
-static void do_key_event(VncState *vs, int down, uint32_t sym)
|
||||
+static void do_key_event(VncState *vs, int down, int keycode, int sym, int shift)
|
||||
{
|
||||
- int keycode;
|
||||
int shift_keys = 0;
|
||||
- int shift = 0;
|
||||
int keypad = 0;
|
||||
int altgr = 0;
|
||||
int altgr_keys = 0;
|
||||
|
||||
if (is_graphic_console()) {
|
||||
- if (sym >= 'A' && sym <= 'Z') {
|
||||
- sym = sym - 'A' + 'a';
|
||||
- shift = 1;
|
||||
- }
|
||||
- else {
|
||||
+ if (!shift)
|
||||
shift = keysym_is_shift(vs->kbd_layout, sym & 0xFFFF);
|
||||
- }
|
||||
|
||||
altgr = keysym_is_altgr(vs->kbd_layout, sym & 0xFFFF);
|
||||
}
|
||||
shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36];
|
||||
altgr_keys = vs->modifiers_state[0xb8];
|
||||
|
||||
- keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
|
||||
- if (keycode == 0) {
|
||||
- fprintf(stderr, "Key lost : keysym=0x%x(%d)\n", sym, sym);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
/* QEMU console switch */
|
||||
switch(keycode) {
|
||||
case 0x2a: /* Left Shift */
|
||||
@@ -1445,7 +1432,25 @@ static void do_key_event(VncState *vs, i
|
||||
|
||||
static void key_event(VncState *vs, int down, uint32_t sym)
|
||||
{
|
||||
- do_key_event(vs, down, sym);
|
||||
+ int keycode;
|
||||
+ int shift = 0;
|
||||
+
|
||||
+ if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) {
|
||||
+ sym = sym - 'A' + 'a';
|
||||
+ shift = 1;
|
||||
+ }
|
||||
+ keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
|
||||
+ do_key_event(vs, down, keycode, sym, shift);
|
||||
+}
|
||||
+
|
||||
+static void ext_key_event(VncState *vs, int down,
|
||||
+ uint32_t sym, uint16_t keycode)
|
||||
+{
|
||||
+ /* if the user specifies a keyboard layout, always use it */
|
||||
+ if (keyboard_layout)
|
||||
+ key_event(vs, down, sym);
|
||||
+ else
|
||||
+ do_key_event(vs, down, keycode, sym, 0);
|
||||
}
|
||||
|
||||
static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h)
|
||||
@@ -1534,6 +1539,15 @@ static void framebuffer_update_request(V
|
||||
qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
|
||||
}
|
||||
|
||||
+static void send_ext_key_event_ack(VncState *vs)
|
||||
+{
|
||||
+ vnc_write_u8(vs, 0);
|
||||
+ vnc_write_u8(vs, 0);
|
||||
+ vnc_write_u16(vs, 1);
|
||||
+ vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), -258);
|
||||
+ vnc_flush(vs);
|
||||
+}
|
||||
+
|
||||
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
|
||||
{
|
||||
int i;
|
||||
@@ -1562,6 +1576,9 @@ static void set_encodings(VncState *vs,
|
||||
case -257:
|
||||
vs->has_pointer_type_change = 1;
|
||||
break;
|
||||
+ case -258:
|
||||
+ send_ext_key_event_ack(vs);
|
||||
+ break;
|
||||
case 0x574D5669:
|
||||
vs->has_WMVi = 1;
|
||||
default:
|
||||
@@ -1774,6 +1791,24 @@ static int protocol_client_msg(VncState
|
||||
|
||||
client_cut_text(vs, read_u32(data, 4), (char *)(data + 8));
|
||||
break;
|
||||
+ case 255:
|
||||
+ if (len == 1)
|
||||
+ return 2;
|
||||
+
|
||||
+ switch (read_u8(data, 1)) {
|
||||
+ case 0:
|
||||
+ if (len == 2)
|
||||
+ return 12;
|
||||
+
|
||||
+ ext_key_event(vs, read_u16(data, 2),
|
||||
+ read_u32(data, 4), read_u32(data, 8));
|
||||
+ break;
|
||||
+ default:
|
||||
+ printf("Msg: %d\n", read_u16(data, 0));
|
||||
+ vnc_client_error(vs);
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
default:
|
||||
printf("Msg: %d\n", data[0]);
|
||||
vnc_client_error(vs);
|
||||
@@ -2445,10 +2480,11 @@ void vnc_display_init(DisplayState *ds)
|
||||
|
||||
vs->ds = ds;
|
||||
|
||||
- if (!keyboard_layout)
|
||||
- keyboard_layout = "en-us";
|
||||
+ if (keyboard_layout)
|
||||
+ vs->kbd_layout = init_keyboard_layout(keyboard_layout);
|
||||
+ else
|
||||
+ vs->kbd_layout = init_keyboard_layout("en-us");
|
||||
|
||||
- vs->kbd_layout = init_keyboard_layout(keyboard_layout);
|
||||
if (!vs->kbd_layout)
|
||||
exit(1);
|
||||
vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
|
@ -1,45 +0,0 @@
|
||||
When access domU from Windows VNC client, spanish keyboard altgr key
|
||||
doesn't work. According to log info, we found that the keycodes passed
|
||||
from vncclient to qemu vncserver have something wrong. When altgr and "2"
|
||||
pressed, keycodes vncserver receives are:
|
||||
ALT_R down,
|
||||
CTRL_L down,
|
||||
CTRL_L up,
|
||||
ATL_R up,
|
||||
"2" down,
|
||||
"2" up,
|
||||
...
|
||||
Since when send "2" down, there is no altgr modifier, the char displayed
|
||||
on screen will be "2" but not "@".
|
||||
|
||||
To solve this problem, there is another patch applied by upstream which
|
||||
sends an additional altgr modifier before "2" down in the above case.
|
||||
It works well when domU is windows, but on sles10 sp3 domU, sometimes it
|
||||
display "@" and sometimes it still displays "2", especially when press
|
||||
altgr+2 continuously.
|
||||
|
||||
For the sles10 sp3 domU problem, maybe because there are two many alt_r (same
|
||||
keycode as altgr on "es") up and down events and the domU OS couldn't handle
|
||||
it well.
|
||||
|
||||
To furtherly solve this problem, I write this patch, when vncserver
|
||||
is "es" and receives a alt_r keysym (this is already abnormal since "es" has
|
||||
no alt_r), then treat the alt_r as alt_l. This can avoid too many altgr
|
||||
keycodes up and down events and make sure the intentionally added altgr keycode can take effect.
|
||||
|
||||
Signed-off by Chunyan Liu (cyliu@novell.com)
|
||||
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
@@ -1440,6 +1440,9 @@ static void key_event(VncState *vs, int
|
||||
int keycode;
|
||||
int shift = 0;
|
||||
|
||||
+ if ( sym == 0xffea && keyboard_layout && !strcmp(keyboard_layout,"es") )
|
||||
+ sym = 0xffe9;
|
||||
+
|
||||
if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) {
|
||||
sym = sym - 'A' + 'a';
|
||||
shift = 1;
|
@ -1,32 +0,0 @@
|
||||
Subject: modify default read/write flag in bdrv_init.
|
||||
Signed-off by Chunyan Liu <cyliu@novell.com>
|
||||
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/vl.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/vl.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/vl.c
|
||||
@@ -2627,6 +2627,8 @@ int drive_init(struct drive_opt *arg, in
|
||||
strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
|
||||
nb_drives++;
|
||||
|
||||
+ bdrv_flags = BDRV_O_RDWR;
|
||||
+
|
||||
switch(type) {
|
||||
case IF_IDE:
|
||||
case IF_XEN:
|
||||
@@ -2640,6 +2642,7 @@ int drive_init(struct drive_opt *arg, in
|
||||
break;
|
||||
case MEDIA_CDROM:
|
||||
bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM);
|
||||
+ bdrv_flags &= ~BDRV_O_RDWR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -2660,7 +2663,6 @@ int drive_init(struct drive_opt *arg, in
|
||||
}
|
||||
if (!file[0])
|
||||
return -2;
|
||||
- bdrv_flags = 0;
|
||||
if (snapshot) {
|
||||
bdrv_flags |= BDRV_O_SNAPSHOT;
|
||||
cache = 2; /* always use write-back with snapshot */
|
@ -1,129 +0,0 @@
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/block.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/block.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/block.c
|
||||
@@ -350,7 +350,7 @@ int bdrv_file_open(BlockDriverState **pb
|
||||
|
||||
int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
{
|
||||
- return bdrv_open2(bs, filename, flags, NULL);
|
||||
+ return bdrv_open2(bs, filename, flags|BDRV_O_RDWR, NULL);
|
||||
}
|
||||
|
||||
int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
@@ -419,12 +419,13 @@ int bdrv_open2(BlockDriverState *bs, con
|
||||
}
|
||||
bs->drv = drv;
|
||||
bs->opaque = qemu_mallocz(drv->instance_size);
|
||||
- /* Note: for compatibility, we open disk image files as RDWR, and
|
||||
- RDONLY as fallback */
|
||||
if (!(flags & BDRV_O_FILE))
|
||||
- open_flags = (flags & BDRV_O_ACCESS) | (flags & BDRV_O_CACHE_MASK);
|
||||
+ open_flags = flags;
|
||||
else
|
||||
open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
|
||||
+ if (!(open_flags & BDRV_O_RDWR))
|
||||
+ bs->read_only = 1;
|
||||
+
|
||||
ret = drv->bdrv_open(bs, filename, open_flags);
|
||||
if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
|
||||
ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR);
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/usb-msd.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/usb-msd.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/usb-msd.c
|
||||
@@ -551,7 +551,7 @@ USBDevice *usb_msd_init(const char *file
|
||||
s = qemu_mallocz(sizeof(MSDState));
|
||||
|
||||
bdrv = bdrv_new("usb");
|
||||
- if (bdrv_open2(bdrv, filename, 0, drv) < 0)
|
||||
+ if (bdrv_open2(bdrv, filename, BDRV_O_RDWR, drv) < 0)
|
||||
goto fail;
|
||||
s->bs = bdrv;
|
||||
*pbs = bdrv;
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-img.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/qemu-img.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-img.c
|
||||
@@ -32,7 +32,7 @@
|
||||
#endif
|
||||
|
||||
/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
|
||||
-#define BRDV_O_FLAGS BDRV_O_CACHE_WB
|
||||
+#define BDRV_O_FLAGS BDRV_O_CACHE_WB
|
||||
|
||||
static void QEMU_NORETURN error(const char *fmt, ...)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ static int read_password(char *buf, int
|
||||
#endif
|
||||
|
||||
static BlockDriverState *bdrv_new_open(const char *filename,
|
||||
- const char *fmt)
|
||||
+ const char *fmt, int flags)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockDriver *drv;
|
||||
@@ -201,7 +201,7 @@ static BlockDriverState *bdrv_new_open(c
|
||||
} else {
|
||||
drv = &bdrv_raw;
|
||||
}
|
||||
- if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
|
||||
+ if (bdrv_open2(bs, filename, flags, drv) < 0) {
|
||||
error("Could not open '%s'", filename);
|
||||
}
|
||||
if (bdrv_is_encrypted(bs)) {
|
||||
@@ -253,7 +253,7 @@ static int img_create(int argc, char **a
|
||||
size = 0;
|
||||
if (base_filename) {
|
||||
BlockDriverState *bs;
|
||||
- bs = bdrv_new_open(base_filename, NULL);
|
||||
+ bs = bdrv_new_open(base_filename, NULL, BDRV_O_RDWR);
|
||||
bdrv_get_geometry(bs, &size);
|
||||
size *= 512;
|
||||
bdrv_delete(bs);
|
||||
@@ -332,7 +332,7 @@ static int img_commit(int argc, char **a
|
||||
} else {
|
||||
drv = NULL;
|
||||
}
|
||||
- if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
|
||||
+ if (bdrv_open2(bs, filename, BDRV_O_RDWR, drv) < 0) {
|
||||
error("Could not open '%s'", filename);
|
||||
}
|
||||
ret = bdrv_commit(bs);
|
||||
@@ -455,7 +455,8 @@ static int img_convert(int argc, char **
|
||||
|
||||
total_sectors = 0;
|
||||
for (bs_i = 0; bs_i < bs_n; bs_i++) {
|
||||
- bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
|
||||
+ bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt,
|
||||
+ BDRV_O_CACHE_WB|BDRV_O_RDONLY);
|
||||
if (!bs[bs_i])
|
||||
error("Could not open '%s'", argv[optind + bs_i]);
|
||||
bdrv_get_geometry(bs[bs_i], &bs_sectors);
|
||||
@@ -483,7 +484,7 @@ static int img_convert(int argc, char **
|
||||
}
|
||||
}
|
||||
|
||||
- out_bs = bdrv_new_open(out_filename, out_fmt);
|
||||
+ out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_CACHE_WB|BDRV_O_RDWR);
|
||||
|
||||
bs_i = 0;
|
||||
bs_offset = 0;
|
||||
@@ -706,7 +707,7 @@ static int img_info(int argc, char **arg
|
||||
} else {
|
||||
drv = NULL;
|
||||
}
|
||||
- if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
|
||||
+ if (bdrv_open2(bs, filename, BDRV_O_FLAGS|BDRV_O_RDWR, drv) < 0) {
|
||||
error("Could not open '%s'", filename);
|
||||
}
|
||||
bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
|
||||
@@ -810,7 +811,7 @@ static void img_snapshot(int argc, char
|
||||
if (!bs)
|
||||
error("Not enough memory");
|
||||
|
||||
- if (bdrv_open2(bs, filename, 0, NULL) < 0) {
|
||||
+ if (bdrv_open2(bs, filename, BDRV_O_RDWR, NULL) < 0) {
|
||||
error("Could not open '%s'", filename);
|
||||
}
|
||||
|
@ -1,72 +0,0 @@
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
|
||||
@@ -225,6 +225,7 @@ static int open_disk(struct td_state *s,
|
||||
BlockDriver* drv;
|
||||
char* devname;
|
||||
static int devnumber = 0;
|
||||
+ int flags = readonly ? BDRV_O_RDONLY : BDRV_O_RDWR;
|
||||
int i;
|
||||
|
||||
DPRINTF("Opening %s as blktap%d\n", path, devnumber);
|
||||
@@ -247,7 +248,7 @@ static int open_disk(struct td_state *s,
|
||||
DPRINTF("%s driver specified\n", drv ? drv->format_name : "No");
|
||||
|
||||
/* Open the image */
|
||||
- if (bdrv_open2(bs, path, 0, drv) != 0) {
|
||||
+ if (bdrv_open2(bs, path, flags, drv) != 0) {
|
||||
fprintf(stderr, "Could not open image file %s\n", path);
|
||||
return -ENOMEM;
|
||||
}
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
@@ -133,7 +133,8 @@ static void insert_media(void *opaque)
|
||||
else
|
||||
format = &bdrv_raw;
|
||||
|
||||
- bdrv_open2(bs, media_filename[i], 0, format);
|
||||
+ /* Temporary BDRV_O_RDWR */
|
||||
+ bdrv_open2(bs, media_filename[i], BDRV_O_RDWR, format);
|
||||
#ifdef CONFIG_STUBDOM
|
||||
{
|
||||
char *buf, *backend, *params_path, *params;
|
||||
@@ -508,7 +509,8 @@ void xenstore_parse_domain_config(int hv
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
- format = NULL; /* don't know what the format is yet */
|
||||
+ flags = 0;
|
||||
+ format = NULL; /* don't know what the format is yet */
|
||||
/* read the backend path */
|
||||
xenstore_get_backend_path(&bpath, "vbd", danger_path, hvm_domid, e_danger[i]);
|
||||
if (bpath == NULL)
|
||||
@@ -594,6 +596,17 @@ void xenstore_parse_domain_config(int hv
|
||||
format = &bdrv_raw;
|
||||
}
|
||||
|
||||
+ /* read the mode of the device */
|
||||
+ if (pasprintf(&buf, "%s/mode", bpath) == -1)
|
||||
+ continue;
|
||||
+ free(mode);
|
||||
+ mode = xs_read(xsh, XBT_NULL, buf, &len);
|
||||
+
|
||||
+ if (!strcmp(mode, "r") || !strcmp(mode, "ro"))
|
||||
+ flags |= BDRV_O_RDONLY;
|
||||
+ if (!strcmp(mode, "w") || !strcmp(mode, "rw"))
|
||||
+ flags |= BDRV_O_RDWR;
|
||||
+
|
||||
#if 0
|
||||
/* Phantom VBDs are disabled because the use of paths
|
||||
* from guest-controlled areas in xenstore is unsafe.
|
||||
@@ -661,7 +674,7 @@ void xenstore_parse_domain_config(int hv
|
||||
#ifdef CONFIG_STUBDOM
|
||||
if (pasprintf(&danger_buf, "%s/device/vbd/%s", danger_path, e_danger[i]) == -1)
|
||||
continue;
|
||||
- if (bdrv_open2(bs, danger_buf, BDRV_O_CACHE_WB /* snapshot and write-back */, &bdrv_raw) == 0) {
|
||||
+ if (bdrv_open2(bs, danger_buf, flags|BDRV_O_CACHE_WB /* snapshot and write-back */, &bdrv_raw) == 0) {
|
||||
if (pasprintf(&buf, "%s/params", bpath) == -1)
|
||||
continue;
|
||||
free(params);
|
@ -1,27 +0,0 @@
|
||||
Index: xen-4.2.0-testing/tools/blktap/drivers/blktapctrl.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/blktap/drivers/blktapctrl.c
|
||||
+++ xen-4.2.0-testing/tools/blktap/drivers/blktapctrl.c
|
||||
@@ -61,6 +61,9 @@
|
||||
#include "list.h"
|
||||
#include "xs_api.h" /* for xs_fire_next_watch() */
|
||||
|
||||
+#undef DPRINTF
|
||||
+#define DPRINTF(_f, _a...) ((void)0)
|
||||
+
|
||||
#define PIDFILE "/var/run/blktapctrl.pid"
|
||||
|
||||
#define NUM_POLL_FDS 2
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
|
||||
@@ -46,7 +46,7 @@
|
||||
#define BLKTAP_CTRL_DIR "/var/run/tap"
|
||||
|
||||
/* If enabled, print debug messages to stderr */
|
||||
-#if 1
|
||||
+#if 0
|
||||
#define DPRINTF(_f, _a...) fprintf(stderr, __FILE__ ":%d: " _f, __LINE__, ##_a)
|
||||
#else
|
||||
#define DPRINTF(_f, _a...) ((void)0)
|
@ -4,15 +4,14 @@
|
||||
tools/blktap/drivers/tapdisk.c | 16
|
||||
tools/blktap/drivers/tapdisk.h | 16
|
||||
tools/blktap/lib/blktaplib.h | 1
|
||||
tools/python/xen/xend/server/BlktapController.py | 1
|
||||
xen/include/public/io/blkif.h | 2
|
||||
xen/include/public/io/cdromif.h | 122 ++++
|
||||
8 files changed, 726 insertions(+), 3 deletions(-)
|
||||
7 files changed, 726 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: xen-4.2.1-testing/tools/blktap/drivers/Makefile
|
||||
Index: xen-4.3.0-testing/tools/blktap/drivers/Makefile
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/blktap/drivers/Makefile
|
||||
+++ xen-4.2.1-testing/tools/blktap/drivers/Makefile
|
||||
--- xen-4.3.0-testing.orig/tools/blktap/drivers/Makefile
|
||||
+++ xen-4.3.0-testing/tools/blktap/drivers/Makefile
|
||||
@@ -38,8 +38,9 @@ endif
|
||||
CFLAGS += $(PTHREAD_CFLAGS)
|
||||
LDFLAGS += $(PTHREAD_LDFLAGS)
|
||||
@ -33,10 +32,10 @@ Index: xen-4.2.1-testing/tools/blktap/drivers/Makefile
|
||||
BLK-OBJS-y += aes.o
|
||||
BLK-OBJS-y += tapaio.o
|
||||
BLK-OBJS-$(CONFIG_Linux) += blk_linux.o
|
||||
Index: xen-4.2.1-testing/tools/blktap/drivers/block-cdrom.c
|
||||
Index: xen-4.3.0-testing/tools/blktap/drivers/block-cdrom.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ xen-4.2.1-testing/tools/blktap/drivers/block-cdrom.c
|
||||
+++ xen-4.3.0-testing/tools/blktap/drivers/block-cdrom.c
|
||||
@@ -0,0 +1,568 @@
|
||||
+/* block-cdrom.c
|
||||
+ *
|
||||
@ -606,10 +605,10 @@ Index: xen-4.2.1-testing/tools/blktap/drivers/block-cdrom.c
|
||||
+ .td_get_parent_id = tdcdrom_get_parent_id,
|
||||
+ .td_validate_parent = tdcdrom_validate_parent
|
||||
+};
|
||||
Index: xen-4.2.1-testing/tools/blktap/drivers/tapdisk.c
|
||||
Index: xen-4.3.0-testing/tools/blktap/drivers/tapdisk.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/blktap/drivers/tapdisk.c
|
||||
+++ xen-4.2.1-testing/tools/blktap/drivers/tapdisk.c
|
||||
--- xen-4.3.0-testing.orig/tools/blktap/drivers/tapdisk.c
|
||||
+++ xen-4.3.0-testing/tools/blktap/drivers/tapdisk.c
|
||||
@@ -735,6 +735,22 @@ static void get_io_request(struct td_sta
|
||||
goto out;
|
||||
}
|
||||
@ -633,10 +632,10 @@ Index: xen-4.2.1-testing/tools/blktap/drivers/tapdisk.c
|
||||
default:
|
||||
DPRINTF("Unknown block operation\n");
|
||||
break;
|
||||
Index: xen-4.2.1-testing/tools/blktap/drivers/tapdisk.h
|
||||
Index: xen-4.3.0-testing/tools/blktap/drivers/tapdisk.h
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/blktap/drivers/tapdisk.h
|
||||
+++ xen-4.2.1-testing/tools/blktap/drivers/tapdisk.h
|
||||
--- xen-4.3.0-testing.orig/tools/blktap/drivers/tapdisk.h
|
||||
+++ xen-4.3.0-testing/tools/blktap/drivers/tapdisk.h
|
||||
@@ -137,6 +137,9 @@ struct tap_disk {
|
||||
int (*td_get_parent_id) (struct disk_driver *dd, struct disk_id *id);
|
||||
int (*td_validate_parent)(struct disk_driver *dd,
|
||||
@ -681,10 +680,10 @@ Index: xen-4.2.1-testing/tools/blktap/drivers/tapdisk.h
|
||||
};
|
||||
|
||||
typedef struct driver_list_entry {
|
||||
Index: xen-4.2.1-testing/tools/blktap/lib/blktaplib.h
|
||||
Index: xen-4.3.0-testing/tools/blktap/lib/blktaplib.h
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/blktap/lib/blktaplib.h
|
||||
+++ xen-4.2.1-testing/tools/blktap/lib/blktaplib.h
|
||||
--- xen-4.3.0-testing.orig/tools/blktap/lib/blktaplib.h
|
||||
+++ xen-4.3.0-testing/tools/blktap/lib/blktaplib.h
|
||||
@@ -219,6 +219,7 @@ typedef struct msg_pid {
|
||||
#define DISK_TYPE_RAM 3
|
||||
#define DISK_TYPE_QCOW 4
|
||||
@ -693,23 +692,11 @@ Index: xen-4.2.1-testing/tools/blktap/lib/blktaplib.h
|
||||
|
||||
/* xenstore/xenbus: */
|
||||
#define DOMNAME "Domain-0"
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xend/server/BlktapController.py
|
||||
Index: xen-4.3.0-testing/xen/include/public/io/blkif.h
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xend/server/BlktapController.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xend/server/BlktapController.py
|
||||
@@ -15,6 +15,7 @@ blktap1_disk_types = [
|
||||
'ram',
|
||||
'qcow',
|
||||
'qcow2',
|
||||
+ 'cdrom',
|
||||
'ioemu',
|
||||
]
|
||||
|
||||
Index: xen-4.2.1-testing/xen/include/public/io/blkif.h
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/xen/include/public/io/blkif.h
|
||||
+++ xen-4.2.1-testing/xen/include/public/io/blkif.h
|
||||
@@ -379,7 +379,7 @@
|
||||
--- xen-4.3.0-testing.orig/xen/include/public/io/blkif.h
|
||||
+++ xen-4.3.0-testing/xen/include/public/io/blkif.h
|
||||
@@ -439,7 +439,7 @@
|
||||
* Used in SLES sources for device specific command packet
|
||||
* contained within the request. Reserved for that purpose.
|
||||
*/
|
||||
@ -718,10 +705,10 @@ Index: xen-4.2.1-testing/xen/include/public/io/blkif.h
|
||||
/*
|
||||
* Indicate to the backend device that a region of storage is no longer in
|
||||
* use, and may be discarded at any time without impact to the client. If
|
||||
Index: xen-4.2.1-testing/xen/include/public/io/cdromif.h
|
||||
Index: xen-4.3.0-testing/xen/include/public/io/cdromif.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ xen-4.2.1-testing/xen/include/public/io/cdromif.h
|
||||
+++ xen-4.3.0-testing/xen/include/public/io/cdromif.h
|
||||
@@ -0,0 +1,122 @@
|
||||
+/******************************************************************************
|
||||
+ * cdromif.h
|
||||
|
55
blktap.patch
55
blktap.patch
@ -1,55 +0,0 @@
|
||||
bug #239173
|
||||
bug #242953
|
||||
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xend/XendDomainInfo.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
@@ -3317,7 +3317,7 @@ class XendDomainInfo:
|
||||
(fn, BOOTLOADER_LOOPBACK_DEVICE))
|
||||
|
||||
vbd = {
|
||||
- 'mode': 'RO',
|
||||
+ 'mode': 'RW',
|
||||
'device': BOOTLOADER_LOOPBACK_DEVICE,
|
||||
}
|
||||
|
||||
Index: xen-4.2.1-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
+++ xen-4.2.1-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
@@ -447,9 +447,9 @@ void xenstore_parse_domain_config(int hv
|
||||
{
|
||||
char **e_danger = NULL;
|
||||
char *buf = NULL;
|
||||
- char *fpath = NULL, *bpath = NULL,
|
||||
+ char *fpath = NULL, *bpath = NULL, *btype = NULL,
|
||||
*dev = NULL, *params = NULL, *drv = NULL;
|
||||
- int i, ret;
|
||||
+ int i, ret, is_tap;
|
||||
unsigned int len, num, hd_index, pci_devid = 0;
|
||||
BlockDriverState *bs;
|
||||
BlockDriver *format;
|
||||
@@ -486,6 +486,14 @@ void xenstore_parse_domain_config(int hv
|
||||
e_danger[i]);
|
||||
if (bpath == NULL)
|
||||
continue;
|
||||
+ /* check to see if type is tap or not */
|
||||
+ if (pasprintf(&buf, "%s/type", bpath) == -1)
|
||||
+ continue;
|
||||
+ free(btype);
|
||||
+ btype = xs_read(xsh, XBT_NULL, buf, &len);
|
||||
+ if (btype == NULL)
|
||||
+ continue;
|
||||
+ is_tap = !strncmp(btype, "tap", 3);
|
||||
/* read the name of the device */
|
||||
if (pasprintf(&buf, "%s/dev", bpath) == -1)
|
||||
continue;
|
||||
@@ -777,6 +785,7 @@ void xenstore_parse_domain_config(int hv
|
||||
free(mode);
|
||||
free(params);
|
||||
free(dev);
|
||||
+ free(btype);
|
||||
free(bpath);
|
||||
free(buf);
|
||||
free(danger_buf);
|
14
blktapctrl-disable-debug-printf.patch
Normal file
14
blktapctrl-disable-debug-printf.patch
Normal file
@ -0,0 +1,14 @@
|
||||
Index: xen-4.2.0-testing/tools/blktap/drivers/blktapctrl.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/blktap/drivers/blktapctrl.c
|
||||
+++ xen-4.2.0-testing/tools/blktap/drivers/blktapctrl.c
|
||||
@@ -61,6 +61,9 @@
|
||||
#include "list.h"
|
||||
#include "xs_api.h" /* for xs_fire_next_watch() */
|
||||
|
||||
+#undef DPRINTF
|
||||
+#define DPRINTF(_f, _a...) ((void)0)
|
||||
+
|
||||
#define PIDFILE "/var/run/blktapctrl.pid"
|
||||
|
||||
#define NUM_POLL_FDS 2
|
33
block-dmmd
33
block-dmmd
@ -93,21 +93,36 @@ function deactivate_md()
|
||||
|
||||
function activate_lvm()
|
||||
{
|
||||
# First scan for PVs and VGs; we may then have to activate the VG
|
||||
# first, but can ignore errors:
|
||||
# /sbin/pvscan || :
|
||||
# /sbin/vgscan --mknodes || :
|
||||
# /sbin/vgchange -ay ${1%/*} || :
|
||||
/sbin/lvchange -ay $1
|
||||
if [ $? -eq 0 ]; then
|
||||
return 0
|
||||
local run_timeout=90
|
||||
local parsed_timeout
|
||||
local end_time
|
||||
|
||||
# Parse device-create-timeout from /etc/xen/xend-config.sxp
|
||||
# If not set, use default timeout of 90s
|
||||
parsed_timeout=$(grep -v "^[ \t]*#.*" /etc/xen/xend-config.sxp|sed -n 's/(device-create-timeout \+\([0-9]\+\))/\1/p')
|
||||
if [ ! -z $parsed_timeout ]; then
|
||||
run_timeout=$((${parsed_timeout}*9/10))
|
||||
fi
|
||||
|
||||
end_time=$(($(date +%s)+${run_timeout}))
|
||||
while true; do
|
||||
/sbin/lvchange -aey $1
|
||||
if [ $? -eq 0 -a -e $1 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
sleep 0.1
|
||||
if [ $(date +%s) -ge ${end_time} ]; then
|
||||
log err "Failed to activate $1 within ${run_timeout} seconds"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
function deactivate_lvm()
|
||||
{
|
||||
/sbin/lvchange -an $1
|
||||
/sbin/lvchange -aen $1
|
||||
if [ $? -eq 0 ]; then
|
||||
# We may have to deactivate the VG now, but can ignore errors:
|
||||
# /sbin/vgchange -an ${1%/*} || :
|
||||
|
@ -1,140 +0,0 @@
|
||||
From f1ebeae7802a5775422004f62630c42e46dcf664 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@suse.de>
|
||||
Date: Tue, 10 Mar 2009 16:32:40 +0100
|
||||
Subject: [PATCH 3/6] ioemu: Build tapdisk-ioemu binary
|
||||
|
||||
When changing away from the old ioemu, changes in the Makefiles
|
||||
resulted in tapdisk-ioemu appearing there, but actually not
|
||||
being built. This patch re-enables the build of tapdisk-ioemu.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@suse.de>
|
||||
---
|
||||
Makefile | 22 +++++++++++++++-------
|
||||
configure | 2 +-
|
||||
qemu-tool.c | 2 +-
|
||||
tapdisk-ioemu.c | 17 -----------------
|
||||
4 files changed, 17 insertions(+), 26 deletions(-)
|
||||
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/Makefile
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/Makefile
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/Makefile
|
||||
@@ -46,14 +46,6 @@ $(filter %-user,$(SUBDIR_RULES)): libqem
|
||||
|
||||
recurse-all: $(SUBDIR_RULES)
|
||||
|
||||
-CPPFLAGS += -I$(XEN_ROOT)/tools/libxc
|
||||
-CPPFLAGS += -I$(XEN_ROOT)/tools/blktap/lib
|
||||
-CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore
|
||||
-CPPFLAGS += -I$(XEN_ROOT)/tools/include
|
||||
-
|
||||
-tapdisk-ioemu: tapdisk-ioemu.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c hw/xen_blktap.c osdep.c
|
||||
- $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
|
||||
-
|
||||
#######################################################################
|
||||
# BLOCK_OBJS is code used by both qemu system emulation and qemu-img
|
||||
|
||||
@@ -72,6 +64,21 @@ endif
|
||||
BLOCK_OBJS += block-raw-posix.o
|
||||
endif
|
||||
|
||||
+#######################################################################
|
||||
+# tapdisk-ioemu
|
||||
+
|
||||
+hw/tapdisk-xen_blktap.o: hw/xen_blktap.c
|
||||
+ $(CC) $(CFLAGS) $(CPPFLAGS) -DQEMU_IMG -DQEMU_TOOL -c -o $@ $<
|
||||
+tapdisk-ioemu.o: tapdisk-ioemu.c
|
||||
+ $(CC) $(CFLAGS) $(CPPFLAGS) -DQEMU_IMG -DQEMU_TOOL -c -o $@ $<
|
||||
+
|
||||
+tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/libxc
|
||||
+tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/blktap/lib
|
||||
+tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore
|
||||
+tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/include
|
||||
+tapdisk-ioemu: tapdisk-ioemu.o $(BLOCK_OBJS) qemu-tool.o hw/tapdisk-xen_blktap.o
|
||||
+ $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS)
|
||||
+
|
||||
######################################################################
|
||||
# libqemu_common.a: Target independent part of system emulation. The
|
||||
# long term path is to suppress *all* target specific code in case of
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/configure
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/configure
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/configure
|
||||
@@ -1511,7 +1511,7 @@ bsd)
|
||||
;;
|
||||
esac
|
||||
|
||||
-tools=
|
||||
+tools="tapdisk-ioemu"
|
||||
if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
|
||||
tools="qemu-img\$(EXESUF) $tools"
|
||||
if [ "$linux" = "yes" ] ; then
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-tool.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/qemu-tool.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-tool.c
|
||||
@@ -68,7 +68,7 @@ void qemu_bh_delete(QEMUBH *bh)
|
||||
qemu_free(bh);
|
||||
}
|
||||
|
||||
-int qemu_set_fd_handler2(int fd,
|
||||
+int __attribute__((weak)) qemu_set_fd_handler2(int fd,
|
||||
IOCanRWHandler *fd_read_poll,
|
||||
IOHandler *fd_read,
|
||||
IOHandler *fd_write,
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/tapdisk-ioemu.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/tapdisk-ioemu.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/tapdisk-ioemu.c
|
||||
@@ -12,34 +12,12 @@
|
||||
|
||||
extern void qemu_aio_init(void);
|
||||
extern void qemu_aio_poll(void);
|
||||
-extern void bdrv_init(void);
|
||||
-
|
||||
-extern void *qemu_mallocz(size_t size);
|
||||
-extern void qemu_free(void *ptr);
|
||||
|
||||
extern void *fd_start;
|
||||
|
||||
int domid = 0;
|
||||
FILE* logfile;
|
||||
|
||||
-void term_printf(const char *fmt, ...)
|
||||
-{
|
||||
- va_list ap;
|
||||
- va_start(ap, fmt);
|
||||
- vprintf(fmt, ap);
|
||||
- va_end(ap);
|
||||
-}
|
||||
-
|
||||
-void term_print_filename(const char *filename)
|
||||
-{
|
||||
- term_printf(filename);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
|
||||
-typedef int IOCanRWHandler(void *opaque);
|
||||
-typedef void IOHandler(void *opaque);
|
||||
-
|
||||
typedef struct IOHandlerRecord {
|
||||
int fd;
|
||||
IOCanRWHandler *fd_read_poll;
|
||||
@@ -103,7 +81,6 @@ int main(void)
|
||||
logfile = stderr;
|
||||
|
||||
bdrv_init();
|
||||
- qemu_aio_init();
|
||||
init_blktap();
|
||||
|
||||
/* Daemonize */
|
||||
@@ -115,8 +92,6 @@ int main(void)
|
||||
* completed aio operations.
|
||||
*/
|
||||
while (1) {
|
||||
- qemu_aio_poll();
|
||||
-
|
||||
max_fd = -1;
|
||||
FD_ZERO(&rfds);
|
||||
for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next)
|
@ -1,16 +0,0 @@
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
@@ -1329,6 +1329,11 @@ static void do_key_event(VncState *vs, i
|
||||
}
|
||||
break;
|
||||
case 0x3a: /* CapsLock */
|
||||
+ if(!down){
|
||||
+ vs->modifiers_state[keycode] ^= 1;
|
||||
+ kbd_put_keycode(keycode | 0x80);
|
||||
+ }
|
||||
+ return;
|
||||
case 0x45: /* NumLock */
|
||||
if (down) {
|
||||
kbd_put_keycode(keycode & 0x7f);
|
@ -1,496 +0,0 @@
|
||||
Index: xen-4.2.0-testing/tools/python/xen/xend/server/HalDaemon.py
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ xen-4.2.0-testing/tools/python/xen/xend/server/HalDaemon.py
|
||||
@@ -0,0 +1,243 @@
|
||||
+#!/usr/bin/env python
|
||||
+# -*- mode: python; -*-
|
||||
+#============================================================================
|
||||
+# 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) 2007 Pat Campbell <plc@novell.com>
|
||||
+# Copyright (C) 2007 Novell Inc.
|
||||
+#============================================================================
|
||||
+
|
||||
+"""hald (Hardware Abstraction Layer Daemon) watcher for Xen management
|
||||
+ of removable block device media.
|
||||
+
|
||||
+"""
|
||||
+
|
||||
+import gobject
|
||||
+import dbus
|
||||
+import dbus.glib
|
||||
+import os
|
||||
+import types
|
||||
+import sys
|
||||
+import signal
|
||||
+import traceback
|
||||
+from xen.xend.xenstore.xstransact import xstransact, complete
|
||||
+from xen.xend.xenstore.xsutil import xshandle
|
||||
+from xen.xend import PrettyPrint
|
||||
+from xen.xend import XendLogging
|
||||
+from xen.xend.XendLogging import log
|
||||
+
|
||||
+DEVICE_TYPES = ['vbd', 'tap']
|
||||
+
|
||||
+class HalDaemon:
|
||||
+ """The Hald block device watcher for XEN
|
||||
+ """
|
||||
+
|
||||
+ """Default path to the log file. """
|
||||
+ logfile_default = "/var/log/xen/hald.log"
|
||||
+
|
||||
+ """Default level of information to be logged."""
|
||||
+ loglevel_default = 'INFO'
|
||||
+
|
||||
+
|
||||
+ def __init__(self):
|
||||
+
|
||||
+ XendLogging.init(self.logfile_default, self.loglevel_default)
|
||||
+ log.debug( "%s", "__init__")
|
||||
+
|
||||
+ self.udi_dict = {}
|
||||
+ self.debug = 0
|
||||
+ self.dbpath = "/local/domain/0/backend"
|
||||
+ self.bus = dbus.SystemBus()
|
||||
+ self.hal_manager_obj = self.bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
|
||||
+ self.hal_manager = dbus.Interface( self.hal_manager_obj, 'org.freedesktop.Hal.Manager')
|
||||
+ self.gatherBlockDevices()
|
||||
+ self.registerDeviceCallbacks()
|
||||
+
|
||||
+ def run(self):
|
||||
+ log.debug( "%s", "In new run" );
|
||||
+ try:
|
||||
+ self.mainloop = gobject.MainLoop()
|
||||
+ self.mainloop.run()
|
||||
+ except KeyboardInterrupt, ex:
|
||||
+ log.debug('Keyboard exception handler: %s', ex )
|
||||
+ self.mainloop.quit()
|
||||
+ except Exception, ex:
|
||||
+ log.debug('Generic exception handler: %s', ex )
|
||||
+ self.mainloop.quit()
|
||||
+
|
||||
+ def __del__(self):
|
||||
+ log.debug( "%s", "In del " );
|
||||
+ self.unRegisterDeviceCallbacks()
|
||||
+ self.mainloop.quit()
|
||||
+
|
||||
+ def shutdown(self):
|
||||
+ log.debug( "%s", "In shutdown now " );
|
||||
+ self.unRegisterDeviceCallbacks()
|
||||
+ self.mainloop.quit()
|
||||
+
|
||||
+ def stop(self):
|
||||
+ log.debug( "%s", "In stop now " );
|
||||
+ self.unRegisterDeviceCallbacks()
|
||||
+ self.mainloop.quit()
|
||||
+
|
||||
+ def gatherBlockDevices(self):
|
||||
+
|
||||
+ # Get all the current devices from hal and save in a dictionary
|
||||
+ try:
|
||||
+ device_names = self.hal_manager.GetAllDevices()
|
||||
+ i = 0;
|
||||
+ for name in device_names:
|
||||
+ #log.debug("device name, device=%s",name)
|
||||
+ dev_obj = self.bus.get_object ('org.freedesktop.Hal', name)
|
||||
+ dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device')
|
||||
+ dev_properties = dev_obj.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device")
|
||||
+ if dev_properties.has_key('block.device'):
|
||||
+ dev_str = dev_properties['block.device']
|
||||
+ dev_major = dev_properties['block.major']
|
||||
+ dev_minor = dev_properties['block.minor']
|
||||
+ udi_info = {}
|
||||
+ udi_info['device'] = dev_str
|
||||
+ udi_info['major'] = dev_major
|
||||
+ udi_info['minor'] = dev_minor
|
||||
+ udi_info['udi'] = name
|
||||
+ self.udi_dict[i] = udi_info
|
||||
+ i = i + 1
|
||||
+ except Exception, ex:
|
||||
+ print >>sys.stderr, 'Exception gathering block devices:', ex
|
||||
+ log.warn("Exception gathering block devices (%s)",ex)
|
||||
+
|
||||
+ #
|
||||
+ def registerDeviceCallbacks(self):
|
||||
+ # setup the callbacks for when the gdl changes
|
||||
+ self.hal_manager.connect_to_signal('DeviceAdded', self.device_added_callback)
|
||||
+ self.hal_manager.connect_to_signal('DeviceRemoved', self.device_removed_callback)
|
||||
+
|
||||
+ #
|
||||
+ def unRegisterDeviceCallbacks(self):
|
||||
+ # setup the callbacks for when the gdl changes
|
||||
+ self.hal_manager.remove_signal_receiver(self.device_added_callback,'DeviceAdded')
|
||||
+ self.hal_manager.remove_signal_receiver(self.device_removed_callback,'DeviceRemoved')
|
||||
+
|
||||
+ #
|
||||
+ def device_removed_callback(self,udi):
|
||||
+ log.debug('UDI %s was removed',udi)
|
||||
+ self.show_dict(self.udi_dict)
|
||||
+ for key in self.udi_dict:
|
||||
+ udi_info = self.udi_dict[key]
|
||||
+ if udi_info['udi'] == udi:
|
||||
+ device = udi_info['device']
|
||||
+ major = udi_info['major']
|
||||
+ minor = udi_info['minor']
|
||||
+ self.change_xenstore( "remove", device, major, minor)
|
||||
+
|
||||
+ # Adds device to dictionary if not already there
|
||||
+ def device_added_callback(self,udi):
|
||||
+ log.debug('UDI %s was added', udi)
|
||||
+ self.show_dict(self.udi_dict)
|
||||
+ dev_obj = self.bus.get_object ('org.freedesktop.Hal', udi)
|
||||
+ dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device')
|
||||
+ device = dev.GetProperty ('block.device')
|
||||
+ major = dev.GetProperty ('block.major')
|
||||
+ minor = dev.GetProperty ('block.minor')
|
||||
+ udi_info = {}
|
||||
+ udi_info['device'] = device
|
||||
+ udi_info['major'] = major
|
||||
+ udi_info['minor'] = minor
|
||||
+ udi_info['udi'] = udi
|
||||
+ already = 0
|
||||
+ cnt = 0;
|
||||
+ for key in self.udi_dict:
|
||||
+ info = self.udi_dict[key]
|
||||
+ if info['udi'] == udi:
|
||||
+ already = 1
|
||||
+ break
|
||||
+ cnt = cnt + 1
|
||||
+ if already == 0:
|
||||
+ self.udi_dict[cnt] = udi_info;
|
||||
+ log.debug('UDI %s was added, device:%s major:%s minor:%s index:%d\n', udi, device, major, minor, cnt)
|
||||
+ self.change_xenstore( "add", device, major, minor)
|
||||
+
|
||||
+ # Debug helper, shows dictionary contents
|
||||
+ def show_dict(self,dict=None):
|
||||
+ if self.debug == 0 :
|
||||
+ return
|
||||
+ if dict == None :
|
||||
+ dict = self.udi_dict
|
||||
+ for key in dict:
|
||||
+ log.debug('udi_info %s udi_info:%s',key,dict[key])
|
||||
+
|
||||
+ # Set or clear xenstore media-present depending on the action argument
|
||||
+ # for every vbd that has this block device
|
||||
+ def change_xenstore(self,action, device, major, minor):
|
||||
+ for type in DEVICE_TYPES:
|
||||
+ path = self.dbpath + '/' + type
|
||||
+ domains = xstransact.List(path)
|
||||
+ log.debug('domains: %s', domains)
|
||||
+ for domain in domains: # for each domain
|
||||
+ devices = xstransact.List( path + '/' + domain)
|
||||
+ log.debug('devices: %s',devices)
|
||||
+ for device in devices: # for each vbd device
|
||||
+ str = device.split('/')
|
||||
+ vbd_type = None;
|
||||
+ vbd_physical_device = None
|
||||
+ vbd_media = None
|
||||
+ vbd_device_path = path + '/' + domain + '/' + device
|
||||
+ listing = xstransact.List(vbd_device_path)
|
||||
+ for entry in listing: # for each entry
|
||||
+ item = path + '/' + entry
|
||||
+ value = xstransact.Read( vbd_device_path + '/' + entry)
|
||||
+ log.debug('%s=%s',item,value)
|
||||
+ if item.find('media-present') != -1:
|
||||
+ vbd_media = item;
|
||||
+ vbd_media_path = item
|
||||
+ if item.find('physical-device') != -1:
|
||||
+ vbd_physical_device = value;
|
||||
+ if item.find('type') != -1:
|
||||
+ vbd_type = value;
|
||||
+ if vbd_type is not None and vbd_physical_device is not None and vbd_media is not None :
|
||||
+ inode = vbd_physical_device.split(':')
|
||||
+ imajor = parse_hex(inode[0])
|
||||
+ iminor = parse_hex(inode[1])
|
||||
+ log.debug("action:%s major:%s- minor:%s- imajor:%s- iminor:%s- inode: %s",
|
||||
+ action,major,minor, imajor, iminor, inode)
|
||||
+ if int(imajor) == int(major) and int(iminor) == int(minor):
|
||||
+ if action == "add":
|
||||
+ xs_dict = {'media': "1"}
|
||||
+ xstransact.Write(vbd_device_path, 'media-present', "1" )
|
||||
+ log.debug("wrote xenstore media-present 1 path:%s",vbd_media_path)
|
||||
+ else:
|
||||
+ xstransact.Write(vbd_device_path, 'media-present', "0" )
|
||||
+ log.debug("wrote xenstore media 0 path:%s",vbd_media_path)
|
||||
+
|
||||
+def mylog( fmt, *args):
|
||||
+ f = open('/tmp/haldaemon.log', 'a')
|
||||
+ print >>f, "HalDaemon ", fmt % args
|
||||
+ f.close()
|
||||
+
|
||||
+
|
||||
+def parse_hex(val):
|
||||
+ try:
|
||||
+ if isinstance(val, types.StringTypes):
|
||||
+ return int(val, 16)
|
||||
+ else:
|
||||
+ return val
|
||||
+ except ValueError:
|
||||
+ return None
|
||||
+
|
||||
+if __name__ == "__main__":
|
||||
+ watcher = HalDaemon()
|
||||
+ watcher.run()
|
||||
+ print 'Falling off end'
|
||||
+
|
||||
+
|
||||
Index: xen-4.2.0-testing/tools/python/xen/xend/server/Hald.py
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ xen-4.2.0-testing/tools/python/xen/xend/server/Hald.py
|
||||
@@ -0,0 +1,125 @@
|
||||
+#============================================================================
|
||||
+# 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) 2007 Pat Campbell <plc@novell.com>
|
||||
+# Copyright (C) 2007 Novell Inc.
|
||||
+#============================================================================
|
||||
+
|
||||
+import errno
|
||||
+import types
|
||||
+import os
|
||||
+import sys
|
||||
+import time
|
||||
+import signal
|
||||
+from traceback import print_exc
|
||||
+
|
||||
+from xen.xend.XendLogging import log
|
||||
+
|
||||
+class Hald:
|
||||
+ def __init__(self):
|
||||
+ self.ready = False
|
||||
+ self.running = True
|
||||
+
|
||||
+ def run(self):
|
||||
+ """Starts the HalDaemon process
|
||||
+ """
|
||||
+ self.ready = True
|
||||
+ try:
|
||||
+ myfile = self.find("xen/xend/server/HalDaemon.py")
|
||||
+ args = (["python", myfile ])
|
||||
+ self.pid = self.daemonize("python", args )
|
||||
+ #log.debug( "%s %s pid:%d", "Hald.py starting ", args, self.pid )
|
||||
+ except:
|
||||
+ self.pid = -1
|
||||
+ log.debug("Unable to start HalDaemon process")
|
||||
+
|
||||
+ def shutdown(self):
|
||||
+ """Shutdown the HalDaemon process
|
||||
+ """
|
||||
+ log.debug("%s pid:%d", "Hald.shutdown()", self.pid)
|
||||
+ self.running = False
|
||||
+ self.ready = False
|
||||
+ if self.pid != -1:
|
||||
+ try:
|
||||
+ os.kill(self.pid, signal.SIGINT)
|
||||
+ except:
|
||||
+ print_exc()
|
||||
+
|
||||
+ def daemonize(self,prog, args):
|
||||
+ """Runs a program as a daemon with the list of arguments. Returns the PID
|
||||
+ of the daemonized program, or returns 0 on error.
|
||||
+ Copied from xm/create.py instead of importing to reduce coupling
|
||||
+ """
|
||||
+ r, w = os.pipe()
|
||||
+ pid = os.fork()
|
||||
+
|
||||
+ if pid == 0:
|
||||
+ os.close(r)
|
||||
+ w = os.fdopen(w, 'w')
|
||||
+ os.setsid()
|
||||
+ try:
|
||||
+ pid2 = os.fork()
|
||||
+ except:
|
||||
+ pid2 = None
|
||||
+ if pid2 == 0:
|
||||
+ os.chdir("/")
|
||||
+ env = os.environ.copy()
|
||||
+ env['PYTHONPATH'] = self.getpythonpath()
|
||||
+ for fd in range(0, 256):
|
||||
+ try:
|
||||
+ os.close(fd)
|
||||
+ except:
|
||||
+ pass
|
||||
+ os.open("/dev/null", os.O_RDWR)
|
||||
+ os.dup2(0, 1)
|
||||
+ os.dup2(0, 2)
|
||||
+ os.execvpe(prog, args, env)
|
||||
+ os._exit(1)
|
||||
+ else:
|
||||
+ w.write(str(pid2 or 0))
|
||||
+ w.close()
|
||||
+ os._exit(0)
|
||||
+ os.close(w)
|
||||
+ r = os.fdopen(r)
|
||||
+ daemon_pid = int(r.read())
|
||||
+ r.close()
|
||||
+ os.waitpid(pid, 0)
|
||||
+ #log.debug( "daemon_pid: %d", daemon_pid )
|
||||
+ return daemon_pid
|
||||
+
|
||||
+ def getpythonpath(self):
|
||||
+ str = " "
|
||||
+ for p in sys.path:
|
||||
+ if str != " ":
|
||||
+ str = str + ":" + p
|
||||
+ else:
|
||||
+ if str != "":
|
||||
+ str = p
|
||||
+ return str
|
||||
+
|
||||
+ def find(self,path, matchFunc=os.path.isfile):
|
||||
+ """Find a module in the sys.path
|
||||
+ From web page: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52224
|
||||
+ """
|
||||
+ for dirname in sys.path:
|
||||
+ candidate = os.path.join(dirname, path)
|
||||
+ if matchFunc(candidate):
|
||||
+ return candidate
|
||||
+ raise Error("Can't find file %s" % path)
|
||||
+
|
||||
+if __name__ == "__main__":
|
||||
+ watcher = Hald()
|
||||
+ watcher.run()
|
||||
+ time.sleep(10)
|
||||
+ watcher.shutdown()
|
||||
Index: xen-4.2.0-testing/tools/python/xen/xend/server/SrvServer.py
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/python/xen/xend/server/SrvServer.py
|
||||
+++ xen-4.2.0-testing/tools/python/xen/xend/server/SrvServer.py
|
||||
@@ -57,6 +57,7 @@ from xen.web.SrvDir import SrvDir
|
||||
|
||||
from SrvRoot import SrvRoot
|
||||
from XMLRPCServer import XMLRPCServer
|
||||
+from xen.xend.server.Hald import Hald
|
||||
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
@@ -252,6 +253,8 @@ def _loadConfig(servers, root, reload):
|
||||
if xoptions.get_xend_unix_xmlrpc_server():
|
||||
servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
|
||||
|
||||
+ servers.add(Hald())
|
||||
+
|
||||
|
||||
def create():
|
||||
root = SrvDir()
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "exec-all.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
+#include "console.h"
|
||||
#include "hw.h"
|
||||
#include "pci.h"
|
||||
#include "qemu-timer.h"
|
||||
@@ -595,6 +596,21 @@ void xenstore_parse_domain_config(int hv
|
||||
#endif
|
||||
|
||||
bs = bdrv_new(dev);
|
||||
+
|
||||
+ /* if cdrom physical put a watch on media-present */
|
||||
+ if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) {
|
||||
+ if (drv && !strcmp(drv, "phy")) {
|
||||
+ if (pasprintf(&buf, "%s/media-present", bpath) != -1) {
|
||||
+ if (bdrv_is_inserted(bs))
|
||||
+ xs_write(xsh, XBT_NULL, buf, "1", strlen("1"));
|
||||
+ else {
|
||||
+ xs_write(xsh, XBT_NULL, buf, "0", strlen("0"));
|
||||
+ }
|
||||
+ xs_watch(xsh, buf, "media-present");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* check if it is a cdrom */
|
||||
if (danger_type && !strcmp(danger_type, "cdrom")) {
|
||||
bdrv_set_type_hint(bs, BDRV_TYPE_CDROM);
|
||||
@@ -1030,6 +1046,50 @@ static void xenstore_process_vcpu_set_ev
|
||||
return;
|
||||
}
|
||||
|
||||
+static void xenstore_process_media_change_event(char **vec)
|
||||
+{
|
||||
+ char *media_present = NULL;
|
||||
+ unsigned int len;
|
||||
+
|
||||
+ media_present = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len);
|
||||
+
|
||||
+ if (media_present) {
|
||||
+ BlockDriverState *bs;
|
||||
+ char *buf = NULL, *cp = NULL, *path = NULL, *dev = NULL;
|
||||
+
|
||||
+ path = strdup(vec[XS_WATCH_PATH]);
|
||||
+ cp = strstr(path, "media-present");
|
||||
+ if (cp){
|
||||
+ *(cp-1) = '\0';
|
||||
+ pasprintf(&buf, "%s/dev", path);
|
||||
+ dev = xs_read(xsh, XBT_NULL, buf, &len);
|
||||
+ if (dev) {
|
||||
+ if ( !strncmp(dev, "xvd", 3)) {
|
||||
+ memmove(dev, dev+1, strlen(dev));
|
||||
+ dev[0] = 'h';
|
||||
+ dev[1] = 'd';
|
||||
+ }
|
||||
+ bs = bdrv_find(dev);
|
||||
+ if (!bs) {
|
||||
+ term_printf("device not found\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ if (strcmp(media_present, "0") == 0 && bs) {
|
||||
+ bdrv_close(bs);
|
||||
+ }
|
||||
+ else if (strcmp(media_present, "1") == 0 &&
|
||||
+ bs != NULL && bs->drv == NULL) {
|
||||
+ if (bdrv_open(bs, bs->filename, 0 /* snapshot */) < 0) {
|
||||
+ fprintf(logfile, "%s() qemu: could not open cdrom disk '%s'\n",
|
||||
+ __func__, bs->filename);
|
||||
+ }
|
||||
+ bs->media_changed = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void xenstore_process_event(void *opaque)
|
||||
{
|
||||
char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL;
|
||||
@@ -1065,6 +1125,11 @@ void xenstore_process_event(void *opaque
|
||||
xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN],
|
||||
xenstore_watch_callbacks[i].opaque);
|
||||
|
||||
+ if (!strcmp(vec[XS_WATCH_TOKEN], "media-present")) {
|
||||
+ xenstore_process_media_change_event(vec);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
hd_index = drive_name_to_index(vec[XS_WATCH_TOKEN]);
|
||||
if (hd_index == -1) {
|
||||
fprintf(stderr,"medium change watch on `%s' -"
|
@ -1,157 +0,0 @@
|
||||
Add support of change-vnc-password while vm is running.
|
||||
|
||||
Signed-off-by: Chunyan Liu <cyliu@novell.com>
|
||||
|
||||
Index: xen-4.2.1-testing/tools/qemu-xen-traditional-dir-remote/vl.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/qemu-xen-traditional-dir-remote/vl.c
|
||||
+++ xen-4.2.1-testing/tools/qemu-xen-traditional-dir-remote/vl.c
|
||||
@@ -200,7 +200,7 @@ DriveInfo drives_table[MAX_DRIVES+1];
|
||||
int nb_drives;
|
||||
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
|
||||
int vga_ram_size;
|
||||
-static DisplayState *display_state;
|
||||
+DisplayState *display_state;
|
||||
int nographic;
|
||||
static int curses;
|
||||
static int sdl;
|
||||
Index: xen-4.2.1-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
+++ xen-4.2.1-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
|
||||
@@ -2627,6 +2627,7 @@ int vnc_display_password(DisplayState *d
|
||||
if (password && password[0]) {
|
||||
if (!(vs->password = qemu_strdup(password)))
|
||||
return -1;
|
||||
+ vs->auth = VNC_AUTH_VNC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
Index: xen-4.2.1-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
+++ xen-4.2.1-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "qemu-timer.h"
|
||||
#include "qemu-xen.h"
|
||||
|
||||
+extern DisplayState *display_state;
|
||||
struct xs_handle *xsh = NULL;
|
||||
static char *media_filename[MAX_DRIVES+1];
|
||||
static QEMUTimer *insert_timer = NULL;
|
||||
@@ -939,6 +940,19 @@ static void xenstore_process_dm_command_
|
||||
} else if (!strncmp(command, "continue", len)) {
|
||||
fprintf(logfile, "dm-command: continue after state save\n");
|
||||
xen_pause_requested = 0;
|
||||
+ } else if (!strncmp(command, "chgvncpasswd", len)) {
|
||||
+ fprintf(logfile, "dm-command: change vnc passwd\n");
|
||||
+ if (pasprintf(&path,
|
||||
+ "/local/domain/0/backend/vfb/%u/0/vncpasswd", domid) == -1) {
|
||||
+ fprintf(logfile, "out of memory reading dm command parameter\n");
|
||||
+ goto out;
|
||||
+ }
|
||||
+ par = xs_read(xsh, XBT_NULL, path, &len);
|
||||
+ if (!par)
|
||||
+ goto out;
|
||||
+ if (vnc_display_password(display_state, par) == 0)
|
||||
+ xenstore_record_dm_state("vncpasswdchged");
|
||||
+ free(par);
|
||||
} else if (!strncmp(command, "usb-add", len)) {
|
||||
fprintf(logfile, "dm-command: usb-add a usb device\n");
|
||||
if (pasprintf(&path,
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xend/XendDomainInfo.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
@@ -1506,6 +1506,20 @@ class XendDomainInfo:
|
||||
target = max_target
|
||||
self.setMemoryTarget(target)
|
||||
|
||||
+ def chgvncpasswd(self, passwd):
|
||||
+ if self._stateGet() != DOM_STATE_HALTED:
|
||||
+ path = '/local/domain/0/backend/vfb/%u/0/' % self.getDomid()
|
||||
+ xstransact.Write(path, 'vncpasswd', passwd)
|
||||
+ self.image.signalDeviceModel("chgvncpasswd", "vncpasswdchged")
|
||||
+
|
||||
+ for dev_uuid, (dev_type, dev_info) in self.info['devices'].items():
|
||||
+ if dev_type == 'vfb':
|
||||
+ dev_info['vncpasswd'] = passwd
|
||||
+ dev_info['other_config']['vncpasswd'] = passwd
|
||||
+ self.info.device_update(dev_uuid, cfg_xenapi = dev_info)
|
||||
+ break
|
||||
+ xen.xend.XendDomain.instance().managed_config_save(self)
|
||||
+
|
||||
def setMemoryTarget(self, target):
|
||||
"""Set the memory target of this domain.
|
||||
@param target: In MiB.
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xend/server/XMLRPCServer.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xend/server/XMLRPCServer.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xend/server/XMLRPCServer.py
|
||||
@@ -95,7 +95,7 @@ methods = ['device_create', 'device_conf
|
||||
'destroyDevice','getDeviceSxprs',
|
||||
'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
|
||||
'send_sysrq', 'getVCPUInfo', 'waitForDevices',
|
||||
- 'getRestartCount', 'getBlockDeviceClass']
|
||||
+ 'getRestartCount', 'getBlockDeviceClass', 'chgvncpasswd']
|
||||
|
||||
exclude = ['domain_create', 'domain_restore']
|
||||
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xm/main.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xm/main.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xm/main.py
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
"""Grand unified management application for Xen.
|
||||
"""
|
||||
+import getpass
|
||||
import atexit
|
||||
import cmd
|
||||
import os
|
||||
@@ -281,6 +282,9 @@ SUBCOMMAND_HELP = {
|
||||
'getenforce' : ('', 'Returns the current enforcing mode for the Flask XSM module (Enforcing,Permissive)'),
|
||||
'setenforce' : ('[ (Enforcing|1) | (Permissive|0) ]',
|
||||
'Modifies the current enforcing mode for the Flask XSM module'),
|
||||
+ #change vnc password
|
||||
+ 'change-vnc-passwd' : ('<Domain>',\
|
||||
+ 'Change vnc password'),
|
||||
}
|
||||
|
||||
SUBCOMMAND_OPTIONS = {
|
||||
@@ -406,6 +410,7 @@ common_commands = [
|
||||
"usb-del",
|
||||
"domstate",
|
||||
"vcpu-set",
|
||||
+ "change-vnc-passwd",
|
||||
]
|
||||
|
||||
domain_commands = [
|
||||
@@ -443,6 +448,7 @@ domain_commands = [
|
||||
"vcpu-list",
|
||||
"vcpu-pin",
|
||||
"vcpu-set",
|
||||
+ "change-vnc-passwd",
|
||||
]
|
||||
|
||||
host_commands = [
|
||||
@@ -3806,6 +3812,10 @@ def xm_cpupool_migrate(args):
|
||||
else:
|
||||
server.xend.cpu_pool.migrate(domname, poolname)
|
||||
|
||||
+def xm_chgvncpasswd(args):
|
||||
+ arg_check(args, "change-vnc-passwd", 1)
|
||||
+ pwd = getpass.getpass("Enter new password: ")
|
||||
+ server.xend.domain.chgvncpasswd(args[0], pwd)
|
||||
|
||||
commands = {
|
||||
"shell": xm_shell,
|
||||
@@ -3914,6 +3924,8 @@ commands = {
|
||||
"usb-del": xm_usb_del,
|
||||
#domstate
|
||||
"domstate": xm_domstate,
|
||||
+ #change vnc password:
|
||||
+ "change-vnc-passwd": xm_chgvncpasswd,
|
||||
}
|
||||
|
||||
## The commands supported by a separate argument parser in xend.xm.
|
@ -1,16 +0,0 @@
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xend/XendDomainInfo.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
@@ -3155,6 +3155,11 @@ class XendDomainInfo:
|
||||
self._cleanup_phantom_devs(paths)
|
||||
self._cleanupVm()
|
||||
|
||||
+ if "change_home_server" in self.info:
|
||||
+ chs = self.info["change_home_server"]
|
||||
+ if (type(chs) is str and chs == "False") or \
|
||||
+ (type(chs) is bool and chs is False):
|
||||
+ self.setChangeHomeServer(None)
|
||||
if ("transient" in self.info["other_config"] and \
|
||||
bool(self.info["other_config"]["transient"])) or \
|
||||
("change_home_server" in self.info and \
|
@ -1,56 +0,0 @@
|
||||
Improve check_device_status to handle HA cases
|
||||
|
||||
In HA environment, sometimes xenstore status has changed but ev.wait() cannot
|
||||
get the signal, it will wait until timeout, thus incorrect device status is
|
||||
returned. To fix this problem, we do not depend on ev.wait() result, but read
|
||||
xenstore directly to get correct device status.
|
||||
|
||||
Index: xen-4.2.0-testing/tools/python/xen/xend/server/DevController.py
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/python/xen/xend/server/DevController.py
|
||||
+++ xen-4.2.0-testing/tools/python/xen/xend/server/DevController.py
|
||||
@@ -149,7 +149,10 @@ class DevController:
|
||||
(status, err) = self.waitForBackend(devid)
|
||||
|
||||
if status == Timeout:
|
||||
- self.destroyDevice(devid, False)
|
||||
+ #Clean timeout backend resource
|
||||
+ dev = self.convertToDeviceNumber(devid)
|
||||
+ self.writeBackend(dev, HOTPLUG_STATUS_NODE, HOTPLUG_STATUS_ERROR)
|
||||
+ self.destroyDevice(devid, True)
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"Hotplug scripts not working." %
|
||||
(devid, self.deviceClass))
|
||||
@@ -554,7 +557,17 @@ class DevController:
|
||||
|
||||
xswatch(statusPath, hotplugStatusCallback, ev, result)
|
||||
|
||||
- ev.wait(DEVICE_CREATE_TIMEOUT)
|
||||
+ for i in range(1, 50):
|
||||
+ ev.wait(DEVICE_CREATE_TIMEOUT/50)
|
||||
+ status = xstransact.Read(statusPath)
|
||||
+ if status is not None:
|
||||
+ if status == HOTPLUG_STATUS_ERROR:
|
||||
+ result['status'] = Error
|
||||
+ elif status == HOTPLUG_STATUS_BUSY:
|
||||
+ result['status'] = Busy
|
||||
+ else:
|
||||
+ result['status'] = Connected
|
||||
+ break
|
||||
|
||||
err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE)
|
||||
|
||||
@@ -571,7 +584,12 @@ class DevController:
|
||||
|
||||
xswatch(statusPath, deviceDestroyCallback, ev, result)
|
||||
|
||||
- ev.wait(DEVICE_DESTROY_TIMEOUT)
|
||||
+ for i in range(1, 50):
|
||||
+ ev.wait(DEVICE_DESTROY_TIMEOUT/50)
|
||||
+ status = xstransact.Read(statusPath)
|
||||
+ if status is None:
|
||||
+ result['status'] = Disconnected
|
||||
+ break
|
||||
|
||||
return result['status']
|
||||
|
@ -1,13 +0,0 @@
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xend/XendCheckpoint.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xend/XendCheckpoint.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xend/XendCheckpoint.py
|
||||
@@ -188,7 +188,7 @@ def save(fd, dominfo, network, live, dst
|
||||
dominfo.destroy()
|
||||
dominfo.testDeviceComplete()
|
||||
try:
|
||||
- dominfo.setName(domain_name, False)
|
||||
+ dominfo.setName(domain_name)
|
||||
except VmError:
|
||||
# Ignore this. The name conflict (hopefully) arises because we
|
||||
# are doing localhost migration; if we are doing a suspend of a
|
@ -1,22 +0,0 @@
|
||||
Index: xen-4.2.0-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/python/xen/xend/XendDomainInfo.py
|
||||
+++ xen-4.2.0-testing/tools/python/xen/xend/XendDomainInfo.py
|
||||
@@ -1298,8 +1298,15 @@ class XendDomainInfo:
|
||||
frontpath = self.getDeviceController(deviceClass).frontendPath(dev)
|
||||
backpath = xstransact.Read(frontpath, "backend")
|
||||
thread.start_new_thread(self.getDeviceController(deviceClass).finishDeviceCleanup, (backpath, path))
|
||||
-
|
||||
- rc = self.getDeviceController(deviceClass).destroyDevice(devid, force)
|
||||
+ if deviceClass =='vusb':
|
||||
+ dev = self.getDeviceController(deviceClass).convertToDeviceNumber(devid)
|
||||
+ state = self.getDeviceController(deviceClass).readBackend(dev, 'state')
|
||||
+ if state == '1':
|
||||
+ rc = self.getDeviceController(deviceClass).destroyDevice(devid, True)
|
||||
+ else:
|
||||
+ rc = self.getDeviceController(deviceClass).destroyDevice(devid, force)
|
||||
+ else:
|
||||
+ rc = self.getDeviceController(deviceClass).destroyDevice(devid, force)
|
||||
if not force and rm_cfg:
|
||||
# The backend path, other than the device itself,
|
||||
# has to be passed because its accompanied frontend
|
340
disable-wget-check.patch
Normal file
340
disable-wget-check.patch
Normal file
@ -0,0 +1,340 @@
|
||||
Index: xen-4.3.0-testing/tools/configure
|
||||
===================================================================
|
||||
--- xen-4.3.0-testing.orig/tools/configure
|
||||
+++ xen-4.3.0-testing/tools/configure
|
||||
@@ -605,9 +605,6 @@ libgcrypt
|
||||
EXTFS_LIBS
|
||||
system_aio
|
||||
zlib
|
||||
-FETCHER
|
||||
-FTP
|
||||
-WGET
|
||||
glib_LIBS
|
||||
glib_CFLAGS
|
||||
PKG_CONFIG_LIBDIR
|
||||
@@ -7068,104 +7065,104 @@ $as_echo "yes" >&6; }
|
||||
fi
|
||||
|
||||
# Extract the first word of "wget", so it can be a program name with args.
|
||||
-set dummy wget; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if test "${ac_cv_path_WGET+set}" = set; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $WGET in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_WGET="$WGET" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
- ac_cv_path_WGET="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- test -z "$ac_cv_path_WGET" && ac_cv_path_WGET="no"
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-WGET=$ac_cv_path_WGET
|
||||
-if test -n "$WGET"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WGET" >&5
|
||||
-$as_echo "$WGET" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
-
|
||||
-if test x"$WGET" != x"no"; then :
|
||||
-
|
||||
- FETCHER="$WGET -c -O"
|
||||
-
|
||||
-else
|
||||
-
|
||||
- # Extract the first word of "ftp", so it can be a program name with args.
|
||||
-set dummy ftp; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if test "${ac_cv_path_FTP+set}" = set; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $FTP in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_FTP="$FTP" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
- ac_cv_path_FTP="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- test -z "$ac_cv_path_FTP" && ac_cv_path_FTP="no"
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-FTP=$ac_cv_path_FTP
|
||||
-if test -n "$FTP"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FTP" >&5
|
||||
-$as_echo "$FTP" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
-
|
||||
- if test x"$FTP" != x"no"; then :
|
||||
-
|
||||
- FETCHER="$FTP -o"
|
||||
-
|
||||
-else
|
||||
-
|
||||
- as_fn_error $? "cannot find wget or ftp" "$LINENO" 5
|
||||
-
|
||||
-fi
|
||||
-
|
||||
-fi
|
||||
+#set dummy wget; ac_word=$2
|
||||
+#{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
+#$as_echo_n "checking for $ac_word... " >&6; }
|
||||
+#if test "${ac_cv_path_WGET+set}" = set; then :
|
||||
+# $as_echo_n "(cached) " >&6
|
||||
+#else
|
||||
+# case $WGET in
|
||||
+# [\\/]* | ?:[\\/]*)
|
||||
+# ac_cv_path_WGET="$WGET" # Let the user override the test with a path.
|
||||
+# ;;
|
||||
+# *)
|
||||
+# as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
+#for as_dir in $PATH
|
||||
+#do
|
||||
+# IFS=$as_save_IFS
|
||||
+# test -z "$as_dir" && as_dir=.
|
||||
+# for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
+# if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
+# ac_cv_path_WGET="$as_dir/$ac_word$ac_exec_ext"
|
||||
+# $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
+# break 2
|
||||
+# fi
|
||||
+#done
|
||||
+# done
|
||||
+#IFS=$as_save_IFS
|
||||
+#
|
||||
+# test -z "$ac_cv_path_WGET" && ac_cv_path_WGET="no"
|
||||
+# ;;
|
||||
+#esac
|
||||
+#fi
|
||||
+#WGET=$ac_cv_path_WGET
|
||||
+#if test -n "$WGET"; then
|
||||
+# { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WGET" >&5
|
||||
+#$as_echo "$WGET" >&6; }
|
||||
+#else
|
||||
+# { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
+#$as_echo "no" >&6; }
|
||||
+#fi
|
||||
+#
|
||||
+#
|
||||
+#if test x"$WGET" != x"no"; then :
|
||||
+#
|
||||
+# FETCHER="$WGET -c -O"
|
||||
+#
|
||||
+#else
|
||||
+#
|
||||
+# # Extract the first word of "ftp", so it can be a program name with args.
|
||||
+#set dummy ftp; ac_word=$2
|
||||
+#{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
+#$as_echo_n "checking for $ac_word... " >&6; }
|
||||
+#if test "${ac_cv_path_FTP+set}" = set; then :
|
||||
+# $as_echo_n "(cached) " >&6
|
||||
+#else
|
||||
+# case $FTP in
|
||||
+# [\\/]* | ?:[\\/]*)
|
||||
+# ac_cv_path_FTP="$FTP" # Let the user override the test with a path.
|
||||
+# ;;
|
||||
+# *)
|
||||
+# as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
+#for as_dir in $PATH
|
||||
+#do
|
||||
+# IFS=$as_save_IFS
|
||||
+# test -z "$as_dir" && as_dir=.
|
||||
+# for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
+# if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
+# ac_cv_path_FTP="$as_dir/$ac_word$ac_exec_ext"
|
||||
+# $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
+# break 2
|
||||
+# fi
|
||||
+#done
|
||||
+# done
|
||||
+#IFS=$as_save_IFS
|
||||
+#
|
||||
+# test -z "$ac_cv_path_FTP" && ac_cv_path_FTP="no"
|
||||
+# ;;
|
||||
+#esac
|
||||
+#fi
|
||||
+#FTP=$ac_cv_path_FTP
|
||||
+#if test -n "$FTP"; then
|
||||
+# { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FTP" >&5
|
||||
+#$as_echo "$FTP" >&6; }
|
||||
+#else
|
||||
+# { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
+#$as_echo "no" >&6; }
|
||||
+#fi
|
||||
+#
|
||||
+#
|
||||
+# if test x"$FTP" != x"no"; then :
|
||||
+#
|
||||
+# FETCHER="$FTP -o"
|
||||
+#
|
||||
+#else
|
||||
+#
|
||||
+# as_fn_error $? "cannot find wget or ftp" "$LINENO" 5
|
||||
+#
|
||||
+#fi
|
||||
+#
|
||||
+#fi
|
||||
|
||||
|
||||
|
||||
Index: xen-4.3.0-testing/stubdom/configure
|
||||
===================================================================
|
||||
--- xen-4.3.0-testing.orig/stubdom/configure
|
||||
+++ xen-4.3.0-testing/stubdom/configure
|
||||
@@ -593,7 +593,6 @@ CPPFLAGS
|
||||
LDFLAGS
|
||||
CFLAGS
|
||||
CC
|
||||
-WGET
|
||||
CMAKE
|
||||
extfiles
|
||||
debug
|
||||
@@ -657,7 +656,6 @@ enable_extfiles
|
||||
host_alias
|
||||
target_alias
|
||||
CMAKE
|
||||
-WGET
|
||||
CC
|
||||
CFLAGS
|
||||
LDFLAGS
|
||||
@@ -1299,7 +1297,6 @@ Optional Features:
|
||||
|
||||
Some influential environment variables:
|
||||
CMAKE Path to the cmake program
|
||||
- WGET Path to wget program
|
||||
CC C compiler command
|
||||
CFLAGS C compiler flags
|
||||
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
|
||||
@@ -3079,50 +3076,50 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCR
|
||||
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
|
||||
|
||||
# Extract the first word of "wget", so it can be a program name with args.
|
||||
-set dummy wget; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if test "${ac_cv_path_WGET+set}" = set; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $WGET in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_WGET="$WGET" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
- ac_cv_path_WGET="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- test -z "$ac_cv_path_WGET" && ac_cv_path_WGET="no"
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-WGET=$ac_cv_path_WGET
|
||||
-if test -n "$WGET"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WGET" >&5
|
||||
-$as_echo "$WGET" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
-
|
||||
-if test x"${WGET}" = x"no"
|
||||
-then
|
||||
- as_fn_error $? "Unable to find wget, please install wget" "$LINENO" 5
|
||||
-fi
|
||||
+#set dummy wget; ac_word=$2
|
||||
+#{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
+#$as_echo_n "checking for $ac_word... " >&6; }
|
||||
+#if test "${ac_cv_path_WGET+set}" = set; then :
|
||||
+# $as_echo_n "(cached) " >&6
|
||||
+#else
|
||||
+# case $WGET in
|
||||
+# [\\/]* | ?:[\\/]*)
|
||||
+# ac_cv_path_WGET="$WGET" # Let the user override the test with a path.
|
||||
+# ;;
|
||||
+# *)
|
||||
+# as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
+#for as_dir in $PATH
|
||||
+#do
|
||||
+# IFS=$as_save_IFS
|
||||
+# test -z "$as_dir" && as_dir=.
|
||||
+# for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
+# if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
+# ac_cv_path_WGET="$as_dir/$ac_word$ac_exec_ext"
|
||||
+# $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
+# break 2
|
||||
+# fi
|
||||
+#done
|
||||
+# done
|
||||
+#IFS=$as_save_IFS
|
||||
+#
|
||||
+# test -z "$ac_cv_path_WGET" && ac_cv_path_WGET="no"
|
||||
+# ;;
|
||||
+#esac
|
||||
+#fi
|
||||
+#WGET=$ac_cv_path_WGET
|
||||
+#if test -n "$WGET"; then
|
||||
+# { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WGET" >&5
|
||||
+#$as_echo "$WGET" >&6; }
|
||||
+#else
|
||||
+# { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
+#$as_echo "no" >&6; }
|
||||
+#fi
|
||||
+#
|
||||
+#
|
||||
+#if test x"${WGET}" = x"no"
|
||||
+#then
|
||||
+# as_fn_error $? "Unable to find wget, please install wget" "$LINENO" 5
|
||||
+#fi
|
||||
|
||||
# Checks for programs that depend on a feature
|
||||
|
@ -1,20 +0,0 @@
|
||||
Index: xen-4.2.0-testing/tools/python/xen/xend/XendConfig.py
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/python/xen/xend/XendConfig.py
|
||||
+++ xen-4.2.0-testing/tools/python/xen/xend/XendConfig.py
|
||||
@@ -1875,7 +1875,14 @@ class XendConfig(dict):
|
||||
ports = sxp.child(dev_sxp, 'port')
|
||||
for port in ports[1:]:
|
||||
try:
|
||||
- num, bus = port
|
||||
+ # When ['port' ['1','']] is saved into sxp file, it will become (port (1 ))
|
||||
+ # If using this sxp file, here variable "port" will be port=1,
|
||||
+ # we should process it, otherwise, it will report error.
|
||||
+ if len(port) == 1:
|
||||
+ num = port[0]
|
||||
+ bus = ""
|
||||
+ else:
|
||||
+ num, bus = port
|
||||
dev_config['port-%i' % int(num)] = str(bus)
|
||||
except TypeError:
|
||||
pass
|
@ -1,68 +0,0 @@
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xend/XendConfig.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xend/XendConfig.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xend/XendConfig.py
|
||||
@@ -161,6 +161,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
|
||||
'nographic': int,
|
||||
'nomigrate': int,
|
||||
'pae' : int,
|
||||
+ 'extid': int,
|
||||
'rtc_timeoffset': int,
|
||||
'parallel': str,
|
||||
'serial': str,
|
||||
@@ -523,6 +524,8 @@ class XendConfig(dict):
|
||||
self['platform']['acpi_firmware'] = ""
|
||||
if 'timer_mode' not in self['platform']:
|
||||
self['platform']['timer_mode'] = 1
|
||||
+ if 'extid' in self['platform'] and int(self['platform']['extid']) == 1:
|
||||
+ self['platform']['viridian'] = 1
|
||||
if 'viridian' not in self['platform']:
|
||||
self['platform']['viridian'] = 0
|
||||
if 'rtc_timeoffset' not in self['platform']:
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xend/image.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xend/image.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xend/image.py
|
||||
@@ -830,6 +830,7 @@ class HVMImageHandler(ImageHandler):
|
||||
|
||||
self.apic = int(vmConfig['platform'].get('apic', 0))
|
||||
self.acpi = int(vmConfig['platform'].get('acpi', 0))
|
||||
+ self.extid = int(vmConfig['platform'].get('extid', 0))
|
||||
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
|
||||
self.memory_sharing = int(vmConfig['memory_sharing'])
|
||||
try:
|
||||
Index: xen-4.2.1-testing/tools/python/xen/xm/create.py
|
||||
===================================================================
|
||||
--- xen-4.2.1-testing.orig/tools/python/xen/xm/create.py
|
||||
+++ xen-4.2.1-testing/tools/python/xen/xm/create.py
|
||||
@@ -242,6 +242,10 @@ gopts.var('viridian', val='VIRIDIAN',
|
||||
use="""Expose Viridian interface to x86 HVM guest?
|
||||
(Default is 0).""")
|
||||
|
||||
+gopts.var('extid', val='EXTID',
|
||||
+ fn=set_int, default=0,
|
||||
+ use="Specify extention ID for a HVM domain.")
|
||||
+
|
||||
gopts.var('acpi', val='ACPI',
|
||||
fn=set_int, default=1,
|
||||
use="Disable or enable ACPI of HVM domain.")
|
||||
@@ -1120,7 +1124,7 @@ def configure_hvm(config_image, vals):
|
||||
'timer_mode',
|
||||
'usb', 'usbdevice',
|
||||
'vcpus', 'vnc', 'vncconsole', 'vncdisplay', 'vnclisten',
|
||||
- 'vncunused', 'viridian', 'vpt_align',
|
||||
+ 'vncunused', 'vpt_align',
|
||||
'watchdog', 'watchdog_action',
|
||||
'xauthority', 'xen_extended_power_mgmt', 'xen_platform_pci',
|
||||
'memory_sharing' ]
|
||||
@@ -1130,6 +1134,10 @@ def configure_hvm(config_image, vals):
|
||||
config_image.append([a, vals.__dict__[a]])
|
||||
if vals.vncpasswd is not None:
|
||||
config_image.append(['vncpasswd', vals.vncpasswd])
|
||||
+ if vals.extid and vals.extid == 1:
|
||||
+ config_image.append(['viridian', vals.extid])
|
||||
+ elif vals.viridian:
|
||||
+ config_image.append(['viridian', vals.viridian])
|
||||
|
||||
|
||||
def make_config(vals):
|
@ -1,32 +0,0 @@
|
||||
qcow2 corruption: Fix alloc_cluster_link_l2 (Kevin Wolf)
|
||||
|
||||
This patch fixes a qcow2 corruption bug introduced in SVN Rev 5861. L2 tables
|
||||
are big endian, so entries must be converted before being passed to functions.
|
||||
|
||||
This bug is easy to trigger. The following script will create and destroy a
|
||||
qcow2 image (the header is gone after three loop iterations):
|
||||
|
||||
#!/bin/bash
|
||||
qemu-img create -f qcow2 test.qcow 1M
|
||||
for i in $(seq 1 10); do
|
||||
qemu-system-x86_64 -hda test.qcow -monitor stdio > /dev/null 2>&1 <<EOF
|
||||
savevm test-$i
|
||||
quit
|
||||
EOF
|
||||
done
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
|
||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/block-qcow2.c
|
||||
===================================================================
|
||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/block-qcow2.c
|
||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/block-qcow2.c
|
||||
@@ -916,7 +916,7 @@ static int alloc_cluster_link_l2(BlockDr
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
- free_any_clusters(bs, old_cluster[i], 1);
|
||||
+ free_any_clusters(bs, be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1);
|
||||
|
||||
ret = 0;
|
||||
err:
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user