This commit is contained in:
parent
6eb384a263
commit
1c73c9b461
75
18720-x86-dom-cleanup.patch
Normal file
75
18720-x86-dom-cleanup.patch
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225113763 0
|
||||||
|
# Node ID 11c86c51a697dab2e4a49efe3dda139ea206f423
|
||||||
|
# Parent 101e50cffc7825065f4dd39610728a2ba3ea68b4
|
||||||
|
x86: fix domain cleanup
|
||||||
|
|
||||||
|
The preemptable page type handling changes modified free_page_type()
|
||||||
|
behavior without adjusting the call site in relinquish_memory(): Any
|
||||||
|
type reference left pending when leaving hypercall handlers is
|
||||||
|
associated with a page reference, and when successful free_page_type()
|
||||||
|
decrements the type refcount - hence relinquish_memory() must now also
|
||||||
|
drop the page reference.
|
||||||
|
|
||||||
|
Also, the recursion avoidance during domain shutdown somehow (probably
|
||||||
|
by me when I merged the patch up to a newer snapshot) got screwed up:
|
||||||
|
The avoidance logic in mm.c should short circuit levels below the top
|
||||||
|
one currently being processed, rather than the top one itself.
|
||||||
|
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
|
||||||
|
--- a/xen/arch/x86/domain.c
|
||||||
|
+++ b/xen/arch/x86/domain.c
|
||||||
|
@@ -1687,6 +1687,7 @@ static int relinquish_memory(
|
||||||
|
{
|
||||||
|
if ( free_page_type(page, x, 0) != 0 )
|
||||||
|
BUG();
|
||||||
|
+ put_page(page);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--- a/xen/arch/x86/mm.c
|
||||||
|
+++ b/xen/arch/x86/mm.c
|
||||||
|
@@ -1343,7 +1343,7 @@ static void free_l1_table(struct page_in
|
||||||
|
|
||||||
|
static int free_l2_table(struct page_info *page, int preemptible)
|
||||||
|
{
|
||||||
|
-#ifdef CONFIG_COMPAT
|
||||||
|
+#if defined(CONFIG_COMPAT) || defined(DOMAIN_DESTRUCT_AVOID_RECURSION)
|
||||||
|
struct domain *d = page_get_owner(page);
|
||||||
|
#endif
|
||||||
|
unsigned long pfn = page_to_mfn(page);
|
||||||
|
@@ -1351,6 +1351,11 @@ static int free_l2_table(struct page_inf
|
||||||
|
unsigned int i = page->nr_validated_ptes - 1;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
+#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION
|
||||||
|
+ if ( d->arch.relmem == RELMEM_l3 )
|
||||||
|
+ return 0;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
pl2e = map_domain_page(pfn);
|
||||||
|
|
||||||
|
ASSERT(page->nr_validated_ptes);
|
||||||
|
@@ -1381,7 +1386,7 @@ static int free_l3_table(struct page_inf
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION
|
||||||
|
- if ( d->arch.relmem == RELMEM_l3 )
|
||||||
|
+ if ( d->arch.relmem == RELMEM_l4 )
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1424,11 +1429,6 @@ static int free_l4_table(struct page_inf
|
||||||
|
unsigned int i = page->nr_validated_ptes - !page->partial_pte;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
-#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION
|
||||||
|
- if ( d->arch.relmem == RELMEM_l4 )
|
||||||
|
- return 0;
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
do {
|
||||||
|
if ( is_guest_l4_slot(d, i) )
|
||||||
|
rc = put_page_from_l4e(pl4e[i], pfn, preemptible);
|
19
18722-x86-fixmap-reserved.patch
Normal file
19
18722-x86-fixmap-reserved.patch
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225114010 0
|
||||||
|
# Node ID 604ffa3cdcc48bbfcfe5e4ccd0af735ddc49d839
|
||||||
|
# Parent 15aed96c7b5cd5a435754a57db13cd72b386717a
|
||||||
|
x86: First fixmap entry (0) is invalid.
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
|
||||||
|
--- a/xen/include/asm-x86/fixmap.h
|
||||||
|
+++ b/xen/include/asm-x86/fixmap.h
|
||||||
|
@@ -29,6 +29,7 @@
|
||||||
|
* from the end of virtual memory backwards.
|
||||||
|
*/
|
||||||
|
enum fixed_addresses {
|
||||||
|
+ FIX_RESERVED, /* Index 0 is reserved since fix_to_virt(0) > FIXADDR_TOP. */
|
||||||
|
#ifdef __i386__
|
||||||
|
FIX_PAE_HIGHMEM_0,
|
||||||
|
FIX_PAE_HIGHMEM_END = FIX_PAE_HIGHMEM_0 + NR_CPUS-1,
|
58
18723-unmap-dom-page-const.patch
Normal file
58
18723-unmap-dom-page-const.patch
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225114053 0
|
||||||
|
# Node ID 9bbb54fd9181644d2bdd3c7f93c2cba1dac1b719
|
||||||
|
# Parent 604ffa3cdcc48bbfcfe5e4ccd0af735ddc49d839
|
||||||
|
Constify arguments to unmap_domain_page() etc.
|
||||||
|
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
|
||||||
|
--- a/xen/arch/x86/x86_32/domain_page.c
|
||||||
|
+++ b/xen/arch/x86/x86_32/domain_page.c
|
||||||
|
@@ -114,7 +114,7 @@ void *map_domain_page(unsigned long mfn)
|
||||||
|
return (void *)va;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void unmap_domain_page(void *va)
|
||||||
|
+void unmap_domain_page(const void *va)
|
||||||
|
{
|
||||||
|
unsigned int idx;
|
||||||
|
struct vcpu *v;
|
||||||
|
@@ -241,7 +241,7 @@ void *map_domain_page_global(unsigned lo
|
||||||
|
return (void *)va;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void unmap_domain_page_global(void *va)
|
||||||
|
+void unmap_domain_page_global(const void *va)
|
||||||
|
{
|
||||||
|
unsigned long __va = (unsigned long)va;
|
||||||
|
l2_pgentry_t *pl2e;
|
||||||
|
--- a/xen/include/xen/domain_page.h
|
||||||
|
+++ b/xen/include/xen/domain_page.h
|
||||||
|
@@ -24,7 +24,7 @@ void *map_domain_page(unsigned long mfn)
|
||||||
|
* Pass a VA within a page previously mapped in the context of the
|
||||||
|
* currently-executing VCPU via a call to map_domain_page().
|
||||||
|
*/
|
||||||
|
-void unmap_domain_page(void *va);
|
||||||
|
+void unmap_domain_page(const void *va);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar to the above calls, except the mapping is accessible in all
|
||||||
|
@@ -32,7 +32,7 @@ void unmap_domain_page(void *va);
|
||||||
|
* mappings can also be unmapped from any context.
|
||||||
|
*/
|
||||||
|
void *map_domain_page_global(unsigned long mfn);
|
||||||
|
-void unmap_domain_page_global(void *va);
|
||||||
|
+void unmap_domain_page_global(const void *va);
|
||||||
|
|
||||||
|
#define DMCACHE_ENTRY_VALID 1U
|
||||||
|
#define DMCACHE_ENTRY_HELD 2U
|
||||||
|
@@ -75,7 +75,7 @@ map_domain_page_with_cache(unsigned long
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
-unmap_domain_page_with_cache(void *va, struct domain_mmap_cache *cache)
|
||||||
|
+unmap_domain_page_with_cache(const void *va, struct domain_mmap_cache *cache)
|
||||||
|
{
|
||||||
|
ASSERT(cache != NULL);
|
||||||
|
cache->flags &= ~DMCACHE_ENTRY_HELD;
|
@ -1,9 +1,27 @@
|
|||||||
-unstable staging c/s 18724
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225114175 0
|
||||||
|
# Node ID 4413d53a8320809e93142ed599a81e1bfe5ae900
|
||||||
|
# Parent 9bbb54fd9181644d2bdd3c7f93c2cba1dac1b719
|
||||||
|
x86: highmem handling assistance hypercalls
|
||||||
|
|
||||||
Index: xen-3.3.1-testing/xen/arch/x86/mm.c
|
While looking at the origin of very frequently executed hypercalls I
|
||||||
===================================================================
|
realized that the high page accessor functions in Linux would be good
|
||||||
--- xen-3.3.1-testing.orig/xen/arch/x86/mm.c
|
candidates to handle in the hypervisor - clearing or copying to/from
|
||||||
+++ xen-3.3.1-testing/xen/arch/x86/mm.c
|
a high page is a pretty frequent operation (provided there's enough
|
||||||
|
memory in the domain). While prior to the first submission I only
|
||||||
|
measured kernel builds (where the results are not hinting at a
|
||||||
|
meaningful improvement), I now found time to do a more specific
|
||||||
|
analysis: page clearing is being improved by about 20%, page copying
|
||||||
|
doesn't seem to significantly benefit (though that may be an effect of
|
||||||
|
the simplistic copy_page() implementation Xen currently uses) -
|
||||||
|
nevertheless I would think that if one function is supported by the
|
||||||
|
hypervisor, then the other should also be.
|
||||||
|
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
|
||||||
|
--- a/xen/arch/x86/mm.c
|
||||||
|
+++ b/xen/arch/x86/mm.c
|
||||||
@@ -2431,6 +2431,29 @@ static inline cpumask_t vcpumask_to_pcpu
|
@@ -2431,6 +2431,29 @@ static inline cpumask_t vcpumask_to_pcpu
|
||||||
return pmask;
|
return pmask;
|
||||||
}
|
}
|
||||||
@ -101,32 +119,8 @@ Index: xen-3.3.1-testing/xen/arch/x86/mm.c
|
|||||||
default:
|
default:
|
||||||
MEM_LOG("Invalid extended pt command 0x%x", op.cmd);
|
MEM_LOG("Invalid extended pt command 0x%x", op.cmd);
|
||||||
rc = -ENOSYS;
|
rc = -ENOSYS;
|
||||||
Index: xen-3.3.1-testing/xen/arch/x86/x86_32/domain_page.c
|
--- a/xen/arch/x86/x86_64/compat/mm.c
|
||||||
===================================================================
|
+++ b/xen/arch/x86/x86_64/compat/mm.c
|
||||||
--- xen-3.3.1-testing.orig/xen/arch/x86/x86_32/domain_page.c
|
|
||||||
+++ xen-3.3.1-testing/xen/arch/x86/x86_32/domain_page.c
|
|
||||||
@@ -114,7 +114,7 @@ void *map_domain_page(unsigned long mfn)
|
|
||||||
return (void *)va;
|
|
||||||
}
|
|
||||||
|
|
||||||
-void unmap_domain_page(void *va)
|
|
||||||
+void unmap_domain_page(const void *va)
|
|
||||||
{
|
|
||||||
unsigned int idx;
|
|
||||||
struct vcpu *v;
|
|
||||||
@@ -241,7 +241,7 @@ void *map_domain_page_global(unsigned lo
|
|
||||||
return (void *)va;
|
|
||||||
}
|
|
||||||
|
|
||||||
-void unmap_domain_page_global(void *va)
|
|
||||||
+void unmap_domain_page_global(const void *va)
|
|
||||||
{
|
|
||||||
unsigned long __va = (unsigned long)va;
|
|
||||||
l2_pgentry_t *pl2e;
|
|
||||||
Index: xen-3.3.1-testing/xen/arch/x86/x86_64/compat/mm.c
|
|
||||||
===================================================================
|
|
||||||
--- xen-3.3.1-testing.orig/xen/arch/x86/x86_64/compat/mm.c
|
|
||||||
+++ xen-3.3.1-testing/xen/arch/x86/x86_64/compat/mm.c
|
|
||||||
@@ -217,6 +217,8 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm
|
@@ -217,6 +217,8 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm
|
||||||
case MMUEXT_PIN_L4_TABLE:
|
case MMUEXT_PIN_L4_TABLE:
|
||||||
case MMUEXT_UNPIN_TABLE:
|
case MMUEXT_UNPIN_TABLE:
|
||||||
@ -146,36 +140,30 @@ Index: xen-3.3.1-testing/xen/arch/x86/x86_64/compat/mm.c
|
|||||||
default:
|
default:
|
||||||
arg2 = -1;
|
arg2 = -1;
|
||||||
break;
|
break;
|
||||||
Index: xen-3.3.1-testing/xen/include/asm-x86/fixmap.h
|
--- a/xen/common/kernel.c
|
||||||
===================================================================
|
+++ b/xen/common/kernel.c
|
||||||
--- xen-3.3.1-testing.orig/xen/include/asm-x86/fixmap.h
|
@@ -222,6 +222,7 @@ DO(xen_version)(int cmd, XEN_GUEST_HANDL
|
||||||
+++ xen-3.3.1-testing/xen/include/asm-x86/fixmap.h
|
#ifdef CONFIG_X86
|
||||||
@@ -29,6 +29,7 @@
|
if ( !is_hvm_vcpu(current) )
|
||||||
* from the end of virtual memory backwards.
|
fi.submap |= (1U << XENFEAT_mmu_pt_update_preserve_ad) |
|
||||||
*/
|
+ (1U << XENFEAT_highmem_assist) |
|
||||||
enum fixed_addresses {
|
(1U << XENFEAT_gnttab_map_avail_bits);
|
||||||
+ FIX_HOLE,
|
#endif
|
||||||
#ifdef __i386__
|
break;
|
||||||
FIX_PAE_HIGHMEM_0,
|
--- a/xen/include/public/features.h
|
||||||
FIX_PAE_HIGHMEM_END = FIX_PAE_HIGHMEM_0 + NR_CPUS-1,
|
+++ b/xen/include/public/features.h
|
||||||
Index: xen-3.3.1-testing/xen/include/public/features.h
|
@@ -59,6 +59,9 @@
|
||||||
===================================================================
|
/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
|
||||||
--- xen-3.3.1-testing.orig/xen/include/public/features.h
|
#define XENFEAT_mmu_pt_update_preserve_ad 5
|
||||||
+++ xen-3.3.1-testing/xen/include/public/features.h
|
|
||||||
@@ -65,6 +65,9 @@
|
|
||||||
*/
|
|
||||||
#define XENFEAT_gnttab_map_avail_bits 7
|
|
||||||
|
|
||||||
+/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */
|
+/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */
|
||||||
+#define XENFEAT_highmem_assist 6
|
+#define XENFEAT_highmem_assist 6
|
||||||
+
|
+
|
||||||
#define XENFEAT_NR_SUBMAPS 1
|
/*
|
||||||
|
* If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel
|
||||||
#endif /* __XEN_PUBLIC_FEATURES_H__ */
|
* available pte bits.
|
||||||
Index: xen-3.3.1-testing/xen/include/public/xen.h
|
--- a/xen/include/public/xen.h
|
||||||
===================================================================
|
+++ b/xen/include/public/xen.h
|
||||||
--- xen-3.3.1-testing.orig/xen/include/public/xen.h
|
|
||||||
+++ xen-3.3.1-testing/xen/include/public/xen.h
|
|
||||||
@@ -231,6 +231,13 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
|
@@ -231,6 +231,13 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
|
||||||
* cmd: MMUEXT_SET_LDT
|
* cmd: MMUEXT_SET_LDT
|
||||||
* linear_addr: Linear address of LDT base (NB. must be page-aligned).
|
* linear_addr: Linear address of LDT base (NB. must be page-aligned).
|
||||||
@ -216,34 +204,3 @@ Index: xen-3.3.1-testing/xen/include/public/xen.h
|
|||||||
} arg2;
|
} arg2;
|
||||||
};
|
};
|
||||||
typedef struct mmuext_op mmuext_op_t;
|
typedef struct mmuext_op mmuext_op_t;
|
||||||
Index: xen-3.3.1-testing/xen/include/xen/domain_page.h
|
|
||||||
===================================================================
|
|
||||||
--- xen-3.3.1-testing.orig/xen/include/xen/domain_page.h
|
|
||||||
+++ xen-3.3.1-testing/xen/include/xen/domain_page.h
|
|
||||||
@@ -24,7 +24,7 @@ void *map_domain_page(unsigned long mfn)
|
|
||||||
* Pass a VA within a page previously mapped in the context of the
|
|
||||||
* currently-executing VCPU via a call to map_domain_page().
|
|
||||||
*/
|
|
||||||
-void unmap_domain_page(void *va);
|
|
||||||
+void unmap_domain_page(const void *va);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Similar to the above calls, except the mapping is accessible in all
|
|
||||||
@@ -32,7 +32,7 @@ void unmap_domain_page(void *va);
|
|
||||||
* mappings can also be unmapped from any context.
|
|
||||||
*/
|
|
||||||
void *map_domain_page_global(unsigned long mfn);
|
|
||||||
-void unmap_domain_page_global(void *va);
|
|
||||||
+void unmap_domain_page_global(const void *va);
|
|
||||||
|
|
||||||
#define DMCACHE_ENTRY_VALID 1U
|
|
||||||
#define DMCACHE_ENTRY_HELD 2U
|
|
||||||
@@ -75,7 +75,7 @@ map_domain_page_with_cache(unsigned long
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
-unmap_domain_page_with_cache(void *va, struct domain_mmap_cache *cache)
|
|
||||||
+unmap_domain_page_with_cache(const void *va, struct domain_mmap_cache *cache)
|
|
||||||
{
|
|
||||||
ASSERT(cache != NULL);
|
|
||||||
cache->flags &= ~DMCACHE_ENTRY_HELD;
|
|
57
18731-x86-dom-cleanup.patch
Normal file
57
18731-x86-dom-cleanup.patch
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225193120 0
|
||||||
|
# Node ID 19549b9766fdd68380ded8efd975c41269ab2801
|
||||||
|
# Parent 2c20d026bb55722247c0d9ab81c125118a10346f
|
||||||
|
x86: Fix circular page reference destruction in relinquish_memory().
|
||||||
|
|
||||||
|
Tested by Jan Beulich and fixes a memory leak, but there is more to be
|
||||||
|
done here.
|
||||||
|
|
||||||
|
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
|
||||||
|
--- a/xen/arch/x86/domain.c
|
||||||
|
+++ b/xen/arch/x86/domain.c
|
||||||
|
@@ -1687,7 +1687,6 @@ static int relinquish_memory(
|
||||||
|
{
|
||||||
|
if ( free_page_type(page, x, 0) != 0 )
|
||||||
|
BUG();
|
||||||
|
- put_page(page);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--- a/xen/arch/x86/mm.c
|
||||||
|
+++ b/xen/arch/x86/mm.c
|
||||||
|
@@ -1973,6 +1973,7 @@ int free_page_type(struct page_info *pag
|
||||||
|
page->nr_validated_ptes = 1U << PAGETABLE_ORDER;
|
||||||
|
page->partial_pte = 0;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
switch ( type & PGT_type_mask )
|
||||||
|
{
|
||||||
|
case PGT_l1_page_table:
|
||||||
|
@@ -1998,6 +1999,15 @@ int free_page_type(struct page_info *pag
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static int __put_final_page_type(
|
||||||
|
+ struct page_info *page, unsigned long type, int preemptible)
|
||||||
|
+{
|
||||||
|
+ int rc = free_page_type(page, type, preemptible);
|
||||||
|
+
|
||||||
|
/* No need for atomic update of type_info here: noone else updates it. */
|
||||||
|
if ( rc == 0 )
|
||||||
|
{
|
||||||
|
@@ -2062,7 +2072,7 @@ static int __put_page_type(struct page_i
|
||||||
|
x, nx)) != x) )
|
||||||
|
continue;
|
||||||
|
/* We cleared the 'valid bit' so we do the clean up. */
|
||||||
|
- return free_page_type(page, x, preemptible);
|
||||||
|
+ return __put_final_page_type(page, x, preemptible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
22
18735-x86-dom-cleanup.patch
Normal file
22
18735-x86-dom-cleanup.patch
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225285777 0
|
||||||
|
# Node ID ae100f264f6ad4e828de1ca2d228cccf6ed2bbfd
|
||||||
|
# Parent 183d2d7adc2f02db63aedaf199e3b006d2e4a053
|
||||||
|
x86: Fix relinquish_memory() for PGT_partial pages.
|
||||||
|
|
||||||
|
Original patch by Jan Beulich.
|
||||||
|
|
||||||
|
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
|
||||||
|
--- a/xen/arch/x86/domain.c
|
||||||
|
+++ b/xen/arch/x86/domain.c
|
||||||
|
@@ -1687,6 +1687,8 @@ static int relinquish_memory(
|
||||||
|
{
|
||||||
|
if ( free_page_type(page, x, 0) != 0 )
|
||||||
|
BUG();
|
||||||
|
+ if ( x & PGT_partial )
|
||||||
|
+ page->u.inuse.type_info--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,13 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225377468 0
|
||||||
|
# Node ID 9e5cf6778a6d1057900c3709f544ac176ddfab67
|
||||||
|
# Parent 112e81ae5824e213b181a65f944b729ba270d658
|
||||||
|
x86: eliminate domain cleanup hack in favor of using the preemptable
|
||||||
|
flavors of the respective functions.
|
||||||
|
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
|
||||||
--- a/xen/arch/x86/domain.c
|
--- a/xen/arch/x86/domain.c
|
||||||
+++ b/xen/arch/x86/domain.c
|
+++ b/xen/arch/x86/domain.c
|
||||||
@@ -1639,32 +1639,23 @@ static int relinquish_memory(
|
@@ -1639,32 +1639,23 @@ static int relinquish_memory(
|
@ -1,14 +1,22 @@
|
|||||||
-unstable staging c/s 18742+18747
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225378404 0
|
||||||
|
# Node ID ed30f4efb728980ba84c34fc7fdc7be5f5a4a78e
|
||||||
|
# Parent 9e5cf6778a6d1057900c3709f544ac176ddfab67
|
||||||
|
x86: fix preemptable page type handling
|
||||||
|
|
||||||
- retain a page reference when PGT_partial is set on a page (and drop
|
- retain a page reference when PGT_partial is set on a page (and drop
|
||||||
it when clearing that flag)
|
it when clearing that flag)
|
||||||
- don't drop a page reference never acquired when freeing the page type
|
- don't drop a page reference never acquired when freeing the page
|
||||||
|
type
|
||||||
of a page where the allocation of the type got preempted (and never
|
of a page where the allocation of the type got preempted (and never
|
||||||
completed)
|
completed)
|
||||||
- don't acquire a page reference when allocating the page type of a
|
- don't acquire a page reference when allocating the page type of a
|
||||||
page where freeing the type got preempted (and never completed, and
|
page where freeing the type got preempted (and never completed, and
|
||||||
hence didn't drop the respective reference)
|
hence didn't drop the respective reference)
|
||||||
|
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
|
||||||
--- a/xen/arch/x86/domain.c
|
--- a/xen/arch/x86/domain.c
|
||||||
+++ b/xen/arch/x86/domain.c
|
+++ b/xen/arch/x86/domain.c
|
||||||
@@ -1683,18 +1683,24 @@ static int relinquish_memory(
|
@@ -1683,18 +1683,24 @@ static int relinquish_memory(
|
||||||
@ -324,126 +332,96 @@
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1837,7 +1856,8 @@ int get_page(struct page_info *page, str
|
@@ -1866,6 +1885,10 @@ static int alloc_page_type(struct page_i
|
||||||
nx = x + 1;
|
struct domain *owner = page_get_owner(page);
|
||||||
d = nd;
|
int rc;
|
||||||
if ( unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
|
|
||||||
- unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
|
|
||||||
+ /* Keep one spare reference to be acquired by get_page_light(). */
|
|
||||||
+ unlikely(((nx + 1) & PGC_count_mask) <= 1) || /* Overflow? */
|
|
||||||
unlikely(d != _domain) ) /* Wrong owner? */
|
|
||||||
{
|
|
||||||
if ( !_shadow_mode_refcounts(domain) && !domain->is_dying )
|
|
||||||
@@ -1859,6 +1879,28 @@ int get_page(struct page_info *page, str
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
+ /* Obtain an extra reference to retain if we set PGT_partial. */
|
||||||
+ * Special version of get_page() to be used exclusively when
|
+ if ( preemptible && !get_page(page, owner) )
|
||||||
+ * - a page is known to already have a non-zero reference count
|
+ return -EINVAL;
|
||||||
+ * - the page does not need its owner to be checked
|
|
||||||
+ * - it will not be called more than once without dropping the thus
|
|
||||||
+ * acquired reference again.
|
|
||||||
+ * Due to get_page() reserving one reference, this call cannot fail.
|
|
||||||
+ */
|
|
||||||
+static void get_page_light(struct page_info *page)
|
|
||||||
+{
|
|
||||||
+ u32 x, nx, y = page->count_info;
|
|
||||||
+
|
+
|
||||||
+ do {
|
/* A page table is dirtied when its type count becomes non-zero. */
|
||||||
+ x = y;
|
if ( likely(owner != NULL) )
|
||||||
+ nx = x + 1;
|
paging_mark_dirty(owner, page_to_mfn(page));
|
||||||
+ BUG_ON(!(x & PGC_count_mask)); /* Not allocated? */
|
@@ -1900,8 +1923,13 @@ static int alloc_page_type(struct page_i
|
||||||
+ BUG_ON(!(nx & PGC_count_mask)); /* Overflow? */
|
|
||||||
+ y = cmpxchg(&page->count_info, x, nx);
|
|
||||||
+ }
|
|
||||||
+ while ( unlikely(y != x) );
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
|
|
||||||
static int alloc_page_type(struct page_info *page, unsigned long type,
|
|
||||||
int preemptible)
|
|
||||||
@@ -1899,6 +1941,7 @@ static int alloc_page_type(struct page_i
|
|
||||||
wmb();
|
|
||||||
if ( rc == -EAGAIN )
|
if ( rc == -EAGAIN )
|
||||||
{
|
{
|
||||||
+ get_page_light(page);
|
|
||||||
page->u.inuse.type_info |= PGT_partial;
|
page->u.inuse.type_info |= PGT_partial;
|
||||||
|
+ return -EAGAIN;
|
||||||
}
|
}
|
||||||
else if ( rc == -EINTR )
|
- else if ( rc == -EINTR )
|
||||||
@@ -2009,8 +2052,8 @@ static int __put_page_type_final(struct
|
+
|
||||||
page->u.inuse.type_info--;
|
+ if ( preemptible )
|
||||||
break;
|
|
||||||
case -EINTR:
|
|
||||||
- ASSERT(!(page->u.inuse.type_info &
|
|
||||||
- (PGT_count_mask|PGT_validated|PGT_partial)));
|
|
||||||
+ ASSERT((page->u.inuse.type_info &
|
|
||||||
+ (PGT_count_mask|PGT_validated|PGT_partial)) == 1);
|
|
||||||
if ( !(shadow_mode_enabled(page_get_owner(page)) &&
|
|
||||||
(page->count_info & PGC_page_table)) )
|
|
||||||
page->tlbflush_timestamp = tlbflush_current_time();
|
|
||||||
@@ -2019,6 +2062,7 @@ static int __put_page_type_final(struct
|
|
||||||
break;
|
|
||||||
case -EAGAIN:
|
|
||||||
wmb();
|
|
||||||
+ get_page_light(page);
|
|
||||||
page->u.inuse.type_info |= PGT_partial;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
@@ -2033,6 +2077,7 @@ static int __put_page_type(struct page_i
|
|
||||||
int preemptible)
|
|
||||||
{
|
|
||||||
unsigned long nx, x, y = page->u.inuse.type_info;
|
|
||||||
+ int rc = 0;
|
|
||||||
|
|
||||||
for ( ; ; )
|
|
||||||
{
|
|
||||||
@@ -2056,7 +2101,10 @@ static int __put_page_type(struct page_i
|
|
||||||
x, nx)) != x) )
|
|
||||||
continue;
|
|
||||||
/* We cleared the 'valid bit' so we do the clean up. */
|
|
||||||
- return __put_page_type_final(page, x, preemptible);
|
|
||||||
+ rc = __put_page_type_final(page, x, preemptible);
|
|
||||||
+ if ( x & PGT_partial )
|
|
||||||
+ put_page(page);
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -2078,7 +2126,7 @@ static int __put_page_type(struct page_i
|
|
||||||
return -EINTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
- return 0;
|
|
||||||
+ return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -2086,6 +2134,7 @@ static int __get_page_type(struct page_i
|
|
||||||
int preemptible)
|
|
||||||
{
|
|
||||||
unsigned long nx, x, y = page->u.inuse.type_info;
|
|
||||||
+ int rc = 0;
|
|
||||||
|
|
||||||
ASSERT(!(type & ~(PGT_type_mask | PGT_pae_xen_l2)));
|
|
||||||
|
|
||||||
@@ -2208,10 +2257,13 @@ static int __get_page_type(struct page_i
|
|
||||||
page->nr_validated_ptes = 0;
|
|
||||||
page->partial_pte = 0;
|
|
||||||
}
|
|
||||||
- return alloc_page_type(page, type, preemptible);
|
|
||||||
+ rc = alloc_page_type(page, type, preemptible);
|
|
||||||
}
|
|
||||||
|
|
||||||
- return 0;
|
|
||||||
+ if ( (x & PGT_partial) && !(nx & PGT_partial) )
|
|
||||||
+ put_page(page);
|
+ put_page(page);
|
||||||
+
|
+
|
||||||
+ return rc;
|
+ if ( rc == -EINTR )
|
||||||
|
{
|
||||||
|
ASSERT((page->u.inuse.type_info &
|
||||||
|
(PGT_count_mask|PGT_validated|PGT_partial)) == 1);
|
||||||
|
@@ -2029,8 +2057,13 @@ static int __put_final_page_type(
|
||||||
|
BUG_ON(rc != -EAGAIN);
|
||||||
|
wmb();
|
||||||
|
page->u.inuse.type_info |= PGT_partial;
|
||||||
|
+ /* Must skip put_page() below. */
|
||||||
|
+ preemptible = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if ( preemptible )
|
||||||
|
+ put_page(page);
|
||||||
|
+
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_page_type(struct page_info *page)
|
@@ -2040,6 +2073,10 @@ static int __put_page_type(struct page_i
|
||||||
@@ -2290,7 +2342,7 @@ int new_guest_cr3(unsigned long mfn)
|
{
|
||||||
|
unsigned long nx, x, y = page->u.inuse.type_info;
|
||||||
|
|
||||||
|
+ /* Obtain an extra reference to retain if we set PGT_partial. */
|
||||||
|
+ if ( preemptible && !get_page(page, page_get_owner(page)) )
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
x = y;
|
||||||
|
@@ -2061,6 +2098,8 @@ static int __put_page_type(struct page_i
|
||||||
|
if ( unlikely((y = cmpxchg(&page->u.inuse.type_info,
|
||||||
|
x, nx)) != x) )
|
||||||
|
continue;
|
||||||
|
+ if ( x & PGT_partial )
|
||||||
|
+ put_page(page);
|
||||||
|
/* We cleared the 'valid bit' so we do the clean up. */
|
||||||
|
return __put_final_page_type(page, x, preemptible);
|
||||||
|
}
|
||||||
|
@@ -2081,9 +2120,16 @@ static int __put_page_type(struct page_i
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( preemptible && hypercall_preempt_check() )
|
||||||
|
+ {
|
||||||
|
+ if ( preemptible )
|
||||||
|
+ put_page(page);
|
||||||
|
return -EINTR;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if ( preemptible )
|
||||||
|
+ put_page(page);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2187,7 +2233,11 @@ static int __get_page_type(struct page_i
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
|
||||||
|
+ {
|
||||||
|
+ if ( (x & PGT_partial) && !(nx & PGT_partial) )
|
||||||
|
+ put_page(page);
|
||||||
|
break;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if ( preemptible && hypercall_preempt_check() )
|
||||||
|
return -EINTR;
|
||||||
|
@@ -2296,7 +2346,7 @@ int new_guest_cr3(unsigned long mfn)
|
||||||
#endif
|
#endif
|
||||||
okay = paging_mode_refcounts(d)
|
okay = paging_mode_refcounts(d)
|
||||||
? get_page_from_pagenr(mfn, d)
|
? get_page_from_pagenr(mfn, d)
|
||||||
@ -452,7 +430,7 @@
|
|||||||
if ( unlikely(!okay) )
|
if ( unlikely(!okay) )
|
||||||
{
|
{
|
||||||
MEM_LOG("Error while installing new baseptr %lx", mfn);
|
MEM_LOG("Error while installing new baseptr %lx", mfn);
|
||||||
@@ -2534,7 +2586,7 @@ int do_mmuext_op(
|
@@ -2540,7 +2590,7 @@ int do_mmuext_op(
|
||||||
if ( paging_mode_refcounts(FOREIGNDOM) )
|
if ( paging_mode_refcounts(FOREIGNDOM) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -461,7 +439,7 @@
|
|||||||
okay = !rc;
|
okay = !rc;
|
||||||
if ( unlikely(!okay) )
|
if ( unlikely(!okay) )
|
||||||
{
|
{
|
||||||
@@ -2615,7 +2667,7 @@ int do_mmuext_op(
|
@@ -2621,7 +2671,7 @@ int do_mmuext_op(
|
||||||
okay = get_page_from_pagenr(mfn, d);
|
okay = get_page_from_pagenr(mfn, d);
|
||||||
else
|
else
|
||||||
okay = !get_page_and_type_from_pagenr(
|
okay = !get_page_and_type_from_pagenr(
|
||||||
@ -470,7 +448,7 @@
|
|||||||
if ( unlikely(!okay) )
|
if ( unlikely(!okay) )
|
||||||
{
|
{
|
||||||
MEM_LOG("Error while installing new mfn %lx", mfn);
|
MEM_LOG("Error while installing new mfn %lx", mfn);
|
||||||
@@ -2722,7 +2774,7 @@ int do_mmuext_op(
|
@@ -2728,7 +2778,7 @@ int do_mmuext_op(
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
|
|
||||||
okay = !get_page_and_type_from_pagenr(mfn, PGT_writable_page,
|
okay = !get_page_and_type_from_pagenr(mfn, PGT_writable_page,
|
||||||
@ -479,7 +457,7 @@
|
|||||||
if ( unlikely(!okay) )
|
if ( unlikely(!okay) )
|
||||||
{
|
{
|
||||||
MEM_LOG("Error while clearing mfn %lx", mfn);
|
MEM_LOG("Error while clearing mfn %lx", mfn);
|
||||||
@@ -2755,7 +2807,7 @@ int do_mmuext_op(
|
@@ -2761,7 +2811,7 @@ int do_mmuext_op(
|
||||||
}
|
}
|
||||||
|
|
||||||
okay = !get_page_and_type_from_pagenr(mfn, PGT_writable_page,
|
okay = !get_page_and_type_from_pagenr(mfn, PGT_writable_page,
|
198
18747-x86-partial-page-ref.patch
Normal file
198
18747-x86-partial-page-ref.patch
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1225708322 0
|
||||||
|
# Node ID 540483d2a98f3fbabf06961cc0cc52e3c59c245b
|
||||||
|
# Parent 303b1014f91e5fa0783a5d7095626a47e82db9d0
|
||||||
|
x86: simplify page reference handling for partially (in-)validated pages
|
||||||
|
|
||||||
|
Simplify general page reference management for preempted (partially
|
||||||
|
[in-]validated) pages: Reserve on reference that can be acquired
|
||||||
|
without the risk of overflowing the reference count, thus allowing to
|
||||||
|
have a simplified get_page() equivalent that cannot fail (but must be
|
||||||
|
used with care).
|
||||||
|
|
||||||
|
Doing this conversion pointed out a latent issue in the changes done
|
||||||
|
previously in this area: The extra reference must be acquired before
|
||||||
|
the 'normal' reference gets dropped, so the patch fixes this at once
|
||||||
|
in both the alloc_page_type() and free_page_type() paths (it's really
|
||||||
|
only the latter that failed to work with the change described above).
|
||||||
|
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
|
||||||
|
--- a/xen/arch/x86/mm.c
|
||||||
|
+++ b/xen/arch/x86/mm.c
|
||||||
|
@@ -1856,7 +1856,8 @@ int get_page(struct page_info *page, str
|
||||||
|
nx = x + 1;
|
||||||
|
d = nd;
|
||||||
|
if ( unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
|
||||||
|
- unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
|
||||||
|
+ /* Keep one spare reference to be acquired by get_page_light(). */
|
||||||
|
+ unlikely(((nx + 1) & PGC_count_mask) <= 1) || /* Overflow? */
|
||||||
|
unlikely(d != _domain) ) /* Wrong owner? */
|
||||||
|
{
|
||||||
|
if ( !_shadow_mode_refcounts(domain) && !domain->is_dying )
|
||||||
|
@@ -1878,6 +1879,28 @@ int get_page(struct page_info *page, str
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Special version of get_page() to be used exclusively when
|
||||||
|
+ * - a page is known to already have a non-zero reference count
|
||||||
|
+ * - the page does not need its owner to be checked
|
||||||
|
+ * - it will not be called more than once without dropping the thus
|
||||||
|
+ * acquired reference again.
|
||||||
|
+ * Due to get_page() reserving one reference, this call cannot fail.
|
||||||
|
+ */
|
||||||
|
+static void get_page_light(struct page_info *page)
|
||||||
|
+{
|
||||||
|
+ u32 x, nx, y = page->count_info;
|
||||||
|
+
|
||||||
|
+ do {
|
||||||
|
+ x = y;
|
||||||
|
+ nx = x + 1;
|
||||||
|
+ BUG_ON(!(x & PGC_count_mask)); /* Not allocated? */
|
||||||
|
+ BUG_ON(!(nx & PGC_count_mask)); /* Overflow? */
|
||||||
|
+ y = cmpxchg(&page->count_info, x, nx);
|
||||||
|
+ }
|
||||||
|
+ while ( unlikely(y != x) );
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
static int alloc_page_type(struct page_info *page, unsigned long type,
|
||||||
|
int preemptible)
|
||||||
|
@@ -1885,10 +1908,6 @@ static int alloc_page_type(struct page_i
|
||||||
|
struct domain *owner = page_get_owner(page);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
- /* Obtain an extra reference to retain if we set PGT_partial. */
|
||||||
|
- if ( preemptible && !get_page(page, owner) )
|
||||||
|
- return -EINVAL;
|
||||||
|
-
|
||||||
|
/* A page table is dirtied when its type count becomes non-zero. */
|
||||||
|
if ( likely(owner != NULL) )
|
||||||
|
paging_mark_dirty(owner, page_to_mfn(page));
|
||||||
|
@@ -1922,14 +1941,10 @@ static int alloc_page_type(struct page_i
|
||||||
|
wmb();
|
||||||
|
if ( rc == -EAGAIN )
|
||||||
|
{
|
||||||
|
+ get_page_light(page);
|
||||||
|
page->u.inuse.type_info |= PGT_partial;
|
||||||
|
- return -EAGAIN;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- if ( preemptible )
|
||||||
|
- put_page(page);
|
||||||
|
-
|
||||||
|
- if ( rc == -EINTR )
|
||||||
|
+ else if ( rc == -EINTR )
|
||||||
|
{
|
||||||
|
ASSERT((page->u.inuse.type_info &
|
||||||
|
(PGT_count_mask|PGT_validated|PGT_partial)) == 1);
|
||||||
|
@@ -2044,8 +2059,8 @@ static int __put_final_page_type(
|
||||||
|
}
|
||||||
|
else if ( rc == -EINTR )
|
||||||
|
{
|
||||||
|
- ASSERT(!(page->u.inuse.type_info &
|
||||||
|
- (PGT_count_mask|PGT_validated|PGT_partial)));
|
||||||
|
+ ASSERT((page->u.inuse.type_info &
|
||||||
|
+ (PGT_count_mask|PGT_validated|PGT_partial)) == 1);
|
||||||
|
if ( !(shadow_mode_enabled(page_get_owner(page)) &&
|
||||||
|
(page->count_info & PGC_page_table)) )
|
||||||
|
page->tlbflush_timestamp = tlbflush_current_time();
|
||||||
|
@@ -2056,14 +2071,10 @@ static int __put_final_page_type(
|
||||||
|
{
|
||||||
|
BUG_ON(rc != -EAGAIN);
|
||||||
|
wmb();
|
||||||
|
+ get_page_light(page);
|
||||||
|
page->u.inuse.type_info |= PGT_partial;
|
||||||
|
- /* Must skip put_page() below. */
|
||||||
|
- preemptible = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ( preemptible )
|
||||||
|
- put_page(page);
|
||||||
|
-
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2072,10 +2083,7 @@ static int __put_page_type(struct page_i
|
||||||
|
int preemptible)
|
||||||
|
{
|
||||||
|
unsigned long nx, x, y = page->u.inuse.type_info;
|
||||||
|
-
|
||||||
|
- /* Obtain an extra reference to retain if we set PGT_partial. */
|
||||||
|
- if ( preemptible && !get_page(page, page_get_owner(page)) )
|
||||||
|
- return -EINVAL;
|
||||||
|
+ int rc = 0;
|
||||||
|
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
@@ -2098,10 +2106,11 @@ static int __put_page_type(struct page_i
|
||||||
|
if ( unlikely((y = cmpxchg(&page->u.inuse.type_info,
|
||||||
|
x, nx)) != x) )
|
||||||
|
continue;
|
||||||
|
+ /* We cleared the 'valid bit' so we do the clean up. */
|
||||||
|
+ rc = __put_final_page_type(page, x, preemptible);
|
||||||
|
if ( x & PGT_partial )
|
||||||
|
put_page(page);
|
||||||
|
- /* We cleared the 'valid bit' so we do the clean up. */
|
||||||
|
- return __put_final_page_type(page, x, preemptible);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -2120,17 +2129,10 @@ static int __put_page_type(struct page_i
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( preemptible && hypercall_preempt_check() )
|
||||||
|
- {
|
||||||
|
- if ( preemptible )
|
||||||
|
- put_page(page);
|
||||||
|
return -EINTR;
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ( preemptible )
|
||||||
|
- put_page(page);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
+ return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2138,6 +2140,7 @@ static int __get_page_type(struct page_i
|
||||||
|
int preemptible)
|
||||||
|
{
|
||||||
|
unsigned long nx, x, y = page->u.inuse.type_info;
|
||||||
|
+ int rc = 0;
|
||||||
|
|
||||||
|
ASSERT(!(type & ~(PGT_type_mask | PGT_pae_xen_l2)));
|
||||||
|
|
||||||
|
@@ -2233,11 +2236,7 @@ static int __get_page_type(struct page_i
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
|
||||||
|
- {
|
||||||
|
- if ( (x & PGT_partial) && !(nx & PGT_partial) )
|
||||||
|
- put_page(page);
|
||||||
|
break;
|
||||||
|
- }
|
||||||
|
|
||||||
|
if ( preemptible && hypercall_preempt_check() )
|
||||||
|
return -EINTR;
|
||||||
|
@@ -2264,10 +2263,13 @@ static int __get_page_type(struct page_i
|
||||||
|
page->nr_validated_ptes = 0;
|
||||||
|
page->partial_pte = 0;
|
||||||
|
}
|
||||||
|
- return alloc_page_type(page, type, preemptible);
|
||||||
|
+ rc = alloc_page_type(page, type, preemptible);
|
||||||
|
}
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ if ( (x & PGT_partial) && !(nx & PGT_partial) )
|
||||||
|
+ put_page(page);
|
||||||
|
+
|
||||||
|
+ return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void put_page_type(struct page_info *page)
|
347
18771-reduce-GDT-switching.patch
Normal file
347
18771-reduce-GDT-switching.patch
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1226491295 0
|
||||||
|
# Node ID 8e18dd41c6c7bb0980b29393b275c564cfb96437
|
||||||
|
# Parent 2bd99c5faa420612544a9d94e298332e0e72a86a
|
||||||
|
x86: reduce GDT switching
|
||||||
|
|
||||||
|
Both idle and HVM vCPU-s can easily run on the GDT mapped into general
|
||||||
|
hypervisor space (rather than that placed in per-vCPU virtual space).
|
||||||
|
|
||||||
|
This makes unnecessary some of the additions c/s 18520 did.
|
||||||
|
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/cpu/common.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/cpu/common.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/cpu/common.c
|
||||||
|
@@ -564,7 +564,10 @@ void __cpuinit cpu_init(void)
|
||||||
|
{
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
struct tss_struct *t = &init_tss[cpu];
|
||||||
|
- char gdt_load[10];
|
||||||
|
+ struct desc_ptr gdt_desc = {
|
||||||
|
+ .base = (unsigned long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENTRY),
|
||||||
|
+ .limit = LAST_RESERVED_GDT_BYTE
|
||||||
|
+ };
|
||||||
|
|
||||||
|
if (cpu_test_and_set(cpu, cpu_initialized)) {
|
||||||
|
printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
|
||||||
|
@@ -578,9 +581,7 @@ void __cpuinit cpu_init(void)
|
||||||
|
/* Install correct page table. */
|
||||||
|
write_ptbase(current);
|
||||||
|
|
||||||
|
- *(unsigned short *)(&gdt_load[0]) = LAST_RESERVED_GDT_BYTE;
|
||||||
|
- *(unsigned long *)(&gdt_load[2]) = GDT_VIRT_START(current);
|
||||||
|
- asm volatile ( "lgdt %0" : "=m" (gdt_load) );
|
||||||
|
+ asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
|
||||||
|
|
||||||
|
/* No nested task. */
|
||||||
|
asm volatile ("pushf ; andw $0xbfff,(%"__OP"sp) ; popf" );
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/domain.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/domain.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/domain.c
|
||||||
|
@@ -309,12 +309,7 @@ int vcpu_initialise(struct vcpu *v)
|
||||||
|
if ( is_idle_domain(d) )
|
||||||
|
{
|
||||||
|
v->arch.schedule_tail = continue_idle_domain;
|
||||||
|
- if ( v->vcpu_id )
|
||||||
|
- v->arch.cr3 = d->vcpu[0]->arch.cr3;
|
||||||
|
- else if ( !*idle_vcpu )
|
||||||
|
- v->arch.cr3 = __pa(idle_pg_table);
|
||||||
|
- else if ( !(v->arch.cr3 = clone_idle_pagetable(v)) )
|
||||||
|
- return -ENOMEM;
|
||||||
|
+ v->arch.cr3 = __pa(idle_pg_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
v->arch.guest_context.ctrlreg[4] =
|
||||||
|
@@ -1171,14 +1166,18 @@ static void paravirt_ctxt_switch_to(stru
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline int need_full_gdt(struct vcpu *v)
|
||||||
|
+{
|
||||||
|
+ return (!is_hvm_vcpu(v) && !is_idle_vcpu(v));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void __context_switch(void)
|
||||||
|
{
|
||||||
|
struct cpu_user_regs *stack_regs = guest_cpu_user_regs();
|
||||||
|
- unsigned int i, cpu = smp_processor_id();
|
||||||
|
+ unsigned int cpu = smp_processor_id();
|
||||||
|
struct vcpu *p = per_cpu(curr_vcpu, cpu);
|
||||||
|
struct vcpu *n = current;
|
||||||
|
struct desc_struct *gdt;
|
||||||
|
- struct page_info *page;
|
||||||
|
struct desc_ptr gdt_desc;
|
||||||
|
|
||||||
|
ASSERT(p != n);
|
||||||
|
@@ -1207,16 +1206,19 @@ static void __context_switch(void)
|
||||||
|
|
||||||
|
gdt = !is_pv_32on64_vcpu(n) ? per_cpu(gdt_table, cpu) :
|
||||||
|
per_cpu(compat_gdt_table, cpu);
|
||||||
|
- page = virt_to_page(gdt);
|
||||||
|
- for (i = 0; i < NR_RESERVED_GDT_PAGES; ++i)
|
||||||
|
+ if ( need_full_gdt(n) )
|
||||||
|
{
|
||||||
|
- l1e_write(n->domain->arch.mm_perdomain_pt +
|
||||||
|
- (n->vcpu_id << GDT_LDT_VCPU_SHIFT) +
|
||||||
|
- FIRST_RESERVED_GDT_PAGE + i,
|
||||||
|
- l1e_from_page(page + i, __PAGE_HYPERVISOR));
|
||||||
|
+ struct page_info *page = virt_to_page(gdt);
|
||||||
|
+ unsigned int i;
|
||||||
|
+ for ( i = 0; i < NR_RESERVED_GDT_PAGES; i++ )
|
||||||
|
+ l1e_write(n->domain->arch.mm_perdomain_pt +
|
||||||
|
+ (n->vcpu_id << GDT_LDT_VCPU_SHIFT) +
|
||||||
|
+ FIRST_RESERVED_GDT_PAGE + i,
|
||||||
|
+ l1e_from_page(page + i, __PAGE_HYPERVISOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ( p->vcpu_id != n->vcpu_id )
|
||||||
|
+ if ( need_full_gdt(p) &&
|
||||||
|
+ ((p->vcpu_id != n->vcpu_id) || !need_full_gdt(n)) )
|
||||||
|
{
|
||||||
|
gdt_desc.limit = LAST_RESERVED_GDT_BYTE;
|
||||||
|
gdt_desc.base = (unsigned long)(gdt - FIRST_RESERVED_GDT_ENTRY);
|
||||||
|
@@ -1225,8 +1227,10 @@ static void __context_switch(void)
|
||||||
|
|
||||||
|
write_ptbase(n);
|
||||||
|
|
||||||
|
- if ( p->vcpu_id != n->vcpu_id )
|
||||||
|
+ if ( need_full_gdt(n) &&
|
||||||
|
+ ((p->vcpu_id != n->vcpu_id) || !need_full_gdt(p)) )
|
||||||
|
{
|
||||||
|
+ gdt_desc.limit = LAST_RESERVED_GDT_BYTE;
|
||||||
|
gdt_desc.base = GDT_VIRT_START(n);
|
||||||
|
asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
|
||||||
|
}
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/domain_build.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/domain_build.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/domain_build.c
|
||||||
|
@@ -707,6 +707,7 @@ int __init construct_dom0(
|
||||||
|
|
||||||
|
/* Install the new page tables. */
|
||||||
|
local_irq_disable();
|
||||||
|
+ /* We run on dom0's page tables for the final part of the build process. */
|
||||||
|
write_ptbase(v);
|
||||||
|
|
||||||
|
/* Copy the OS image and free temporary buffer. */
|
||||||
|
@@ -719,11 +720,11 @@ int __init construct_dom0(
|
||||||
|
(parms.virt_hypercall >= v_end) )
|
||||||
|
{
|
||||||
|
write_ptbase(current);
|
||||||
|
- local_irq_enable();
|
||||||
|
printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
- hypercall_page_initialise(d, (void *)(unsigned long)parms.virt_hypercall);
|
||||||
|
+ hypercall_page_initialise(
|
||||||
|
+ d, (void *)(unsigned long)parms.virt_hypercall);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the initial ramdisk. */
|
||||||
|
@@ -804,7 +805,7 @@ int __init construct_dom0(
|
||||||
|
xlat_start_info(si, XLAT_start_info_console_dom0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- /* Reinstate the caller's page tables. */
|
||||||
|
+ /* Return to idle domain's page tables. */
|
||||||
|
write_ptbase(current);
|
||||||
|
local_irq_enable();
|
||||||
|
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/hvm/vmx/vmcs.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/hvm/vmx/vmcs.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/hvm/vmx/vmcs.c
|
||||||
|
@@ -444,6 +444,8 @@ static void vmx_set_host_env(struct vcpu
|
||||||
|
{
|
||||||
|
unsigned int cpu = smp_processor_id();
|
||||||
|
|
||||||
|
+ __vmwrite(HOST_GDTR_BASE,
|
||||||
|
+ (unsigned long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENTRY));
|
||||||
|
__vmwrite(HOST_IDTR_BASE, (unsigned long)idt_tables[cpu]);
|
||||||
|
|
||||||
|
__vmwrite(HOST_TR_SELECTOR, TSS_ENTRY << 3);
|
||||||
|
@@ -541,9 +543,6 @@ 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));
|
||||||
|
|
||||||
|
- /* Host GDTR base. */
|
||||||
|
- __vmwrite(HOST_GDTR_BASE, GDT_VIRT_START(v));
|
||||||
|
-
|
||||||
|
/* Host data selectors. */
|
||||||
|
__vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
|
||||||
|
__vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/setup.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/setup.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/setup.c
|
||||||
|
@@ -230,7 +230,6 @@ static void __init percpu_init_areas(voi
|
||||||
|
static void __init init_idle_domain(void)
|
||||||
|
{
|
||||||
|
struct domain *idle_domain;
|
||||||
|
- unsigned int i;
|
||||||
|
|
||||||
|
/* Domain creation requires that scheduler structures are initialised. */
|
||||||
|
scheduler_init();
|
||||||
|
@@ -243,12 +242,6 @@ static void __init init_idle_domain(void
|
||||||
|
idle_vcpu[0] = this_cpu(curr_vcpu) = current;
|
||||||
|
|
||||||
|
setup_idle_pagetable();
|
||||||
|
-
|
||||||
|
- for (i = 0; i < NR_RESERVED_GDT_PAGES; ++i)
|
||||||
|
- idle_domain->arch.mm_perdomain_pt[FIRST_RESERVED_GDT_PAGE + i] =
|
||||||
|
- l1e_from_page(virt_to_page(boot_cpu_gdt_table) + i,
|
||||||
|
- __PAGE_HYPERVISOR);
|
||||||
|
-
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init srat_detect_node(int cpu)
|
||||||
|
@@ -456,6 +449,7 @@ void __init __start_xen(unsigned long mb
|
||||||
|
parse_video_info();
|
||||||
|
|
||||||
|
set_current((struct vcpu *)0xfffff000); /* debug sanity */
|
||||||
|
+ idle_vcpu[0] = current;
|
||||||
|
set_processor_id(0); /* needed early, for smp_processor_id() */
|
||||||
|
if ( cpu_has_efer )
|
||||||
|
rdmsrl(MSR_EFER, this_cpu(efer));
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/smpboot.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/smpboot.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/smpboot.c
|
||||||
|
@@ -828,7 +828,7 @@ static int __devinit do_boot_cpu(int api
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned long boot_error;
|
||||||
|
- unsigned int i;
|
||||||
|
+ unsigned int order;
|
||||||
|
int timeout;
|
||||||
|
unsigned long start_eip;
|
||||||
|
unsigned short nmi_high = 0, nmi_low = 0;
|
||||||
|
@@ -864,21 +864,21 @@ static int __devinit do_boot_cpu(int api
|
||||||
|
|
||||||
|
gdt = per_cpu(gdt_table, cpu);
|
||||||
|
if (gdt == boot_cpu_gdt_table) {
|
||||||
|
- i = get_order_from_pages(NR_RESERVED_GDT_PAGES);
|
||||||
|
+ order = get_order_from_pages(NR_RESERVED_GDT_PAGES);
|
||||||
|
#ifdef __x86_64__
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
- page = alloc_domheap_pages(NULL, i,
|
||||||
|
+ page = alloc_domheap_pages(NULL, order,
|
||||||
|
MEMF_node(cpu_to_node(cpu)));
|
||||||
|
per_cpu(compat_gdt_table, cpu) = gdt = page_to_virt(page);
|
||||||
|
memcpy(gdt, boot_cpu_compat_gdt_table,
|
||||||
|
NR_RESERVED_GDT_PAGES * PAGE_SIZE);
|
||||||
|
gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu;
|
||||||
|
#endif
|
||||||
|
- page = alloc_domheap_pages(NULL, i,
|
||||||
|
+ page = alloc_domheap_pages(NULL, order,
|
||||||
|
MEMF_node(cpu_to_node(cpu)));
|
||||||
|
per_cpu(gdt_table, cpu) = gdt = page_to_virt(page);
|
||||||
|
#else
|
||||||
|
- per_cpu(gdt_table, cpu) = gdt = alloc_xenheap_pages(i);
|
||||||
|
+ per_cpu(gdt_table, cpu) = gdt = alloc_xenheap_pages(order);
|
||||||
|
#endif
|
||||||
|
memcpy(gdt, boot_cpu_gdt_table,
|
||||||
|
NR_RESERVED_GDT_PAGES * PAGE_SIZE);
|
||||||
|
@@ -886,13 +886,6 @@ static int __devinit do_boot_cpu(int api
|
||||||
|
gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
- for (i = 0; i < NR_RESERVED_GDT_PAGES; ++i)
|
||||||
|
- v->domain->arch.mm_perdomain_pt
|
||||||
|
- [(v->vcpu_id << GDT_LDT_VCPU_SHIFT) +
|
||||||
|
- FIRST_RESERVED_GDT_PAGE + i]
|
||||||
|
- = l1e_from_page(virt_to_page(gdt) + i,
|
||||||
|
- __PAGE_HYPERVISOR);
|
||||||
|
-
|
||||||
|
#ifdef __i386__
|
||||||
|
if (!per_cpu(doublefault_tss, cpu)) {
|
||||||
|
per_cpu(doublefault_tss, cpu) = alloc_xenheap_page();
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/x86_32/mm.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/x86_32/mm.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/x86_32/mm.c
|
||||||
|
@@ -132,30 +132,6 @@ void __init setup_idle_pagetable(void)
|
||||||
|
__PAGE_HYPERVISOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
-unsigned long clone_idle_pagetable(struct vcpu *v)
|
||||||
|
-{
|
||||||
|
- unsigned int i;
|
||||||
|
- struct domain *d = v->domain;
|
||||||
|
- l3_pgentry_t *l3_table = v->arch.pae_l3_cache.table[0];
|
||||||
|
- l2_pgentry_t *l2_table = alloc_xenheap_page();
|
||||||
|
-
|
||||||
|
- if ( !l2_table )
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
- memcpy(l3_table, idle_pg_table, L3_PAGETABLE_ENTRIES * sizeof(*l3_table));
|
||||||
|
- l3_table[l3_table_offset(PERDOMAIN_VIRT_START)] =
|
||||||
|
- l3e_from_page(virt_to_page(l2_table), _PAGE_PRESENT);
|
||||||
|
-
|
||||||
|
- copy_page(l2_table, idle_pg_table_l2 +
|
||||||
|
- l3_table_offset(PERDOMAIN_VIRT_START) * L2_PAGETABLE_ENTRIES);
|
||||||
|
- for ( i = 0; i < PDPT_L2_ENTRIES; ++i )
|
||||||
|
- l2_table[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
|
||||||
|
- l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt) + i,
|
||||||
|
- __PAGE_HYPERVISOR);
|
||||||
|
-
|
||||||
|
- return __pa(l3_table);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void __init zap_low_mappings(l2_pgentry_t *dom0_l2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/x86_64/mm.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/x86_64/mm.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/x86_64/mm.c
|
||||||
|
@@ -21,7 +21,6 @@
|
||||||
|
#include <xen/lib.h>
|
||||||
|
#include <xen/init.h>
|
||||||
|
#include <xen/mm.h>
|
||||||
|
-#include <xen/numa.h>
|
||||||
|
#include <xen/sched.h>
|
||||||
|
#include <xen/guest_access.h>
|
||||||
|
#include <asm/current.h>
|
||||||
|
@@ -207,24 +206,6 @@ void __init setup_idle_pagetable(void)
|
||||||
|
__PAGE_HYPERVISOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
-unsigned long clone_idle_pagetable(struct vcpu *v)
|
||||||
|
-{
|
||||||
|
- struct domain *d = v->domain;
|
||||||
|
- struct page_info *page = alloc_domheap_page(NULL,
|
||||||
|
- MEMF_node(vcpu_to_node(v)));
|
||||||
|
- l4_pgentry_t *l4_table = page_to_virt(page);
|
||||||
|
-
|
||||||
|
- if ( !page )
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
- copy_page(l4_table, idle_pg_table);
|
||||||
|
- l4_table[l4_table_offset(PERDOMAIN_VIRT_START)] =
|
||||||
|
- l4e_from_page(virt_to_page(d->arch.mm_perdomain_l3),
|
||||||
|
- __PAGE_HYPERVISOR);
|
||||||
|
-
|
||||||
|
- return __pa(l4_table);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void __init zap_low_mappings(void)
|
||||||
|
{
|
||||||
|
BUG_ON(num_online_cpus() != 1);
|
||||||
|
Index: xen-3.3.1-testing/xen/include/asm-x86/page.h
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/include/asm-x86/page.h
|
||||||
|
+++ xen-3.3.1-testing/xen/include/asm-x86/page.h
|
||||||
|
@@ -278,7 +278,6 @@ extern unsigned int m2p_compat_vstart;
|
||||||
|
#endif
|
||||||
|
void paging_init(void);
|
||||||
|
void setup_idle_pagetable(void);
|
||||||
|
-unsigned long clone_idle_pagetable(struct vcpu *);
|
||||||
|
#endif /* !defined(__ASSEMBLY__) */
|
||||||
|
|
||||||
|
#define _PAGE_PRESENT 0x001U
|
92
18778-msi-irq-fix.patch
Normal file
92
18778-msi-irq-fix.patch
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User Keir Fraser <keir.fraser@citrix.com>
|
||||||
|
# Date 1226593868 0
|
||||||
|
# Node ID a0910b1b5ec0c938f1c46437df6c28cbeff52c68
|
||||||
|
# Parent d44ad6db638c1308e5ee4a47509769c3cccbe1e8
|
||||||
|
x86: don't disable MSI in order to mask an IRQ
|
||||||
|
|
||||||
|
... as that's not really correct, and there are devices which can't
|
||||||
|
even cope with that. Instead, check whether an MSI IRQ can be masked,
|
||||||
|
and if it can't, treat it just like a level triggered IO-APIC IRQ.
|
||||||
|
|
||||||
|
There's one other bug fix in here, correcting an off-by-one error on
|
||||||
|
the entry_nr range check in __pci_enable_msix().
|
||||||
|
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||||||
|
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/irq.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/irq.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/irq.c
|
||||||
|
@@ -463,14 +463,19 @@ int pirq_acktype(struct domain *d, int i
|
||||||
|
/*
|
||||||
|
* Edge-triggered IO-APIC and LAPIC interrupts need no final
|
||||||
|
* acknowledgement: we ACK early during interrupt processing.
|
||||||
|
- * MSIs are treated as edge-triggered interrupts.
|
||||||
|
*/
|
||||||
|
if ( !strcmp(desc->handler->typename, "IO-APIC-edge") ||
|
||||||
|
- !strcmp(desc->handler->typename, "local-APIC-edge") ||
|
||||||
|
- !strcmp(desc->handler->typename, "PCI-MSI") )
|
||||||
|
+ !strcmp(desc->handler->typename, "local-APIC-edge") )
|
||||||
|
return ACKTYPE_NONE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * MSIs are treated as edge-triggered interrupts, except
|
||||||
|
+ * when there is no proper way to mask them.
|
||||||
|
+ */
|
||||||
|
+ if ( desc->handler == &pci_msi_type )
|
||||||
|
+ return msi_maskable_irq(desc->msi_desc) ? ACKTYPE_NONE : ACKTYPE_EOI;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
* Level-triggered IO-APIC interrupts need to be acknowledged on the CPU
|
||||||
|
* on which they were received. This is because we tickle the LAPIC to EOI.
|
||||||
|
*/
|
||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/msi.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/msi.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/msi.c
|
||||||
|
@@ -303,6 +303,13 @@ static void msix_flush_writes(unsigned i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+int msi_maskable_irq(const struct msi_desc *entry)
|
||||||
|
+{
|
||||||
|
+ BUG_ON(!entry);
|
||||||
|
+ return entry->msi_attrib.type != PCI_CAP_ID_MSI
|
||||||
|
+ || entry->msi_attrib.maskbit;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void msi_set_mask_bit(unsigned int irq, int flag)
|
||||||
|
{
|
||||||
|
struct msi_desc *entry = irq_desc[irq].msi_desc;
|
||||||
|
@@ -323,8 +330,6 @@ static void msi_set_mask_bit(unsigned in
|
||||||
|
mask_bits &= ~(1);
|
||||||
|
mask_bits |= flag;
|
||||||
|
pci_conf_write32(bus, slot, func, pos, mask_bits);
|
||||||
|
- } else {
|
||||||
|
- msi_set_enable(entry->dev, !flag);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PCI_CAP_ID_MSIX:
|
||||||
|
@@ -654,7 +659,7 @@ static int __pci_enable_msix(struct msi_
|
||||||
|
pos = pci_find_cap_offset(msi->bus, slot, func, PCI_CAP_ID_MSIX);
|
||||||
|
control = pci_conf_read16(msi->bus, slot, func, msi_control_reg(pos));
|
||||||
|
nr_entries = multi_msix_capable(control);
|
||||||
|
- if (msi->entry_nr > nr_entries)
|
||||||
|
+ if (msi->entry_nr >= nr_entries)
|
||||||
|
{
|
||||||
|
spin_unlock(&pdev->lock);
|
||||||
|
return -EINVAL;
|
||||||
|
Index: xen-3.3.1-testing/xen/include/asm-x86/msi.h
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/include/asm-x86/msi.h
|
||||||
|
+++ xen-3.3.1-testing/xen/include/asm-x86/msi.h
|
||||||
|
@@ -97,6 +97,8 @@ struct msi_desc {
|
||||||
|
int remap_index; /* index in interrupt remapping table */
|
||||||
|
};
|
||||||
|
|
||||||
|
+int msi_maskable_irq(const struct msi_desc *);
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Assume the maximum number of hot plug slots supported by the system is about
|
||||||
|
* ten. The worstcase is that each of these slots is hot-added with a device,
|
@ -45,7 +45,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
/* read the name of the device */
|
/* read the name of the device */
|
||||||
if (pasprintf(&buf, "%s/dev", bpath) == -1)
|
if (pasprintf(&buf, "%s/dev", bpath) == -1)
|
||||||
continue;
|
continue;
|
||||||
@@ -429,6 +437,7 @@ void xenstore_parse_domain_config(int hv
|
@@ -432,6 +440,7 @@ void xenstore_parse_domain_config(int hv
|
||||||
free(type);
|
free(type);
|
||||||
free(params);
|
free(params);
|
||||||
free(dev);
|
free(dev);
|
||||||
|
@ -401,24 +401,27 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xenstore.c
|
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xenstore.c
|
||||||
+++ xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
+++ xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
||||||
@@ -297,6 +297,16 @@ void xenstore_parse_domain_config(int hv
|
@@ -333,6 +333,19 @@ void xenstore_parse_domain_config(int hv
|
||||||
bdrv_set_type_hint(bs, BDRV_TYPE_CDROM);
|
if (bdrv_open2(bs, params, 0 /* snapshot */, format) < 0)
|
||||||
if (pasprintf(&buf, "%s/params", bpath) != -1)
|
fprintf(stderr, "qemu: could not open vbd '%s' or hard disk image '%s' (drv '%s' format '%s')\n", buf, params, drv ? drv : "?", format ? format->format_name : "0");
|
||||||
xs_watch(xsh, buf, dev);
|
}
|
||||||
+ /* if pyhsical put a watch on media-present */
|
+ /* if cdrom pyhsical put a watch on media-present */
|
||||||
|
+ if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) {
|
||||||
+ if (drv && !strcmp(drv, "phy")) {
|
+ if (drv && !strcmp(drv, "phy")) {
|
||||||
+ if (pasprintf(&buf, "%s/media-present", bpath) != -1) {
|
+ if (pasprintf(&buf, "%s/media-present", bpath) != -1) {
|
||||||
+ if (bdrv_is_inserted(bs))
|
+ if (bdrv_is_inserted(bs))
|
||||||
+ xs_write(xsh, XBT_NULL, buf, "1", strlen("1"));
|
+ xs_write(xsh, XBT_NULL, buf, "1", strlen("1"));
|
||||||
+ else
|
+ else {
|
||||||
+ xs_write(xsh, XBT_NULL, buf, "0", strlen("0"));
|
+ xs_write(xsh, XBT_NULL, buf, "0", strlen("0"));
|
||||||
|
+ }
|
||||||
+ xs_watch(xsh, buf, "media-present");
|
+ xs_watch(xsh, buf, "media-present");
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
}
|
+ }
|
||||||
|
|
||||||
/* open device now if media present */
|
drives_table[nb_drives].bdrv = bs;
|
||||||
@@ -631,6 +641,50 @@ void xenstore_record_dm_state(char *stat
|
nb_drives++;
|
||||||
|
@@ -631,6 +644,50 @@ void xenstore_record_dm_state(char *stat
|
||||||
xenstore_record_dm("state", state);
|
xenstore_record_dm("state", state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,7 +472,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
void xenstore_process_event(void *opaque)
|
void xenstore_process_event(void *opaque)
|
||||||
{
|
{
|
||||||
char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL;
|
char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL;
|
||||||
@@ -650,6 +704,11 @@ void xenstore_process_event(void *opaque
|
@@ -650,6 +707,11 @@ void xenstore_process_event(void *opaque
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/image.py
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/tools/python/xen/xend/image.py
|
--- xen-3.3.1-testing.orig/tools/python/xen/xend/image.py
|
||||||
+++ xen-3.3.1-testing/tools/python/xen/xend/image.py
|
+++ xen-3.3.1-testing/tools/python/xen/xend/image.py
|
||||||
@@ -697,6 +697,7 @@ class HVMImageHandler(ImageHandler):
|
@@ -703,6 +703,7 @@ class HVMImageHandler(ImageHandler):
|
||||||
|
|
||||||
self.apic = int(vmConfig['platform'].get('apic', 0))
|
self.apic = int(vmConfig['platform'].get('apic', 0))
|
||||||
self.acpi = int(vmConfig['platform'].get('acpi', 0))
|
self.acpi = int(vmConfig['platform'].get('acpi', 0))
|
||||||
@ -53,7 +53,7 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/image.py
|
|||||||
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
|
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
|
||||||
|
|
||||||
|
|
||||||
@@ -803,6 +804,7 @@ class HVMImageHandler(ImageHandler):
|
@@ -809,6 +810,7 @@ class HVMImageHandler(ImageHandler):
|
||||||
log.debug("store_evtchn = %d", store_evtchn)
|
log.debug("store_evtchn = %d", store_evtchn)
|
||||||
log.debug("memsize = %d", mem_mb)
|
log.debug("memsize = %d", mem_mb)
|
||||||
log.debug("vcpus = %d", self.vm.getVCpuCount())
|
log.debug("vcpus = %d", self.vm.getVCpuCount())
|
||||||
@ -61,7 +61,7 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/image.py
|
|||||||
log.debug("acpi = %d", self.acpi)
|
log.debug("acpi = %d", self.acpi)
|
||||||
log.debug("apic = %d", self.apic)
|
log.debug("apic = %d", self.apic)
|
||||||
|
|
||||||
@@ -810,6 +812,7 @@ class HVMImageHandler(ImageHandler):
|
@@ -816,6 +818,7 @@ class HVMImageHandler(ImageHandler):
|
||||||
image = self.loader,
|
image = self.loader,
|
||||||
memsize = mem_mb,
|
memsize = mem_mb,
|
||||||
vcpus = self.vm.getVCpuCount(),
|
vcpus = self.vm.getVCpuCount(),
|
||||||
|
@ -108,7 +108,7 @@ Index: xen-3.3.1-testing/xen/arch/x86/hvm/hvm.c
|
|||||||
return hvm_funcs.msr_write_intercept(regs);
|
return hvm_funcs.msr_write_intercept(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1961,6 +1977,10 @@ int hvm_do_hypercall(struct cpu_user_reg
|
@@ -2002,6 +2018,10 @@ int hvm_do_hypercall(struct cpu_user_reg
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ Index: xen-3.3.1-testing/xen/arch/x86/hvm/hvm.c
|
|||||||
|
|
||||||
if ( (eax >= NR_hypercalls) || !hvm_hypercall32_table[eax] )
|
if ( (eax >= NR_hypercalls) || !hvm_hypercall32_table[eax] )
|
||||||
{
|
{
|
||||||
@@ -2462,6 +2482,15 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
@@ -2503,6 +2523,15 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -31,7 +31,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/hw/xen_blktap.c
|
|||||||
|
|
||||||
/*Open file*/
|
/*Open file*/
|
||||||
if (s == NULL || open_disk(s, path, msg->drivertype, msg->readonly)) {
|
if (s == NULL || open_disk(s, path, msg->drivertype, msg->readonly)) {
|
||||||
@@ -624,7 +632,8 @@ static void handle_blktap_ctrlmsg(void*
|
@@ -645,7 +653,8 @@ static void handle_blktap_ctrlmsg(void*
|
||||||
case CTLMSG_CLOSE:
|
case CTLMSG_CLOSE:
|
||||||
s = get_state(msg->cookie);
|
s = get_state(msg->cookie);
|
||||||
if (s) unmap_disk(s);
|
if (s) unmap_disk(s);
|
||||||
|
63
ioemu-vnc-resize.patch
Normal file
63
ioemu-vnc-resize.patch
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
Index: xen-3.3.1-testing/tools/ioemu-remote/vnc.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/tools/ioemu-remote/vnc.c
|
||||||
|
+++ xen-3.3.1-testing/tools/ioemu-remote/vnc.c
|
||||||
|
@@ -352,6 +352,11 @@ static void vnc_dpy_update(DisplayState
|
||||||
|
{
|
||||||
|
VncState *vs = ds->opaque;
|
||||||
|
|
||||||
|
+ x = MIN(x, vs->width);
|
||||||
|
+ y = MIN(y, vs->height);
|
||||||
|
+ w = MIN(w, vs->width - x);
|
||||||
|
+ h = MIN(h, vs->height - y);
|
||||||
|
+
|
||||||
|
set_bits_in_row(vs, vs->dirty_row, x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -405,9 +413,13 @@ static void vnc_dpy_resize_shared(Displa
|
||||||
|
size_changed = ds->width != w || ds->height != h;
|
||||||
|
ds->width = w;
|
||||||
|
ds->height = h;
|
||||||
|
- if (vs->csock != -1 && vs->has_resize && size_changed) {
|
||||||
|
+ if (size_changed) {
|
||||||
|
vs->width = ds->width;
|
||||||
|
vs->height = ds->height;
|
||||||
|
+ VNC_DEBUG("vs->width = %d, vs->height = %d\n",
|
||||||
|
+ ds->width, ds->height);
|
||||||
|
+ }
|
||||||
|
+ if (vs->csock != -1 && vs->has_resize && size_changed) {
|
||||||
|
if (vs->update_requested) {
|
||||||
|
vnc_write_u8(vs, 0); /* msg id */
|
||||||
|
vnc_write_u8(vs, 0);
|
||||||
|
@@ -1794,6 +1837,31 @@ static int protocol_client_msg(VncState
|
||||||
|
}
|
||||||
|
|
||||||
|
set_encodings(vs, (int32_t *)(data + 4), limit);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * The initialization of a VNC connection can race with xenfb changing
|
||||||
|
+ * the resolution. This happens when the VNC connection is already
|
||||||
|
+ * established, but the client has not yet advertised has_resize, so it
|
||||||
|
+ * won't get notified of the switch.
|
||||||
|
+ *
|
||||||
|
+ * Therefore we resend the resolution as soon as the client has sent its
|
||||||
|
+ * encodings.
|
||||||
|
+ */
|
||||||
|
+ if (vs->has_resize) {
|
||||||
|
+ /* Resize the VNC window */
|
||||||
|
+ vnc_write_u8(vs, 0); /* msg id */
|
||||||
|
+ vnc_write_u8(vs, 0);
|
||||||
|
+ vnc_write_u16(vs, 1); /* number of rects */
|
||||||
|
+ vnc_framebuffer_update(vs, 0, 0, vs->ds->width, vs->ds->height, -223);
|
||||||
|
+
|
||||||
|
+ /* Ensure that the new area is updated */
|
||||||
|
+ vnc_write_u8(vs, 0); /* msg id */
|
||||||
|
+ vnc_write_u8(vs, 0);
|
||||||
|
+ vnc_write_u16(vs, 1); /* number of rects */
|
||||||
|
+ send_framebuffer_update(vs, 0, 0, vs->ds->width, vs->ds->height);
|
||||||
|
+
|
||||||
|
+ vnc_flush(vs);
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (len == 1)
|
@ -2,7 +2,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xenstore.c
|
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xenstore.c
|
||||||
+++ xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
+++ xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
||||||
@@ -652,6 +652,19 @@ static void xenstore_process_dm_command_
|
@@ -671,6 +671,18 @@ static void xenstore_process_dm_command_
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot_name = xs_read(xsh, XBT_NULL, path, &len);
|
snapshot_name = xs_read(xsh, XBT_NULL, path, &len);
|
||||||
@ -16,9 +16,69 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
+ par = xs_read(xsh, XBT_NULL, path, &len);
|
+ par = xs_read(xsh, XBT_NULL, path, &len);
|
||||||
+ if (!par)
|
+ if (!par)
|
||||||
+ goto out;
|
+ goto out;
|
||||||
+ // TODO Error handling
|
+ if (delete_disk_snapshots(par) == 0)
|
||||||
+ do_delvm(par);
|
+ xenstore_record_dm_state("snapshot-deleted");
|
||||||
+ xenstore_record_dm_state("snapshot-deleted");
|
|
||||||
} else if (!strncmp(command, "continue", len)) {
|
} else if (!strncmp(command, "continue", len)) {
|
||||||
fprintf(logfile, "dm-command: continue after state save\n");
|
fprintf(logfile, "dm-command: continue after state save\n");
|
||||||
xen_pause_requested = 0;
|
xen_pause_requested = 0;
|
||||||
|
Index: xen-3.3.1-testing/tools/ioemu-remote/xen-vl-extra.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xen-vl-extra.c
|
||||||
|
+++ xen-3.3.1-testing/tools/ioemu-remote/xen-vl-extra.c
|
||||||
|
@@ -16,6 +16,8 @@ static int qemu_savevm_state(QEMUFile *f
|
||||||
|
static int qemu_loadvm_state(QEMUFile *f);
|
||||||
|
|
||||||
|
static int bdrv_can_snapshot(BlockDriverState *bs);
|
||||||
|
+static int bdrv_has_snapshot(BlockDriverState *bs);
|
||||||
|
+static BlockDriverState *get_bs_snapshots(void);
|
||||||
|
static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
@@ -166,6 +168,35 @@ the_end:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int delete_disk_snapshots(const char* name)
|
||||||
|
+{
|
||||||
|
+ BlockDriverState *bs, *bs1;
|
||||||
|
+ int i, ret;
|
||||||
|
+
|
||||||
|
+ bs = get_bs_snapshots();
|
||||||
|
+ if (!bs) {
|
||||||
|
+ xenstore_record_dm_error("No block device supports snapshots");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for(i = 0; i <= nb_drives; i++) {
|
||||||
|
+ bs1 = drives_table[i].bdrv;
|
||||||
|
+ if (bdrv_has_snapshot(bs1)) {
|
||||||
|
+ ret = bdrv_snapshot_delete(bs1, name);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ if (ret == -ENOTSUP)
|
||||||
|
+ fprintf(stderr, "Snapshots not supported on device '%s'\n",
|
||||||
|
+ bdrv_get_device_name(bs1));
|
||||||
|
+ else
|
||||||
|
+ fprintf(stderr, "Error %d while deleting snapshot on "
|
||||||
|
+ "'%s'\n", ret, bdrv_get_device_name(bs1));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct qemu_alarm_timer;
|
||||||
|
static int unix_start_timer(struct qemu_alarm_timer *t) { return 0; }
|
||||||
|
static void unix_stop_timer(struct qemu_alarm_timer *t) { }
|
||||||
|
Index: xen-3.3.1-testing/tools/ioemu-remote/qemu-xen.h
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/tools/ioemu-remote/qemu-xen.h
|
||||||
|
+++ xen-3.3.1-testing/tools/ioemu-remote/qemu-xen.h
|
||||||
|
@@ -22,6 +22,7 @@ enum {
|
||||||
|
|
||||||
|
/* xen-vl-extra.c */
|
||||||
|
int save_disk_snapshots(const char* name);
|
||||||
|
+int delete_disk_snapshots(const char* name);
|
||||||
|
|
||||||
|
/* helper2.c */
|
||||||
|
extern long time_offset;
|
||||||
|
@ -35,7 +35,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/hw/xen_blktap.c
|
|||||||
static void handle_blktap_iomsg(void* private);
|
static void handle_blktap_iomsg(void* private);
|
||||||
|
|
||||||
struct aiocb_info {
|
struct aiocb_info {
|
||||||
@@ -502,6 +504,10 @@ static void handle_blktap_ctrlmsg(void*
|
@@ -502,6 +504,10 @@ static void handle_blktap_ctrlmsg(void*
|
||||||
|
|
||||||
char buf[MSG_SIZE];
|
char buf[MSG_SIZE];
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/hw/xen_blktap.c
|
|||||||
length = read(read_fd, buf, MSG_SIZE);
|
length = read(read_fd, buf, MSG_SIZE);
|
||||||
|
|
||||||
if (length > 0 && length >= sizeof(msg_hdr_t))
|
if (length > 0 && length >= sizeof(msg_hdr_t))
|
||||||
@@ -557,7 +563,18 @@ static void handle_blktap_ctrlmsg(void*
|
@@ -557,7 +563,39 @@ static void handle_blktap_ctrlmsg(void*
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
ret = ((map_new_dev(s, msg_dev->devnum)
|
ret = ((map_new_dev(s, msg_dev->devnum)
|
||||||
== msg_dev->devnum ? 0: -1));
|
== msg_dev->devnum ? 0: -1));
|
||||||
@ -57,10 +57,31 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/hw/xen_blktap.c
|
|||||||
+ fprintf(stderr, "Reading snapshot name for %d\n", msg_dev->be_id);
|
+ fprintf(stderr, "Reading snapshot name for %d\n", msg_dev->be_id);
|
||||||
+ snapshot = get_snapshot_name(msg_dev->be_id);
|
+ snapshot = get_snapshot_name(msg_dev->be_id);
|
||||||
+ if (snapshot) {
|
+ if (snapshot) {
|
||||||
+ // TODO Error handling
|
|
||||||
+ fprintf(stderr, "Using snapshot %s\n", snapshot);
|
+ fprintf(stderr, "Using snapshot %s\n", snapshot);
|
||||||
+ if (bdrv_snapshot_goto(s->bs, snapshot) < 0)
|
+ ret = bdrv_snapshot_goto(s->bs, snapshot);
|
||||||
|
+ switch (ret) {
|
||||||
|
+ case 0:
|
||||||
|
+ /* Success */
|
||||||
|
+ break;
|
||||||
|
+ case -ENOTSUP:
|
||||||
|
+ if (s->flags & TD_RDONLY) {
|
||||||
|
+ fprintf(stderr, "Snapshots not supported for "
|
||||||
|
+ "image format of a read-only image\n");
|
||||||
|
+ } else {
|
||||||
|
+ fprintf(stderr, "Snapshots not supported "
|
||||||
|
+ "for this image format");
|
||||||
|
+ ret = -1;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ case -ENOENT:
|
||||||
|
+ fprintf(stderr, "No such snapshot");
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
+ fprintf(stderr, "Could not load snapshot");
|
+ fprintf(stderr, "Could not load snapshot");
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+#endif
|
+#endif
|
||||||
|
|
||||||
@ -79,7 +100,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
static int pasprintf(char **buf, const char *fmt, ...)
|
static int pasprintf(char **buf, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -373,8 +375,17 @@ void xenstore_parse_domain_config(int hv
|
@@ -363,8 +365,33 @@ void xenstore_parse_domain_config(int hv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pstrcpy(bs->filename, sizeof(bs->filename), params);
|
pstrcpy(bs->filename, sizeof(bs->filename), params);
|
||||||
@ -89,16 +110,32 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
+ } else {
|
+ } else {
|
||||||
+ char* snapshot = get_snapshot_name(atoi(e[i]));
|
+ char* snapshot = get_snapshot_name(atoi(e[i]));
|
||||||
+ if (snapshot) {
|
+ if (snapshot) {
|
||||||
+ // TODO Error handling
|
|
||||||
+ fprintf(stderr, "Using snapshot %s\n", snapshot);
|
+ fprintf(stderr, "Using snapshot %s\n", snapshot);
|
||||||
+ if (bdrv_snapshot_goto(bs, snapshot) < 0)
|
+ ret = bdrv_snapshot_goto(bs, snapshot);
|
||||||
+ fprintf(stderr, "Could not load snapshot");
|
+ switch (ret) {
|
||||||
|
+ case 0:
|
||||||
|
+ /* Success */
|
||||||
|
+ break;
|
||||||
|
+ case -ENOTSUP:
|
||||||
|
+ /* Don't abort here (could be read-only ISO) */
|
||||||
|
+ fprintf(stderr, "Snapshots are not supported for "
|
||||||
|
+ "this image file format\n");
|
||||||
|
+ break;
|
||||||
|
+ case -ENOENT:
|
||||||
|
+ fprintf(stderr, "No such snapshot, skipping this "
|
||||||
|
+ "image file\n");
|
||||||
|
+ continue;
|
||||||
|
+ default:
|
||||||
|
+ fprintf(stderr, "Could not load snapshot, skipping"
|
||||||
|
+ " this image file\n");
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
}
|
}
|
||||||
|
/* if cdrom pyhsical put a watch on media-present */
|
||||||
drives_table[nb_drives].bdrv = bs;
|
if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) {
|
||||||
@@ -471,6 +482,23 @@ void xenstore_parse_domain_config(int hv
|
@@ -474,6 +485,23 @@ void xenstore_parse_domain_config(int hv
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,15 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/i386-dm/helper2.c
|
|||||||
CPUX86State *cpu_x86_init(const char *cpu_model)
|
CPUX86State *cpu_x86_init(const char *cpu_model)
|
||||||
{
|
{
|
||||||
CPUX86State *env;
|
CPUX86State *env;
|
||||||
@@ -574,9 +577,24 @@ int main_loop(void)
|
@@ -547,6 +550,7 @@ int main_loop(void)
|
||||||
|
int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle);
|
||||||
|
char *qemu_file;
|
||||||
|
fd_set fds;
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
main_loop_prepare();
|
||||||
|
|
||||||
|
@@ -574,11 +578,43 @@ int main_loop(void)
|
||||||
main_loop_wait(1); /* For the select() on events */
|
main_loop_wait(1); /* For the select() on events */
|
||||||
|
|
||||||
/* Save the device state */
|
/* Save the device state */
|
||||||
@ -129,22 +137,42 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/i386-dm/helper2.c
|
|||||||
+ asprintf(&qemu_file, "/var/lib/xen/qemu-save.%d", domid);
|
+ asprintf(&qemu_file, "/var/lib/xen/qemu-save.%d", domid);
|
||||||
+ do_savevm(qemu_file);
|
+ do_savevm(qemu_file);
|
||||||
+ free(qemu_file);
|
+ free(qemu_file);
|
||||||
|
+ xenstore_record_dm_state("paused");
|
||||||
+ break;
|
+ break;
|
||||||
+
|
+
|
||||||
+ case SUSPEND_SNAPSHOT:
|
+ case SUSPEND_SNAPSHOT:
|
||||||
+ // TODO Error reporting
|
|
||||||
+ if (snapshot_name != NULL) {
|
+ if (snapshot_name != NULL) {
|
||||||
+ save_disk_snapshots(snapshot_name);
|
+ ret = save_disk_snapshots(snapshot_name);
|
||||||
+ free(snapshot_name);
|
+ free(snapshot_name);
|
||||||
+ snapshot_name = NULL;
|
+ snapshot_name = NULL;
|
||||||
|
+
|
||||||
|
+ switch (ret) {
|
||||||
|
+ case 0:
|
||||||
|
+ xenstore_record_dm_state("paused");
|
||||||
|
+ break;
|
||||||
|
+ case -ENOTSUP:
|
||||||
|
+ xenstore_record_dm_error("Snapshots not supported on all"
|
||||||
|
+ " attached read-write disks");
|
||||||
|
+ break;
|
||||||
|
+ case -ENOENT:
|
||||||
|
+ xenstore_record_dm_error("A snapshot with the same name"
|
||||||
|
+ " already exists");
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ xenstore_record_dm_error("An error occurred while saving"
|
||||||
|
+ " the snapshot");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
+ } else {
|
+ } else {
|
||||||
+ fprintf(logfile, "No snapshot name given\n");
|
+ xenstore_record_dm_error("No snapshot name given");
|
||||||
+ }
|
+ }
|
||||||
+ break;
|
+ break;
|
||||||
+ }
|
+ }
|
||||||
|
|
||||||
xenstore_record_dm_state("paused");
|
- xenstore_record_dm_state("paused");
|
||||||
|
|
||||||
|
/* Wait to be allowed to continue */
|
||||||
|
while (xen_pause_requested) {
|
||||||
Index: xen-3.3.1-testing/tools/ioemu-remote/qemu-xen.h
|
Index: xen-3.3.1-testing/tools/ioemu-remote/qemu-xen.h
|
||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/tools/ioemu-remote/qemu-xen.h
|
--- xen-3.3.1-testing.orig/tools/ioemu-remote/qemu-xen.h
|
||||||
@ -165,6 +193,14 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/qemu-xen.h
|
|||||||
/* helper2.c */
|
/* helper2.c */
|
||||||
extern long time_offset;
|
extern long time_offset;
|
||||||
void timeoffset_get(void);
|
void timeoffset_get(void);
|
||||||
|
@@ -43,6 +52,7 @@ int xenstore_fd(void);
|
||||||
|
void xenstore_process_event(void *opaque);
|
||||||
|
void xenstore_record_dm(char *subpath, char *state);
|
||||||
|
void xenstore_record_dm_state(char *state);
|
||||||
|
+void xenstore_record_dm_error(char *errmsg);
|
||||||
|
void xenstore_check_new_media_present(int timeout);
|
||||||
|
void xenstore_write_vncport(int vnc_display);
|
||||||
|
void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen);
|
||||||
Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xenstore.c
|
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xenstore.c
|
||||||
@ -177,7 +213,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
|
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
@@ -598,6 +599,7 @@ static void xenstore_process_dm_command_
|
@@ -601,6 +602,7 @@ static void xenstore_process_dm_command_
|
||||||
{
|
{
|
||||||
char *path = NULL, *command = NULL, *par = NULL;
|
char *path = NULL, *command = NULL, *par = NULL;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
@ -185,7 +221,7 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
|
|
||||||
if (pasprintf(&path,
|
if (pasprintf(&path,
|
||||||
"/local/domain/0/device-model/%u/command", domid) == -1) {
|
"/local/domain/0/device-model/%u/command", domid) == -1) {
|
||||||
@@ -610,7 +612,18 @@ static void xenstore_process_dm_command_
|
@@ -613,7 +615,18 @@ static void xenstore_process_dm_command_
|
||||||
|
|
||||||
if (!strncmp(command, "save", len)) {
|
if (!strncmp(command, "save", len)) {
|
||||||
fprintf(logfile, "dm-command: pause and save state\n");
|
fprintf(logfile, "dm-command: pause and save state\n");
|
||||||
@ -205,3 +241,17 @@ Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
|
|||||||
} else if (!strncmp(command, "continue", len)) {
|
} else if (!strncmp(command, "continue", len)) {
|
||||||
fprintf(logfile, "dm-command: continue after state save\n");
|
fprintf(logfile, "dm-command: continue after state save\n");
|
||||||
xen_pause_requested = 0;
|
xen_pause_requested = 0;
|
||||||
|
@@ -677,6 +690,13 @@ void xenstore_record_dm_state(char *stat
|
||||||
|
xenstore_record_dm("state", state);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void xenstore_record_dm_error(char *errmsg)
|
||||||
|
+{
|
||||||
|
+ fprintf(logfile, "%s\n", errmsg);
|
||||||
|
+ xenstore_record_dm("error", errmsg);
|
||||||
|
+ xenstore_record_dm_state("error");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void xenstore_process_media_change_event(char **vec)
|
||||||
|
{
|
||||||
|
char *media_present = NULL;
|
||||||
|
@ -2,7 +2,20 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/image.py
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/tools/python/xen/xend/image.py
|
--- xen-3.3.1-testing.orig/tools/python/xen/xend/image.py
|
||||||
+++ xen-3.3.1-testing/tools/python/xen/xend/image.py
|
+++ xen-3.3.1-testing/tools/python/xen/xend/image.py
|
||||||
@@ -476,6 +476,10 @@ class ImageHandler:
|
@@ -447,6 +447,12 @@ class ImageHandler:
|
||||||
|
while state != ret:
|
||||||
|
state = xstransact.Read("/local/domain/0/device-model/%i/state"
|
||||||
|
% self.vm.getDomid())
|
||||||
|
+ if state == 'error':
|
||||||
|
+ msg = ("The device model returned an error: %s"
|
||||||
|
+ % xstransact.Read("/local/domain/0/device-model/%i/error"
|
||||||
|
+ % self.vm.getDomid()))
|
||||||
|
+ raise VmError(msg)
|
||||||
|
+
|
||||||
|
time.sleep(0.1)
|
||||||
|
count += 1
|
||||||
|
if count > 100:
|
||||||
|
@@ -476,6 +482,10 @@ class ImageHandler:
|
||||||
# but this can easily lead to very rapid restart loops against
|
# but this can easily lead to very rapid restart loops against
|
||||||
# which we currently have no protection
|
# which we currently have no protection
|
||||||
|
|
||||||
@ -164,8 +177,6 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/XendCheckpoint.py
|
|||||||
+ log.info("Domain %d suspended.", dominfo.getDomid())
|
+ log.info("Domain %d suspended.", dominfo.getDomid())
|
||||||
+ dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
|
+ dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
|
||||||
+ domain_name)
|
+ domain_name)
|
||||||
+ if name:
|
|
||||||
+ dominfo.image.snapshotDeviceModel(name)
|
|
||||||
+ if hvm:
|
+ if hvm:
|
||||||
+ dominfo.image.saveDeviceModel()
|
+ dominfo.image.saveDeviceModel()
|
||||||
+
|
+
|
||||||
@ -192,6 +203,8 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/XendCheckpoint.py
|
|||||||
+ else:
|
+ else:
|
||||||
+ dominfo.shutdown('suspend')
|
+ dominfo.shutdown('suspend')
|
||||||
+ dominfo.waitForShutdown()
|
+ dominfo.waitForShutdown()
|
||||||
|
+
|
||||||
|
+ if name:
|
||||||
+ dominfo.image.snapshotDeviceModel(name)
|
+ dominfo.image.snapshotDeviceModel(name)
|
||||||
+
|
+
|
||||||
|
|
||||||
@ -315,7 +328,7 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/XendDomain.py
|
|||||||
|
|
||||||
xc = xen.lowlevel.xc.xc()
|
xc = xen.lowlevel.xc.xc()
|
||||||
xoptions = XendOptions.instance()
|
xoptions = XendOptions.instance()
|
||||||
@@ -1400,6 +1401,164 @@ class XendDomain:
|
@@ -1400,6 +1401,181 @@ class XendDomain:
|
||||||
raise XendError("can't write guest state file %s: %s" %
|
raise XendError("can't write guest state file %s: %s" %
|
||||||
(dst, ex[1]))
|
(dst, ex[1]))
|
||||||
|
|
||||||
@ -348,6 +361,22 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/XendDomain.py
|
|||||||
+ raise XendError("Domain is not managed by Xend lifecycle " +
|
+ raise XendError("Domain is not managed by Xend lifecycle " +
|
||||||
+ "support.")
|
+ "support.")
|
||||||
+
|
+
|
||||||
|
+ # Check if all images support snapshots
|
||||||
|
+ for dev_type, dev_info in dominfo.info.all_devices_sxpr():
|
||||||
|
+ mode = sxp.child_value(dev_info, 'mode')
|
||||||
|
+ if mode == 'r':
|
||||||
|
+ continue;
|
||||||
|
+ if dev_type == 'vbd':
|
||||||
|
+ raise XendError("All writable images need to use the " +
|
||||||
|
+ "tap:qcow2 protocol for snapshot support")
|
||||||
|
+ if dev_type == 'tap':
|
||||||
|
+ # Fetch the protocol name from tap:xyz:filename
|
||||||
|
+ type = sxp.child_value(dev_info, 'uname')
|
||||||
|
+ type = type.split(':')[1]
|
||||||
|
+ if type != 'qcow2':
|
||||||
|
+ raise XendError("All writable images need to use the " +
|
||||||
|
+ "tap:qcow2 protocol for snapshot support")
|
||||||
|
+
|
||||||
+ snap_path = os.path.join(xoptions.get_xend_domains_path(),
|
+ snap_path = os.path.join(xoptions.get_xend_domains_path(),
|
||||||
+ dominfo.get_uuid(), "snapshots")
|
+ dominfo.get_uuid(), "snapshots")
|
||||||
+ mkdir.parents(snap_path, stat.S_IRWXU)
|
+ mkdir.parents(snap_path, stat.S_IRWXU)
|
||||||
@ -363,6 +392,7 @@ Index: xen-3.3.1-testing/tools/python/xen/xend/XendDomain.py
|
|||||||
+ True, name=name, diskonly=diskonly)
|
+ True, name=name, diskonly=diskonly)
|
||||||
+ except Exception, e:
|
+ except Exception, e:
|
||||||
+ os.close(fd)
|
+ os.close(fd)
|
||||||
|
+ os.unlink(snap_file)
|
||||||
+ raise e
|
+ raise e
|
||||||
+ os.close(fd)
|
+ os.close(fd)
|
||||||
+ except OSError, ex:
|
+ except OSError, ex:
|
||||||
|
9
udev-rules.patch
Normal file
9
udev-rules.patch
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Index: xen-3.3.1-testing/tools/examples/xen-backend.rules
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/tools/examples/xen-backend.rules
|
||||||
|
+++ xen-3.3.1-testing/tools/examples/xen-backend.rules
|
||||||
|
@@ -7,3 +7,4 @@ SUBSYSTEM=="xen-backend", KERNEL=="vscsi
|
||||||
|
SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
|
||||||
|
KERNEL=="evtchn", NAME="xen/%k"
|
||||||
|
KERNEL=="blktap[0-9]*", NAME="xen/%k"
|
||||||
|
+KERNELS=="xen", KERNEL=="xvd*", SUBSYSTEM=="block", OPTIONS+="last_rule"
|
@ -1,157 +0,0 @@
|
|||||||
Equivalent of -unstable c/s 18720, 18731, and 18735.
|
|
||||||
|
|
||||||
--- a/xen/arch/x86/domain.c
|
|
||||||
+++ b/xen/arch/x86/domain.c
|
|
||||||
@@ -1687,6 +1687,8 @@ static int relinquish_memory(
|
|
||||||
{
|
|
||||||
if ( free_page_type(page, x, 0) != 0 )
|
|
||||||
BUG();
|
|
||||||
+ if ( x & PGT_partial )
|
|
||||||
+ page->u.inuse.type_info--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--- a/xen/arch/x86/mm.c
|
|
||||||
+++ b/xen/arch/x86/mm.c
|
|
||||||
@@ -1343,7 +1343,7 @@ static void free_l1_table(struct page_in
|
|
||||||
|
|
||||||
static int free_l2_table(struct page_info *page, int preemptible)
|
|
||||||
{
|
|
||||||
-#ifdef CONFIG_COMPAT
|
|
||||||
+#if defined(CONFIG_COMPAT) || defined(DOMAIN_DESTRUCT_AVOID_RECURSION)
|
|
||||||
struct domain *d = page_get_owner(page);
|
|
||||||
#endif
|
|
||||||
unsigned long pfn = page_to_mfn(page);
|
|
||||||
@@ -1351,6 +1351,11 @@ static int free_l2_table(struct page_inf
|
|
||||||
unsigned int i = page->nr_validated_ptes - 1;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
+#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION
|
|
||||||
+ if ( d->arch.relmem == RELMEM_l3 )
|
|
||||||
+ return 0;
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
pl2e = map_domain_page(pfn);
|
|
||||||
|
|
||||||
ASSERT(page->nr_validated_ptes);
|
|
||||||
@@ -1381,7 +1386,7 @@ static int free_l3_table(struct page_inf
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION
|
|
||||||
- if ( d->arch.relmem == RELMEM_l3 )
|
|
||||||
+ if ( d->arch.relmem == RELMEM_l4 )
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1424,11 +1429,6 @@ static int free_l4_table(struct page_inf
|
|
||||||
unsigned int i = page->nr_validated_ptes - !page->partial_pte;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
-#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION
|
|
||||||
- if ( d->arch.relmem == RELMEM_l4 )
|
|
||||||
- return 0;
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
do {
|
|
||||||
if ( is_guest_l4_slot(d, i) )
|
|
||||||
rc = put_page_from_l4e(pl4e[i], pfn, preemptible);
|
|
||||||
@@ -1940,7 +1940,6 @@ int free_page_type(struct page_info *pag
|
|
||||||
{
|
|
||||||
struct domain *owner = page_get_owner(page);
|
|
||||||
unsigned long gmfn;
|
|
||||||
- int rc;
|
|
||||||
|
|
||||||
if ( likely(owner != NULL) )
|
|
||||||
{
|
|
||||||
@@ -1973,34 +1972,39 @@ int free_page_type(struct page_info *pag
|
|
||||||
page->nr_validated_ptes = 1U << PAGETABLE_ORDER;
|
|
||||||
page->partial_pte = 0;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
switch ( type & PGT_type_mask )
|
|
||||||
{
|
|
||||||
case PGT_l1_page_table:
|
|
||||||
free_l1_table(page);
|
|
||||||
- rc = 0;
|
|
||||||
- break;
|
|
||||||
+ return 0;
|
|
||||||
case PGT_l2_page_table:
|
|
||||||
- rc = free_l2_table(page, preemptible);
|
|
||||||
- break;
|
|
||||||
+ return free_l2_table(page, preemptible);
|
|
||||||
case PGT_l3_page_table:
|
|
||||||
#if CONFIG_PAGING_LEVELS == 3
|
|
||||||
if ( !(type & PGT_partial) )
|
|
||||||
page->nr_validated_ptes = L3_PAGETABLE_ENTRIES;
|
|
||||||
#endif
|
|
||||||
- rc = free_l3_table(page, preemptible);
|
|
||||||
- break;
|
|
||||||
+ return free_l3_table(page, preemptible);
|
|
||||||
case PGT_l4_page_table:
|
|
||||||
- rc = free_l4_table(page, preemptible);
|
|
||||||
- break;
|
|
||||||
- default:
|
|
||||||
- MEM_LOG("type %lx pfn %lx\n", type, page_to_mfn(page));
|
|
||||||
- rc = -EINVAL;
|
|
||||||
- BUG();
|
|
||||||
+ return free_l4_table(page, preemptible);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ MEM_LOG("type %lx pfn %lx\n", type, page_to_mfn(page));
|
|
||||||
+ BUG();
|
|
||||||
+ return -EINVAL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int __put_page_type_final(struct page_info *page, unsigned long type,
|
|
||||||
+ int preemptible)
|
|
||||||
+{
|
|
||||||
+ int rc = free_page_type(page, type, preemptible);
|
|
||||||
+
|
|
||||||
/* No need for atomic update of type_info here: noone else updates it. */
|
|
||||||
- if ( rc == 0 )
|
|
||||||
+ switch ( rc )
|
|
||||||
{
|
|
||||||
+ case 0:
|
|
||||||
/*
|
|
||||||
* Record TLB information for flush later. We do not stamp page tables
|
|
||||||
* when running in shadow mode:
|
|
||||||
@@ -2013,9 +2017,8 @@ int free_page_type(struct page_info *pag
|
|
||||||
page->tlbflush_timestamp = tlbflush_current_time();
|
|
||||||
wmb();
|
|
||||||
page->u.inuse.type_info--;
|
|
||||||
- }
|
|
||||||
- else if ( rc == -EINTR )
|
|
||||||
- {
|
|
||||||
+ break;
|
|
||||||
+ case -EINTR:
|
|
||||||
ASSERT(!(page->u.inuse.type_info &
|
|
||||||
(PGT_count_mask|PGT_validated|PGT_partial)));
|
|
||||||
if ( !(shadow_mode_enabled(page_get_owner(page)) &&
|
|
||||||
@@ -2023,12 +2026,13 @@ int free_page_type(struct page_info *pag
|
|
||||||
page->tlbflush_timestamp = tlbflush_current_time();
|
|
||||||
wmb();
|
|
||||||
page->u.inuse.type_info |= PGT_validated;
|
|
||||||
- }
|
|
||||||
- else
|
|
||||||
- {
|
|
||||||
- BUG_ON(rc != -EAGAIN);
|
|
||||||
+ break;
|
|
||||||
+ case -EAGAIN:
|
|
||||||
wmb();
|
|
||||||
page->u.inuse.type_info |= PGT_partial;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ BUG();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
@@ -2062,7 +2066,7 @@ static int __put_page_type(struct page_i
|
|
||||||
x, nx)) != x) )
|
|
||||||
continue;
|
|
||||||
/* We cleared the 'valid bit' so we do the clean up. */
|
|
||||||
- return free_page_type(page, x, preemptible);
|
|
||||||
+ return __put_page_type_final(page, x, preemptible);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
@ -69,7 +69,7 @@ Index: xen-3.3.1-testing/xen/arch/x86/x86_64/mm.c
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/xen/arch/x86/x86_64/mm.c
|
--- xen-3.3.1-testing.orig/xen/arch/x86/x86_64/mm.c
|
||||||
+++ xen-3.3.1-testing/xen/arch/x86/x86_64/mm.c
|
+++ xen-3.3.1-testing/xen/arch/x86/x86_64/mm.c
|
||||||
@@ -33,6 +33,7 @@
|
@@ -32,6 +32,7 @@
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <public/memory.h>
|
#include <public/memory.h>
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ Index: xen-3.3.1-testing/xen/arch/x86/x86_64/mm.c
|
|||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
unsigned int m2p_compat_vstart = __HYPERVISOR_COMPAT_VIRT_START;
|
unsigned int m2p_compat_vstart = __HYPERVISOR_COMPAT_VIRT_START;
|
||||||
#endif
|
#endif
|
||||||
@@ -152,6 +153,8 @@ void __init paging_init(void)
|
@@ -151,6 +152,8 @@ void __init paging_init(void)
|
||||||
l2_ro_mpt++;
|
l2_ro_mpt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ Index: xen-3.3.1-testing/xen/include/asm-x86/mm.h
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/xen/include/asm-x86/mm.h
|
--- xen-3.3.1-testing.orig/xen/include/asm-x86/mm.h
|
||||||
+++ xen-3.3.1-testing/xen/include/asm-x86/mm.h
|
+++ xen-3.3.1-testing/xen/include/asm-x86/mm.h
|
||||||
@@ -307,6 +307,7 @@ TYPE_SAFE(unsigned long,mfn);
|
@@ -331,6 +331,7 @@ TYPE_SAFE(unsigned long,mfn);
|
||||||
#define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
|
#define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
|
||||||
#define INVALID_M2P_ENTRY (~0UL)
|
#define INVALID_M2P_ENTRY (~0UL)
|
||||||
#define VALID_M2P(_e) (!((_e) & (1UL<<(BITS_PER_LONG-1))))
|
#define VALID_M2P(_e) (!((_e) & (1UL<<(BITS_PER_LONG-1))))
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:3ce2034661e3f994e29c466829910cfd89dba75ba71c4235d66a7940cf3956f5
|
oid sha256:e32c923438b84304bb99311df54aa02eb057b9dbcce2770f3b0310975b3ab066
|
||||||
size 22695411
|
size 22694395
|
||||||
|
@ -31,7 +31,7 @@ Index: xen-3.3.1-testing/xen/arch/x86/x86_32/mm.c
|
|||||||
+ lowmem_emergency_pool_pages = 4000;
|
+ lowmem_emergency_pool_pages = 4000;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long clone_idle_pagetable(struct vcpu *v)
|
void __init zap_low_mappings(l2_pgentry_t *dom0_l2)
|
||||||
Index: xen-3.3.1-testing/xen/common/page_alloc.c
|
Index: xen-3.3.1-testing/xen/common/page_alloc.c
|
||||||
===================================================================
|
===================================================================
|
||||||
--- xen-3.3.1-testing.orig/xen/common/page_alloc.c
|
--- xen-3.3.1-testing.orig/xen/common/page_alloc.c
|
||||||
|
30
xen-x86-emulate-movnti.patch
Normal file
30
xen-x86-emulate-movnti.patch
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Index: xen-3.3.1-testing/xen/arch/x86/x86_emulate/x86_emulate.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/x86_emulate/x86_emulate.c
|
||||||
|
+++ xen-3.3.1-testing/xen/arch/x86/x86_emulate/x86_emulate.c
|
||||||
|
@@ -3657,6 +3657,12 @@ x86_emulate(
|
||||||
|
case 8: *src.reg = dst.val; break;
|
||||||
|
}
|
||||||
|
goto add;
|
||||||
|
+
|
||||||
|
+ case 0xc3: /* movnti */
|
||||||
|
+ /* Ignore the non-temporal hint for now. */
|
||||||
|
+ generate_exception_if(dst.bytes <= 2, EXC_UD, -1);
|
||||||
|
+ dst.val = src.val;
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
goto writeback;
|
||||||
|
|
||||||
|
@@ -3923,12 +3929,6 @@ x86_emulate(
|
||||||
|
src.val = x86_seg_gs;
|
||||||
|
goto pop_seg;
|
||||||
|
|
||||||
|
- case 0xc3: /* movnti */
|
||||||
|
- /* Ignore the non-temporal hint for now. */
|
||||||
|
- generate_exception_if(dst.bytes <= 2, EXC_UD, -1);
|
||||||
|
- dst.val = src.val;
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
case 0xc7: /* Grp9 (cmpxchg8b/cmpxchg16b) */ {
|
||||||
|
unsigned long old[2], exp[2], new[2];
|
||||||
|
unsigned int i;
|
48
xen.changes
48
xen.changes
@ -1,3 +1,51 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Nov 20 19:57:19 CET 2008 - kwolf@suse.de
|
||||||
|
|
||||||
|
- bnc#444731 - Fix data corruption bug (caused by broken x86
|
||||||
|
emulation for movnti instruction)
|
||||||
|
|
||||||
|
xen-x86-emulate-movnti.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Nov 19 20:14:54 CET 2008 - kwolf@suse.de
|
||||||
|
|
||||||
|
- Report device model errors during the creation of snapshots
|
||||||
|
to xend instead of failing silently
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Nov 19 16:27:01 CET 2008 - kwolf@suse.de
|
||||||
|
|
||||||
|
- bnc#445659 - ioemu: Workaround for VNC client initialization
|
||||||
|
race with xenfb changing the resolution (caused VNC connection
|
||||||
|
to be closed, vm-install recognized this as failed installation)
|
||||||
|
|
||||||
|
ioemu-vnc-resize.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Nov 18 08:11:34 MST 2008 - carnold@novell.com
|
||||||
|
|
||||||
|
- bnc#444203 - With EPT mode4, HVM S3 causes Xen HV crash.
|
||||||
|
18783-hvm-vcpu-reset-state-fix.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Nov 17 09:14:12 MST 2008 - carnold@novell.com
|
||||||
|
|
||||||
|
- bnc#444731 - Blackscreen instead of second stage during
|
||||||
|
installation
|
||||||
|
18766-realmode-stack-size-fix.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Nov 13 09:22:54 MST 2008 - carnold@novell.com
|
||||||
|
|
||||||
|
- bnc#429739 - Network failure with bnx2 when booted to XEN
|
||||||
|
18778-msi-irq-fix.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Nov 12 19:07:11 CET 2008 - kwolf@suse.de
|
||||||
|
|
||||||
|
- bnc#444197 - Add udev rule to fix domUloader race with
|
||||||
|
automounter (udev-rules.patch)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Sun Nov 9 23:54:34 CET 2008 - ro@suse.de
|
Sun Nov 9 23:54:34 CET 2008 - ro@suse.de
|
||||||
|
|
||||||
|
78
xen.spec
78
xen.spec
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# spec file for package xen (Version 3.3.1_18486_01)
|
# spec file for package xen (Version 3.3.1_18494_02)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
# Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
#
|
#
|
||||||
@ -22,7 +22,7 @@ Name: xen
|
|||||||
ExclusiveArch: %ix86 x86_64
|
ExclusiveArch: %ix86 x86_64
|
||||||
%define xvers 3.3
|
%define xvers 3.3
|
||||||
%define xvermaj 3
|
%define xvermaj 3
|
||||||
%define changeset 18486
|
%define changeset 18494
|
||||||
%define xen_build_dir xen-3.3.1-testing
|
%define xen_build_dir xen-3.3.1-testing
|
||||||
%define with_kmp 0
|
%define with_kmp 0
|
||||||
BuildRequires: LibVNCServer-devel SDL-devel automake bin86 curl-devel dev86 graphviz latex2html libjpeg-devel libxml2-devel ncurses-devel openssl openssl-devel pciutils-devel python-devel transfig
|
BuildRequires: LibVNCServer-devel SDL-devel automake bin86 curl-devel dev86 graphviz latex2html libjpeg-devel libxml2-devel ncurses-devel openssl openssl-devel pciutils-devel python-devel transfig
|
||||||
@ -37,8 +37,8 @@ BuildRequires: glibc-32bit glibc-devel-32bit
|
|||||||
%if %{?with_kmp}0
|
%if %{?with_kmp}0
|
||||||
BuildRequires: kernel-source kernel-syms module-init-tools xorg-x11
|
BuildRequires: kernel-source kernel-syms module-init-tools xorg-x11
|
||||||
%endif
|
%endif
|
||||||
Version: 3.3.1_18486_01
|
Version: 3.3.1_18494_02
|
||||||
Release: 2
|
Release: 1
|
||||||
License: GPL v2 only
|
License: GPL v2 only
|
||||||
Group: System/Kernel
|
Group: System/Kernel
|
||||||
AutoReqProv: on
|
AutoReqProv: on
|
||||||
@ -99,7 +99,20 @@ Patch29: 18637-vmx-set-dr7.patch
|
|||||||
Patch30: 18654-xend-vcpus.patch
|
Patch30: 18654-xend-vcpus.patch
|
||||||
Patch31: 18656-vtd-alloc-checks.patch
|
Patch31: 18656-vtd-alloc-checks.patch
|
||||||
Patch32: 18661-recursive-spinlocks.patch
|
Patch32: 18661-recursive-spinlocks.patch
|
||||||
Patch33: 18745-xend-ioport-irq.patch
|
Patch33: 18720-x86-dom-cleanup.patch
|
||||||
|
Patch34: 18722-x86-fixmap-reserved.patch
|
||||||
|
Patch35: 18723-unmap-dom-page-const.patch
|
||||||
|
Patch36: 18724-i386-highmem-assist.patch
|
||||||
|
Patch37: 18731-x86-dom-cleanup.patch
|
||||||
|
Patch38: 18735-x86-dom-cleanup.patch
|
||||||
|
Patch39: 18741-x86-dom-cleanup-no-hack.patch
|
||||||
|
Patch40: 18742-x86-partial-page-ref.patch
|
||||||
|
Patch41: 18745-xend-ioport-irq.patch
|
||||||
|
Patch42: 18747-x86-partial-page-ref.patch
|
||||||
|
Patch43: 18771-reduce-GDT-switching.patch
|
||||||
|
Patch44: 18778-msi-irq-fix.patch
|
||||||
|
# Will be fixed in 3.3-testing soon
|
||||||
|
Patch90: xen-x86-emulate-movnti.patch
|
||||||
# Our patches
|
# Our patches
|
||||||
Patch100: xen-config.diff
|
Patch100: xen-config.diff
|
||||||
Patch101: xend-config.diff
|
Patch101: xend-config.diff
|
||||||
@ -147,6 +160,8 @@ Patch159: tools-gdbserver-build.diff
|
|||||||
Patch160: network-route.patch
|
Patch160: network-route.patch
|
||||||
# Needs to go upstream sometime, when python 2.6 is widespread
|
# Needs to go upstream sometime, when python 2.6 is widespread
|
||||||
Patch161: python2.6-fixes.patch
|
Patch161: python2.6-fixes.patch
|
||||||
|
Patch162: udev-rules.patch
|
||||||
|
Patch163: ioemu-vnc-resize.patch
|
||||||
# Patches for snapshot support
|
# Patches for snapshot support
|
||||||
Patch170: qemu-img-snapshot.patch
|
Patch170: qemu-img-snapshot.patch
|
||||||
Patch171: ioemu-blktap-fix-open.patch
|
Patch171: ioemu-blktap-fix-open.patch
|
||||||
@ -176,12 +191,8 @@ Patch350: pv-driver-build.patch
|
|||||||
Patch351: xen-ioemu-hvm-pv-support.diff
|
Patch351: xen-ioemu-hvm-pv-support.diff
|
||||||
Patch352: pvdrv_emulation_control.patch
|
Patch352: pvdrv_emulation_control.patch
|
||||||
Patch353: blktap-pv-cdrom.patch
|
Patch353: blktap-pv-cdrom.patch
|
||||||
Patch354: i386-highmem-assist.patch
|
Patch354: x86-cpufreq-report.patch
|
||||||
Patch355: x86-cpufreq-report.patch
|
Patch355: dom-print.patch
|
||||||
Patch356: x86-dom-cleanup.patch
|
|
||||||
Patch357: x86-dom-cleanup-no-hack.patch
|
|
||||||
Patch358: x86-partial-page-ref.patch
|
|
||||||
Patch359: dom-print.patch
|
|
||||||
# novell_shim patches
|
# novell_shim patches
|
||||||
Patch400: hv_tools.patch
|
Patch400: hv_tools.patch
|
||||||
Patch401: hv_xen_base.patch
|
Patch401: hv_xen_base.patch
|
||||||
@ -251,7 +262,7 @@ Authors:
|
|||||||
License: GPL v2 or later
|
License: GPL v2 or later
|
||||||
Summary: Xen Virtualization: Libraries
|
Summary: Xen Virtualization: Libraries
|
||||||
Group: System/Kernel
|
Group: System/Kernel
|
||||||
Requires: xen = %{version}
|
#Requires: xen = %{version}
|
||||||
AutoReqProv: on
|
AutoReqProv: on
|
||||||
|
|
||||||
%description libs
|
%description libs
|
||||||
@ -551,6 +562,18 @@ Authors:
|
|||||||
%patch31 -p1
|
%patch31 -p1
|
||||||
%patch32 -p1
|
%patch32 -p1
|
||||||
%patch33 -p1
|
%patch33 -p1
|
||||||
|
%patch34 -p1
|
||||||
|
%patch35 -p1
|
||||||
|
%patch36 -p1
|
||||||
|
%patch37 -p1
|
||||||
|
%patch38 -p1
|
||||||
|
%patch39 -p1
|
||||||
|
%patch40 -p1
|
||||||
|
%patch41 -p1
|
||||||
|
%patch42 -p1
|
||||||
|
%patch43 -p1
|
||||||
|
%patch44 -p1
|
||||||
|
%patch90 -p1
|
||||||
%patch100 -p1
|
%patch100 -p1
|
||||||
%patch101 -p1
|
%patch101 -p1
|
||||||
%patch102 -p1
|
%patch102 -p1
|
||||||
@ -596,6 +619,8 @@ Authors:
|
|||||||
%patch159 -p1
|
%patch159 -p1
|
||||||
%patch160 -p1
|
%patch160 -p1
|
||||||
%patch161 -p1
|
%patch161 -p1
|
||||||
|
%patch162 -p1
|
||||||
|
%patch163 -p1
|
||||||
%patch170 -p1
|
%patch170 -p1
|
||||||
%patch171 -p1
|
%patch171 -p1
|
||||||
%patch172 -p1
|
%patch172 -p1
|
||||||
@ -623,10 +648,6 @@ Authors:
|
|||||||
%patch353 -p1
|
%patch353 -p1
|
||||||
%patch354 -p1
|
%patch354 -p1
|
||||||
%patch355 -p1
|
%patch355 -p1
|
||||||
%patch356 -p1
|
|
||||||
%patch357 -p1
|
|
||||||
%patch358 -p1
|
|
||||||
%patch359 -p1
|
|
||||||
# Don't use shim for now
|
# Don't use shim for now
|
||||||
%ifarch x86_64
|
%ifarch x86_64
|
||||||
%patch400 -p1
|
%patch400 -p1
|
||||||
@ -976,6 +997,31 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/xen/bin/qemu-dm.debug
|
|||||||
/sbin/ldconfig
|
/sbin/ldconfig
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Nov 20 2008 kwolf@suse.de
|
||||||
|
- bnc#444731 - Fix data corruption bug (caused by broken x86
|
||||||
|
emulation for movnti instruction)
|
||||||
|
xen-x86-emulate-movnti.patch
|
||||||
|
* Wed Nov 19 2008 kwolf@suse.de
|
||||||
|
- Report device model errors during the creation of snapshots
|
||||||
|
to xend instead of failing silently
|
||||||
|
* Wed Nov 19 2008 kwolf@suse.de
|
||||||
|
- bnc#445659 - ioemu: Workaround for VNC client initialization
|
||||||
|
race with xenfb changing the resolution (caused VNC connection
|
||||||
|
to be closed, vm-install recognized this as failed installation)
|
||||||
|
ioemu-vnc-resize.patch
|
||||||
|
* Tue Nov 18 2008 carnold@novell.com
|
||||||
|
- bnc#444203 - With EPT mode4, HVM S3 causes Xen HV crash.
|
||||||
|
18783-hvm-vcpu-reset-state-fix.patch
|
||||||
|
* Mon Nov 17 2008 carnold@novell.com
|
||||||
|
- bnc#444731 - Blackscreen instead of second stage during
|
||||||
|
installation
|
||||||
|
18766-realmode-stack-size-fix.patch
|
||||||
|
* Thu Nov 13 2008 carnold@novell.com
|
||||||
|
- bnc#429739 - Network failure with bnx2 when booted to XEN
|
||||||
|
18778-msi-irq-fix.patch
|
||||||
|
* Wed Nov 12 2008 kwolf@suse.de
|
||||||
|
- bnc#444197 - Add udev rule to fix domUloader race with
|
||||||
|
automounter (udev-rules.patch)
|
||||||
* Sun Nov 09 2008 ro@suse.de
|
* Sun Nov 09 2008 ro@suse.de
|
||||||
- disable kmp to fix build again
|
- disable kmp to fix build again
|
||||||
* Fri Nov 07 2008 kwolf@suse.de
|
* Fri Nov 07 2008 kwolf@suse.de
|
||||||
|
Loading…
x
Reference in New Issue
Block a user