- 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.c | 16
|
||||||
tools/blktap/drivers/tapdisk.h | 16
|
tools/blktap/drivers/tapdisk.h | 16
|
||||||
tools/blktap/lib/blktaplib.h | 1
|
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/blkif.h | 2
|
||||||
xen/include/public/io/cdromif.h | 122 ++++
|
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.3.0-testing.orig/tools/blktap/drivers/Makefile
|
||||||
+++ xen-4.2.1-testing/tools/blktap/drivers/Makefile
|
+++ xen-4.3.0-testing/tools/blktap/drivers/Makefile
|
||||||
@@ -38,8 +38,9 @@ endif
|
@@ -38,8 +38,9 @@ endif
|
||||||
CFLAGS += $(PTHREAD_CFLAGS)
|
CFLAGS += $(PTHREAD_CFLAGS)
|
||||||
LDFLAGS += $(PTHREAD_LDFLAGS)
|
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 += aes.o
|
||||||
BLK-OBJS-y += tapaio.o
|
BLK-OBJS-y += tapaio.o
|
||||||
BLK-OBJS-$(CONFIG_Linux) += blk_linux.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
|
--- /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 @@
|
@@ -0,0 +1,568 @@
|
||||||
+/* block-cdrom.c
|
+/* 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_get_parent_id = tdcdrom_get_parent_id,
|
||||||
+ .td_validate_parent = tdcdrom_validate_parent
|
+ .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.3.0-testing.orig/tools/blktap/drivers/tapdisk.c
|
||||||
+++ xen-4.2.1-testing/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
|
@@ -735,6 +735,22 @@ static void get_io_request(struct td_sta
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -633,10 +632,10 @@ Index: xen-4.2.1-testing/tools/blktap/drivers/tapdisk.c
|
|||||||
default:
|
default:
|
||||||
DPRINTF("Unknown block operation\n");
|
DPRINTF("Unknown block operation\n");
|
||||||
break;
|
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.3.0-testing.orig/tools/blktap/drivers/tapdisk.h
|
||||||
+++ xen-4.2.1-testing/tools/blktap/drivers/tapdisk.h
|
+++ xen-4.3.0-testing/tools/blktap/drivers/tapdisk.h
|
||||||
@@ -137,6 +137,9 @@ struct tap_disk {
|
@@ -137,6 +137,9 @@ struct tap_disk {
|
||||||
int (*td_get_parent_id) (struct disk_driver *dd, struct disk_id *id);
|
int (*td_get_parent_id) (struct disk_driver *dd, struct disk_id *id);
|
||||||
int (*td_validate_parent)(struct disk_driver *dd,
|
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 {
|
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.3.0-testing.orig/tools/blktap/lib/blktaplib.h
|
||||||
+++ xen-4.2.1-testing/tools/blktap/lib/blktaplib.h
|
+++ xen-4.3.0-testing/tools/blktap/lib/blktaplib.h
|
||||||
@@ -219,6 +219,7 @@ typedef struct msg_pid {
|
@@ -219,6 +219,7 @@ typedef struct msg_pid {
|
||||||
#define DISK_TYPE_RAM 3
|
#define DISK_TYPE_RAM 3
|
||||||
#define DISK_TYPE_QCOW 4
|
#define DISK_TYPE_QCOW 4
|
||||||
@ -693,23 +692,11 @@ Index: xen-4.2.1-testing/tools/blktap/lib/blktaplib.h
|
|||||||
|
|
||||||
/* xenstore/xenbus: */
|
/* xenstore/xenbus: */
|
||||||
#define DOMNAME "Domain-0"
|
#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.3.0-testing.orig/xen/include/public/io/blkif.h
|
||||||
+++ xen-4.2.1-testing/tools/python/xen/xend/server/BlktapController.py
|
+++ xen-4.3.0-testing/xen/include/public/io/blkif.h
|
||||||
@@ -15,6 +15,7 @@ blktap1_disk_types = [
|
@@ -439,7 +439,7 @@
|
||||||
'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 @@
|
|
||||||
* Used in SLES sources for device specific command packet
|
* Used in SLES sources for device specific command packet
|
||||||
* contained within the request. Reserved for that purpose.
|
* 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
|
* 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
|
* 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
|
--- /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 @@
|
@@ -0,0 +1,122 @@
|
||||||
+/******************************************************************************
|
+/******************************************************************************
|
||||||
+ * cdromif.h
|
+ * 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()
|
function activate_lvm()
|
||||||
{
|
{
|
||||||
# First scan for PVs and VGs; we may then have to activate the VG
|
local run_timeout=90
|
||||||
# first, but can ignore errors:
|
local parsed_timeout
|
||||||
# /sbin/pvscan || :
|
local end_time
|
||||||
# /sbin/vgscan --mknodes || :
|
|
||||||
# /sbin/vgchange -ay ${1%/*} || :
|
# Parse device-create-timeout from /etc/xen/xend-config.sxp
|
||||||
/sbin/lvchange -ay $1
|
# If not set, use default timeout of 90s
|
||||||
if [ $? -eq 0 ]; then
|
parsed_timeout=$(grep -v "^[ \t]*#.*" /etc/xen/xend-config.sxp|sed -n 's/(device-create-timeout \+\([0-9]\+\))/\1/p')
|
||||||
return 0
|
if [ ! -z $parsed_timeout ]; then
|
||||||
|
run_timeout=$((${parsed_timeout}*9/10))
|
||||||
fi
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function deactivate_lvm()
|
function deactivate_lvm()
|
||||||
{
|
{
|
||||||
/sbin/lvchange -an $1
|
/sbin/lvchange -aen $1
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
# We may have to deactivate the VG now, but can ignore errors:
|
# We may have to deactivate the VG now, but can ignore errors:
|
||||||
# /sbin/vgchange -an ${1%/*} || :
|
# /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