diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 09:20:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 09:20:28 -0400 |
commit | ccff9b1db693062b0a9c9070f4304deb47ef215c (patch) | |
tree | a956cc800a03f11254105fbd9926bab537b6863f | |
parent | 3dc329baa2ed1740036183041cefaf8ceb714038 (diff) | |
parent | cb6b6df111e46b9d0f79eb971575fd50555f43f4 (diff) |
Merge tag 'stable/for-linus-3.7-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
Pull Xen fixes from Konrad Rzeszutek Wilk:
"This has four bug-fixes and one tiny feature that I forgot to put
initially in my tree due to oversight.
The feature is for kdump kernels to speed up the /proc/vmcore reading.
There is a ram_is_pfn helper function that the different platforms can
register for. We are now doing that.
The bug-fixes cover some embarrassing struct pv_cpu_ops variables
being set to NULL on Xen (but not baremetal). We had a similar issue
in the past with {write|read}_msr_safe and this fills the three
missing ones. The other bug-fix is to make the console output (hvc)
be capable of dealing with misbehaving backends and not fall flat on
its face. Lastly, a quirk for older XenBus implementations that came
with an ancient v3.4 hypervisor (so RHEL5 based) - reading of certain
non-existent attributes just hangs the guest during bootup - so we
take precaution of not doing that on such older installations.
Feature:
- Register a pfn_is_ram helper to speed up reading of /proc/vmcore.
Bug-fixes:
- Three pvops call for Xen were undefined causing BUG_ONs.
- Add a quirk so that the shutdown watches (used by kdump) are not
used with older Xen (3.4).
- Fix ungraceful state transition for the HVC console."
* tag 'stable/for-linus-3.7-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
xen/pv-on-hvm kexec: add quirk for Xen 3.4 and shutdown watches.
xen/bootup: allow {read|write}_cr8 pvops call.
xen/bootup: allow read_tscp call for Xen PV guests.
xen pv-on-hvm: add pfn_is_ram helper for kdump
xen/hvc: handle backend CLOSED without CLOSING
-rw-r--r-- | arch/x86/xen/enlighten.c | 18 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 41 | ||||
-rw-r--r-- | drivers/tty/hvc/hvc_xen.c | 5 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_xs.c | 21 | ||||
-rw-r--r-- | include/xen/interface/hvm/hvm_op.h | 19 |
5 files changed, 102 insertions, 2 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index bf788d34530d..e3497f240eab 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -987,7 +987,16 @@ static void xen_write_cr4(unsigned long cr4) | |||
987 | 987 | ||
988 | native_write_cr4(cr4); | 988 | native_write_cr4(cr4); |
989 | } | 989 | } |
990 | 990 | #ifdef CONFIG_X86_64 | |
991 | static inline unsigned long xen_read_cr8(void) | ||
992 | { | ||
993 | return 0; | ||
994 | } | ||
995 | static inline void xen_write_cr8(unsigned long val) | ||
996 | { | ||
997 | BUG_ON(val); | ||
998 | } | ||
999 | #endif | ||
991 | static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) | 1000 | static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) |
992 | { | 1001 | { |
993 | int ret; | 1002 | int ret; |
@@ -1156,6 +1165,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { | |||
1156 | .read_cr4_safe = native_read_cr4_safe, | 1165 | .read_cr4_safe = native_read_cr4_safe, |
1157 | .write_cr4 = xen_write_cr4, | 1166 | .write_cr4 = xen_write_cr4, |
1158 | 1167 | ||
1168 | #ifdef CONFIG_X86_64 | ||
1169 | .read_cr8 = xen_read_cr8, | ||
1170 | .write_cr8 = xen_write_cr8, | ||
1171 | #endif | ||
1172 | |||
1159 | .wbinvd = native_wbinvd, | 1173 | .wbinvd = native_wbinvd, |
1160 | 1174 | ||
1161 | .read_msr = native_read_msr_safe, | 1175 | .read_msr = native_read_msr_safe, |
@@ -1164,6 +1178,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { | |||
1164 | .read_tsc = native_read_tsc, | 1178 | .read_tsc = native_read_tsc, |
1165 | .read_pmc = native_read_pmc, | 1179 | .read_pmc = native_read_pmc, |
1166 | 1180 | ||
1181 | .read_tscp = native_read_tscp, | ||
1182 | |||
1167 | .iret = xen_iret, | 1183 | .iret = xen_iret, |
1168 | .irq_enable_sysexit = xen_sysexit, | 1184 | .irq_enable_sysexit = xen_sysexit, |
1169 | #ifdef CONFIG_X86_64 | 1185 | #ifdef CONFIG_X86_64 |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index fd28d86fe3d2..6226c99729b9 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/gfp.h> | 47 | #include <linux/gfp.h> |
48 | #include <linux/memblock.h> | 48 | #include <linux/memblock.h> |
49 | #include <linux/seq_file.h> | 49 | #include <linux/seq_file.h> |
50 | #include <linux/crash_dump.h> | ||
50 | 51 | ||
51 | #include <trace/events/xen.h> | 52 | #include <trace/events/xen.h> |
52 | 53 | ||
@@ -2381,6 +2382,43 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) | |||
2381 | EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region); | 2382 | EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region); |
2382 | 2383 | ||
2383 | #ifdef CONFIG_XEN_PVHVM | 2384 | #ifdef CONFIG_XEN_PVHVM |
2385 | #ifdef CONFIG_PROC_VMCORE | ||
2386 | /* | ||
2387 | * This function is used in two contexts: | ||
2388 | * - the kdump kernel has to check whether a pfn of the crashed kernel | ||
2389 | * was a ballooned page. vmcore is using this function to decide | ||
2390 | * whether to access a pfn of the crashed kernel. | ||
2391 | * - the kexec kernel has to check whether a pfn was ballooned by the | ||
2392 | * previous kernel. If the pfn is ballooned, handle it properly. | ||
2393 | * Returns 0 if the pfn is not backed by a RAM page, the caller may | ||
2394 | * handle the pfn special in this case. | ||
2395 | */ | ||
2396 | static int xen_oldmem_pfn_is_ram(unsigned long pfn) | ||
2397 | { | ||
2398 | struct xen_hvm_get_mem_type a = { | ||
2399 | .domid = DOMID_SELF, | ||
2400 | .pfn = pfn, | ||
2401 | }; | ||
2402 | int ram; | ||
2403 | |||
2404 | if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a)) | ||
2405 | return -ENXIO; | ||
2406 | |||
2407 | switch (a.mem_type) { | ||
2408 | case HVMMEM_mmio_dm: | ||
2409 | ram = 0; | ||
2410 | break; | ||
2411 | case HVMMEM_ram_rw: | ||
2412 | case HVMMEM_ram_ro: | ||
2413 | default: | ||
2414 | ram = 1; | ||
2415 | break; | ||
2416 | } | ||
2417 | |||
2418 | return ram; | ||
2419 | } | ||
2420 | #endif | ||
2421 | |||
2384 | static void xen_hvm_exit_mmap(struct mm_struct *mm) | 2422 | static void xen_hvm_exit_mmap(struct mm_struct *mm) |
2385 | { | 2423 | { |
2386 | struct xen_hvm_pagetable_dying a; | 2424 | struct xen_hvm_pagetable_dying a; |
@@ -2411,6 +2449,9 @@ void __init xen_hvm_init_mmu_ops(void) | |||
2411 | { | 2449 | { |
2412 | if (is_pagetable_dying_supported()) | 2450 | if (is_pagetable_dying_supported()) |
2413 | pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap; | 2451 | pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap; |
2452 | #ifdef CONFIG_PROC_VMCORE | ||
2453 | register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram); | ||
2454 | #endif | ||
2414 | } | 2455 | } |
2415 | #endif | 2456 | #endif |
2416 | 2457 | ||
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 2944ff88fdc0..f4abfe238f98 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c | |||
@@ -478,7 +478,6 @@ static void xencons_backend_changed(struct xenbus_device *dev, | |||
478 | case XenbusStateInitialising: | 478 | case XenbusStateInitialising: |
479 | case XenbusStateInitialised: | 479 | case XenbusStateInitialised: |
480 | case XenbusStateUnknown: | 480 | case XenbusStateUnknown: |
481 | case XenbusStateClosed: | ||
482 | break; | 481 | break; |
483 | 482 | ||
484 | case XenbusStateInitWait: | 483 | case XenbusStateInitWait: |
@@ -488,6 +487,10 @@ static void xencons_backend_changed(struct xenbus_device *dev, | |||
488 | xenbus_switch_state(dev, XenbusStateConnected); | 487 | xenbus_switch_state(dev, XenbusStateConnected); |
489 | break; | 488 | break; |
490 | 489 | ||
490 | case XenbusStateClosed: | ||
491 | if (dev->state == XenbusStateClosed) | ||
492 | break; | ||
493 | /* Missed the backend's CLOSING state -- fallthrough */ | ||
491 | case XenbusStateClosing: | 494 | case XenbusStateClosing: |
492 | xenbus_frontend_closed(dev); | 495 | xenbus_frontend_closed(dev); |
493 | break; | 496 | break; |
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 131dec04794e..48220e129f85 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <xen/xenbus.h> | 48 | #include <xen/xenbus.h> |
49 | #include <xen/xen.h> | 49 | #include <xen/xen.h> |
50 | #include "xenbus_comms.h" | 50 | #include "xenbus_comms.h" |
51 | #include <asm/xen/hypervisor.h> | ||
51 | 52 | ||
52 | struct xs_stored_msg { | 53 | struct xs_stored_msg { |
53 | struct list_head list; | 54 | struct list_head list; |
@@ -618,7 +619,24 @@ static struct xenbus_watch *find_watch(const char *token) | |||
618 | 619 | ||
619 | return NULL; | 620 | return NULL; |
620 | } | 621 | } |
622 | /* | ||
623 | * Certain older XenBus toolstack cannot handle reading values that are | ||
624 | * not populated. Some Xen 3.4 installation are incapable of doing this | ||
625 | * so if we are running on anything older than 4 do not attempt to read | ||
626 | * control/platform-feature-xs_reset_watches. | ||
627 | */ | ||
628 | static bool xen_strict_xenbus_quirk() | ||
629 | { | ||
630 | uint32_t eax, ebx, ecx, edx, base; | ||
631 | |||
632 | base = xen_cpuid_base(); | ||
633 | cpuid(base + 1, &eax, &ebx, &ecx, &edx); | ||
621 | 634 | ||
635 | if ((eax >> 16) < 4) | ||
636 | return true; | ||
637 | return false; | ||
638 | |||
639 | } | ||
622 | static void xs_reset_watches(void) | 640 | static void xs_reset_watches(void) |
623 | { | 641 | { |
624 | int err, supported = 0; | 642 | int err, supported = 0; |
@@ -626,6 +644,9 @@ static void xs_reset_watches(void) | |||
626 | if (!xen_hvm_domain() || xen_initial_domain()) | 644 | if (!xen_hvm_domain() || xen_initial_domain()) |
627 | return; | 645 | return; |
628 | 646 | ||
647 | if (xen_strict_xenbus_quirk()) | ||
648 | return; | ||
649 | |||
629 | err = xenbus_scanf(XBT_NIL, "control", | 650 | err = xenbus_scanf(XBT_NIL, "control", |
630 | "platform-feature-xs_reset_watches", "%d", &supported); | 651 | "platform-feature-xs_reset_watches", "%d", &supported); |
631 | if (err != 1 || !supported) | 652 | if (err != 1 || !supported) |
diff --git a/include/xen/interface/hvm/hvm_op.h b/include/xen/interface/hvm/hvm_op.h index a4827f46ee97..956a04682865 100644 --- a/include/xen/interface/hvm/hvm_op.h +++ b/include/xen/interface/hvm/hvm_op.h | |||
@@ -43,4 +43,23 @@ struct xen_hvm_pagetable_dying { | |||
43 | typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t; | 43 | typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t; |
44 | DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_pagetable_dying_t); | 44 | DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_pagetable_dying_t); |
45 | 45 | ||
46 | enum hvmmem_type_t { | ||
47 | HVMMEM_ram_rw, /* Normal read/write guest RAM */ | ||
48 | HVMMEM_ram_ro, /* Read-only; writes are discarded */ | ||
49 | HVMMEM_mmio_dm, /* Reads and write go to the device model */ | ||
50 | }; | ||
51 | |||
52 | #define HVMOP_get_mem_type 15 | ||
53 | /* Return hvmmem_type_t for the specified pfn. */ | ||
54 | struct xen_hvm_get_mem_type { | ||
55 | /* Domain to be queried. */ | ||
56 | domid_t domid; | ||
57 | /* OUT variable. */ | ||
58 | uint16_t mem_type; | ||
59 | uint16_t pad[2]; /* align next field on 8-byte boundary */ | ||
60 | /* IN variable. */ | ||
61 | uint64_t pfn; | ||
62 | }; | ||
63 | DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_get_mem_type); | ||
64 | |||
46 | #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */ | 65 | #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */ |