diff options
-rw-r--r-- | meta/recipes-kernel/linux/linux-yocto/0001-Fix-qemux86-pat-issue.patch | 100 | ||||
-rw-r--r-- | meta/recipes-kernel/linux/linux-yocto_4.4.bb | 2 | ||||
-rwxr-xr-x | scripts/runqemu-internal | 2 |
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 @@ | |||
1 | From 9bfb2c711f66fc8eb6482f5ca6ea33c2ec1d792f Mon Sep 17 00:00:00 2001 | ||
2 | From: Richard Purdie <richard.purdie@linuxfoundation.org> | ||
3 | Date: Sat, 13 Feb 2016 17:36:23 +0000 | ||
4 | Subject: [PATCH] Fix qemux86 pat issue | ||
5 | |||
6 | on qemux86, X doesn't start and there is | ||
7 | a backtrace in the logs: | ||
8 | |||
9 | x86/PAT: Xorg:705 map pfn expected mapping type uncached-minus for [mem 0xfd000000-0xfdffffff], got write-combining | ||
10 | ------------[ cut here ]------------ | ||
11 | WARNING: 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() | ||
12 | Modules linked in: uvesafb | ||
13 | CPU: 0 PID: 705 Comm: Xorg Not tainted 4.4.1-yocto-standard #1 | ||
14 | Hardware 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 | ||
18 | Call 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 ]--- | ||
37 | x86/PAT: Xorg:705 map pfn expected mapping type uncached-minus for [mem 0xfd000000-0xfdffffff], got write-combining | ||
38 | |||
39 | The entry in question is setup by uvesafb which in its | ||
40 | uvesafb_ioremap() function calls ioremap_wc(). | ||
41 | |||
42 | It appears that Xorg mmaps this from userspace, then later does a | ||
43 | fork() to execute a utility. At this point, when creating the vmas for | ||
44 | the new process, the pat code says "eeek!" as the protection mode for | ||
45 | the new vmas don't match the old one, returns -EINVAL, the process dies | ||
46 | and X goes with it. | ||
47 | |||
48 | There are a few hammers we can hit this with, we can boot with "nopat" | ||
49 | option which makes the problem go away, or turn off CONFIG_X86_PAT. No | ||
50 | surprises there. Changing uvesafb to use mtrr=0 doesn't help since the | ||
51 | ioremap_wc call still happens. | ||
52 | |||
53 | The real issue is the "expected mapping type uncached-minus for got | ||
54 | write-combining" message, it all goes wrong from there. | ||
55 | |||
56 | Upon looking at the code and scratching my head for a long while, I | ||
57 | notice that there are two ways of representing the protection mode | ||
58 | data, "enum page_cache_mode" and "pgprot_t & _PAGE_CACHE_MASK". | ||
59 | |||
60 | The exact meaning of pgprot_t depends on which CPU you're running, | ||
61 | older CPUs have errata meaning only a small number of bits can be used. | ||
62 | The exact mapping table is determined by __cachemode2pte_tbl and is | ||
63 | updated at boot by calls from update_cache_mode_entry(). | ||
64 | |||
65 | The 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 | |||
68 | This means the comparison in reserve_pfn_range() where it does "pcm != | ||
69 | want_pcm" isn't correct and can trigger even in cases where there isn't | ||
70 | a problem. | ||
71 | |||
72 | This can be "fixed" by doing cachemode2protval(pcm) != | ||
73 | cachemode2protval(want_pcm) and checking whether the protection bits | ||
74 | match, rather than the enum values, since in reality this is what we | ||
75 | really care about. With that change, X boots up just fine. | ||
76 | |||
77 | We don't see this on qemux86-64 since that has more PAT bits working | ||
78 | and hence the values map correctly. | ||
79 | |||
80 | Signed-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 | |||
85 | diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c | ||
86 | index 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 | -- | ||
99 | 2.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" | |||
40 | KERNEL_FEATURES_append_qemux86=" cfg/sound.scc cfg/paravirt_kvm.scc" | 40 | KERNEL_FEATURES_append_qemux86=" cfg/sound.scc cfg/paravirt_kvm.scc" |
41 | KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc cfg/paravirt_kvm.scc" | 41 | KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc cfg/paravirt_kvm.scc" |
42 | KERNEL_FEATURES_append = " ${@bb.utils.contains("TUNE_FEATURES", "mx32", " cfg/x32.scc", "" ,d)}" | 42 | KERNEL_FEATURES_append = " ${@bb.utils.contains("TUNE_FEATURES", "mx32", " cfg/x32.scc", "" ,d)}" |
43 | |||
44 | SRC_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" |
438 | fi | 438 | fi |
439 | 439 | ||
440 | if [ "$MACHINE" = "qemux86-64" ]; then | 440 | if [ "$MACHINE" = "qemux86-64" ]; then |