summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2016-02-14 09:25:34 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-02-15 16:28:45 +0000
commit94abdb2eea610b174064978d2fb8354a6231fc0c (patch)
treeea72235ee1ca6bf03c9ca991f41fed121c6aae7e
parent6fb493aa1b78ab46847c0822e32e8e83adf61560 (diff)
downloadpoky-94abdb2eea610b174064978d2fb8354a6231fc0c.tar.gz
linux-yocto: Work around PAT issue on qemux86
We have an issue with PAT handling on older processes with limited PAT bits, see the patch description for the full problem. This replaces the runqemu workaround with a kernel patch until we can get the kernel trees sorted out and discuss a proper fix with upstream. It should be safe everywhere so is applied unconditionally. (From OE-Core rev: e00f0794a535c8e68ae1c87c8b01dd65645d570b) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-kernel/linux/linux-yocto/0001-Fix-qemux86-pat-issue.patch100
-rw-r--r--meta/recipes-kernel/linux/linux-yocto_4.4.bb2
-rwxr-xr-xscripts/runqemu-internal2
3 files changed, 103 insertions, 1 deletions
diff --git a/meta/recipes-kernel/linux/linux-yocto/0001-Fix-qemux86-pat-issue.patch b/meta/recipes-kernel/linux/linux-yocto/0001-Fix-qemux86-pat-issue.patch
new file mode 100644
index 0000000000..367d9b4ace
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-yocto/0001-Fix-qemux86-pat-issue.patch
@@ -0,0 +1,100 @@
1From 9bfb2c711f66fc8eb6482f5ca6ea33c2ec1d792f Mon Sep 17 00:00:00 2001
2From: Richard Purdie <richard.purdie@linuxfoundation.org>
3Date: Sat, 13 Feb 2016 17:36:23 +0000
4Subject: [PATCH] Fix qemux86 pat issue
5
6on qemux86, X doesn't start and there is
7a backtrace in the logs:
8
9x86/PAT: Xorg:705 map pfn expected mapping type uncached-minus for [mem 0xfd000000-0xfdffffff], got write-combining
10------------[ cut here ]------------
11WARNING: CPU: 0 PID: 705 at /media/build1/poky/build/tmp/work-shared/qemux86/kernel-source/arch/x86/mm/pat.c:985 untrack_pfn+0xaf/0xc0()
12Modules linked in: uvesafb
13CPU: 0 PID: 705 Comm: Xorg Not tainted 4.4.1-yocto-standard #1
14Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
15 00000000 00000000 cf14dd78 c1397ab2 00000000 cf14dda8 c1051477 c1aa4f6c
16 00000000 000002c1 c1a9fa4c 000003d9 c104b98f c104b98f cf244000 b6355000
17 00000000 cf14ddb8 c1051552 00000009 00000000 cf14dde0 c104b98f cf14ddd0
18Call Trace:
19 [<c1397ab2>] dump_stack+0x4b/0x79
20 [<c1051477>] warn_slowpath_common+0x87/0xc0
21 [<c104b98f>] ? untrack_pfn+0xaf/0xc0
22 [<c104b98f>] ? untrack_pfn+0xaf/0xc0
23 [<c1051552>] warn_slowpath_null+0x22/0x30
24 [<c104b98f>] untrack_pfn+0xaf/0xc0
25 [<c104d54c>] ? kmap_atomic_prot+0x3c/0xf0
26 [<c114e17f>] unmap_single_vma+0x4ef/0x500
27 [<c114f007>] unmap_vmas+0x37/0x50
28 [<c1154f8f>] exit_mmap+0x5f/0xf0
29 [<c104eedd>] mmput+0x2d/0xb0
30 [<c105009c>] copy_process+0xd2c/0x13c0
31 [<c1050892>] _do_fork+0x82/0x340
32 [<c105f2d1>] ? SyS_rt_sigaction+0x51/0xa0
33 [<c1050c3c>] SyS_clone+0x2c/0x30
34 [<c1001a03>] do_syscall_32_irqs_on+0x53/0xb0
35 [<c189a94a>] entry_INT80_32+0x2a/0x2a
36---[ end trace be3e0a61097feddc ]---
37x86/PAT: Xorg:705 map pfn expected mapping type uncached-minus for [mem 0xfd000000-0xfdffffff], got write-combining
38
39The entry in question is setup by uvesafb which in its
40uvesafb_ioremap() function calls ioremap_wc().
41
42It appears that Xorg mmaps this from userspace, then later does a
43fork() to execute a utility. At this point, when creating the vmas for
44the new process, the pat code says "eeek!" as the protection mode for
45the new vmas don't match the old one, returns -EINVAL, the process dies
46and X goes with it.
47
48There are a few hammers we can hit this with, we can boot with "nopat"
49option which makes the problem go away, or turn off CONFIG_X86_PAT. No
50surprises there. Changing uvesafb to use mtrr=0 doesn't help since the
51ioremap_wc call still happens.
52
53The real issue is the "expected mapping type uncached-minus for got
54write-combining" message, it all goes wrong from there.
55
56Upon looking at the code and scratching my head for a long while, I
57notice that there are two ways of representing the protection mode
58data, "enum page_cache_mode" and "pgprot_t & _PAGE_CACHE_MASK".
59
60The exact meaning of pgprot_t depends on which CPU you're running,
61older CPUs have errata meaning only a small number of bits can be used.
62The exact mapping table is determined by __cachemode2pte_tbl and is
63updated at boot by calls from update_cache_mode_entry().
64
65The result of this if you map enum -> pgprot_t, then try to do pgprot_t
66-> enum, you can get different values since its not a 1:1 mapping.
67
68This means the comparison in reserve_pfn_range() where it does "pcm !=
69want_pcm" isn't correct and can trigger even in cases where there isn't
70a problem.
71
72This can be "fixed" by doing cachemode2protval(pcm) !=
73cachemode2protval(want_pcm) and checking whether the protection bits
74match, rather than the enum values, since in reality this is what we
75really care about. With that change, X boots up just fine.
76
77We don't see this on qemux86-64 since that has more PAT bits working
78and hence the values map correctly.
79
80Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
81---
82 arch/x86/mm/pat.c | 2 +-
83 1 file changed, 1 insertion(+), 1 deletion(-)
84
85diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
86index 031782e..11064fb 100644
87--- a/arch/x86/mm/pat.c
88+++ b/arch/x86/mm/pat.c
89@@ -833,7 +833,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
90 if (ret)
91 return ret;
92
93- if (pcm != want_pcm) {
94+ if (cachemode2protval(pcm) != cachemode2protval(want_pcm)) {
95 if (strict_prot ||
96 !is_new_memtype_allowed(paddr, size, want_pcm, pcm)) {
97 free_memtype(paddr, paddr + size);
98--
992.5.0
100
diff --git a/meta/recipes-kernel/linux/linux-yocto_4.4.bb b/meta/recipes-kernel/linux/linux-yocto_4.4.bb
index 1beeea6698..c0edcf13c3 100644
--- a/meta/recipes-kernel/linux/linux-yocto_4.4.bb
+++ b/meta/recipes-kernel/linux/linux-yocto_4.4.bb
@@ -40,3 +40,5 @@ KERNEL_FEATURES_append_qemuall=" cfg/virtio.scc"
40KERNEL_FEATURES_append_qemux86=" cfg/sound.scc cfg/paravirt_kvm.scc" 40KERNEL_FEATURES_append_qemux86=" cfg/sound.scc cfg/paravirt_kvm.scc"
41KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc cfg/paravirt_kvm.scc" 41KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc cfg/paravirt_kvm.scc"
42KERNEL_FEATURES_append = " ${@bb.utils.contains("TUNE_FEATURES", "mx32", " cfg/x32.scc", "" ,d)}" 42KERNEL_FEATURES_append = " ${@bb.utils.contains("TUNE_FEATURES", "mx32", " cfg/x32.scc", "" ,d)}"
43
44SRC_URI_append = " file://0001-Fix-qemux86-pat-issue.patch"
diff --git a/scripts/runqemu-internal b/scripts/runqemu-internal
index ad854d108d..ebed2bdd01 100755
--- a/scripts/runqemu-internal
+++ b/scripts/runqemu-internal
@@ -434,7 +434,7 @@ if [ "$MACHINE" = "qemux86" ]; then
434 fi 434 fi
435 # Currently oprofile's event based interrupt mode doesn't work(Bug #828) in 435 # Currently oprofile's event based interrupt mode doesn't work(Bug #828) in
436 # qemux86 and qemux86-64. We can use timer interrupt mode for now. 436 # qemux86 and qemux86-64. We can use timer interrupt mode for now.
437 KERNCMDLINE="$KERNCMDLINE oprofile.timer=1 nopat" 437 KERNCMDLINE="$KERNCMDLINE oprofile.timer=1"
438fi 438fi
439 439
440if [ "$MACHINE" = "qemux86-64" ]; then 440if [ "$MACHINE" = "qemux86-64" ]; then