diff options
984 files changed, 28951 insertions, 12452 deletions
diff --git a/Documentation/ABI/testing/sysfs-firmware-efi b/Documentation/ABI/testing/sysfs-firmware-efi new file mode 100644 index 000000000000..05874da7ce80 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-firmware-efi | |||
@@ -0,0 +1,20 @@ | |||
1 | What: /sys/firmware/efi/fw_vendor | ||
2 | Date: December 2013 | ||
3 | Contact: Dave Young <dyoung@redhat.com> | ||
4 | Description: It shows the physical address of firmware vendor field in the | ||
5 | EFI system table. | ||
6 | Users: Kexec | ||
7 | |||
8 | What: /sys/firmware/efi/runtime | ||
9 | Date: December 2013 | ||
10 | Contact: Dave Young <dyoung@redhat.com> | ||
11 | Description: It shows the physical address of runtime service table entry in | ||
12 | the EFI system table. | ||
13 | Users: Kexec | ||
14 | |||
15 | What: /sys/firmware/efi/config_table | ||
16 | Date: December 2013 | ||
17 | Contact: Dave Young <dyoung@redhat.com> | ||
18 | Description: It shows the physical address of config table entry in the EFI | ||
19 | system table. | ||
20 | Users: Kexec | ||
diff --git a/Documentation/ABI/testing/sysfs-firmware-efi-runtime-map b/Documentation/ABI/testing/sysfs-firmware-efi-runtime-map new file mode 100644 index 000000000000..c61b9b348e99 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-firmware-efi-runtime-map | |||
@@ -0,0 +1,34 @@ | |||
1 | What: /sys/firmware/efi/runtime-map/ | ||
2 | Date: December 2013 | ||
3 | Contact: Dave Young <dyoung@redhat.com> | ||
4 | Description: Switching efi runtime services to virtual mode requires | ||
5 | that all efi memory ranges which have the runtime attribute | ||
6 | bit set to be mapped to virtual addresses. | ||
7 | |||
8 | The efi runtime services can only be switched to virtual | ||
9 | mode once without rebooting. The kexec kernel must maintain | ||
10 | the same physical to virtual address mappings as the first | ||
11 | kernel. The mappings are exported to sysfs so userspace tools | ||
12 | can reassemble them and pass them into the kexec kernel. | ||
13 | |||
14 | /sys/firmware/efi/runtime-map/ is the directory the kernel | ||
15 | exports that information in. | ||
16 | |||
17 | subdirectories are named with the number of the memory range: | ||
18 | |||
19 | /sys/firmware/efi/runtime-map/0 | ||
20 | /sys/firmware/efi/runtime-map/1 | ||
21 | /sys/firmware/efi/runtime-map/2 | ||
22 | /sys/firmware/efi/runtime-map/3 | ||
23 | ... | ||
24 | |||
25 | Each subdirectory contains five files: | ||
26 | |||
27 | attribute : The attributes of the memory range. | ||
28 | num_pages : The size of the memory range in pages. | ||
29 | phys_addr : The physical address of the memory range. | ||
30 | type : The type of the memory range. | ||
31 | virt_addr : The virtual address of the memory range. | ||
32 | |||
33 | Above values are all hexadecimal numbers with the '0x' prefix. | ||
34 | Users: Kexec | ||
diff --git a/Documentation/ABI/testing/sysfs-kernel-boot_params b/Documentation/ABI/testing/sysfs-kernel-boot_params new file mode 100644 index 000000000000..eca38ce2852d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-boot_params | |||
@@ -0,0 +1,38 @@ | |||
1 | What: /sys/kernel/boot_params | ||
2 | Date: December 2013 | ||
3 | Contact: Dave Young <dyoung@redhat.com> | ||
4 | Description: The /sys/kernel/boot_params directory contains two | ||
5 | files: "data" and "version" and one subdirectory "setup_data". | ||
6 | It is used to export the kernel boot parameters of an x86 | ||
7 | platform to userspace for kexec and debugging purpose. | ||
8 | |||
9 | If there's no setup_data in boot_params the subdirectory will | ||
10 | not be created. | ||
11 | |||
12 | "data" file is the binary representation of struct boot_params. | ||
13 | |||
14 | "version" file is the string representation of boot | ||
15 | protocol version. | ||
16 | |||
17 | "setup_data" subdirectory contains the setup_data data | ||
18 | structure in boot_params. setup_data is maintained in kernel | ||
19 | as a link list. In "setup_data" subdirectory there's one | ||
20 | subdirectory for each link list node named with the number | ||
21 | of the list nodes. The list node subdirectory contains two | ||
22 | files "type" and "data". "type" file is the string | ||
23 | representation of setup_data type. "data" file is the binary | ||
24 | representation of setup_data payload. | ||
25 | |||
26 | The whole boot_params directory structure is like below: | ||
27 | /sys/kernel/boot_params | ||
28 | |__ data | ||
29 | |__ setup_data | ||
30 | | |__ 0 | ||
31 | | | |__ data | ||
32 | | | |__ type | ||
33 | | |__ 1 | ||
34 | | |__ data | ||
35 | | |__ type | ||
36 | |__ version | ||
37 | |||
38 | Users: Kexec | ||
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt index f3778f8952da..910870b15acd 100644 --- a/Documentation/RCU/trace.txt +++ b/Documentation/RCU/trace.txt | |||
@@ -396,14 +396,14 @@ o Each element of the form "3/3 ..>. 0:7 ^0" represents one rcu_node | |||
396 | 396 | ||
397 | The output of "cat rcu/rcu_sched/rcu_pending" looks as follows: | 397 | The output of "cat rcu/rcu_sched/rcu_pending" looks as follows: |
398 | 398 | ||
399 | 0!np=26111 qsp=29 rpq=5386 cbr=1 cng=570 gpc=3674 gps=577 nn=15903 | 399 | 0!np=26111 qsp=29 rpq=5386 cbr=1 cng=570 gpc=3674 gps=577 nn=15903 ndw=0 |
400 | 1!np=28913 qsp=35 rpq=6097 cbr=1 cng=448 gpc=3700 gps=554 nn=18113 | 400 | 1!np=28913 qsp=35 rpq=6097 cbr=1 cng=448 gpc=3700 gps=554 nn=18113 ndw=0 |
401 | 2!np=32740 qsp=37 rpq=6202 cbr=0 cng=476 gpc=4627 gps=546 nn=20889 | 401 | 2!np=32740 qsp=37 rpq=6202 cbr=0 cng=476 gpc=4627 gps=546 nn=20889 ndw=0 |
402 | 3 np=23679 qsp=22 rpq=5044 cbr=1 cng=415 gpc=3403 gps=347 nn=14469 | 402 | 3 np=23679 qsp=22 rpq=5044 cbr=1 cng=415 gpc=3403 gps=347 nn=14469 ndw=0 |
403 | 4!np=30714 qsp=4 rpq=5574 cbr=0 cng=528 gpc=3931 gps=639 nn=20042 | 403 | 4!np=30714 qsp=4 rpq=5574 cbr=0 cng=528 gpc=3931 gps=639 nn=20042 ndw=0 |
404 | 5 np=28910 qsp=2 rpq=5246 cbr=0 cng=428 gpc=4105 gps=709 nn=18422 | 404 | 5 np=28910 qsp=2 rpq=5246 cbr=0 cng=428 gpc=4105 gps=709 nn=18422 ndw=0 |
405 | 6!np=38648 qsp=5 rpq=7076 cbr=0 cng=840 gpc=4072 gps=961 nn=25699 | 405 | 6!np=38648 qsp=5 rpq=7076 cbr=0 cng=840 gpc=4072 gps=961 nn=25699 ndw=0 |
406 | 7 np=37275 qsp=2 rpq=6873 cbr=0 cng=868 gpc=3416 gps=971 nn=25147 | 406 | 7 np=37275 qsp=2 rpq=6873 cbr=0 cng=868 gpc=3416 gps=971 nn=25147 ndw=0 |
407 | 407 | ||
408 | The fields are as follows: | 408 | The fields are as follows: |
409 | 409 | ||
@@ -432,6 +432,10 @@ o "gpc" is the number of times that an old grace period had | |||
432 | o "gps" is the number of times that a new grace period had started, | 432 | o "gps" is the number of times that a new grace period had started, |
433 | but this CPU was not yet aware of it. | 433 | but this CPU was not yet aware of it. |
434 | 434 | ||
435 | o "ndw" is the number of times that a wakeup of an rcuo | ||
436 | callback-offload kthread had to be deferred in order to avoid | ||
437 | deadlock. | ||
438 | |||
435 | o "nn" is the number of times that this CPU needed nothing. | 439 | o "nn" is the number of times that this CPU needed nothing. |
436 | 440 | ||
437 | 441 | ||
@@ -443,7 +447,7 @@ The output of "cat rcu/rcuboost" looks as follows: | |||
443 | balk: nt=0 egt=6541 bt=0 nb=0 ny=126 nos=0 | 447 | balk: nt=0 egt=6541 bt=0 nb=0 ny=126 nos=0 |
444 | 448 | ||
445 | This information is output only for rcu_preempt. Each two-line entry | 449 | This information is output only for rcu_preempt. Each two-line entry |
446 | corresponds to a leaf rcu_node strcuture. The fields are as follows: | 450 | corresponds to a leaf rcu_node structure. The fields are as follows: |
447 | 451 | ||
448 | o "n:m" is the CPU-number range for the corresponding two-line | 452 | o "n:m" is the CPU-number range for the corresponding two-line |
449 | entry. In the sample output above, the first entry covers | 453 | entry. In the sample output above, the first entry covers |
diff --git a/Documentation/acpi/apei/einj.txt b/Documentation/acpi/apei/einj.txt index a58b63da1a36..f51861bcb07b 100644 --- a/Documentation/acpi/apei/einj.txt +++ b/Documentation/acpi/apei/einj.txt | |||
@@ -45,11 +45,22 @@ directory apei/einj. The following files are provided. | |||
45 | injection. Before this, please specify all necessary error | 45 | injection. Before this, please specify all necessary error |
46 | parameters. | 46 | parameters. |
47 | 47 | ||
48 | - flags | ||
49 | Present for kernel version 3.13 and above. Used to specify which | ||
50 | of param{1..4} are valid and should be used by BIOS during injection. | ||
51 | Value is a bitmask as specified in ACPI5.0 spec for the | ||
52 | SET_ERROR_TYPE_WITH_ADDRESS data structure: | ||
53 | Bit 0 - Processor APIC field valid (see param3 below) | ||
54 | Bit 1 - Memory address and mask valid (param1 and param2) | ||
55 | Bit 2 - PCIe (seg,bus,dev,fn) valid (param4 below) | ||
56 | If set to zero, legacy behaviour is used where the type of injection | ||
57 | specifies just one bit set, and param1 is multiplexed. | ||
58 | |||
48 | - param1 | 59 | - param1 |
49 | This file is used to set the first error parameter value. Effect of | 60 | This file is used to set the first error parameter value. Effect of |
50 | parameter depends on error_type specified. For example, if error | 61 | parameter depends on error_type specified. For example, if error |
51 | type is memory related type, the param1 should be a valid physical | 62 | type is memory related type, the param1 should be a valid physical |
52 | memory address. | 63 | memory address. [Unless "flag" is set - see above] |
53 | 64 | ||
54 | - param2 | 65 | - param2 |
55 | This file is used to set the second error parameter value. Effect of | 66 | This file is used to set the second error parameter value. Effect of |
@@ -58,6 +69,12 @@ directory apei/einj. The following files are provided. | |||
58 | address mask. Linux requires page or narrower granularity, say, | 69 | address mask. Linux requires page or narrower granularity, say, |
59 | 0xfffffffffffff000. | 70 | 0xfffffffffffff000. |
60 | 71 | ||
72 | - param3 | ||
73 | Used when the 0x1 bit is set in "flag" to specify the APIC id | ||
74 | |||
75 | - param4 | ||
76 | Used when the 0x4 bit is set in "flag" to specify target PCIe device | ||
77 | |||
61 | - notrigger | 78 | - notrigger |
62 | The EINJ mechanism is a two step process. First inject the error, then | 79 | The EINJ mechanism is a two step process. First inject the error, then |
63 | perform some actions to trigger it. Setting "notrigger" to 1 skips the | 80 | perform some actions to trigger it. Setting "notrigger" to 1 skips the |
diff --git a/Documentation/circular-buffers.txt b/Documentation/circular-buffers.txt index 8117e5bf6065..88951b179262 100644 --- a/Documentation/circular-buffers.txt +++ b/Documentation/circular-buffers.txt | |||
@@ -160,6 +160,7 @@ The producer will look something like this: | |||
160 | spin_lock(&producer_lock); | 160 | spin_lock(&producer_lock); |
161 | 161 | ||
162 | unsigned long head = buffer->head; | 162 | unsigned long head = buffer->head; |
163 | /* The spin_unlock() and next spin_lock() provide needed ordering. */ | ||
163 | unsigned long tail = ACCESS_ONCE(buffer->tail); | 164 | unsigned long tail = ACCESS_ONCE(buffer->tail); |
164 | 165 | ||
165 | if (CIRC_SPACE(head, tail, buffer->size) >= 1) { | 166 | if (CIRC_SPACE(head, tail, buffer->size) >= 1) { |
@@ -168,9 +169,8 @@ The producer will look something like this: | |||
168 | 169 | ||
169 | produce_item(item); | 170 | produce_item(item); |
170 | 171 | ||
171 | smp_wmb(); /* commit the item before incrementing the head */ | 172 | smp_store_release(buffer->head, |
172 | 173 | (head + 1) & (buffer->size - 1)); | |
173 | buffer->head = (head + 1) & (buffer->size - 1); | ||
174 | 174 | ||
175 | /* wake_up() will make sure that the head is committed before | 175 | /* wake_up() will make sure that the head is committed before |
176 | * waking anyone up */ | 176 | * waking anyone up */ |
@@ -183,9 +183,14 @@ This will instruct the CPU that the contents of the new item must be written | |||
183 | before the head index makes it available to the consumer and then instructs the | 183 | before the head index makes it available to the consumer and then instructs the |
184 | CPU that the revised head index must be written before the consumer is woken. | 184 | CPU that the revised head index must be written before the consumer is woken. |
185 | 185 | ||
186 | Note that wake_up() doesn't have to be the exact mechanism used, but whatever | 186 | Note that wake_up() does not guarantee any sort of barrier unless something |
187 | is used must guarantee a (write) memory barrier between the update of the head | 187 | is actually awakened. We therefore cannot rely on it for ordering. However, |
188 | index and the change of state of the consumer, if a change of state occurs. | 188 | there is always one element of the array left empty. Therefore, the |
189 | producer must produce two elements before it could possibly corrupt the | ||
190 | element currently being read by the consumer. Therefore, the unlock-lock | ||
191 | pair between consecutive invocations of the consumer provides the necessary | ||
192 | ordering between the read of the index indicating that the consumer has | ||
193 | vacated a given element and the write by the producer to that same element. | ||
189 | 194 | ||
190 | 195 | ||
191 | THE CONSUMER | 196 | THE CONSUMER |
@@ -195,21 +200,20 @@ The consumer will look something like this: | |||
195 | 200 | ||
196 | spin_lock(&consumer_lock); | 201 | spin_lock(&consumer_lock); |
197 | 202 | ||
198 | unsigned long head = ACCESS_ONCE(buffer->head); | 203 | /* Read index before reading contents at that index. */ |
204 | unsigned long head = smp_load_acquire(buffer->head); | ||
199 | unsigned long tail = buffer->tail; | 205 | unsigned long tail = buffer->tail; |
200 | 206 | ||
201 | if (CIRC_CNT(head, tail, buffer->size) >= 1) { | 207 | if (CIRC_CNT(head, tail, buffer->size) >= 1) { |
202 | /* read index before reading contents at that index */ | ||
203 | smp_read_barrier_depends(); | ||
204 | 208 | ||
205 | /* extract one item from the buffer */ | 209 | /* extract one item from the buffer */ |
206 | struct item *item = buffer[tail]; | 210 | struct item *item = buffer[tail]; |
207 | 211 | ||
208 | consume_item(item); | 212 | consume_item(item); |
209 | 213 | ||
210 | smp_mb(); /* finish reading descriptor before incrementing tail */ | 214 | /* Finish reading descriptor before incrementing tail. */ |
211 | 215 | smp_store_release(buffer->tail, | |
212 | buffer->tail = (tail + 1) & (buffer->size - 1); | 216 | (tail + 1) & (buffer->size - 1)); |
213 | } | 217 | } |
214 | 218 | ||
215 | spin_unlock(&consumer_lock); | 219 | spin_unlock(&consumer_lock); |
@@ -218,12 +222,17 @@ This will instruct the CPU to make sure the index is up to date before reading | |||
218 | the new item, and then it shall make sure the CPU has finished reading the item | 222 | the new item, and then it shall make sure the CPU has finished reading the item |
219 | before it writes the new tail pointer, which will erase the item. | 223 | before it writes the new tail pointer, which will erase the item. |
220 | 224 | ||
221 | 225 | Note the use of ACCESS_ONCE() and smp_load_acquire() to read the | |
222 | Note the use of ACCESS_ONCE() in both algorithms to read the opposition index. | 226 | opposition index. This prevents the compiler from discarding and |
223 | This prevents the compiler from discarding and reloading its cached value - | 227 | reloading its cached value - which some compilers will do across |
224 | which some compilers will do across smp_read_barrier_depends(). This isn't | 228 | smp_read_barrier_depends(). This isn't strictly needed if you can |
225 | strictly needed if you can be sure that the opposition index will _only_ be | 229 | be sure that the opposition index will _only_ be used the once. |
226 | used the once. | 230 | The smp_load_acquire() additionally forces the CPU to order against |
231 | subsequent memory references. Similarly, smp_store_release() is used | ||
232 | in both algorithms to write the thread's index. This documents the | ||
233 | fact that we are writing to something that can be read concurrently, | ||
234 | prevents the compiler from tearing the store, and enforces ordering | ||
235 | against previous accesses. | ||
227 | 236 | ||
228 | 237 | ||
229 | =============== | 238 | =============== |
diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt new file mode 100644 index 000000000000..7c26154b8bbb --- /dev/null +++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt | |||
@@ -0,0 +1,22 @@ | |||
1 | Allwinner SoCs High Speed Timer Controller | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible : should be "allwinner,sun5i-a13-hstimer" or | ||
6 | "allwinner,sun7i-a20-hstimer" | ||
7 | - reg : Specifies base physical address and size of the registers. | ||
8 | - interrupts : The interrupts of these timers (2 for the sun5i IP, 4 for the sun7i | ||
9 | one) | ||
10 | - clocks: phandle to the source clock (usually the AHB clock) | ||
11 | |||
12 | Example: | ||
13 | |||
14 | timer@01c60000 { | ||
15 | compatible = "allwinner,sun7i-a20-hstimer"; | ||
16 | reg = <0x01c60000 0x1000>; | ||
17 | interrupts = <0 51 1>, | ||
18 | <0 52 1>, | ||
19 | <0 53 1>, | ||
20 | <0 54 1>; | ||
21 | clocks = <&ahb1_gates 19>; | ||
22 | }; | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index b9e9bd854298..4252af6ffda1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -774,6 +774,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
774 | disable= [IPV6] | 774 | disable= [IPV6] |
775 | See Documentation/networking/ipv6.txt. | 775 | See Documentation/networking/ipv6.txt. |
776 | 776 | ||
777 | disable_cpu_apicid= [X86,APIC,SMP] | ||
778 | Format: <int> | ||
779 | The number of initial APIC ID for the | ||
780 | corresponding CPU to be disabled at boot, | ||
781 | mostly used for the kdump 2nd kernel to | ||
782 | disable BSP to wake up multiple CPUs without | ||
783 | causing system reset or hang due to sending | ||
784 | INIT from AP to BSP. | ||
785 | |||
777 | disable_ddw [PPC/PSERIES] | 786 | disable_ddw [PPC/PSERIES] |
778 | Disable Dynamic DMA Window support. Use this if | 787 | Disable Dynamic DMA Window support. Use this if |
779 | to workaround buggy firmware. | 788 | to workaround buggy firmware. |
@@ -881,6 +890,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
881 | 890 | ||
882 | The xen output can only be used by Xen PV guests. | 891 | The xen output can only be used by Xen PV guests. |
883 | 892 | ||
893 | edac_report= [HW,EDAC] Control how to report EDAC event | ||
894 | Format: {"on" | "off" | "force"} | ||
895 | on: enable EDAC to report H/W event. May be overridden | ||
896 | by other higher priority error reporting module. | ||
897 | off: disable H/W event reporting through EDAC. | ||
898 | force: enforce the use of EDAC to report H/W event. | ||
899 | default: on. | ||
900 | |||
884 | ekgdboc= [X86,KGDB] Allow early kernel console debugging | 901 | ekgdboc= [X86,KGDB] Allow early kernel console debugging |
885 | ekgdboc=kbd | 902 | ekgdboc=kbd |
886 | 903 | ||
@@ -890,6 +907,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
890 | edd= [EDD] | 907 | edd= [EDD] |
891 | Format: {"off" | "on" | "skip[mbr]"} | 908 | Format: {"off" | "on" | "skip[mbr]"} |
892 | 909 | ||
910 | efi= [EFI] | ||
911 | Format: { "old_map" } | ||
912 | old_map [X86-64]: switch to the old ioremap-based EFI | ||
913 | runtime services mapping. 32-bit still uses this one by | ||
914 | default. | ||
915 | |||
893 | efi_no_storage_paranoia [EFI; X86] | 916 | efi_no_storage_paranoia [EFI; X86] |
894 | Using this parameter you can use more than 50% of | 917 | Using this parameter you can use more than 50% of |
895 | your efi variable storage. Use this parameter only if | 918 | your efi variable storage. Use this parameter only if |
@@ -1994,6 +2017,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
1994 | noapic [SMP,APIC] Tells the kernel to not make use of any | 2017 | noapic [SMP,APIC] Tells the kernel to not make use of any |
1995 | IOAPICs that may be present in the system. | 2018 | IOAPICs that may be present in the system. |
1996 | 2019 | ||
2020 | nokaslr [X86] | ||
2021 | Disable kernel base offset ASLR (Address Space | ||
2022 | Layout Randomization) if built into the kernel. | ||
2023 | |||
1997 | noautogroup Disable scheduler automatic task group creation. | 2024 | noautogroup Disable scheduler automatic task group creation. |
1998 | 2025 | ||
1999 | nobats [PPC] Do not use BATs for mapping kernel lowmem | 2026 | nobats [PPC] Do not use BATs for mapping kernel lowmem |
@@ -2627,7 +2654,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
2627 | for RCU-preempt, and "s" for RCU-sched, and "N" | 2654 | for RCU-preempt, and "s" for RCU-sched, and "N" |
2628 | is the CPU number. This reduces OS jitter on the | 2655 | is the CPU number. This reduces OS jitter on the |
2629 | offloaded CPUs, which can be useful for HPC and | 2656 | offloaded CPUs, which can be useful for HPC and |
2630 | |||
2631 | real-time workloads. It can also improve energy | 2657 | real-time workloads. It can also improve energy |
2632 | efficiency for asymmetric multiprocessors. | 2658 | efficiency for asymmetric multiprocessors. |
2633 | 2659 | ||
@@ -2643,8 +2669,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
2643 | periodically wake up to do the polling. | 2669 | periodically wake up to do the polling. |
2644 | 2670 | ||
2645 | rcutree.blimit= [KNL] | 2671 | rcutree.blimit= [KNL] |
2646 | Set maximum number of finished RCU callbacks to process | 2672 | Set maximum number of finished RCU callbacks to |
2647 | in one batch. | 2673 | process in one batch. |
2648 | 2674 | ||
2649 | rcutree.rcu_fanout_leaf= [KNL] | 2675 | rcutree.rcu_fanout_leaf= [KNL] |
2650 | Increase the number of CPUs assigned to each | 2676 | Increase the number of CPUs assigned to each |
@@ -2663,8 +2689,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
2663 | value is one, and maximum value is HZ. | 2689 | value is one, and maximum value is HZ. |
2664 | 2690 | ||
2665 | rcutree.qhimark= [KNL] | 2691 | rcutree.qhimark= [KNL] |
2666 | Set threshold of queued | 2692 | Set threshold of queued RCU callbacks beyond which |
2667 | RCU callbacks over which batch limiting is disabled. | 2693 | batch limiting is disabled. |
2668 | 2694 | ||
2669 | rcutree.qlowmark= [KNL] | 2695 | rcutree.qlowmark= [KNL] |
2670 | Set threshold of queued RCU callbacks below which | 2696 | Set threshold of queued RCU callbacks below which |
diff --git a/Documentation/kmsg/s390/zcrypt b/Documentation/kmsg/s390/zcrypt new file mode 100644 index 000000000000..7fb2087409d6 --- /dev/null +++ b/Documentation/kmsg/s390/zcrypt | |||
@@ -0,0 +1,20 @@ | |||
1 | /*? | ||
2 | * Text: "Cryptographic device %x failed and was set offline\n" | ||
3 | * Severity: Error | ||
4 | * Parameter: | ||
5 | * @1: device index | ||
6 | * Description: | ||
7 | * A cryptographic device failed to process a cryptographic request. | ||
8 | * The cryptographic device driver could not correct the error and | ||
9 | * set the device offline. The application that issued the | ||
10 | * request received an indication that the request has failed. | ||
11 | * User action: | ||
12 | * Use the lszcrypt command to confirm that the cryptographic | ||
13 | * hardware is still configured to your LPAR or z/VM guest virtual | ||
14 | * machine. If the device is available to your Linux instance the | ||
15 | * command output contains a line that begins with 'card<device index>', | ||
16 | * where <device index> is the two-digit decimal number in the message text. | ||
17 | * After ensuring that the device is available, use the chzcrypt command to | ||
18 | * set it online again. | ||
19 | * If the error persists, contact your support organization. | ||
20 | */ | ||
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index c8c42e64e953..102dc19c4119 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt | |||
@@ -194,18 +194,22 @@ There are some minimal guarantees that may be expected of a CPU: | |||
194 | (*) On any given CPU, dependent memory accesses will be issued in order, with | 194 | (*) On any given CPU, dependent memory accesses will be issued in order, with |
195 | respect to itself. This means that for: | 195 | respect to itself. This means that for: |
196 | 196 | ||
197 | Q = P; D = *Q; | 197 | ACCESS_ONCE(Q) = P; smp_read_barrier_depends(); D = ACCESS_ONCE(*Q); |
198 | 198 | ||
199 | the CPU will issue the following memory operations: | 199 | the CPU will issue the following memory operations: |
200 | 200 | ||
201 | Q = LOAD P, D = LOAD *Q | 201 | Q = LOAD P, D = LOAD *Q |
202 | 202 | ||
203 | and always in that order. | 203 | and always in that order. On most systems, smp_read_barrier_depends() |
204 | does nothing, but it is required for DEC Alpha. The ACCESS_ONCE() | ||
205 | is required to prevent compiler mischief. Please note that you | ||
206 | should normally use something like rcu_dereference() instead of | ||
207 | open-coding smp_read_barrier_depends(). | ||
204 | 208 | ||
205 | (*) Overlapping loads and stores within a particular CPU will appear to be | 209 | (*) Overlapping loads and stores within a particular CPU will appear to be |
206 | ordered within that CPU. This means that for: | 210 | ordered within that CPU. This means that for: |
207 | 211 | ||
208 | a = *X; *X = b; | 212 | a = ACCESS_ONCE(*X); ACCESS_ONCE(*X) = b; |
209 | 213 | ||
210 | the CPU will only issue the following sequence of memory operations: | 214 | the CPU will only issue the following sequence of memory operations: |
211 | 215 | ||
@@ -213,7 +217,7 @@ There are some minimal guarantees that may be expected of a CPU: | |||
213 | 217 | ||
214 | And for: | 218 | And for: |
215 | 219 | ||
216 | *X = c; d = *X; | 220 | ACCESS_ONCE(*X) = c; d = ACCESS_ONCE(*X); |
217 | 221 | ||
218 | the CPU will only issue: | 222 | the CPU will only issue: |
219 | 223 | ||
@@ -224,6 +228,12 @@ There are some minimal guarantees that may be expected of a CPU: | |||
224 | 228 | ||
225 | And there are a number of things that _must_ or _must_not_ be assumed: | 229 | And there are a number of things that _must_ or _must_not_ be assumed: |
226 | 230 | ||
231 | (*) It _must_not_ be assumed that the compiler will do what you want with | ||
232 | memory references that are not protected by ACCESS_ONCE(). Without | ||
233 | ACCESS_ONCE(), the compiler is within its rights to do all sorts | ||
234 | of "creative" transformations, which are covered in the Compiler | ||
235 | Barrier section. | ||
236 | |||
227 | (*) It _must_not_ be assumed that independent loads and stores will be issued | 237 | (*) It _must_not_ be assumed that independent loads and stores will be issued |
228 | in the order given. This means that for: | 238 | in the order given. This means that for: |
229 | 239 | ||
@@ -371,33 +381,44 @@ Memory barriers come in four basic varieties: | |||
371 | 381 | ||
372 | And a couple of implicit varieties: | 382 | And a couple of implicit varieties: |
373 | 383 | ||
374 | (5) LOCK operations. | 384 | (5) ACQUIRE operations. |
375 | 385 | ||
376 | This acts as a one-way permeable barrier. It guarantees that all memory | 386 | This acts as a one-way permeable barrier. It guarantees that all memory |
377 | operations after the LOCK operation will appear to happen after the LOCK | 387 | operations after the ACQUIRE operation will appear to happen after the |
378 | operation with respect to the other components of the system. | 388 | ACQUIRE operation with respect to the other components of the system. |
389 | ACQUIRE operations include LOCK operations and smp_load_acquire() | ||
390 | operations. | ||
379 | 391 | ||
380 | Memory operations that occur before a LOCK operation may appear to happen | 392 | Memory operations that occur before an ACQUIRE operation may appear to |
381 | after it completes. | 393 | happen after it completes. |
382 | 394 | ||
383 | A LOCK operation should almost always be paired with an UNLOCK operation. | 395 | An ACQUIRE operation should almost always be paired with a RELEASE |
396 | operation. | ||
384 | 397 | ||
385 | 398 | ||
386 | (6) UNLOCK operations. | 399 | (6) RELEASE operations. |
387 | 400 | ||
388 | This also acts as a one-way permeable barrier. It guarantees that all | 401 | This also acts as a one-way permeable barrier. It guarantees that all |
389 | memory operations before the UNLOCK operation will appear to happen before | 402 | memory operations before the RELEASE operation will appear to happen |
390 | the UNLOCK operation with respect to the other components of the system. | 403 | before the RELEASE operation with respect to the other components of the |
404 | system. RELEASE operations include UNLOCK operations and | ||
405 | smp_store_release() operations. | ||
391 | 406 | ||
392 | Memory operations that occur after an UNLOCK operation may appear to | 407 | Memory operations that occur after a RELEASE operation may appear to |
393 | happen before it completes. | 408 | happen before it completes. |
394 | 409 | ||
395 | LOCK and UNLOCK operations are guaranteed to appear with respect to each | 410 | The use of ACQUIRE and RELEASE operations generally precludes the need |
396 | other strictly in the order specified. | 411 | for other sorts of memory barrier (but note the exceptions mentioned in |
412 | the subsection "MMIO write barrier"). In addition, a RELEASE+ACQUIRE | ||
413 | pair is -not- guaranteed to act as a full memory barrier. However, after | ||
414 | an ACQUIRE on a given variable, all memory accesses preceding any prior | ||
415 | RELEASE on that same variable are guaranteed to be visible. In other | ||
416 | words, within a given variable's critical section, all accesses of all | ||
417 | previous critical sections for that variable are guaranteed to have | ||
418 | completed. | ||
397 | 419 | ||
398 | The use of LOCK and UNLOCK operations generally precludes the need for | 420 | This means that ACQUIRE acts as a minimal "acquire" operation and |
399 | other sorts of memory barrier (but note the exceptions mentioned in the | 421 | RELEASE acts as a minimal "release" operation. |
400 | subsection "MMIO write barrier"). | ||
401 | 422 | ||
402 | 423 | ||
403 | Memory barriers are only required where there's a possibility of interaction | 424 | Memory barriers are only required where there's a possibility of interaction |
@@ -450,14 +471,14 @@ The usage requirements of data dependency barriers are a little subtle, and | |||
450 | it's not always obvious that they're needed. To illustrate, consider the | 471 | it's not always obvious that they're needed. To illustrate, consider the |
451 | following sequence of events: | 472 | following sequence of events: |
452 | 473 | ||
453 | CPU 1 CPU 2 | 474 | CPU 1 CPU 2 |
454 | =============== =============== | 475 | =============== =============== |
455 | { A == 1, B == 2, C = 3, P == &A, Q == &C } | 476 | { A == 1, B == 2, C = 3, P == &A, Q == &C } |
456 | B = 4; | 477 | B = 4; |
457 | <write barrier> | 478 | <write barrier> |
458 | P = &B | 479 | ACCESS_ONCE(P) = &B |
459 | Q = P; | 480 | Q = ACCESS_ONCE(P); |
460 | D = *Q; | 481 | D = *Q; |
461 | 482 | ||
462 | There's a clear data dependency here, and it would seem that by the end of the | 483 | There's a clear data dependency here, and it would seem that by the end of the |
463 | sequence, Q must be either &A or &B, and that: | 484 | sequence, Q must be either &A or &B, and that: |
@@ -477,15 +498,15 @@ Alpha). | |||
477 | To deal with this, a data dependency barrier or better must be inserted | 498 | To deal with this, a data dependency barrier or better must be inserted |
478 | between the address load and the data load: | 499 | between the address load and the data load: |
479 | 500 | ||
480 | CPU 1 CPU 2 | 501 | CPU 1 CPU 2 |
481 | =============== =============== | 502 | =============== =============== |
482 | { A == 1, B == 2, C = 3, P == &A, Q == &C } | 503 | { A == 1, B == 2, C = 3, P == &A, Q == &C } |
483 | B = 4; | 504 | B = 4; |
484 | <write barrier> | 505 | <write barrier> |
485 | P = &B | 506 | ACCESS_ONCE(P) = &B |
486 | Q = P; | 507 | Q = ACCESS_ONCE(P); |
487 | <data dependency barrier> | 508 | <data dependency barrier> |
488 | D = *Q; | 509 | D = *Q; |
489 | 510 | ||
490 | This enforces the occurrence of one of the two implications, and prevents the | 511 | This enforces the occurrence of one of the two implications, and prevents the |
491 | third possibility from arising. | 512 | third possibility from arising. |
@@ -500,25 +521,26 @@ odd-numbered bank is idle, one can see the new value of the pointer P (&B), | |||
500 | but the old value of the variable B (2). | 521 | but the old value of the variable B (2). |
501 | 522 | ||
502 | 523 | ||
503 | Another example of where data dependency barriers might by required is where a | 524 | Another example of where data dependency barriers might be required is where a |
504 | number is read from memory and then used to calculate the index for an array | 525 | number is read from memory and then used to calculate the index for an array |
505 | access: | 526 | access: |
506 | 527 | ||
507 | CPU 1 CPU 2 | 528 | CPU 1 CPU 2 |
508 | =============== =============== | 529 | =============== =============== |
509 | { M[0] == 1, M[1] == 2, M[3] = 3, P == 0, Q == 3 } | 530 | { M[0] == 1, M[1] == 2, M[3] = 3, P == 0, Q == 3 } |
510 | M[1] = 4; | 531 | M[1] = 4; |
511 | <write barrier> | 532 | <write barrier> |
512 | P = 1 | 533 | ACCESS_ONCE(P) = 1 |
513 | Q = P; | 534 | Q = ACCESS_ONCE(P); |
514 | <data dependency barrier> | 535 | <data dependency barrier> |
515 | D = M[Q]; | 536 | D = M[Q]; |
516 | 537 | ||
517 | 538 | ||
518 | The data dependency barrier is very important to the RCU system, for example. | 539 | The data dependency barrier is very important to the RCU system, |
519 | See rcu_dereference() in include/linux/rcupdate.h. This permits the current | 540 | for example. See rcu_assign_pointer() and rcu_dereference() in |
520 | target of an RCU'd pointer to be replaced with a new modified target, without | 541 | include/linux/rcupdate.h. This permits the current target of an RCU'd |
521 | the replacement target appearing to be incompletely initialised. | 542 | pointer to be replaced with a new modified target, without the replacement |
543 | target appearing to be incompletely initialised. | ||
522 | 544 | ||
523 | See also the subsection on "Cache Coherency" for a more thorough example. | 545 | See also the subsection on "Cache Coherency" for a more thorough example. |
524 | 546 | ||
@@ -530,24 +552,190 @@ A control dependency requires a full read memory barrier, not simply a data | |||
530 | dependency barrier to make it work correctly. Consider the following bit of | 552 | dependency barrier to make it work correctly. Consider the following bit of |
531 | code: | 553 | code: |
532 | 554 | ||
533 | q = &a; | 555 | q = ACCESS_ONCE(a); |
534 | if (p) { | 556 | if (q) { |
535 | <data dependency barrier> | 557 | <data dependency barrier> /* BUG: No data dependency!!! */ |
536 | q = &b; | 558 | p = ACCESS_ONCE(b); |
537 | } | 559 | } |
538 | x = *q; | ||
539 | 560 | ||
540 | This will not have the desired effect because there is no actual data | 561 | This will not have the desired effect because there is no actual data |
541 | dependency, but rather a control dependency that the CPU may short-circuit by | 562 | dependency, but rather a control dependency that the CPU may short-circuit |
542 | attempting to predict the outcome in advance. In such a case what's actually | 563 | by attempting to predict the outcome in advance, so that other CPUs see |
543 | required is: | 564 | the load from b as having happened before the load from a. In such a |
565 | case what's actually required is: | ||
544 | 566 | ||
545 | q = &a; | 567 | q = ACCESS_ONCE(a); |
546 | if (p) { | 568 | if (q) { |
547 | <read barrier> | 569 | <read barrier> |
548 | q = &b; | 570 | p = ACCESS_ONCE(b); |
571 | } | ||
572 | |||
573 | However, stores are not speculated. This means that ordering -is- provided | ||
574 | in the following example: | ||
575 | |||
576 | q = ACCESS_ONCE(a); | ||
577 | if (ACCESS_ONCE(q)) { | ||
578 | ACCESS_ONCE(b) = p; | ||
579 | } | ||
580 | |||
581 | Please note that ACCESS_ONCE() is not optional! Without the ACCESS_ONCE(), | ||
582 | the compiler is within its rights to transform this example: | ||
583 | |||
584 | q = a; | ||
585 | if (q) { | ||
586 | b = p; /* BUG: Compiler can reorder!!! */ | ||
587 | do_something(); | ||
588 | } else { | ||
589 | b = p; /* BUG: Compiler can reorder!!! */ | ||
590 | do_something_else(); | ||
591 | } | ||
592 | |||
593 | into this, which of course defeats the ordering: | ||
594 | |||
595 | b = p; | ||
596 | q = a; | ||
597 | if (q) | ||
598 | do_something(); | ||
599 | else | ||
600 | do_something_else(); | ||
601 | |||
602 | Worse yet, if the compiler is able to prove (say) that the value of | ||
603 | variable 'a' is always non-zero, it would be well within its rights | ||
604 | to optimize the original example by eliminating the "if" statement | ||
605 | as follows: | ||
606 | |||
607 | q = a; | ||
608 | b = p; /* BUG: Compiler can reorder!!! */ | ||
609 | do_something(); | ||
610 | |||
611 | The solution is again ACCESS_ONCE(), which preserves the ordering between | ||
612 | the load from variable 'a' and the store to variable 'b': | ||
613 | |||
614 | q = ACCESS_ONCE(a); | ||
615 | if (q) { | ||
616 | ACCESS_ONCE(b) = p; | ||
617 | do_something(); | ||
618 | } else { | ||
619 | ACCESS_ONCE(b) = p; | ||
620 | do_something_else(); | ||
621 | } | ||
622 | |||
623 | You could also use barrier() to prevent the compiler from moving | ||
624 | the stores to variable 'b', but barrier() would not prevent the | ||
625 | compiler from proving to itself that a==1 always, so ACCESS_ONCE() | ||
626 | is also needed. | ||
627 | |||
628 | It is important to note that control dependencies absolutely require a | ||
629 | a conditional. For example, the following "optimized" version of | ||
630 | the above example breaks ordering: | ||
631 | |||
632 | q = ACCESS_ONCE(a); | ||
633 | ACCESS_ONCE(b) = p; /* BUG: No ordering vs. load from a!!! */ | ||
634 | if (q) { | ||
635 | /* ACCESS_ONCE(b) = p; -- moved up, BUG!!! */ | ||
636 | do_something(); | ||
637 | } else { | ||
638 | /* ACCESS_ONCE(b) = p; -- moved up, BUG!!! */ | ||
639 | do_something_else(); | ||
549 | } | 640 | } |
550 | x = *q; | 641 | |
642 | It is of course legal for the prior load to be part of the conditional, | ||
643 | for example, as follows: | ||
644 | |||
645 | if (ACCESS_ONCE(a) > 0) { | ||
646 | ACCESS_ONCE(b) = q / 2; | ||
647 | do_something(); | ||
648 | } else { | ||
649 | ACCESS_ONCE(b) = q / 3; | ||
650 | do_something_else(); | ||
651 | } | ||
652 | |||
653 | This will again ensure that the load from variable 'a' is ordered before the | ||
654 | stores to variable 'b'. | ||
655 | |||
656 | In addition, you need to be careful what you do with the local variable 'q', | ||
657 | otherwise the compiler might be able to guess the value and again remove | ||
658 | the needed conditional. For example: | ||
659 | |||
660 | q = ACCESS_ONCE(a); | ||
661 | if (q % MAX) { | ||
662 | ACCESS_ONCE(b) = p; | ||
663 | do_something(); | ||
664 | } else { | ||
665 | ACCESS_ONCE(b) = p; | ||
666 | do_something_else(); | ||
667 | } | ||
668 | |||
669 | If MAX is defined to be 1, then the compiler knows that (q % MAX) is | ||
670 | equal to zero, in which case the compiler is within its rights to | ||
671 | transform the above code into the following: | ||
672 | |||
673 | q = ACCESS_ONCE(a); | ||
674 | ACCESS_ONCE(b) = p; | ||
675 | do_something_else(); | ||
676 | |||
677 | This transformation loses the ordering between the load from variable 'a' | ||
678 | and the store to variable 'b'. If you are relying on this ordering, you | ||
679 | should do something like the following: | ||
680 | |||
681 | q = ACCESS_ONCE(a); | ||
682 | BUILD_BUG_ON(MAX <= 1); /* Order load from a with store to b. */ | ||
683 | if (q % MAX) { | ||
684 | ACCESS_ONCE(b) = p; | ||
685 | do_something(); | ||
686 | } else { | ||
687 | ACCESS_ONCE(b) = p; | ||
688 | do_something_else(); | ||
689 | } | ||
690 | |||
691 | Finally, control dependencies do -not- provide transitivity. This is | ||
692 | demonstrated by two related examples: | ||
693 | |||
694 | CPU 0 CPU 1 | ||
695 | ===================== ===================== | ||
696 | r1 = ACCESS_ONCE(x); r2 = ACCESS_ONCE(y); | ||
697 | if (r1 >= 0) if (r2 >= 0) | ||
698 | ACCESS_ONCE(y) = 1; ACCESS_ONCE(x) = 1; | ||
699 | |||
700 | assert(!(r1 == 1 && r2 == 1)); | ||
701 | |||
702 | The above two-CPU example will never trigger the assert(). However, | ||
703 | if control dependencies guaranteed transitivity (which they do not), | ||
704 | then adding the following two CPUs would guarantee a related assertion: | ||
705 | |||
706 | CPU 2 CPU 3 | ||
707 | ===================== ===================== | ||
708 | ACCESS_ONCE(x) = 2; ACCESS_ONCE(y) = 2; | ||
709 | |||
710 | assert(!(r1 == 2 && r2 == 2 && x == 1 && y == 1)); /* FAILS!!! */ | ||
711 | |||
712 | But because control dependencies do -not- provide transitivity, the | ||
713 | above assertion can fail after the combined four-CPU example completes. | ||
714 | If you need the four-CPU example to provide ordering, you will need | ||
715 | smp_mb() between the loads and stores in the CPU 0 and CPU 1 code fragments. | ||
716 | |||
717 | In summary: | ||
718 | |||
719 | (*) Control dependencies can order prior loads against later stores. | ||
720 | However, they do -not- guarantee any other sort of ordering: | ||
721 | Not prior loads against later loads, nor prior stores against | ||
722 | later anything. If you need these other forms of ordering, | ||
723 | use smb_rmb(), smp_wmb(), or, in the case of prior stores and | ||
724 | later loads, smp_mb(). | ||
725 | |||
726 | (*) Control dependencies require at least one run-time conditional | ||
727 | between the prior load and the subsequent store. If the compiler | ||
728 | is able to optimize the conditional away, it will have also | ||
729 | optimized away the ordering. Careful use of ACCESS_ONCE() can | ||
730 | help to preserve the needed conditional. | ||
731 | |||
732 | (*) Control dependencies require that the compiler avoid reordering the | ||
733 | dependency into nonexistence. Careful use of ACCESS_ONCE() or | ||
734 | barrier() can help to preserve your control dependency. Please | ||
735 | see the Compiler Barrier section for more information. | ||
736 | |||
737 | (*) Control dependencies do -not- provide transitivity. If you | ||
738 | need transitivity, use smp_mb(). | ||
551 | 739 | ||
552 | 740 | ||
553 | SMP BARRIER PAIRING | 741 | SMP BARRIER PAIRING |
@@ -561,23 +749,23 @@ barrier, though a general barrier would also be viable. Similarly a read | |||
561 | barrier or a data dependency barrier should always be paired with at least an | 749 | barrier or a data dependency barrier should always be paired with at least an |
562 | write barrier, though, again, a general barrier is viable: | 750 | write barrier, though, again, a general barrier is viable: |
563 | 751 | ||
564 | CPU 1 CPU 2 | 752 | CPU 1 CPU 2 |
565 | =============== =============== | 753 | =============== =============== |
566 | a = 1; | 754 | ACCESS_ONCE(a) = 1; |
567 | <write barrier> | 755 | <write barrier> |
568 | b = 2; x = b; | 756 | ACCESS_ONCE(b) = 2; x = ACCESS_ONCE(b); |
569 | <read barrier> | 757 | <read barrier> |
570 | y = a; | 758 | y = ACCESS_ONCE(a); |
571 | 759 | ||
572 | Or: | 760 | Or: |
573 | 761 | ||
574 | CPU 1 CPU 2 | 762 | CPU 1 CPU 2 |
575 | =============== =============================== | 763 | =============== =============================== |
576 | a = 1; | 764 | a = 1; |
577 | <write barrier> | 765 | <write barrier> |
578 | b = &a; x = b; | 766 | ACCESS_ONCE(b) = &a; x = ACCESS_ONCE(b); |
579 | <data dependency barrier> | 767 | <data dependency barrier> |
580 | y = *x; | 768 | y = *x; |
581 | 769 | ||
582 | Basically, the read barrier always has to be there, even though it can be of | 770 | Basically, the read barrier always has to be there, even though it can be of |
583 | the "weaker" type. | 771 | the "weaker" type. |
@@ -586,13 +774,13 @@ the "weaker" type. | |||
586 | match the loads after the read barrier or the data dependency barrier, and vice | 774 | match the loads after the read barrier or the data dependency barrier, and vice |
587 | versa: | 775 | versa: |
588 | 776 | ||
589 | CPU 1 CPU 2 | 777 | CPU 1 CPU 2 |
590 | =============== =============== | 778 | =================== =================== |
591 | a = 1; }---- --->{ v = c | 779 | ACCESS_ONCE(a) = 1; }---- --->{ v = ACCESS_ONCE(c); |
592 | b = 2; } \ / { w = d | 780 | ACCESS_ONCE(b) = 2; } \ / { w = ACCESS_ONCE(d); |
593 | <write barrier> \ <read barrier> | 781 | <write barrier> \ <read barrier> |
594 | c = 3; } / \ { x = a; | 782 | ACCESS_ONCE(c) = 3; } / \ { x = ACCESS_ONCE(a); |
595 | d = 4; }---- --->{ y = b; | 783 | ACCESS_ONCE(d) = 4; }---- --->{ y = ACCESS_ONCE(b); |
596 | 784 | ||
597 | 785 | ||
598 | EXAMPLES OF MEMORY BARRIER SEQUENCES | 786 | EXAMPLES OF MEMORY BARRIER SEQUENCES |
@@ -882,12 +1070,12 @@ cache it for later use. | |||
882 | 1070 | ||
883 | Consider: | 1071 | Consider: |
884 | 1072 | ||
885 | CPU 1 CPU 2 | 1073 | CPU 1 CPU 2 |
886 | ======================= ======================= | 1074 | ======================= ======================= |
887 | LOAD B | 1075 | LOAD B |
888 | DIVIDE } Divide instructions generally | 1076 | DIVIDE } Divide instructions generally |
889 | DIVIDE } take a long time to perform | 1077 | DIVIDE } take a long time to perform |
890 | LOAD A | 1078 | LOAD A |
891 | 1079 | ||
892 | Which might appear as this: | 1080 | Which might appear as this: |
893 | 1081 | ||
@@ -910,13 +1098,13 @@ Which might appear as this: | |||
910 | Placing a read barrier or a data dependency barrier just before the second | 1098 | Placing a read barrier or a data dependency barrier just before the second |
911 | load: | 1099 | load: |
912 | 1100 | ||
913 | CPU 1 CPU 2 | 1101 | CPU 1 CPU 2 |
914 | ======================= ======================= | 1102 | ======================= ======================= |
915 | LOAD B | 1103 | LOAD B |
916 | DIVIDE | 1104 | DIVIDE |
917 | DIVIDE | 1105 | DIVIDE |
918 | <read barrier> | 1106 | <read barrier> |
919 | LOAD A | 1107 | LOAD A |
920 | 1108 | ||
921 | will force any value speculatively obtained to be reconsidered to an extent | 1109 | will force any value speculatively obtained to be reconsidered to an extent |
922 | dependent on the type of barrier used. If there was no change made to the | 1110 | dependent on the type of barrier used. If there was no change made to the |
@@ -1042,10 +1230,277 @@ compiler from moving the memory accesses either side of it to the other side: | |||
1042 | 1230 | ||
1043 | barrier(); | 1231 | barrier(); |
1044 | 1232 | ||
1045 | This is a general barrier - lesser varieties of compiler barrier do not exist. | 1233 | This is a general barrier -- there are no read-read or write-write variants |
1234 | of barrier(). However, ACCESS_ONCE() can be thought of as a weak form | ||
1235 | for barrier() that affects only the specific accesses flagged by the | ||
1236 | ACCESS_ONCE(). | ||
1237 | |||
1238 | The barrier() function has the following effects: | ||
1239 | |||
1240 | (*) Prevents the compiler from reordering accesses following the | ||
1241 | barrier() to precede any accesses preceding the barrier(). | ||
1242 | One example use for this property is to ease communication between | ||
1243 | interrupt-handler code and the code that was interrupted. | ||
1244 | |||
1245 | (*) Within a loop, forces the compiler to load the variables used | ||
1246 | in that loop's conditional on each pass through that loop. | ||
1247 | |||
1248 | The ACCESS_ONCE() function can prevent any number of optimizations that, | ||
1249 | while perfectly safe in single-threaded code, can be fatal in concurrent | ||
1250 | code. Here are some examples of these sorts of optimizations: | ||
1251 | |||
1252 | (*) The compiler is within its rights to merge successive loads from | ||
1253 | the same variable. Such merging can cause the compiler to "optimize" | ||
1254 | the following code: | ||
1255 | |||
1256 | while (tmp = a) | ||
1257 | do_something_with(tmp); | ||
1258 | |||
1259 | into the following code, which, although in some sense legitimate | ||
1260 | for single-threaded code, is almost certainly not what the developer | ||
1261 | intended: | ||
1262 | |||
1263 | if (tmp = a) | ||
1264 | for (;;) | ||
1265 | do_something_with(tmp); | ||
1266 | |||
1267 | Use ACCESS_ONCE() to prevent the compiler from doing this to you: | ||
1268 | |||
1269 | while (tmp = ACCESS_ONCE(a)) | ||
1270 | do_something_with(tmp); | ||
1271 | |||
1272 | (*) The compiler is within its rights to reload a variable, for example, | ||
1273 | in cases where high register pressure prevents the compiler from | ||
1274 | keeping all data of interest in registers. The compiler might | ||
1275 | therefore optimize the variable 'tmp' out of our previous example: | ||
1276 | |||
1277 | while (tmp = a) | ||
1278 | do_something_with(tmp); | ||
1279 | |||
1280 | This could result in the following code, which is perfectly safe in | ||
1281 | single-threaded code, but can be fatal in concurrent code: | ||
1282 | |||
1283 | while (a) | ||
1284 | do_something_with(a); | ||
1285 | |||
1286 | For example, the optimized version of this code could result in | ||
1287 | passing a zero to do_something_with() in the case where the variable | ||
1288 | a was modified by some other CPU between the "while" statement and | ||
1289 | the call to do_something_with(). | ||
1290 | |||
1291 | Again, use ACCESS_ONCE() to prevent the compiler from doing this: | ||
1292 | |||
1293 | while (tmp = ACCESS_ONCE(a)) | ||
1294 | do_something_with(tmp); | ||
1295 | |||
1296 | Note that if the compiler runs short of registers, it might save | ||
1297 | tmp onto the stack. The overhead of this saving and later restoring | ||
1298 | is why compilers reload variables. Doing so is perfectly safe for | ||
1299 | single-threaded code, so you need to tell the compiler about cases | ||
1300 | where it is not safe. | ||
1301 | |||
1302 | (*) The compiler is within its rights to omit a load entirely if it knows | ||
1303 | what the value will be. For example, if the compiler can prove that | ||
1304 | the value of variable 'a' is always zero, it can optimize this code: | ||
1305 | |||
1306 | while (tmp = a) | ||
1307 | do_something_with(tmp); | ||
1046 | 1308 | ||
1047 | The compiler barrier has no direct effect on the CPU, which may then reorder | 1309 | Into this: |
1048 | things however it wishes. | 1310 | |
1311 | do { } while (0); | ||
1312 | |||
1313 | This transformation is a win for single-threaded code because it gets | ||
1314 | rid of a load and a branch. The problem is that the compiler will | ||
1315 | carry out its proof assuming that the current CPU is the only one | ||
1316 | updating variable 'a'. If variable 'a' is shared, then the compiler's | ||
1317 | proof will be erroneous. Use ACCESS_ONCE() to tell the compiler | ||
1318 | that it doesn't know as much as it thinks it does: | ||
1319 | |||
1320 | while (tmp = ACCESS_ONCE(a)) | ||
1321 | do_something_with(tmp); | ||
1322 | |||
1323 | But please note that the compiler is also closely watching what you | ||
1324 | do with the value after the ACCESS_ONCE(). For example, suppose you | ||
1325 | do the following and MAX is a preprocessor macro with the value 1: | ||
1326 | |||
1327 | while ((tmp = ACCESS_ONCE(a)) % MAX) | ||
1328 | do_something_with(tmp); | ||
1329 | |||
1330 | Then the compiler knows that the result of the "%" operator applied | ||
1331 | to MAX will always be zero, again allowing the compiler to optimize | ||
1332 | the code into near-nonexistence. (It will still load from the | ||
1333 | variable 'a'.) | ||
1334 | |||
1335 | (*) Similarly, the compiler is within its rights to omit a store entirely | ||
1336 | if it knows that the variable already has the value being stored. | ||
1337 | Again, the compiler assumes that the current CPU is the only one | ||
1338 | storing into the variable, which can cause the compiler to do the | ||
1339 | wrong thing for shared variables. For example, suppose you have | ||
1340 | the following: | ||
1341 | |||
1342 | a = 0; | ||
1343 | /* Code that does not store to variable a. */ | ||
1344 | a = 0; | ||
1345 | |||
1346 | The compiler sees that the value of variable 'a' is already zero, so | ||
1347 | it might well omit the second store. This would come as a fatal | ||
1348 | surprise if some other CPU might have stored to variable 'a' in the | ||
1349 | meantime. | ||
1350 | |||
1351 | Use ACCESS_ONCE() to prevent the compiler from making this sort of | ||
1352 | wrong guess: | ||
1353 | |||
1354 | ACCESS_ONCE(a) = 0; | ||
1355 | /* Code that does not store to variable a. */ | ||
1356 | ACCESS_ONCE(a) = 0; | ||
1357 | |||
1358 | (*) The compiler is within its rights to reorder memory accesses unless | ||
1359 | you tell it not to. For example, consider the following interaction | ||
1360 | between process-level code and an interrupt handler: | ||
1361 | |||
1362 | void process_level(void) | ||
1363 | { | ||
1364 | msg = get_message(); | ||
1365 | flag = true; | ||
1366 | } | ||
1367 | |||
1368 | void interrupt_handler(void) | ||
1369 | { | ||
1370 | if (flag) | ||
1371 | process_message(msg); | ||
1372 | } | ||
1373 | |||
1374 | There is nothing to prevent the the compiler from transforming | ||
1375 | process_level() to the following, in fact, this might well be a | ||
1376 | win for single-threaded code: | ||
1377 | |||
1378 | void process_level(void) | ||
1379 | { | ||
1380 | flag = true; | ||
1381 | msg = get_message(); | ||
1382 | } | ||
1383 | |||
1384 | If the interrupt occurs between these two statement, then | ||
1385 | interrupt_handler() might be passed a garbled msg. Use ACCESS_ONCE() | ||
1386 | to prevent this as follows: | ||
1387 | |||
1388 | void process_level(void) | ||
1389 | { | ||
1390 | ACCESS_ONCE(msg) = get_message(); | ||
1391 | ACCESS_ONCE(flag) = true; | ||
1392 | } | ||
1393 | |||
1394 | void interrupt_handler(void) | ||
1395 | { | ||
1396 | if (ACCESS_ONCE(flag)) | ||
1397 | process_message(ACCESS_ONCE(msg)); | ||
1398 | } | ||
1399 | |||
1400 | Note that the ACCESS_ONCE() wrappers in interrupt_handler() | ||
1401 | are needed if this interrupt handler can itself be interrupted | ||
1402 | by something that also accesses 'flag' and 'msg', for example, | ||
1403 | a nested interrupt or an NMI. Otherwise, ACCESS_ONCE() is not | ||
1404 | needed in interrupt_handler() other than for documentation purposes. | ||
1405 | (Note also that nested interrupts do not typically occur in modern | ||
1406 | Linux kernels, in fact, if an interrupt handler returns with | ||
1407 | interrupts enabled, you will get a WARN_ONCE() splat.) | ||
1408 | |||
1409 | You should assume that the compiler can move ACCESS_ONCE() past | ||
1410 | code not containing ACCESS_ONCE(), barrier(), or similar primitives. | ||
1411 | |||
1412 | This effect could also be achieved using barrier(), but ACCESS_ONCE() | ||
1413 | is more selective: With ACCESS_ONCE(), the compiler need only forget | ||
1414 | the contents of the indicated memory locations, while with barrier() | ||
1415 | the compiler must discard the value of all memory locations that | ||
1416 | it has currented cached in any machine registers. Of course, | ||
1417 | the compiler must also respect the order in which the ACCESS_ONCE()s | ||
1418 | occur, though the CPU of course need not do so. | ||
1419 | |||
1420 | (*) The compiler is within its rights to invent stores to a variable, | ||
1421 | as in the following example: | ||
1422 | |||
1423 | if (a) | ||
1424 | b = a; | ||
1425 | else | ||
1426 | b = 42; | ||
1427 | |||
1428 | The compiler might save a branch by optimizing this as follows: | ||
1429 | |||
1430 | b = 42; | ||
1431 | if (a) | ||
1432 | b = a; | ||
1433 | |||
1434 | In single-threaded code, this is not only safe, but also saves | ||
1435 | a branch. Unfortunately, in concurrent code, this optimization | ||
1436 | could cause some other CPU to see a spurious value of 42 -- even | ||
1437 | if variable 'a' was never zero -- when loading variable 'b'. | ||
1438 | Use ACCESS_ONCE() to prevent this as follows: | ||
1439 | |||
1440 | if (a) | ||
1441 | ACCESS_ONCE(b) = a; | ||
1442 | else | ||
1443 | ACCESS_ONCE(b) = 42; | ||
1444 | |||
1445 | The compiler can also invent loads. These are usually less | ||
1446 | damaging, but they can result in cache-line bouncing and thus in | ||
1447 | poor performance and scalability. Use ACCESS_ONCE() to prevent | ||
1448 | invented loads. | ||
1449 | |||
1450 | (*) For aligned memory locations whose size allows them to be accessed | ||
1451 | with a single memory-reference instruction, prevents "load tearing" | ||
1452 | and "store tearing," in which a single large access is replaced by | ||
1453 | multiple smaller accesses. For example, given an architecture having | ||
1454 | 16-bit store instructions with 7-bit immediate fields, the compiler | ||
1455 | might be tempted to use two 16-bit store-immediate instructions to | ||
1456 | implement the following 32-bit store: | ||
1457 | |||
1458 | p = 0x00010002; | ||
1459 | |||
1460 | Please note that GCC really does use this sort of optimization, | ||
1461 | which is not surprising given that it would likely take more | ||
1462 | than two instructions to build the constant and then store it. | ||
1463 | This optimization can therefore be a win in single-threaded code. | ||
1464 | In fact, a recent bug (since fixed) caused GCC to incorrectly use | ||
1465 | this optimization in a volatile store. In the absence of such bugs, | ||
1466 | use of ACCESS_ONCE() prevents store tearing in the following example: | ||
1467 | |||
1468 | ACCESS_ONCE(p) = 0x00010002; | ||
1469 | |||
1470 | Use of packed structures can also result in load and store tearing, | ||
1471 | as in this example: | ||
1472 | |||
1473 | struct __attribute__((__packed__)) foo { | ||
1474 | short a; | ||
1475 | int b; | ||
1476 | short c; | ||
1477 | }; | ||
1478 | struct foo foo1, foo2; | ||
1479 | ... | ||
1480 | |||
1481 | foo2.a = foo1.a; | ||
1482 | foo2.b = foo1.b; | ||
1483 | foo2.c = foo1.c; | ||
1484 | |||
1485 | Because there are no ACCESS_ONCE() wrappers and no volatile markings, | ||
1486 | the compiler would be well within its rights to implement these three | ||
1487 | assignment statements as a pair of 32-bit loads followed by a pair | ||
1488 | of 32-bit stores. This would result in load tearing on 'foo1.b' | ||
1489 | and store tearing on 'foo2.b'. ACCESS_ONCE() again prevents tearing | ||
1490 | in this example: | ||
1491 | |||
1492 | foo2.a = foo1.a; | ||
1493 | ACCESS_ONCE(foo2.b) = ACCESS_ONCE(foo1.b); | ||
1494 | foo2.c = foo1.c; | ||
1495 | |||
1496 | All that aside, it is never necessary to use ACCESS_ONCE() on a variable | ||
1497 | that has been marked volatile. For example, because 'jiffies' is marked | ||
1498 | volatile, it is never necessary to say ACCESS_ONCE(jiffies). The reason | ||
1499 | for this is that ACCESS_ONCE() is implemented as a volatile cast, which | ||
1500 | has no effect when its argument is already marked volatile. | ||
1501 | |||
1502 | Please note that these compiler barriers have no direct effect on the CPU, | ||
1503 | which may then reorder things however it wishes. | ||
1049 | 1504 | ||
1050 | 1505 | ||
1051 | CPU MEMORY BARRIERS | 1506 | CPU MEMORY BARRIERS |
@@ -1135,7 +1590,7 @@ There are some more advanced barrier functions: | |||
1135 | clear_bit( ... ); | 1590 | clear_bit( ... ); |
1136 | 1591 | ||
1137 | This prevents memory operations before the clear leaking to after it. See | 1592 | This prevents memory operations before the clear leaking to after it. See |
1138 | the subsection on "Locking Functions" with reference to UNLOCK operation | 1593 | the subsection on "Locking Functions" with reference to RELEASE operation |
1139 | implications. | 1594 | implications. |
1140 | 1595 | ||
1141 | See Documentation/atomic_ops.txt for more information. See the "Atomic | 1596 | See Documentation/atomic_ops.txt for more information. See the "Atomic |
@@ -1169,8 +1624,8 @@ provide more substantial guarantees, but these may not be relied upon outside | |||
1169 | of arch specific code. | 1624 | of arch specific code. |
1170 | 1625 | ||
1171 | 1626 | ||
1172 | LOCKING FUNCTIONS | 1627 | ACQUIRING FUNCTIONS |
1173 | ----------------- | 1628 | ------------------- |
1174 | 1629 | ||
1175 | The Linux kernel has a number of locking constructs: | 1630 | The Linux kernel has a number of locking constructs: |
1176 | 1631 | ||
@@ -1181,65 +1636,107 @@ The Linux kernel has a number of locking constructs: | |||
1181 | (*) R/W semaphores | 1636 | (*) R/W semaphores |
1182 | (*) RCU | 1637 | (*) RCU |
1183 | 1638 | ||
1184 | In all cases there are variants on "LOCK" operations and "UNLOCK" operations | 1639 | In all cases there are variants on "ACQUIRE" operations and "RELEASE" operations |
1185 | for each construct. These operations all imply certain barriers: | 1640 | for each construct. These operations all imply certain barriers: |
1186 | 1641 | ||
1187 | (1) LOCK operation implication: | 1642 | (1) ACQUIRE operation implication: |
1188 | 1643 | ||
1189 | Memory operations issued after the LOCK will be completed after the LOCK | 1644 | Memory operations issued after the ACQUIRE will be completed after the |
1190 | operation has completed. | 1645 | ACQUIRE operation has completed. |
1191 | 1646 | ||
1192 | Memory operations issued before the LOCK may be completed after the LOCK | 1647 | Memory operations issued before the ACQUIRE may be completed after the |
1193 | operation has completed. | 1648 | ACQUIRE operation has completed. An smp_mb__before_spinlock(), combined |
1649 | with a following ACQUIRE, orders prior loads against subsequent stores and | ||
1650 | stores and prior stores against subsequent stores. Note that this is | ||
1651 | weaker than smp_mb()! The smp_mb__before_spinlock() primitive is free on | ||
1652 | many architectures. | ||
1194 | 1653 | ||
1195 | (2) UNLOCK operation implication: | 1654 | (2) RELEASE operation implication: |
1196 | 1655 | ||
1197 | Memory operations issued before the UNLOCK will be completed before the | 1656 | Memory operations issued before the RELEASE will be completed before the |
1198 | UNLOCK operation has completed. | 1657 | RELEASE operation has completed. |
1199 | 1658 | ||
1200 | Memory operations issued after the UNLOCK may be completed before the | 1659 | Memory operations issued after the RELEASE may be completed before the |
1201 | UNLOCK operation has completed. | 1660 | RELEASE operation has completed. |
1202 | 1661 | ||
1203 | (3) LOCK vs LOCK implication: | 1662 | (3) ACQUIRE vs ACQUIRE implication: |
1204 | 1663 | ||
1205 | All LOCK operations issued before another LOCK operation will be completed | 1664 | All ACQUIRE operations issued before another ACQUIRE operation will be |
1206 | before that LOCK operation. | 1665 | completed before that ACQUIRE operation. |
1207 | 1666 | ||
1208 | (4) LOCK vs UNLOCK implication: | 1667 | (4) ACQUIRE vs RELEASE implication: |
1209 | 1668 | ||
1210 | All LOCK operations issued before an UNLOCK operation will be completed | 1669 | All ACQUIRE operations issued before a RELEASE operation will be |
1211 | before the UNLOCK operation. | 1670 | completed before the RELEASE operation. |
1212 | 1671 | ||
1213 | All UNLOCK operations issued before a LOCK operation will be completed | 1672 | (5) Failed conditional ACQUIRE implication: |
1214 | before the LOCK operation. | ||
1215 | 1673 | ||
1216 | (5) Failed conditional LOCK implication: | 1674 | Certain locking variants of the ACQUIRE operation may fail, either due to |
1217 | 1675 | being unable to get the lock immediately, or due to receiving an unblocked | |
1218 | Certain variants of the LOCK operation may fail, either due to being | ||
1219 | unable to get the lock immediately, or due to receiving an unblocked | ||
1220 | signal whilst asleep waiting for the lock to become available. Failed | 1676 | signal whilst asleep waiting for the lock to become available. Failed |
1221 | locks do not imply any sort of barrier. | 1677 | locks do not imply any sort of barrier. |
1222 | 1678 | ||
1223 | Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is | 1679 | [!] Note: one of the consequences of lock ACQUIREs and RELEASEs being only |
1224 | equivalent to a full barrier, but a LOCK followed by an UNLOCK is not. | 1680 | one-way barriers is that the effects of instructions outside of a critical |
1225 | 1681 | section may seep into the inside of the critical section. | |
1226 | [!] Note: one of the consequences of LOCKs and UNLOCKs being only one-way | ||
1227 | barriers is that the effects of instructions outside of a critical section | ||
1228 | may seep into the inside of the critical section. | ||
1229 | 1682 | ||
1230 | A LOCK followed by an UNLOCK may not be assumed to be full memory barrier | 1683 | An ACQUIRE followed by a RELEASE may not be assumed to be full memory barrier |
1231 | because it is possible for an access preceding the LOCK to happen after the | 1684 | because it is possible for an access preceding the ACQUIRE to happen after the |
1232 | LOCK, and an access following the UNLOCK to happen before the UNLOCK, and the | 1685 | ACQUIRE, and an access following the RELEASE to happen before the RELEASE, and |
1233 | two accesses can themselves then cross: | 1686 | the two accesses can themselves then cross: |
1234 | 1687 | ||
1235 | *A = a; | 1688 | *A = a; |
1236 | LOCK | 1689 | ACQUIRE M |
1237 | UNLOCK | 1690 | RELEASE M |
1238 | *B = b; | 1691 | *B = b; |
1239 | 1692 | ||
1240 | may occur as: | 1693 | may occur as: |
1241 | 1694 | ||
1242 | LOCK, STORE *B, STORE *A, UNLOCK | 1695 | ACQUIRE M, STORE *B, STORE *A, RELEASE M |
1696 | |||
1697 | This same reordering can of course occur if the lock's ACQUIRE and RELEASE are | ||
1698 | to the same lock variable, but only from the perspective of another CPU not | ||
1699 | holding that lock. | ||
1700 | |||
1701 | In short, a RELEASE followed by an ACQUIRE may -not- be assumed to be a full | ||
1702 | memory barrier because it is possible for a preceding RELEASE to pass a | ||
1703 | later ACQUIRE from the viewpoint of the CPU, but not from the viewpoint | ||
1704 | of the compiler. Note that deadlocks cannot be introduced by this | ||
1705 | interchange because if such a deadlock threatened, the RELEASE would | ||
1706 | simply complete. | ||
1707 | |||
1708 | If it is necessary for a RELEASE-ACQUIRE pair to produce a full barrier, the | ||
1709 | ACQUIRE can be followed by an smp_mb__after_unlock_lock() invocation. This | ||
1710 | will produce a full barrier if either (a) the RELEASE and the ACQUIRE are | ||
1711 | executed by the same CPU or task, or (b) the RELEASE and ACQUIRE act on the | ||
1712 | same variable. The smp_mb__after_unlock_lock() primitive is free on many | ||
1713 | architectures. Without smp_mb__after_unlock_lock(), the critical sections | ||
1714 | corresponding to the RELEASE and the ACQUIRE can cross: | ||
1715 | |||
1716 | *A = a; | ||
1717 | RELEASE M | ||
1718 | ACQUIRE N | ||
1719 | *B = b; | ||
1720 | |||
1721 | could occur as: | ||
1722 | |||
1723 | ACQUIRE N, STORE *B, STORE *A, RELEASE M | ||
1724 | |||
1725 | With smp_mb__after_unlock_lock(), they cannot, so that: | ||
1726 | |||
1727 | *A = a; | ||
1728 | RELEASE M | ||
1729 | ACQUIRE N | ||
1730 | smp_mb__after_unlock_lock(); | ||
1731 | *B = b; | ||
1732 | |||
1733 | will always occur as either of the following: | ||
1734 | |||
1735 | STORE *A, RELEASE, ACQUIRE, STORE *B | ||
1736 | STORE *A, ACQUIRE, RELEASE, STORE *B | ||
1737 | |||
1738 | If the RELEASE and ACQUIRE were instead both operating on the same lock | ||
1739 | variable, only the first of these two alternatives can occur. | ||
1243 | 1740 | ||
1244 | Locks and semaphores may not provide any guarantee of ordering on UP compiled | 1741 | Locks and semaphores may not provide any guarantee of ordering on UP compiled |
1245 | systems, and so cannot be counted on in such a situation to actually achieve | 1742 | systems, and so cannot be counted on in such a situation to actually achieve |
@@ -1253,33 +1750,33 @@ As an example, consider the following: | |||
1253 | 1750 | ||
1254 | *A = a; | 1751 | *A = a; |
1255 | *B = b; | 1752 | *B = b; |
1256 | LOCK | 1753 | ACQUIRE |
1257 | *C = c; | 1754 | *C = c; |
1258 | *D = d; | 1755 | *D = d; |
1259 | UNLOCK | 1756 | RELEASE |
1260 | *E = e; | 1757 | *E = e; |
1261 | *F = f; | 1758 | *F = f; |
1262 | 1759 | ||
1263 | The following sequence of events is acceptable: | 1760 | The following sequence of events is acceptable: |
1264 | 1761 | ||
1265 | LOCK, {*F,*A}, *E, {*C,*D}, *B, UNLOCK | 1762 | ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE |
1266 | 1763 | ||
1267 | [+] Note that {*F,*A} indicates a combined access. | 1764 | [+] Note that {*F,*A} indicates a combined access. |
1268 | 1765 | ||
1269 | But none of the following are: | 1766 | But none of the following are: |
1270 | 1767 | ||
1271 | {*F,*A}, *B, LOCK, *C, *D, UNLOCK, *E | 1768 | {*F,*A}, *B, ACQUIRE, *C, *D, RELEASE, *E |
1272 | *A, *B, *C, LOCK, *D, UNLOCK, *E, *F | 1769 | *A, *B, *C, ACQUIRE, *D, RELEASE, *E, *F |
1273 | *A, *B, LOCK, *C, UNLOCK, *D, *E, *F | 1770 | *A, *B, ACQUIRE, *C, RELEASE, *D, *E, *F |
1274 | *B, LOCK, *C, *D, UNLOCK, {*F,*A}, *E | 1771 | *B, ACQUIRE, *C, *D, RELEASE, {*F,*A}, *E |
1275 | 1772 | ||
1276 | 1773 | ||
1277 | 1774 | ||
1278 | INTERRUPT DISABLING FUNCTIONS | 1775 | INTERRUPT DISABLING FUNCTIONS |
1279 | ----------------------------- | 1776 | ----------------------------- |
1280 | 1777 | ||
1281 | Functions that disable interrupts (LOCK equivalent) and enable interrupts | 1778 | Functions that disable interrupts (ACQUIRE equivalent) and enable interrupts |
1282 | (UNLOCK equivalent) will act as compiler barriers only. So if memory or I/O | 1779 | (RELEASE equivalent) will act as compiler barriers only. So if memory or I/O |
1283 | barriers are required in such a situation, they must be provided from some | 1780 | barriers are required in such a situation, they must be provided from some |
1284 | other means. | 1781 | other means. |
1285 | 1782 | ||
@@ -1418,75 +1915,81 @@ Other functions that imply barriers: | |||
1418 | (*) schedule() and similar imply full memory barriers. | 1915 | (*) schedule() and similar imply full memory barriers. |
1419 | 1916 | ||
1420 | 1917 | ||
1421 | ================================= | 1918 | =================================== |
1422 | INTER-CPU LOCKING BARRIER EFFECTS | 1919 | INTER-CPU ACQUIRING BARRIER EFFECTS |
1423 | ================================= | 1920 | =================================== |
1424 | 1921 | ||
1425 | On SMP systems locking primitives give a more substantial form of barrier: one | 1922 | On SMP systems locking primitives give a more substantial form of barrier: one |
1426 | that does affect memory access ordering on other CPUs, within the context of | 1923 | that does affect memory access ordering on other CPUs, within the context of |
1427 | conflict on any particular lock. | 1924 | conflict on any particular lock. |
1428 | 1925 | ||
1429 | 1926 | ||
1430 | LOCKS VS MEMORY ACCESSES | 1927 | ACQUIRES VS MEMORY ACCESSES |
1431 | ------------------------ | 1928 | --------------------------- |
1432 | 1929 | ||
1433 | Consider the following: the system has a pair of spinlocks (M) and (Q), and | 1930 | Consider the following: the system has a pair of spinlocks (M) and (Q), and |
1434 | three CPUs; then should the following sequence of events occur: | 1931 | three CPUs; then should the following sequence of events occur: |
1435 | 1932 | ||
1436 | CPU 1 CPU 2 | 1933 | CPU 1 CPU 2 |
1437 | =============================== =============================== | 1934 | =============================== =============================== |
1438 | *A = a; *E = e; | 1935 | ACCESS_ONCE(*A) = a; ACCESS_ONCE(*E) = e; |
1439 | LOCK M LOCK Q | 1936 | ACQUIRE M ACQUIRE Q |
1440 | *B = b; *F = f; | 1937 | ACCESS_ONCE(*B) = b; ACCESS_ONCE(*F) = f; |
1441 | *C = c; *G = g; | 1938 | ACCESS_ONCE(*C) = c; ACCESS_ONCE(*G) = g; |
1442 | UNLOCK M UNLOCK Q | 1939 | RELEASE M RELEASE Q |
1443 | *D = d; *H = h; | 1940 | ACCESS_ONCE(*D) = d; ACCESS_ONCE(*H) = h; |
1444 | 1941 | ||
1445 | Then there is no guarantee as to what order CPU 3 will see the accesses to *A | 1942 | Then there is no guarantee as to what order CPU 3 will see the accesses to *A |
1446 | through *H occur in, other than the constraints imposed by the separate locks | 1943 | through *H occur in, other than the constraints imposed by the separate locks |
1447 | on the separate CPUs. It might, for example, see: | 1944 | on the separate CPUs. It might, for example, see: |
1448 | 1945 | ||
1449 | *E, LOCK M, LOCK Q, *G, *C, *F, *A, *B, UNLOCK Q, *D, *H, UNLOCK M | 1946 | *E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M |
1450 | 1947 | ||
1451 | But it won't see any of: | 1948 | But it won't see any of: |
1452 | 1949 | ||
1453 | *B, *C or *D preceding LOCK M | 1950 | *B, *C or *D preceding ACQUIRE M |
1454 | *A, *B or *C following UNLOCK M | 1951 | *A, *B or *C following RELEASE M |
1455 | *F, *G or *H preceding LOCK Q | 1952 | *F, *G or *H preceding ACQUIRE Q |
1456 | *E, *F or *G following UNLOCK Q | 1953 | *E, *F or *G following RELEASE Q |
1457 | 1954 | ||
1458 | 1955 | ||
1459 | However, if the following occurs: | 1956 | However, if the following occurs: |
1460 | 1957 | ||
1461 | CPU 1 CPU 2 | 1958 | CPU 1 CPU 2 |
1462 | =============================== =============================== | 1959 | =============================== =============================== |
1463 | *A = a; | 1960 | ACCESS_ONCE(*A) = a; |
1464 | LOCK M [1] | 1961 | ACQUIRE M [1] |
1465 | *B = b; | 1962 | ACCESS_ONCE(*B) = b; |
1466 | *C = c; | 1963 | ACCESS_ONCE(*C) = c; |
1467 | UNLOCK M [1] | 1964 | RELEASE M [1] |
1468 | *D = d; *E = e; | 1965 | ACCESS_ONCE(*D) = d; ACCESS_ONCE(*E) = e; |
1469 | LOCK M [2] | 1966 | ACQUIRE M [2] |
1470 | *F = f; | 1967 | smp_mb__after_unlock_lock(); |
1471 | *G = g; | 1968 | ACCESS_ONCE(*F) = f; |
1472 | UNLOCK M [2] | 1969 | ACCESS_ONCE(*G) = g; |
1473 | *H = h; | 1970 | RELEASE M [2] |
1971 | ACCESS_ONCE(*H) = h; | ||
1474 | 1972 | ||
1475 | CPU 3 might see: | 1973 | CPU 3 might see: |
1476 | 1974 | ||
1477 | *E, LOCK M [1], *C, *B, *A, UNLOCK M [1], | 1975 | *E, ACQUIRE M [1], *C, *B, *A, RELEASE M [1], |
1478 | LOCK M [2], *H, *F, *G, UNLOCK M [2], *D | 1976 | ACQUIRE M [2], *H, *F, *G, RELEASE M [2], *D |
1479 | 1977 | ||
1480 | But assuming CPU 1 gets the lock first, CPU 3 won't see any of: | 1978 | But assuming CPU 1 gets the lock first, CPU 3 won't see any of: |
1481 | 1979 | ||
1482 | *B, *C, *D, *F, *G or *H preceding LOCK M [1] | 1980 | *B, *C, *D, *F, *G or *H preceding ACQUIRE M [1] |
1483 | *A, *B or *C following UNLOCK M [1] | 1981 | *A, *B or *C following RELEASE M [1] |
1484 | *F, *G or *H preceding LOCK M [2] | 1982 | *F, *G or *H preceding ACQUIRE M [2] |
1485 | *A, *B, *C, *E, *F or *G following UNLOCK M [2] | 1983 | *A, *B, *C, *E, *F or *G following RELEASE M [2] |
1486 | 1984 | ||
1985 | Note that the smp_mb__after_unlock_lock() is critically important | ||
1986 | here: Without it CPU 3 might see some of the above orderings. | ||
1987 | Without smp_mb__after_unlock_lock(), the accesses are not guaranteed | ||
1988 | to be seen in order unless CPU 3 holds lock M. | ||
1487 | 1989 | ||
1488 | LOCKS VS I/O ACCESSES | 1990 | |
1489 | --------------------- | 1991 | ACQUIRES VS I/O ACCESSES |
1992 | ------------------------ | ||
1490 | 1993 | ||
1491 | Under certain circumstances (especially involving NUMA), I/O accesses within | 1994 | Under certain circumstances (especially involving NUMA), I/O accesses within |
1492 | two spinlocked sections on two different CPUs may be seen as interleaved by the | 1995 | two spinlocked sections on two different CPUs may be seen as interleaved by the |
@@ -1687,28 +2190,30 @@ explicit lock operations, described later). These include: | |||
1687 | 2190 | ||
1688 | xchg(); | 2191 | xchg(); |
1689 | cmpxchg(); | 2192 | cmpxchg(); |
1690 | atomic_xchg(); | 2193 | atomic_xchg(); atomic_long_xchg(); |
1691 | atomic_cmpxchg(); | 2194 | atomic_cmpxchg(); atomic_long_cmpxchg(); |
1692 | atomic_inc_return(); | 2195 | atomic_inc_return(); atomic_long_inc_return(); |
1693 | atomic_dec_return(); | 2196 | atomic_dec_return(); atomic_long_dec_return(); |
1694 | atomic_add_return(); | 2197 | atomic_add_return(); atomic_long_add_return(); |
1695 | atomic_sub_return(); | 2198 | atomic_sub_return(); atomic_long_sub_return(); |
1696 | atomic_inc_and_test(); | 2199 | atomic_inc_and_test(); atomic_long_inc_and_test(); |
1697 | atomic_dec_and_test(); | 2200 | atomic_dec_and_test(); atomic_long_dec_and_test(); |
1698 | atomic_sub_and_test(); | 2201 | atomic_sub_and_test(); atomic_long_sub_and_test(); |
1699 | atomic_add_negative(); | 2202 | atomic_add_negative(); atomic_long_add_negative(); |
1700 | atomic_add_unless(); /* when succeeds (returns 1) */ | ||
1701 | test_and_set_bit(); | 2203 | test_and_set_bit(); |
1702 | test_and_clear_bit(); | 2204 | test_and_clear_bit(); |
1703 | test_and_change_bit(); | 2205 | test_and_change_bit(); |
1704 | 2206 | ||
1705 | These are used for such things as implementing LOCK-class and UNLOCK-class | 2207 | /* when succeeds (returns 1) */ |
2208 | atomic_add_unless(); atomic_long_add_unless(); | ||
2209 | |||
2210 | These are used for such things as implementing ACQUIRE-class and RELEASE-class | ||
1706 | operations and adjusting reference counters towards object destruction, and as | 2211 | operations and adjusting reference counters towards object destruction, and as |
1707 | such the implicit memory barrier effects are necessary. | 2212 | such the implicit memory barrier effects are necessary. |
1708 | 2213 | ||
1709 | 2214 | ||
1710 | The following operations are potential problems as they do _not_ imply memory | 2215 | The following operations are potential problems as they do _not_ imply memory |
1711 | barriers, but might be used for implementing such things as UNLOCK-class | 2216 | barriers, but might be used for implementing such things as RELEASE-class |
1712 | operations: | 2217 | operations: |
1713 | 2218 | ||
1714 | atomic_set(); | 2219 | atomic_set(); |
@@ -1750,7 +2255,7 @@ The following operations are special locking primitives: | |||
1750 | clear_bit_unlock(); | 2255 | clear_bit_unlock(); |
1751 | __clear_bit_unlock(); | 2256 | __clear_bit_unlock(); |
1752 | 2257 | ||
1753 | These implement LOCK-class and UNLOCK-class operations. These should be used in | 2258 | These implement ACQUIRE-class and RELEASE-class operations. These should be used in |
1754 | preference to other operations when implementing locking primitives, because | 2259 | preference to other operations when implementing locking primitives, because |
1755 | their implementations can be optimised on many architectures. | 2260 | their implementations can be optimised on many architectures. |
1756 | 2261 | ||
@@ -1887,8 +2392,8 @@ functions: | |||
1887 | space should suffice for PCI. | 2392 | space should suffice for PCI. |
1888 | 2393 | ||
1889 | [*] NOTE! attempting to load from the same location as was written to may | 2394 | [*] NOTE! attempting to load from the same location as was written to may |
1890 | cause a malfunction - consider the 16550 Rx/Tx serial registers for | 2395 | cause a malfunction - consider the 16550 Rx/Tx serial registers for |
1891 | example. | 2396 | example. |
1892 | 2397 | ||
1893 | Used with prefetchable I/O memory, an mmiowb() barrier may be required to | 2398 | Used with prefetchable I/O memory, an mmiowb() barrier may be required to |
1894 | force stores to be ordered. | 2399 | force stores to be ordered. |
@@ -1955,19 +2460,19 @@ barriers for the most part act at the interface between the CPU and its cache | |||
1955 | : | 2460 | : |
1956 | +--------+ +--------+ : +--------+ +-----------+ | 2461 | +--------+ +--------+ : +--------+ +-----------+ |
1957 | | | | | : | | | | +--------+ | 2462 | | | | | : | | | | +--------+ |
1958 | | CPU | | Memory | : | CPU | | | | | | 2463 | | CPU | | Memory | : | CPU | | | | | |
1959 | | Core |--->| Access |----->| Cache |<-->| | | | | 2464 | | Core |--->| Access |----->| Cache |<-->| | | | |
1960 | | | | Queue | : | | | |--->| Memory | | 2465 | | | | Queue | : | | | |--->| Memory | |
1961 | | | | | : | | | | | | | 2466 | | | | | : | | | | | | |
1962 | +--------+ +--------+ : +--------+ | | | | | 2467 | +--------+ +--------+ : +--------+ | | | | |
1963 | : | Cache | +--------+ | 2468 | : | Cache | +--------+ |
1964 | : | Coherency | | 2469 | : | Coherency | |
1965 | : | Mechanism | +--------+ | 2470 | : | Mechanism | +--------+ |
1966 | +--------+ +--------+ : +--------+ | | | | | 2471 | +--------+ +--------+ : +--------+ | | | | |
1967 | | | | | : | | | | | | | 2472 | | | | | : | | | | | | |
1968 | | CPU | | Memory | : | CPU | | |--->| Device | | 2473 | | CPU | | Memory | : | CPU | | |--->| Device | |
1969 | | Core |--->| Access |----->| Cache |<-->| | | | | 2474 | | Core |--->| Access |----->| Cache |<-->| | | | |
1970 | | | | Queue | : | | | | | | | 2475 | | | | Queue | : | | | | | | |
1971 | | | | | : | | | | +--------+ | 2476 | | | | | : | | | | +--------+ |
1972 | +--------+ +--------+ : +--------+ +-----------+ | 2477 | +--------+ +--------+ : +--------+ +-----------+ |
1973 | : | 2478 | : |
@@ -2090,7 +2595,7 @@ CPU's caches by some other cache event: | |||
2090 | p = &v; q = p; | 2595 | p = &v; q = p; |
2091 | <D:request p> | 2596 | <D:request p> |
2092 | <B:modify p=&v> <D:commit p=&v> | 2597 | <B:modify p=&v> <D:commit p=&v> |
2093 | <D:read p> | 2598 | <D:read p> |
2094 | x = *q; | 2599 | x = *q; |
2095 | <C:read *q> Reads from v before v updated in cache | 2600 | <C:read *q> Reads from v before v updated in cache |
2096 | <C:unbusy> | 2601 | <C:unbusy> |
@@ -2115,7 +2620,7 @@ queue before processing any further requests: | |||
2115 | p = &v; q = p; | 2620 | p = &v; q = p; |
2116 | <D:request p> | 2621 | <D:request p> |
2117 | <B:modify p=&v> <D:commit p=&v> | 2622 | <B:modify p=&v> <D:commit p=&v> |
2118 | <D:read p> | 2623 | <D:read p> |
2119 | smp_read_barrier_depends() | 2624 | smp_read_barrier_depends() |
2120 | <C:unbusy> | 2625 | <C:unbusy> |
2121 | <C:commit v=2> | 2626 | <C:commit v=2> |
@@ -2177,11 +2682,11 @@ A programmer might take it for granted that the CPU will perform memory | |||
2177 | operations in exactly the order specified, so that if the CPU is, for example, | 2682 | operations in exactly the order specified, so that if the CPU is, for example, |
2178 | given the following piece of code to execute: | 2683 | given the following piece of code to execute: |
2179 | 2684 | ||
2180 | a = *A; | 2685 | a = ACCESS_ONCE(*A); |
2181 | *B = b; | 2686 | ACCESS_ONCE(*B) = b; |
2182 | c = *C; | 2687 | c = ACCESS_ONCE(*C); |
2183 | d = *D; | 2688 | d = ACCESS_ONCE(*D); |
2184 | *E = e; | 2689 | ACCESS_ONCE(*E) = e; |
2185 | 2690 | ||
2186 | they would then expect that the CPU will complete the memory operation for each | 2691 | they would then expect that the CPU will complete the memory operation for each |
2187 | instruction before moving on to the next one, leading to a definite sequence of | 2692 | instruction before moving on to the next one, leading to a definite sequence of |
@@ -2228,12 +2733,12 @@ However, it is guaranteed that a CPU will be self-consistent: it will see its | |||
2228 | _own_ accesses appear to be correctly ordered, without the need for a memory | 2733 | _own_ accesses appear to be correctly ordered, without the need for a memory |
2229 | barrier. For instance with the following code: | 2734 | barrier. For instance with the following code: |
2230 | 2735 | ||
2231 | U = *A; | 2736 | U = ACCESS_ONCE(*A); |
2232 | *A = V; | 2737 | ACCESS_ONCE(*A) = V; |
2233 | *A = W; | 2738 | ACCESS_ONCE(*A) = W; |
2234 | X = *A; | 2739 | X = ACCESS_ONCE(*A); |
2235 | *A = Y; | 2740 | ACCESS_ONCE(*A) = Y; |
2236 | Z = *A; | 2741 | Z = ACCESS_ONCE(*A); |
2237 | 2742 | ||
2238 | and assuming no intervention by an external influence, it can be assumed that | 2743 | and assuming no intervention by an external influence, it can be assumed that |
2239 | the final result will appear to be: | 2744 | the final result will appear to be: |
@@ -2250,7 +2755,12 @@ accesses: | |||
2250 | 2755 | ||
2251 | in that order, but, without intervention, the sequence may have almost any | 2756 | in that order, but, without intervention, the sequence may have almost any |
2252 | combination of elements combined or discarded, provided the program's view of | 2757 | combination of elements combined or discarded, provided the program's view of |
2253 | the world remains consistent. | 2758 | the world remains consistent. Note that ACCESS_ONCE() is -not- optional |
2759 | in the above example, as there are architectures where a given CPU might | ||
2760 | interchange successive loads to the same location. On such architectures, | ||
2761 | ACCESS_ONCE() does whatever is necessary to prevent this, for example, on | ||
2762 | Itanium the volatile casts used by ACCESS_ONCE() cause GCC to emit the | ||
2763 | special ld.acq and st.rel instructions that prevent such reordering. | ||
2254 | 2764 | ||
2255 | The compiler may also combine, discard or defer elements of the sequence before | 2765 | The compiler may also combine, discard or defer elements of the sequence before |
2256 | the CPU even sees them. | 2766 | the CPU even sees them. |
@@ -2264,13 +2774,13 @@ may be reduced to: | |||
2264 | 2774 | ||
2265 | *A = W; | 2775 | *A = W; |
2266 | 2776 | ||
2267 | since, without a write barrier, it can be assumed that the effect of the | 2777 | since, without either a write barrier or an ACCESS_ONCE(), it can be |
2268 | storage of V to *A is lost. Similarly: | 2778 | assumed that the effect of the storage of V to *A is lost. Similarly: |
2269 | 2779 | ||
2270 | *A = Y; | 2780 | *A = Y; |
2271 | Z = *A; | 2781 | Z = *A; |
2272 | 2782 | ||
2273 | may, without a memory barrier, be reduced to: | 2783 | may, without a memory barrier or an ACCESS_ONCE(), be reduced to: |
2274 | 2784 | ||
2275 | *A = Y; | 2785 | *A = Y; |
2276 | Z = Y; | 2786 | Z = Y; |
diff --git a/Documentation/robust-futex-ABI.txt b/Documentation/robust-futex-ABI.txt index fd1cd8aae4eb..16eb314f56cc 100644 --- a/Documentation/robust-futex-ABI.txt +++ b/Documentation/robust-futex-ABI.txt | |||
@@ -146,8 +146,8 @@ On removal: | |||
146 | 1) set the 'list_op_pending' word to the address of the 'lock entry' | 146 | 1) set the 'list_op_pending' word to the address of the 'lock entry' |
147 | to be removed, | 147 | to be removed, |
148 | 2) remove the lock entry for this lock from the 'head' list, | 148 | 2) remove the lock entry for this lock from the 'head' list, |
149 | 2) release the futex lock, and | 149 | 3) release the futex lock, and |
150 | 2) clear the 'lock_op_pending' word. | 150 | 4) clear the 'lock_op_pending' word. |
151 | 151 | ||
152 | On exit, the kernel will consider the address stored in | 152 | On exit, the kernel will consider the address stored in |
153 | 'list_op_pending' and the address of each 'lock word' found by walking | 153 | 'list_op_pending' and the address of each 'lock word' found by walking |
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 26b7ee491df8..6d486404200e 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt | |||
@@ -428,11 +428,6 @@ rate for each task. | |||
428 | numa_balancing_scan_size_mb is how many megabytes worth of pages are | 428 | numa_balancing_scan_size_mb is how many megabytes worth of pages are |
429 | scanned for a given scan. | 429 | scanned for a given scan. |
430 | 430 | ||
431 | numa_balancing_settle_count is how many scan periods must complete before | ||
432 | the schedule balancer stops pushing the task towards a preferred node. This | ||
433 | gives the scheduler a chance to place the task on an alternative node if the | ||
434 | preferred node is overloaded. | ||
435 | |||
436 | numa_balancing_migrate_deferred is how many page migrations get skipped | 431 | numa_balancing_migrate_deferred is how many page migrations get skipped |
437 | unconditionally, after a page migration is skipped because a page is shared | 432 | unconditionally, after a page migration is skipped because a page is shared |
438 | with other tasks. This reduces page migration overhead, and determines | 433 | with other tasks. This reduces page migration overhead, and determines |
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index f4f268c2b826..cb81741d3b0b 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt | |||
@@ -608,6 +608,9 @@ Protocol: 2.12+ | |||
608 | - If 1, the kernel supports the 64-bit EFI handoff entry point | 608 | - If 1, the kernel supports the 64-bit EFI handoff entry point |
609 | given at handover_offset + 0x200. | 609 | given at handover_offset + 0x200. |
610 | 610 | ||
611 | Bit 4 (read): XLF_EFI_KEXEC | ||
612 | - If 1, the kernel supports kexec EFI boot with EFI runtime support. | ||
613 | |||
611 | Field name: cmdline_size | 614 | Field name: cmdline_size |
612 | Type: read | 615 | Type: read |
613 | Offset/size: 0x238/4 | 616 | Offset/size: 0x238/4 |
diff --git a/Documentation/x86/x86_64/mm.txt b/Documentation/x86/x86_64/mm.txt index 881582f75c9c..c584a51add15 100644 --- a/Documentation/x86/x86_64/mm.txt +++ b/Documentation/x86/x86_64/mm.txt | |||
@@ -28,4 +28,11 @@ reference. | |||
28 | Current X86-64 implementations only support 40 bits of address space, | 28 | Current X86-64 implementations only support 40 bits of address space, |
29 | but we support up to 46 bits. This expands into MBZ space in the page tables. | 29 | but we support up to 46 bits. This expands into MBZ space in the page tables. |
30 | 30 | ||
31 | ->trampoline_pgd: | ||
32 | |||
33 | We map EFI runtime services in the aforementioned PGD in the virtual | ||
34 | range of 64Gb (arbitrarily set, can be raised if needed) | ||
35 | |||
36 | 0xffffffef00000000 - 0xffffffff00000000 | ||
37 | |||
31 | -Andi Kleen, Jul 2004 | 38 | -Andi Kleen, Jul 2004 |
diff --git a/Documentation/zorro.txt b/Documentation/zorro.txt index d5829d14774a..90a64d52bea2 100644 --- a/Documentation/zorro.txt +++ b/Documentation/zorro.txt | |||
@@ -95,8 +95,9 @@ The treatment of these regions depends on the type of Zorro space: | |||
95 | ------------- | 95 | ------------- |
96 | 96 | ||
97 | linux/include/linux/zorro.h | 97 | linux/include/linux/zorro.h |
98 | linux/include/asm-{m68k,ppc}/zorro.h | 98 | linux/include/uapi/linux/zorro.h |
99 | linux/include/linux/zorro_ids.h | 99 | linux/include/uapi/linux/zorro_ids.h |
100 | linux/arch/m68k/include/asm/zorro.h | ||
100 | linux/drivers/zorro | 101 | linux/drivers/zorro |
101 | /proc/bus/zorro | 102 | /proc/bus/zorro |
102 | 103 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 31a046213274..ce1645ebe70c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5141,6 +5141,11 @@ F: drivers/lguest/ | |||
5141 | F: include/linux/lguest*.h | 5141 | F: include/linux/lguest*.h |
5142 | F: tools/lguest/ | 5142 | F: tools/lguest/ |
5143 | 5143 | ||
5144 | LIBLOCKDEP | ||
5145 | M: Sasha Levin <sasha.levin@oracle.com> | ||
5146 | S: Maintained | ||
5147 | F: tools/lib/lockdep/ | ||
5148 | |||
5144 | LINUX FOR IBM pSERIES (RS/6000) | 5149 | LINUX FOR IBM pSERIES (RS/6000) |
5145 | M: Paul Mackerras <paulus@au.ibm.com> | 5150 | M: Paul Mackerras <paulus@au.ibm.com> |
5146 | W: http://www.ibm.com/linux/ltc/projects/ppc | 5151 | W: http://www.ibm.com/linux/ltc/projects/ppc |
@@ -7099,6 +7104,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git | |||
7099 | F: Documentation/RCU/torture.txt | 7104 | F: Documentation/RCU/torture.txt |
7100 | F: kernel/rcu/torture.c | 7105 | F: kernel/rcu/torture.c |
7101 | 7106 | ||
7107 | RCUTORTURE TEST FRAMEWORK | ||
7108 | M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> | ||
7109 | S: Supported | ||
7110 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git | ||
7111 | F: tools/testing/selftests/rcutorture | ||
7112 | |||
7102 | RDC R-321X SoC | 7113 | RDC R-321X SoC |
7103 | M: Florian Fainelli <florian@openwrt.org> | 7114 | M: Florian Fainelli <florian@openwrt.org> |
7104 | S: Maintained | 7115 | S: Maintained |
@@ -9231,6 +9242,7 @@ F: include/media/videobuf2-* | |||
9231 | 9242 | ||
9232 | VIRTIO CONSOLE DRIVER | 9243 | VIRTIO CONSOLE DRIVER |
9233 | M: Amit Shah <amit.shah@redhat.com> | 9244 | M: Amit Shah <amit.shah@redhat.com> |
9245 | L: virtio-dev@lists.oasis-open.org | ||
9234 | L: virtualization@lists.linux-foundation.org | 9246 | L: virtualization@lists.linux-foundation.org |
9235 | S: Maintained | 9247 | S: Maintained |
9236 | F: drivers/char/virtio_console.c | 9248 | F: drivers/char/virtio_console.c |
@@ -9240,6 +9252,7 @@ F: include/uapi/linux/virtio_console.h | |||
9240 | VIRTIO CORE, NET AND BLOCK DRIVERS | 9252 | VIRTIO CORE, NET AND BLOCK DRIVERS |
9241 | M: Rusty Russell <rusty@rustcorp.com.au> | 9253 | M: Rusty Russell <rusty@rustcorp.com.au> |
9242 | M: "Michael S. Tsirkin" <mst@redhat.com> | 9254 | M: "Michael S. Tsirkin" <mst@redhat.com> |
9255 | L: virtio-dev@lists.oasis-open.org | ||
9243 | L: virtualization@lists.linux-foundation.org | 9256 | L: virtualization@lists.linux-foundation.org |
9244 | S: Maintained | 9257 | S: Maintained |
9245 | F: drivers/virtio/ | 9258 | F: drivers/virtio/ |
@@ -9252,6 +9265,7 @@ F: include/uapi/linux/virtio_*.h | |||
9252 | VIRTIO HOST (VHOST) | 9265 | VIRTIO HOST (VHOST) |
9253 | M: "Michael S. Tsirkin" <mst@redhat.com> | 9266 | M: "Michael S. Tsirkin" <mst@redhat.com> |
9254 | L: kvm@vger.kernel.org | 9267 | L: kvm@vger.kernel.org |
9268 | L: virtio-dev@lists.oasis-open.org | ||
9255 | L: virtualization@lists.linux-foundation.org | 9269 | L: virtualization@lists.linux-foundation.org |
9256 | L: netdev@vger.kernel.org | 9270 | L: netdev@vger.kernel.org |
9257 | S: Maintained | 9271 | S: Maintained |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 3 | 1 | VERSION = 3 |
2 | PATCHLEVEL = 13 | 2 | PATCHLEVEL = 13 |
3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
4 | EXTRAVERSION = -rc8 | 4 | EXTRAVERSION = |
5 | NAME = One Giant Leap for Frogkind | 5 | NAME = One Giant Leap for Frogkind |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
@@ -595,10 +595,24 @@ ifneq ($(CONFIG_FRAME_WARN),0) | |||
595 | KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) | 595 | KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) |
596 | endif | 596 | endif |
597 | 597 | ||
598 | # Force gcc to behave correct even for buggy distributions | 598 | # Handle stack protector mode. |
599 | ifndef CONFIG_CC_STACKPROTECTOR | 599 | ifdef CONFIG_CC_STACKPROTECTOR_REGULAR |
600 | KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) | 600 | stackp-flag := -fstack-protector |
601 | ifeq ($(call cc-option, $(stackp-flag)),) | ||
602 | $(warning Cannot use CONFIG_CC_STACKPROTECTOR: \ | ||
603 | -fstack-protector not supported by compiler)) | ||
604 | endif | ||
605 | else ifdef CONFIG_CC_STACKPROTECTOR_STRONG | ||
606 | stackp-flag := -fstack-protector-strong | ||
607 | ifeq ($(call cc-option, $(stackp-flag)),) | ||
608 | $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \ | ||
609 | -fstack-protector-strong not supported by compiler) | ||
610 | endif | ||
611 | else | ||
612 | # Force off for distro compilers that enable stack protector by default. | ||
613 | stackp-flag := $(call cc-option, -fno-stack-protector) | ||
601 | endif | 614 | endif |
615 | KBUILD_CFLAGS += $(stackp-flag) | ||
602 | 616 | ||
603 | # This warning generated too much noise in a regular build. | 617 | # This warning generated too much noise in a regular build. |
604 | # Use make W=1 to enable this warning (see scripts/Makefile.build) | 618 | # Use make W=1 to enable this warning (see scripts/Makefile.build) |
diff --git a/arch/Kconfig b/arch/Kconfig index f1cf895c040f..80bbb8ccd0d1 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -336,6 +336,73 @@ config SECCOMP_FILTER | |||
336 | 336 | ||
337 | See Documentation/prctl/seccomp_filter.txt for details. | 337 | See Documentation/prctl/seccomp_filter.txt for details. |
338 | 338 | ||
339 | config HAVE_CC_STACKPROTECTOR | ||
340 | bool | ||
341 | help | ||
342 | An arch should select this symbol if: | ||
343 | - its compiler supports the -fstack-protector option | ||
344 | - it has implemented a stack canary (e.g. __stack_chk_guard) | ||
345 | |||
346 | config CC_STACKPROTECTOR | ||
347 | def_bool n | ||
348 | help | ||
349 | Set when a stack-protector mode is enabled, so that the build | ||
350 | can enable kernel-side support for the GCC feature. | ||
351 | |||
352 | choice | ||
353 | prompt "Stack Protector buffer overflow detection" | ||
354 | depends on HAVE_CC_STACKPROTECTOR | ||
355 | default CC_STACKPROTECTOR_NONE | ||
356 | help | ||
357 | This option turns on the "stack-protector" GCC feature. This | ||
358 | feature puts, at the beginning of functions, a canary value on | ||
359 | the stack just before the return address, and validates | ||
360 | the value just before actually returning. Stack based buffer | ||
361 | overflows (that need to overwrite this return address) now also | ||
362 | overwrite the canary, which gets detected and the attack is then | ||
363 | neutralized via a kernel panic. | ||
364 | |||
365 | config CC_STACKPROTECTOR_NONE | ||
366 | bool "None" | ||
367 | help | ||
368 | Disable "stack-protector" GCC feature. | ||
369 | |||
370 | config CC_STACKPROTECTOR_REGULAR | ||
371 | bool "Regular" | ||
372 | select CC_STACKPROTECTOR | ||
373 | help | ||
374 | Functions will have the stack-protector canary logic added if they | ||
375 | have an 8-byte or larger character array on the stack. | ||
376 | |||
377 | This feature requires gcc version 4.2 or above, or a distribution | ||
378 | gcc with the feature backported ("-fstack-protector"). | ||
379 | |||
380 | On an x86 "defconfig" build, this feature adds canary checks to | ||
381 | about 3% of all kernel functions, which increases kernel code size | ||
382 | by about 0.3%. | ||
383 | |||
384 | config CC_STACKPROTECTOR_STRONG | ||
385 | bool "Strong" | ||
386 | select CC_STACKPROTECTOR | ||
387 | help | ||
388 | Functions will have the stack-protector canary logic added in any | ||
389 | of the following conditions: | ||
390 | |||
391 | - local variable's address used as part of the right hand side of an | ||
392 | assignment or function argument | ||
393 | - local variable is an array (or union containing an array), | ||
394 | regardless of array type or length | ||
395 | - uses register local variables | ||
396 | |||
397 | This feature requires gcc version 4.9 or above, or a distribution | ||
398 | gcc with the feature backported ("-fstack-protector-strong"). | ||
399 | |||
400 | On an x86 "defconfig" build, this feature adds canary checks to | ||
401 | about 20% of all kernel functions, which increases the kernel code | ||
402 | size by about 2%. | ||
403 | |||
404 | endchoice | ||
405 | |||
339 | config HAVE_CONTEXT_TRACKING | 406 | config HAVE_CONTEXT_TRACKING |
340 | bool | 407 | bool |
341 | help | 408 | help |
diff --git a/arch/alpha/include/asm/barrier.h b/arch/alpha/include/asm/barrier.h index ce8860a0b32d..3832bdb794fe 100644 --- a/arch/alpha/include/asm/barrier.h +++ b/arch/alpha/include/asm/barrier.h | |||
@@ -3,33 +3,18 @@ | |||
3 | 3 | ||
4 | #include <asm/compiler.h> | 4 | #include <asm/compiler.h> |
5 | 5 | ||
6 | #define mb() \ | 6 | #define mb() __asm__ __volatile__("mb": : :"memory") |
7 | __asm__ __volatile__("mb": : :"memory") | 7 | #define rmb() __asm__ __volatile__("mb": : :"memory") |
8 | #define wmb() __asm__ __volatile__("wmb": : :"memory") | ||
8 | 9 | ||
9 | #define rmb() \ | 10 | #define read_barrier_depends() __asm__ __volatile__("mb": : :"memory") |
10 | __asm__ __volatile__("mb": : :"memory") | ||
11 | |||
12 | #define wmb() \ | ||
13 | __asm__ __volatile__("wmb": : :"memory") | ||
14 | |||
15 | #define read_barrier_depends() \ | ||
16 | __asm__ __volatile__("mb": : :"memory") | ||
17 | 11 | ||
18 | #ifdef CONFIG_SMP | 12 | #ifdef CONFIG_SMP |
19 | #define __ASM_SMP_MB "\tmb\n" | 13 | #define __ASM_SMP_MB "\tmb\n" |
20 | #define smp_mb() mb() | ||
21 | #define smp_rmb() rmb() | ||
22 | #define smp_wmb() wmb() | ||
23 | #define smp_read_barrier_depends() read_barrier_depends() | ||
24 | #else | 14 | #else |
25 | #define __ASM_SMP_MB | 15 | #define __ASM_SMP_MB |
26 | #define smp_mb() barrier() | ||
27 | #define smp_rmb() barrier() | ||
28 | #define smp_wmb() barrier() | ||
29 | #define smp_read_barrier_depends() do { } while (0) | ||
30 | #endif | 16 | #endif |
31 | 17 | ||
32 | #define set_mb(var, value) \ | 18 | #include <asm-generic/barrier.h> |
33 | do { var = value; mb(); } while (0) | ||
34 | 19 | ||
35 | #endif /* __BARRIER_H */ | 20 | #endif /* __BARRIER_H */ |
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index 5943f7f9d325..9ae21c198007 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild | |||
@@ -1,4 +1,5 @@ | |||
1 | generic-y += auxvec.h | 1 | generic-y += auxvec.h |
2 | generic-y += barrier.h | ||
2 | generic-y += bugs.h | 3 | generic-y += bugs.h |
3 | generic-y += bitsperlong.h | 4 | generic-y += bitsperlong.h |
4 | generic-y += clkdev.h | 5 | generic-y += clkdev.h |
diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h index 83f03ca6caf6..03e494f695d1 100644 --- a/arch/arc/include/asm/atomic.h +++ b/arch/arc/include/asm/atomic.h | |||
@@ -190,6 +190,11 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | |||
190 | 190 | ||
191 | #endif /* !CONFIG_ARC_HAS_LLSC */ | 191 | #endif /* !CONFIG_ARC_HAS_LLSC */ |
192 | 192 | ||
193 | #define smp_mb__before_atomic_dec() barrier() | ||
194 | #define smp_mb__after_atomic_dec() barrier() | ||
195 | #define smp_mb__before_atomic_inc() barrier() | ||
196 | #define smp_mb__after_atomic_inc() barrier() | ||
197 | |||
193 | /** | 198 | /** |
194 | * __atomic_add_unless - add unless the number is a given value | 199 | * __atomic_add_unless - add unless the number is a given value |
195 | * @v: pointer of type atomic_t | 200 | * @v: pointer of type atomic_t |
diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h index f6cb7c4ffb35..c32245c3d1e9 100644 --- a/arch/arc/include/asm/barrier.h +++ b/arch/arc/include/asm/barrier.h | |||
@@ -30,11 +30,6 @@ | |||
30 | #define smp_wmb() barrier() | 30 | #define smp_wmb() barrier() |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #define smp_mb__before_atomic_dec() barrier() | ||
34 | #define smp_mb__after_atomic_dec() barrier() | ||
35 | #define smp_mb__before_atomic_inc() barrier() | ||
36 | #define smp_mb__after_atomic_inc() barrier() | ||
37 | |||
38 | #define smp_read_barrier_depends() do { } while (0) | 33 | #define smp_read_barrier_depends() do { } while (0) |
39 | 34 | ||
40 | #endif | 35 | #endif |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c1f1a7eee953..9c909fc29272 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -30,6 +30,7 @@ config ARM | |||
30 | select HAVE_BPF_JIT | 30 | select HAVE_BPF_JIT |
31 | select HAVE_CONTEXT_TRACKING | 31 | select HAVE_CONTEXT_TRACKING |
32 | select HAVE_C_RECORDMCOUNT | 32 | select HAVE_C_RECORDMCOUNT |
33 | select HAVE_CC_STACKPROTECTOR | ||
33 | select HAVE_DEBUG_KMEMLEAK | 34 | select HAVE_DEBUG_KMEMLEAK |
34 | select HAVE_DMA_API_DEBUG | 35 | select HAVE_DMA_API_DEBUG |
35 | select HAVE_DMA_ATTRS | 36 | select HAVE_DMA_ATTRS |
@@ -1856,18 +1857,6 @@ config SECCOMP | |||
1856 | and the task is only allowed to execute a few safe syscalls | 1857 | and the task is only allowed to execute a few safe syscalls |
1857 | defined by each seccomp mode. | 1858 | defined by each seccomp mode. |
1858 | 1859 | ||
1859 | config CC_STACKPROTECTOR | ||
1860 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" | ||
1861 | help | ||
1862 | This option turns on the -fstack-protector GCC feature. This | ||
1863 | feature puts, at the beginning of functions, a canary value on | ||
1864 | the stack just before the return address, and validates | ||
1865 | the value just before actually returning. Stack based buffer | ||
1866 | overflows (that need to overwrite this return address) now also | ||
1867 | overwrite the canary, which gets detected and the attack is then | ||
1868 | neutralized via a kernel panic. | ||
1869 | This feature requires gcc version 4.2 or above. | ||
1870 | |||
1871 | config SWIOTLB | 1860 | config SWIOTLB |
1872 | def_bool y | 1861 | def_bool y |
1873 | 1862 | ||
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c99b1086d83d..55b4255ad6ed 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -40,10 +40,6 @@ ifeq ($(CONFIG_FRAME_POINTER),y) | |||
40 | KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog | 40 | KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog |
41 | endif | 41 | endif |
42 | 42 | ||
43 | ifeq ($(CONFIG_CC_STACKPROTECTOR),y) | ||
44 | KBUILD_CFLAGS +=-fstack-protector | ||
45 | endif | ||
46 | |||
47 | ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) | 43 | ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) |
48 | KBUILD_CPPFLAGS += -mbig-endian | 44 | KBUILD_CPPFLAGS += -mbig-endian |
49 | AS += -EB | 45 | AS += -EB |
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 31bd43b82095..d4f891f56996 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c | |||
@@ -127,6 +127,18 @@ asmlinkage void __div0(void) | |||
127 | error("Attempting division by 0!"); | 127 | error("Attempting division by 0!"); |
128 | } | 128 | } |
129 | 129 | ||
130 | unsigned long __stack_chk_guard; | ||
131 | |||
132 | void __stack_chk_guard_setup(void) | ||
133 | { | ||
134 | __stack_chk_guard = 0x000a0dff; | ||
135 | } | ||
136 | |||
137 | void __stack_chk_fail(void) | ||
138 | { | ||
139 | error("stack-protector: Kernel stack is corrupted\n"); | ||
140 | } | ||
141 | |||
130 | extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); | 142 | extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); |
131 | 143 | ||
132 | 144 | ||
@@ -137,6 +149,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, | |||
137 | { | 149 | { |
138 | int ret; | 150 | int ret; |
139 | 151 | ||
152 | __stack_chk_guard_setup(); | ||
153 | |||
140 | output_data = (unsigned char *)output_start; | 154 | output_data = (unsigned char *)output_start; |
141 | free_mem_ptr = free_mem_ptr_p; | 155 | free_mem_ptr = free_mem_ptr_p; |
142 | free_mem_end_ptr = free_mem_ptr_end_p; | 156 | free_mem_end_ptr = free_mem_ptr_end_p; |
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 52476742a104..e674c94c7206 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi | |||
@@ -332,5 +332,12 @@ | |||
332 | clock-frequency = <100000>; | 332 | clock-frequency = <100000>; |
333 | status = "disabled"; | 333 | status = "disabled"; |
334 | }; | 334 | }; |
335 | |||
336 | timer@01c60000 { | ||
337 | compatible = "allwinner,sun5i-a13-hstimer"; | ||
338 | reg = <0x01c60000 0x1000>; | ||
339 | interrupts = <82>, <83>; | ||
340 | clocks = <&ahb_gates 28>; | ||
341 | }; | ||
335 | }; | 342 | }; |
336 | }; | 343 | }; |
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index ce8ef2a45be0..1ccd75d37f49 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi | |||
@@ -273,5 +273,12 @@ | |||
273 | clock-frequency = <100000>; | 273 | clock-frequency = <100000>; |
274 | status = "disabled"; | 274 | status = "disabled"; |
275 | }; | 275 | }; |
276 | |||
277 | timer@01c60000 { | ||
278 | compatible = "allwinner,sun5i-a13-hstimer"; | ||
279 | reg = <0x01c60000 0x1000>; | ||
280 | interrupts = <82>, <83>; | ||
281 | clocks = <&ahb_gates 28>; | ||
282 | }; | ||
276 | }; | 283 | }; |
277 | }; | 284 | }; |
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 367611a0730b..0135039eff96 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi | |||
@@ -395,6 +395,16 @@ | |||
395 | status = "disabled"; | 395 | status = "disabled"; |
396 | }; | 396 | }; |
397 | 397 | ||
398 | hstimer@01c60000 { | ||
399 | compatible = "allwinner,sun7i-a20-hstimer"; | ||
400 | reg = <0x01c60000 0x1000>; | ||
401 | interrupts = <0 81 1>, | ||
402 | <0 82 1>, | ||
403 | <0 83 1>, | ||
404 | <0 84 1>; | ||
405 | clocks = <&ahb_gates 28>; | ||
406 | }; | ||
407 | |||
398 | gic: interrupt-controller@01c81000 { | 408 | gic: interrupt-controller@01c81000 { |
399 | compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; | 409 | compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; |
400 | reg = <0x01c81000 0x1000>, | 410 | reg = <0x01c81000 0x1000>, |
diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h index 60f15e274e6d..2f59f7443396 100644 --- a/arch/arm/include/asm/barrier.h +++ b/arch/arm/include/asm/barrier.h | |||
@@ -59,6 +59,21 @@ | |||
59 | #define smp_wmb() dmb(ishst) | 59 | #define smp_wmb() dmb(ishst) |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | #define smp_store_release(p, v) \ | ||
63 | do { \ | ||
64 | compiletime_assert_atomic_type(*p); \ | ||
65 | smp_mb(); \ | ||
66 | ACCESS_ONCE(*p) = (v); \ | ||
67 | } while (0) | ||
68 | |||
69 | #define smp_load_acquire(p) \ | ||
70 | ({ \ | ||
71 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
72 | compiletime_assert_atomic_type(*p); \ | ||
73 | smp_mb(); \ | ||
74 | ___p1; \ | ||
75 | }) | ||
76 | |||
62 | #define read_barrier_depends() do { } while(0) | 77 | #define read_barrier_depends() do { } while(0) |
63 | #define smp_read_barrier_depends() do { } while(0) | 78 | #define smp_read_barrier_depends() do { } while(0) |
64 | 79 | ||
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 141baa3f9a72..acabef1a75df 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #include <uapi/asm/unistd.h> | 16 | #include <uapi/asm/unistd.h> |
17 | 17 | ||
18 | #define __NR_syscalls (380) | 18 | #define __NR_syscalls (384) |
19 | #define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0) | 19 | #define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0) |
20 | 20 | ||
21 | #define __ARCH_WANT_STAT64 | 21 | #define __ARCH_WANT_STAT64 |
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h index af33b44990ed..fb5584d0cc05 100644 --- a/arch/arm/include/uapi/asm/unistd.h +++ b/arch/arm/include/uapi/asm/unistd.h | |||
@@ -406,6 +406,8 @@ | |||
406 | #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) | 406 | #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) |
407 | #define __NR_kcmp (__NR_SYSCALL_BASE+378) | 407 | #define __NR_kcmp (__NR_SYSCALL_BASE+378) |
408 | #define __NR_finit_module (__NR_SYSCALL_BASE+379) | 408 | #define __NR_finit_module (__NR_SYSCALL_BASE+379) |
409 | #define __NR_sched_setattr (__NR_SYSCALL_BASE+380) | ||
410 | #define __NR_sched_getattr (__NR_SYSCALL_BASE+381) | ||
409 | 411 | ||
410 | /* | 412 | /* |
411 | * This may need to be greater than __NR_last_syscall+1 in order to | 413 | * This may need to be greater than __NR_last_syscall+1 in order to |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index c6ca7e376773..166e945de832 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -389,6 +389,8 @@ | |||
389 | CALL(sys_process_vm_writev) | 389 | CALL(sys_process_vm_writev) |
390 | CALL(sys_kcmp) | 390 | CALL(sys_kcmp) |
391 | CALL(sys_finit_module) | 391 | CALL(sys_finit_module) |
392 | /* 380 */ CALL(sys_sched_setattr) | ||
393 | CALL(sys_sched_getattr) | ||
392 | #ifndef syscalls_counted | 394 | #ifndef syscalls_counted |
393 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls | 395 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls |
394 | #define syscalls_counted | 396 | #define syscalls_counted |
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index 739c3dfc1da2..34d5fd585bbb 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c | |||
@@ -171,7 +171,7 @@ void __init arm_dt_init_cpu_maps(void) | |||
171 | 171 | ||
172 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | 172 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) |
173 | { | 173 | { |
174 | return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu); | 174 | return phys_id == cpu_logical_map(cpu); |
175 | } | 175 | } |
176 | 176 | ||
177 | static const void * __init arch_get_next_mach(const char *const **match) | 177 | static const void * __init arch_get_next_mach(const char *const **match) |
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index bc3f2efa0d86..789d846a9184 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -99,10 +99,6 @@ int armpmu_event_set_period(struct perf_event *event) | |||
99 | s64 period = hwc->sample_period; | 99 | s64 period = hwc->sample_period; |
100 | int ret = 0; | 100 | int ret = 0; |
101 | 101 | ||
102 | /* The period may have been changed by PERF_EVENT_IOC_PERIOD */ | ||
103 | if (unlikely(period != hwc->last_period)) | ||
104 | left = period - (hwc->last_period - left); | ||
105 | |||
106 | if (unlikely(left <= -period)) { | 102 | if (unlikely(left <= -period)) { |
107 | left = period; | 103 | left = period; |
108 | local64_set(&hwc->period_left, left); | 104 | local64_set(&hwc->period_left, left); |
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index d85055cd24ba..20d553c9f5e2 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c | |||
@@ -254,7 +254,7 @@ static int probe_current_pmu(struct arm_pmu *pmu) | |||
254 | static int cpu_pmu_device_probe(struct platform_device *pdev) | 254 | static int cpu_pmu_device_probe(struct platform_device *pdev) |
255 | { | 255 | { |
256 | const struct of_device_id *of_id; | 256 | const struct of_device_id *of_id; |
257 | int (*init_fn)(struct arm_pmu *); | 257 | const int (*init_fn)(struct arm_pmu *); |
258 | struct device_node *node = pdev->dev.of_node; | 258 | struct device_node *node = pdev->dev.of_node; |
259 | struct arm_pmu *pmu; | 259 | struct arm_pmu *pmu; |
260 | int ret = -ENODEV; | 260 | int ret = -ENODEV; |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 6eda3bf85c52..4636d56af2db 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -431,9 +431,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
431 | instr2 = __mem_to_opcode_thumb16(instr2); | 431 | instr2 = __mem_to_opcode_thumb16(instr2); |
432 | instr = __opcode_thumb32_compose(instr, instr2); | 432 | instr = __opcode_thumb32_compose(instr, instr2); |
433 | } | 433 | } |
434 | } else if (get_user(instr, (u32 __user *)pc)) { | 434 | } else { |
435 | if (get_user(instr, (u32 __user *)pc)) | ||
436 | goto die_sig; | ||
435 | instr = __mem_to_opcode_arm(instr); | 437 | instr = __mem_to_opcode_arm(instr); |
436 | goto die_sig; | ||
437 | } | 438 | } |
438 | 439 | ||
439 | if (call_undef_hook(regs, instr) == 0) | 440 | if (call_undef_hook(regs, instr) == 0) |
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index bd3bf66ce344..c7de89b263dd 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c | |||
@@ -53,6 +53,7 @@ static void __init highbank_scu_map_io(void) | |||
53 | 53 | ||
54 | static void highbank_l2x0_disable(void) | 54 | static void highbank_l2x0_disable(void) |
55 | { | 55 | { |
56 | outer_flush_all(); | ||
56 | /* Disable PL310 L2 Cache controller */ | 57 | /* Disable PL310 L2 Cache controller */ |
57 | highbank_smc1(0x102, 0x0); | 58 | highbank_smc1(0x102, 0x0); |
58 | } | 59 | } |
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index b39efd46abf9..c0ab9b26be3d 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c | |||
@@ -162,6 +162,7 @@ void __iomem *omap4_get_l2cache_base(void) | |||
162 | 162 | ||
163 | static void omap4_l2x0_disable(void) | 163 | static void omap4_l2x0_disable(void) |
164 | { | 164 | { |
165 | outer_flush_all(); | ||
165 | /* Disable PL310 L2 Cache controller */ | 166 | /* Disable PL310 L2 Cache controller */ |
166 | omap_smc1(0x102, 0x0); | 167 | omap_smc1(0x102, 0x0); |
167 | } | 168 | } |
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index c9e72c89066a..bce0d4277f71 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig | |||
@@ -12,3 +12,4 @@ config ARCH_SUNXI | |||
12 | select PINCTRL_SUNXI | 12 | select PINCTRL_SUNXI |
13 | select SPARSE_IRQ | 13 | select SPARSE_IRQ |
14 | select SUN4I_TIMER | 14 | select SUN4I_TIMER |
15 | select SUN5I_HSTIMER | ||
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 1f7b19a47060..3e8f106ee5fe 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -229,7 +229,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc) | |||
229 | #ifdef CONFIG_ZONE_DMA | 229 | #ifdef CONFIG_ZONE_DMA |
230 | if (mdesc->dma_zone_size) { | 230 | if (mdesc->dma_zone_size) { |
231 | arm_dma_zone_size = mdesc->dma_zone_size; | 231 | arm_dma_zone_size = mdesc->dma_zone_size; |
232 | arm_dma_limit = __pv_phys_offset + arm_dma_zone_size - 1; | 232 | arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1; |
233 | } else | 233 | } else |
234 | arm_dma_limit = 0xffffffff; | 234 | arm_dma_limit = 0xffffffff; |
235 | arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT; | 235 | arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT; |
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 9ed155ad0f97..271b5e971568 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c | |||
@@ -641,10 +641,10 @@ load_ind: | |||
641 | emit(ARM_MUL(r_A, r_A, r_X), ctx); | 641 | emit(ARM_MUL(r_A, r_A, r_X), ctx); |
642 | break; | 642 | break; |
643 | case BPF_S_ALU_DIV_K: | 643 | case BPF_S_ALU_DIV_K: |
644 | /* current k == reciprocal_value(userspace k) */ | 644 | if (k == 1) |
645 | break; | ||
645 | emit_mov_i(r_scratch, k, ctx); | 646 | emit_mov_i(r_scratch, k, ctx); |
646 | /* A = top 32 bits of the product */ | 647 | emit_udiv(r_A, r_A, r_scratch, ctx); |
647 | emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx); | ||
648 | break; | 648 | break; |
649 | case BPF_S_ALU_DIV_X: | 649 | case BPF_S_ALU_DIV_X: |
650 | update_on_xread(ctx); | 650 | update_on_xread(ctx); |
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index d4a63338a53c..78e20ba8806b 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h | |||
@@ -35,10 +35,60 @@ | |||
35 | #define smp_mb() barrier() | 35 | #define smp_mb() barrier() |
36 | #define smp_rmb() barrier() | 36 | #define smp_rmb() barrier() |
37 | #define smp_wmb() barrier() | 37 | #define smp_wmb() barrier() |
38 | |||
39 | #define smp_store_release(p, v) \ | ||
40 | do { \ | ||
41 | compiletime_assert_atomic_type(*p); \ | ||
42 | smp_mb(); \ | ||
43 | ACCESS_ONCE(*p) = (v); \ | ||
44 | } while (0) | ||
45 | |||
46 | #define smp_load_acquire(p) \ | ||
47 | ({ \ | ||
48 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
49 | compiletime_assert_atomic_type(*p); \ | ||
50 | smp_mb(); \ | ||
51 | ___p1; \ | ||
52 | }) | ||
53 | |||
38 | #else | 54 | #else |
55 | |||
39 | #define smp_mb() asm volatile("dmb ish" : : : "memory") | 56 | #define smp_mb() asm volatile("dmb ish" : : : "memory") |
40 | #define smp_rmb() asm volatile("dmb ishld" : : : "memory") | 57 | #define smp_rmb() asm volatile("dmb ishld" : : : "memory") |
41 | #define smp_wmb() asm volatile("dmb ishst" : : : "memory") | 58 | #define smp_wmb() asm volatile("dmb ishst" : : : "memory") |
59 | |||
60 | #define smp_store_release(p, v) \ | ||
61 | do { \ | ||
62 | compiletime_assert_atomic_type(*p); \ | ||
63 | switch (sizeof(*p)) { \ | ||
64 | case 4: \ | ||
65 | asm volatile ("stlr %w1, %0" \ | ||
66 | : "=Q" (*p) : "r" (v) : "memory"); \ | ||
67 | break; \ | ||
68 | case 8: \ | ||
69 | asm volatile ("stlr %1, %0" \ | ||
70 | : "=Q" (*p) : "r" (v) : "memory"); \ | ||
71 | break; \ | ||
72 | } \ | ||
73 | } while (0) | ||
74 | |||
75 | #define smp_load_acquire(p) \ | ||
76 | ({ \ | ||
77 | typeof(*p) ___p1; \ | ||
78 | compiletime_assert_atomic_type(*p); \ | ||
79 | switch (sizeof(*p)) { \ | ||
80 | case 4: \ | ||
81 | asm volatile ("ldar %w0, %1" \ | ||
82 | : "=r" (___p1) : "Q" (*p) : "memory"); \ | ||
83 | break; \ | ||
84 | case 8: \ | ||
85 | asm volatile ("ldar %0, %1" \ | ||
86 | : "=r" (___p1) : "Q" (*p) : "memory"); \ | ||
87 | break; \ | ||
88 | } \ | ||
89 | ___p1; \ | ||
90 | }) | ||
91 | |||
42 | #endif | 92 | #endif |
43 | 93 | ||
44 | #define read_barrier_depends() do { } while(0) | 94 | #define read_barrier_depends() do { } while(0) |
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 572769727227..4cc813eddacb 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h | |||
@@ -229,7 +229,7 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot | |||
229 | extern void __iounmap(volatile void __iomem *addr); | 229 | extern void __iounmap(volatile void __iomem *addr); |
230 | extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); | 230 | extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); |
231 | 231 | ||
232 | #define PROT_DEFAULT (pgprot_default | PTE_DIRTY) | 232 | #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY) |
233 | #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) | 233 | #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) |
234 | #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC)) | 234 | #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC)) |
235 | #define PROT_NORMAL (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) | 235 | #define PROT_NORMAL (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) |
diff --git a/arch/avr32/include/asm/barrier.h b/arch/avr32/include/asm/barrier.h index 0961275373db..715100790fd0 100644 --- a/arch/avr32/include/asm/barrier.h +++ b/arch/avr32/include/asm/barrier.h | |||
@@ -8,22 +8,15 @@ | |||
8 | #ifndef __ASM_AVR32_BARRIER_H | 8 | #ifndef __ASM_AVR32_BARRIER_H |
9 | #define __ASM_AVR32_BARRIER_H | 9 | #define __ASM_AVR32_BARRIER_H |
10 | 10 | ||
11 | #define nop() asm volatile("nop") | 11 | /* |
12 | 12 | * Weirdest thing ever.. no full barrier, but it has a write barrier! | |
13 | #define mb() asm volatile("" : : : "memory") | 13 | */ |
14 | #define rmb() mb() | 14 | #define wmb() asm volatile("sync 0" : : : "memory") |
15 | #define wmb() asm volatile("sync 0" : : : "memory") | ||
16 | #define read_barrier_depends() do { } while(0) | ||
17 | #define set_mb(var, value) do { var = value; mb(); } while(0) | ||
18 | 15 | ||
19 | #ifdef CONFIG_SMP | 16 | #ifdef CONFIG_SMP |
20 | # error "The AVR32 port does not support SMP" | 17 | # error "The AVR32 port does not support SMP" |
21 | #else | ||
22 | # define smp_mb() barrier() | ||
23 | # define smp_rmb() barrier() | ||
24 | # define smp_wmb() barrier() | ||
25 | # define smp_read_barrier_depends() do { } while(0) | ||
26 | #endif | 18 | #endif |
27 | 19 | ||
20 | #include <asm-generic/barrier.h> | ||
28 | 21 | ||
29 | #endif /* __ASM_AVR32_BARRIER_H */ | 22 | #endif /* __ASM_AVR32_BARRIER_H */ |
diff --git a/arch/blackfin/include/asm/barrier.h b/arch/blackfin/include/asm/barrier.h index ebb189507dd7..19283a16ac08 100644 --- a/arch/blackfin/include/asm/barrier.h +++ b/arch/blackfin/include/asm/barrier.h | |||
@@ -23,26 +23,10 @@ | |||
23 | # define rmb() do { barrier(); smp_check_barrier(); } while (0) | 23 | # define rmb() do { barrier(); smp_check_barrier(); } while (0) |
24 | # define wmb() do { barrier(); smp_mark_barrier(); } while (0) | 24 | # define wmb() do { barrier(); smp_mark_barrier(); } while (0) |
25 | # define read_barrier_depends() do { barrier(); smp_check_barrier(); } while (0) | 25 | # define read_barrier_depends() do { barrier(); smp_check_barrier(); } while (0) |
26 | #else | ||
27 | # define mb() barrier() | ||
28 | # define rmb() barrier() | ||
29 | # define wmb() barrier() | ||
30 | # define read_barrier_depends() do { } while (0) | ||
31 | #endif | 26 | #endif |
32 | 27 | ||
33 | #else /* !CONFIG_SMP */ | ||
34 | |||
35 | #define mb() barrier() | ||
36 | #define rmb() barrier() | ||
37 | #define wmb() barrier() | ||
38 | #define read_barrier_depends() do { } while (0) | ||
39 | |||
40 | #endif /* !CONFIG_SMP */ | 28 | #endif /* !CONFIG_SMP */ |
41 | 29 | ||
42 | #define smp_mb() mb() | 30 | #include <asm-generic/barrier.h> |
43 | #define smp_rmb() rmb() | ||
44 | #define smp_wmb() wmb() | ||
45 | #define set_mb(var, value) do { var = value; mb(); } while (0) | ||
46 | #define smp_read_barrier_depends() read_barrier_depends() | ||
47 | 31 | ||
48 | #endif /* _BLACKFIN_BARRIER_H */ | 32 | #endif /* _BLACKFIN_BARRIER_H */ |
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index b06caf649a95..199b1a9dab89 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild | |||
@@ -3,6 +3,7 @@ header-y += arch-v10/ | |||
3 | header-y += arch-v32/ | 3 | header-y += arch-v32/ |
4 | 4 | ||
5 | 5 | ||
6 | generic-y += barrier.h | ||
6 | generic-y += clkdev.h | 7 | generic-y += clkdev.h |
7 | generic-y += exec.h | 8 | generic-y += exec.h |
8 | generic-y += kvm_para.h | 9 | generic-y += kvm_para.h |
diff --git a/arch/cris/include/asm/barrier.h b/arch/cris/include/asm/barrier.h deleted file mode 100644 index 198ad7fa6b25..000000000000 --- a/arch/cris/include/asm/barrier.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | #ifndef __ASM_CRIS_BARRIER_H | ||
2 | #define __ASM_CRIS_BARRIER_H | ||
3 | |||
4 | #define nop() __asm__ __volatile__ ("nop"); | ||
5 | |||
6 | #define barrier() __asm__ __volatile__("": : :"memory") | ||
7 | #define mb() barrier() | ||
8 | #define rmb() mb() | ||
9 | #define wmb() mb() | ||
10 | #define read_barrier_depends() do { } while(0) | ||
11 | #define set_mb(var, value) do { var = value; mb(); } while (0) | ||
12 | |||
13 | #ifdef CONFIG_SMP | ||
14 | #define smp_mb() mb() | ||
15 | #define smp_rmb() rmb() | ||
16 | #define smp_wmb() wmb() | ||
17 | #define smp_read_barrier_depends() read_barrier_depends() | ||
18 | #else | ||
19 | #define smp_mb() barrier() | ||
20 | #define smp_rmb() barrier() | ||
21 | #define smp_wmb() barrier() | ||
22 | #define smp_read_barrier_depends() do { } while(0) | ||
23 | #endif | ||
24 | |||
25 | #endif /* __ASM_CRIS_BARRIER_H */ | ||
diff --git a/arch/frv/include/asm/barrier.h b/arch/frv/include/asm/barrier.h index 06776ad9f5e9..abbef470154c 100644 --- a/arch/frv/include/asm/barrier.h +++ b/arch/frv/include/asm/barrier.h | |||
@@ -17,13 +17,7 @@ | |||
17 | #define mb() asm volatile ("membar" : : :"memory") | 17 | #define mb() asm volatile ("membar" : : :"memory") |
18 | #define rmb() asm volatile ("membar" : : :"memory") | 18 | #define rmb() asm volatile ("membar" : : :"memory") |
19 | #define wmb() asm volatile ("membar" : : :"memory") | 19 | #define wmb() asm volatile ("membar" : : :"memory") |
20 | #define read_barrier_depends() do { } while (0) | ||
21 | 20 | ||
22 | #define smp_mb() barrier() | 21 | #include <asm-generic/barrier.h> |
23 | #define smp_rmb() barrier() | ||
24 | #define smp_wmb() barrier() | ||
25 | #define smp_read_barrier_depends() do {} while(0) | ||
26 | #define set_mb(var, value) \ | ||
27 | do { var = (value); barrier(); } while (0) | ||
28 | 22 | ||
29 | #endif /* _ASM_BARRIER_H */ | 23 | #endif /* _ASM_BARRIER_H */ |
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index 67c3450309b7..ada843c701ef 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild | |||
@@ -2,6 +2,7 @@ | |||
2 | header-y += ucontext.h | 2 | header-y += ucontext.h |
3 | 3 | ||
4 | generic-y += auxvec.h | 4 | generic-y += auxvec.h |
5 | generic-y += barrier.h | ||
5 | generic-y += bug.h | 6 | generic-y += bug.h |
6 | generic-y += bugs.h | 7 | generic-y += bugs.h |
7 | generic-y += clkdev.h | 8 | generic-y += clkdev.h |
diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h index 8a64ff2337f6..7aae4cb2a29a 100644 --- a/arch/hexagon/include/asm/atomic.h +++ b/arch/hexagon/include/asm/atomic.h | |||
@@ -160,8 +160,12 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) | |||
160 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, (v)) == 0) | 160 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, (v)) == 0) |
161 | #define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0) | 161 | #define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0) |
162 | 162 | ||
163 | |||
164 | #define atomic_inc_return(v) (atomic_add_return(1, v)) | 163 | #define atomic_inc_return(v) (atomic_add_return(1, v)) |
165 | #define atomic_dec_return(v) (atomic_sub_return(1, v)) | 164 | #define atomic_dec_return(v) (atomic_sub_return(1, v)) |
166 | 165 | ||
166 | #define smp_mb__before_atomic_dec() barrier() | ||
167 | #define smp_mb__after_atomic_dec() barrier() | ||
168 | #define smp_mb__before_atomic_inc() barrier() | ||
169 | #define smp_mb__after_atomic_inc() barrier() | ||
170 | |||
167 | #endif | 171 | #endif |
diff --git a/arch/hexagon/include/asm/barrier.h b/arch/hexagon/include/asm/barrier.h index 1041a8e70ce8..4e863daea25b 100644 --- a/arch/hexagon/include/asm/barrier.h +++ b/arch/hexagon/include/asm/barrier.h | |||
@@ -29,10 +29,6 @@ | |||
29 | #define smp_read_barrier_depends() barrier() | 29 | #define smp_read_barrier_depends() barrier() |
30 | #define smp_wmb() barrier() | 30 | #define smp_wmb() barrier() |
31 | #define smp_mb() barrier() | 31 | #define smp_mb() barrier() |
32 | #define smp_mb__before_atomic_dec() barrier() | ||
33 | #define smp_mb__after_atomic_dec() barrier() | ||
34 | #define smp_mb__before_atomic_inc() barrier() | ||
35 | #define smp_mb__after_atomic_inc() barrier() | ||
36 | 32 | ||
37 | /* Set a value and use a memory barrier. Used by the scheduler somewhere. */ | 33 | /* Set a value and use a memory barrier. Used by the scheduler somewhere. */ |
38 | #define set_mb(var, value) \ | 34 | #define set_mb(var, value) \ |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 4e4119b0e691..a8c3a11dc5ab 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -147,9 +147,6 @@ config PARAVIRT | |||
147 | over full virtualization. However, when run without a hypervisor | 147 | over full virtualization. However, when run without a hypervisor |
148 | the kernel is theoretically slower and slightly larger. | 148 | the kernel is theoretically slower and slightly larger. |
149 | 149 | ||
150 | |||
151 | source "arch/ia64/xen/Kconfig" | ||
152 | |||
153 | endif | 150 | endif |
154 | 151 | ||
155 | choice | 152 | choice |
@@ -175,7 +172,6 @@ config IA64_GENERIC | |||
175 | SGI-SN2 For SGI Altix systems | 172 | SGI-SN2 For SGI Altix systems |
176 | SGI-UV For SGI UV systems | 173 | SGI-UV For SGI UV systems |
177 | Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/> | 174 | Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/> |
178 | Xen-domU For xen domU system | ||
179 | 175 | ||
180 | If you don't know what to do, choose "generic". | 176 | If you don't know what to do, choose "generic". |
181 | 177 | ||
@@ -231,14 +227,6 @@ config IA64_HP_SIM | |||
231 | bool "Ski-simulator" | 227 | bool "Ski-simulator" |
232 | select SWIOTLB | 228 | select SWIOTLB |
233 | 229 | ||
234 | config IA64_XEN_GUEST | ||
235 | bool "Xen guest" | ||
236 | select SWIOTLB | ||
237 | depends on XEN | ||
238 | help | ||
239 | Build a kernel that runs on Xen guest domain. At this moment only | ||
240 | 16KB page size in supported. | ||
241 | |||
242 | endchoice | 230 | endchoice |
243 | 231 | ||
244 | choice | 232 | choice |
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index be7bfa12b705..f37238f45bcd 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile | |||
@@ -51,11 +51,9 @@ core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/ | |||
51 | core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ | 51 | core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ |
52 | core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ | 52 | core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ |
53 | core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/ | 53 | core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/ |
54 | core-$(CONFIG_IA64_XEN_GUEST) += arch/ia64/dig/ | ||
55 | core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/ | 54 | core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/ |
56 | core-$(CONFIG_IA64_SGI_UV) += arch/ia64/uv/ | 55 | core-$(CONFIG_IA64_SGI_UV) += arch/ia64/uv/ |
57 | core-$(CONFIG_KVM) += arch/ia64/kvm/ | 56 | core-$(CONFIG_KVM) += arch/ia64/kvm/ |
58 | core-$(CONFIG_XEN) += arch/ia64/xen/ | ||
59 | 57 | ||
60 | drivers-$(CONFIG_PCI) += arch/ia64/pci/ | 58 | drivers-$(CONFIG_PCI) += arch/ia64/pci/ |
61 | drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ | 59 | drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ |
diff --git a/arch/ia64/configs/xen_domu_defconfig b/arch/ia64/configs/xen_domu_defconfig deleted file mode 100644 index b025acfde5c1..000000000000 --- a/arch/ia64/configs/xen_domu_defconfig +++ /dev/null | |||
@@ -1,199 +0,0 @@ | |||
1 | CONFIG_EXPERIMENTAL=y | ||
2 | CONFIG_SYSVIPC=y | ||
3 | CONFIG_POSIX_MQUEUE=y | ||
4 | CONFIG_IKCONFIG=y | ||
5 | CONFIG_IKCONFIG_PROC=y | ||
6 | CONFIG_LOG_BUF_SHIFT=20 | ||
7 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
8 | CONFIG_BLK_DEV_INITRD=y | ||
9 | CONFIG_KALLSYMS_ALL=y | ||
10 | CONFIG_MODULES=y | ||
11 | CONFIG_MODULE_UNLOAD=y | ||
12 | CONFIG_MODVERSIONS=y | ||
13 | CONFIG_MODULE_SRCVERSION_ALL=y | ||
14 | # CONFIG_BLK_DEV_BSG is not set | ||
15 | CONFIG_PARAVIRT_GUEST=y | ||
16 | CONFIG_IA64_XEN_GUEST=y | ||
17 | CONFIG_MCKINLEY=y | ||
18 | CONFIG_IA64_CYCLONE=y | ||
19 | CONFIG_SMP=y | ||
20 | CONFIG_NR_CPUS=16 | ||
21 | CONFIG_HOTPLUG_CPU=y | ||
22 | CONFIG_PERMIT_BSP_REMOVE=y | ||
23 | CONFIG_FORCE_CPEI_RETARGET=y | ||
24 | CONFIG_IA64_MCA_RECOVERY=y | ||
25 | CONFIG_PERFMON=y | ||
26 | CONFIG_IA64_PALINFO=y | ||
27 | CONFIG_KEXEC=y | ||
28 | CONFIG_EFI_VARS=y | ||
29 | CONFIG_BINFMT_MISC=m | ||
30 | CONFIG_ACPI_PROCFS=y | ||
31 | CONFIG_ACPI_BUTTON=m | ||
32 | CONFIG_ACPI_FAN=m | ||
33 | CONFIG_ACPI_PROCESSOR=m | ||
34 | CONFIG_ACPI_CONTAINER=m | ||
35 | CONFIG_HOTPLUG_PCI=y | ||
36 | CONFIG_HOTPLUG_PCI_ACPI=m | ||
37 | CONFIG_PACKET=y | ||
38 | CONFIG_UNIX=y | ||
39 | CONFIG_INET=y | ||
40 | CONFIG_IP_MULTICAST=y | ||
41 | CONFIG_ARPD=y | ||
42 | CONFIG_SYN_COOKIES=y | ||
43 | # CONFIG_INET_LRO is not set | ||
44 | # CONFIG_IPV6 is not set | ||
45 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
46 | CONFIG_BLK_DEV_LOOP=m | ||
47 | CONFIG_BLK_DEV_CRYPTOLOOP=m | ||
48 | CONFIG_BLK_DEV_NBD=m | ||
49 | CONFIG_BLK_DEV_RAM=y | ||
50 | CONFIG_IDE=y | ||
51 | CONFIG_BLK_DEV_IDECD=y | ||
52 | CONFIG_BLK_DEV_GENERIC=y | ||
53 | CONFIG_BLK_DEV_CMD64X=y | ||
54 | CONFIG_BLK_DEV_PIIX=y | ||
55 | CONFIG_SCSI=y | ||
56 | CONFIG_BLK_DEV_SD=y | ||
57 | CONFIG_CHR_DEV_ST=m | ||
58 | CONFIG_BLK_DEV_SR=m | ||
59 | CONFIG_CHR_DEV_SG=m | ||
60 | CONFIG_SCSI_SYM53C8XX_2=y | ||
61 | CONFIG_SCSI_QLOGIC_1280=y | ||
62 | CONFIG_MD=y | ||
63 | CONFIG_BLK_DEV_MD=m | ||
64 | CONFIG_MD_LINEAR=m | ||
65 | CONFIG_MD_RAID0=m | ||
66 | CONFIG_MD_RAID1=m | ||
67 | CONFIG_MD_MULTIPATH=m | ||
68 | CONFIG_BLK_DEV_DM=m | ||
69 | CONFIG_DM_CRYPT=m | ||
70 | CONFIG_DM_SNAPSHOT=m | ||
71 | CONFIG_DM_MIRROR=m | ||
72 | CONFIG_DM_ZERO=m | ||
73 | CONFIG_FUSION=y | ||
74 | CONFIG_FUSION_SPI=y | ||
75 | CONFIG_FUSION_FC=y | ||
76 | CONFIG_FUSION_CTL=y | ||
77 | CONFIG_NETDEVICES=y | ||
78 | CONFIG_DUMMY=m | ||
79 | CONFIG_NET_ETHERNET=y | ||
80 | CONFIG_NET_TULIP=y | ||
81 | CONFIG_TULIP=m | ||
82 | CONFIG_NET_PCI=y | ||
83 | CONFIG_NET_VENDOR_INTEL=y | ||
84 | CONFIG_E100=m | ||
85 | CONFIG_E1000=y | ||
86 | CONFIG_TIGON3=y | ||
87 | CONFIG_NETCONSOLE=y | ||
88 | # CONFIG_SERIO_SERPORT is not set | ||
89 | CONFIG_GAMEPORT=m | ||
90 | CONFIG_SERIAL_NONSTANDARD=y | ||
91 | CONFIG_SERIAL_8250=y | ||
92 | CONFIG_SERIAL_8250_CONSOLE=y | ||
93 | CONFIG_SERIAL_8250_NR_UARTS=6 | ||
94 | CONFIG_SERIAL_8250_EXTENDED=y | ||
95 | CONFIG_SERIAL_8250_SHARE_IRQ=y | ||
96 | # CONFIG_HW_RANDOM is not set | ||
97 | CONFIG_EFI_RTC=y | ||
98 | CONFIG_RAW_DRIVER=m | ||
99 | CONFIG_HPET=y | ||
100 | CONFIG_AGP=m | ||
101 | CONFIG_DRM=m | ||
102 | CONFIG_DRM_TDFX=m | ||
103 | CONFIG_DRM_R128=m | ||
104 | CONFIG_DRM_RADEON=m | ||
105 | CONFIG_DRM_MGA=m | ||
106 | CONFIG_DRM_SIS=m | ||
107 | CONFIG_HID_GYRATION=y | ||
108 | CONFIG_HID_NTRIG=y | ||
109 | CONFIG_HID_PANTHERLORD=y | ||
110 | CONFIG_HID_PETALYNX=y | ||
111 | CONFIG_HID_SAMSUNG=y | ||
112 | CONFIG_HID_SONY=y | ||
113 | CONFIG_HID_SUNPLUS=y | ||
114 | CONFIG_HID_TOPSEED=y | ||
115 | CONFIG_USB=y | ||
116 | CONFIG_USB_DEVICEFS=y | ||
117 | CONFIG_USB_EHCI_HCD=m | ||
118 | CONFIG_USB_OHCI_HCD=m | ||
119 | CONFIG_USB_UHCI_HCD=y | ||
120 | CONFIG_USB_STORAGE=m | ||
121 | CONFIG_EXT2_FS=y | ||
122 | CONFIG_EXT2_FS_XATTR=y | ||
123 | CONFIG_EXT2_FS_POSIX_ACL=y | ||
124 | CONFIG_EXT2_FS_SECURITY=y | ||
125 | CONFIG_EXT3_FS=y | ||
126 | CONFIG_EXT3_FS_POSIX_ACL=y | ||
127 | CONFIG_EXT3_FS_SECURITY=y | ||
128 | CONFIG_REISERFS_FS=y | ||
129 | CONFIG_REISERFS_FS_XATTR=y | ||
130 | CONFIG_REISERFS_FS_POSIX_ACL=y | ||
131 | CONFIG_REISERFS_FS_SECURITY=y | ||
132 | CONFIG_XFS_FS=y | ||
133 | CONFIG_AUTOFS_FS=y | ||
134 | CONFIG_AUTOFS4_FS=y | ||
135 | CONFIG_ISO9660_FS=m | ||
136 | CONFIG_JOLIET=y | ||
137 | CONFIG_UDF_FS=m | ||
138 | CONFIG_VFAT_FS=y | ||
139 | CONFIG_NTFS_FS=m | ||
140 | CONFIG_PROC_KCORE=y | ||
141 | CONFIG_TMPFS=y | ||
142 | CONFIG_HUGETLBFS=y | ||
143 | CONFIG_NFS_FS=m | ||
144 | CONFIG_NFS_V3=y | ||
145 | CONFIG_NFS_V4=y | ||
146 | CONFIG_NFSD=m | ||
147 | CONFIG_NFSD_V4=y | ||
148 | CONFIG_SMB_FS=m | ||
149 | CONFIG_SMB_NLS_DEFAULT=y | ||
150 | CONFIG_CIFS=m | ||
151 | CONFIG_PARTITION_ADVANCED=y | ||
152 | CONFIG_SGI_PARTITION=y | ||
153 | CONFIG_EFI_PARTITION=y | ||
154 | CONFIG_NLS_CODEPAGE_437=y | ||
155 | CONFIG_NLS_CODEPAGE_737=m | ||
156 | CONFIG_NLS_CODEPAGE_775=m | ||
157 | CONFIG_NLS_CODEPAGE_850=m | ||
158 | CONFIG_NLS_CODEPAGE_852=m | ||
159 | CONFIG_NLS_CODEPAGE_855=m | ||
160 | CONFIG_NLS_CODEPAGE_857=m | ||
161 | CONFIG_NLS_CODEPAGE_860=m | ||
162 | CONFIG_NLS_CODEPAGE_861=m | ||
163 | CONFIG_NLS_CODEPAGE_862=m | ||
164 | CONFIG_NLS_CODEPAGE_863=m | ||
165 | CONFIG_NLS_CODEPAGE_864=m | ||
166 | CONFIG_NLS_CODEPAGE_865=m | ||
167 | CONFIG_NLS_CODEPAGE_866=m | ||
168 | CONFIG_NLS_CODEPAGE_869=m | ||
169 | CONFIG_NLS_CODEPAGE_936=m | ||
170 | CONFIG_NLS_CODEPAGE_950=m | ||
171 | CONFIG_NLS_CODEPAGE_932=m | ||
172 | CONFIG_NLS_CODEPAGE_949=m | ||
173 | CONFIG_NLS_CODEPAGE_874=m | ||
174 | CONFIG_NLS_ISO8859_8=m | ||
175 | CONFIG_NLS_CODEPAGE_1250=m | ||
176 | CONFIG_NLS_CODEPAGE_1251=m | ||
177 | CONFIG_NLS_ISO8859_1=y | ||
178 | CONFIG_NLS_ISO8859_2=m | ||
179 | CONFIG_NLS_ISO8859_3=m | ||
180 | CONFIG_NLS_ISO8859_4=m | ||
181 | CONFIG_NLS_ISO8859_5=m | ||
182 | CONFIG_NLS_ISO8859_6=m | ||
183 | CONFIG_NLS_ISO8859_7=m | ||
184 | CONFIG_NLS_ISO8859_9=m | ||
185 | CONFIG_NLS_ISO8859_13=m | ||
186 | CONFIG_NLS_ISO8859_14=m | ||
187 | CONFIG_NLS_ISO8859_15=m | ||
188 | CONFIG_NLS_KOI8_R=m | ||
189 | CONFIG_NLS_KOI8_U=m | ||
190 | CONFIG_NLS_UTF8=m | ||
191 | CONFIG_MAGIC_SYSRQ=y | ||
192 | CONFIG_DEBUG_KERNEL=y | ||
193 | CONFIG_DEBUG_MUTEXES=y | ||
194 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
195 | CONFIG_IA64_GRANULE_16MB=y | ||
196 | CONFIG_CRYPTO_ECB=m | ||
197 | CONFIG_CRYPTO_PCBC=m | ||
198 | CONFIG_CRYPTO_MD5=y | ||
199 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | ||
diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index faa1bf0da815..d651102a4d45 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h | |||
@@ -111,8 +111,6 @@ static inline const char *acpi_get_sysname (void) | |||
111 | return "uv"; | 111 | return "uv"; |
112 | # elif defined (CONFIG_IA64_DIG) | 112 | # elif defined (CONFIG_IA64_DIG) |
113 | return "dig"; | 113 | return "dig"; |
114 | # elif defined (CONFIG_IA64_XEN_GUEST) | ||
115 | return "xen"; | ||
116 | # elif defined(CONFIG_IA64_DIG_VTD) | 114 | # elif defined(CONFIG_IA64_DIG_VTD) |
117 | return "dig_vtd"; | 115 | return "dig_vtd"; |
118 | # else | 116 | # else |
diff --git a/arch/ia64/include/asm/barrier.h b/arch/ia64/include/asm/barrier.h index 60576e06b6fb..d0a69aa35e27 100644 --- a/arch/ia64/include/asm/barrier.h +++ b/arch/ia64/include/asm/barrier.h | |||
@@ -45,14 +45,37 @@ | |||
45 | # define smp_rmb() rmb() | 45 | # define smp_rmb() rmb() |
46 | # define smp_wmb() wmb() | 46 | # define smp_wmb() wmb() |
47 | # define smp_read_barrier_depends() read_barrier_depends() | 47 | # define smp_read_barrier_depends() read_barrier_depends() |
48 | |||
48 | #else | 49 | #else |
50 | |||
49 | # define smp_mb() barrier() | 51 | # define smp_mb() barrier() |
50 | # define smp_rmb() barrier() | 52 | # define smp_rmb() barrier() |
51 | # define smp_wmb() barrier() | 53 | # define smp_wmb() barrier() |
52 | # define smp_read_barrier_depends() do { } while(0) | 54 | # define smp_read_barrier_depends() do { } while(0) |
55 | |||
53 | #endif | 56 | #endif |
54 | 57 | ||
55 | /* | 58 | /* |
59 | * IA64 GCC turns volatile stores into st.rel and volatile loads into ld.acq no | ||
60 | * need for asm trickery! | ||
61 | */ | ||
62 | |||
63 | #define smp_store_release(p, v) \ | ||
64 | do { \ | ||
65 | compiletime_assert_atomic_type(*p); \ | ||
66 | barrier(); \ | ||
67 | ACCESS_ONCE(*p) = (v); \ | ||
68 | } while (0) | ||
69 | |||
70 | #define smp_load_acquire(p) \ | ||
71 | ({ \ | ||
72 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
73 | compiletime_assert_atomic_type(*p); \ | ||
74 | barrier(); \ | ||
75 | ___p1; \ | ||
76 | }) | ||
77 | |||
78 | /* | ||
56 | * XXX check on this ---I suspect what Linus really wants here is | 79 | * XXX check on this ---I suspect what Linus really wants here is |
57 | * acquire vs release semantics but we can't discuss this stuff with | 80 | * acquire vs release semantics but we can't discuss this stuff with |
58 | * Linus just yet. Grrr... | 81 | * Linus just yet. Grrr... |
diff --git a/arch/ia64/include/asm/machvec.h b/arch/ia64/include/asm/machvec.h index 2d1ad4b11a85..9c39bdfc2da8 100644 --- a/arch/ia64/include/asm/machvec.h +++ b/arch/ia64/include/asm/machvec.h | |||
@@ -113,8 +113,6 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); | |||
113 | # include <asm/machvec_sn2.h> | 113 | # include <asm/machvec_sn2.h> |
114 | # elif defined (CONFIG_IA64_SGI_UV) | 114 | # elif defined (CONFIG_IA64_SGI_UV) |
115 | # include <asm/machvec_uv.h> | 115 | # include <asm/machvec_uv.h> |
116 | # elif defined (CONFIG_IA64_XEN_GUEST) | ||
117 | # include <asm/machvec_xen.h> | ||
118 | # elif defined (CONFIG_IA64_GENERIC) | 116 | # elif defined (CONFIG_IA64_GENERIC) |
119 | 117 | ||
120 | # ifdef MACHVEC_PLATFORM_HEADER | 118 | # ifdef MACHVEC_PLATFORM_HEADER |
diff --git a/arch/ia64/include/asm/machvec_xen.h b/arch/ia64/include/asm/machvec_xen.h deleted file mode 100644 index 8b8bd0eb3923..000000000000 --- a/arch/ia64/include/asm/machvec_xen.h +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | #ifndef _ASM_IA64_MACHVEC_XEN_h | ||
2 | #define _ASM_IA64_MACHVEC_XEN_h | ||
3 | |||
4 | extern ia64_mv_setup_t dig_setup; | ||
5 | extern ia64_mv_cpu_init_t xen_cpu_init; | ||
6 | extern ia64_mv_irq_init_t xen_irq_init; | ||
7 | extern ia64_mv_send_ipi_t xen_platform_send_ipi; | ||
8 | |||
9 | /* | ||
10 | * This stuff has dual use! | ||
11 | * | ||
12 | * For a generic kernel, the macros are used to initialize the | ||
13 | * platform's machvec structure. When compiling a non-generic kernel, | ||
14 | * the macros are used directly. | ||
15 | */ | ||
16 | #define ia64_platform_name "xen" | ||
17 | #define platform_setup dig_setup | ||
18 | #define platform_cpu_init xen_cpu_init | ||
19 | #define platform_irq_init xen_irq_init | ||
20 | #define platform_send_ipi xen_platform_send_ipi | ||
21 | |||
22 | #endif /* _ASM_IA64_MACHVEC_XEN_h */ | ||
diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/meminit.h index 61c7b1750b16..092f1c91b36c 100644 --- a/arch/ia64/include/asm/meminit.h +++ b/arch/ia64/include/asm/meminit.h | |||
@@ -18,7 +18,6 @@ | |||
18 | * - crash dumping code reserved region | 18 | * - crash dumping code reserved region |
19 | * - Kernel memory map built from EFI memory map | 19 | * - Kernel memory map built from EFI memory map |
20 | * - ELF core header | 20 | * - ELF core header |
21 | * - xen start info if CONFIG_XEN | ||
22 | * | 21 | * |
23 | * More could be added if necessary | 22 | * More could be added if necessary |
24 | */ | 23 | */ |
diff --git a/arch/ia64/include/asm/paravirt.h b/arch/ia64/include/asm/paravirt.h index b149b88ea795..b53518a98026 100644 --- a/arch/ia64/include/asm/paravirt.h +++ b/arch/ia64/include/asm/paravirt.h | |||
@@ -75,7 +75,6 @@ void *paravirt_get_gate_section(void); | |||
75 | #ifdef CONFIG_PARAVIRT_GUEST | 75 | #ifdef CONFIG_PARAVIRT_GUEST |
76 | 76 | ||
77 | #define PARAVIRT_HYPERVISOR_TYPE_DEFAULT 0 | 77 | #define PARAVIRT_HYPERVISOR_TYPE_DEFAULT 0 |
78 | #define PARAVIRT_HYPERVISOR_TYPE_XEN 1 | ||
79 | 78 | ||
80 | #ifndef __ASSEMBLY__ | 79 | #ifndef __ASSEMBLY__ |
81 | 80 | ||
diff --git a/arch/ia64/include/asm/pvclock-abi.h b/arch/ia64/include/asm/pvclock-abi.h index 44ef9ef8f5b3..42b233bedeb5 100644 --- a/arch/ia64/include/asm/pvclock-abi.h +++ b/arch/ia64/include/asm/pvclock-abi.h | |||
@@ -11,7 +11,7 @@ | |||
11 | /* | 11 | /* |
12 | * These structs MUST NOT be changed. | 12 | * These structs MUST NOT be changed. |
13 | * They are the ABI between hypervisor and guest OS. | 13 | * They are the ABI between hypervisor and guest OS. |
14 | * Both Xen and KVM are using this. | 14 | * KVM is using this. |
15 | * | 15 | * |
16 | * pvclock_vcpu_time_info holds the system time and the tsc timestamp | 16 | * pvclock_vcpu_time_info holds the system time and the tsc timestamp |
17 | * of the last update. So the guest can use the tsc delta to get a | 17 | * of the last update. So the guest can use the tsc delta to get a |
diff --git a/arch/ia64/include/asm/sync_bitops.h b/arch/ia64/include/asm/sync_bitops.h deleted file mode 100644 index 593c12eeb270..000000000000 --- a/arch/ia64/include/asm/sync_bitops.h +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | #ifndef _ASM_IA64_SYNC_BITOPS_H | ||
2 | #define _ASM_IA64_SYNC_BITOPS_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
6 | * | ||
7 | * Based on synch_bitops.h which Dan Magenhaimer wrote. | ||
8 | * | ||
9 | * bit operations which provide guaranteed strong synchronisation | ||
10 | * when communicating with Xen or other guest OSes running on other CPUs. | ||
11 | */ | ||
12 | |||
13 | static inline void sync_set_bit(int nr, volatile void *addr) | ||
14 | { | ||
15 | set_bit(nr, addr); | ||
16 | } | ||
17 | |||
18 | static inline void sync_clear_bit(int nr, volatile void *addr) | ||
19 | { | ||
20 | clear_bit(nr, addr); | ||
21 | } | ||
22 | |||
23 | static inline void sync_change_bit(int nr, volatile void *addr) | ||
24 | { | ||
25 | change_bit(nr, addr); | ||
26 | } | ||
27 | |||
28 | static inline int sync_test_and_set_bit(int nr, volatile void *addr) | ||
29 | { | ||
30 | return test_and_set_bit(nr, addr); | ||
31 | } | ||
32 | |||
33 | static inline int sync_test_and_clear_bit(int nr, volatile void *addr) | ||
34 | { | ||
35 | return test_and_clear_bit(nr, addr); | ||
36 | } | ||
37 | |||
38 | static inline int sync_test_and_change_bit(int nr, volatile void *addr) | ||
39 | { | ||
40 | return test_and_change_bit(nr, addr); | ||
41 | } | ||
42 | |||
43 | static inline int sync_test_bit(int nr, const volatile void *addr) | ||
44 | { | ||
45 | return test_bit(nr, addr); | ||
46 | } | ||
47 | |||
48 | #define sync_cmpxchg(ptr, old, new) \ | ||
49 | ((__typeof__(*(ptr)))cmpxchg_acq((ptr), (old), (new))) | ||
50 | |||
51 | #endif /* _ASM_IA64_SYNC_BITOPS_H */ | ||
diff --git a/arch/ia64/include/asm/xen/events.h b/arch/ia64/include/asm/xen/events.h deleted file mode 100644 index baa74c82aa71..000000000000 --- a/arch/ia64/include/asm/xen/events.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/include/asm/xen/events.h | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | #ifndef _ASM_IA64_XEN_EVENTS_H | ||
23 | #define _ASM_IA64_XEN_EVENTS_H | ||
24 | |||
25 | enum ipi_vector { | ||
26 | XEN_RESCHEDULE_VECTOR, | ||
27 | XEN_IPI_VECTOR, | ||
28 | XEN_CMCP_VECTOR, | ||
29 | XEN_CPEP_VECTOR, | ||
30 | |||
31 | XEN_NR_IPIS, | ||
32 | }; | ||
33 | |||
34 | static inline int xen_irqs_disabled(struct pt_regs *regs) | ||
35 | { | ||
36 | return !(ia64_psr(regs)->i); | ||
37 | } | ||
38 | |||
39 | #define irq_ctx_init(cpu) do { } while (0) | ||
40 | |||
41 | #endif /* _ASM_IA64_XEN_EVENTS_H */ | ||
diff --git a/arch/ia64/include/asm/xen/hypercall.h b/arch/ia64/include/asm/xen/hypercall.h deleted file mode 100644 index ed28bcd5bb85..000000000000 --- a/arch/ia64/include/asm/xen/hypercall.h +++ /dev/null | |||
@@ -1,265 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * hypercall.h | ||
3 | * | ||
4 | * Linux-specific hypervisor handling. | ||
5 | * | ||
6 | * Copyright (c) 2002-2004, K A Fraser | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation; or, when distributed | ||
11 | * separately from the Linux kernel or incorporated into other | ||
12 | * software packages, subject to the following license: | ||
13 | * | ||
14 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
15 | * of this source file (the "Software"), to deal in the Software without | ||
16 | * restriction, including without limitation the rights to use, copy, modify, | ||
17 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | ||
18 | * and to permit persons to whom the Software is furnished to do so, subject to | ||
19 | * the following conditions: | ||
20 | * | ||
21 | * The above copyright notice and this permission notice shall be included in | ||
22 | * all copies or substantial portions of the Software. | ||
23 | * | ||
24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
30 | * IN THE SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | #ifndef _ASM_IA64_XEN_HYPERCALL_H | ||
34 | #define _ASM_IA64_XEN_HYPERCALL_H | ||
35 | |||
36 | #include <xen/interface/xen.h> | ||
37 | #include <xen/interface/physdev.h> | ||
38 | #include <xen/interface/sched.h> | ||
39 | #include <asm/xen/xcom_hcall.h> | ||
40 | struct xencomm_handle; | ||
41 | extern unsigned long __hypercall(unsigned long a1, unsigned long a2, | ||
42 | unsigned long a3, unsigned long a4, | ||
43 | unsigned long a5, unsigned long cmd); | ||
44 | |||
45 | /* | ||
46 | * Assembler stubs for hyper-calls. | ||
47 | */ | ||
48 | |||
49 | #define _hypercall0(type, name) \ | ||
50 | ({ \ | ||
51 | long __res; \ | ||
52 | __res = __hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name);\ | ||
53 | (type)__res; \ | ||
54 | }) | ||
55 | |||
56 | #define _hypercall1(type, name, a1) \ | ||
57 | ({ \ | ||
58 | long __res; \ | ||
59 | __res = __hypercall((unsigned long)a1, \ | ||
60 | 0, 0, 0, 0, __HYPERVISOR_##name); \ | ||
61 | (type)__res; \ | ||
62 | }) | ||
63 | |||
64 | #define _hypercall2(type, name, a1, a2) \ | ||
65 | ({ \ | ||
66 | long __res; \ | ||
67 | __res = __hypercall((unsigned long)a1, \ | ||
68 | (unsigned long)a2, \ | ||
69 | 0, 0, 0, __HYPERVISOR_##name); \ | ||
70 | (type)__res; \ | ||
71 | }) | ||
72 | |||
73 | #define _hypercall3(type, name, a1, a2, a3) \ | ||
74 | ({ \ | ||
75 | long __res; \ | ||
76 | __res = __hypercall((unsigned long)a1, \ | ||
77 | (unsigned long)a2, \ | ||
78 | (unsigned long)a3, \ | ||
79 | 0, 0, __HYPERVISOR_##name); \ | ||
80 | (type)__res; \ | ||
81 | }) | ||
82 | |||
83 | #define _hypercall4(type, name, a1, a2, a3, a4) \ | ||
84 | ({ \ | ||
85 | long __res; \ | ||
86 | __res = __hypercall((unsigned long)a1, \ | ||
87 | (unsigned long)a2, \ | ||
88 | (unsigned long)a3, \ | ||
89 | (unsigned long)a4, \ | ||
90 | 0, __HYPERVISOR_##name); \ | ||
91 | (type)__res; \ | ||
92 | }) | ||
93 | |||
94 | #define _hypercall5(type, name, a1, a2, a3, a4, a5) \ | ||
95 | ({ \ | ||
96 | long __res; \ | ||
97 | __res = __hypercall((unsigned long)a1, \ | ||
98 | (unsigned long)a2, \ | ||
99 | (unsigned long)a3, \ | ||
100 | (unsigned long)a4, \ | ||
101 | (unsigned long)a5, \ | ||
102 | __HYPERVISOR_##name); \ | ||
103 | (type)__res; \ | ||
104 | }) | ||
105 | |||
106 | |||
107 | static inline int | ||
108 | xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg) | ||
109 | { | ||
110 | return _hypercall2(int, sched_op, cmd, arg); | ||
111 | } | ||
112 | |||
113 | static inline long | ||
114 | HYPERVISOR_set_timer_op(u64 timeout) | ||
115 | { | ||
116 | unsigned long timeout_hi = (unsigned long)(timeout >> 32); | ||
117 | unsigned long timeout_lo = (unsigned long)timeout; | ||
118 | return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); | ||
119 | } | ||
120 | |||
121 | static inline int | ||
122 | xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list, | ||
123 | int nr_calls) | ||
124 | { | ||
125 | return _hypercall2(int, multicall, call_list, nr_calls); | ||
126 | } | ||
127 | |||
128 | static inline int | ||
129 | xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg) | ||
130 | { | ||
131 | return _hypercall2(int, memory_op, cmd, arg); | ||
132 | } | ||
133 | |||
134 | static inline int | ||
135 | xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg) | ||
136 | { | ||
137 | return _hypercall2(int, event_channel_op, cmd, arg); | ||
138 | } | ||
139 | |||
140 | static inline int | ||
141 | xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg) | ||
142 | { | ||
143 | return _hypercall2(int, xen_version, cmd, arg); | ||
144 | } | ||
145 | |||
146 | static inline int | ||
147 | xencomm_arch_hypercall_console_io(int cmd, int count, | ||
148 | struct xencomm_handle *str) | ||
149 | { | ||
150 | return _hypercall3(int, console_io, cmd, count, str); | ||
151 | } | ||
152 | |||
153 | static inline int | ||
154 | xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg) | ||
155 | { | ||
156 | return _hypercall2(int, physdev_op, cmd, arg); | ||
157 | } | ||
158 | |||
159 | static inline int | ||
160 | xencomm_arch_hypercall_grant_table_op(unsigned int cmd, | ||
161 | struct xencomm_handle *uop, | ||
162 | unsigned int count) | ||
163 | { | ||
164 | return _hypercall3(int, grant_table_op, cmd, uop, count); | ||
165 | } | ||
166 | |||
167 | int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); | ||
168 | |||
169 | extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg); | ||
170 | |||
171 | static inline int | ||
172 | xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg) | ||
173 | { | ||
174 | return _hypercall2(int, callback_op, cmd, arg); | ||
175 | } | ||
176 | |||
177 | static inline long | ||
178 | xencomm_arch_hypercall_vcpu_op(int cmd, int cpu, void *arg) | ||
179 | { | ||
180 | return _hypercall3(long, vcpu_op, cmd, cpu, arg); | ||
181 | } | ||
182 | |||
183 | static inline int | ||
184 | HYPERVISOR_physdev_op(int cmd, void *arg) | ||
185 | { | ||
186 | switch (cmd) { | ||
187 | case PHYSDEVOP_eoi: | ||
188 | return _hypercall1(int, ia64_fast_eoi, | ||
189 | ((struct physdev_eoi *)arg)->irq); | ||
190 | default: | ||
191 | return xencomm_hypercall_physdev_op(cmd, arg); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | static inline long | ||
196 | xencomm_arch_hypercall_opt_feature(struct xencomm_handle *arg) | ||
197 | { | ||
198 | return _hypercall1(long, opt_feature, arg); | ||
199 | } | ||
200 | |||
201 | /* for balloon driver */ | ||
202 | #define HYPERVISOR_update_va_mapping(va, new_val, flags) (0) | ||
203 | |||
204 | /* Use xencomm to do hypercalls. */ | ||
205 | #define HYPERVISOR_sched_op xencomm_hypercall_sched_op | ||
206 | #define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op | ||
207 | #define HYPERVISOR_callback_op xencomm_hypercall_callback_op | ||
208 | #define HYPERVISOR_multicall xencomm_hypercall_multicall | ||
209 | #define HYPERVISOR_xen_version xencomm_hypercall_xen_version | ||
210 | #define HYPERVISOR_console_io xencomm_hypercall_console_io | ||
211 | #define HYPERVISOR_memory_op xencomm_hypercall_memory_op | ||
212 | #define HYPERVISOR_suspend xencomm_hypercall_suspend | ||
213 | #define HYPERVISOR_vcpu_op xencomm_hypercall_vcpu_op | ||
214 | #define HYPERVISOR_opt_feature xencomm_hypercall_opt_feature | ||
215 | |||
216 | /* to compile gnttab_copy_grant_page() in drivers/xen/core/gnttab.c */ | ||
217 | #define HYPERVISOR_mmu_update(req, count, success_count, domid) ({ BUG(); 0; }) | ||
218 | |||
219 | static inline int | ||
220 | HYPERVISOR_shutdown( | ||
221 | unsigned int reason) | ||
222 | { | ||
223 | struct sched_shutdown sched_shutdown = { | ||
224 | .reason = reason | ||
225 | }; | ||
226 | |||
227 | int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); | ||
228 | |||
229 | return rc; | ||
230 | } | ||
231 | |||
232 | /* for netfront.c, netback.c */ | ||
233 | #define MULTI_UVMFLAGS_INDEX 0 /* XXX any value */ | ||
234 | |||
235 | static inline void | ||
236 | MULTI_update_va_mapping( | ||
237 | struct multicall_entry *mcl, unsigned long va, | ||
238 | pte_t new_val, unsigned long flags) | ||
239 | { | ||
240 | mcl->op = __HYPERVISOR_update_va_mapping; | ||
241 | mcl->result = 0; | ||
242 | } | ||
243 | |||
244 | static inline void | ||
245 | MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd, | ||
246 | void *uop, unsigned int count) | ||
247 | { | ||
248 | mcl->op = __HYPERVISOR_grant_table_op; | ||
249 | mcl->args[0] = cmd; | ||
250 | mcl->args[1] = (unsigned long)uop; | ||
251 | mcl->args[2] = count; | ||
252 | } | ||
253 | |||
254 | static inline void | ||
255 | MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req, | ||
256 | int count, int *success_count, domid_t domid) | ||
257 | { | ||
258 | mcl->op = __HYPERVISOR_mmu_update; | ||
259 | mcl->args[0] = (unsigned long)req; | ||
260 | mcl->args[1] = count; | ||
261 | mcl->args[2] = (unsigned long)success_count; | ||
262 | mcl->args[3] = domid; | ||
263 | } | ||
264 | |||
265 | #endif /* _ASM_IA64_XEN_HYPERCALL_H */ | ||
diff --git a/arch/ia64/include/asm/xen/hypervisor.h b/arch/ia64/include/asm/xen/hypervisor.h deleted file mode 100644 index 67455c2ed2b1..000000000000 --- a/arch/ia64/include/asm/xen/hypervisor.h +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * hypervisor.h | ||
3 | * | ||
4 | * Linux-specific hypervisor handling. | ||
5 | * | ||
6 | * Copyright (c) 2002-2004, K A Fraser | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation; or, when distributed | ||
11 | * separately from the Linux kernel or incorporated into other | ||
12 | * software packages, subject to the following license: | ||
13 | * | ||
14 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
15 | * of this source file (the "Software"), to deal in the Software without | ||
16 | * restriction, including without limitation the rights to use, copy, modify, | ||
17 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | ||
18 | * and to permit persons to whom the Software is furnished to do so, subject to | ||
19 | * the following conditions: | ||
20 | * | ||
21 | * The above copyright notice and this permission notice shall be included in | ||
22 | * all copies or substantial portions of the Software. | ||
23 | * | ||
24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
30 | * IN THE SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | #ifndef _ASM_IA64_XEN_HYPERVISOR_H | ||
34 | #define _ASM_IA64_XEN_HYPERVISOR_H | ||
35 | |||
36 | #include <linux/err.h> | ||
37 | #include <xen/interface/xen.h> | ||
38 | #include <xen/interface/version.h> /* to compile feature.c */ | ||
39 | #include <xen/features.h> /* to comiple xen-netfront.c */ | ||
40 | #include <xen/xen.h> | ||
41 | #include <asm/xen/hypercall.h> | ||
42 | |||
43 | #ifdef CONFIG_XEN | ||
44 | extern struct shared_info *HYPERVISOR_shared_info; | ||
45 | extern struct start_info *xen_start_info; | ||
46 | |||
47 | void __init xen_setup_vcpu_info_placement(void); | ||
48 | void force_evtchn_callback(void); | ||
49 | |||
50 | /* for drivers/xen/balloon/balloon.c */ | ||
51 | #ifdef CONFIG_XEN_SCRUB_PAGES | ||
52 | #define scrub_pages(_p, _n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT) | ||
53 | #else | ||
54 | #define scrub_pages(_p, _n) ((void)0) | ||
55 | #endif | ||
56 | |||
57 | /* For setup_arch() in arch/ia64/kernel/setup.c */ | ||
58 | void xen_ia64_enable_opt_feature(void); | ||
59 | #endif | ||
60 | |||
61 | #endif /* _ASM_IA64_XEN_HYPERVISOR_H */ | ||
diff --git a/arch/ia64/include/asm/xen/inst.h b/arch/ia64/include/asm/xen/inst.h deleted file mode 100644 index c53a47611208..000000000000 --- a/arch/ia64/include/asm/xen/inst.h +++ /dev/null | |||
@@ -1,486 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/include/asm/xen/inst.h | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <asm/xen/privop.h> | ||
24 | |||
25 | #define ia64_ivt xen_ivt | ||
26 | #define DO_SAVE_MIN XEN_DO_SAVE_MIN | ||
27 | |||
28 | #define __paravirt_switch_to xen_switch_to | ||
29 | #define __paravirt_leave_syscall xen_leave_syscall | ||
30 | #define __paravirt_work_processed_syscall xen_work_processed_syscall | ||
31 | #define __paravirt_leave_kernel xen_leave_kernel | ||
32 | #define __paravirt_pending_syscall_end xen_work_pending_syscall_end | ||
33 | #define __paravirt_work_processed_syscall_target \ | ||
34 | xen_work_processed_syscall | ||
35 | |||
36 | #define paravirt_fsyscall_table xen_fsyscall_table | ||
37 | #define paravirt_fsys_bubble_down xen_fsys_bubble_down | ||
38 | |||
39 | #define MOV_FROM_IFA(reg) \ | ||
40 | movl reg = XSI_IFA; \ | ||
41 | ;; \ | ||
42 | ld8 reg = [reg] | ||
43 | |||
44 | #define MOV_FROM_ITIR(reg) \ | ||
45 | movl reg = XSI_ITIR; \ | ||
46 | ;; \ | ||
47 | ld8 reg = [reg] | ||
48 | |||
49 | #define MOV_FROM_ISR(reg) \ | ||
50 | movl reg = XSI_ISR; \ | ||
51 | ;; \ | ||
52 | ld8 reg = [reg] | ||
53 | |||
54 | #define MOV_FROM_IHA(reg) \ | ||
55 | movl reg = XSI_IHA; \ | ||
56 | ;; \ | ||
57 | ld8 reg = [reg] | ||
58 | |||
59 | #define MOV_FROM_IPSR(pred, reg) \ | ||
60 | (pred) movl reg = XSI_IPSR; \ | ||
61 | ;; \ | ||
62 | (pred) ld8 reg = [reg] | ||
63 | |||
64 | #define MOV_FROM_IIM(reg) \ | ||
65 | movl reg = XSI_IIM; \ | ||
66 | ;; \ | ||
67 | ld8 reg = [reg] | ||
68 | |||
69 | #define MOV_FROM_IIP(reg) \ | ||
70 | movl reg = XSI_IIP; \ | ||
71 | ;; \ | ||
72 | ld8 reg = [reg] | ||
73 | |||
74 | .macro __MOV_FROM_IVR reg, clob | ||
75 | .ifc "\reg", "r8" | ||
76 | XEN_HYPER_GET_IVR | ||
77 | .exitm | ||
78 | .endif | ||
79 | .ifc "\clob", "r8" | ||
80 | XEN_HYPER_GET_IVR | ||
81 | ;; | ||
82 | mov \reg = r8 | ||
83 | .exitm | ||
84 | .endif | ||
85 | |||
86 | mov \clob = r8 | ||
87 | ;; | ||
88 | XEN_HYPER_GET_IVR | ||
89 | ;; | ||
90 | mov \reg = r8 | ||
91 | ;; | ||
92 | mov r8 = \clob | ||
93 | .endm | ||
94 | #define MOV_FROM_IVR(reg, clob) __MOV_FROM_IVR reg, clob | ||
95 | |||
96 | .macro __MOV_FROM_PSR pred, reg, clob | ||
97 | .ifc "\reg", "r8" | ||
98 | (\pred) XEN_HYPER_GET_PSR; | ||
99 | .exitm | ||
100 | .endif | ||
101 | .ifc "\clob", "r8" | ||
102 | (\pred) XEN_HYPER_GET_PSR | ||
103 | ;; | ||
104 | (\pred) mov \reg = r8 | ||
105 | .exitm | ||
106 | .endif | ||
107 | |||
108 | (\pred) mov \clob = r8 | ||
109 | (\pred) XEN_HYPER_GET_PSR | ||
110 | ;; | ||
111 | (\pred) mov \reg = r8 | ||
112 | (\pred) mov r8 = \clob | ||
113 | .endm | ||
114 | #define MOV_FROM_PSR(pred, reg, clob) __MOV_FROM_PSR pred, reg, clob | ||
115 | |||
116 | /* assuming ar.itc is read with interrupt disabled. */ | ||
117 | #define MOV_FROM_ITC(pred, pred_clob, reg, clob) \ | ||
118 | (pred) movl clob = XSI_ITC_OFFSET; \ | ||
119 | ;; \ | ||
120 | (pred) ld8 clob = [clob]; \ | ||
121 | (pred) mov reg = ar.itc; \ | ||
122 | ;; \ | ||
123 | (pred) add reg = reg, clob; \ | ||
124 | ;; \ | ||
125 | (pred) movl clob = XSI_ITC_LAST; \ | ||
126 | ;; \ | ||
127 | (pred) ld8 clob = [clob]; \ | ||
128 | ;; \ | ||
129 | (pred) cmp.geu.unc pred_clob, p0 = clob, reg; \ | ||
130 | ;; \ | ||
131 | (pred_clob) add reg = 1, clob; \ | ||
132 | ;; \ | ||
133 | (pred) movl clob = XSI_ITC_LAST; \ | ||
134 | ;; \ | ||
135 | (pred) st8 [clob] = reg | ||
136 | |||
137 | |||
138 | #define MOV_TO_IFA(reg, clob) \ | ||
139 | movl clob = XSI_IFA; \ | ||
140 | ;; \ | ||
141 | st8 [clob] = reg \ | ||
142 | |||
143 | #define MOV_TO_ITIR(pred, reg, clob) \ | ||
144 | (pred) movl clob = XSI_ITIR; \ | ||
145 | ;; \ | ||
146 | (pred) st8 [clob] = reg | ||
147 | |||
148 | #define MOV_TO_IHA(pred, reg, clob) \ | ||
149 | (pred) movl clob = XSI_IHA; \ | ||
150 | ;; \ | ||
151 | (pred) st8 [clob] = reg | ||
152 | |||
153 | #define MOV_TO_IPSR(pred, reg, clob) \ | ||
154 | (pred) movl clob = XSI_IPSR; \ | ||
155 | ;; \ | ||
156 | (pred) st8 [clob] = reg; \ | ||
157 | ;; | ||
158 | |||
159 | #define MOV_TO_IFS(pred, reg, clob) \ | ||
160 | (pred) movl clob = XSI_IFS; \ | ||
161 | ;; \ | ||
162 | (pred) st8 [clob] = reg; \ | ||
163 | ;; | ||
164 | |||
165 | #define MOV_TO_IIP(reg, clob) \ | ||
166 | movl clob = XSI_IIP; \ | ||
167 | ;; \ | ||
168 | st8 [clob] = reg | ||
169 | |||
170 | .macro ____MOV_TO_KR kr, reg, clob0, clob1 | ||
171 | .ifc "\clob0", "r9" | ||
172 | .error "clob0 \clob0 must not be r9" | ||
173 | .endif | ||
174 | .ifc "\clob1", "r8" | ||
175 | .error "clob1 \clob1 must not be r8" | ||
176 | .endif | ||
177 | |||
178 | .ifnc "\reg", "r9" | ||
179 | .ifnc "\clob1", "r9" | ||
180 | mov \clob1 = r9 | ||
181 | .endif | ||
182 | mov r9 = \reg | ||
183 | .endif | ||
184 | .ifnc "\clob0", "r8" | ||
185 | mov \clob0 = r8 | ||
186 | .endif | ||
187 | mov r8 = \kr | ||
188 | ;; | ||
189 | XEN_HYPER_SET_KR | ||
190 | |||
191 | .ifnc "\reg", "r9" | ||
192 | .ifnc "\clob1", "r9" | ||
193 | mov r9 = \clob1 | ||
194 | .endif | ||
195 | .endif | ||
196 | .ifnc "\clob0", "r8" | ||
197 | mov r8 = \clob0 | ||
198 | .endif | ||
199 | .endm | ||
200 | |||
201 | .macro __MOV_TO_KR kr, reg, clob0, clob1 | ||
202 | .ifc "\clob0", "r9" | ||
203 | ____MOV_TO_KR \kr, \reg, \clob1, \clob0 | ||
204 | .exitm | ||
205 | .endif | ||
206 | .ifc "\clob1", "r8" | ||
207 | ____MOV_TO_KR \kr, \reg, \clob1, \clob0 | ||
208 | .exitm | ||
209 | .endif | ||
210 | |||
211 | ____MOV_TO_KR \kr, \reg, \clob0, \clob1 | ||
212 | .endm | ||
213 | |||
214 | #define MOV_TO_KR(kr, reg, clob0, clob1) \ | ||
215 | __MOV_TO_KR IA64_KR_ ## kr, reg, clob0, clob1 | ||
216 | |||
217 | |||
218 | .macro __ITC_I pred, reg, clob | ||
219 | .ifc "\reg", "r8" | ||
220 | (\pred) XEN_HYPER_ITC_I | ||
221 | .exitm | ||
222 | .endif | ||
223 | .ifc "\clob", "r8" | ||
224 | (\pred) mov r8 = \reg | ||
225 | ;; | ||
226 | (\pred) XEN_HYPER_ITC_I | ||
227 | .exitm | ||
228 | .endif | ||
229 | |||
230 | (\pred) mov \clob = r8 | ||
231 | (\pred) mov r8 = \reg | ||
232 | ;; | ||
233 | (\pred) XEN_HYPER_ITC_I | ||
234 | ;; | ||
235 | (\pred) mov r8 = \clob | ||
236 | ;; | ||
237 | .endm | ||
238 | #define ITC_I(pred, reg, clob) __ITC_I pred, reg, clob | ||
239 | |||
240 | .macro __ITC_D pred, reg, clob | ||
241 | .ifc "\reg", "r8" | ||
242 | (\pred) XEN_HYPER_ITC_D | ||
243 | ;; | ||
244 | .exitm | ||
245 | .endif | ||
246 | .ifc "\clob", "r8" | ||
247 | (\pred) mov r8 = \reg | ||
248 | ;; | ||
249 | (\pred) XEN_HYPER_ITC_D | ||
250 | ;; | ||
251 | .exitm | ||
252 | .endif | ||
253 | |||
254 | (\pred) mov \clob = r8 | ||
255 | (\pred) mov r8 = \reg | ||
256 | ;; | ||
257 | (\pred) XEN_HYPER_ITC_D | ||
258 | ;; | ||
259 | (\pred) mov r8 = \clob | ||
260 | ;; | ||
261 | .endm | ||
262 | #define ITC_D(pred, reg, clob) __ITC_D pred, reg, clob | ||
263 | |||
264 | .macro __ITC_I_AND_D pred_i, pred_d, reg, clob | ||
265 | .ifc "\reg", "r8" | ||
266 | (\pred_i)XEN_HYPER_ITC_I | ||
267 | ;; | ||
268 | (\pred_d)XEN_HYPER_ITC_D | ||
269 | ;; | ||
270 | .exitm | ||
271 | .endif | ||
272 | .ifc "\clob", "r8" | ||
273 | mov r8 = \reg | ||
274 | ;; | ||
275 | (\pred_i)XEN_HYPER_ITC_I | ||
276 | ;; | ||
277 | (\pred_d)XEN_HYPER_ITC_D | ||
278 | ;; | ||
279 | .exitm | ||
280 | .endif | ||
281 | |||
282 | mov \clob = r8 | ||
283 | mov r8 = \reg | ||
284 | ;; | ||
285 | (\pred_i)XEN_HYPER_ITC_I | ||
286 | ;; | ||
287 | (\pred_d)XEN_HYPER_ITC_D | ||
288 | ;; | ||
289 | mov r8 = \clob | ||
290 | ;; | ||
291 | .endm | ||
292 | #define ITC_I_AND_D(pred_i, pred_d, reg, clob) \ | ||
293 | __ITC_I_AND_D pred_i, pred_d, reg, clob | ||
294 | |||
295 | .macro __THASH pred, reg0, reg1, clob | ||
296 | .ifc "\reg0", "r8" | ||
297 | (\pred) mov r8 = \reg1 | ||
298 | (\pred) XEN_HYPER_THASH | ||
299 | .exitm | ||
300 | .endc | ||
301 | .ifc "\reg1", "r8" | ||
302 | (\pred) XEN_HYPER_THASH | ||
303 | ;; | ||
304 | (\pred) mov \reg0 = r8 | ||
305 | ;; | ||
306 | .exitm | ||
307 | .endif | ||
308 | .ifc "\clob", "r8" | ||
309 | (\pred) mov r8 = \reg1 | ||
310 | (\pred) XEN_HYPER_THASH | ||
311 | ;; | ||
312 | (\pred) mov \reg0 = r8 | ||
313 | ;; | ||
314 | .exitm | ||
315 | .endif | ||
316 | |||
317 | (\pred) mov \clob = r8 | ||
318 | (\pred) mov r8 = \reg1 | ||
319 | (\pred) XEN_HYPER_THASH | ||
320 | ;; | ||
321 | (\pred) mov \reg0 = r8 | ||
322 | (\pred) mov r8 = \clob | ||
323 | ;; | ||
324 | .endm | ||
325 | #define THASH(pred, reg0, reg1, clob) __THASH pred, reg0, reg1, clob | ||
326 | |||
327 | #define SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(clob0, clob1) \ | ||
328 | mov clob0 = 1; \ | ||
329 | movl clob1 = XSI_PSR_IC; \ | ||
330 | ;; \ | ||
331 | st4 [clob1] = clob0 \ | ||
332 | ;; | ||
333 | |||
334 | #define SSM_PSR_IC_AND_SRLZ_D(clob0, clob1) \ | ||
335 | ;; \ | ||
336 | srlz.d; \ | ||
337 | mov clob1 = 1; \ | ||
338 | movl clob0 = XSI_PSR_IC; \ | ||
339 | ;; \ | ||
340 | st4 [clob0] = clob1 | ||
341 | |||
342 | #define RSM_PSR_IC(clob) \ | ||
343 | movl clob = XSI_PSR_IC; \ | ||
344 | ;; \ | ||
345 | st4 [clob] = r0; \ | ||
346 | ;; | ||
347 | |||
348 | /* pred will be clobbered */ | ||
349 | #define MASK_TO_PEND_OFS (-1) | ||
350 | #define SSM_PSR_I(pred, pred_clob, clob) \ | ||
351 | (pred) movl clob = XSI_PSR_I_ADDR \ | ||
352 | ;; \ | ||
353 | (pred) ld8 clob = [clob] \ | ||
354 | ;; \ | ||
355 | /* if (pred) vpsr.i = 1 */ \ | ||
356 | /* if (pred) (vcpu->vcpu_info->evtchn_upcall_mask)=0 */ \ | ||
357 | (pred) st1 [clob] = r0, MASK_TO_PEND_OFS \ | ||
358 | ;; \ | ||
359 | /* if (vcpu->vcpu_info->evtchn_upcall_pending) */ \ | ||
360 | (pred) ld1 clob = [clob] \ | ||
361 | ;; \ | ||
362 | (pred) cmp.ne.unc pred_clob, p0 = clob, r0 \ | ||
363 | ;; \ | ||
364 | (pred_clob)XEN_HYPER_SSM_I /* do areal ssm psr.i */ | ||
365 | |||
366 | #define RSM_PSR_I(pred, clob0, clob1) \ | ||
367 | movl clob0 = XSI_PSR_I_ADDR; \ | ||
368 | mov clob1 = 1; \ | ||
369 | ;; \ | ||
370 | ld8 clob0 = [clob0]; \ | ||
371 | ;; \ | ||
372 | (pred) st1 [clob0] = clob1 | ||
373 | |||
374 | #define RSM_PSR_I_IC(clob0, clob1, clob2) \ | ||
375 | movl clob0 = XSI_PSR_I_ADDR; \ | ||
376 | movl clob1 = XSI_PSR_IC; \ | ||
377 | ;; \ | ||
378 | ld8 clob0 = [clob0]; \ | ||
379 | mov clob2 = 1; \ | ||
380 | ;; \ | ||
381 | /* note: clears both vpsr.i and vpsr.ic! */ \ | ||
382 | st1 [clob0] = clob2; \ | ||
383 | st4 [clob1] = r0; \ | ||
384 | ;; | ||
385 | |||
386 | #define RSM_PSR_DT \ | ||
387 | XEN_HYPER_RSM_PSR_DT | ||
388 | |||
389 | #define RSM_PSR_BE_I(clob0, clob1) \ | ||
390 | RSM_PSR_I(p0, clob0, clob1); \ | ||
391 | rum psr.be | ||
392 | |||
393 | #define SSM_PSR_DT_AND_SRLZ_I \ | ||
394 | XEN_HYPER_SSM_PSR_DT | ||
395 | |||
396 | #define BSW_0(clob0, clob1, clob2) \ | ||
397 | ;; \ | ||
398 | /* r16-r31 all now hold bank1 values */ \ | ||
399 | mov clob2 = ar.unat; \ | ||
400 | movl clob0 = XSI_BANK1_R16; \ | ||
401 | movl clob1 = XSI_BANK1_R16 + 8; \ | ||
402 | ;; \ | ||
403 | .mem.offset 0, 0; st8.spill [clob0] = r16, 16; \ | ||
404 | .mem.offset 8, 0; st8.spill [clob1] = r17, 16; \ | ||
405 | ;; \ | ||
406 | .mem.offset 0, 0; st8.spill [clob0] = r18, 16; \ | ||
407 | .mem.offset 8, 0; st8.spill [clob1] = r19, 16; \ | ||
408 | ;; \ | ||
409 | .mem.offset 0, 0; st8.spill [clob0] = r20, 16; \ | ||
410 | .mem.offset 8, 0; st8.spill [clob1] = r21, 16; \ | ||
411 | ;; \ | ||
412 | .mem.offset 0, 0; st8.spill [clob0] = r22, 16; \ | ||
413 | .mem.offset 8, 0; st8.spill [clob1] = r23, 16; \ | ||
414 | ;; \ | ||
415 | .mem.offset 0, 0; st8.spill [clob0] = r24, 16; \ | ||
416 | .mem.offset 8, 0; st8.spill [clob1] = r25, 16; \ | ||
417 | ;; \ | ||
418 | .mem.offset 0, 0; st8.spill [clob0] = r26, 16; \ | ||
419 | .mem.offset 8, 0; st8.spill [clob1] = r27, 16; \ | ||
420 | ;; \ | ||
421 | .mem.offset 0, 0; st8.spill [clob0] = r28, 16; \ | ||
422 | .mem.offset 8, 0; st8.spill [clob1] = r29, 16; \ | ||
423 | ;; \ | ||
424 | .mem.offset 0, 0; st8.spill [clob0] = r30, 16; \ | ||
425 | .mem.offset 8, 0; st8.spill [clob1] = r31, 16; \ | ||
426 | ;; \ | ||
427 | mov clob1 = ar.unat; \ | ||
428 | movl clob0 = XSI_B1NAT; \ | ||
429 | ;; \ | ||
430 | st8 [clob0] = clob1; \ | ||
431 | mov ar.unat = clob2; \ | ||
432 | movl clob0 = XSI_BANKNUM; \ | ||
433 | ;; \ | ||
434 | st4 [clob0] = r0 | ||
435 | |||
436 | |||
437 | /* FIXME: THIS CODE IS NOT NaT SAFE! */ | ||
438 | #define XEN_BSW_1(clob) \ | ||
439 | mov clob = ar.unat; \ | ||
440 | movl r30 = XSI_B1NAT; \ | ||
441 | ;; \ | ||
442 | ld8 r30 = [r30]; \ | ||
443 | mov r31 = 1; \ | ||
444 | ;; \ | ||
445 | mov ar.unat = r30; \ | ||
446 | movl r30 = XSI_BANKNUM; \ | ||
447 | ;; \ | ||
448 | st4 [r30] = r31; \ | ||
449 | movl r30 = XSI_BANK1_R16; \ | ||
450 | movl r31 = XSI_BANK1_R16+8; \ | ||
451 | ;; \ | ||
452 | ld8.fill r16 = [r30], 16; \ | ||
453 | ld8.fill r17 = [r31], 16; \ | ||
454 | ;; \ | ||
455 | ld8.fill r18 = [r30], 16; \ | ||
456 | ld8.fill r19 = [r31], 16; \ | ||
457 | ;; \ | ||
458 | ld8.fill r20 = [r30], 16; \ | ||
459 | ld8.fill r21 = [r31], 16; \ | ||
460 | ;; \ | ||
461 | ld8.fill r22 = [r30], 16; \ | ||
462 | ld8.fill r23 = [r31], 16; \ | ||
463 | ;; \ | ||
464 | ld8.fill r24 = [r30], 16; \ | ||
465 | ld8.fill r25 = [r31], 16; \ | ||
466 | ;; \ | ||
467 | ld8.fill r26 = [r30], 16; \ | ||
468 | ld8.fill r27 = [r31], 16; \ | ||
469 | ;; \ | ||
470 | ld8.fill r28 = [r30], 16; \ | ||
471 | ld8.fill r29 = [r31], 16; \ | ||
472 | ;; \ | ||
473 | ld8.fill r30 = [r30]; \ | ||
474 | ld8.fill r31 = [r31]; \ | ||
475 | ;; \ | ||
476 | mov ar.unat = clob | ||
477 | |||
478 | #define BSW_1(clob0, clob1) XEN_BSW_1(clob1) | ||
479 | |||
480 | |||
481 | #define COVER \ | ||
482 | XEN_HYPER_COVER | ||
483 | |||
484 | #define RFI \ | ||
485 | XEN_HYPER_RFI; \ | ||
486 | dv_serialize_data | ||
diff --git a/arch/ia64/include/asm/xen/interface.h b/arch/ia64/include/asm/xen/interface.h deleted file mode 100644 index e88c5de27410..000000000000 --- a/arch/ia64/include/asm/xen/interface.h +++ /dev/null | |||
@@ -1,363 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch-ia64/hypervisor-if.h | ||
3 | * | ||
4 | * Guest OS interface to IA64 Xen. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | * of this software and associated documentation files (the "Software"), to | ||
8 | * deal in the Software without restriction, including without limitation the | ||
9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
10 | * sell copies of the Software, and to permit persons to whom the Software is | ||
11 | * furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in | ||
14 | * all copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
22 | * DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
24 | * Copyright by those who contributed. (in alphabetical order) | ||
25 | * | ||
26 | * Anthony Xu <anthony.xu@intel.com> | ||
27 | * Eddie Dong <eddie.dong@intel.com> | ||
28 | * Fred Yang <fred.yang@intel.com> | ||
29 | * Kevin Tian <kevin.tian@intel.com> | ||
30 | * Alex Williamson <alex.williamson@hp.com> | ||
31 | * Chris Wright <chrisw@sous-sol.org> | ||
32 | * Christian Limpach <Christian.Limpach@cl.cam.ac.uk> | ||
33 | * Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> | ||
34 | * Hollis Blanchard <hollisb@us.ibm.com> | ||
35 | * Isaku Yamahata <yamahata@valinux.co.jp> | ||
36 | * Jan Beulich <jbeulich@novell.com> | ||
37 | * John Levon <john.levon@sun.com> | ||
38 | * Kazuhiro Suzuki <kaz@jp.fujitsu.com> | ||
39 | * Keir Fraser <keir.fraser@citrix.com> | ||
40 | * Kouya Shimura <kouya@jp.fujitsu.com> | ||
41 | * Masaki Kanno <kanno.masaki@jp.fujitsu.com> | ||
42 | * Matt Chapman <matthewc@hp.com> | ||
43 | * Matthew Chapman <matthewc@hp.com> | ||
44 | * Samuel Thibault <samuel.thibault@eu.citrix.com> | ||
45 | * Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com> | ||
46 | * Tristan Gingold <tgingold@free.fr> | ||
47 | * Tsunehisa Doi <Doi.Tsunehisa@jp.fujitsu.com> | ||
48 | * Yutaka Ezaki <yutaka.ezaki@jp.fujitsu.com> | ||
49 | * Zhang Xin <xing.z.zhang@intel.com> | ||
50 | * Zhang xiantao <xiantao.zhang@intel.com> | ||
51 | * dan.magenheimer@hp.com | ||
52 | * ian.pratt@cl.cam.ac.uk | ||
53 | * michael.fetterman@cl.cam.ac.uk | ||
54 | */ | ||
55 | |||
56 | #ifndef _ASM_IA64_XEN_INTERFACE_H | ||
57 | #define _ASM_IA64_XEN_INTERFACE_H | ||
58 | |||
59 | #define __DEFINE_GUEST_HANDLE(name, type) \ | ||
60 | typedef struct { type *p; } __guest_handle_ ## name | ||
61 | |||
62 | #define DEFINE_GUEST_HANDLE_STRUCT(name) \ | ||
63 | __DEFINE_GUEST_HANDLE(name, struct name) | ||
64 | #define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) | ||
65 | #define GUEST_HANDLE(name) __guest_handle_ ## name | ||
66 | #define GUEST_HANDLE_64(name) GUEST_HANDLE(name) | ||
67 | #define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) | ||
68 | |||
69 | #ifndef __ASSEMBLY__ | ||
70 | /* Explicitly size integers that represent pfns in the public interface | ||
71 | * with Xen so that we could have one ABI that works for 32 and 64 bit | ||
72 | * guests. */ | ||
73 | typedef unsigned long xen_pfn_t; | ||
74 | typedef unsigned long xen_ulong_t; | ||
75 | /* Guest handles for primitive C types. */ | ||
76 | __DEFINE_GUEST_HANDLE(uchar, unsigned char); | ||
77 | __DEFINE_GUEST_HANDLE(uint, unsigned int); | ||
78 | __DEFINE_GUEST_HANDLE(ulong, unsigned long); | ||
79 | |||
80 | DEFINE_GUEST_HANDLE(char); | ||
81 | DEFINE_GUEST_HANDLE(int); | ||
82 | DEFINE_GUEST_HANDLE(long); | ||
83 | DEFINE_GUEST_HANDLE(void); | ||
84 | DEFINE_GUEST_HANDLE(uint64_t); | ||
85 | DEFINE_GUEST_HANDLE(uint32_t); | ||
86 | |||
87 | DEFINE_GUEST_HANDLE(xen_pfn_t); | ||
88 | #define PRI_xen_pfn "lx" | ||
89 | #endif | ||
90 | |||
91 | /* Arch specific VIRQs definition */ | ||
92 | #define VIRQ_ITC VIRQ_ARCH_0 /* V. Virtual itc timer */ | ||
93 | #define VIRQ_MCA_CMC VIRQ_ARCH_1 /* MCA cmc interrupt */ | ||
94 | #define VIRQ_MCA_CPE VIRQ_ARCH_2 /* MCA cpe interrupt */ | ||
95 | |||
96 | /* Maximum number of virtual CPUs in multi-processor guests. */ | ||
97 | /* keep sizeof(struct shared_page) <= PAGE_SIZE. | ||
98 | * this is checked in arch/ia64/xen/hypervisor.c. */ | ||
99 | #define MAX_VIRT_CPUS 64 | ||
100 | |||
101 | #ifndef __ASSEMBLY__ | ||
102 | |||
103 | #define INVALID_MFN (~0UL) | ||
104 | |||
105 | union vac { | ||
106 | unsigned long value; | ||
107 | struct { | ||
108 | int a_int:1; | ||
109 | int a_from_int_cr:1; | ||
110 | int a_to_int_cr:1; | ||
111 | int a_from_psr:1; | ||
112 | int a_from_cpuid:1; | ||
113 | int a_cover:1; | ||
114 | int a_bsw:1; | ||
115 | long reserved:57; | ||
116 | }; | ||
117 | }; | ||
118 | |||
119 | union vdc { | ||
120 | unsigned long value; | ||
121 | struct { | ||
122 | int d_vmsw:1; | ||
123 | int d_extint:1; | ||
124 | int d_ibr_dbr:1; | ||
125 | int d_pmc:1; | ||
126 | int d_to_pmd:1; | ||
127 | int d_itm:1; | ||
128 | long reserved:58; | ||
129 | }; | ||
130 | }; | ||
131 | |||
132 | struct mapped_regs { | ||
133 | union vac vac; | ||
134 | union vdc vdc; | ||
135 | unsigned long virt_env_vaddr; | ||
136 | unsigned long reserved1[29]; | ||
137 | unsigned long vhpi; | ||
138 | unsigned long reserved2[95]; | ||
139 | union { | ||
140 | unsigned long vgr[16]; | ||
141 | unsigned long bank1_regs[16]; /* bank1 regs (r16-r31) | ||
142 | when bank0 active */ | ||
143 | }; | ||
144 | union { | ||
145 | unsigned long vbgr[16]; | ||
146 | unsigned long bank0_regs[16]; /* bank0 regs (r16-r31) | ||
147 | when bank1 active */ | ||
148 | }; | ||
149 | unsigned long vnat; | ||
150 | unsigned long vbnat; | ||
151 | unsigned long vcpuid[5]; | ||
152 | unsigned long reserved3[11]; | ||
153 | unsigned long vpsr; | ||
154 | unsigned long vpr; | ||
155 | unsigned long reserved4[76]; | ||
156 | union { | ||
157 | unsigned long vcr[128]; | ||
158 | struct { | ||
159 | unsigned long dcr; /* CR0 */ | ||
160 | unsigned long itm; | ||
161 | unsigned long iva; | ||
162 | unsigned long rsv1[5]; | ||
163 | unsigned long pta; /* CR8 */ | ||
164 | unsigned long rsv2[7]; | ||
165 | unsigned long ipsr; /* CR16 */ | ||
166 | unsigned long isr; | ||
167 | unsigned long rsv3; | ||
168 | unsigned long iip; | ||
169 | unsigned long ifa; | ||
170 | unsigned long itir; | ||
171 | unsigned long iipa; | ||
172 | unsigned long ifs; | ||
173 | unsigned long iim; /* CR24 */ | ||
174 | unsigned long iha; | ||
175 | unsigned long rsv4[38]; | ||
176 | unsigned long lid; /* CR64 */ | ||
177 | unsigned long ivr; | ||
178 | unsigned long tpr; | ||
179 | unsigned long eoi; | ||
180 | unsigned long irr[4]; | ||
181 | unsigned long itv; /* CR72 */ | ||
182 | unsigned long pmv; | ||
183 | unsigned long cmcv; | ||
184 | unsigned long rsv5[5]; | ||
185 | unsigned long lrr0; /* CR80 */ | ||
186 | unsigned long lrr1; | ||
187 | unsigned long rsv6[46]; | ||
188 | }; | ||
189 | }; | ||
190 | union { | ||
191 | unsigned long reserved5[128]; | ||
192 | struct { | ||
193 | unsigned long precover_ifs; | ||
194 | unsigned long unat; /* not sure if this is needed | ||
195 | until NaT arch is done */ | ||
196 | int interrupt_collection_enabled; /* virtual psr.ic */ | ||
197 | |||
198 | /* virtual interrupt deliverable flag is | ||
199 | * evtchn_upcall_mask in shared info area now. | ||
200 | * interrupt_mask_addr is the address | ||
201 | * of evtchn_upcall_mask for current vcpu | ||
202 | */ | ||
203 | unsigned char *interrupt_mask_addr; | ||
204 | int pending_interruption; | ||
205 | unsigned char vpsr_pp; | ||
206 | unsigned char vpsr_dfh; | ||
207 | unsigned char hpsr_dfh; | ||
208 | unsigned char hpsr_mfh; | ||
209 | unsigned long reserved5_1[4]; | ||
210 | int metaphysical_mode; /* 1 = use metaphys mapping | ||
211 | 0 = use virtual */ | ||
212 | int banknum; /* 0 or 1, which virtual | ||
213 | register bank is active */ | ||
214 | unsigned long rrs[8]; /* region registers */ | ||
215 | unsigned long krs[8]; /* kernel registers */ | ||
216 | unsigned long tmp[16]; /* temp registers | ||
217 | (e.g. for hyperprivops) */ | ||
218 | |||
219 | /* itc paravirtualization | ||
220 | * vAR.ITC = mAR.ITC + itc_offset | ||
221 | * itc_last is one which was lastly passed to | ||
222 | * the guest OS in order to prevent it from | ||
223 | * going backwords. | ||
224 | */ | ||
225 | unsigned long itc_offset; | ||
226 | unsigned long itc_last; | ||
227 | }; | ||
228 | }; | ||
229 | }; | ||
230 | |||
231 | struct arch_vcpu_info { | ||
232 | /* nothing */ | ||
233 | }; | ||
234 | |||
235 | /* | ||
236 | * This structure is used for magic page in domain pseudo physical address | ||
237 | * space and the result of XENMEM_machine_memory_map. | ||
238 | * As the XENMEM_machine_memory_map result, | ||
239 | * xen_memory_map::nr_entries indicates the size in bytes | ||
240 | * including struct xen_ia64_memmap_info. Not the number of entries. | ||
241 | */ | ||
242 | struct xen_ia64_memmap_info { | ||
243 | uint64_t efi_memmap_size; /* size of EFI memory map */ | ||
244 | uint64_t efi_memdesc_size; /* size of an EFI memory map | ||
245 | * descriptor */ | ||
246 | uint32_t efi_memdesc_version; /* memory descriptor version */ | ||
247 | void *memdesc[0]; /* array of efi_memory_desc_t */ | ||
248 | }; | ||
249 | |||
250 | struct arch_shared_info { | ||
251 | /* PFN of the start_info page. */ | ||
252 | unsigned long start_info_pfn; | ||
253 | |||
254 | /* Interrupt vector for event channel. */ | ||
255 | int evtchn_vector; | ||
256 | |||
257 | /* PFN of memmap_info page */ | ||
258 | unsigned int memmap_info_num_pages; /* currently only = 1 case is | ||
259 | supported. */ | ||
260 | unsigned long memmap_info_pfn; | ||
261 | |||
262 | uint64_t pad[31]; | ||
263 | }; | ||
264 | |||
265 | struct xen_callback { | ||
266 | unsigned long ip; | ||
267 | }; | ||
268 | typedef struct xen_callback xen_callback_t; | ||
269 | |||
270 | #endif /* !__ASSEMBLY__ */ | ||
271 | |||
272 | #include <asm/pvclock-abi.h> | ||
273 | |||
274 | /* Size of the shared_info area (this is not related to page size). */ | ||
275 | #define XSI_SHIFT 14 | ||
276 | #define XSI_SIZE (1 << XSI_SHIFT) | ||
277 | /* Log size of mapped_regs area (64 KB - only 4KB is used). */ | ||
278 | #define XMAPPEDREGS_SHIFT 12 | ||
279 | #define XMAPPEDREGS_SIZE (1 << XMAPPEDREGS_SHIFT) | ||
280 | /* Offset of XASI (Xen arch shared info) wrt XSI_BASE. */ | ||
281 | #define XMAPPEDREGS_OFS XSI_SIZE | ||
282 | |||
283 | /* Hyperprivops. */ | ||
284 | #define HYPERPRIVOP_START 0x1 | ||
285 | #define HYPERPRIVOP_RFI (HYPERPRIVOP_START + 0x0) | ||
286 | #define HYPERPRIVOP_RSM_DT (HYPERPRIVOP_START + 0x1) | ||
287 | #define HYPERPRIVOP_SSM_DT (HYPERPRIVOP_START + 0x2) | ||
288 | #define HYPERPRIVOP_COVER (HYPERPRIVOP_START + 0x3) | ||
289 | #define HYPERPRIVOP_ITC_D (HYPERPRIVOP_START + 0x4) | ||
290 | #define HYPERPRIVOP_ITC_I (HYPERPRIVOP_START + 0x5) | ||
291 | #define HYPERPRIVOP_SSM_I (HYPERPRIVOP_START + 0x6) | ||
292 | #define HYPERPRIVOP_GET_IVR (HYPERPRIVOP_START + 0x7) | ||
293 | #define HYPERPRIVOP_GET_TPR (HYPERPRIVOP_START + 0x8) | ||
294 | #define HYPERPRIVOP_SET_TPR (HYPERPRIVOP_START + 0x9) | ||
295 | #define HYPERPRIVOP_EOI (HYPERPRIVOP_START + 0xa) | ||
296 | #define HYPERPRIVOP_SET_ITM (HYPERPRIVOP_START + 0xb) | ||
297 | #define HYPERPRIVOP_THASH (HYPERPRIVOP_START + 0xc) | ||
298 | #define HYPERPRIVOP_PTC_GA (HYPERPRIVOP_START + 0xd) | ||
299 | #define HYPERPRIVOP_ITR_D (HYPERPRIVOP_START + 0xe) | ||
300 | #define HYPERPRIVOP_GET_RR (HYPERPRIVOP_START + 0xf) | ||
301 | #define HYPERPRIVOP_SET_RR (HYPERPRIVOP_START + 0x10) | ||
302 | #define HYPERPRIVOP_SET_KR (HYPERPRIVOP_START + 0x11) | ||
303 | #define HYPERPRIVOP_FC (HYPERPRIVOP_START + 0x12) | ||
304 | #define HYPERPRIVOP_GET_CPUID (HYPERPRIVOP_START + 0x13) | ||
305 | #define HYPERPRIVOP_GET_PMD (HYPERPRIVOP_START + 0x14) | ||
306 | #define HYPERPRIVOP_GET_EFLAG (HYPERPRIVOP_START + 0x15) | ||
307 | #define HYPERPRIVOP_SET_EFLAG (HYPERPRIVOP_START + 0x16) | ||
308 | #define HYPERPRIVOP_RSM_BE (HYPERPRIVOP_START + 0x17) | ||
309 | #define HYPERPRIVOP_GET_PSR (HYPERPRIVOP_START + 0x18) | ||
310 | #define HYPERPRIVOP_SET_RR0_TO_RR4 (HYPERPRIVOP_START + 0x19) | ||
311 | #define HYPERPRIVOP_MAX (0x1a) | ||
312 | |||
313 | /* Fast and light hypercalls. */ | ||
314 | #define __HYPERVISOR_ia64_fast_eoi __HYPERVISOR_arch_1 | ||
315 | |||
316 | /* Xencomm macros. */ | ||
317 | #define XENCOMM_INLINE_MASK 0xf800000000000000UL | ||
318 | #define XENCOMM_INLINE_FLAG 0x8000000000000000UL | ||
319 | |||
320 | #ifndef __ASSEMBLY__ | ||
321 | |||
322 | /* | ||
323 | * Optimization features. | ||
324 | * The hypervisor may do some special optimizations for guests. This hypercall | ||
325 | * can be used to switch on/of these special optimizations. | ||
326 | */ | ||
327 | #define __HYPERVISOR_opt_feature 0x700UL | ||
328 | |||
329 | #define XEN_IA64_OPTF_OFF 0x0 | ||
330 | #define XEN_IA64_OPTF_ON 0x1 | ||
331 | |||
332 | /* | ||
333 | * If this feature is switched on, the hypervisor inserts the | ||
334 | * tlb entries without calling the guests traphandler. | ||
335 | * This is useful in guests using region 7 for identity mapping | ||
336 | * like the linux kernel does. | ||
337 | */ | ||
338 | #define XEN_IA64_OPTF_IDENT_MAP_REG7 1 | ||
339 | |||
340 | /* Identity mapping of region 4 addresses in HVM. */ | ||
341 | #define XEN_IA64_OPTF_IDENT_MAP_REG4 2 | ||
342 | |||
343 | /* Identity mapping of region 5 addresses in HVM. */ | ||
344 | #define XEN_IA64_OPTF_IDENT_MAP_REG5 3 | ||
345 | |||
346 | #define XEN_IA64_OPTF_IDENT_MAP_NOT_SET (0) | ||
347 | |||
348 | struct xen_ia64_opt_feature { | ||
349 | unsigned long cmd; /* Which feature */ | ||
350 | unsigned char on; /* Switch feature on/off */ | ||
351 | union { | ||
352 | struct { | ||
353 | /* The page protection bit mask of the pte. | ||
354 | * This will be or'ed with the pte. */ | ||
355 | unsigned long pgprot; | ||
356 | unsigned long key; /* A protection key for itir.*/ | ||
357 | }; | ||
358 | }; | ||
359 | }; | ||
360 | |||
361 | #endif /* __ASSEMBLY__ */ | ||
362 | |||
363 | #endif /* _ASM_IA64_XEN_INTERFACE_H */ | ||
diff --git a/arch/ia64/include/asm/xen/irq.h b/arch/ia64/include/asm/xen/irq.h deleted file mode 100644 index a90450983003..000000000000 --- a/arch/ia64/include/asm/xen/irq.h +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/include/asm/xen/irq.h | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef _ASM_IA64_XEN_IRQ_H | ||
24 | #define _ASM_IA64_XEN_IRQ_H | ||
25 | |||
26 | /* | ||
27 | * The flat IRQ space is divided into two regions: | ||
28 | * 1. A one-to-one mapping of real physical IRQs. This space is only used | ||
29 | * if we have physical device-access privilege. This region is at the | ||
30 | * start of the IRQ space so that existing device drivers do not need | ||
31 | * to be modified to translate physical IRQ numbers into our IRQ space. | ||
32 | * 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These | ||
33 | * are bound using the provided bind/unbind functions. | ||
34 | */ | ||
35 | |||
36 | #define XEN_PIRQ_BASE 0 | ||
37 | #define XEN_NR_PIRQS 256 | ||
38 | |||
39 | #define XEN_DYNIRQ_BASE (XEN_PIRQ_BASE + XEN_NR_PIRQS) | ||
40 | #define XEN_NR_DYNIRQS (NR_CPUS * 8) | ||
41 | |||
42 | #define XEN_NR_IRQS (XEN_NR_PIRQS + XEN_NR_DYNIRQS) | ||
43 | |||
44 | #endif /* _ASM_IA64_XEN_IRQ_H */ | ||
diff --git a/arch/ia64/include/asm/xen/minstate.h b/arch/ia64/include/asm/xen/minstate.h deleted file mode 100644 index 00cf03e0cb82..000000000000 --- a/arch/ia64/include/asm/xen/minstate.h +++ /dev/null | |||
@@ -1,143 +0,0 @@ | |||
1 | |||
2 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE | ||
3 | /* read ar.itc in advance, and use it before leaving bank 0 */ | ||
4 | #define XEN_ACCOUNT_GET_STAMP \ | ||
5 | MOV_FROM_ITC(pUStk, p6, r20, r2); | ||
6 | #else | ||
7 | #define XEN_ACCOUNT_GET_STAMP | ||
8 | #endif | ||
9 | |||
10 | /* | ||
11 | * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves | ||
12 | * the minimum state necessary that allows us to turn psr.ic back | ||
13 | * on. | ||
14 | * | ||
15 | * Assumed state upon entry: | ||
16 | * psr.ic: off | ||
17 | * r31: contains saved predicates (pr) | ||
18 | * | ||
19 | * Upon exit, the state is as follows: | ||
20 | * psr.ic: off | ||
21 | * r2 = points to &pt_regs.r16 | ||
22 | * r8 = contents of ar.ccv | ||
23 | * r9 = contents of ar.csd | ||
24 | * r10 = contents of ar.ssd | ||
25 | * r11 = FPSR_DEFAULT | ||
26 | * r12 = kernel sp (kernel virtual address) | ||
27 | * r13 = points to current task_struct (kernel virtual address) | ||
28 | * p15 = TRUE if psr.i is set in cr.ipsr | ||
29 | * predicate registers (other than p2, p3, and p15), b6, r3, r14, r15: | ||
30 | * preserved | ||
31 | * CONFIG_XEN note: p6/p7 are not preserved | ||
32 | * | ||
33 | * Note that psr.ic is NOT turned on by this macro. This is so that | ||
34 | * we can pass interruption state as arguments to a handler. | ||
35 | */ | ||
36 | #define XEN_DO_SAVE_MIN(__COVER,SAVE_IFS,EXTRA,WORKAROUND) \ | ||
37 | mov r16=IA64_KR(CURRENT); /* M */ \ | ||
38 | mov r27=ar.rsc; /* M */ \ | ||
39 | mov r20=r1; /* A */ \ | ||
40 | mov r25=ar.unat; /* M */ \ | ||
41 | MOV_FROM_IPSR(p0,r29); /* M */ \ | ||
42 | MOV_FROM_IIP(r28); /* M */ \ | ||
43 | mov r21=ar.fpsr; /* M */ \ | ||
44 | mov r26=ar.pfs; /* I */ \ | ||
45 | __COVER; /* B;; (or nothing) */ \ | ||
46 | adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \ | ||
47 | ;; \ | ||
48 | ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \ | ||
49 | st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \ | ||
50 | adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \ | ||
51 | /* switch from user to kernel RBS: */ \ | ||
52 | ;; \ | ||
53 | invala; /* M */ \ | ||
54 | /* SAVE_IFS;*/ /* see xen special handling below */ \ | ||
55 | cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \ | ||
56 | ;; \ | ||
57 | (pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ | ||
58 | ;; \ | ||
59 | (pUStk) mov.m r24=ar.rnat; \ | ||
60 | (pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \ | ||
61 | (pKStk) mov r1=sp; /* get sp */ \ | ||
62 | ;; \ | ||
63 | (pUStk) lfetch.fault.excl.nt1 [r22]; \ | ||
64 | (pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ | ||
65 | (pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ | ||
66 | ;; \ | ||
67 | (pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ | ||
68 | (pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ | ||
69 | ;; \ | ||
70 | (pUStk) mov r18=ar.bsp; \ | ||
71 | (pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ | ||
72 | adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \ | ||
73 | adds r16=PT(CR_IPSR),r1; \ | ||
74 | ;; \ | ||
75 | lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \ | ||
76 | st8 [r16]=r29; /* save cr.ipsr */ \ | ||
77 | ;; \ | ||
78 | lfetch.fault.excl.nt1 [r17]; \ | ||
79 | tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ | ||
80 | mov r29=b0 \ | ||
81 | ;; \ | ||
82 | WORKAROUND; \ | ||
83 | adds r16=PT(R8),r1; /* initialize first base pointer */ \ | ||
84 | adds r17=PT(R9),r1; /* initialize second base pointer */ \ | ||
85 | (pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ | ||
86 | ;; \ | ||
87 | .mem.offset 0,0; st8.spill [r16]=r8,16; \ | ||
88 | .mem.offset 8,0; st8.spill [r17]=r9,16; \ | ||
89 | ;; \ | ||
90 | .mem.offset 0,0; st8.spill [r16]=r10,24; \ | ||
91 | movl r8=XSI_PRECOVER_IFS; \ | ||
92 | .mem.offset 8,0; st8.spill [r17]=r11,24; \ | ||
93 | ;; \ | ||
94 | /* xen special handling for possibly lazy cover */ \ | ||
95 | /* SAVE_MIN case in dispatch_ia32_handler: mov r30=r0 */ \ | ||
96 | ld8 r30=[r8]; \ | ||
97 | (pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \ | ||
98 | st8 [r16]=r28,16; /* save cr.iip */ \ | ||
99 | ;; \ | ||
100 | st8 [r17]=r30,16; /* save cr.ifs */ \ | ||
101 | mov r8=ar.ccv; \ | ||
102 | mov r9=ar.csd; \ | ||
103 | mov r10=ar.ssd; \ | ||
104 | movl r11=FPSR_DEFAULT; /* L-unit */ \ | ||
105 | ;; \ | ||
106 | st8 [r16]=r25,16; /* save ar.unat */ \ | ||
107 | st8 [r17]=r26,16; /* save ar.pfs */ \ | ||
108 | shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \ | ||
109 | ;; \ | ||
110 | st8 [r16]=r27,16; /* save ar.rsc */ \ | ||
111 | (pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \ | ||
112 | (pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \ | ||
113 | ;; /* avoid RAW on r16 & r17 */ \ | ||
114 | (pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \ | ||
115 | st8 [r17]=r31,16; /* save predicates */ \ | ||
116 | (pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \ | ||
117 | ;; \ | ||
118 | st8 [r16]=r29,16; /* save b0 */ \ | ||
119 | st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \ | ||
120 | cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ | ||
121 | ;; \ | ||
122 | .mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \ | ||
123 | .mem.offset 8,0; st8.spill [r17]=r12,16; \ | ||
124 | adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \ | ||
125 | ;; \ | ||
126 | .mem.offset 0,0; st8.spill [r16]=r13,16; \ | ||
127 | .mem.offset 8,0; st8.spill [r17]=r21,16; /* save ar.fpsr */ \ | ||
128 | mov r13=IA64_KR(CURRENT); /* establish `current' */ \ | ||
129 | ;; \ | ||
130 | .mem.offset 0,0; st8.spill [r16]=r15,16; \ | ||
131 | .mem.offset 8,0; st8.spill [r17]=r14,16; \ | ||
132 | ;; \ | ||
133 | .mem.offset 0,0; st8.spill [r16]=r2,16; \ | ||
134 | .mem.offset 8,0; st8.spill [r17]=r3,16; \ | ||
135 | XEN_ACCOUNT_GET_STAMP \ | ||
136 | adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ | ||
137 | ;; \ | ||
138 | EXTRA; \ | ||
139 | movl r1=__gp; /* establish kernel global pointer */ \ | ||
140 | ;; \ | ||
141 | ACCOUNT_SYS_ENTER \ | ||
142 | BSW_1(r3,r14); /* switch back to bank 1 (must be last in insn group) */ \ | ||
143 | ;; | ||
diff --git a/arch/ia64/include/asm/xen/page-coherent.h b/arch/ia64/include/asm/xen/page-coherent.h deleted file mode 100644 index 96e42f97fa1f..000000000000 --- a/arch/ia64/include/asm/xen/page-coherent.h +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | #ifndef _ASM_IA64_XEN_PAGE_COHERENT_H | ||
2 | #define _ASM_IA64_XEN_PAGE_COHERENT_H | ||
3 | |||
4 | #include <asm/page.h> | ||
5 | #include <linux/dma-attrs.h> | ||
6 | #include <linux/dma-mapping.h> | ||
7 | |||
8 | static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size, | ||
9 | dma_addr_t *dma_handle, gfp_t flags, | ||
10 | struct dma_attrs *attrs) | ||
11 | { | ||
12 | void *vstart = (void*)__get_free_pages(flags, get_order(size)); | ||
13 | *dma_handle = virt_to_phys(vstart); | ||
14 | return vstart; | ||
15 | } | ||
16 | |||
17 | static inline void xen_free_coherent_pages(struct device *hwdev, size_t size, | ||
18 | void *cpu_addr, dma_addr_t dma_handle, | ||
19 | struct dma_attrs *attrs) | ||
20 | { | ||
21 | free_pages((unsigned long) cpu_addr, get_order(size)); | ||
22 | } | ||
23 | |||
24 | static inline void xen_dma_map_page(struct device *hwdev, struct page *page, | ||
25 | unsigned long offset, size_t size, enum dma_data_direction dir, | ||
26 | struct dma_attrs *attrs) { } | ||
27 | |||
28 | static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | ||
29 | size_t size, enum dma_data_direction dir, | ||
30 | struct dma_attrs *attrs) { } | ||
31 | |||
32 | static inline void xen_dma_sync_single_for_cpu(struct device *hwdev, | ||
33 | dma_addr_t handle, size_t size, enum dma_data_direction dir) { } | ||
34 | |||
35 | static inline void xen_dma_sync_single_for_device(struct device *hwdev, | ||
36 | dma_addr_t handle, size_t size, enum dma_data_direction dir) { } | ||
37 | |||
38 | #endif /* _ASM_IA64_XEN_PAGE_COHERENT_H */ | ||
diff --git a/arch/ia64/include/asm/xen/page.h b/arch/ia64/include/asm/xen/page.h deleted file mode 100644 index 03441a780b5b..000000000000 --- a/arch/ia64/include/asm/xen/page.h +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/include/asm/xen/page.h | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef _ASM_IA64_XEN_PAGE_H | ||
24 | #define _ASM_IA64_XEN_PAGE_H | ||
25 | |||
26 | #define INVALID_P2M_ENTRY (~0UL) | ||
27 | |||
28 | static inline unsigned long mfn_to_pfn(unsigned long mfn) | ||
29 | { | ||
30 | return mfn; | ||
31 | } | ||
32 | |||
33 | static inline unsigned long pfn_to_mfn(unsigned long pfn) | ||
34 | { | ||
35 | return pfn; | ||
36 | } | ||
37 | |||
38 | #define phys_to_machine_mapping_valid(_x) (1) | ||
39 | |||
40 | static inline void *mfn_to_virt(unsigned long mfn) | ||
41 | { | ||
42 | return __va(mfn << PAGE_SHIFT); | ||
43 | } | ||
44 | |||
45 | static inline unsigned long virt_to_mfn(void *virt) | ||
46 | { | ||
47 | return __pa(virt) >> PAGE_SHIFT; | ||
48 | } | ||
49 | |||
50 | /* for tpmfront.c */ | ||
51 | static inline unsigned long virt_to_machine(void *virt) | ||
52 | { | ||
53 | return __pa(virt); | ||
54 | } | ||
55 | |||
56 | static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) | ||
57 | { | ||
58 | /* nothing */ | ||
59 | } | ||
60 | |||
61 | #define pte_mfn(_x) pte_pfn(_x) | ||
62 | #define mfn_pte(_x, _y) __pte_ma(0) /* unmodified use */ | ||
63 | #define __pte_ma(_x) ((pte_t) {(_x)}) /* unmodified use */ | ||
64 | |||
65 | #endif /* _ASM_IA64_XEN_PAGE_H */ | ||
diff --git a/arch/ia64/include/asm/xen/patchlist.h b/arch/ia64/include/asm/xen/patchlist.h deleted file mode 100644 index eae944e88846..000000000000 --- a/arch/ia64/include/asm/xen/patchlist.h +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/include/asm/xen/patchlist.h | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #define __paravirt_start_gate_fsyscall_patchlist \ | ||
24 | __xen_start_gate_fsyscall_patchlist | ||
25 | #define __paravirt_end_gate_fsyscall_patchlist \ | ||
26 | __xen_end_gate_fsyscall_patchlist | ||
27 | #define __paravirt_start_gate_brl_fsys_bubble_down_patchlist \ | ||
28 | __xen_start_gate_brl_fsys_bubble_down_patchlist | ||
29 | #define __paravirt_end_gate_brl_fsys_bubble_down_patchlist \ | ||
30 | __xen_end_gate_brl_fsys_bubble_down_patchlist | ||
31 | #define __paravirt_start_gate_vtop_patchlist \ | ||
32 | __xen_start_gate_vtop_patchlist | ||
33 | #define __paravirt_end_gate_vtop_patchlist \ | ||
34 | __xen_end_gate_vtop_patchlist | ||
35 | #define __paravirt_start_gate_mckinley_e9_patchlist \ | ||
36 | __xen_start_gate_mckinley_e9_patchlist | ||
37 | #define __paravirt_end_gate_mckinley_e9_patchlist \ | ||
38 | __xen_end_gate_mckinley_e9_patchlist | ||
diff --git a/arch/ia64/include/asm/xen/privop.h b/arch/ia64/include/asm/xen/privop.h deleted file mode 100644 index fb4ec5e0b066..000000000000 --- a/arch/ia64/include/asm/xen/privop.h +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | #ifndef _ASM_IA64_XEN_PRIVOP_H | ||
2 | #define _ASM_IA64_XEN_PRIVOP_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 2005 Hewlett-Packard Co | ||
6 | * Dan Magenheimer <dan.magenheimer@hp.com> | ||
7 | * | ||
8 | * Paravirtualizations of privileged operations for Xen/ia64 | ||
9 | * | ||
10 | * | ||
11 | * inline privop and paravirt_alt support | ||
12 | * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> | ||
13 | * VA Linux Systems Japan K.K. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __ASSEMBLY__ | ||
18 | #include <linux/types.h> /* arch-ia64.h requires uint64_t */ | ||
19 | #endif | ||
20 | #include <asm/xen/interface.h> | ||
21 | |||
22 | /* At 1 MB, before per-cpu space but still addressable using addl instead | ||
23 | of movl. */ | ||
24 | #define XSI_BASE 0xfffffffffff00000 | ||
25 | |||
26 | /* Address of mapped regs. */ | ||
27 | #define XMAPPEDREGS_BASE (XSI_BASE + XSI_SIZE) | ||
28 | |||
29 | #ifdef __ASSEMBLY__ | ||
30 | #define XEN_HYPER_RFI break HYPERPRIVOP_RFI | ||
31 | #define XEN_HYPER_RSM_PSR_DT break HYPERPRIVOP_RSM_DT | ||
32 | #define XEN_HYPER_SSM_PSR_DT break HYPERPRIVOP_SSM_DT | ||
33 | #define XEN_HYPER_COVER break HYPERPRIVOP_COVER | ||
34 | #define XEN_HYPER_ITC_D break HYPERPRIVOP_ITC_D | ||
35 | #define XEN_HYPER_ITC_I break HYPERPRIVOP_ITC_I | ||
36 | #define XEN_HYPER_SSM_I break HYPERPRIVOP_SSM_I | ||
37 | #define XEN_HYPER_GET_IVR break HYPERPRIVOP_GET_IVR | ||
38 | #define XEN_HYPER_THASH break HYPERPRIVOP_THASH | ||
39 | #define XEN_HYPER_ITR_D break HYPERPRIVOP_ITR_D | ||
40 | #define XEN_HYPER_SET_KR break HYPERPRIVOP_SET_KR | ||
41 | #define XEN_HYPER_GET_PSR break HYPERPRIVOP_GET_PSR | ||
42 | #define XEN_HYPER_SET_RR0_TO_RR4 break HYPERPRIVOP_SET_RR0_TO_RR4 | ||
43 | |||
44 | #define XSI_IFS (XSI_BASE + XSI_IFS_OFS) | ||
45 | #define XSI_PRECOVER_IFS (XSI_BASE + XSI_PRECOVER_IFS_OFS) | ||
46 | #define XSI_IFA (XSI_BASE + XSI_IFA_OFS) | ||
47 | #define XSI_ISR (XSI_BASE + XSI_ISR_OFS) | ||
48 | #define XSI_IIM (XSI_BASE + XSI_IIM_OFS) | ||
49 | #define XSI_ITIR (XSI_BASE + XSI_ITIR_OFS) | ||
50 | #define XSI_PSR_I_ADDR (XSI_BASE + XSI_PSR_I_ADDR_OFS) | ||
51 | #define XSI_PSR_IC (XSI_BASE + XSI_PSR_IC_OFS) | ||
52 | #define XSI_IPSR (XSI_BASE + XSI_IPSR_OFS) | ||
53 | #define XSI_IIP (XSI_BASE + XSI_IIP_OFS) | ||
54 | #define XSI_B1NAT (XSI_BASE + XSI_B1NATS_OFS) | ||
55 | #define XSI_BANK1_R16 (XSI_BASE + XSI_BANK1_R16_OFS) | ||
56 | #define XSI_BANKNUM (XSI_BASE + XSI_BANKNUM_OFS) | ||
57 | #define XSI_IHA (XSI_BASE + XSI_IHA_OFS) | ||
58 | #define XSI_ITC_OFFSET (XSI_BASE + XSI_ITC_OFFSET_OFS) | ||
59 | #define XSI_ITC_LAST (XSI_BASE + XSI_ITC_LAST_OFS) | ||
60 | #endif | ||
61 | |||
62 | #ifndef __ASSEMBLY__ | ||
63 | |||
64 | /************************************************/ | ||
65 | /* Instructions paravirtualized for correctness */ | ||
66 | /************************************************/ | ||
67 | |||
68 | /* "fc" and "thash" are privilege-sensitive instructions, meaning they | ||
69 | * may have different semantics depending on whether they are executed | ||
70 | * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't | ||
71 | * be allowed to execute directly, lest incorrect semantics result. */ | ||
72 | extern void xen_fc(void *addr); | ||
73 | extern unsigned long xen_thash(unsigned long addr); | ||
74 | |||
75 | /* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" | ||
76 | * is not currently used (though it may be in a long-format VHPT system!) | ||
77 | * and the semantics of cover only change if psr.ic is off which is very | ||
78 | * rare (and currently non-existent outside of assembly code */ | ||
79 | |||
80 | /* There are also privilege-sensitive registers. These registers are | ||
81 | * readable at any privilege level but only writable at PL0. */ | ||
82 | extern unsigned long xen_get_cpuid(int index); | ||
83 | extern unsigned long xen_get_pmd(int index); | ||
84 | |||
85 | #ifndef ASM_SUPPORTED | ||
86 | extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */ | ||
87 | extern void xen_set_eflag(unsigned long); /* see xen_ia64_setreg */ | ||
88 | #endif | ||
89 | |||
90 | /************************************************/ | ||
91 | /* Instructions paravirtualized for performance */ | ||
92 | /************************************************/ | ||
93 | |||
94 | /* Xen uses memory-mapped virtual privileged registers for access to many | ||
95 | * performance-sensitive privileged registers. Some, like the processor | ||
96 | * status register (psr), are broken up into multiple memory locations. | ||
97 | * Others, like "pend", are abstractions based on privileged registers. | ||
98 | * "Pend" is guaranteed to be set if reading cr.ivr would return a | ||
99 | * (non-spurious) interrupt. */ | ||
100 | #define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE) | ||
101 | |||
102 | #define XSI_PSR_I \ | ||
103 | (*XEN_MAPPEDREGS->interrupt_mask_addr) | ||
104 | #define xen_get_virtual_psr_i() \ | ||
105 | (!XSI_PSR_I) | ||
106 | #define xen_set_virtual_psr_i(_val) \ | ||
107 | ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; }) | ||
108 | #define xen_set_virtual_psr_ic(_val) \ | ||
109 | ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; }) | ||
110 | #define xen_get_virtual_pend() \ | ||
111 | (*(((uint8_t *)XEN_MAPPEDREGS->interrupt_mask_addr) - 1)) | ||
112 | |||
113 | #ifndef ASM_SUPPORTED | ||
114 | /* Although all privileged operations can be left to trap and will | ||
115 | * be properly handled by Xen, some are frequent enough that we use | ||
116 | * hyperprivops for performance. */ | ||
117 | extern unsigned long xen_get_psr(void); | ||
118 | extern unsigned long xen_get_ivr(void); | ||
119 | extern unsigned long xen_get_tpr(void); | ||
120 | extern void xen_hyper_ssm_i(void); | ||
121 | extern void xen_set_itm(unsigned long); | ||
122 | extern void xen_set_tpr(unsigned long); | ||
123 | extern void xen_eoi(unsigned long); | ||
124 | extern unsigned long xen_get_rr(unsigned long index); | ||
125 | extern void xen_set_rr(unsigned long index, unsigned long val); | ||
126 | extern void xen_set_rr0_to_rr4(unsigned long val0, unsigned long val1, | ||
127 | unsigned long val2, unsigned long val3, | ||
128 | unsigned long val4); | ||
129 | extern void xen_set_kr(unsigned long index, unsigned long val); | ||
130 | extern void xen_ptcga(unsigned long addr, unsigned long size); | ||
131 | #endif /* !ASM_SUPPORTED */ | ||
132 | |||
133 | #endif /* !__ASSEMBLY__ */ | ||
134 | |||
135 | #endif /* _ASM_IA64_XEN_PRIVOP_H */ | ||
diff --git a/arch/ia64/include/asm/xen/xcom_hcall.h b/arch/ia64/include/asm/xen/xcom_hcall.h deleted file mode 100644 index 20b2950c71b6..000000000000 --- a/arch/ia64/include/asm/xen/xcom_hcall.h +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Tristan Gingold <tristan.gingold@bull.net>, Bull SAS | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef _ASM_IA64_XEN_XCOM_HCALL_H | ||
20 | #define _ASM_IA64_XEN_XCOM_HCALL_H | ||
21 | |||
22 | /* These function creates inline or mini descriptor for the parameters and | ||
23 | calls the corresponding xencomm_arch_hypercall_X. | ||
24 | Architectures should defines HYPERVISOR_xxx as xencomm_hypercall_xxx unless | ||
25 | they want to use their own wrapper. */ | ||
26 | extern int xencomm_hypercall_console_io(int cmd, int count, char *str); | ||
27 | |||
28 | extern int xencomm_hypercall_event_channel_op(int cmd, void *op); | ||
29 | |||
30 | extern int xencomm_hypercall_xen_version(int cmd, void *arg); | ||
31 | |||
32 | extern int xencomm_hypercall_physdev_op(int cmd, void *op); | ||
33 | |||
34 | extern int xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, | ||
35 | unsigned int count); | ||
36 | |||
37 | extern int xencomm_hypercall_sched_op(int cmd, void *arg); | ||
38 | |||
39 | extern int xencomm_hypercall_multicall(void *call_list, int nr_calls); | ||
40 | |||
41 | extern int xencomm_hypercall_callback_op(int cmd, void *arg); | ||
42 | |||
43 | extern int xencomm_hypercall_memory_op(unsigned int cmd, void *arg); | ||
44 | |||
45 | extern int xencomm_hypercall_suspend(unsigned long srec); | ||
46 | |||
47 | extern long xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg); | ||
48 | |||
49 | extern long xencomm_hypercall_opt_feature(void *arg); | ||
50 | |||
51 | #endif /* _ASM_IA64_XEN_XCOM_HCALL_H */ | ||
diff --git a/arch/ia64/include/asm/xen/xencomm.h b/arch/ia64/include/asm/xen/xencomm.h deleted file mode 100644 index cded677bebf2..000000000000 --- a/arch/ia64/include/asm/xen/xencomm.h +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef _ASM_IA64_XEN_XENCOMM_H | ||
20 | #define _ASM_IA64_XEN_XENCOMM_H | ||
21 | |||
22 | #include <xen/xencomm.h> | ||
23 | #include <asm/pgtable.h> | ||
24 | |||
25 | /* Must be called before any hypercall. */ | ||
26 | extern void xencomm_initialize(void); | ||
27 | extern int xencomm_is_initialized(void); | ||
28 | |||
29 | /* Check if virtual contiguity means physical contiguity | ||
30 | * where the passed address is a pointer value in virtual address. | ||
31 | * On ia64, identity mapping area in region 7 or the piece of region 5 | ||
32 | * that is mapped by itr[IA64_TR_KERNEL]/dtr[IA64_TR_KERNEL] | ||
33 | */ | ||
34 | static inline int xencomm_is_phys_contiguous(unsigned long addr) | ||
35 | { | ||
36 | return (PAGE_OFFSET <= addr && | ||
37 | addr < (PAGE_OFFSET + (1UL << IA64_MAX_PHYS_BITS))) || | ||
38 | (KERNEL_START <= addr && | ||
39 | addr < KERNEL_START + KERNEL_TR_PAGE_SIZE); | ||
40 | } | ||
41 | |||
42 | #endif /* _ASM_IA64_XEN_XENCOMM_H */ | ||
diff --git a/arch/ia64/include/uapi/asm/break.h b/arch/ia64/include/uapi/asm/break.h index e90c40ec9edf..f03402039896 100644 --- a/arch/ia64/include/uapi/asm/break.h +++ b/arch/ia64/include/uapi/asm/break.h | |||
@@ -20,13 +20,4 @@ | |||
20 | */ | 20 | */ |
21 | #define __IA64_BREAK_SYSCALL 0x100000 | 21 | #define __IA64_BREAK_SYSCALL 0x100000 |
22 | 22 | ||
23 | /* | ||
24 | * Xen specific break numbers: | ||
25 | */ | ||
26 | #define __IA64_XEN_HYPERCALL 0x1000 | ||
27 | /* [__IA64_XEN_HYPERPRIVOP_START, __IA64_XEN_HYPERPRIVOP_MAX] is used | ||
28 | for xen hyperprivops */ | ||
29 | #define __IA64_XEN_HYPERPRIVOP_START 0x1 | ||
30 | #define __IA64_XEN_HYPERPRIVOP_MAX 0x1a | ||
31 | |||
32 | #endif /* _ASM_IA64_BREAK_H */ | 23 | #endif /* _ASM_IA64_BREAK_H */ |
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 59d52e3aef12..bfa19311e09c 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c | |||
@@ -53,7 +53,6 @@ | |||
53 | #include <asm/numa.h> | 53 | #include <asm/numa.h> |
54 | #include <asm/sal.h> | 54 | #include <asm/sal.h> |
55 | #include <asm/cyclone.h> | 55 | #include <asm/cyclone.h> |
56 | #include <asm/xen/hypervisor.h> | ||
57 | 56 | ||
58 | #define BAD_MADT_ENTRY(entry, end) ( \ | 57 | #define BAD_MADT_ENTRY(entry, end) ( \ |
59 | (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ | 58 | (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ |
@@ -120,8 +119,6 @@ acpi_get_sysname(void) | |||
120 | return "uv"; | 119 | return "uv"; |
121 | else | 120 | else |
122 | return "sn2"; | 121 | return "sn2"; |
123 | } else if (xen_pv_domain() && !strcmp(hdr->oem_id, "XEN")) { | ||
124 | return "xen"; | ||
125 | } | 122 | } |
126 | 123 | ||
127 | #ifdef CONFIG_INTEL_IOMMU | 124 | #ifdef CONFIG_INTEL_IOMMU |
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 46c9e3007315..60ef83e6db71 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c | |||
@@ -16,9 +16,6 @@ | |||
16 | #include <asm/sigcontext.h> | 16 | #include <asm/sigcontext.h> |
17 | #include <asm/mca.h> | 17 | #include <asm/mca.h> |
18 | 18 | ||
19 | #include <asm/xen/interface.h> | ||
20 | #include <asm/xen/hypervisor.h> | ||
21 | |||
22 | #include "../kernel/sigframe.h" | 19 | #include "../kernel/sigframe.h" |
23 | #include "../kernel/fsyscall_gtod_data.h" | 20 | #include "../kernel/fsyscall_gtod_data.h" |
24 | 21 | ||
@@ -290,33 +287,4 @@ void foo(void) | |||
290 | DEFINE(IA64_ITC_LASTCYCLE_OFFSET, | 287 | DEFINE(IA64_ITC_LASTCYCLE_OFFSET, |
291 | offsetof (struct itc_jitter_data_t, itc_lastcycle)); | 288 | offsetof (struct itc_jitter_data_t, itc_lastcycle)); |
292 | 289 | ||
293 | #ifdef CONFIG_XEN | ||
294 | BLANK(); | ||
295 | |||
296 | DEFINE(XEN_NATIVE_ASM, XEN_NATIVE); | ||
297 | DEFINE(XEN_PV_DOMAIN_ASM, XEN_PV_DOMAIN); | ||
298 | |||
299 | #define DEFINE_MAPPED_REG_OFS(sym, field) \ | ||
300 | DEFINE(sym, (XMAPPEDREGS_OFS + offsetof(struct mapped_regs, field))) | ||
301 | |||
302 | DEFINE_MAPPED_REG_OFS(XSI_PSR_I_ADDR_OFS, interrupt_mask_addr); | ||
303 | DEFINE_MAPPED_REG_OFS(XSI_IPSR_OFS, ipsr); | ||
304 | DEFINE_MAPPED_REG_OFS(XSI_IIP_OFS, iip); | ||
305 | DEFINE_MAPPED_REG_OFS(XSI_IFS_OFS, ifs); | ||
306 | DEFINE_MAPPED_REG_OFS(XSI_PRECOVER_IFS_OFS, precover_ifs); | ||
307 | DEFINE_MAPPED_REG_OFS(XSI_ISR_OFS, isr); | ||
308 | DEFINE_MAPPED_REG_OFS(XSI_IFA_OFS, ifa); | ||
309 | DEFINE_MAPPED_REG_OFS(XSI_IIPA_OFS, iipa); | ||
310 | DEFINE_MAPPED_REG_OFS(XSI_IIM_OFS, iim); | ||
311 | DEFINE_MAPPED_REG_OFS(XSI_IHA_OFS, iha); | ||
312 | DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir); | ||
313 | DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled); | ||
314 | DEFINE_MAPPED_REG_OFS(XSI_BANKNUM_OFS, banknum); | ||
315 | DEFINE_MAPPED_REG_OFS(XSI_BANK0_R16_OFS, bank0_regs[0]); | ||
316 | DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]); | ||
317 | DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat); | ||
318 | DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat); | ||
319 | DEFINE_MAPPED_REG_OFS(XSI_ITC_OFFSET_OFS, itc_offset); | ||
320 | DEFINE_MAPPED_REG_OFS(XSI_ITC_LAST_OFS, itc_last); | ||
321 | #endif /* CONFIG_XEN */ | ||
322 | } | 290 | } |
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 991ca336b8a2..e6f80fcf013b 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S | |||
@@ -416,8 +416,6 @@ start_ap: | |||
416 | 416 | ||
417 | default_setup_hook = 0 // Currently nothing needs to be done. | 417 | default_setup_hook = 0 // Currently nothing needs to be done. |
418 | 418 | ||
419 | .weak xen_setup_hook | ||
420 | |||
421 | .global hypervisor_type | 419 | .global hypervisor_type |
422 | hypervisor_type: | 420 | hypervisor_type: |
423 | data8 PARAVIRT_HYPERVISOR_TYPE_DEFAULT | 421 | data8 PARAVIRT_HYPERVISOR_TYPE_DEFAULT |
@@ -426,7 +424,6 @@ hypervisor_type: | |||
426 | 424 | ||
427 | hypervisor_setup_hooks: | 425 | hypervisor_setup_hooks: |
428 | data8 default_setup_hook | 426 | data8 default_setup_hook |
429 | data8 xen_setup_hook | ||
430 | num_hypervisor_hooks = (. - hypervisor_setup_hooks) / 8 | 427 | num_hypervisor_hooks = (. - hypervisor_setup_hooks) / 8 |
431 | .previous | 428 | .previous |
432 | 429 | ||
diff --git a/arch/ia64/kernel/nr-irqs.c b/arch/ia64/kernel/nr-irqs.c index ee564575148e..f6769cd54bd9 100644 --- a/arch/ia64/kernel/nr-irqs.c +++ b/arch/ia64/kernel/nr-irqs.c | |||
@@ -10,15 +10,11 @@ | |||
10 | #include <linux/kbuild.h> | 10 | #include <linux/kbuild.h> |
11 | #include <linux/threads.h> | 11 | #include <linux/threads.h> |
12 | #include <asm/native/irq.h> | 12 | #include <asm/native/irq.h> |
13 | #include <asm/xen/irq.h> | ||
14 | 13 | ||
15 | void foo(void) | 14 | void foo(void) |
16 | { | 15 | { |
17 | union paravirt_nr_irqs_max { | 16 | union paravirt_nr_irqs_max { |
18 | char ia64_native_nr_irqs[IA64_NATIVE_NR_IRQS]; | 17 | char ia64_native_nr_irqs[IA64_NATIVE_NR_IRQS]; |
19 | #ifdef CONFIG_XEN | ||
20 | char xen_nr_irqs[XEN_NR_IRQS]; | ||
21 | #endif | ||
22 | }; | 18 | }; |
23 | 19 | ||
24 | DEFINE(NR_IRQS, sizeof (union paravirt_nr_irqs_max)); | 20 | DEFINE(NR_IRQS, sizeof (union paravirt_nr_irqs_max)); |
diff --git a/arch/ia64/kernel/paravirt_inst.h b/arch/ia64/kernel/paravirt_inst.h index 64d6d810c64b..1ad7512b5f65 100644 --- a/arch/ia64/kernel/paravirt_inst.h +++ b/arch/ia64/kernel/paravirt_inst.h | |||
@@ -22,9 +22,6 @@ | |||
22 | 22 | ||
23 | #ifdef __IA64_ASM_PARAVIRTUALIZED_PVCHECK | 23 | #ifdef __IA64_ASM_PARAVIRTUALIZED_PVCHECK |
24 | #include <asm/native/pvchk_inst.h> | 24 | #include <asm/native/pvchk_inst.h> |
25 | #elif defined(__IA64_ASM_PARAVIRTUALIZED_XEN) | ||
26 | #include <asm/xen/inst.h> | ||
27 | #include <asm/xen/minstate.h> | ||
28 | #else | 25 | #else |
29 | #include <asm/native/inst.h> | 26 | #include <asm/native/inst.h> |
30 | #endif | 27 | #endif |
diff --git a/arch/ia64/kernel/paravirt_patchlist.h b/arch/ia64/kernel/paravirt_patchlist.h index 0684aa6c6507..67cffc3643a3 100644 --- a/arch/ia64/kernel/paravirt_patchlist.h +++ b/arch/ia64/kernel/paravirt_patchlist.h | |||
@@ -20,9 +20,5 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #if defined(__IA64_GATE_PARAVIRTUALIZED_XEN) | ||
24 | #include <asm/xen/patchlist.h> | ||
25 | #else | ||
26 | #include <asm/native/patchlist.h> | 23 | #include <asm/native/patchlist.h> |
27 | #endif | ||
28 | 24 | ||
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 0ccb28fab27e..84f8a52ac5ae 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -182,12 +182,6 @@ SECTIONS { | |||
182 | __start_gate_section = .; | 182 | __start_gate_section = .; |
183 | *(.data..gate) | 183 | *(.data..gate) |
184 | __stop_gate_section = .; | 184 | __stop_gate_section = .; |
185 | #ifdef CONFIG_XEN | ||
186 | . = ALIGN(PAGE_SIZE); | ||
187 | __xen_start_gate_section = .; | ||
188 | *(.data..gate.xen) | ||
189 | __xen_stop_gate_section = .; | ||
190 | #endif | ||
191 | } | 185 | } |
192 | /* | 186 | /* |
193 | * make sure the gate page doesn't expose | 187 | * make sure the gate page doesn't expose |
diff --git a/arch/ia64/xen/Kconfig b/arch/ia64/xen/Kconfig deleted file mode 100644 index 5d8a06b0ddf7..000000000000 --- a/arch/ia64/xen/Kconfig +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | # | ||
2 | # This Kconfig describes xen/ia64 options | ||
3 | # | ||
4 | |||
5 | config XEN | ||
6 | bool "Xen hypervisor support" | ||
7 | default y | ||
8 | depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB | ||
9 | select XEN_XENCOMM | ||
10 | select NO_IDLE_HZ | ||
11 | # followings are required to save/restore. | ||
12 | select ARCH_SUSPEND_POSSIBLE | ||
13 | select SUSPEND | ||
14 | select PM_SLEEP | ||
15 | help | ||
16 | Enable Xen hypervisor support. Resulting kernel runs | ||
17 | both as a guest OS on Xen and natively on hardware. | ||
18 | |||
19 | config XEN_XENCOMM | ||
20 | depends on XEN | ||
21 | bool | ||
22 | |||
23 | config NO_IDLE_HZ | ||
24 | depends on XEN | ||
25 | bool | ||
diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile deleted file mode 100644 index e6f4a0a74228..000000000000 --- a/arch/ia64/xen/Makefile +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for Xen components | ||
3 | # | ||
4 | |||
5 | obj-y := hypercall.o xenivt.o xensetup.o xen_pv_ops.o irq_xen.o \ | ||
6 | hypervisor.o xencomm.o xcom_hcall.o grant-table.o time.o suspend.o \ | ||
7 | gate-data.o | ||
8 | |||
9 | obj-$(CONFIG_IA64_GENERIC) += machvec.o | ||
10 | |||
11 | # The gate DSO image is built using a special linker script. | ||
12 | include $(srctree)/arch/ia64/kernel/Makefile.gate | ||
13 | |||
14 | # tell compiled for xen | ||
15 | CPPFLAGS_gate.lds += -D__IA64_GATE_PARAVIRTUALIZED_XEN | ||
16 | AFLAGS_gate.o += -D__IA64_ASM_PARAVIRTUALIZED_XEN -D__IA64_GATE_PARAVIRTUALIZED_XEN | ||
17 | |||
18 | # use same file of native. | ||
19 | $(obj)/gate.o: $(src)/../kernel/gate.S FORCE | ||
20 | $(call if_changed_dep,as_o_S) | ||
21 | $(obj)/gate.lds: $(src)/../kernel/gate.lds.S FORCE | ||
22 | $(call if_changed_dep,cpp_lds_S) | ||
23 | |||
24 | |||
25 | AFLAGS_xenivt.o += -D__IA64_ASM_PARAVIRTUALIZED_XEN | ||
26 | |||
27 | # xen multi compile | ||
28 | ASM_PARAVIRT_MULTI_COMPILE_SRCS = ivt.S entry.S fsys.S | ||
29 | ASM_PARAVIRT_OBJS = $(addprefix xen-,$(ASM_PARAVIRT_MULTI_COMPILE_SRCS:.S=.o)) | ||
30 | obj-y += $(ASM_PARAVIRT_OBJS) | ||
31 | define paravirtualized_xen | ||
32 | AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_XEN | ||
33 | endef | ||
34 | $(foreach o,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_xen,$(o)))) | ||
35 | |||
36 | $(obj)/xen-%.o: $(src)/../kernel/%.S FORCE | ||
37 | $(call if_changed_dep,as_o_S) | ||
diff --git a/arch/ia64/xen/gate-data.S b/arch/ia64/xen/gate-data.S deleted file mode 100644 index 6f95b6b32a4e..000000000000 --- a/arch/ia64/xen/gate-data.S +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | .section .data..gate.xen, "aw" | ||
2 | |||
3 | .incbin "arch/ia64/xen/gate.so" | ||
diff --git a/arch/ia64/xen/grant-table.c b/arch/ia64/xen/grant-table.c deleted file mode 100644 index c18281332f84..000000000000 --- a/arch/ia64/xen/grant-table.c +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/xen/grant-table.c | ||
3 | * | ||
4 | * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/vmalloc.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/mm.h> | ||
27 | |||
28 | #include <xen/interface/xen.h> | ||
29 | #include <xen/interface/memory.h> | ||
30 | #include <xen/grant_table.h> | ||
31 | |||
32 | #include <asm/xen/hypervisor.h> | ||
33 | |||
34 | /**************************************************************************** | ||
35 | * grant table hack | ||
36 | * cmd: GNTTABOP_xxx | ||
37 | */ | ||
38 | |||
39 | int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, | ||
40 | unsigned long max_nr_gframes, | ||
41 | struct grant_entry **__shared) | ||
42 | { | ||
43 | *__shared = __va(frames[0] << PAGE_SHIFT); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | void arch_gnttab_unmap_shared(struct grant_entry *shared, | ||
48 | unsigned long nr_gframes) | ||
49 | { | ||
50 | /* nothing */ | ||
51 | } | ||
52 | |||
53 | static void | ||
54 | gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop) | ||
55 | { | ||
56 | uint32_t flags; | ||
57 | |||
58 | flags = uop->flags; | ||
59 | |||
60 | if (flags & GNTMAP_host_map) { | ||
61 | if (flags & GNTMAP_application_map) { | ||
62 | printk(KERN_DEBUG | ||
63 | "GNTMAP_application_map is not supported yet: " | ||
64 | "flags 0x%x\n", flags); | ||
65 | BUG(); | ||
66 | } | ||
67 | if (flags & GNTMAP_contains_pte) { | ||
68 | printk(KERN_DEBUG | ||
69 | "GNTMAP_contains_pte is not supported yet: " | ||
70 | "flags 0x%x\n", flags); | ||
71 | BUG(); | ||
72 | } | ||
73 | } else if (flags & GNTMAP_device_map) { | ||
74 | printk("GNTMAP_device_map is not supported yet 0x%x\n", flags); | ||
75 | BUG(); /* not yet. actually this flag is not used. */ | ||
76 | } else { | ||
77 | BUG(); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | int | ||
82 | HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) | ||
83 | { | ||
84 | if (cmd == GNTTABOP_map_grant_ref) { | ||
85 | unsigned int i; | ||
86 | for (i = 0; i < count; i++) { | ||
87 | gnttab_map_grant_ref_pre( | ||
88 | (struct gnttab_map_grant_ref *)uop + i); | ||
89 | } | ||
90 | } | ||
91 | return xencomm_hypercall_grant_table_op(cmd, uop, count); | ||
92 | } | ||
93 | |||
94 | EXPORT_SYMBOL(HYPERVISOR_grant_table_op); | ||
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S deleted file mode 100644 index 08847aa12583..000000000000 --- a/arch/ia64/xen/hypercall.S +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | /* | ||
2 | * Support routines for Xen hypercalls | ||
3 | * | ||
4 | * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com> | ||
5 | * Copyright (C) 2008 Yaozu (Eddie) Dong <eddie.dong@intel.com> | ||
6 | */ | ||
7 | |||
8 | #include <asm/asmmacro.h> | ||
9 | #include <asm/intrinsics.h> | ||
10 | #include <asm/xen/privop.h> | ||
11 | |||
12 | #ifdef __INTEL_COMPILER | ||
13 | /* | ||
14 | * Hypercalls without parameter. | ||
15 | */ | ||
16 | #define __HCALL0(name,hcall) \ | ||
17 | GLOBAL_ENTRY(name); \ | ||
18 | break hcall; \ | ||
19 | br.ret.sptk.many rp; \ | ||
20 | END(name) | ||
21 | |||
22 | /* | ||
23 | * Hypercalls with 1 parameter. | ||
24 | */ | ||
25 | #define __HCALL1(name,hcall) \ | ||
26 | GLOBAL_ENTRY(name); \ | ||
27 | mov r8=r32; \ | ||
28 | break hcall; \ | ||
29 | br.ret.sptk.many rp; \ | ||
30 | END(name) | ||
31 | |||
32 | /* | ||
33 | * Hypercalls with 2 parameters. | ||
34 | */ | ||
35 | #define __HCALL2(name,hcall) \ | ||
36 | GLOBAL_ENTRY(name); \ | ||
37 | mov r8=r32; \ | ||
38 | mov r9=r33; \ | ||
39 | break hcall; \ | ||
40 | br.ret.sptk.many rp; \ | ||
41 | END(name) | ||
42 | |||
43 | __HCALL0(xen_get_psr, HYPERPRIVOP_GET_PSR) | ||
44 | __HCALL0(xen_get_ivr, HYPERPRIVOP_GET_IVR) | ||
45 | __HCALL0(xen_get_tpr, HYPERPRIVOP_GET_TPR) | ||
46 | __HCALL0(xen_hyper_ssm_i, HYPERPRIVOP_SSM_I) | ||
47 | |||
48 | __HCALL1(xen_set_tpr, HYPERPRIVOP_SET_TPR) | ||
49 | __HCALL1(xen_eoi, HYPERPRIVOP_EOI) | ||
50 | __HCALL1(xen_thash, HYPERPRIVOP_THASH) | ||
51 | __HCALL1(xen_set_itm, HYPERPRIVOP_SET_ITM) | ||
52 | __HCALL1(xen_get_rr, HYPERPRIVOP_GET_RR) | ||
53 | __HCALL1(xen_fc, HYPERPRIVOP_FC) | ||
54 | __HCALL1(xen_get_cpuid, HYPERPRIVOP_GET_CPUID) | ||
55 | __HCALL1(xen_get_pmd, HYPERPRIVOP_GET_PMD) | ||
56 | |||
57 | __HCALL2(xen_ptcga, HYPERPRIVOP_PTC_GA) | ||
58 | __HCALL2(xen_set_rr, HYPERPRIVOP_SET_RR) | ||
59 | __HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR) | ||
60 | |||
61 | GLOBAL_ENTRY(xen_set_rr0_to_rr4) | ||
62 | mov r8=r32 | ||
63 | mov r9=r33 | ||
64 | mov r10=r34 | ||
65 | mov r11=r35 | ||
66 | mov r14=r36 | ||
67 | XEN_HYPER_SET_RR0_TO_RR4 | ||
68 | br.ret.sptk.many rp | ||
69 | ;; | ||
70 | END(xen_set_rr0_to_rr4) | ||
71 | #endif | ||
72 | |||
73 | GLOBAL_ENTRY(xen_send_ipi) | ||
74 | mov r14=r32 | ||
75 | mov r15=r33 | ||
76 | mov r2=0x400 | ||
77 | break 0x1000 | ||
78 | ;; | ||
79 | br.ret.sptk.many rp | ||
80 | ;; | ||
81 | END(xen_send_ipi) | ||
82 | |||
83 | GLOBAL_ENTRY(__hypercall) | ||
84 | mov r2=r37 | ||
85 | break 0x1000 | ||
86 | br.ret.sptk.many b0 | ||
87 | ;; | ||
88 | END(__hypercall) | ||
diff --git a/arch/ia64/xen/hypervisor.c b/arch/ia64/xen/hypervisor.c deleted file mode 100644 index fab62528a80b..000000000000 --- a/arch/ia64/xen/hypervisor.c +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/xen/hypervisor.c | ||
3 | * | ||
4 | * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/efi.h> | ||
24 | #include <linux/export.h> | ||
25 | #include <asm/xen/hypervisor.h> | ||
26 | #include <asm/xen/privop.h> | ||
27 | |||
28 | #include "irq_xen.h" | ||
29 | |||
30 | struct shared_info *HYPERVISOR_shared_info __read_mostly = | ||
31 | (struct shared_info *)XSI_BASE; | ||
32 | EXPORT_SYMBOL(HYPERVISOR_shared_info); | ||
33 | |||
34 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | ||
35 | |||
36 | struct start_info *xen_start_info; | ||
37 | EXPORT_SYMBOL(xen_start_info); | ||
38 | |||
39 | EXPORT_SYMBOL(xen_domain_type); | ||
40 | |||
41 | EXPORT_SYMBOL(__hypercall); | ||
42 | |||
43 | /* Stolen from arch/x86/xen/enlighten.c */ | ||
44 | /* | ||
45 | * Flag to determine whether vcpu info placement is available on all | ||
46 | * VCPUs. We assume it is to start with, and then set it to zero on | ||
47 | * the first failure. This is because it can succeed on some VCPUs | ||
48 | * and not others, since it can involve hypervisor memory allocation, | ||
49 | * or because the guest failed to guarantee all the appropriate | ||
50 | * constraints on all VCPUs (ie buffer can't cross a page boundary). | ||
51 | * | ||
52 | * Note that any particular CPU may be using a placed vcpu structure, | ||
53 | * but we can only optimise if the all are. | ||
54 | * | ||
55 | * 0: not available, 1: available | ||
56 | */ | ||
57 | |||
58 | static void __init xen_vcpu_setup(int cpu) | ||
59 | { | ||
60 | /* | ||
61 | * WARNING: | ||
62 | * before changing MAX_VIRT_CPUS, | ||
63 | * check that shared_info fits on a page | ||
64 | */ | ||
65 | BUILD_BUG_ON(sizeof(struct shared_info) > PAGE_SIZE); | ||
66 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; | ||
67 | } | ||
68 | |||
69 | void __init xen_setup_vcpu_info_placement(void) | ||
70 | { | ||
71 | int cpu; | ||
72 | |||
73 | for_each_possible_cpu(cpu) | ||
74 | xen_vcpu_setup(cpu); | ||
75 | } | ||
76 | |||
77 | void | ||
78 | xen_cpu_init(void) | ||
79 | { | ||
80 | xen_smp_intr_init(); | ||
81 | } | ||
82 | |||
83 | /************************************************************************** | ||
84 | * opt feature | ||
85 | */ | ||
86 | void | ||
87 | xen_ia64_enable_opt_feature(void) | ||
88 | { | ||
89 | /* Enable region 7 identity map optimizations in Xen */ | ||
90 | struct xen_ia64_opt_feature optf; | ||
91 | |||
92 | optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG7; | ||
93 | optf.on = XEN_IA64_OPTF_ON; | ||
94 | optf.pgprot = pgprot_val(PAGE_KERNEL); | ||
95 | optf.key = 0; /* No key on linux. */ | ||
96 | HYPERVISOR_opt_feature(&optf); | ||
97 | } | ||
diff --git a/arch/ia64/xen/irq_xen.c b/arch/ia64/xen/irq_xen.c deleted file mode 100644 index efb74dafec4d..000000000000 --- a/arch/ia64/xen/irq_xen.c +++ /dev/null | |||
@@ -1,443 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/xen/irq_xen.c | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/cpu.h> | ||
24 | |||
25 | #include <xen/interface/xen.h> | ||
26 | #include <xen/interface/callback.h> | ||
27 | #include <xen/events.h> | ||
28 | |||
29 | #include <asm/xen/privop.h> | ||
30 | |||
31 | #include "irq_xen.h" | ||
32 | |||
33 | /*************************************************************************** | ||
34 | * pv_irq_ops | ||
35 | * irq operations | ||
36 | */ | ||
37 | |||
38 | static int | ||
39 | xen_assign_irq_vector(int irq) | ||
40 | { | ||
41 | struct physdev_irq irq_op; | ||
42 | |||
43 | irq_op.irq = irq; | ||
44 | if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) | ||
45 | return -ENOSPC; | ||
46 | |||
47 | return irq_op.vector; | ||
48 | } | ||
49 | |||
50 | static void | ||
51 | xen_free_irq_vector(int vector) | ||
52 | { | ||
53 | struct physdev_irq irq_op; | ||
54 | |||
55 | if (vector < IA64_FIRST_DEVICE_VECTOR || | ||
56 | vector > IA64_LAST_DEVICE_VECTOR) | ||
57 | return; | ||
58 | |||
59 | irq_op.vector = vector; | ||
60 | if (HYPERVISOR_physdev_op(PHYSDEVOP_free_irq_vector, &irq_op)) | ||
61 | printk(KERN_WARNING "%s: xen_free_irq_vector fail vector=%d\n", | ||
62 | __func__, vector); | ||
63 | } | ||
64 | |||
65 | |||
66 | static DEFINE_PER_CPU(int, xen_timer_irq) = -1; | ||
67 | static DEFINE_PER_CPU(int, xen_ipi_irq) = -1; | ||
68 | static DEFINE_PER_CPU(int, xen_resched_irq) = -1; | ||
69 | static DEFINE_PER_CPU(int, xen_cmc_irq) = -1; | ||
70 | static DEFINE_PER_CPU(int, xen_cmcp_irq) = -1; | ||
71 | static DEFINE_PER_CPU(int, xen_cpep_irq) = -1; | ||
72 | #define NAME_SIZE 15 | ||
73 | static DEFINE_PER_CPU(char[NAME_SIZE], xen_timer_name); | ||
74 | static DEFINE_PER_CPU(char[NAME_SIZE], xen_ipi_name); | ||
75 | static DEFINE_PER_CPU(char[NAME_SIZE], xen_resched_name); | ||
76 | static DEFINE_PER_CPU(char[NAME_SIZE], xen_cmc_name); | ||
77 | static DEFINE_PER_CPU(char[NAME_SIZE], xen_cmcp_name); | ||
78 | static DEFINE_PER_CPU(char[NAME_SIZE], xen_cpep_name); | ||
79 | #undef NAME_SIZE | ||
80 | |||
81 | struct saved_irq { | ||
82 | unsigned int irq; | ||
83 | struct irqaction *action; | ||
84 | }; | ||
85 | /* 16 should be far optimistic value, since only several percpu irqs | ||
86 | * are registered early. | ||
87 | */ | ||
88 | #define MAX_LATE_IRQ 16 | ||
89 | static struct saved_irq saved_percpu_irqs[MAX_LATE_IRQ]; | ||
90 | static unsigned short late_irq_cnt; | ||
91 | static unsigned short saved_irq_cnt; | ||
92 | static int xen_slab_ready; | ||
93 | |||
94 | #ifdef CONFIG_SMP | ||
95 | #include <linux/sched.h> | ||
96 | |||
97 | /* Dummy stub. Though we may check XEN_RESCHEDULE_VECTOR before __do_IRQ, | ||
98 | * it ends up to issue several memory accesses upon percpu data and | ||
99 | * thus adds unnecessary traffic to other paths. | ||
100 | */ | ||
101 | static irqreturn_t | ||
102 | xen_dummy_handler(int irq, void *dev_id) | ||
103 | { | ||
104 | return IRQ_HANDLED; | ||
105 | } | ||
106 | |||
107 | static irqreturn_t | ||
108 | xen_resched_handler(int irq, void *dev_id) | ||
109 | { | ||
110 | scheduler_ipi(); | ||
111 | return IRQ_HANDLED; | ||
112 | } | ||
113 | |||
114 | static struct irqaction xen_ipi_irqaction = { | ||
115 | .handler = handle_IPI, | ||
116 | .flags = IRQF_DISABLED, | ||
117 | .name = "IPI" | ||
118 | }; | ||
119 | |||
120 | static struct irqaction xen_resched_irqaction = { | ||
121 | .handler = xen_resched_handler, | ||
122 | .flags = IRQF_DISABLED, | ||
123 | .name = "resched" | ||
124 | }; | ||
125 | |||
126 | static struct irqaction xen_tlb_irqaction = { | ||
127 | .handler = xen_dummy_handler, | ||
128 | .flags = IRQF_DISABLED, | ||
129 | .name = "tlb_flush" | ||
130 | }; | ||
131 | #endif | ||
132 | |||
133 | /* | ||
134 | * This is xen version percpu irq registration, which needs bind | ||
135 | * to xen specific evtchn sub-system. One trick here is that xen | ||
136 | * evtchn binding interface depends on kmalloc because related | ||
137 | * port needs to be freed at device/cpu down. So we cache the | ||
138 | * registration on BSP before slab is ready and then deal them | ||
139 | * at later point. For rest instances happening after slab ready, | ||
140 | * we hook them to xen evtchn immediately. | ||
141 | * | ||
142 | * FIXME: MCA is not supported by far, and thus "nomca" boot param is | ||
143 | * required. | ||
144 | */ | ||
145 | static void | ||
146 | __xen_register_percpu_irq(unsigned int cpu, unsigned int vec, | ||
147 | struct irqaction *action, int save) | ||
148 | { | ||
149 | int irq = 0; | ||
150 | |||
151 | if (xen_slab_ready) { | ||
152 | switch (vec) { | ||
153 | case IA64_TIMER_VECTOR: | ||
154 | snprintf(per_cpu(xen_timer_name, cpu), | ||
155 | sizeof(per_cpu(xen_timer_name, cpu)), | ||
156 | "%s%d", action->name, cpu); | ||
157 | irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu, | ||
158 | action->handler, action->flags, | ||
159 | per_cpu(xen_timer_name, cpu), action->dev_id); | ||
160 | per_cpu(xen_timer_irq, cpu) = irq; | ||
161 | break; | ||
162 | case IA64_IPI_RESCHEDULE: | ||
163 | snprintf(per_cpu(xen_resched_name, cpu), | ||
164 | sizeof(per_cpu(xen_resched_name, cpu)), | ||
165 | "%s%d", action->name, cpu); | ||
166 | irq = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, cpu, | ||
167 | action->handler, action->flags, | ||
168 | per_cpu(xen_resched_name, cpu), action->dev_id); | ||
169 | per_cpu(xen_resched_irq, cpu) = irq; | ||
170 | break; | ||
171 | case IA64_IPI_VECTOR: | ||
172 | snprintf(per_cpu(xen_ipi_name, cpu), | ||
173 | sizeof(per_cpu(xen_ipi_name, cpu)), | ||
174 | "%s%d", action->name, cpu); | ||
175 | irq = bind_ipi_to_irqhandler(XEN_IPI_VECTOR, cpu, | ||
176 | action->handler, action->flags, | ||
177 | per_cpu(xen_ipi_name, cpu), action->dev_id); | ||
178 | per_cpu(xen_ipi_irq, cpu) = irq; | ||
179 | break; | ||
180 | case IA64_CMC_VECTOR: | ||
181 | snprintf(per_cpu(xen_cmc_name, cpu), | ||
182 | sizeof(per_cpu(xen_cmc_name, cpu)), | ||
183 | "%s%d", action->name, cpu); | ||
184 | irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, | ||
185 | action->handler, | ||
186 | action->flags, | ||
187 | per_cpu(xen_cmc_name, cpu), | ||
188 | action->dev_id); | ||
189 | per_cpu(xen_cmc_irq, cpu) = irq; | ||
190 | break; | ||
191 | case IA64_CMCP_VECTOR: | ||
192 | snprintf(per_cpu(xen_cmcp_name, cpu), | ||
193 | sizeof(per_cpu(xen_cmcp_name, cpu)), | ||
194 | "%s%d", action->name, cpu); | ||
195 | irq = bind_ipi_to_irqhandler(XEN_CMCP_VECTOR, cpu, | ||
196 | action->handler, | ||
197 | action->flags, | ||
198 | per_cpu(xen_cmcp_name, cpu), | ||
199 | action->dev_id); | ||
200 | per_cpu(xen_cmcp_irq, cpu) = irq; | ||
201 | break; | ||
202 | case IA64_CPEP_VECTOR: | ||
203 | snprintf(per_cpu(xen_cpep_name, cpu), | ||
204 | sizeof(per_cpu(xen_cpep_name, cpu)), | ||
205 | "%s%d", action->name, cpu); | ||
206 | irq = bind_ipi_to_irqhandler(XEN_CPEP_VECTOR, cpu, | ||
207 | action->handler, | ||
208 | action->flags, | ||
209 | per_cpu(xen_cpep_name, cpu), | ||
210 | action->dev_id); | ||
211 | per_cpu(xen_cpep_irq, cpu) = irq; | ||
212 | break; | ||
213 | case IA64_CPE_VECTOR: | ||
214 | case IA64_MCA_RENDEZ_VECTOR: | ||
215 | case IA64_PERFMON_VECTOR: | ||
216 | case IA64_MCA_WAKEUP_VECTOR: | ||
217 | case IA64_SPURIOUS_INT_VECTOR: | ||
218 | /* No need to complain, these aren't supported. */ | ||
219 | break; | ||
220 | default: | ||
221 | printk(KERN_WARNING "Percpu irq %d is unsupported " | ||
222 | "by xen!\n", vec); | ||
223 | break; | ||
224 | } | ||
225 | BUG_ON(irq < 0); | ||
226 | |||
227 | if (irq > 0) { | ||
228 | /* | ||
229 | * Mark percpu. Without this, migrate_irqs() will | ||
230 | * mark the interrupt for migrations and trigger it | ||
231 | * on cpu hotplug. | ||
232 | */ | ||
233 | irq_set_status_flags(irq, IRQ_PER_CPU); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | /* For BSP, we cache registered percpu irqs, and then re-walk | ||
238 | * them when initializing APs | ||
239 | */ | ||
240 | if (!cpu && save) { | ||
241 | BUG_ON(saved_irq_cnt == MAX_LATE_IRQ); | ||
242 | saved_percpu_irqs[saved_irq_cnt].irq = vec; | ||
243 | saved_percpu_irqs[saved_irq_cnt].action = action; | ||
244 | saved_irq_cnt++; | ||
245 | if (!xen_slab_ready) | ||
246 | late_irq_cnt++; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static void | ||
251 | xen_register_percpu_irq(ia64_vector vec, struct irqaction *action) | ||
252 | { | ||
253 | __xen_register_percpu_irq(smp_processor_id(), vec, action, 1); | ||
254 | } | ||
255 | |||
256 | static void | ||
257 | xen_bind_early_percpu_irq(void) | ||
258 | { | ||
259 | int i; | ||
260 | |||
261 | xen_slab_ready = 1; | ||
262 | /* There's no race when accessing this cached array, since only | ||
263 | * BSP will face with such step shortly | ||
264 | */ | ||
265 | for (i = 0; i < late_irq_cnt; i++) | ||
266 | __xen_register_percpu_irq(smp_processor_id(), | ||
267 | saved_percpu_irqs[i].irq, | ||
268 | saved_percpu_irqs[i].action, 0); | ||
269 | } | ||
270 | |||
271 | /* FIXME: There's no obvious point to check whether slab is ready. So | ||
272 | * a hack is used here by utilizing a late time hook. | ||
273 | */ | ||
274 | |||
275 | #ifdef CONFIG_HOTPLUG_CPU | ||
276 | static int unbind_evtchn_callback(struct notifier_block *nfb, | ||
277 | unsigned long action, void *hcpu) | ||
278 | { | ||
279 | unsigned int cpu = (unsigned long)hcpu; | ||
280 | |||
281 | if (action == CPU_DEAD) { | ||
282 | /* Unregister evtchn. */ | ||
283 | if (per_cpu(xen_cpep_irq, cpu) >= 0) { | ||
284 | unbind_from_irqhandler(per_cpu(xen_cpep_irq, cpu), | ||
285 | NULL); | ||
286 | per_cpu(xen_cpep_irq, cpu) = -1; | ||
287 | } | ||
288 | if (per_cpu(xen_cmcp_irq, cpu) >= 0) { | ||
289 | unbind_from_irqhandler(per_cpu(xen_cmcp_irq, cpu), | ||
290 | NULL); | ||
291 | per_cpu(xen_cmcp_irq, cpu) = -1; | ||
292 | } | ||
293 | if (per_cpu(xen_cmc_irq, cpu) >= 0) { | ||
294 | unbind_from_irqhandler(per_cpu(xen_cmc_irq, cpu), NULL); | ||
295 | per_cpu(xen_cmc_irq, cpu) = -1; | ||
296 | } | ||
297 | if (per_cpu(xen_ipi_irq, cpu) >= 0) { | ||
298 | unbind_from_irqhandler(per_cpu(xen_ipi_irq, cpu), NULL); | ||
299 | per_cpu(xen_ipi_irq, cpu) = -1; | ||
300 | } | ||
301 | if (per_cpu(xen_resched_irq, cpu) >= 0) { | ||
302 | unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), | ||
303 | NULL); | ||
304 | per_cpu(xen_resched_irq, cpu) = -1; | ||
305 | } | ||
306 | if (per_cpu(xen_timer_irq, cpu) >= 0) { | ||
307 | unbind_from_irqhandler(per_cpu(xen_timer_irq, cpu), | ||
308 | NULL); | ||
309 | per_cpu(xen_timer_irq, cpu) = -1; | ||
310 | } | ||
311 | } | ||
312 | return NOTIFY_OK; | ||
313 | } | ||
314 | |||
315 | static struct notifier_block unbind_evtchn_notifier = { | ||
316 | .notifier_call = unbind_evtchn_callback, | ||
317 | .priority = 0 | ||
318 | }; | ||
319 | #endif | ||
320 | |||
321 | void xen_smp_intr_init_early(unsigned int cpu) | ||
322 | { | ||
323 | #ifdef CONFIG_SMP | ||
324 | unsigned int i; | ||
325 | |||
326 | for (i = 0; i < saved_irq_cnt; i++) | ||
327 | __xen_register_percpu_irq(cpu, saved_percpu_irqs[i].irq, | ||
328 | saved_percpu_irqs[i].action, 0); | ||
329 | #endif | ||
330 | } | ||
331 | |||
332 | void xen_smp_intr_init(void) | ||
333 | { | ||
334 | #ifdef CONFIG_SMP | ||
335 | unsigned int cpu = smp_processor_id(); | ||
336 | struct callback_register event = { | ||
337 | .type = CALLBACKTYPE_event, | ||
338 | .address = { .ip = (unsigned long)&xen_event_callback }, | ||
339 | }; | ||
340 | |||
341 | if (cpu == 0) { | ||
342 | /* Initialization was already done for boot cpu. */ | ||
343 | #ifdef CONFIG_HOTPLUG_CPU | ||
344 | /* Register the notifier only once. */ | ||
345 | register_cpu_notifier(&unbind_evtchn_notifier); | ||
346 | #endif | ||
347 | return; | ||
348 | } | ||
349 | |||
350 | /* This should be piggyback when setup vcpu guest context */ | ||
351 | BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); | ||
352 | #endif /* CONFIG_SMP */ | ||
353 | } | ||
354 | |||
355 | void __init | ||
356 | xen_irq_init(void) | ||
357 | { | ||
358 | struct callback_register event = { | ||
359 | .type = CALLBACKTYPE_event, | ||
360 | .address = { .ip = (unsigned long)&xen_event_callback }, | ||
361 | }; | ||
362 | |||
363 | xen_init_IRQ(); | ||
364 | BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); | ||
365 | late_time_init = xen_bind_early_percpu_irq; | ||
366 | } | ||
367 | |||
368 | void | ||
369 | xen_platform_send_ipi(int cpu, int vector, int delivery_mode, int redirect) | ||
370 | { | ||
371 | #ifdef CONFIG_SMP | ||
372 | /* TODO: we need to call vcpu_up here */ | ||
373 | if (unlikely(vector == ap_wakeup_vector)) { | ||
374 | /* XXX | ||
375 | * This should be in __cpu_up(cpu) in ia64 smpboot.c | ||
376 | * like x86. But don't want to modify it, | ||
377 | * keep it untouched. | ||
378 | */ | ||
379 | xen_smp_intr_init_early(cpu); | ||
380 | |||
381 | xen_send_ipi(cpu, vector); | ||
382 | /* vcpu_prepare_and_up(cpu); */ | ||
383 | return; | ||
384 | } | ||
385 | #endif | ||
386 | |||
387 | switch (vector) { | ||
388 | case IA64_IPI_VECTOR: | ||
389 | xen_send_IPI_one(cpu, XEN_IPI_VECTOR); | ||
390 | break; | ||
391 | case IA64_IPI_RESCHEDULE: | ||
392 | xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR); | ||
393 | break; | ||
394 | case IA64_CMCP_VECTOR: | ||
395 | xen_send_IPI_one(cpu, XEN_CMCP_VECTOR); | ||
396 | break; | ||
397 | case IA64_CPEP_VECTOR: | ||
398 | xen_send_IPI_one(cpu, XEN_CPEP_VECTOR); | ||
399 | break; | ||
400 | case IA64_TIMER_VECTOR: { | ||
401 | /* this is used only once by check_sal_cache_flush() | ||
402 | at boot time */ | ||
403 | static int used = 0; | ||
404 | if (!used) { | ||
405 | xen_send_ipi(cpu, IA64_TIMER_VECTOR); | ||
406 | used = 1; | ||
407 | break; | ||
408 | } | ||
409 | /* fallthrough */ | ||
410 | } | ||
411 | default: | ||
412 | printk(KERN_WARNING "Unsupported IPI type 0x%x\n", | ||
413 | vector); | ||
414 | notify_remote_via_irq(0); /* defaults to 0 irq */ | ||
415 | break; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | static void __init | ||
420 | xen_register_ipi(void) | ||
421 | { | ||
422 | #ifdef CONFIG_SMP | ||
423 | register_percpu_irq(IA64_IPI_VECTOR, &xen_ipi_irqaction); | ||
424 | register_percpu_irq(IA64_IPI_RESCHEDULE, &xen_resched_irqaction); | ||
425 | register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &xen_tlb_irqaction); | ||
426 | #endif | ||
427 | } | ||
428 | |||
429 | static void | ||
430 | xen_resend_irq(unsigned int vector) | ||
431 | { | ||
432 | (void)resend_irq_on_evtchn(vector); | ||
433 | } | ||
434 | |||
435 | const struct pv_irq_ops xen_irq_ops __initconst = { | ||
436 | .register_ipi = xen_register_ipi, | ||
437 | |||
438 | .assign_irq_vector = xen_assign_irq_vector, | ||
439 | .free_irq_vector = xen_free_irq_vector, | ||
440 | .register_percpu_irq = xen_register_percpu_irq, | ||
441 | |||
442 | .resend_irq = xen_resend_irq, | ||
443 | }; | ||
diff --git a/arch/ia64/xen/irq_xen.h b/arch/ia64/xen/irq_xen.h deleted file mode 100644 index 1778517b90fe..000000000000 --- a/arch/ia64/xen/irq_xen.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/xen/irq_xen.h | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef IRQ_XEN_H | ||
24 | #define IRQ_XEN_H | ||
25 | |||
26 | extern void (*late_time_init)(void); | ||
27 | extern char xen_event_callback; | ||
28 | void __init xen_init_IRQ(void); | ||
29 | |||
30 | extern const struct pv_irq_ops xen_irq_ops __initconst; | ||
31 | extern void xen_smp_intr_init(void); | ||
32 | extern void xen_send_ipi(int cpu, int vec); | ||
33 | |||
34 | #endif /* IRQ_XEN_H */ | ||
diff --git a/arch/ia64/xen/machvec.c b/arch/ia64/xen/machvec.c deleted file mode 100644 index 4ad588a7c279..000000000000 --- a/arch/ia64/xen/machvec.c +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #define MACHVEC_PLATFORM_NAME xen | ||
2 | #define MACHVEC_PLATFORM_HEADER <asm/machvec_xen.h> | ||
3 | #include <asm/machvec_init.h> | ||
4 | |||
diff --git a/arch/ia64/xen/suspend.c b/arch/ia64/xen/suspend.c deleted file mode 100644 index 419c8620945a..000000000000 --- a/arch/ia64/xen/suspend.c +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/xen/suspend.c | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | * suspend/resume | ||
22 | */ | ||
23 | |||
24 | #include <xen/xen-ops.h> | ||
25 | #include <asm/xen/hypervisor.h> | ||
26 | #include "time.h" | ||
27 | |||
28 | void | ||
29 | xen_mm_pin_all(void) | ||
30 | { | ||
31 | /* nothing */ | ||
32 | } | ||
33 | |||
34 | void | ||
35 | xen_mm_unpin_all(void) | ||
36 | { | ||
37 | /* nothing */ | ||
38 | } | ||
39 | |||
40 | void | ||
41 | xen_arch_pre_suspend() | ||
42 | { | ||
43 | /* nothing */ | ||
44 | } | ||
45 | |||
46 | void | ||
47 | xen_arch_post_suspend(int suspend_cancelled) | ||
48 | { | ||
49 | if (suspend_cancelled) | ||
50 | return; | ||
51 | |||
52 | xen_ia64_enable_opt_feature(); | ||
53 | /* add more if necessary */ | ||
54 | } | ||
55 | |||
56 | void xen_arch_resume(void) | ||
57 | { | ||
58 | xen_timer_resume_on_aps(); | ||
59 | } | ||
diff --git a/arch/ia64/xen/time.c b/arch/ia64/xen/time.c deleted file mode 100644 index 1f8244a78bee..000000000000 --- a/arch/ia64/xen/time.c +++ /dev/null | |||
@@ -1,257 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/xen/time.c | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/delay.h> | ||
24 | #include <linux/kernel_stat.h> | ||
25 | #include <linux/posix-timers.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/clocksource.h> | ||
28 | |||
29 | #include <asm/timex.h> | ||
30 | |||
31 | #include <asm/xen/hypervisor.h> | ||
32 | |||
33 | #include <xen/interface/vcpu.h> | ||
34 | |||
35 | #include "../kernel/fsyscall_gtod_data.h" | ||
36 | |||
37 | static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); | ||
38 | static DEFINE_PER_CPU(unsigned long, xen_stolen_time); | ||
39 | static DEFINE_PER_CPU(unsigned long, xen_blocked_time); | ||
40 | |||
41 | /* taken from i386/kernel/time-xen.c */ | ||
42 | static void xen_init_missing_ticks_accounting(int cpu) | ||
43 | { | ||
44 | struct vcpu_register_runstate_memory_area area; | ||
45 | struct vcpu_runstate_info *runstate = &per_cpu(xen_runstate, cpu); | ||
46 | int rc; | ||
47 | |||
48 | memset(runstate, 0, sizeof(*runstate)); | ||
49 | |||
50 | area.addr.v = runstate; | ||
51 | rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, | ||
52 | &area); | ||
53 | WARN_ON(rc && rc != -ENOSYS); | ||
54 | |||
55 | per_cpu(xen_blocked_time, cpu) = runstate->time[RUNSTATE_blocked]; | ||
56 | per_cpu(xen_stolen_time, cpu) = runstate->time[RUNSTATE_runnable] | ||
57 | + runstate->time[RUNSTATE_offline]; | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * Runstate accounting | ||
62 | */ | ||
63 | /* stolen from arch/x86/xen/time.c */ | ||
64 | static void get_runstate_snapshot(struct vcpu_runstate_info *res) | ||
65 | { | ||
66 | u64 state_time; | ||
67 | struct vcpu_runstate_info *state; | ||
68 | |||
69 | BUG_ON(preemptible()); | ||
70 | |||
71 | state = &__get_cpu_var(xen_runstate); | ||
72 | |||
73 | /* | ||
74 | * The runstate info is always updated by the hypervisor on | ||
75 | * the current CPU, so there's no need to use anything | ||
76 | * stronger than a compiler barrier when fetching it. | ||
77 | */ | ||
78 | do { | ||
79 | state_time = state->state_entry_time; | ||
80 | rmb(); | ||
81 | *res = *state; | ||
82 | rmb(); | ||
83 | } while (state->state_entry_time != state_time); | ||
84 | } | ||
85 | |||
86 | #define NS_PER_TICK (1000000000LL/HZ) | ||
87 | |||
88 | static unsigned long | ||
89 | consider_steal_time(unsigned long new_itm) | ||
90 | { | ||
91 | unsigned long stolen, blocked; | ||
92 | unsigned long delta_itm = 0, stolentick = 0; | ||
93 | int cpu = smp_processor_id(); | ||
94 | struct vcpu_runstate_info runstate; | ||
95 | struct task_struct *p = current; | ||
96 | |||
97 | get_runstate_snapshot(&runstate); | ||
98 | |||
99 | /* | ||
100 | * Check for vcpu migration effect | ||
101 | * In this case, itc value is reversed. | ||
102 | * This causes huge stolen value. | ||
103 | * This function just checks and reject this effect. | ||
104 | */ | ||
105 | if (!time_after_eq(runstate.time[RUNSTATE_blocked], | ||
106 | per_cpu(xen_blocked_time, cpu))) | ||
107 | blocked = 0; | ||
108 | |||
109 | if (!time_after_eq(runstate.time[RUNSTATE_runnable] + | ||
110 | runstate.time[RUNSTATE_offline], | ||
111 | per_cpu(xen_stolen_time, cpu))) | ||
112 | stolen = 0; | ||
113 | |||
114 | if (!time_after(delta_itm + new_itm, ia64_get_itc())) | ||
115 | stolentick = ia64_get_itc() - new_itm; | ||
116 | |||
117 | do_div(stolentick, NS_PER_TICK); | ||
118 | stolentick++; | ||
119 | |||
120 | do_div(stolen, NS_PER_TICK); | ||
121 | |||
122 | if (stolen > stolentick) | ||
123 | stolen = stolentick; | ||
124 | |||
125 | stolentick -= stolen; | ||
126 | do_div(blocked, NS_PER_TICK); | ||
127 | |||
128 | if (blocked > stolentick) | ||
129 | blocked = stolentick; | ||
130 | |||
131 | if (stolen > 0 || blocked > 0) { | ||
132 | account_steal_ticks(stolen); | ||
133 | account_idle_ticks(blocked); | ||
134 | run_local_timers(); | ||
135 | |||
136 | rcu_check_callbacks(cpu, user_mode(get_irq_regs())); | ||
137 | |||
138 | scheduler_tick(); | ||
139 | run_posix_cpu_timers(p); | ||
140 | delta_itm += local_cpu_data->itm_delta * (stolen + blocked); | ||
141 | |||
142 | if (cpu == time_keeper_id) | ||
143 | xtime_update(stolen + blocked); | ||
144 | |||
145 | local_cpu_data->itm_next = delta_itm + new_itm; | ||
146 | |||
147 | per_cpu(xen_stolen_time, cpu) += NS_PER_TICK * stolen; | ||
148 | per_cpu(xen_blocked_time, cpu) += NS_PER_TICK * blocked; | ||
149 | } | ||
150 | return delta_itm; | ||
151 | } | ||
152 | |||
153 | static int xen_do_steal_accounting(unsigned long *new_itm) | ||
154 | { | ||
155 | unsigned long delta_itm; | ||
156 | delta_itm = consider_steal_time(*new_itm); | ||
157 | *new_itm += delta_itm; | ||
158 | if (time_after(*new_itm, ia64_get_itc()) && delta_itm) | ||
159 | return 1; | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void xen_itc_jitter_data_reset(void) | ||
165 | { | ||
166 | u64 lcycle, ret; | ||
167 | |||
168 | do { | ||
169 | lcycle = itc_jitter_data.itc_lastcycle; | ||
170 | ret = cmpxchg(&itc_jitter_data.itc_lastcycle, lcycle, 0); | ||
171 | } while (unlikely(ret != lcycle)); | ||
172 | } | ||
173 | |||
174 | /* based on xen_sched_clock() in arch/x86/xen/time.c. */ | ||
175 | /* | ||
176 | * This relies on HAVE_UNSTABLE_SCHED_CLOCK. If it can't be defined, | ||
177 | * something similar logic should be implemented here. | ||
178 | */ | ||
179 | /* | ||
180 | * Xen sched_clock implementation. Returns the number of unstolen | ||
181 | * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED | ||
182 | * states. | ||
183 | */ | ||
184 | static unsigned long long xen_sched_clock(void) | ||
185 | { | ||
186 | struct vcpu_runstate_info runstate; | ||
187 | |||
188 | unsigned long long now; | ||
189 | unsigned long long offset; | ||
190 | unsigned long long ret; | ||
191 | |||
192 | /* | ||
193 | * Ideally sched_clock should be called on a per-cpu basis | ||
194 | * anyway, so preempt should already be disabled, but that's | ||
195 | * not current practice at the moment. | ||
196 | */ | ||
197 | preempt_disable(); | ||
198 | |||
199 | /* | ||
200 | * both ia64_native_sched_clock() and xen's runstate are | ||
201 | * based on mAR.ITC. So difference of them makes sense. | ||
202 | */ | ||
203 | now = ia64_native_sched_clock(); | ||
204 | |||
205 | get_runstate_snapshot(&runstate); | ||
206 | |||
207 | WARN_ON(runstate.state != RUNSTATE_running); | ||
208 | |||
209 | offset = 0; | ||
210 | if (now > runstate.state_entry_time) | ||
211 | offset = now - runstate.state_entry_time; | ||
212 | ret = runstate.time[RUNSTATE_blocked] + | ||
213 | runstate.time[RUNSTATE_running] + | ||
214 | offset; | ||
215 | |||
216 | preempt_enable(); | ||
217 | |||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | struct pv_time_ops xen_time_ops __initdata = { | ||
222 | .init_missing_ticks_accounting = xen_init_missing_ticks_accounting, | ||
223 | .do_steal_accounting = xen_do_steal_accounting, | ||
224 | .clocksource_resume = xen_itc_jitter_data_reset, | ||
225 | .sched_clock = xen_sched_clock, | ||
226 | }; | ||
227 | |||
228 | /* Called after suspend, to resume time. */ | ||
229 | static void xen_local_tick_resume(void) | ||
230 | { | ||
231 | /* Just trigger a tick. */ | ||
232 | ia64_cpu_local_tick(); | ||
233 | touch_softlockup_watchdog(); | ||
234 | } | ||
235 | |||
236 | void | ||
237 | xen_timer_resume(void) | ||
238 | { | ||
239 | unsigned int cpu; | ||
240 | |||
241 | xen_local_tick_resume(); | ||
242 | |||
243 | for_each_online_cpu(cpu) | ||
244 | xen_init_missing_ticks_accounting(cpu); | ||
245 | } | ||
246 | |||
247 | static void ia64_cpu_local_tick_fn(void *unused) | ||
248 | { | ||
249 | xen_local_tick_resume(); | ||
250 | xen_init_missing_ticks_accounting(smp_processor_id()); | ||
251 | } | ||
252 | |||
253 | void | ||
254 | xen_timer_resume_on_aps(void) | ||
255 | { | ||
256 | smp_call_function(&ia64_cpu_local_tick_fn, NULL, 1); | ||
257 | } | ||
diff --git a/arch/ia64/xen/time.h b/arch/ia64/xen/time.h deleted file mode 100644 index f98d7e1a42f0..000000000000 --- a/arch/ia64/xen/time.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/xen/time.h | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | extern struct pv_time_ops xen_time_ops __initdata; | ||
24 | void xen_timer_resume_on_aps(void); | ||
diff --git a/arch/ia64/xen/xcom_hcall.c b/arch/ia64/xen/xcom_hcall.c deleted file mode 100644 index ccaf7431f7c8..000000000000 --- a/arch/ia64/xen/xcom_hcall.c +++ /dev/null | |||
@@ -1,441 +0,0 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
15 | * | ||
16 | * Tristan Gingold <tristan.gingold@bull.net> | ||
17 | * | ||
18 | * Copyright (c) 2007 | ||
19 | * Isaku Yamahata <yamahata at valinux co jp> | ||
20 | * VA Linux Systems Japan K.K. | ||
21 | * consolidate mini and inline version. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <xen/interface/xen.h> | ||
26 | #include <xen/interface/memory.h> | ||
27 | #include <xen/interface/grant_table.h> | ||
28 | #include <xen/interface/callback.h> | ||
29 | #include <xen/interface/vcpu.h> | ||
30 | #include <asm/xen/hypervisor.h> | ||
31 | #include <asm/xen/xencomm.h> | ||
32 | |||
33 | /* Xencomm notes: | ||
34 | * This file defines hypercalls to be used by xencomm. The hypercalls simply | ||
35 | * create inlines or mini descriptors for pointers and then call the raw arch | ||
36 | * hypercall xencomm_arch_hypercall_XXX | ||
37 | * | ||
38 | * If the arch wants to directly use these hypercalls, simply define macros | ||
39 | * in asm/xen/hypercall.h, eg: | ||
40 | * #define HYPERVISOR_sched_op xencomm_hypercall_sched_op | ||
41 | * | ||
42 | * The arch may also define HYPERVISOR_xxx as a function and do more operations | ||
43 | * before/after doing the hypercall. | ||
44 | * | ||
45 | * Note: because only inline or mini descriptors are created these functions | ||
46 | * must only be called with in kernel memory parameters. | ||
47 | */ | ||
48 | |||
49 | int | ||
50 | xencomm_hypercall_console_io(int cmd, int count, char *str) | ||
51 | { | ||
52 | /* xen early printk uses console io hypercall before | ||
53 | * xencomm initialization. In that case, we just ignore it. | ||
54 | */ | ||
55 | if (!xencomm_is_initialized()) | ||
56 | return 0; | ||
57 | |||
58 | return xencomm_arch_hypercall_console_io | ||
59 | (cmd, count, xencomm_map_no_alloc(str, count)); | ||
60 | } | ||
61 | EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io); | ||
62 | |||
63 | int | ||
64 | xencomm_hypercall_event_channel_op(int cmd, void *op) | ||
65 | { | ||
66 | struct xencomm_handle *desc; | ||
67 | desc = xencomm_map_no_alloc(op, sizeof(struct evtchn_op)); | ||
68 | if (desc == NULL) | ||
69 | return -EINVAL; | ||
70 | |||
71 | return xencomm_arch_hypercall_event_channel_op(cmd, desc); | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op); | ||
74 | |||
75 | int | ||
76 | xencomm_hypercall_xen_version(int cmd, void *arg) | ||
77 | { | ||
78 | struct xencomm_handle *desc; | ||
79 | unsigned int argsize; | ||
80 | |||
81 | switch (cmd) { | ||
82 | case XENVER_version: | ||
83 | /* do not actually pass an argument */ | ||
84 | return xencomm_arch_hypercall_xen_version(cmd, 0); | ||
85 | case XENVER_extraversion: | ||
86 | argsize = sizeof(struct xen_extraversion); | ||
87 | break; | ||
88 | case XENVER_compile_info: | ||
89 | argsize = sizeof(struct xen_compile_info); | ||
90 | break; | ||
91 | case XENVER_capabilities: | ||
92 | argsize = sizeof(struct xen_capabilities_info); | ||
93 | break; | ||
94 | case XENVER_changeset: | ||
95 | argsize = sizeof(struct xen_changeset_info); | ||
96 | break; | ||
97 | case XENVER_platform_parameters: | ||
98 | argsize = sizeof(struct xen_platform_parameters); | ||
99 | break; | ||
100 | case XENVER_get_features: | ||
101 | argsize = (arg == NULL) ? 0 : sizeof(struct xen_feature_info); | ||
102 | break; | ||
103 | |||
104 | default: | ||
105 | printk(KERN_DEBUG | ||
106 | "%s: unknown version op %d\n", __func__, cmd); | ||
107 | return -ENOSYS; | ||
108 | } | ||
109 | |||
110 | desc = xencomm_map_no_alloc(arg, argsize); | ||
111 | if (desc == NULL) | ||
112 | return -EINVAL; | ||
113 | |||
114 | return xencomm_arch_hypercall_xen_version(cmd, desc); | ||
115 | } | ||
116 | EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version); | ||
117 | |||
118 | int | ||
119 | xencomm_hypercall_physdev_op(int cmd, void *op) | ||
120 | { | ||
121 | unsigned int argsize; | ||
122 | |||
123 | switch (cmd) { | ||
124 | case PHYSDEVOP_apic_read: | ||
125 | case PHYSDEVOP_apic_write: | ||
126 | argsize = sizeof(struct physdev_apic); | ||
127 | break; | ||
128 | case PHYSDEVOP_alloc_irq_vector: | ||
129 | case PHYSDEVOP_free_irq_vector: | ||
130 | argsize = sizeof(struct physdev_irq); | ||
131 | break; | ||
132 | case PHYSDEVOP_irq_status_query: | ||
133 | argsize = sizeof(struct physdev_irq_status_query); | ||
134 | break; | ||
135 | |||
136 | default: | ||
137 | printk(KERN_DEBUG | ||
138 | "%s: unknown physdev op %d\n", __func__, cmd); | ||
139 | return -ENOSYS; | ||
140 | } | ||
141 | |||
142 | return xencomm_arch_hypercall_physdev_op | ||
143 | (cmd, xencomm_map_no_alloc(op, argsize)); | ||
144 | } | ||
145 | |||
146 | static int | ||
147 | xencommize_grant_table_op(struct xencomm_mini **xc_area, | ||
148 | unsigned int cmd, void *op, unsigned int count, | ||
149 | struct xencomm_handle **desc) | ||
150 | { | ||
151 | struct xencomm_handle *desc1; | ||
152 | unsigned int argsize; | ||
153 | |||
154 | switch (cmd) { | ||
155 | case GNTTABOP_map_grant_ref: | ||
156 | argsize = sizeof(struct gnttab_map_grant_ref); | ||
157 | break; | ||
158 | case GNTTABOP_unmap_grant_ref: | ||
159 | argsize = sizeof(struct gnttab_unmap_grant_ref); | ||
160 | break; | ||
161 | case GNTTABOP_setup_table: | ||
162 | { | ||
163 | struct gnttab_setup_table *setup = op; | ||
164 | |||
165 | argsize = sizeof(*setup); | ||
166 | |||
167 | if (count != 1) | ||
168 | return -EINVAL; | ||
169 | desc1 = __xencomm_map_no_alloc | ||
170 | (xen_guest_handle(setup->frame_list), | ||
171 | setup->nr_frames * | ||
172 | sizeof(*xen_guest_handle(setup->frame_list)), | ||
173 | *xc_area); | ||
174 | if (desc1 == NULL) | ||
175 | return -EINVAL; | ||
176 | (*xc_area)++; | ||
177 | set_xen_guest_handle(setup->frame_list, (void *)desc1); | ||
178 | break; | ||
179 | } | ||
180 | case GNTTABOP_dump_table: | ||
181 | argsize = sizeof(struct gnttab_dump_table); | ||
182 | break; | ||
183 | case GNTTABOP_transfer: | ||
184 | argsize = sizeof(struct gnttab_transfer); | ||
185 | break; | ||
186 | case GNTTABOP_copy: | ||
187 | argsize = sizeof(struct gnttab_copy); | ||
188 | break; | ||
189 | case GNTTABOP_query_size: | ||
190 | argsize = sizeof(struct gnttab_query_size); | ||
191 | break; | ||
192 | default: | ||
193 | printk(KERN_DEBUG "%s: unknown hypercall grant table op %d\n", | ||
194 | __func__, cmd); | ||
195 | BUG(); | ||
196 | } | ||
197 | |||
198 | *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area); | ||
199 | if (*desc == NULL) | ||
200 | return -EINVAL; | ||
201 | (*xc_area)++; | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | int | ||
207 | xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, | ||
208 | unsigned int count) | ||
209 | { | ||
210 | int rc; | ||
211 | struct xencomm_handle *desc; | ||
212 | XENCOMM_MINI_ALIGNED(xc_area, 2); | ||
213 | |||
214 | rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc); | ||
215 | if (rc) | ||
216 | return rc; | ||
217 | |||
218 | return xencomm_arch_hypercall_grant_table_op(cmd, desc, count); | ||
219 | } | ||
220 | EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op); | ||
221 | |||
222 | int | ||
223 | xencomm_hypercall_sched_op(int cmd, void *arg) | ||
224 | { | ||
225 | struct xencomm_handle *desc; | ||
226 | unsigned int argsize; | ||
227 | |||
228 | switch (cmd) { | ||
229 | case SCHEDOP_yield: | ||
230 | case SCHEDOP_block: | ||
231 | argsize = 0; | ||
232 | break; | ||
233 | case SCHEDOP_shutdown: | ||
234 | argsize = sizeof(struct sched_shutdown); | ||
235 | break; | ||
236 | case SCHEDOP_poll: | ||
237 | { | ||
238 | struct sched_poll *poll = arg; | ||
239 | struct xencomm_handle *ports; | ||
240 | |||
241 | argsize = sizeof(struct sched_poll); | ||
242 | ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports), | ||
243 | sizeof(*xen_guest_handle(poll->ports))); | ||
244 | |||
245 | set_xen_guest_handle(poll->ports, (void *)ports); | ||
246 | break; | ||
247 | } | ||
248 | default: | ||
249 | printk(KERN_DEBUG "%s: unknown sched op %d\n", __func__, cmd); | ||
250 | return -ENOSYS; | ||
251 | } | ||
252 | |||
253 | desc = xencomm_map_no_alloc(arg, argsize); | ||
254 | if (desc == NULL) | ||
255 | return -EINVAL; | ||
256 | |||
257 | return xencomm_arch_hypercall_sched_op(cmd, desc); | ||
258 | } | ||
259 | EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op); | ||
260 | |||
261 | int | ||
262 | xencomm_hypercall_multicall(void *call_list, int nr_calls) | ||
263 | { | ||
264 | int rc; | ||
265 | int i; | ||
266 | struct multicall_entry *mce; | ||
267 | struct xencomm_handle *desc; | ||
268 | XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2); | ||
269 | |||
270 | for (i = 0; i < nr_calls; i++) { | ||
271 | mce = (struct multicall_entry *)call_list + i; | ||
272 | |||
273 | switch (mce->op) { | ||
274 | case __HYPERVISOR_update_va_mapping: | ||
275 | case __HYPERVISOR_mmu_update: | ||
276 | /* No-op on ia64. */ | ||
277 | break; | ||
278 | case __HYPERVISOR_grant_table_op: | ||
279 | rc = xencommize_grant_table_op | ||
280 | (&xc_area, | ||
281 | mce->args[0], (void *)mce->args[1], | ||
282 | mce->args[2], &desc); | ||
283 | if (rc) | ||
284 | return rc; | ||
285 | mce->args[1] = (unsigned long)desc; | ||
286 | break; | ||
287 | case __HYPERVISOR_memory_op: | ||
288 | default: | ||
289 | printk(KERN_DEBUG | ||
290 | "%s: unhandled multicall op entry op %lu\n", | ||
291 | __func__, mce->op); | ||
292 | return -ENOSYS; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | desc = xencomm_map_no_alloc(call_list, | ||
297 | nr_calls * sizeof(struct multicall_entry)); | ||
298 | if (desc == NULL) | ||
299 | return -EINVAL; | ||
300 | |||
301 | return xencomm_arch_hypercall_multicall(desc, nr_calls); | ||
302 | } | ||
303 | EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall); | ||
304 | |||
305 | int | ||
306 | xencomm_hypercall_callback_op(int cmd, void *arg) | ||
307 | { | ||
308 | unsigned int argsize; | ||
309 | switch (cmd) { | ||
310 | case CALLBACKOP_register: | ||
311 | argsize = sizeof(struct callback_register); | ||
312 | break; | ||
313 | case CALLBACKOP_unregister: | ||
314 | argsize = sizeof(struct callback_unregister); | ||
315 | break; | ||
316 | default: | ||
317 | printk(KERN_DEBUG | ||
318 | "%s: unknown callback op %d\n", __func__, cmd); | ||
319 | return -ENOSYS; | ||
320 | } | ||
321 | |||
322 | return xencomm_arch_hypercall_callback_op | ||
323 | (cmd, xencomm_map_no_alloc(arg, argsize)); | ||
324 | } | ||
325 | |||
326 | static int | ||
327 | xencommize_memory_reservation(struct xencomm_mini *xc_area, | ||
328 | struct xen_memory_reservation *mop) | ||
329 | { | ||
330 | struct xencomm_handle *desc; | ||
331 | |||
332 | desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start), | ||
333 | mop->nr_extents * | ||
334 | sizeof(*xen_guest_handle(mop->extent_start)), | ||
335 | xc_area); | ||
336 | if (desc == NULL) | ||
337 | return -EINVAL; | ||
338 | |||
339 | set_xen_guest_handle(mop->extent_start, (void *)desc); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | int | ||
344 | xencomm_hypercall_memory_op(unsigned int cmd, void *arg) | ||
345 | { | ||
346 | GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} }; | ||
347 | struct xen_memory_reservation *xmr = NULL; | ||
348 | int rc; | ||
349 | struct xencomm_handle *desc; | ||
350 | unsigned int argsize; | ||
351 | XENCOMM_MINI_ALIGNED(xc_area, 2); | ||
352 | |||
353 | switch (cmd) { | ||
354 | case XENMEM_increase_reservation: | ||
355 | case XENMEM_decrease_reservation: | ||
356 | case XENMEM_populate_physmap: | ||
357 | xmr = (struct xen_memory_reservation *)arg; | ||
358 | set_xen_guest_handle(extent_start_va[0], | ||
359 | xen_guest_handle(xmr->extent_start)); | ||
360 | |||
361 | argsize = sizeof(*xmr); | ||
362 | rc = xencommize_memory_reservation(xc_area, xmr); | ||
363 | if (rc) | ||
364 | return rc; | ||
365 | xc_area++; | ||
366 | break; | ||
367 | |||
368 | case XENMEM_maximum_ram_page: | ||
369 | argsize = 0; | ||
370 | break; | ||
371 | |||
372 | case XENMEM_add_to_physmap: | ||
373 | argsize = sizeof(struct xen_add_to_physmap); | ||
374 | break; | ||
375 | |||
376 | default: | ||
377 | printk(KERN_DEBUG "%s: unknown memory op %d\n", __func__, cmd); | ||
378 | return -ENOSYS; | ||
379 | } | ||
380 | |||
381 | desc = xencomm_map_no_alloc(arg, argsize); | ||
382 | if (desc == NULL) | ||
383 | return -EINVAL; | ||
384 | |||
385 | rc = xencomm_arch_hypercall_memory_op(cmd, desc); | ||
386 | |||
387 | switch (cmd) { | ||
388 | case XENMEM_increase_reservation: | ||
389 | case XENMEM_decrease_reservation: | ||
390 | case XENMEM_populate_physmap: | ||
391 | set_xen_guest_handle(xmr->extent_start, | ||
392 | xen_guest_handle(extent_start_va[0])); | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | return rc; | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op); | ||
399 | |||
400 | int | ||
401 | xencomm_hypercall_suspend(unsigned long srec) | ||
402 | { | ||
403 | struct sched_shutdown arg; | ||
404 | |||
405 | arg.reason = SHUTDOWN_suspend; | ||
406 | |||
407 | return xencomm_arch_hypercall_sched_op( | ||
408 | SCHEDOP_shutdown, xencomm_map_no_alloc(&arg, sizeof(arg))); | ||
409 | } | ||
410 | |||
411 | long | ||
412 | xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg) | ||
413 | { | ||
414 | unsigned int argsize; | ||
415 | switch (cmd) { | ||
416 | case VCPUOP_register_runstate_memory_area: { | ||
417 | struct vcpu_register_runstate_memory_area *area = | ||
418 | (struct vcpu_register_runstate_memory_area *)arg; | ||
419 | argsize = sizeof(*arg); | ||
420 | set_xen_guest_handle(area->addr.h, | ||
421 | (void *)xencomm_map_no_alloc(area->addr.v, | ||
422 | sizeof(area->addr.v))); | ||
423 | break; | ||
424 | } | ||
425 | |||
426 | default: | ||
427 | printk(KERN_DEBUG "%s: unknown vcpu op %d\n", __func__, cmd); | ||
428 | return -ENOSYS; | ||
429 | } | ||
430 | |||
431 | return xencomm_arch_hypercall_vcpu_op(cmd, cpu, | ||
432 | xencomm_map_no_alloc(arg, argsize)); | ||
433 | } | ||
434 | |||
435 | long | ||
436 | xencomm_hypercall_opt_feature(void *arg) | ||
437 | { | ||
438 | return xencomm_arch_hypercall_opt_feature( | ||
439 | xencomm_map_no_alloc(arg, | ||
440 | sizeof(struct xen_ia64_opt_feature))); | ||
441 | } | ||
diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c deleted file mode 100644 index 3e8d350fdf39..000000000000 --- a/arch/ia64/xen/xen_pv_ops.c +++ /dev/null | |||
@@ -1,1141 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch/ia64/xen/xen_pv_ops.c | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/console.h> | ||
24 | #include <linux/irq.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/pm.h> | ||
27 | #include <linux/unistd.h> | ||
28 | |||
29 | #include <asm/xen/hypervisor.h> | ||
30 | #include <asm/xen/xencomm.h> | ||
31 | #include <asm/xen/privop.h> | ||
32 | |||
33 | #include "irq_xen.h" | ||
34 | #include "time.h" | ||
35 | |||
36 | /*************************************************************************** | ||
37 | * general info | ||
38 | */ | ||
39 | static struct pv_info xen_info __initdata = { | ||
40 | .kernel_rpl = 2, /* or 1: determin at runtime */ | ||
41 | .paravirt_enabled = 1, | ||
42 | .name = "Xen/ia64", | ||
43 | }; | ||
44 | |||
45 | #define IA64_RSC_PL_SHIFT 2 | ||
46 | #define IA64_RSC_PL_BIT_SIZE 2 | ||
47 | #define IA64_RSC_PL_MASK \ | ||
48 | (((1UL << IA64_RSC_PL_BIT_SIZE) - 1) << IA64_RSC_PL_SHIFT) | ||
49 | |||
50 | static void __init | ||
51 | xen_info_init(void) | ||
52 | { | ||
53 | /* Xenified Linux/ia64 may run on pl = 1 or 2. | ||
54 | * determin at run time. */ | ||
55 | unsigned long rsc = ia64_getreg(_IA64_REG_AR_RSC); | ||
56 | unsigned int rpl = (rsc & IA64_RSC_PL_MASK) >> IA64_RSC_PL_SHIFT; | ||
57 | xen_info.kernel_rpl = rpl; | ||
58 | } | ||
59 | |||
60 | /*************************************************************************** | ||
61 | * pv_init_ops | ||
62 | * initialization hooks. | ||
63 | */ | ||
64 | |||
65 | static void | ||
66 | xen_panic_hypercall(struct unw_frame_info *info, void *arg) | ||
67 | { | ||
68 | current->thread.ksp = (__u64)info->sw - 16; | ||
69 | HYPERVISOR_shutdown(SHUTDOWN_crash); | ||
70 | /* we're never actually going to get here... */ | ||
71 | } | ||
72 | |||
73 | static int | ||
74 | xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) | ||
75 | { | ||
76 | unw_init_running(xen_panic_hypercall, NULL); | ||
77 | /* we're never actually going to get here... */ | ||
78 | return NOTIFY_DONE; | ||
79 | } | ||
80 | |||
81 | static struct notifier_block xen_panic_block = { | ||
82 | xen_panic_event, NULL, 0 /* try to go last */ | ||
83 | }; | ||
84 | |||
85 | static void xen_pm_power_off(void) | ||
86 | { | ||
87 | local_irq_disable(); | ||
88 | HYPERVISOR_shutdown(SHUTDOWN_poweroff); | ||
89 | } | ||
90 | |||
91 | static void __init | ||
92 | xen_banner(void) | ||
93 | { | ||
94 | printk(KERN_INFO | ||
95 | "Running on Xen! pl = %d start_info_pfn=0x%lx nr_pages=%ld " | ||
96 | "flags=0x%x\n", | ||
97 | xen_info.kernel_rpl, | ||
98 | HYPERVISOR_shared_info->arch.start_info_pfn, | ||
99 | xen_start_info->nr_pages, xen_start_info->flags); | ||
100 | } | ||
101 | |||
102 | static int __init | ||
103 | xen_reserve_memory(struct rsvd_region *region) | ||
104 | { | ||
105 | region->start = (unsigned long)__va( | ||
106 | (HYPERVISOR_shared_info->arch.start_info_pfn << PAGE_SHIFT)); | ||
107 | region->end = region->start + PAGE_SIZE; | ||
108 | return 1; | ||
109 | } | ||
110 | |||
111 | static void __init | ||
112 | xen_arch_setup_early(void) | ||
113 | { | ||
114 | struct shared_info *s; | ||
115 | BUG_ON(!xen_pv_domain()); | ||
116 | |||
117 | s = HYPERVISOR_shared_info; | ||
118 | xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT); | ||
119 | |||
120 | /* Must be done before any hypercall. */ | ||
121 | xencomm_initialize(); | ||
122 | |||
123 | xen_setup_features(); | ||
124 | /* Register a call for panic conditions. */ | ||
125 | atomic_notifier_chain_register(&panic_notifier_list, | ||
126 | &xen_panic_block); | ||
127 | pm_power_off = xen_pm_power_off; | ||
128 | |||
129 | xen_ia64_enable_opt_feature(); | ||
130 | } | ||
131 | |||
132 | static void __init | ||
133 | xen_arch_setup_console(char **cmdline_p) | ||
134 | { | ||
135 | add_preferred_console("xenboot", 0, NULL); | ||
136 | add_preferred_console("tty", 0, NULL); | ||
137 | /* use hvc_xen */ | ||
138 | add_preferred_console("hvc", 0, NULL); | ||
139 | |||
140 | #if !defined(CONFIG_VT) || !defined(CONFIG_DUMMY_CONSOLE) | ||
141 | conswitchp = NULL; | ||
142 | #endif | ||
143 | } | ||
144 | |||
145 | static int __init | ||
146 | xen_arch_setup_nomca(void) | ||
147 | { | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | static void __init | ||
152 | xen_post_smp_prepare_boot_cpu(void) | ||
153 | { | ||
154 | xen_setup_vcpu_info_placement(); | ||
155 | } | ||
156 | |||
157 | #ifdef ASM_SUPPORTED | ||
158 | static unsigned long __init_or_module | ||
159 | xen_patch_bundle(void *sbundle, void *ebundle, unsigned long type); | ||
160 | #endif | ||
161 | static void __init | ||
162 | xen_patch_branch(unsigned long tag, unsigned long type); | ||
163 | |||
164 | static const struct pv_init_ops xen_init_ops __initconst = { | ||
165 | .banner = xen_banner, | ||
166 | |||
167 | .reserve_memory = xen_reserve_memory, | ||
168 | |||
169 | .arch_setup_early = xen_arch_setup_early, | ||
170 | .arch_setup_console = xen_arch_setup_console, | ||
171 | .arch_setup_nomca = xen_arch_setup_nomca, | ||
172 | |||
173 | .post_smp_prepare_boot_cpu = xen_post_smp_prepare_boot_cpu, | ||
174 | #ifdef ASM_SUPPORTED | ||
175 | .patch_bundle = xen_patch_bundle, | ||
176 | #endif | ||
177 | .patch_branch = xen_patch_branch, | ||
178 | }; | ||
179 | |||
180 | /*************************************************************************** | ||
181 | * pv_fsys_data | ||
182 | * addresses for fsys | ||
183 | */ | ||
184 | |||
185 | extern unsigned long xen_fsyscall_table[NR_syscalls]; | ||
186 | extern char xen_fsys_bubble_down[]; | ||
187 | struct pv_fsys_data xen_fsys_data __initdata = { | ||
188 | .fsyscall_table = (unsigned long *)xen_fsyscall_table, | ||
189 | .fsys_bubble_down = (void *)xen_fsys_bubble_down, | ||
190 | }; | ||
191 | |||
192 | /*************************************************************************** | ||
193 | * pv_patchdata | ||
194 | * patchdata addresses | ||
195 | */ | ||
196 | |||
197 | #define DECLARE(name) \ | ||
198 | extern unsigned long __xen_start_gate_##name##_patchlist[]; \ | ||
199 | extern unsigned long __xen_end_gate_##name##_patchlist[] | ||
200 | |||
201 | DECLARE(fsyscall); | ||
202 | DECLARE(brl_fsys_bubble_down); | ||
203 | DECLARE(vtop); | ||
204 | DECLARE(mckinley_e9); | ||
205 | |||
206 | extern unsigned long __xen_start_gate_section[]; | ||
207 | |||
208 | #define ASSIGN(name) \ | ||
209 | .start_##name##_patchlist = \ | ||
210 | (unsigned long)__xen_start_gate_##name##_patchlist, \ | ||
211 | .end_##name##_patchlist = \ | ||
212 | (unsigned long)__xen_end_gate_##name##_patchlist | ||
213 | |||
214 | static struct pv_patchdata xen_patchdata __initdata = { | ||
215 | ASSIGN(fsyscall), | ||
216 | ASSIGN(brl_fsys_bubble_down), | ||
217 | ASSIGN(vtop), | ||
218 | ASSIGN(mckinley_e9), | ||
219 | |||
220 | .gate_section = (void*)__xen_start_gate_section, | ||
221 | }; | ||
222 | |||
223 | /*************************************************************************** | ||
224 | * pv_cpu_ops | ||
225 | * intrinsics hooks. | ||
226 | */ | ||
227 | |||
228 | #ifndef ASM_SUPPORTED | ||
229 | static void | ||
230 | xen_set_itm_with_offset(unsigned long val) | ||
231 | { | ||
232 | /* ia64_cpu_local_tick() calls this with interrupt enabled. */ | ||
233 | /* WARN_ON(!irqs_disabled()); */ | ||
234 | xen_set_itm(val - XEN_MAPPEDREGS->itc_offset); | ||
235 | } | ||
236 | |||
237 | static unsigned long | ||
238 | xen_get_itm_with_offset(void) | ||
239 | { | ||
240 | /* unused at this moment */ | ||
241 | printk(KERN_DEBUG "%s is called.\n", __func__); | ||
242 | |||
243 | WARN_ON(!irqs_disabled()); | ||
244 | return ia64_native_getreg(_IA64_REG_CR_ITM) + | ||
245 | XEN_MAPPEDREGS->itc_offset; | ||
246 | } | ||
247 | |||
248 | /* ia64_set_itc() is only called by | ||
249 | * cpu_init() with ia64_set_itc(0) and ia64_sync_itc(). | ||
250 | * So XEN_MAPPEDRESG->itc_offset cal be considered as almost constant. | ||
251 | */ | ||
252 | static void | ||
253 | xen_set_itc(unsigned long val) | ||
254 | { | ||
255 | unsigned long mitc; | ||
256 | |||
257 | WARN_ON(!irqs_disabled()); | ||
258 | mitc = ia64_native_getreg(_IA64_REG_AR_ITC); | ||
259 | XEN_MAPPEDREGS->itc_offset = val - mitc; | ||
260 | XEN_MAPPEDREGS->itc_last = val; | ||
261 | } | ||
262 | |||
263 | static unsigned long | ||
264 | xen_get_itc(void) | ||
265 | { | ||
266 | unsigned long res; | ||
267 | unsigned long itc_offset; | ||
268 | unsigned long itc_last; | ||
269 | unsigned long ret_itc_last; | ||
270 | |||
271 | itc_offset = XEN_MAPPEDREGS->itc_offset; | ||
272 | do { | ||
273 | itc_last = XEN_MAPPEDREGS->itc_last; | ||
274 | res = ia64_native_getreg(_IA64_REG_AR_ITC); | ||
275 | res += itc_offset; | ||
276 | if (itc_last >= res) | ||
277 | res = itc_last + 1; | ||
278 | ret_itc_last = cmpxchg(&XEN_MAPPEDREGS->itc_last, | ||
279 | itc_last, res); | ||
280 | } while (unlikely(ret_itc_last != itc_last)); | ||
281 | return res; | ||
282 | |||
283 | #if 0 | ||
284 | /* ia64_itc_udelay() calls ia64_get_itc() with interrupt enabled. | ||
285 | Should it be paravirtualized instead? */ | ||
286 | WARN_ON(!irqs_disabled()); | ||
287 | itc_offset = XEN_MAPPEDREGS->itc_offset; | ||
288 | itc_last = XEN_MAPPEDREGS->itc_last; | ||
289 | res = ia64_native_getreg(_IA64_REG_AR_ITC); | ||
290 | res += itc_offset; | ||
291 | if (itc_last >= res) | ||
292 | res = itc_last + 1; | ||
293 | XEN_MAPPEDREGS->itc_last = res; | ||
294 | return res; | ||
295 | #endif | ||
296 | } | ||
297 | |||
298 | static void xen_setreg(int regnum, unsigned long val) | ||
299 | { | ||
300 | switch (regnum) { | ||
301 | case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: | ||
302 | xen_set_kr(regnum - _IA64_REG_AR_KR0, val); | ||
303 | break; | ||
304 | case _IA64_REG_AR_ITC: | ||
305 | xen_set_itc(val); | ||
306 | break; | ||
307 | case _IA64_REG_CR_TPR: | ||
308 | xen_set_tpr(val); | ||
309 | break; | ||
310 | case _IA64_REG_CR_ITM: | ||
311 | xen_set_itm_with_offset(val); | ||
312 | break; | ||
313 | case _IA64_REG_CR_EOI: | ||
314 | xen_eoi(val); | ||
315 | break; | ||
316 | default: | ||
317 | ia64_native_setreg_func(regnum, val); | ||
318 | break; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | static unsigned long xen_getreg(int regnum) | ||
323 | { | ||
324 | unsigned long res; | ||
325 | |||
326 | switch (regnum) { | ||
327 | case _IA64_REG_PSR: | ||
328 | res = xen_get_psr(); | ||
329 | break; | ||
330 | case _IA64_REG_AR_ITC: | ||
331 | res = xen_get_itc(); | ||
332 | break; | ||
333 | case _IA64_REG_CR_ITM: | ||
334 | res = xen_get_itm_with_offset(); | ||
335 | break; | ||
336 | case _IA64_REG_CR_IVR: | ||
337 | res = xen_get_ivr(); | ||
338 | break; | ||
339 | case _IA64_REG_CR_TPR: | ||
340 | res = xen_get_tpr(); | ||
341 | break; | ||
342 | default: | ||
343 | res = ia64_native_getreg_func(regnum); | ||
344 | break; | ||
345 | } | ||
346 | return res; | ||
347 | } | ||
348 | |||
349 | /* turning on interrupts is a bit more complicated.. write to the | ||
350 | * memory-mapped virtual psr.i bit first (to avoid race condition), | ||
351 | * then if any interrupts were pending, we have to execute a hyperprivop | ||
352 | * to ensure the pending interrupt gets delivered; else we're done! */ | ||
353 | static void | ||
354 | xen_ssm_i(void) | ||
355 | { | ||
356 | int old = xen_get_virtual_psr_i(); | ||
357 | xen_set_virtual_psr_i(1); | ||
358 | barrier(); | ||
359 | if (!old && xen_get_virtual_pend()) | ||
360 | xen_hyper_ssm_i(); | ||
361 | } | ||
362 | |||
363 | /* turning off interrupts can be paravirtualized simply by writing | ||
364 | * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */ | ||
365 | static void | ||
366 | xen_rsm_i(void) | ||
367 | { | ||
368 | xen_set_virtual_psr_i(0); | ||
369 | barrier(); | ||
370 | } | ||
371 | |||
372 | static unsigned long | ||
373 | xen_get_psr_i(void) | ||
374 | { | ||
375 | return xen_get_virtual_psr_i() ? IA64_PSR_I : 0; | ||
376 | } | ||
377 | |||
378 | static void | ||
379 | xen_intrin_local_irq_restore(unsigned long mask) | ||
380 | { | ||
381 | if (mask & IA64_PSR_I) | ||
382 | xen_ssm_i(); | ||
383 | else | ||
384 | xen_rsm_i(); | ||
385 | } | ||
386 | #else | ||
387 | #define __DEFINE_FUNC(name, code) \ | ||
388 | extern const char xen_ ## name ## _direct_start[]; \ | ||
389 | extern const char xen_ ## name ## _direct_end[]; \ | ||
390 | asm (".align 32\n" \ | ||
391 | ".proc xen_" #name "\n" \ | ||
392 | "xen_" #name ":\n" \ | ||
393 | "xen_" #name "_direct_start:\n" \ | ||
394 | code \ | ||
395 | "xen_" #name "_direct_end:\n" \ | ||
396 | "br.cond.sptk.many b6\n" \ | ||
397 | ".endp xen_" #name "\n") | ||
398 | |||
399 | #define DEFINE_VOID_FUNC0(name, code) \ | ||
400 | extern void \ | ||
401 | xen_ ## name (void); \ | ||
402 | __DEFINE_FUNC(name, code) | ||
403 | |||
404 | #define DEFINE_VOID_FUNC1(name, code) \ | ||
405 | extern void \ | ||
406 | xen_ ## name (unsigned long arg); \ | ||
407 | __DEFINE_FUNC(name, code) | ||
408 | |||
409 | #define DEFINE_VOID_FUNC1_VOID(name, code) \ | ||
410 | extern void \ | ||
411 | xen_ ## name (void *arg); \ | ||
412 | __DEFINE_FUNC(name, code) | ||
413 | |||
414 | #define DEFINE_VOID_FUNC2(name, code) \ | ||
415 | extern void \ | ||
416 | xen_ ## name (unsigned long arg0, \ | ||
417 | unsigned long arg1); \ | ||
418 | __DEFINE_FUNC(name, code) | ||
419 | |||
420 | #define DEFINE_FUNC0(name, code) \ | ||
421 | extern unsigned long \ | ||
422 | xen_ ## name (void); \ | ||
423 | __DEFINE_FUNC(name, code) | ||
424 | |||
425 | #define DEFINE_FUNC1(name, type, code) \ | ||
426 | extern unsigned long \ | ||
427 | xen_ ## name (type arg); \ | ||
428 | __DEFINE_FUNC(name, code) | ||
429 | |||
430 | #define XEN_PSR_I_ADDR_ADDR (XSI_BASE + XSI_PSR_I_ADDR_OFS) | ||
431 | |||
432 | /* | ||
433 | * static void xen_set_itm_with_offset(unsigned long val) | ||
434 | * xen_set_itm(val - XEN_MAPPEDREGS->itc_offset); | ||
435 | */ | ||
436 | /* 2 bundles */ | ||
437 | DEFINE_VOID_FUNC1(set_itm_with_offset, | ||
438 | "mov r2 = " __stringify(XSI_BASE) " + " | ||
439 | __stringify(XSI_ITC_OFFSET_OFS) "\n" | ||
440 | ";;\n" | ||
441 | "ld8 r3 = [r2]\n" | ||
442 | ";;\n" | ||
443 | "sub r8 = r8, r3\n" | ||
444 | "break " __stringify(HYPERPRIVOP_SET_ITM) "\n"); | ||
445 | |||
446 | /* | ||
447 | * static unsigned long xen_get_itm_with_offset(void) | ||
448 | * return ia64_native_getreg(_IA64_REG_CR_ITM) + XEN_MAPPEDREGS->itc_offset; | ||
449 | */ | ||
450 | /* 2 bundles */ | ||
451 | DEFINE_FUNC0(get_itm_with_offset, | ||
452 | "mov r2 = " __stringify(XSI_BASE) " + " | ||
453 | __stringify(XSI_ITC_OFFSET_OFS) "\n" | ||
454 | ";;\n" | ||
455 | "ld8 r3 = [r2]\n" | ||
456 | "mov r8 = cr.itm\n" | ||
457 | ";;\n" | ||
458 | "add r8 = r8, r2\n"); | ||
459 | |||
460 | /* | ||
461 | * static void xen_set_itc(unsigned long val) | ||
462 | * unsigned long mitc; | ||
463 | * | ||
464 | * WARN_ON(!irqs_disabled()); | ||
465 | * mitc = ia64_native_getreg(_IA64_REG_AR_ITC); | ||
466 | * XEN_MAPPEDREGS->itc_offset = val - mitc; | ||
467 | * XEN_MAPPEDREGS->itc_last = val; | ||
468 | */ | ||
469 | /* 2 bundles */ | ||
470 | DEFINE_VOID_FUNC1(set_itc, | ||
471 | "mov r2 = " __stringify(XSI_BASE) " + " | ||
472 | __stringify(XSI_ITC_LAST_OFS) "\n" | ||
473 | "mov r3 = ar.itc\n" | ||
474 | ";;\n" | ||
475 | "sub r3 = r8, r3\n" | ||
476 | "st8 [r2] = r8, " | ||
477 | __stringify(XSI_ITC_LAST_OFS) " - " | ||
478 | __stringify(XSI_ITC_OFFSET_OFS) "\n" | ||
479 | ";;\n" | ||
480 | "st8 [r2] = r3\n"); | ||
481 | |||
482 | /* | ||
483 | * static unsigned long xen_get_itc(void) | ||
484 | * unsigned long res; | ||
485 | * unsigned long itc_offset; | ||
486 | * unsigned long itc_last; | ||
487 | * unsigned long ret_itc_last; | ||
488 | * | ||
489 | * itc_offset = XEN_MAPPEDREGS->itc_offset; | ||
490 | * do { | ||
491 | * itc_last = XEN_MAPPEDREGS->itc_last; | ||
492 | * res = ia64_native_getreg(_IA64_REG_AR_ITC); | ||
493 | * res += itc_offset; | ||
494 | * if (itc_last >= res) | ||
495 | * res = itc_last + 1; | ||
496 | * ret_itc_last = cmpxchg(&XEN_MAPPEDREGS->itc_last, | ||
497 | * itc_last, res); | ||
498 | * } while (unlikely(ret_itc_last != itc_last)); | ||
499 | * return res; | ||
500 | */ | ||
501 | /* 5 bundles */ | ||
502 | DEFINE_FUNC0(get_itc, | ||
503 | "mov r2 = " __stringify(XSI_BASE) " + " | ||
504 | __stringify(XSI_ITC_OFFSET_OFS) "\n" | ||
505 | ";;\n" | ||
506 | "ld8 r9 = [r2], " __stringify(XSI_ITC_LAST_OFS) " - " | ||
507 | __stringify(XSI_ITC_OFFSET_OFS) "\n" | ||
508 | /* r9 = itc_offset */ | ||
509 | /* r2 = XSI_ITC_OFFSET */ | ||
510 | "888:\n" | ||
511 | "mov r8 = ar.itc\n" /* res = ar.itc */ | ||
512 | ";;\n" | ||
513 | "ld8 r3 = [r2]\n" /* r3 = itc_last */ | ||
514 | "add r8 = r8, r9\n" /* res = ar.itc + itc_offset */ | ||
515 | ";;\n" | ||
516 | "cmp.gtu p6, p0 = r3, r8\n" | ||
517 | ";;\n" | ||
518 | "(p6) add r8 = 1, r3\n" /* if (itc_last > res) itc_last + 1 */ | ||
519 | ";;\n" | ||
520 | "mov ar.ccv = r8\n" | ||
521 | ";;\n" | ||
522 | "cmpxchg8.acq r10 = [r2], r8, ar.ccv\n" | ||
523 | ";;\n" | ||
524 | "cmp.ne p6, p0 = r10, r3\n" | ||
525 | "(p6) hint @pause\n" | ||
526 | "(p6) br.cond.spnt 888b\n"); | ||
527 | |||
528 | DEFINE_VOID_FUNC1_VOID(fc, | ||
529 | "break " __stringify(HYPERPRIVOP_FC) "\n"); | ||
530 | |||
531 | /* | ||
532 | * psr_i_addr_addr = XEN_PSR_I_ADDR_ADDR | ||
533 | * masked_addr = *psr_i_addr_addr | ||
534 | * pending_intr_addr = masked_addr - 1 | ||
535 | * if (val & IA64_PSR_I) { | ||
536 | * masked = *masked_addr | ||
537 | * *masked_addr = 0:xen_set_virtual_psr_i(1) | ||
538 | * compiler barrier | ||
539 | * if (masked) { | ||
540 | * uint8_t pending = *pending_intr_addr; | ||
541 | * if (pending) | ||
542 | * XEN_HYPER_SSM_I | ||
543 | * } | ||
544 | * } else { | ||
545 | * *masked_addr = 1:xen_set_virtual_psr_i(0) | ||
546 | * } | ||
547 | */ | ||
548 | /* 6 bundles */ | ||
549 | DEFINE_VOID_FUNC1(intrin_local_irq_restore, | ||
550 | /* r8 = input value: 0 or IA64_PSR_I | ||
551 | * p6 = (flags & IA64_PSR_I) | ||
552 | * = if clause | ||
553 | * p7 = !(flags & IA64_PSR_I) | ||
554 | * = else clause | ||
555 | */ | ||
556 | "cmp.ne p6, p7 = r8, r0\n" | ||
557 | "mov r9 = " __stringify(XEN_PSR_I_ADDR_ADDR) "\n" | ||
558 | ";;\n" | ||
559 | /* r9 = XEN_PSR_I_ADDR */ | ||
560 | "ld8 r9 = [r9]\n" | ||
561 | ";;\n" | ||
562 | |||
563 | /* r10 = masked previous value */ | ||
564 | "(p6) ld1.acq r10 = [r9]\n" | ||
565 | ";;\n" | ||
566 | |||
567 | /* p8 = !masked interrupt masked previously? */ | ||
568 | "(p6) cmp.ne.unc p8, p0 = r10, r0\n" | ||
569 | |||
570 | /* p7 = else clause */ | ||
571 | "(p7) mov r11 = 1\n" | ||
572 | ";;\n" | ||
573 | /* masked = 1 */ | ||
574 | "(p7) st1.rel [r9] = r11\n" | ||
575 | |||
576 | /* p6 = if clause */ | ||
577 | /* masked = 0 | ||
578 | * r9 = masked_addr - 1 | ||
579 | * = pending_intr_addr | ||
580 | */ | ||
581 | "(p8) st1.rel [r9] = r0, -1\n" | ||
582 | ";;\n" | ||
583 | /* r8 = pending_intr */ | ||
584 | "(p8) ld1.acq r11 = [r9]\n" | ||
585 | ";;\n" | ||
586 | /* p9 = interrupt pending? */ | ||
587 | "(p8) cmp.ne.unc p9, p10 = r11, r0\n" | ||
588 | ";;\n" | ||
589 | "(p10) mf\n" | ||
590 | /* issue hypercall to trigger interrupt */ | ||
591 | "(p9) break " __stringify(HYPERPRIVOP_SSM_I) "\n"); | ||
592 | |||
593 | DEFINE_VOID_FUNC2(ptcga, | ||
594 | "break " __stringify(HYPERPRIVOP_PTC_GA) "\n"); | ||
595 | DEFINE_VOID_FUNC2(set_rr, | ||
596 | "break " __stringify(HYPERPRIVOP_SET_RR) "\n"); | ||
597 | |||
598 | /* | ||
599 | * tmp = XEN_MAPPEDREGS->interrupt_mask_addr = XEN_PSR_I_ADDR_ADDR; | ||
600 | * tmp = *tmp | ||
601 | * tmp = *tmp; | ||
602 | * psr_i = tmp? 0: IA64_PSR_I; | ||
603 | */ | ||
604 | /* 4 bundles */ | ||
605 | DEFINE_FUNC0(get_psr_i, | ||
606 | "mov r9 = " __stringify(XEN_PSR_I_ADDR_ADDR) "\n" | ||
607 | ";;\n" | ||
608 | "ld8 r9 = [r9]\n" /* r9 = XEN_PSR_I_ADDR */ | ||
609 | "mov r8 = 0\n" /* psr_i = 0 */ | ||
610 | ";;\n" | ||
611 | "ld1.acq r9 = [r9]\n" /* r9 = XEN_PSR_I */ | ||
612 | ";;\n" | ||
613 | "cmp.eq.unc p6, p0 = r9, r0\n" /* p6 = (XEN_PSR_I != 0) */ | ||
614 | ";;\n" | ||
615 | "(p6) mov r8 = " __stringify(1 << IA64_PSR_I_BIT) "\n"); | ||
616 | |||
617 | DEFINE_FUNC1(thash, unsigned long, | ||
618 | "break " __stringify(HYPERPRIVOP_THASH) "\n"); | ||
619 | DEFINE_FUNC1(get_cpuid, int, | ||
620 | "break " __stringify(HYPERPRIVOP_GET_CPUID) "\n"); | ||
621 | DEFINE_FUNC1(get_pmd, int, | ||
622 | "break " __stringify(HYPERPRIVOP_GET_PMD) "\n"); | ||
623 | DEFINE_FUNC1(get_rr, unsigned long, | ||
624 | "break " __stringify(HYPERPRIVOP_GET_RR) "\n"); | ||
625 | |||
626 | /* | ||
627 | * void xen_privop_ssm_i(void) | ||
628 | * | ||
629 | * int masked = !xen_get_virtual_psr_i(); | ||
630 | * // masked = *(*XEN_MAPPEDREGS->interrupt_mask_addr) | ||
631 | * xen_set_virtual_psr_i(1) | ||
632 | * // *(*XEN_MAPPEDREGS->interrupt_mask_addr) = 0 | ||
633 | * // compiler barrier | ||
634 | * if (masked) { | ||
635 | * uint8_t* pend_int_addr = | ||
636 | * (uint8_t*)(*XEN_MAPPEDREGS->interrupt_mask_addr) - 1; | ||
637 | * uint8_t pending = *pend_int_addr; | ||
638 | * if (pending) | ||
639 | * XEN_HYPER_SSM_I | ||
640 | * } | ||
641 | */ | ||
642 | /* 4 bundles */ | ||
643 | DEFINE_VOID_FUNC0(ssm_i, | ||
644 | "mov r8 = " __stringify(XEN_PSR_I_ADDR_ADDR) "\n" | ||
645 | ";;\n" | ||
646 | "ld8 r8 = [r8]\n" /* r8 = XEN_PSR_I_ADDR */ | ||
647 | ";;\n" | ||
648 | "ld1.acq r9 = [r8]\n" /* r9 = XEN_PSR_I */ | ||
649 | ";;\n" | ||
650 | "st1.rel [r8] = r0, -1\n" /* psr_i = 0. enable interrupt | ||
651 | * r8 = XEN_PSR_I_ADDR - 1 | ||
652 | * = pend_int_addr | ||
653 | */ | ||
654 | "cmp.eq.unc p0, p6 = r9, r0\n"/* p6 = !XEN_PSR_I | ||
655 | * previously interrupt | ||
656 | * masked? | ||
657 | */ | ||
658 | ";;\n" | ||
659 | "(p6) ld1.acq r8 = [r8]\n" /* r8 = xen_pend_int */ | ||
660 | ";;\n" | ||
661 | "(p6) cmp.eq.unc p6, p7 = r8, r0\n" /*interrupt pending?*/ | ||
662 | ";;\n" | ||
663 | /* issue hypercall to get interrupt */ | ||
664 | "(p7) break " __stringify(HYPERPRIVOP_SSM_I) "\n" | ||
665 | ";;\n"); | ||
666 | |||
667 | /* | ||
668 | * psr_i_addr_addr = XEN_MAPPEDREGS->interrupt_mask_addr | ||
669 | * = XEN_PSR_I_ADDR_ADDR; | ||
670 | * psr_i_addr = *psr_i_addr_addr; | ||
671 | * *psr_i_addr = 1; | ||
672 | */ | ||
673 | /* 2 bundles */ | ||
674 | DEFINE_VOID_FUNC0(rsm_i, | ||
675 | "mov r8 = " __stringify(XEN_PSR_I_ADDR_ADDR) "\n" | ||
676 | /* r8 = XEN_PSR_I_ADDR */ | ||
677 | "mov r9 = 1\n" | ||
678 | ";;\n" | ||
679 | "ld8 r8 = [r8]\n" /* r8 = XEN_PSR_I */ | ||
680 | ";;\n" | ||
681 | "st1.rel [r8] = r9\n"); /* XEN_PSR_I = 1 */ | ||
682 | |||
683 | extern void | ||
684 | xen_set_rr0_to_rr4(unsigned long val0, unsigned long val1, | ||
685 | unsigned long val2, unsigned long val3, | ||
686 | unsigned long val4); | ||
687 | __DEFINE_FUNC(set_rr0_to_rr4, | ||
688 | "break " __stringify(HYPERPRIVOP_SET_RR0_TO_RR4) "\n"); | ||
689 | |||
690 | |||
691 | extern unsigned long xen_getreg(int regnum); | ||
692 | #define __DEFINE_GET_REG(id, privop) \ | ||
693 | "mov r2 = " __stringify(_IA64_REG_ ## id) "\n" \ | ||
694 | ";;\n" \ | ||
695 | "cmp.eq p6, p0 = r2, r8\n" \ | ||
696 | ";;\n" \ | ||
697 | "(p6) break " __stringify(HYPERPRIVOP_GET_ ## privop) "\n" \ | ||
698 | "(p6) br.cond.sptk.many b6\n" \ | ||
699 | ";;\n" | ||
700 | |||
701 | __DEFINE_FUNC(getreg, | ||
702 | __DEFINE_GET_REG(PSR, PSR) | ||
703 | |||
704 | /* get_itc */ | ||
705 | "mov r2 = " __stringify(_IA64_REG_AR_ITC) "\n" | ||
706 | ";;\n" | ||
707 | "cmp.eq p6, p0 = r2, r8\n" | ||
708 | ";;\n" | ||
709 | "(p6) br.cond.spnt xen_get_itc\n" | ||
710 | ";;\n" | ||
711 | |||
712 | /* get itm */ | ||
713 | "mov r2 = " __stringify(_IA64_REG_CR_ITM) "\n" | ||
714 | ";;\n" | ||
715 | "cmp.eq p6, p0 = r2, r8\n" | ||
716 | ";;\n" | ||
717 | "(p6) br.cond.spnt xen_get_itm_with_offset\n" | ||
718 | ";;\n" | ||
719 | |||
720 | __DEFINE_GET_REG(CR_IVR, IVR) | ||
721 | __DEFINE_GET_REG(CR_TPR, TPR) | ||
722 | |||
723 | /* fall back */ | ||
724 | "movl r2 = ia64_native_getreg_func\n" | ||
725 | ";;\n" | ||
726 | "mov b7 = r2\n" | ||
727 | ";;\n" | ||
728 | "br.cond.sptk.many b7\n"); | ||
729 | |||
730 | extern void xen_setreg(int regnum, unsigned long val); | ||
731 | #define __DEFINE_SET_REG(id, privop) \ | ||
732 | "mov r2 = " __stringify(_IA64_REG_ ## id) "\n" \ | ||
733 | ";;\n" \ | ||
734 | "cmp.eq p6, p0 = r2, r9\n" \ | ||
735 | ";;\n" \ | ||
736 | "(p6) break " __stringify(HYPERPRIVOP_ ## privop) "\n" \ | ||
737 | "(p6) br.cond.sptk.many b6\n" \ | ||
738 | ";;\n" | ||
739 | |||
740 | __DEFINE_FUNC(setreg, | ||
741 | /* kr0 .. kr 7*/ | ||
742 | /* | ||
743 | * if (_IA64_REG_AR_KR0 <= regnum && | ||
744 | * regnum <= _IA64_REG_AR_KR7) { | ||
745 | * register __index asm ("r8") = regnum - _IA64_REG_AR_KR0 | ||
746 | * register __val asm ("r9") = val | ||
747 | * "break HYPERPRIVOP_SET_KR" | ||
748 | * } | ||
749 | */ | ||
750 | "mov r17 = r9\n" | ||
751 | "mov r2 = " __stringify(_IA64_REG_AR_KR0) "\n" | ||
752 | ";;\n" | ||
753 | "cmp.ge p6, p0 = r9, r2\n" | ||
754 | "sub r17 = r17, r2\n" | ||
755 | ";;\n" | ||
756 | "(p6) cmp.ge.unc p7, p0 = " | ||
757 | __stringify(_IA64_REG_AR_KR7) " - " __stringify(_IA64_REG_AR_KR0) | ||
758 | ", r17\n" | ||
759 | ";;\n" | ||
760 | "(p7) mov r9 = r8\n" | ||
761 | ";;\n" | ||
762 | "(p7) mov r8 = r17\n" | ||
763 | "(p7) break " __stringify(HYPERPRIVOP_SET_KR) "\n" | ||
764 | |||
765 | /* set itm */ | ||
766 | "mov r2 = " __stringify(_IA64_REG_CR_ITM) "\n" | ||
767 | ";;\n" | ||
768 | "cmp.eq p6, p0 = r2, r8\n" | ||
769 | ";;\n" | ||
770 | "(p6) br.cond.spnt xen_set_itm_with_offset\n" | ||
771 | |||
772 | /* set itc */ | ||
773 | "mov r2 = " __stringify(_IA64_REG_AR_ITC) "\n" | ||
774 | ";;\n" | ||
775 | "cmp.eq p6, p0 = r2, r8\n" | ||
776 | ";;\n" | ||
777 | "(p6) br.cond.spnt xen_set_itc\n" | ||
778 | |||
779 | __DEFINE_SET_REG(CR_TPR, SET_TPR) | ||
780 | __DEFINE_SET_REG(CR_EOI, EOI) | ||
781 | |||
782 | /* fall back */ | ||
783 | "movl r2 = ia64_native_setreg_func\n" | ||
784 | ";;\n" | ||
785 | "mov b7 = r2\n" | ||
786 | ";;\n" | ||
787 | "br.cond.sptk.many b7\n"); | ||
788 | #endif | ||
789 | |||
790 | static const struct pv_cpu_ops xen_cpu_ops __initconst = { | ||
791 | .fc = xen_fc, | ||
792 | .thash = xen_thash, | ||
793 | .get_cpuid = xen_get_cpuid, | ||
794 | .get_pmd = xen_get_pmd, | ||
795 | .getreg = xen_getreg, | ||
796 | .setreg = xen_setreg, | ||
797 | .ptcga = xen_ptcga, | ||
798 | .get_rr = xen_get_rr, | ||
799 | .set_rr = xen_set_rr, | ||
800 | .set_rr0_to_rr4 = xen_set_rr0_to_rr4, | ||
801 | .ssm_i = xen_ssm_i, | ||
802 | .rsm_i = xen_rsm_i, | ||
803 | .get_psr_i = xen_get_psr_i, | ||
804 | .intrin_local_irq_restore | ||
805 | = xen_intrin_local_irq_restore, | ||
806 | }; | ||
807 | |||
808 | /****************************************************************************** | ||
809 | * replacement of hand written assembly codes. | ||
810 | */ | ||
811 | |||
812 | extern char xen_switch_to; | ||
813 | extern char xen_leave_syscall; | ||
814 | extern char xen_work_processed_syscall; | ||
815 | extern char xen_leave_kernel; | ||
816 | |||
817 | const struct pv_cpu_asm_switch xen_cpu_asm_switch = { | ||
818 | .switch_to = (unsigned long)&xen_switch_to, | ||
819 | .leave_syscall = (unsigned long)&xen_leave_syscall, | ||
820 | .work_processed_syscall = (unsigned long)&xen_work_processed_syscall, | ||
821 | .leave_kernel = (unsigned long)&xen_leave_kernel, | ||
822 | }; | ||
823 | |||
824 | /*************************************************************************** | ||
825 | * pv_iosapic_ops | ||
826 | * iosapic read/write hooks. | ||
827 | */ | ||
828 | static void | ||
829 | xen_pcat_compat_init(void) | ||
830 | { | ||
831 | /* nothing */ | ||
832 | } | ||
833 | |||
834 | static struct irq_chip* | ||
835 | xen_iosapic_get_irq_chip(unsigned long trigger) | ||
836 | { | ||
837 | return NULL; | ||
838 | } | ||
839 | |||
840 | static unsigned int | ||
841 | xen_iosapic_read(char __iomem *iosapic, unsigned int reg) | ||
842 | { | ||
843 | struct physdev_apic apic_op; | ||
844 | int ret; | ||
845 | |||
846 | apic_op.apic_physbase = (unsigned long)iosapic - | ||
847 | __IA64_UNCACHED_OFFSET; | ||
848 | apic_op.reg = reg; | ||
849 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op); | ||
850 | if (ret) | ||
851 | return ret; | ||
852 | return apic_op.value; | ||
853 | } | ||
854 | |||
855 | static void | ||
856 | xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) | ||
857 | { | ||
858 | struct physdev_apic apic_op; | ||
859 | |||
860 | apic_op.apic_physbase = (unsigned long)iosapic - | ||
861 | __IA64_UNCACHED_OFFSET; | ||
862 | apic_op.reg = reg; | ||
863 | apic_op.value = val; | ||
864 | HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op); | ||
865 | } | ||
866 | |||
867 | static struct pv_iosapic_ops xen_iosapic_ops __initdata = { | ||
868 | .pcat_compat_init = xen_pcat_compat_init, | ||
869 | .__get_irq_chip = xen_iosapic_get_irq_chip, | ||
870 | |||
871 | .__read = xen_iosapic_read, | ||
872 | .__write = xen_iosapic_write, | ||
873 | }; | ||
874 | |||
875 | /*************************************************************************** | ||
876 | * pv_ops initialization | ||
877 | */ | ||
878 | |||
879 | void __init | ||
880 | xen_setup_pv_ops(void) | ||
881 | { | ||
882 | xen_info_init(); | ||
883 | pv_info = xen_info; | ||
884 | pv_init_ops = xen_init_ops; | ||
885 | pv_fsys_data = xen_fsys_data; | ||
886 | pv_patchdata = xen_patchdata; | ||
887 | pv_cpu_ops = xen_cpu_ops; | ||
888 | pv_iosapic_ops = xen_iosapic_ops; | ||
889 | pv_irq_ops = xen_irq_ops; | ||
890 | pv_time_ops = xen_time_ops; | ||
891 | |||
892 | paravirt_cpu_asm_init(&xen_cpu_asm_switch); | ||
893 | } | ||
894 | |||
895 | #ifdef ASM_SUPPORTED | ||
896 | /*************************************************************************** | ||
897 | * binary pacthing | ||
898 | * pv_init_ops.patch_bundle | ||
899 | */ | ||
900 | |||
901 | #define DEFINE_FUNC_GETREG(name, privop) \ | ||
902 | DEFINE_FUNC0(get_ ## name, \ | ||
903 | "break "__stringify(HYPERPRIVOP_GET_ ## privop) "\n") | ||
904 | |||
905 | DEFINE_FUNC_GETREG(psr, PSR); | ||
906 | DEFINE_FUNC_GETREG(eflag, EFLAG); | ||
907 | DEFINE_FUNC_GETREG(ivr, IVR); | ||
908 | DEFINE_FUNC_GETREG(tpr, TPR); | ||
909 | |||
910 | #define DEFINE_FUNC_SET_KR(n) \ | ||
911 | DEFINE_VOID_FUNC0(set_kr ## n, \ | ||
912 | ";;\n" \ | ||
913 | "mov r9 = r8\n" \ | ||
914 | "mov r8 = " #n "\n" \ | ||
915 | "break " __stringify(HYPERPRIVOP_SET_KR) "\n") | ||
916 | |||
917 | DEFINE_FUNC_SET_KR(0); | ||
918 | DEFINE_FUNC_SET_KR(1); | ||
919 | DEFINE_FUNC_SET_KR(2); | ||
920 | DEFINE_FUNC_SET_KR(3); | ||
921 | DEFINE_FUNC_SET_KR(4); | ||
922 | DEFINE_FUNC_SET_KR(5); | ||
923 | DEFINE_FUNC_SET_KR(6); | ||
924 | DEFINE_FUNC_SET_KR(7); | ||
925 | |||
926 | #define __DEFINE_FUNC_SETREG(name, privop) \ | ||
927 | DEFINE_VOID_FUNC0(name, \ | ||
928 | "break "__stringify(HYPERPRIVOP_ ## privop) "\n") | ||
929 | |||
930 | #define DEFINE_FUNC_SETREG(name, privop) \ | ||
931 | __DEFINE_FUNC_SETREG(set_ ## name, SET_ ## privop) | ||
932 | |||
933 | DEFINE_FUNC_SETREG(eflag, EFLAG); | ||
934 | DEFINE_FUNC_SETREG(tpr, TPR); | ||
935 | __DEFINE_FUNC_SETREG(eoi, EOI); | ||
936 | |||
937 | extern const char xen_check_events[]; | ||
938 | extern const char __xen_intrin_local_irq_restore_direct_start[]; | ||
939 | extern const char __xen_intrin_local_irq_restore_direct_end[]; | ||
940 | extern const unsigned long __xen_intrin_local_irq_restore_direct_reloc; | ||
941 | |||
942 | asm ( | ||
943 | ".align 32\n" | ||
944 | ".proc xen_check_events\n" | ||
945 | "xen_check_events:\n" | ||
946 | /* masked = 0 | ||
947 | * r9 = masked_addr - 1 | ||
948 | * = pending_intr_addr | ||
949 | */ | ||
950 | "st1.rel [r9] = r0, -1\n" | ||
951 | ";;\n" | ||
952 | /* r8 = pending_intr */ | ||
953 | "ld1.acq r11 = [r9]\n" | ||
954 | ";;\n" | ||
955 | /* p9 = interrupt pending? */ | ||
956 | "cmp.ne p9, p10 = r11, r0\n" | ||
957 | ";;\n" | ||
958 | "(p10) mf\n" | ||
959 | /* issue hypercall to trigger interrupt */ | ||
960 | "(p9) break " __stringify(HYPERPRIVOP_SSM_I) "\n" | ||
961 | "br.cond.sptk.many b6\n" | ||
962 | ".endp xen_check_events\n" | ||
963 | "\n" | ||
964 | ".align 32\n" | ||
965 | ".proc __xen_intrin_local_irq_restore_direct\n" | ||
966 | "__xen_intrin_local_irq_restore_direct:\n" | ||
967 | "__xen_intrin_local_irq_restore_direct_start:\n" | ||
968 | "1:\n" | ||
969 | "{\n" | ||
970 | "cmp.ne p6, p7 = r8, r0\n" | ||
971 | "mov r17 = ip\n" /* get ip to calc return address */ | ||
972 | "mov r9 = "__stringify(XEN_PSR_I_ADDR_ADDR) "\n" | ||
973 | ";;\n" | ||
974 | "}\n" | ||
975 | "{\n" | ||
976 | /* r9 = XEN_PSR_I_ADDR */ | ||
977 | "ld8 r9 = [r9]\n" | ||
978 | ";;\n" | ||
979 | /* r10 = masked previous value */ | ||
980 | "(p6) ld1.acq r10 = [r9]\n" | ||
981 | "adds r17 = 1f - 1b, r17\n" /* calculate return address */ | ||
982 | ";;\n" | ||
983 | "}\n" | ||
984 | "{\n" | ||
985 | /* p8 = !masked interrupt masked previously? */ | ||
986 | "(p6) cmp.ne.unc p8, p0 = r10, r0\n" | ||
987 | "\n" | ||
988 | /* p7 = else clause */ | ||
989 | "(p7) mov r11 = 1\n" | ||
990 | ";;\n" | ||
991 | "(p8) mov b6 = r17\n" /* set return address */ | ||
992 | "}\n" | ||
993 | "{\n" | ||
994 | /* masked = 1 */ | ||
995 | "(p7) st1.rel [r9] = r11\n" | ||
996 | "\n" | ||
997 | "[99:]\n" | ||
998 | "(p8) brl.cond.dptk.few xen_check_events\n" | ||
999 | "}\n" | ||
1000 | /* pv calling stub is 5 bundles. fill nop to adjust return address */ | ||
1001 | "{\n" | ||
1002 | "nop 0\n" | ||
1003 | "nop 0\n" | ||
1004 | "nop 0\n" | ||
1005 | "}\n" | ||
1006 | "1:\n" | ||
1007 | "__xen_intrin_local_irq_restore_direct_end:\n" | ||
1008 | ".endp __xen_intrin_local_irq_restore_direct\n" | ||
1009 | "\n" | ||
1010 | ".align 8\n" | ||
1011 | "__xen_intrin_local_irq_restore_direct_reloc:\n" | ||
1012 | "data8 99b\n" | ||
1013 | ); | ||
1014 | |||
1015 | static struct paravirt_patch_bundle_elem xen_patch_bundle_elems[] | ||
1016 | __initdata_or_module = | ||
1017 | { | ||
1018 | #define XEN_PATCH_BUNDLE_ELEM(name, type) \ | ||
1019 | { \ | ||
1020 | (void*)xen_ ## name ## _direct_start, \ | ||
1021 | (void*)xen_ ## name ## _direct_end, \ | ||
1022 | PARAVIRT_PATCH_TYPE_ ## type, \ | ||
1023 | } | ||
1024 | |||
1025 | XEN_PATCH_BUNDLE_ELEM(fc, FC), | ||
1026 | XEN_PATCH_BUNDLE_ELEM(thash, THASH), | ||
1027 | XEN_PATCH_BUNDLE_ELEM(get_cpuid, GET_CPUID), | ||
1028 | XEN_PATCH_BUNDLE_ELEM(get_pmd, GET_PMD), | ||
1029 | XEN_PATCH_BUNDLE_ELEM(ptcga, PTCGA), | ||
1030 | XEN_PATCH_BUNDLE_ELEM(get_rr, GET_RR), | ||
1031 | XEN_PATCH_BUNDLE_ELEM(set_rr, SET_RR), | ||
1032 | XEN_PATCH_BUNDLE_ELEM(set_rr0_to_rr4, SET_RR0_TO_RR4), | ||
1033 | XEN_PATCH_BUNDLE_ELEM(ssm_i, SSM_I), | ||
1034 | XEN_PATCH_BUNDLE_ELEM(rsm_i, RSM_I), | ||
1035 | XEN_PATCH_BUNDLE_ELEM(get_psr_i, GET_PSR_I), | ||
1036 | { | ||
1037 | (void*)__xen_intrin_local_irq_restore_direct_start, | ||
1038 | (void*)__xen_intrin_local_irq_restore_direct_end, | ||
1039 | PARAVIRT_PATCH_TYPE_INTRIN_LOCAL_IRQ_RESTORE, | ||
1040 | }, | ||
1041 | |||
1042 | #define XEN_PATCH_BUNDLE_ELEM_GETREG(name, reg) \ | ||
1043 | { \ | ||
1044 | xen_get_ ## name ## _direct_start, \ | ||
1045 | xen_get_ ## name ## _direct_end, \ | ||
1046 | PARAVIRT_PATCH_TYPE_GETREG + _IA64_REG_ ## reg, \ | ||
1047 | } | ||
1048 | |||
1049 | XEN_PATCH_BUNDLE_ELEM_GETREG(psr, PSR), | ||
1050 | XEN_PATCH_BUNDLE_ELEM_GETREG(eflag, AR_EFLAG), | ||
1051 | |||
1052 | XEN_PATCH_BUNDLE_ELEM_GETREG(ivr, CR_IVR), | ||
1053 | XEN_PATCH_BUNDLE_ELEM_GETREG(tpr, CR_TPR), | ||
1054 | |||
1055 | XEN_PATCH_BUNDLE_ELEM_GETREG(itc, AR_ITC), | ||
1056 | XEN_PATCH_BUNDLE_ELEM_GETREG(itm_with_offset, CR_ITM), | ||
1057 | |||
1058 | |||
1059 | #define __XEN_PATCH_BUNDLE_ELEM_SETREG(name, reg) \ | ||
1060 | { \ | ||
1061 | xen_ ## name ## _direct_start, \ | ||
1062 | xen_ ## name ## _direct_end, \ | ||
1063 | PARAVIRT_PATCH_TYPE_SETREG + _IA64_REG_ ## reg, \ | ||
1064 | } | ||
1065 | |||
1066 | #define XEN_PATCH_BUNDLE_ELEM_SETREG(name, reg) \ | ||
1067 | __XEN_PATCH_BUNDLE_ELEM_SETREG(set_ ## name, reg) | ||
1068 | |||
1069 | XEN_PATCH_BUNDLE_ELEM_SETREG(kr0, AR_KR0), | ||
1070 | XEN_PATCH_BUNDLE_ELEM_SETREG(kr1, AR_KR1), | ||
1071 | XEN_PATCH_BUNDLE_ELEM_SETREG(kr2, AR_KR2), | ||
1072 | XEN_PATCH_BUNDLE_ELEM_SETREG(kr3, AR_KR3), | ||
1073 | XEN_PATCH_BUNDLE_ELEM_SETREG(kr4, AR_KR4), | ||
1074 | XEN_PATCH_BUNDLE_ELEM_SETREG(kr5, AR_KR5), | ||
1075 | XEN_PATCH_BUNDLE_ELEM_SETREG(kr6, AR_KR6), | ||
1076 | XEN_PATCH_BUNDLE_ELEM_SETREG(kr7, AR_KR7), | ||
1077 | |||
1078 | XEN_PATCH_BUNDLE_ELEM_SETREG(eflag, AR_EFLAG), | ||
1079 | XEN_PATCH_BUNDLE_ELEM_SETREG(tpr, CR_TPR), | ||
1080 | __XEN_PATCH_BUNDLE_ELEM_SETREG(eoi, CR_EOI), | ||
1081 | |||
1082 | XEN_PATCH_BUNDLE_ELEM_SETREG(itc, AR_ITC), | ||
1083 | XEN_PATCH_BUNDLE_ELEM_SETREG(itm_with_offset, CR_ITM), | ||
1084 | }; | ||
1085 | |||
1086 | static unsigned long __init_or_module | ||
1087 | xen_patch_bundle(void *sbundle, void *ebundle, unsigned long type) | ||
1088 | { | ||
1089 | const unsigned long nelems = sizeof(xen_patch_bundle_elems) / | ||
1090 | sizeof(xen_patch_bundle_elems[0]); | ||
1091 | unsigned long used; | ||
1092 | const struct paravirt_patch_bundle_elem *found; | ||
1093 | |||
1094 | used = __paravirt_patch_apply_bundle(sbundle, ebundle, type, | ||
1095 | xen_patch_bundle_elems, nelems, | ||
1096 | &found); | ||
1097 | |||
1098 | if (found == NULL) | ||
1099 | /* fallback */ | ||
1100 | return ia64_native_patch_bundle(sbundle, ebundle, type); | ||
1101 | if (used == 0) | ||
1102 | return used; | ||
1103 | |||
1104 | /* relocation */ | ||
1105 | switch (type) { | ||
1106 | case PARAVIRT_PATCH_TYPE_INTRIN_LOCAL_IRQ_RESTORE: { | ||
1107 | unsigned long reloc = | ||
1108 | __xen_intrin_local_irq_restore_direct_reloc; | ||
1109 | unsigned long reloc_offset = reloc - (unsigned long) | ||
1110 | __xen_intrin_local_irq_restore_direct_start; | ||
1111 | unsigned long tag = (unsigned long)sbundle + reloc_offset; | ||
1112 | paravirt_patch_reloc_brl(tag, xen_check_events); | ||
1113 | break; | ||
1114 | } | ||
1115 | default: | ||
1116 | /* nothing */ | ||
1117 | break; | ||
1118 | } | ||
1119 | return used; | ||
1120 | } | ||
1121 | #endif /* ASM_SUPPOTED */ | ||
1122 | |||
1123 | const struct paravirt_patch_branch_target xen_branch_target[] | ||
1124 | __initconst = { | ||
1125 | #define PARAVIRT_BR_TARGET(name, type) \ | ||
1126 | { \ | ||
1127 | &xen_ ## name, \ | ||
1128 | PARAVIRT_PATCH_TYPE_BR_ ## type, \ | ||
1129 | } | ||
1130 | PARAVIRT_BR_TARGET(switch_to, SWITCH_TO), | ||
1131 | PARAVIRT_BR_TARGET(leave_syscall, LEAVE_SYSCALL), | ||
1132 | PARAVIRT_BR_TARGET(work_processed_syscall, WORK_PROCESSED_SYSCALL), | ||
1133 | PARAVIRT_BR_TARGET(leave_kernel, LEAVE_KERNEL), | ||
1134 | }; | ||
1135 | |||
1136 | static void __init | ||
1137 | xen_patch_branch(unsigned long tag, unsigned long type) | ||
1138 | { | ||
1139 | __paravirt_patch_apply_branch(tag, type, xen_branch_target, | ||
1140 | ARRAY_SIZE(xen_branch_target)); | ||
1141 | } | ||
diff --git a/arch/ia64/xen/xencomm.c b/arch/ia64/xen/xencomm.c deleted file mode 100644 index 73d903ca2d64..000000000000 --- a/arch/ia64/xen/xencomm.c +++ /dev/null | |||
@@ -1,106 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include <linux/mm.h> | ||
20 | #include <linux/err.h> | ||
21 | |||
22 | static unsigned long kernel_virtual_offset; | ||
23 | static int is_xencomm_initialized; | ||
24 | |||
25 | /* for xen early printk. It uses console io hypercall which uses xencomm. | ||
26 | * However early printk may use it before xencomm initialization. | ||
27 | */ | ||
28 | int | ||
29 | xencomm_is_initialized(void) | ||
30 | { | ||
31 | return is_xencomm_initialized; | ||
32 | } | ||
33 | |||
34 | void | ||
35 | xencomm_initialize(void) | ||
36 | { | ||
37 | kernel_virtual_offset = KERNEL_START - ia64_tpa(KERNEL_START); | ||
38 | is_xencomm_initialized = 1; | ||
39 | } | ||
40 | |||
41 | /* Translate virtual address to physical address. */ | ||
42 | unsigned long | ||
43 | xencomm_vtop(unsigned long vaddr) | ||
44 | { | ||
45 | struct page *page; | ||
46 | struct vm_area_struct *vma; | ||
47 | |||
48 | if (vaddr == 0) | ||
49 | return 0UL; | ||
50 | |||
51 | if (REGION_NUMBER(vaddr) == 5) { | ||
52 | pgd_t *pgd; | ||
53 | pud_t *pud; | ||
54 | pmd_t *pmd; | ||
55 | pte_t *ptep; | ||
56 | |||
57 | /* On ia64, TASK_SIZE refers to current. It is not initialized | ||
58 | during boot. | ||
59 | Furthermore the kernel is relocatable and __pa() doesn't | ||
60 | work on addresses. */ | ||
61 | if (vaddr >= KERNEL_START | ||
62 | && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) | ||
63 | return vaddr - kernel_virtual_offset; | ||
64 | |||
65 | /* In kernel area -- virtually mapped. */ | ||
66 | pgd = pgd_offset_k(vaddr); | ||
67 | if (pgd_none(*pgd) || pgd_bad(*pgd)) | ||
68 | return ~0UL; | ||
69 | |||
70 | pud = pud_offset(pgd, vaddr); | ||
71 | if (pud_none(*pud) || pud_bad(*pud)) | ||
72 | return ~0UL; | ||
73 | |||
74 | pmd = pmd_offset(pud, vaddr); | ||
75 | if (pmd_none(*pmd) || pmd_bad(*pmd)) | ||
76 | return ~0UL; | ||
77 | |||
78 | ptep = pte_offset_kernel(pmd, vaddr); | ||
79 | if (!ptep) | ||
80 | return ~0UL; | ||
81 | |||
82 | return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK); | ||
83 | } | ||
84 | |||
85 | if (vaddr > TASK_SIZE) { | ||
86 | /* percpu variables */ | ||
87 | if (REGION_NUMBER(vaddr) == 7 && | ||
88 | REGION_OFFSET(vaddr) >= (1ULL << IA64_MAX_PHYS_BITS)) | ||
89 | ia64_tpa(vaddr); | ||
90 | |||
91 | /* kernel address */ | ||
92 | return __pa(vaddr); | ||
93 | } | ||
94 | |||
95 | /* XXX double-check (lack of) locking */ | ||
96 | vma = find_extend_vma(current->mm, vaddr); | ||
97 | if (!vma) | ||
98 | return ~0UL; | ||
99 | |||
100 | /* We assume the page is modified. */ | ||
101 | page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH); | ||
102 | if (IS_ERR_OR_NULL(page)) | ||
103 | return ~0UL; | ||
104 | |||
105 | return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK); | ||
106 | } | ||
diff --git a/arch/ia64/xen/xenivt.S b/arch/ia64/xen/xenivt.S deleted file mode 100644 index 3e71d50584d9..000000000000 --- a/arch/ia64/xen/xenivt.S +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ia64/xen/ivt.S | ||
3 | * | ||
4 | * Copyright (C) 2005 Hewlett-Packard Co | ||
5 | * Dan Magenheimer <dan.magenheimer@hp.com> | ||
6 | * | ||
7 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
8 | * VA Linux Systems Japan K.K. | ||
9 | * pv_ops. | ||
10 | */ | ||
11 | |||
12 | #include <asm/asmmacro.h> | ||
13 | #include <asm/kregs.h> | ||
14 | #include <asm/pgtable.h> | ||
15 | |||
16 | #include "../kernel/minstate.h" | ||
17 | |||
18 | .section .text,"ax" | ||
19 | GLOBAL_ENTRY(xen_event_callback) | ||
20 | mov r31=pr // prepare to save predicates | ||
21 | ;; | ||
22 | SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 | ||
23 | ;; | ||
24 | movl r3=XSI_PSR_IC | ||
25 | mov r14=1 | ||
26 | ;; | ||
27 | st4 [r3]=r14 | ||
28 | ;; | ||
29 | adds r3=8,r2 // set up second base pointer for SAVE_REST | ||
30 | srlz.i // ensure everybody knows psr.ic is back on | ||
31 | ;; | ||
32 | SAVE_REST | ||
33 | ;; | ||
34 | 1: | ||
35 | alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group | ||
36 | add out0=16,sp // pass pointer to pt_regs as first arg | ||
37 | ;; | ||
38 | br.call.sptk.many b0=xen_evtchn_do_upcall | ||
39 | ;; | ||
40 | movl r20=XSI_PSR_I_ADDR | ||
41 | ;; | ||
42 | ld8 r20=[r20] | ||
43 | ;; | ||
44 | adds r20=-1,r20 // vcpu_info->evtchn_upcall_pending | ||
45 | ;; | ||
46 | ld1 r20=[r20] | ||
47 | ;; | ||
48 | cmp.ne p6,p0=r20,r0 // if there are pending events, | ||
49 | (p6) br.spnt.few 1b // call evtchn_do_upcall again. | ||
50 | br.sptk.many xen_leave_kernel // we know ia64_leave_kernel is | ||
51 | // paravirtualized as xen_leave_kernel | ||
52 | END(xen_event_callback) | ||
diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S deleted file mode 100644 index e29519ebe2d2..000000000000 --- a/arch/ia64/xen/xensetup.S +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | /* | ||
2 | * Support routines for Xen | ||
3 | * | ||
4 | * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com> | ||
5 | */ | ||
6 | |||
7 | #include <asm/processor.h> | ||
8 | #include <asm/asmmacro.h> | ||
9 | #include <asm/pgtable.h> | ||
10 | #include <asm/paravirt.h> | ||
11 | #include <asm/xen/privop.h> | ||
12 | #include <linux/elfnote.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <xen/interface/elfnote.h> | ||
15 | |||
16 | .section .data..read_mostly | ||
17 | .align 8 | ||
18 | .global xen_domain_type | ||
19 | xen_domain_type: | ||
20 | data4 XEN_NATIVE_ASM | ||
21 | .previous | ||
22 | |||
23 | __INIT | ||
24 | ENTRY(startup_xen) | ||
25 | // Calculate load offset. | ||
26 | // The constant, LOAD_OFFSET, can't be used because the boot | ||
27 | // loader doesn't always load to the LMA specified by the vmlinux.lds. | ||
28 | mov r9=ip // must be the first instruction to make sure | ||
29 | // that r9 = the physical address of startup_xen. | ||
30 | // Usually r9 = startup_xen - LOAD_OFFSET | ||
31 | movl r8=startup_xen | ||
32 | ;; | ||
33 | sub r9=r9,r8 // Usually r9 = -LOAD_OFFSET. | ||
34 | |||
35 | mov r10=PARAVIRT_HYPERVISOR_TYPE_XEN | ||
36 | movl r11=_start | ||
37 | ;; | ||
38 | add r11=r11,r9 | ||
39 | movl r8=hypervisor_type | ||
40 | ;; | ||
41 | add r8=r8,r9 | ||
42 | mov b0=r11 | ||
43 | ;; | ||
44 | st8 [r8]=r10 | ||
45 | br.cond.sptk.many b0 | ||
46 | ;; | ||
47 | END(startup_xen) | ||
48 | |||
49 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") | ||
50 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6") | ||
51 | ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0") | ||
52 | ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, data8.ua startup_xen - LOAD_OFFSET) | ||
53 | |||
54 | #define isBP p3 // are we the Bootstrap Processor? | ||
55 | |||
56 | GLOBAL_ENTRY(xen_setup_hook) | ||
57 | mov r8=XEN_PV_DOMAIN_ASM | ||
58 | (isBP) movl r9=xen_domain_type;; | ||
59 | (isBP) st4 [r9]=r8 | ||
60 | movl r10=xen_ivt;; | ||
61 | |||
62 | mov cr.iva=r10 | ||
63 | |||
64 | /* Set xsi base. */ | ||
65 | #define FW_HYPERCALL_SET_SHARED_INFO_VA 0x600 | ||
66 | (isBP) mov r2=FW_HYPERCALL_SET_SHARED_INFO_VA | ||
67 | (isBP) movl r28=XSI_BASE;; | ||
68 | (isBP) break 0x1000;; | ||
69 | |||
70 | /* setup pv_ops */ | ||
71 | (isBP) mov r4=rp | ||
72 | ;; | ||
73 | (isBP) br.call.sptk.many rp=xen_setup_pv_ops | ||
74 | ;; | ||
75 | (isBP) mov rp=r4 | ||
76 | ;; | ||
77 | |||
78 | br.ret.sptk.many rp | ||
79 | ;; | ||
80 | END(xen_setup_hook) | ||
diff --git a/arch/m32r/include/asm/barrier.h b/arch/m32r/include/asm/barrier.h index 6976621efd3f..1a40265e8d88 100644 --- a/arch/m32r/include/asm/barrier.h +++ b/arch/m32r/include/asm/barrier.h | |||
@@ -11,84 +11,6 @@ | |||
11 | 11 | ||
12 | #define nop() __asm__ __volatile__ ("nop" : : ) | 12 | #define nop() __asm__ __volatile__ ("nop" : : ) |
13 | 13 | ||
14 | /* | 14 | #include <asm-generic/barrier.h> |
15 | * Memory barrier. | ||
16 | * | ||
17 | * mb() prevents loads and stores being reordered across this point. | ||
18 | * rmb() prevents loads being reordered across this point. | ||
19 | * wmb() prevents stores being reordered across this point. | ||
20 | */ | ||
21 | #define mb() barrier() | ||
22 | #define rmb() mb() | ||
23 | #define wmb() mb() | ||
24 | |||
25 | /** | ||
26 | * read_barrier_depends - Flush all pending reads that subsequents reads | ||
27 | * depend on. | ||
28 | * | ||
29 | * No data-dependent reads from memory-like regions are ever reordered | ||
30 | * over this barrier. All reads preceding this primitive are guaranteed | ||
31 | * to access memory (but not necessarily other CPUs' caches) before any | ||
32 | * reads following this primitive that depend on the data return by | ||
33 | * any of the preceding reads. This primitive is much lighter weight than | ||
34 | * rmb() on most CPUs, and is never heavier weight than is | ||
35 | * rmb(). | ||
36 | * | ||
37 | * These ordering constraints are respected by both the local CPU | ||
38 | * and the compiler. | ||
39 | * | ||
40 | * Ordering is not guaranteed by anything other than these primitives, | ||
41 | * not even by data dependencies. See the documentation for | ||
42 | * memory_barrier() for examples and URLs to more information. | ||
43 | * | ||
44 | * For example, the following code would force ordering (the initial | ||
45 | * value of "a" is zero, "b" is one, and "p" is "&a"): | ||
46 | * | ||
47 | * <programlisting> | ||
48 | * CPU 0 CPU 1 | ||
49 | * | ||
50 | * b = 2; | ||
51 | * memory_barrier(); | ||
52 | * p = &b; q = p; | ||
53 | * read_barrier_depends(); | ||
54 | * d = *q; | ||
55 | * </programlisting> | ||
56 | * | ||
57 | * | ||
58 | * because the read of "*q" depends on the read of "p" and these | ||
59 | * two reads are separated by a read_barrier_depends(). However, | ||
60 | * the following code, with the same initial values for "a" and "b": | ||
61 | * | ||
62 | * <programlisting> | ||
63 | * CPU 0 CPU 1 | ||
64 | * | ||
65 | * a = 2; | ||
66 | * memory_barrier(); | ||
67 | * b = 3; y = b; | ||
68 | * read_barrier_depends(); | ||
69 | * x = a; | ||
70 | * </programlisting> | ||
71 | * | ||
72 | * does not enforce ordering, since there is no data dependency between | ||
73 | * the read of "a" and the read of "b". Therefore, on some CPUs, such | ||
74 | * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() | ||
75 | * in cases like this where there are no data dependencies. | ||
76 | **/ | ||
77 | |||
78 | #define read_barrier_depends() do { } while (0) | ||
79 | |||
80 | #ifdef CONFIG_SMP | ||
81 | #define smp_mb() mb() | ||
82 | #define smp_rmb() rmb() | ||
83 | #define smp_wmb() wmb() | ||
84 | #define smp_read_barrier_depends() read_barrier_depends() | ||
85 | #define set_mb(var, value) do { (void) xchg(&var, value); } while (0) | ||
86 | #else | ||
87 | #define smp_mb() barrier() | ||
88 | #define smp_rmb() barrier() | ||
89 | #define smp_wmb() barrier() | ||
90 | #define smp_read_barrier_depends() do { } while (0) | ||
91 | #define set_mb(var, value) do { var = value; barrier(); } while (0) | ||
92 | #endif | ||
93 | 15 | ||
94 | #endif /* _ASM_M32R_BARRIER_H */ | 16 | #endif /* _ASM_M32R_BARRIER_H */ |
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 75f25a8e3001..dbdd2231c75d 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
@@ -87,6 +87,30 @@ config MMU_SUN3 | |||
87 | bool | 87 | bool |
88 | depends on MMU && !MMU_MOTOROLA && !MMU_COLDFIRE | 88 | depends on MMU && !MMU_MOTOROLA && !MMU_COLDFIRE |
89 | 89 | ||
90 | config KEXEC | ||
91 | bool "kexec system call" | ||
92 | depends on M68KCLASSIC | ||
93 | help | ||
94 | kexec is a system call that implements the ability to shutdown your | ||
95 | current kernel, and to start another kernel. It is like a reboot | ||
96 | but it is independent of the system firmware. And like a reboot | ||
97 | you can start any kernel with it, not just Linux. | ||
98 | |||
99 | The name comes from the similarity to the exec system call. | ||
100 | |||
101 | It is an ongoing process to be certain the hardware in a machine | ||
102 | is properly shutdown, so do not be surprised if this code does not | ||
103 | initially work for you. As of this writing the exact hardware | ||
104 | interface is strongly in flux, so no good recommendation can be | ||
105 | made. | ||
106 | |||
107 | config BOOTINFO_PROC | ||
108 | bool "Export bootinfo in procfs" | ||
109 | depends on KEXEC && M68KCLASSIC | ||
110 | help | ||
111 | Say Y to export the bootinfo used to boot the kernel in a | ||
112 | "bootinfo" file in procfs. This is useful with kexec. | ||
113 | |||
90 | menu "Platform setup" | 114 | menu "Platform setup" |
91 | 115 | ||
92 | source arch/m68k/Kconfig.cpu | 116 | source arch/m68k/Kconfig.cpu |
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c index 99449fbf9a72..ba03cec3f711 100644 --- a/arch/m68k/amiga/chipram.c +++ b/arch/m68k/amiga/chipram.c | |||
@@ -87,7 +87,7 @@ void *amiga_chip_alloc_res(unsigned long size, struct resource *res) | |||
87 | 87 | ||
88 | atomic_sub(size, &chipavail); | 88 | atomic_sub(size, &chipavail); |
89 | pr_debug("amiga_chip_alloc_res: returning %pR\n", res); | 89 | pr_debug("amiga_chip_alloc_res: returning %pR\n", res); |
90 | return (void *)ZTWO_VADDR(res->start); | 90 | return ZTWO_VADDR(res->start); |
91 | } | 91 | } |
92 | 92 | ||
93 | void amiga_chip_free(void *ptr) | 93 | void amiga_chip_free(void *ptr) |
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index b819390e29cd..9625b7132227 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/keyboard.h> | 28 | #include <linux/keyboard.h> |
29 | 29 | ||
30 | #include <asm/bootinfo.h> | 30 | #include <asm/bootinfo.h> |
31 | #include <asm/bootinfo-amiga.h> | ||
32 | #include <asm/byteorder.h> | ||
31 | #include <asm/setup.h> | 33 | #include <asm/setup.h> |
32 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
33 | #include <asm/amigahw.h> | 35 | #include <asm/amigahw.h> |
@@ -140,46 +142,46 @@ static struct resource ram_resource[NUM_MEMINFO]; | |||
140 | * Parse an Amiga-specific record in the bootinfo | 142 | * Parse an Amiga-specific record in the bootinfo |
141 | */ | 143 | */ |
142 | 144 | ||
143 | int amiga_parse_bootinfo(const struct bi_record *record) | 145 | int __init amiga_parse_bootinfo(const struct bi_record *record) |
144 | { | 146 | { |
145 | int unknown = 0; | 147 | int unknown = 0; |
146 | const unsigned long *data = record->data; | 148 | const void *data = record->data; |
147 | 149 | ||
148 | switch (record->tag) { | 150 | switch (be16_to_cpu(record->tag)) { |
149 | case BI_AMIGA_MODEL: | 151 | case BI_AMIGA_MODEL: |
150 | amiga_model = *data; | 152 | amiga_model = be32_to_cpup(data); |
151 | break; | 153 | break; |
152 | 154 | ||
153 | case BI_AMIGA_ECLOCK: | 155 | case BI_AMIGA_ECLOCK: |
154 | amiga_eclock = *data; | 156 | amiga_eclock = be32_to_cpup(data); |
155 | break; | 157 | break; |
156 | 158 | ||
157 | case BI_AMIGA_CHIPSET: | 159 | case BI_AMIGA_CHIPSET: |
158 | amiga_chipset = *data; | 160 | amiga_chipset = be32_to_cpup(data); |
159 | break; | 161 | break; |
160 | 162 | ||
161 | case BI_AMIGA_CHIP_SIZE: | 163 | case BI_AMIGA_CHIP_SIZE: |
162 | amiga_chip_size = *(const int *)data; | 164 | amiga_chip_size = be32_to_cpup(data); |
163 | break; | 165 | break; |
164 | 166 | ||
165 | case BI_AMIGA_VBLANK: | 167 | case BI_AMIGA_VBLANK: |
166 | amiga_vblank = *(const unsigned char *)data; | 168 | amiga_vblank = *(const __u8 *)data; |
167 | break; | 169 | break; |
168 | 170 | ||
169 | case BI_AMIGA_PSFREQ: | 171 | case BI_AMIGA_PSFREQ: |
170 | amiga_psfreq = *(const unsigned char *)data; | 172 | amiga_psfreq = *(const __u8 *)data; |
171 | break; | 173 | break; |
172 | 174 | ||
173 | case BI_AMIGA_AUTOCON: | 175 | case BI_AMIGA_AUTOCON: |
174 | #ifdef CONFIG_ZORRO | 176 | #ifdef CONFIG_ZORRO |
175 | if (zorro_num_autocon < ZORRO_NUM_AUTO) { | 177 | if (zorro_num_autocon < ZORRO_NUM_AUTO) { |
176 | const struct ConfigDev *cd = (struct ConfigDev *)data; | 178 | const struct ConfigDev *cd = data; |
177 | struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++]; | 179 | struct zorro_dev_init *dev = &zorro_autocon_init[zorro_num_autocon++]; |
178 | dev->rom = cd->cd_Rom; | 180 | dev->rom = cd->cd_Rom; |
179 | dev->slotaddr = cd->cd_SlotAddr; | 181 | dev->slotaddr = be16_to_cpu(cd->cd_SlotAddr); |
180 | dev->slotsize = cd->cd_SlotSize; | 182 | dev->slotsize = be16_to_cpu(cd->cd_SlotSize); |
181 | dev->resource.start = (unsigned long)cd->cd_BoardAddr; | 183 | dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr); |
182 | dev->resource.end = dev->resource.start + cd->cd_BoardSize - 1; | 184 | dev->boardsize = be32_to_cpu(cd->cd_BoardSize); |
183 | } else | 185 | } else |
184 | printk("amiga_parse_bootinfo: too many AutoConfig devices\n"); | 186 | printk("amiga_parse_bootinfo: too many AutoConfig devices\n"); |
185 | #endif /* CONFIG_ZORRO */ | 187 | #endif /* CONFIG_ZORRO */ |
@@ -358,6 +360,14 @@ static void __init amiga_identify(void) | |||
358 | #undef AMIGAHW_ANNOUNCE | 360 | #undef AMIGAHW_ANNOUNCE |
359 | } | 361 | } |
360 | 362 | ||
363 | |||
364 | static unsigned long amiga_random_get_entropy(void) | ||
365 | { | ||
366 | /* VPOSR/VHPOSR provide at least 17 bits of data changing at 1.79 MHz */ | ||
367 | return *(unsigned long *)&amiga_custom.vposr; | ||
368 | } | ||
369 | |||
370 | |||
361 | /* | 371 | /* |
362 | * Setup the Amiga configuration info | 372 | * Setup the Amiga configuration info |
363 | */ | 373 | */ |
@@ -395,6 +405,8 @@ void __init config_amiga(void) | |||
395 | mach_heartbeat = amiga_heartbeat; | 405 | mach_heartbeat = amiga_heartbeat; |
396 | #endif | 406 | #endif |
397 | 407 | ||
408 | mach_random_get_entropy = amiga_random_get_entropy; | ||
409 | |||
398 | /* Fill in the clock value (based on the 700 kHz E-Clock) */ | 410 | /* Fill in the clock value (based on the 700 kHz E-Clock) */ |
399 | amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */ | 411 | amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */ |
400 | 412 | ||
@@ -608,6 +620,8 @@ static void amiga_mem_console_write(struct console *co, const char *s, | |||
608 | 620 | ||
609 | static int __init amiga_savekmsg_setup(char *arg) | 621 | static int __init amiga_savekmsg_setup(char *arg) |
610 | { | 622 | { |
623 | bool registered; | ||
624 | |||
611 | if (!MACH_IS_AMIGA || strcmp(arg, "mem")) | 625 | if (!MACH_IS_AMIGA || strcmp(arg, "mem")) |
612 | return 0; | 626 | return 0; |
613 | 627 | ||
@@ -618,14 +632,16 @@ static int __init amiga_savekmsg_setup(char *arg) | |||
618 | 632 | ||
619 | /* Just steal the block, the chipram allocator isn't functional yet */ | 633 | /* Just steal the block, the chipram allocator isn't functional yet */ |
620 | amiga_chip_size -= SAVEKMSG_MAXMEM; | 634 | amiga_chip_size -= SAVEKMSG_MAXMEM; |
621 | savekmsg = (void *)ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size); | 635 | savekmsg = ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size); |
622 | savekmsg->magic1 = SAVEKMSG_MAGIC1; | 636 | savekmsg->magic1 = SAVEKMSG_MAGIC1; |
623 | savekmsg->magic2 = SAVEKMSG_MAGIC2; | 637 | savekmsg->magic2 = SAVEKMSG_MAGIC2; |
624 | savekmsg->magicptr = ZTWO_PADDR(savekmsg); | 638 | savekmsg->magicptr = ZTWO_PADDR(savekmsg); |
625 | savekmsg->size = 0; | 639 | savekmsg->size = 0; |
626 | 640 | ||
641 | registered = !!amiga_console_driver.write; | ||
627 | amiga_console_driver.write = amiga_mem_console_write; | 642 | amiga_console_driver.write = amiga_mem_console_write; |
628 | register_console(&amiga_console_driver); | 643 | if (!registered) |
644 | register_console(&amiga_console_driver); | ||
629 | return 0; | 645 | return 0; |
630 | } | 646 | } |
631 | 647 | ||
@@ -707,11 +723,16 @@ void amiga_serial_gets(struct console *co, char *s, int len) | |||
707 | 723 | ||
708 | static int __init amiga_debug_setup(char *arg) | 724 | static int __init amiga_debug_setup(char *arg) |
709 | { | 725 | { |
710 | if (MACH_IS_AMIGA && !strcmp(arg, "ser")) { | 726 | bool registered; |
711 | /* no initialization required (?) */ | 727 | |
712 | amiga_console_driver.write = amiga_serial_console_write; | 728 | if (!MACH_IS_AMIGA || strcmp(arg, "ser")) |
729 | return 0; | ||
730 | |||
731 | /* no initialization required (?) */ | ||
732 | registered = !!amiga_console_driver.write; | ||
733 | amiga_console_driver.write = amiga_serial_console_write; | ||
734 | if (!registered) | ||
713 | register_console(&amiga_console_driver); | 735 | register_console(&amiga_console_driver); |
714 | } | ||
715 | return 0; | 736 | return 0; |
716 | } | 737 | } |
717 | 738 | ||
diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index dacd9f911f71..d34029d7b058 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <asm/amigahw.h> | 14 | #include <asm/amigahw.h> |
15 | #include <asm/amigayle.h> | 15 | #include <asm/amigayle.h> |
16 | #include <asm/byteorder.h> | ||
16 | 17 | ||
17 | 18 | ||
18 | #ifdef CONFIG_ZORRO | 19 | #ifdef CONFIG_ZORRO |
@@ -66,10 +67,12 @@ static int __init z_dev_present(zorro_id id) | |||
66 | { | 67 | { |
67 | unsigned int i; | 68 | unsigned int i; |
68 | 69 | ||
69 | for (i = 0; i < zorro_num_autocon; i++) | 70 | for (i = 0; i < zorro_num_autocon; i++) { |
70 | if (zorro_autocon[i].rom.er_Manufacturer == ZORRO_MANUF(id) && | 71 | const struct ExpansionRom *rom = &zorro_autocon_init[i].rom; |
71 | zorro_autocon[i].rom.er_Product == ZORRO_PROD(id)) | 72 | if (be16_to_cpu(rom->er_Manufacturer) == ZORRO_MANUF(id) && |
73 | rom->er_Product == ZORRO_PROD(id)) | ||
72 | return 1; | 74 | return 1; |
75 | } | ||
73 | 76 | ||
74 | return 0; | 77 | return 0; |
75 | } | 78 | } |
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c index 3ea56b90e718..9268c0f96376 100644 --- a/arch/m68k/apollo/config.c +++ b/arch/m68k/apollo/config.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <linux/init.h> | ||
1 | #include <linux/types.h> | 2 | #include <linux/types.h> |
2 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
3 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
@@ -9,6 +10,8 @@ | |||
9 | 10 | ||
10 | #include <asm/setup.h> | 11 | #include <asm/setup.h> |
11 | #include <asm/bootinfo.h> | 12 | #include <asm/bootinfo.h> |
13 | #include <asm/bootinfo-apollo.h> | ||
14 | #include <asm/byteorder.h> | ||
12 | #include <asm/pgtable.h> | 15 | #include <asm/pgtable.h> |
13 | #include <asm/apollohw.h> | 16 | #include <asm/apollohw.h> |
14 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
@@ -43,26 +46,25 @@ static const char *apollo_models[] = { | |||
43 | [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)" | 46 | [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)" |
44 | }; | 47 | }; |
45 | 48 | ||
46 | int apollo_parse_bootinfo(const struct bi_record *record) { | 49 | int __init apollo_parse_bootinfo(const struct bi_record *record) |
47 | 50 | { | |
48 | int unknown = 0; | 51 | int unknown = 0; |
49 | const unsigned long *data = record->data; | 52 | const void *data = record->data; |
50 | 53 | ||
51 | switch(record->tag) { | 54 | switch (be16_to_cpu(record->tag)) { |
52 | case BI_APOLLO_MODEL: | 55 | case BI_APOLLO_MODEL: |
53 | apollo_model=*data; | 56 | apollo_model = be32_to_cpup(data); |
54 | break; | 57 | break; |
55 | 58 | ||
56 | default: | 59 | default: |
57 | unknown=1; | 60 | unknown=1; |
58 | } | 61 | } |
59 | 62 | ||
60 | return unknown; | 63 | return unknown; |
61 | } | 64 | } |
62 | 65 | ||
63 | void dn_setup_model(void) { | 66 | static void __init dn_setup_model(void) |
64 | 67 | { | |
65 | |||
66 | printk("Apollo hardware found: "); | 68 | printk("Apollo hardware found: "); |
67 | printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]); | 69 | printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]); |
68 | 70 | ||
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 20cde4e9fc77..3e73a63c066f 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c | |||
@@ -333,6 +333,9 @@ void __init atari_init_IRQ(void) | |||
333 | m68k_setup_irq_controller(&atari_mfptimer_chip, handle_simple_irq, | 333 | m68k_setup_irq_controller(&atari_mfptimer_chip, handle_simple_irq, |
334 | IRQ_MFP_TIMER1, 8); | 334 | IRQ_MFP_TIMER1, 8); |
335 | 335 | ||
336 | irq_set_status_flags(IRQ_MFP_TIMER1, IRQ_IS_POLLED); | ||
337 | irq_set_status_flags(IRQ_MFP_TIMER2, IRQ_IS_POLLED); | ||
338 | |||
336 | /* prepare timer D data for use as poll interrupt */ | 339 | /* prepare timer D data for use as poll interrupt */ |
337 | /* set Timer D data Register - needs to be > 0 */ | 340 | /* set Timer D data Register - needs to be > 0 */ |
338 | st_mfp.tim_dt_d = 254; /* < 100 Hz */ | 341 | st_mfp.tim_dt_d = 254; /* < 100 Hz */ |
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index fb2d0bd9b3ad..01a62161b08a 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | 38 | ||
39 | #include <asm/bootinfo.h> | 39 | #include <asm/bootinfo.h> |
40 | #include <asm/bootinfo-atari.h> | ||
41 | #include <asm/byteorder.h> | ||
40 | #include <asm/setup.h> | 42 | #include <asm/setup.h> |
41 | #include <asm/atarihw.h> | 43 | #include <asm/atarihw.h> |
42 | #include <asm/atariints.h> | 44 | #include <asm/atariints.h> |
@@ -129,14 +131,14 @@ static int __init scc_test(volatile char *ctla) | |||
129 | int __init atari_parse_bootinfo(const struct bi_record *record) | 131 | int __init atari_parse_bootinfo(const struct bi_record *record) |
130 | { | 132 | { |
131 | int unknown = 0; | 133 | int unknown = 0; |
132 | const u_long *data = record->data; | 134 | const void *data = record->data; |
133 | 135 | ||
134 | switch (record->tag) { | 136 | switch (be16_to_cpu(record->tag)) { |
135 | case BI_ATARI_MCH_COOKIE: | 137 | case BI_ATARI_MCH_COOKIE: |
136 | atari_mch_cookie = *data; | 138 | atari_mch_cookie = be32_to_cpup(data); |
137 | break; | 139 | break; |
138 | case BI_ATARI_MCH_TYPE: | 140 | case BI_ATARI_MCH_TYPE: |
139 | atari_mch_type = *data; | 141 | atari_mch_type = be32_to_cpup(data); |
140 | break; | 142 | break; |
141 | default: | 143 | default: |
142 | unknown = 1; | 144 | unknown = 1; |
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c index a547ba9683d1..03cb5e08d7cf 100644 --- a/arch/m68k/atari/debug.c +++ b/arch/m68k/atari/debug.c | |||
@@ -287,6 +287,8 @@ static void __init atari_init_midi_port(int cflag) | |||
287 | 287 | ||
288 | static int __init atari_debug_setup(char *arg) | 288 | static int __init atari_debug_setup(char *arg) |
289 | { | 289 | { |
290 | bool registered; | ||
291 | |||
290 | if (!MACH_IS_ATARI) | 292 | if (!MACH_IS_ATARI) |
291 | return 0; | 293 | return 0; |
292 | 294 | ||
@@ -294,6 +296,7 @@ static int __init atari_debug_setup(char *arg) | |||
294 | /* defaults to ser2 for a Falcon and ser1 otherwise */ | 296 | /* defaults to ser2 for a Falcon and ser1 otherwise */ |
295 | arg = MACH_IS_FALCON ? "ser2" : "ser1"; | 297 | arg = MACH_IS_FALCON ? "ser2" : "ser1"; |
296 | 298 | ||
299 | registered = !!atari_console_driver.write; | ||
297 | if (!strcmp(arg, "ser1")) { | 300 | if (!strcmp(arg, "ser1")) { |
298 | /* ST-MFP Modem1 serial port */ | 301 | /* ST-MFP Modem1 serial port */ |
299 | atari_init_mfp_port(B9600|CS8); | 302 | atari_init_mfp_port(B9600|CS8); |
@@ -317,7 +320,7 @@ static int __init atari_debug_setup(char *arg) | |||
317 | sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */ | 320 | sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */ |
318 | atari_console_driver.write = atari_par_console_write; | 321 | atari_console_driver.write = atari_par_console_write; |
319 | } | 322 | } |
320 | if (atari_console_driver.write) | 323 | if (atari_console_driver.write && !registered) |
321 | register_console(&atari_console_driver); | 324 | register_console(&atari_console_driver); |
322 | 325 | ||
323 | return 0; | 326 | return 0; |
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 8943aa4c18e6..478623dbb209 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/bcd.h> | 28 | #include <linux/bcd.h> |
29 | 29 | ||
30 | #include <asm/bootinfo.h> | 30 | #include <asm/bootinfo.h> |
31 | #include <asm/bootinfo-vme.h> | ||
32 | #include <asm/byteorder.h> | ||
31 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
32 | #include <asm/setup.h> | 34 | #include <asm/setup.h> |
33 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
@@ -50,9 +52,9 @@ void bvme6000_set_vectors (void); | |||
50 | static irq_handler_t tick_handler; | 52 | static irq_handler_t tick_handler; |
51 | 53 | ||
52 | 54 | ||
53 | int bvme6000_parse_bootinfo(const struct bi_record *bi) | 55 | int __init bvme6000_parse_bootinfo(const struct bi_record *bi) |
54 | { | 56 | { |
55 | if (bi->tag == BI_VME_TYPE) | 57 | if (be16_to_cpu(bi->tag) == BI_VME_TYPE) |
56 | return 0; | 58 | return 0; |
57 | else | 59 | else |
58 | return 1; | 60 | return 1; |
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 19325e117eea..559ff3af8ff7 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig | |||
@@ -52,7 +52,6 @@ CONFIG_IP_PNP_RARP=y | |||
52 | CONFIG_NET_IPIP=m | 52 | CONFIG_NET_IPIP=m |
53 | CONFIG_NET_IPGRE_DEMUX=m | 53 | CONFIG_NET_IPGRE_DEMUX=m |
54 | CONFIG_NET_IPGRE=m | 54 | CONFIG_NET_IPGRE=m |
55 | CONFIG_SYN_COOKIES=y | ||
56 | CONFIG_NET_IPVTI=m | 55 | CONFIG_NET_IPVTI=m |
57 | CONFIG_INET_AH=m | 56 | CONFIG_INET_AH=m |
58 | CONFIG_INET_ESP=m | 57 | CONFIG_INET_ESP=m |
@@ -63,11 +62,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
63 | # CONFIG_INET_LRO is not set | 62 | # CONFIG_INET_LRO is not set |
64 | CONFIG_INET_DIAG=m | 63 | CONFIG_INET_DIAG=m |
65 | CONFIG_INET_UDP_DIAG=m | 64 | CONFIG_INET_UDP_DIAG=m |
66 | CONFIG_IPV6_PRIVACY=y | ||
67 | CONFIG_IPV6_ROUTER_PREF=y | 65 | CONFIG_IPV6_ROUTER_PREF=y |
68 | CONFIG_INET6_AH=m | 66 | CONFIG_INET6_AH=m |
69 | CONFIG_INET6_ESP=m | 67 | CONFIG_INET6_ESP=m |
70 | CONFIG_INET6_IPCOMP=m | 68 | CONFIG_INET6_IPCOMP=m |
69 | CONFIG_IPV6_VTI=m | ||
71 | CONFIG_IPV6_GRE=m | 70 | CONFIG_IPV6_GRE=m |
72 | CONFIG_NETFILTER=y | 71 | CONFIG_NETFILTER=y |
73 | CONFIG_NF_CONNTRACK=m | 72 | CONFIG_NF_CONNTRACK=m |
@@ -85,6 +84,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
85 | CONFIG_NF_CONNTRACK_SANE=m | 84 | CONFIG_NF_CONNTRACK_SANE=m |
86 | CONFIG_NF_CONNTRACK_SIP=m | 85 | CONFIG_NF_CONNTRACK_SIP=m |
87 | CONFIG_NF_CONNTRACK_TFTP=m | 86 | CONFIG_NF_CONNTRACK_TFTP=m |
87 | CONFIG_NF_TABLES=m | ||
88 | CONFIG_NFT_EXTHDR=m | ||
89 | CONFIG_NFT_META=m | ||
90 | CONFIG_NFT_CT=m | ||
91 | CONFIG_NFT_RBTREE=m | ||
92 | CONFIG_NFT_HASH=m | ||
93 | CONFIG_NFT_COUNTER=m | ||
94 | CONFIG_NFT_LOG=m | ||
95 | CONFIG_NFT_LIMIT=m | ||
96 | CONFIG_NFT_NAT=m | ||
97 | CONFIG_NFT_COMPAT=m | ||
88 | CONFIG_NETFILTER_XT_SET=m | 98 | CONFIG_NETFILTER_XT_SET=m |
89 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 99 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
90 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 100 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -98,6 +108,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
98 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 108 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
99 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 109 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
100 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 110 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
111 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
101 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 112 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
102 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 113 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
103 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 114 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -130,6 +141,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
130 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 141 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
131 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 142 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
132 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 143 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
144 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
133 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 145 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
134 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 146 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
135 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 147 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -144,11 +156,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
144 | CONFIG_IP_SET_HASH_IPPORT=m | 156 | CONFIG_IP_SET_HASH_IPPORT=m |
145 | CONFIG_IP_SET_HASH_IPPORTIP=m | 157 | CONFIG_IP_SET_HASH_IPPORTIP=m |
146 | CONFIG_IP_SET_HASH_IPPORTNET=m | 158 | CONFIG_IP_SET_HASH_IPPORTNET=m |
159 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
147 | CONFIG_IP_SET_HASH_NET=m | 160 | CONFIG_IP_SET_HASH_NET=m |
161 | CONFIG_IP_SET_HASH_NETNET=m | ||
148 | CONFIG_IP_SET_HASH_NETPORT=m | 162 | CONFIG_IP_SET_HASH_NETPORT=m |
149 | CONFIG_IP_SET_HASH_NETIFACE=m | 163 | CONFIG_IP_SET_HASH_NETIFACE=m |
150 | CONFIG_IP_SET_LIST_SET=m | 164 | CONFIG_IP_SET_LIST_SET=m |
151 | CONFIG_NF_CONNTRACK_IPV4=m | 165 | CONFIG_NF_CONNTRACK_IPV4=m |
166 | CONFIG_NF_TABLES_IPV4=m | ||
167 | CONFIG_NFT_REJECT_IPV4=m | ||
168 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
169 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
170 | CONFIG_NF_TABLES_ARP=m | ||
152 | CONFIG_IP_NF_IPTABLES=m | 171 | CONFIG_IP_NF_IPTABLES=m |
153 | CONFIG_IP_NF_MATCH_AH=m | 172 | CONFIG_IP_NF_MATCH_AH=m |
154 | CONFIG_IP_NF_MATCH_ECN=m | 173 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -156,6 +175,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
156 | CONFIG_IP_NF_MATCH_TTL=m | 175 | CONFIG_IP_NF_MATCH_TTL=m |
157 | CONFIG_IP_NF_FILTER=m | 176 | CONFIG_IP_NF_FILTER=m |
158 | CONFIG_IP_NF_TARGET_REJECT=m | 177 | CONFIG_IP_NF_TARGET_REJECT=m |
178 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
159 | CONFIG_IP_NF_TARGET_ULOG=m | 179 | CONFIG_IP_NF_TARGET_ULOG=m |
160 | CONFIG_NF_NAT_IPV4=m | 180 | CONFIG_NF_NAT_IPV4=m |
161 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 181 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -170,6 +190,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
170 | CONFIG_IP_NF_ARPFILTER=m | 190 | CONFIG_IP_NF_ARPFILTER=m |
171 | CONFIG_IP_NF_ARP_MANGLE=m | 191 | CONFIG_IP_NF_ARP_MANGLE=m |
172 | CONFIG_NF_CONNTRACK_IPV6=m | 192 | CONFIG_NF_CONNTRACK_IPV6=m |
193 | CONFIG_NF_TABLES_IPV6=m | ||
194 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
195 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
173 | CONFIG_IP6_NF_IPTABLES=m | 196 | CONFIG_IP6_NF_IPTABLES=m |
174 | CONFIG_IP6_NF_MATCH_AH=m | 197 | CONFIG_IP6_NF_MATCH_AH=m |
175 | CONFIG_IP6_NF_MATCH_EUI64=m | 198 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -183,11 +206,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
183 | CONFIG_IP6_NF_TARGET_HL=m | 206 | CONFIG_IP6_NF_TARGET_HL=m |
184 | CONFIG_IP6_NF_FILTER=m | 207 | CONFIG_IP6_NF_FILTER=m |
185 | CONFIG_IP6_NF_TARGET_REJECT=m | 208 | CONFIG_IP6_NF_TARGET_REJECT=m |
209 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
186 | CONFIG_IP6_NF_MANGLE=m | 210 | CONFIG_IP6_NF_MANGLE=m |
187 | CONFIG_IP6_NF_RAW=m | 211 | CONFIG_IP6_NF_RAW=m |
188 | CONFIG_NF_NAT_IPV6=m | 212 | CONFIG_NF_NAT_IPV6=m |
189 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 213 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
190 | CONFIG_IP6_NF_TARGET_NPT=m | 214 | CONFIG_IP6_NF_TARGET_NPT=m |
215 | CONFIG_NF_TABLES_BRIDGE=m | ||
191 | CONFIG_IP_DCCP=m | 216 | CONFIG_IP_DCCP=m |
192 | # CONFIG_IP_DCCP_CCID3 is not set | 217 | # CONFIG_IP_DCCP_CCID3 is not set |
193 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 218 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -195,10 +220,13 @@ CONFIG_RDS=m | |||
195 | CONFIG_RDS_TCP=m | 220 | CONFIG_RDS_TCP=m |
196 | CONFIG_L2TP=m | 221 | CONFIG_L2TP=m |
197 | CONFIG_ATALK=m | 222 | CONFIG_ATALK=m |
223 | CONFIG_DNS_RESOLVER=y | ||
198 | CONFIG_BATMAN_ADV=m | 224 | CONFIG_BATMAN_ADV=m |
199 | CONFIG_BATMAN_ADV_DAT=y | 225 | CONFIG_BATMAN_ADV_DAT=y |
226 | CONFIG_BATMAN_ADV_NC=y | ||
227 | CONFIG_NETLINK_DIAG=m | ||
228 | CONFIG_NET_MPLS_GSO=m | ||
200 | # CONFIG_WIRELESS is not set | 229 | # CONFIG_WIRELESS is not set |
201 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
202 | CONFIG_DEVTMPFS=y | 230 | CONFIG_DEVTMPFS=y |
203 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 231 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
204 | # CONFIG_FW_LOADER_USER_HELPER is not set | 232 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -216,6 +244,7 @@ CONFIG_BLK_DEV_NBD=m | |||
216 | CONFIG_BLK_DEV_RAM=y | 244 | CONFIG_BLK_DEV_RAM=y |
217 | CONFIG_CDROM_PKTCDVD=m | 245 | CONFIG_CDROM_PKTCDVD=m |
218 | CONFIG_ATA_OVER_ETH=m | 246 | CONFIG_ATA_OVER_ETH=m |
247 | CONFIG_DUMMY_IRQ=m | ||
219 | CONFIG_IDE=y | 248 | CONFIG_IDE=y |
220 | CONFIG_IDE_GD_ATAPI=y | 249 | CONFIG_IDE_GD_ATAPI=y |
221 | CONFIG_BLK_DEV_IDECD=y | 250 | CONFIG_BLK_DEV_IDECD=y |
@@ -262,6 +291,7 @@ CONFIG_EQUALIZER=m | |||
262 | CONFIG_NET_TEAM=m | 291 | CONFIG_NET_TEAM=m |
263 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 292 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
264 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 293 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
294 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
265 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 295 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
266 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 296 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
267 | CONFIG_VXLAN=m | 297 | CONFIG_VXLAN=m |
@@ -271,10 +301,10 @@ CONFIG_VETH=m | |||
271 | # CONFIG_NET_VENDOR_3COM is not set | 301 | # CONFIG_NET_VENDOR_3COM is not set |
272 | CONFIG_A2065=y | 302 | CONFIG_A2065=y |
273 | CONFIG_ARIADNE=y | 303 | CONFIG_ARIADNE=y |
304 | # CONFIG_NET_VENDOR_ARC is not set | ||
274 | # CONFIG_NET_CADENCE is not set | 305 | # CONFIG_NET_CADENCE is not set |
275 | # CONFIG_NET_VENDOR_BROADCOM is not set | 306 | # CONFIG_NET_VENDOR_BROADCOM is not set |
276 | # CONFIG_NET_VENDOR_CIRRUS is not set | 307 | # CONFIG_NET_VENDOR_CIRRUS is not set |
277 | # CONFIG_NET_VENDOR_FUJITSU is not set | ||
278 | # CONFIG_NET_VENDOR_HP is not set | 308 | # CONFIG_NET_VENDOR_HP is not set |
279 | # CONFIG_NET_VENDOR_INTEL is not set | 309 | # CONFIG_NET_VENDOR_INTEL is not set |
280 | # CONFIG_NET_VENDOR_MARVELL is not set | 310 | # CONFIG_NET_VENDOR_MARVELL is not set |
@@ -285,6 +315,7 @@ CONFIG_ZORRO8390=y | |||
285 | # CONFIG_NET_VENDOR_SEEQ is not set | 315 | # CONFIG_NET_VENDOR_SEEQ is not set |
286 | # CONFIG_NET_VENDOR_SMSC is not set | 316 | # CONFIG_NET_VENDOR_SMSC is not set |
287 | # CONFIG_NET_VENDOR_STMICRO is not set | 317 | # CONFIG_NET_VENDOR_STMICRO is not set |
318 | # CONFIG_NET_VENDOR_VIA is not set | ||
288 | # CONFIG_NET_VENDOR_WIZNET is not set | 319 | # CONFIG_NET_VENDOR_WIZNET is not set |
289 | CONFIG_PPP=m | 320 | CONFIG_PPP=m |
290 | CONFIG_PPP_BSDCOMP=m | 321 | CONFIG_PPP_BSDCOMP=m |
@@ -311,7 +342,6 @@ CONFIG_JOYSTICK_AMIGA=m | |||
311 | CONFIG_INPUT_MISC=y | 342 | CONFIG_INPUT_MISC=y |
312 | CONFIG_INPUT_M68K_BEEP=m | 343 | CONFIG_INPUT_M68K_BEEP=m |
313 | # CONFIG_SERIO is not set | 344 | # CONFIG_SERIO is not set |
314 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
315 | # CONFIG_LEGACY_PTYS is not set | 345 | # CONFIG_LEGACY_PTYS is not set |
316 | # CONFIG_DEVKMEM is not set | 346 | # CONFIG_DEVKMEM is not set |
317 | CONFIG_PRINTER=m | 347 | CONFIG_PRINTER=m |
@@ -345,10 +375,6 @@ CONFIG_HEARTBEAT=y | |||
345 | CONFIG_PROC_HARDWARE=y | 375 | CONFIG_PROC_HARDWARE=y |
346 | CONFIG_AMIGA_BUILTIN_SERIAL=y | 376 | CONFIG_AMIGA_BUILTIN_SERIAL=y |
347 | CONFIG_SERIAL_CONSOLE=y | 377 | CONFIG_SERIAL_CONSOLE=y |
348 | CONFIG_EXT2_FS=y | ||
349 | CONFIG_EXT3_FS=y | ||
350 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
351 | # CONFIG_EXT3_FS_XATTR is not set | ||
352 | CONFIG_EXT4_FS=y | 378 | CONFIG_EXT4_FS=y |
353 | CONFIG_REISERFS_FS=m | 379 | CONFIG_REISERFS_FS=m |
354 | CONFIG_JFS_FS=m | 380 | CONFIG_JFS_FS=m |
@@ -385,7 +411,7 @@ CONFIG_QNX6FS_FS=m | |||
385 | CONFIG_SYSV_FS=m | 411 | CONFIG_SYSV_FS=m |
386 | CONFIG_UFS_FS=m | 412 | CONFIG_UFS_FS=m |
387 | CONFIG_NFS_FS=y | 413 | CONFIG_NFS_FS=y |
388 | CONFIG_NFS_V4=y | 414 | CONFIG_NFS_V4=m |
389 | CONFIG_NFS_SWAP=y | 415 | CONFIG_NFS_SWAP=y |
390 | CONFIG_ROOT_NFS=y | 416 | CONFIG_ROOT_NFS=y |
391 | CONFIG_NFSD=m | 417 | CONFIG_NFSD=m |
@@ -444,10 +470,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
444 | CONFIG_DLM=m | 470 | CONFIG_DLM=m |
445 | CONFIG_MAGIC_SYSRQ=y | 471 | CONFIG_MAGIC_SYSRQ=y |
446 | CONFIG_ASYNC_RAID6_TEST=m | 472 | CONFIG_ASYNC_RAID6_TEST=m |
473 | CONFIG_TEST_STRING_HELPERS=m | ||
447 | CONFIG_ENCRYPTED_KEYS=m | 474 | CONFIG_ENCRYPTED_KEYS=m |
448 | CONFIG_CRYPTO_MANAGER=y | 475 | CONFIG_CRYPTO_MANAGER=y |
449 | CONFIG_CRYPTO_USER=m | 476 | CONFIG_CRYPTO_USER=m |
450 | CONFIG_CRYPTO_NULL=m | ||
451 | CONFIG_CRYPTO_CRYPTD=m | 477 | CONFIG_CRYPTO_CRYPTD=m |
452 | CONFIG_CRYPTO_TEST=m | 478 | CONFIG_CRYPTO_TEST=m |
453 | CONFIG_CRYPTO_CCM=m | 479 | CONFIG_CRYPTO_CCM=m |
@@ -480,6 +506,8 @@ CONFIG_CRYPTO_TEA=m | |||
480 | CONFIG_CRYPTO_TWOFISH=m | 506 | CONFIG_CRYPTO_TWOFISH=m |
481 | CONFIG_CRYPTO_ZLIB=m | 507 | CONFIG_CRYPTO_ZLIB=m |
482 | CONFIG_CRYPTO_LZO=m | 508 | CONFIG_CRYPTO_LZO=m |
509 | CONFIG_CRYPTO_LZ4=m | ||
510 | CONFIG_CRYPTO_LZ4HC=m | ||
483 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 511 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
484 | CONFIG_CRYPTO_USER_API_HASH=m | 512 | CONFIG_CRYPTO_USER_API_HASH=m |
485 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 513 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 14dc6ccda7f4..cb1f55df69b6 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig | |||
@@ -50,7 +50,6 @@ CONFIG_IP_PNP_RARP=y | |||
50 | CONFIG_NET_IPIP=m | 50 | CONFIG_NET_IPIP=m |
51 | CONFIG_NET_IPGRE_DEMUX=m | 51 | CONFIG_NET_IPGRE_DEMUX=m |
52 | CONFIG_NET_IPGRE=m | 52 | CONFIG_NET_IPGRE=m |
53 | CONFIG_SYN_COOKIES=y | ||
54 | CONFIG_NET_IPVTI=m | 53 | CONFIG_NET_IPVTI=m |
55 | CONFIG_INET_AH=m | 54 | CONFIG_INET_AH=m |
56 | CONFIG_INET_ESP=m | 55 | CONFIG_INET_ESP=m |
@@ -61,11 +60,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
61 | # CONFIG_INET_LRO is not set | 60 | # CONFIG_INET_LRO is not set |
62 | CONFIG_INET_DIAG=m | 61 | CONFIG_INET_DIAG=m |
63 | CONFIG_INET_UDP_DIAG=m | 62 | CONFIG_INET_UDP_DIAG=m |
64 | CONFIG_IPV6_PRIVACY=y | ||
65 | CONFIG_IPV6_ROUTER_PREF=y | 63 | CONFIG_IPV6_ROUTER_PREF=y |
66 | CONFIG_INET6_AH=m | 64 | CONFIG_INET6_AH=m |
67 | CONFIG_INET6_ESP=m | 65 | CONFIG_INET6_ESP=m |
68 | CONFIG_INET6_IPCOMP=m | 66 | CONFIG_INET6_IPCOMP=m |
67 | CONFIG_IPV6_VTI=m | ||
69 | CONFIG_IPV6_GRE=m | 68 | CONFIG_IPV6_GRE=m |
70 | CONFIG_NETFILTER=y | 69 | CONFIG_NETFILTER=y |
71 | CONFIG_NF_CONNTRACK=m | 70 | CONFIG_NF_CONNTRACK=m |
@@ -83,6 +82,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
83 | CONFIG_NF_CONNTRACK_SANE=m | 82 | CONFIG_NF_CONNTRACK_SANE=m |
84 | CONFIG_NF_CONNTRACK_SIP=m | 83 | CONFIG_NF_CONNTRACK_SIP=m |
85 | CONFIG_NF_CONNTRACK_TFTP=m | 84 | CONFIG_NF_CONNTRACK_TFTP=m |
85 | CONFIG_NF_TABLES=m | ||
86 | CONFIG_NFT_EXTHDR=m | ||
87 | CONFIG_NFT_META=m | ||
88 | CONFIG_NFT_CT=m | ||
89 | CONFIG_NFT_RBTREE=m | ||
90 | CONFIG_NFT_HASH=m | ||
91 | CONFIG_NFT_COUNTER=m | ||
92 | CONFIG_NFT_LOG=m | ||
93 | CONFIG_NFT_LIMIT=m | ||
94 | CONFIG_NFT_NAT=m | ||
95 | CONFIG_NFT_COMPAT=m | ||
86 | CONFIG_NETFILTER_XT_SET=m | 96 | CONFIG_NETFILTER_XT_SET=m |
87 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 97 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
88 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 98 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -96,6 +106,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
96 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 106 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
97 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 107 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
98 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 108 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
109 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
99 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 110 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
100 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 111 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
101 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 112 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -128,6 +139,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
128 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 139 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
129 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 140 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
130 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 141 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
142 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
131 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 143 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
132 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 144 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
133 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 145 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -142,11 +154,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
142 | CONFIG_IP_SET_HASH_IPPORT=m | 154 | CONFIG_IP_SET_HASH_IPPORT=m |
143 | CONFIG_IP_SET_HASH_IPPORTIP=m | 155 | CONFIG_IP_SET_HASH_IPPORTIP=m |
144 | CONFIG_IP_SET_HASH_IPPORTNET=m | 156 | CONFIG_IP_SET_HASH_IPPORTNET=m |
157 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
145 | CONFIG_IP_SET_HASH_NET=m | 158 | CONFIG_IP_SET_HASH_NET=m |
159 | CONFIG_IP_SET_HASH_NETNET=m | ||
146 | CONFIG_IP_SET_HASH_NETPORT=m | 160 | CONFIG_IP_SET_HASH_NETPORT=m |
147 | CONFIG_IP_SET_HASH_NETIFACE=m | 161 | CONFIG_IP_SET_HASH_NETIFACE=m |
148 | CONFIG_IP_SET_LIST_SET=m | 162 | CONFIG_IP_SET_LIST_SET=m |
149 | CONFIG_NF_CONNTRACK_IPV4=m | 163 | CONFIG_NF_CONNTRACK_IPV4=m |
164 | CONFIG_NF_TABLES_IPV4=m | ||
165 | CONFIG_NFT_REJECT_IPV4=m | ||
166 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
167 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
168 | CONFIG_NF_TABLES_ARP=m | ||
150 | CONFIG_IP_NF_IPTABLES=m | 169 | CONFIG_IP_NF_IPTABLES=m |
151 | CONFIG_IP_NF_MATCH_AH=m | 170 | CONFIG_IP_NF_MATCH_AH=m |
152 | CONFIG_IP_NF_MATCH_ECN=m | 171 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -154,6 +173,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
154 | CONFIG_IP_NF_MATCH_TTL=m | 173 | CONFIG_IP_NF_MATCH_TTL=m |
155 | CONFIG_IP_NF_FILTER=m | 174 | CONFIG_IP_NF_FILTER=m |
156 | CONFIG_IP_NF_TARGET_REJECT=m | 175 | CONFIG_IP_NF_TARGET_REJECT=m |
176 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
157 | CONFIG_IP_NF_TARGET_ULOG=m | 177 | CONFIG_IP_NF_TARGET_ULOG=m |
158 | CONFIG_NF_NAT_IPV4=m | 178 | CONFIG_NF_NAT_IPV4=m |
159 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 179 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -168,6 +188,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
168 | CONFIG_IP_NF_ARPFILTER=m | 188 | CONFIG_IP_NF_ARPFILTER=m |
169 | CONFIG_IP_NF_ARP_MANGLE=m | 189 | CONFIG_IP_NF_ARP_MANGLE=m |
170 | CONFIG_NF_CONNTRACK_IPV6=m | 190 | CONFIG_NF_CONNTRACK_IPV6=m |
191 | CONFIG_NF_TABLES_IPV6=m | ||
192 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
193 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
171 | CONFIG_IP6_NF_IPTABLES=m | 194 | CONFIG_IP6_NF_IPTABLES=m |
172 | CONFIG_IP6_NF_MATCH_AH=m | 195 | CONFIG_IP6_NF_MATCH_AH=m |
173 | CONFIG_IP6_NF_MATCH_EUI64=m | 196 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -181,11 +204,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
181 | CONFIG_IP6_NF_TARGET_HL=m | 204 | CONFIG_IP6_NF_TARGET_HL=m |
182 | CONFIG_IP6_NF_FILTER=m | 205 | CONFIG_IP6_NF_FILTER=m |
183 | CONFIG_IP6_NF_TARGET_REJECT=m | 206 | CONFIG_IP6_NF_TARGET_REJECT=m |
207 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
184 | CONFIG_IP6_NF_MANGLE=m | 208 | CONFIG_IP6_NF_MANGLE=m |
185 | CONFIG_IP6_NF_RAW=m | 209 | CONFIG_IP6_NF_RAW=m |
186 | CONFIG_NF_NAT_IPV6=m | 210 | CONFIG_NF_NAT_IPV6=m |
187 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 211 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
188 | CONFIG_IP6_NF_TARGET_NPT=m | 212 | CONFIG_IP6_NF_TARGET_NPT=m |
213 | CONFIG_NF_TABLES_BRIDGE=m | ||
189 | CONFIG_IP_DCCP=m | 214 | CONFIG_IP_DCCP=m |
190 | # CONFIG_IP_DCCP_CCID3 is not set | 215 | # CONFIG_IP_DCCP_CCID3 is not set |
191 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 216 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -193,10 +218,13 @@ CONFIG_RDS=m | |||
193 | CONFIG_RDS_TCP=m | 218 | CONFIG_RDS_TCP=m |
194 | CONFIG_L2TP=m | 219 | CONFIG_L2TP=m |
195 | CONFIG_ATALK=m | 220 | CONFIG_ATALK=m |
221 | CONFIG_DNS_RESOLVER=y | ||
196 | CONFIG_BATMAN_ADV=m | 222 | CONFIG_BATMAN_ADV=m |
197 | CONFIG_BATMAN_ADV_DAT=y | 223 | CONFIG_BATMAN_ADV_DAT=y |
224 | CONFIG_BATMAN_ADV_NC=y | ||
225 | CONFIG_NETLINK_DIAG=m | ||
226 | CONFIG_NET_MPLS_GSO=m | ||
198 | # CONFIG_WIRELESS is not set | 227 | # CONFIG_WIRELESS is not set |
199 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
200 | CONFIG_DEVTMPFS=y | 228 | CONFIG_DEVTMPFS=y |
201 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 229 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
202 | # CONFIG_FW_LOADER_USER_HELPER is not set | 230 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -208,6 +236,7 @@ CONFIG_BLK_DEV_NBD=m | |||
208 | CONFIG_BLK_DEV_RAM=y | 236 | CONFIG_BLK_DEV_RAM=y |
209 | CONFIG_CDROM_PKTCDVD=m | 237 | CONFIG_CDROM_PKTCDVD=m |
210 | CONFIG_ATA_OVER_ETH=m | 238 | CONFIG_ATA_OVER_ETH=m |
239 | CONFIG_DUMMY_IRQ=m | ||
211 | CONFIG_RAID_ATTRS=m | 240 | CONFIG_RAID_ATTRS=m |
212 | CONFIG_SCSI=y | 241 | CONFIG_SCSI=y |
213 | CONFIG_SCSI_TGT=m | 242 | CONFIG_SCSI_TGT=m |
@@ -244,12 +273,14 @@ CONFIG_EQUALIZER=m | |||
244 | CONFIG_NET_TEAM=m | 273 | CONFIG_NET_TEAM=m |
245 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 274 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
246 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 275 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
276 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
247 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 277 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
248 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 278 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
249 | CONFIG_VXLAN=m | 279 | CONFIG_VXLAN=m |
250 | CONFIG_NETCONSOLE=m | 280 | CONFIG_NETCONSOLE=m |
251 | CONFIG_NETCONSOLE_DYNAMIC=y | 281 | CONFIG_NETCONSOLE_DYNAMIC=y |
252 | CONFIG_VETH=m | 282 | CONFIG_VETH=m |
283 | # CONFIG_NET_VENDOR_ARC is not set | ||
253 | # CONFIG_NET_CADENCE is not set | 284 | # CONFIG_NET_CADENCE is not set |
254 | # CONFIG_NET_VENDOR_BROADCOM is not set | 285 | # CONFIG_NET_VENDOR_BROADCOM is not set |
255 | # CONFIG_NET_VENDOR_INTEL is not set | 286 | # CONFIG_NET_VENDOR_INTEL is not set |
@@ -258,6 +289,7 @@ CONFIG_VETH=m | |||
258 | # CONFIG_NET_VENDOR_NATSEMI is not set | 289 | # CONFIG_NET_VENDOR_NATSEMI is not set |
259 | # CONFIG_NET_VENDOR_SEEQ is not set | 290 | # CONFIG_NET_VENDOR_SEEQ is not set |
260 | # CONFIG_NET_VENDOR_STMICRO is not set | 291 | # CONFIG_NET_VENDOR_STMICRO is not set |
292 | # CONFIG_NET_VENDOR_VIA is not set | ||
261 | # CONFIG_NET_VENDOR_WIZNET is not set | 293 | # CONFIG_NET_VENDOR_WIZNET is not set |
262 | CONFIG_PPP=m | 294 | CONFIG_PPP=m |
263 | CONFIG_PPP_BSDCOMP=m | 295 | CONFIG_PPP_BSDCOMP=m |
@@ -279,7 +311,6 @@ CONFIG_INPUT_EVDEV=m | |||
279 | # CONFIG_MOUSE_PS2 is not set | 311 | # CONFIG_MOUSE_PS2 is not set |
280 | CONFIG_MOUSE_SERIAL=m | 312 | CONFIG_MOUSE_SERIAL=m |
281 | CONFIG_SERIO=m | 313 | CONFIG_SERIO=m |
282 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
283 | # CONFIG_LEGACY_PTYS is not set | 314 | # CONFIG_LEGACY_PTYS is not set |
284 | # CONFIG_DEVKMEM is not set | 315 | # CONFIG_DEVKMEM is not set |
285 | # CONFIG_HW_RANDOM is not set | 316 | # CONFIG_HW_RANDOM is not set |
@@ -302,10 +333,6 @@ CONFIG_RTC_DRV_GENERIC=m | |||
302 | # CONFIG_IOMMU_SUPPORT is not set | 333 | # CONFIG_IOMMU_SUPPORT is not set |
303 | CONFIG_HEARTBEAT=y | 334 | CONFIG_HEARTBEAT=y |
304 | CONFIG_PROC_HARDWARE=y | 335 | CONFIG_PROC_HARDWARE=y |
305 | CONFIG_EXT2_FS=y | ||
306 | CONFIG_EXT3_FS=y | ||
307 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
308 | # CONFIG_EXT3_FS_XATTR is not set | ||
309 | CONFIG_EXT4_FS=y | 336 | CONFIG_EXT4_FS=y |
310 | CONFIG_REISERFS_FS=m | 337 | CONFIG_REISERFS_FS=m |
311 | CONFIG_JFS_FS=m | 338 | CONFIG_JFS_FS=m |
@@ -342,7 +369,7 @@ CONFIG_QNX6FS_FS=m | |||
342 | CONFIG_SYSV_FS=m | 369 | CONFIG_SYSV_FS=m |
343 | CONFIG_UFS_FS=m | 370 | CONFIG_UFS_FS=m |
344 | CONFIG_NFS_FS=y | 371 | CONFIG_NFS_FS=y |
345 | CONFIG_NFS_V4=y | 372 | CONFIG_NFS_V4=m |
346 | CONFIG_NFS_SWAP=y | 373 | CONFIG_NFS_SWAP=y |
347 | CONFIG_ROOT_NFS=y | 374 | CONFIG_ROOT_NFS=y |
348 | CONFIG_NFSD=m | 375 | CONFIG_NFSD=m |
@@ -401,10 +428,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
401 | CONFIG_DLM=m | 428 | CONFIG_DLM=m |
402 | CONFIG_MAGIC_SYSRQ=y | 429 | CONFIG_MAGIC_SYSRQ=y |
403 | CONFIG_ASYNC_RAID6_TEST=m | 430 | CONFIG_ASYNC_RAID6_TEST=m |
431 | CONFIG_TEST_STRING_HELPERS=m | ||
404 | CONFIG_ENCRYPTED_KEYS=m | 432 | CONFIG_ENCRYPTED_KEYS=m |
405 | CONFIG_CRYPTO_MANAGER=y | 433 | CONFIG_CRYPTO_MANAGER=y |
406 | CONFIG_CRYPTO_USER=m | 434 | CONFIG_CRYPTO_USER=m |
407 | CONFIG_CRYPTO_NULL=m | ||
408 | CONFIG_CRYPTO_CRYPTD=m | 435 | CONFIG_CRYPTO_CRYPTD=m |
409 | CONFIG_CRYPTO_TEST=m | 436 | CONFIG_CRYPTO_TEST=m |
410 | CONFIG_CRYPTO_CCM=m | 437 | CONFIG_CRYPTO_CCM=m |
@@ -437,6 +464,8 @@ CONFIG_CRYPTO_TEA=m | |||
437 | CONFIG_CRYPTO_TWOFISH=m | 464 | CONFIG_CRYPTO_TWOFISH=m |
438 | CONFIG_CRYPTO_ZLIB=m | 465 | CONFIG_CRYPTO_ZLIB=m |
439 | CONFIG_CRYPTO_LZO=m | 466 | CONFIG_CRYPTO_LZO=m |
467 | CONFIG_CRYPTO_LZ4=m | ||
468 | CONFIG_CRYPTO_LZ4HC=m | ||
440 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 469 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
441 | CONFIG_CRYPTO_USER_API_HASH=m | 470 | CONFIG_CRYPTO_USER_API_HASH=m |
442 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 471 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 6d5370c914b2..e880cfbb62d9 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig | |||
@@ -49,7 +49,6 @@ CONFIG_IP_PNP_RARP=y | |||
49 | CONFIG_NET_IPIP=m | 49 | CONFIG_NET_IPIP=m |
50 | CONFIG_NET_IPGRE_DEMUX=m | 50 | CONFIG_NET_IPGRE_DEMUX=m |
51 | CONFIG_NET_IPGRE=m | 51 | CONFIG_NET_IPGRE=m |
52 | CONFIG_SYN_COOKIES=y | ||
53 | CONFIG_NET_IPVTI=m | 52 | CONFIG_NET_IPVTI=m |
54 | CONFIG_INET_AH=m | 53 | CONFIG_INET_AH=m |
55 | CONFIG_INET_ESP=m | 54 | CONFIG_INET_ESP=m |
@@ -60,11 +59,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
60 | # CONFIG_INET_LRO is not set | 59 | # CONFIG_INET_LRO is not set |
61 | CONFIG_INET_DIAG=m | 60 | CONFIG_INET_DIAG=m |
62 | CONFIG_INET_UDP_DIAG=m | 61 | CONFIG_INET_UDP_DIAG=m |
63 | CONFIG_IPV6_PRIVACY=y | ||
64 | CONFIG_IPV6_ROUTER_PREF=y | 62 | CONFIG_IPV6_ROUTER_PREF=y |
65 | CONFIG_INET6_AH=m | 63 | CONFIG_INET6_AH=m |
66 | CONFIG_INET6_ESP=m | 64 | CONFIG_INET6_ESP=m |
67 | CONFIG_INET6_IPCOMP=m | 65 | CONFIG_INET6_IPCOMP=m |
66 | CONFIG_IPV6_VTI=m | ||
68 | CONFIG_IPV6_GRE=m | 67 | CONFIG_IPV6_GRE=m |
69 | CONFIG_NETFILTER=y | 68 | CONFIG_NETFILTER=y |
70 | CONFIG_NF_CONNTRACK=m | 69 | CONFIG_NF_CONNTRACK=m |
@@ -82,6 +81,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
82 | CONFIG_NF_CONNTRACK_SANE=m | 81 | CONFIG_NF_CONNTRACK_SANE=m |
83 | CONFIG_NF_CONNTRACK_SIP=m | 82 | CONFIG_NF_CONNTRACK_SIP=m |
84 | CONFIG_NF_CONNTRACK_TFTP=m | 83 | CONFIG_NF_CONNTRACK_TFTP=m |
84 | CONFIG_NF_TABLES=m | ||
85 | CONFIG_NFT_EXTHDR=m | ||
86 | CONFIG_NFT_META=m | ||
87 | CONFIG_NFT_CT=m | ||
88 | CONFIG_NFT_RBTREE=m | ||
89 | CONFIG_NFT_HASH=m | ||
90 | CONFIG_NFT_COUNTER=m | ||
91 | CONFIG_NFT_LOG=m | ||
92 | CONFIG_NFT_LIMIT=m | ||
93 | CONFIG_NFT_NAT=m | ||
94 | CONFIG_NFT_COMPAT=m | ||
85 | CONFIG_NETFILTER_XT_SET=m | 95 | CONFIG_NETFILTER_XT_SET=m |
86 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 96 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
87 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 97 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -95,6 +105,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
95 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 105 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
96 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 106 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
97 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 107 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
108 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
98 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 109 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
99 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 110 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
100 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 111 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -127,6 +138,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
127 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 138 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
128 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 139 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
129 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 140 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
141 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
130 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 142 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
131 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 143 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
132 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 144 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -141,11 +153,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
141 | CONFIG_IP_SET_HASH_IPPORT=m | 153 | CONFIG_IP_SET_HASH_IPPORT=m |
142 | CONFIG_IP_SET_HASH_IPPORTIP=m | 154 | CONFIG_IP_SET_HASH_IPPORTIP=m |
143 | CONFIG_IP_SET_HASH_IPPORTNET=m | 155 | CONFIG_IP_SET_HASH_IPPORTNET=m |
156 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
144 | CONFIG_IP_SET_HASH_NET=m | 157 | CONFIG_IP_SET_HASH_NET=m |
158 | CONFIG_IP_SET_HASH_NETNET=m | ||
145 | CONFIG_IP_SET_HASH_NETPORT=m | 159 | CONFIG_IP_SET_HASH_NETPORT=m |
146 | CONFIG_IP_SET_HASH_NETIFACE=m | 160 | CONFIG_IP_SET_HASH_NETIFACE=m |
147 | CONFIG_IP_SET_LIST_SET=m | 161 | CONFIG_IP_SET_LIST_SET=m |
148 | CONFIG_NF_CONNTRACK_IPV4=m | 162 | CONFIG_NF_CONNTRACK_IPV4=m |
163 | CONFIG_NF_TABLES_IPV4=m | ||
164 | CONFIG_NFT_REJECT_IPV4=m | ||
165 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
166 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
167 | CONFIG_NF_TABLES_ARP=m | ||
149 | CONFIG_IP_NF_IPTABLES=m | 168 | CONFIG_IP_NF_IPTABLES=m |
150 | CONFIG_IP_NF_MATCH_AH=m | 169 | CONFIG_IP_NF_MATCH_AH=m |
151 | CONFIG_IP_NF_MATCH_ECN=m | 170 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -153,6 +172,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
153 | CONFIG_IP_NF_MATCH_TTL=m | 172 | CONFIG_IP_NF_MATCH_TTL=m |
154 | CONFIG_IP_NF_FILTER=m | 173 | CONFIG_IP_NF_FILTER=m |
155 | CONFIG_IP_NF_TARGET_REJECT=m | 174 | CONFIG_IP_NF_TARGET_REJECT=m |
175 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
156 | CONFIG_IP_NF_TARGET_ULOG=m | 176 | CONFIG_IP_NF_TARGET_ULOG=m |
157 | CONFIG_NF_NAT_IPV4=m | 177 | CONFIG_NF_NAT_IPV4=m |
158 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 178 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -167,6 +187,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
167 | CONFIG_IP_NF_ARPFILTER=m | 187 | CONFIG_IP_NF_ARPFILTER=m |
168 | CONFIG_IP_NF_ARP_MANGLE=m | 188 | CONFIG_IP_NF_ARP_MANGLE=m |
169 | CONFIG_NF_CONNTRACK_IPV6=m | 189 | CONFIG_NF_CONNTRACK_IPV6=m |
190 | CONFIG_NF_TABLES_IPV6=m | ||
191 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
192 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
170 | CONFIG_IP6_NF_IPTABLES=m | 193 | CONFIG_IP6_NF_IPTABLES=m |
171 | CONFIG_IP6_NF_MATCH_AH=m | 194 | CONFIG_IP6_NF_MATCH_AH=m |
172 | CONFIG_IP6_NF_MATCH_EUI64=m | 195 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -180,11 +203,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
180 | CONFIG_IP6_NF_TARGET_HL=m | 203 | CONFIG_IP6_NF_TARGET_HL=m |
181 | CONFIG_IP6_NF_FILTER=m | 204 | CONFIG_IP6_NF_FILTER=m |
182 | CONFIG_IP6_NF_TARGET_REJECT=m | 205 | CONFIG_IP6_NF_TARGET_REJECT=m |
206 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
183 | CONFIG_IP6_NF_MANGLE=m | 207 | CONFIG_IP6_NF_MANGLE=m |
184 | CONFIG_IP6_NF_RAW=m | 208 | CONFIG_IP6_NF_RAW=m |
185 | CONFIG_NF_NAT_IPV6=m | 209 | CONFIG_NF_NAT_IPV6=m |
186 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 210 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
187 | CONFIG_IP6_NF_TARGET_NPT=m | 211 | CONFIG_IP6_NF_TARGET_NPT=m |
212 | CONFIG_NF_TABLES_BRIDGE=m | ||
188 | CONFIG_IP_DCCP=m | 213 | CONFIG_IP_DCCP=m |
189 | # CONFIG_IP_DCCP_CCID3 is not set | 214 | # CONFIG_IP_DCCP_CCID3 is not set |
190 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 215 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -192,10 +217,13 @@ CONFIG_RDS=m | |||
192 | CONFIG_RDS_TCP=m | 217 | CONFIG_RDS_TCP=m |
193 | CONFIG_L2TP=m | 218 | CONFIG_L2TP=m |
194 | CONFIG_ATALK=m | 219 | CONFIG_ATALK=m |
220 | CONFIG_DNS_RESOLVER=y | ||
195 | CONFIG_BATMAN_ADV=m | 221 | CONFIG_BATMAN_ADV=m |
196 | CONFIG_BATMAN_ADV_DAT=y | 222 | CONFIG_BATMAN_ADV_DAT=y |
223 | CONFIG_BATMAN_ADV_NC=y | ||
224 | CONFIG_NETLINK_DIAG=m | ||
225 | CONFIG_NET_MPLS_GSO=m | ||
197 | # CONFIG_WIRELESS is not set | 226 | # CONFIG_WIRELESS is not set |
198 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
199 | CONFIG_DEVTMPFS=y | 227 | CONFIG_DEVTMPFS=y |
200 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 228 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
201 | # CONFIG_FW_LOADER_USER_HELPER is not set | 229 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -211,6 +239,7 @@ CONFIG_BLK_DEV_NBD=m | |||
211 | CONFIG_BLK_DEV_RAM=y | 239 | CONFIG_BLK_DEV_RAM=y |
212 | CONFIG_CDROM_PKTCDVD=m | 240 | CONFIG_CDROM_PKTCDVD=m |
213 | CONFIG_ATA_OVER_ETH=m | 241 | CONFIG_ATA_OVER_ETH=m |
242 | CONFIG_DUMMY_IRQ=m | ||
214 | CONFIG_IDE=y | 243 | CONFIG_IDE=y |
215 | CONFIG_IDE_GD_ATAPI=y | 244 | CONFIG_IDE_GD_ATAPI=y |
216 | CONFIG_BLK_DEV_IDECD=y | 245 | CONFIG_BLK_DEV_IDECD=y |
@@ -249,10 +278,10 @@ CONFIG_TCM_PSCSI=m | |||
249 | CONFIG_NETDEVICES=y | 278 | CONFIG_NETDEVICES=y |
250 | CONFIG_DUMMY=m | 279 | CONFIG_DUMMY=m |
251 | CONFIG_EQUALIZER=m | 280 | CONFIG_EQUALIZER=m |
252 | CONFIG_MII=y | ||
253 | CONFIG_NET_TEAM=m | 281 | CONFIG_NET_TEAM=m |
254 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 282 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
255 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 283 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
284 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
256 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 285 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
257 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 286 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
258 | CONFIG_VXLAN=m | 287 | CONFIG_VXLAN=m |
@@ -260,6 +289,7 @@ CONFIG_NETCONSOLE=m | |||
260 | CONFIG_NETCONSOLE_DYNAMIC=y | 289 | CONFIG_NETCONSOLE_DYNAMIC=y |
261 | CONFIG_VETH=m | 290 | CONFIG_VETH=m |
262 | CONFIG_ATARILANCE=y | 291 | CONFIG_ATARILANCE=y |
292 | # CONFIG_NET_VENDOR_ARC is not set | ||
263 | # CONFIG_NET_CADENCE is not set | 293 | # CONFIG_NET_CADENCE is not set |
264 | # CONFIG_NET_VENDOR_BROADCOM is not set | 294 | # CONFIG_NET_VENDOR_BROADCOM is not set |
265 | # CONFIG_NET_VENDOR_INTEL is not set | 295 | # CONFIG_NET_VENDOR_INTEL is not set |
@@ -267,6 +297,7 @@ CONFIG_ATARILANCE=y | |||
267 | # CONFIG_NET_VENDOR_MICREL is not set | 297 | # CONFIG_NET_VENDOR_MICREL is not set |
268 | # CONFIG_NET_VENDOR_SEEQ is not set | 298 | # CONFIG_NET_VENDOR_SEEQ is not set |
269 | # CONFIG_NET_VENDOR_STMICRO is not set | 299 | # CONFIG_NET_VENDOR_STMICRO is not set |
300 | # CONFIG_NET_VENDOR_VIA is not set | ||
270 | # CONFIG_NET_VENDOR_WIZNET is not set | 301 | # CONFIG_NET_VENDOR_WIZNET is not set |
271 | CONFIG_PPP=m | 302 | CONFIG_PPP=m |
272 | CONFIG_PPP_BSDCOMP=m | 303 | CONFIG_PPP_BSDCOMP=m |
@@ -291,7 +322,6 @@ CONFIG_MOUSE_ATARI=m | |||
291 | CONFIG_INPUT_MISC=y | 322 | CONFIG_INPUT_MISC=y |
292 | CONFIG_INPUT_M68K_BEEP=m | 323 | CONFIG_INPUT_M68K_BEEP=m |
293 | # CONFIG_SERIO is not set | 324 | # CONFIG_SERIO is not set |
294 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
295 | # CONFIG_LEGACY_PTYS is not set | 325 | # CONFIG_LEGACY_PTYS is not set |
296 | # CONFIG_DEVKMEM is not set | 326 | # CONFIG_DEVKMEM is not set |
297 | CONFIG_PRINTER=m | 327 | CONFIG_PRINTER=m |
@@ -320,10 +350,6 @@ CONFIG_NFBLOCK=y | |||
320 | CONFIG_NFCON=y | 350 | CONFIG_NFCON=y |
321 | CONFIG_NFETH=y | 351 | CONFIG_NFETH=y |
322 | CONFIG_ATARI_DSP56K=m | 352 | CONFIG_ATARI_DSP56K=m |
323 | CONFIG_EXT2_FS=y | ||
324 | CONFIG_EXT3_FS=y | ||
325 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
326 | # CONFIG_EXT3_FS_XATTR is not set | ||
327 | CONFIG_EXT4_FS=y | 353 | CONFIG_EXT4_FS=y |
328 | CONFIG_REISERFS_FS=m | 354 | CONFIG_REISERFS_FS=m |
329 | CONFIG_JFS_FS=m | 355 | CONFIG_JFS_FS=m |
@@ -360,7 +386,7 @@ CONFIG_QNX6FS_FS=m | |||
360 | CONFIG_SYSV_FS=m | 386 | CONFIG_SYSV_FS=m |
361 | CONFIG_UFS_FS=m | 387 | CONFIG_UFS_FS=m |
362 | CONFIG_NFS_FS=y | 388 | CONFIG_NFS_FS=y |
363 | CONFIG_NFS_V4=y | 389 | CONFIG_NFS_V4=m |
364 | CONFIG_NFS_SWAP=y | 390 | CONFIG_NFS_SWAP=y |
365 | CONFIG_ROOT_NFS=y | 391 | CONFIG_ROOT_NFS=y |
366 | CONFIG_NFSD=m | 392 | CONFIG_NFSD=m |
@@ -419,10 +445,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
419 | CONFIG_DLM=m | 445 | CONFIG_DLM=m |
420 | CONFIG_MAGIC_SYSRQ=y | 446 | CONFIG_MAGIC_SYSRQ=y |
421 | CONFIG_ASYNC_RAID6_TEST=m | 447 | CONFIG_ASYNC_RAID6_TEST=m |
448 | CONFIG_TEST_STRING_HELPERS=m | ||
422 | CONFIG_ENCRYPTED_KEYS=m | 449 | CONFIG_ENCRYPTED_KEYS=m |
423 | CONFIG_CRYPTO_MANAGER=y | 450 | CONFIG_CRYPTO_MANAGER=y |
424 | CONFIG_CRYPTO_USER=m | 451 | CONFIG_CRYPTO_USER=m |
425 | CONFIG_CRYPTO_NULL=m | ||
426 | CONFIG_CRYPTO_CRYPTD=m | 452 | CONFIG_CRYPTO_CRYPTD=m |
427 | CONFIG_CRYPTO_TEST=m | 453 | CONFIG_CRYPTO_TEST=m |
428 | CONFIG_CRYPTO_CCM=m | 454 | CONFIG_CRYPTO_CCM=m |
@@ -455,6 +481,8 @@ CONFIG_CRYPTO_TEA=m | |||
455 | CONFIG_CRYPTO_TWOFISH=m | 481 | CONFIG_CRYPTO_TWOFISH=m |
456 | CONFIG_CRYPTO_ZLIB=m | 482 | CONFIG_CRYPTO_ZLIB=m |
457 | CONFIG_CRYPTO_LZO=m | 483 | CONFIG_CRYPTO_LZO=m |
484 | CONFIG_CRYPTO_LZ4=m | ||
485 | CONFIG_CRYPTO_LZ4HC=m | ||
458 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 486 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
459 | CONFIG_CRYPTO_USER_API_HASH=m | 487 | CONFIG_CRYPTO_USER_API_HASH=m |
460 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 488 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index c015ddb6fd80..4aa4f45e52a8 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig | |||
@@ -48,7 +48,6 @@ CONFIG_IP_PNP_RARP=y | |||
48 | CONFIG_NET_IPIP=m | 48 | CONFIG_NET_IPIP=m |
49 | CONFIG_NET_IPGRE_DEMUX=m | 49 | CONFIG_NET_IPGRE_DEMUX=m |
50 | CONFIG_NET_IPGRE=m | 50 | CONFIG_NET_IPGRE=m |
51 | CONFIG_SYN_COOKIES=y | ||
52 | CONFIG_NET_IPVTI=m | 51 | CONFIG_NET_IPVTI=m |
53 | CONFIG_INET_AH=m | 52 | CONFIG_INET_AH=m |
54 | CONFIG_INET_ESP=m | 53 | CONFIG_INET_ESP=m |
@@ -59,11 +58,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
59 | # CONFIG_INET_LRO is not set | 58 | # CONFIG_INET_LRO is not set |
60 | CONFIG_INET_DIAG=m | 59 | CONFIG_INET_DIAG=m |
61 | CONFIG_INET_UDP_DIAG=m | 60 | CONFIG_INET_UDP_DIAG=m |
62 | CONFIG_IPV6_PRIVACY=y | ||
63 | CONFIG_IPV6_ROUTER_PREF=y | 61 | CONFIG_IPV6_ROUTER_PREF=y |
64 | CONFIG_INET6_AH=m | 62 | CONFIG_INET6_AH=m |
65 | CONFIG_INET6_ESP=m | 63 | CONFIG_INET6_ESP=m |
66 | CONFIG_INET6_IPCOMP=m | 64 | CONFIG_INET6_IPCOMP=m |
65 | CONFIG_IPV6_VTI=m | ||
67 | CONFIG_IPV6_GRE=m | 66 | CONFIG_IPV6_GRE=m |
68 | CONFIG_NETFILTER=y | 67 | CONFIG_NETFILTER=y |
69 | CONFIG_NF_CONNTRACK=m | 68 | CONFIG_NF_CONNTRACK=m |
@@ -81,6 +80,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
81 | CONFIG_NF_CONNTRACK_SANE=m | 80 | CONFIG_NF_CONNTRACK_SANE=m |
82 | CONFIG_NF_CONNTRACK_SIP=m | 81 | CONFIG_NF_CONNTRACK_SIP=m |
83 | CONFIG_NF_CONNTRACK_TFTP=m | 82 | CONFIG_NF_CONNTRACK_TFTP=m |
83 | CONFIG_NF_TABLES=m | ||
84 | CONFIG_NFT_EXTHDR=m | ||
85 | CONFIG_NFT_META=m | ||
86 | CONFIG_NFT_CT=m | ||
87 | CONFIG_NFT_RBTREE=m | ||
88 | CONFIG_NFT_HASH=m | ||
89 | CONFIG_NFT_COUNTER=m | ||
90 | CONFIG_NFT_LOG=m | ||
91 | CONFIG_NFT_LIMIT=m | ||
92 | CONFIG_NFT_NAT=m | ||
93 | CONFIG_NFT_COMPAT=m | ||
84 | CONFIG_NETFILTER_XT_SET=m | 94 | CONFIG_NETFILTER_XT_SET=m |
85 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 95 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
86 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 96 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -94,6 +104,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
94 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 104 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
95 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 105 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
96 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 106 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
107 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
97 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 108 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
98 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 109 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
99 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 110 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -126,6 +137,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
126 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 137 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
127 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 138 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
128 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 139 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
140 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
129 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 141 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
130 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 142 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
131 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 143 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -140,11 +152,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
140 | CONFIG_IP_SET_HASH_IPPORT=m | 152 | CONFIG_IP_SET_HASH_IPPORT=m |
141 | CONFIG_IP_SET_HASH_IPPORTIP=m | 153 | CONFIG_IP_SET_HASH_IPPORTIP=m |
142 | CONFIG_IP_SET_HASH_IPPORTNET=m | 154 | CONFIG_IP_SET_HASH_IPPORTNET=m |
155 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
143 | CONFIG_IP_SET_HASH_NET=m | 156 | CONFIG_IP_SET_HASH_NET=m |
157 | CONFIG_IP_SET_HASH_NETNET=m | ||
144 | CONFIG_IP_SET_HASH_NETPORT=m | 158 | CONFIG_IP_SET_HASH_NETPORT=m |
145 | CONFIG_IP_SET_HASH_NETIFACE=m | 159 | CONFIG_IP_SET_HASH_NETIFACE=m |
146 | CONFIG_IP_SET_LIST_SET=m | 160 | CONFIG_IP_SET_LIST_SET=m |
147 | CONFIG_NF_CONNTRACK_IPV4=m | 161 | CONFIG_NF_CONNTRACK_IPV4=m |
162 | CONFIG_NF_TABLES_IPV4=m | ||
163 | CONFIG_NFT_REJECT_IPV4=m | ||
164 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
165 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
166 | CONFIG_NF_TABLES_ARP=m | ||
148 | CONFIG_IP_NF_IPTABLES=m | 167 | CONFIG_IP_NF_IPTABLES=m |
149 | CONFIG_IP_NF_MATCH_AH=m | 168 | CONFIG_IP_NF_MATCH_AH=m |
150 | CONFIG_IP_NF_MATCH_ECN=m | 169 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -152,6 +171,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
152 | CONFIG_IP_NF_MATCH_TTL=m | 171 | CONFIG_IP_NF_MATCH_TTL=m |
153 | CONFIG_IP_NF_FILTER=m | 172 | CONFIG_IP_NF_FILTER=m |
154 | CONFIG_IP_NF_TARGET_REJECT=m | 173 | CONFIG_IP_NF_TARGET_REJECT=m |
174 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
155 | CONFIG_IP_NF_TARGET_ULOG=m | 175 | CONFIG_IP_NF_TARGET_ULOG=m |
156 | CONFIG_NF_NAT_IPV4=m | 176 | CONFIG_NF_NAT_IPV4=m |
157 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 177 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -166,6 +186,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
166 | CONFIG_IP_NF_ARPFILTER=m | 186 | CONFIG_IP_NF_ARPFILTER=m |
167 | CONFIG_IP_NF_ARP_MANGLE=m | 187 | CONFIG_IP_NF_ARP_MANGLE=m |
168 | CONFIG_NF_CONNTRACK_IPV6=m | 188 | CONFIG_NF_CONNTRACK_IPV6=m |
189 | CONFIG_NF_TABLES_IPV6=m | ||
190 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
191 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
169 | CONFIG_IP6_NF_IPTABLES=m | 192 | CONFIG_IP6_NF_IPTABLES=m |
170 | CONFIG_IP6_NF_MATCH_AH=m | 193 | CONFIG_IP6_NF_MATCH_AH=m |
171 | CONFIG_IP6_NF_MATCH_EUI64=m | 194 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -179,11 +202,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
179 | CONFIG_IP6_NF_TARGET_HL=m | 202 | CONFIG_IP6_NF_TARGET_HL=m |
180 | CONFIG_IP6_NF_FILTER=m | 203 | CONFIG_IP6_NF_FILTER=m |
181 | CONFIG_IP6_NF_TARGET_REJECT=m | 204 | CONFIG_IP6_NF_TARGET_REJECT=m |
205 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
182 | CONFIG_IP6_NF_MANGLE=m | 206 | CONFIG_IP6_NF_MANGLE=m |
183 | CONFIG_IP6_NF_RAW=m | 207 | CONFIG_IP6_NF_RAW=m |
184 | CONFIG_NF_NAT_IPV6=m | 208 | CONFIG_NF_NAT_IPV6=m |
185 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 209 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
186 | CONFIG_IP6_NF_TARGET_NPT=m | 210 | CONFIG_IP6_NF_TARGET_NPT=m |
211 | CONFIG_NF_TABLES_BRIDGE=m | ||
187 | CONFIG_IP_DCCP=m | 212 | CONFIG_IP_DCCP=m |
188 | # CONFIG_IP_DCCP_CCID3 is not set | 213 | # CONFIG_IP_DCCP_CCID3 is not set |
189 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 214 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -191,10 +216,13 @@ CONFIG_RDS=m | |||
191 | CONFIG_RDS_TCP=m | 216 | CONFIG_RDS_TCP=m |
192 | CONFIG_L2TP=m | 217 | CONFIG_L2TP=m |
193 | CONFIG_ATALK=m | 218 | CONFIG_ATALK=m |
219 | CONFIG_DNS_RESOLVER=y | ||
194 | CONFIG_BATMAN_ADV=m | 220 | CONFIG_BATMAN_ADV=m |
195 | CONFIG_BATMAN_ADV_DAT=y | 221 | CONFIG_BATMAN_ADV_DAT=y |
222 | CONFIG_BATMAN_ADV_NC=y | ||
223 | CONFIG_NETLINK_DIAG=m | ||
224 | CONFIG_NET_MPLS_GSO=m | ||
196 | # CONFIG_WIRELESS is not set | 225 | # CONFIG_WIRELESS is not set |
197 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
198 | CONFIG_DEVTMPFS=y | 226 | CONFIG_DEVTMPFS=y |
199 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 227 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
200 | # CONFIG_FW_LOADER_USER_HELPER is not set | 228 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -206,6 +234,7 @@ CONFIG_BLK_DEV_NBD=m | |||
206 | CONFIG_BLK_DEV_RAM=y | 234 | CONFIG_BLK_DEV_RAM=y |
207 | CONFIG_CDROM_PKTCDVD=m | 235 | CONFIG_CDROM_PKTCDVD=m |
208 | CONFIG_ATA_OVER_ETH=m | 236 | CONFIG_ATA_OVER_ETH=m |
237 | CONFIG_DUMMY_IRQ=m | ||
209 | CONFIG_RAID_ATTRS=m | 238 | CONFIG_RAID_ATTRS=m |
210 | CONFIG_SCSI=y | 239 | CONFIG_SCSI=y |
211 | CONFIG_SCSI_TGT=m | 240 | CONFIG_SCSI_TGT=m |
@@ -243,12 +272,14 @@ CONFIG_EQUALIZER=m | |||
243 | CONFIG_NET_TEAM=m | 272 | CONFIG_NET_TEAM=m |
244 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 273 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
245 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 274 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
275 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
246 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 276 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
247 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 277 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
248 | CONFIG_VXLAN=m | 278 | CONFIG_VXLAN=m |
249 | CONFIG_NETCONSOLE=m | 279 | CONFIG_NETCONSOLE=m |
250 | CONFIG_NETCONSOLE_DYNAMIC=y | 280 | CONFIG_NETCONSOLE_DYNAMIC=y |
251 | CONFIG_VETH=m | 281 | CONFIG_VETH=m |
282 | # CONFIG_NET_VENDOR_ARC is not set | ||
252 | # CONFIG_NET_CADENCE is not set | 283 | # CONFIG_NET_CADENCE is not set |
253 | # CONFIG_NET_VENDOR_BROADCOM is not set | 284 | # CONFIG_NET_VENDOR_BROADCOM is not set |
254 | CONFIG_BVME6000_NET=y | 285 | CONFIG_BVME6000_NET=y |
@@ -257,6 +288,7 @@ CONFIG_BVME6000_NET=y | |||
257 | # CONFIG_NET_VENDOR_NATSEMI is not set | 288 | # CONFIG_NET_VENDOR_NATSEMI is not set |
258 | # CONFIG_NET_VENDOR_SEEQ is not set | 289 | # CONFIG_NET_VENDOR_SEEQ is not set |
259 | # CONFIG_NET_VENDOR_STMICRO is not set | 290 | # CONFIG_NET_VENDOR_STMICRO is not set |
291 | # CONFIG_NET_VENDOR_VIA is not set | ||
260 | # CONFIG_NET_VENDOR_WIZNET is not set | 292 | # CONFIG_NET_VENDOR_WIZNET is not set |
261 | CONFIG_PPP=m | 293 | CONFIG_PPP=m |
262 | CONFIG_PPP_BSDCOMP=m | 294 | CONFIG_PPP_BSDCOMP=m |
@@ -294,10 +326,6 @@ CONFIG_RTC_CLASS=y | |||
294 | CONFIG_RTC_DRV_GENERIC=m | 326 | CONFIG_RTC_DRV_GENERIC=m |
295 | # CONFIG_IOMMU_SUPPORT is not set | 327 | # CONFIG_IOMMU_SUPPORT is not set |
296 | CONFIG_PROC_HARDWARE=y | 328 | CONFIG_PROC_HARDWARE=y |
297 | CONFIG_EXT2_FS=y | ||
298 | CONFIG_EXT3_FS=y | ||
299 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
300 | # CONFIG_EXT3_FS_XATTR is not set | ||
301 | CONFIG_EXT4_FS=y | 329 | CONFIG_EXT4_FS=y |
302 | CONFIG_REISERFS_FS=m | 330 | CONFIG_REISERFS_FS=m |
303 | CONFIG_JFS_FS=m | 331 | CONFIG_JFS_FS=m |
@@ -334,7 +362,7 @@ CONFIG_QNX6FS_FS=m | |||
334 | CONFIG_SYSV_FS=m | 362 | CONFIG_SYSV_FS=m |
335 | CONFIG_UFS_FS=m | 363 | CONFIG_UFS_FS=m |
336 | CONFIG_NFS_FS=y | 364 | CONFIG_NFS_FS=y |
337 | CONFIG_NFS_V4=y | 365 | CONFIG_NFS_V4=m |
338 | CONFIG_NFS_SWAP=y | 366 | CONFIG_NFS_SWAP=y |
339 | CONFIG_ROOT_NFS=y | 367 | CONFIG_ROOT_NFS=y |
340 | CONFIG_NFSD=m | 368 | CONFIG_NFSD=m |
@@ -393,10 +421,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
393 | CONFIG_DLM=m | 421 | CONFIG_DLM=m |
394 | CONFIG_MAGIC_SYSRQ=y | 422 | CONFIG_MAGIC_SYSRQ=y |
395 | CONFIG_ASYNC_RAID6_TEST=m | 423 | CONFIG_ASYNC_RAID6_TEST=m |
424 | CONFIG_TEST_STRING_HELPERS=m | ||
396 | CONFIG_ENCRYPTED_KEYS=m | 425 | CONFIG_ENCRYPTED_KEYS=m |
397 | CONFIG_CRYPTO_MANAGER=y | 426 | CONFIG_CRYPTO_MANAGER=y |
398 | CONFIG_CRYPTO_USER=m | 427 | CONFIG_CRYPTO_USER=m |
399 | CONFIG_CRYPTO_NULL=m | ||
400 | CONFIG_CRYPTO_CRYPTD=m | 428 | CONFIG_CRYPTO_CRYPTD=m |
401 | CONFIG_CRYPTO_TEST=m | 429 | CONFIG_CRYPTO_TEST=m |
402 | CONFIG_CRYPTO_CCM=m | 430 | CONFIG_CRYPTO_CCM=m |
@@ -429,6 +457,8 @@ CONFIG_CRYPTO_TEA=m | |||
429 | CONFIG_CRYPTO_TWOFISH=m | 457 | CONFIG_CRYPTO_TWOFISH=m |
430 | CONFIG_CRYPTO_ZLIB=m | 458 | CONFIG_CRYPTO_ZLIB=m |
431 | CONFIG_CRYPTO_LZO=m | 459 | CONFIG_CRYPTO_LZO=m |
460 | CONFIG_CRYPTO_LZ4=m | ||
461 | CONFIG_CRYPTO_LZ4HC=m | ||
432 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 462 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
433 | CONFIG_CRYPTO_USER_API_HASH=m | 463 | CONFIG_CRYPTO_USER_API_HASH=m |
434 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 464 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index ec7382d8afff..7cd9d9f456fb 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig | |||
@@ -50,7 +50,6 @@ CONFIG_IP_PNP_RARP=y | |||
50 | CONFIG_NET_IPIP=m | 50 | CONFIG_NET_IPIP=m |
51 | CONFIG_NET_IPGRE_DEMUX=m | 51 | CONFIG_NET_IPGRE_DEMUX=m |
52 | CONFIG_NET_IPGRE=m | 52 | CONFIG_NET_IPGRE=m |
53 | CONFIG_SYN_COOKIES=y | ||
54 | CONFIG_NET_IPVTI=m | 53 | CONFIG_NET_IPVTI=m |
55 | CONFIG_INET_AH=m | 54 | CONFIG_INET_AH=m |
56 | CONFIG_INET_ESP=m | 55 | CONFIG_INET_ESP=m |
@@ -61,11 +60,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
61 | # CONFIG_INET_LRO is not set | 60 | # CONFIG_INET_LRO is not set |
62 | CONFIG_INET_DIAG=m | 61 | CONFIG_INET_DIAG=m |
63 | CONFIG_INET_UDP_DIAG=m | 62 | CONFIG_INET_UDP_DIAG=m |
64 | CONFIG_IPV6_PRIVACY=y | ||
65 | CONFIG_IPV6_ROUTER_PREF=y | 63 | CONFIG_IPV6_ROUTER_PREF=y |
66 | CONFIG_INET6_AH=m | 64 | CONFIG_INET6_AH=m |
67 | CONFIG_INET6_ESP=m | 65 | CONFIG_INET6_ESP=m |
68 | CONFIG_INET6_IPCOMP=m | 66 | CONFIG_INET6_IPCOMP=m |
67 | CONFIG_IPV6_VTI=m | ||
69 | CONFIG_IPV6_GRE=m | 68 | CONFIG_IPV6_GRE=m |
70 | CONFIG_NETFILTER=y | 69 | CONFIG_NETFILTER=y |
71 | CONFIG_NF_CONNTRACK=m | 70 | CONFIG_NF_CONNTRACK=m |
@@ -83,6 +82,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
83 | CONFIG_NF_CONNTRACK_SANE=m | 82 | CONFIG_NF_CONNTRACK_SANE=m |
84 | CONFIG_NF_CONNTRACK_SIP=m | 83 | CONFIG_NF_CONNTRACK_SIP=m |
85 | CONFIG_NF_CONNTRACK_TFTP=m | 84 | CONFIG_NF_CONNTRACK_TFTP=m |
85 | CONFIG_NF_TABLES=m | ||
86 | CONFIG_NFT_EXTHDR=m | ||
87 | CONFIG_NFT_META=m | ||
88 | CONFIG_NFT_CT=m | ||
89 | CONFIG_NFT_RBTREE=m | ||
90 | CONFIG_NFT_HASH=m | ||
91 | CONFIG_NFT_COUNTER=m | ||
92 | CONFIG_NFT_LOG=m | ||
93 | CONFIG_NFT_LIMIT=m | ||
94 | CONFIG_NFT_NAT=m | ||
95 | CONFIG_NFT_COMPAT=m | ||
86 | CONFIG_NETFILTER_XT_SET=m | 96 | CONFIG_NETFILTER_XT_SET=m |
87 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 97 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
88 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 98 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -96,6 +106,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
96 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 106 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
97 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 107 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
98 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 108 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
109 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
99 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 110 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
100 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 111 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
101 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 112 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -128,6 +139,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
128 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 139 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
129 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 140 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
130 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 141 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
142 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
131 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 143 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
132 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 144 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
133 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 145 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -142,11 +154,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
142 | CONFIG_IP_SET_HASH_IPPORT=m | 154 | CONFIG_IP_SET_HASH_IPPORT=m |
143 | CONFIG_IP_SET_HASH_IPPORTIP=m | 155 | CONFIG_IP_SET_HASH_IPPORTIP=m |
144 | CONFIG_IP_SET_HASH_IPPORTNET=m | 156 | CONFIG_IP_SET_HASH_IPPORTNET=m |
157 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
145 | CONFIG_IP_SET_HASH_NET=m | 158 | CONFIG_IP_SET_HASH_NET=m |
159 | CONFIG_IP_SET_HASH_NETNET=m | ||
146 | CONFIG_IP_SET_HASH_NETPORT=m | 160 | CONFIG_IP_SET_HASH_NETPORT=m |
147 | CONFIG_IP_SET_HASH_NETIFACE=m | 161 | CONFIG_IP_SET_HASH_NETIFACE=m |
148 | CONFIG_IP_SET_LIST_SET=m | 162 | CONFIG_IP_SET_LIST_SET=m |
149 | CONFIG_NF_CONNTRACK_IPV4=m | 163 | CONFIG_NF_CONNTRACK_IPV4=m |
164 | CONFIG_NF_TABLES_IPV4=m | ||
165 | CONFIG_NFT_REJECT_IPV4=m | ||
166 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
167 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
168 | CONFIG_NF_TABLES_ARP=m | ||
150 | CONFIG_IP_NF_IPTABLES=m | 169 | CONFIG_IP_NF_IPTABLES=m |
151 | CONFIG_IP_NF_MATCH_AH=m | 170 | CONFIG_IP_NF_MATCH_AH=m |
152 | CONFIG_IP_NF_MATCH_ECN=m | 171 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -154,6 +173,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
154 | CONFIG_IP_NF_MATCH_TTL=m | 173 | CONFIG_IP_NF_MATCH_TTL=m |
155 | CONFIG_IP_NF_FILTER=m | 174 | CONFIG_IP_NF_FILTER=m |
156 | CONFIG_IP_NF_TARGET_REJECT=m | 175 | CONFIG_IP_NF_TARGET_REJECT=m |
176 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
157 | CONFIG_IP_NF_TARGET_ULOG=m | 177 | CONFIG_IP_NF_TARGET_ULOG=m |
158 | CONFIG_NF_NAT_IPV4=m | 178 | CONFIG_NF_NAT_IPV4=m |
159 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 179 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -168,6 +188,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
168 | CONFIG_IP_NF_ARPFILTER=m | 188 | CONFIG_IP_NF_ARPFILTER=m |
169 | CONFIG_IP_NF_ARP_MANGLE=m | 189 | CONFIG_IP_NF_ARP_MANGLE=m |
170 | CONFIG_NF_CONNTRACK_IPV6=m | 190 | CONFIG_NF_CONNTRACK_IPV6=m |
191 | CONFIG_NF_TABLES_IPV6=m | ||
192 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
193 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
171 | CONFIG_IP6_NF_IPTABLES=m | 194 | CONFIG_IP6_NF_IPTABLES=m |
172 | CONFIG_IP6_NF_MATCH_AH=m | 195 | CONFIG_IP6_NF_MATCH_AH=m |
173 | CONFIG_IP6_NF_MATCH_EUI64=m | 196 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -181,11 +204,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
181 | CONFIG_IP6_NF_TARGET_HL=m | 204 | CONFIG_IP6_NF_TARGET_HL=m |
182 | CONFIG_IP6_NF_FILTER=m | 205 | CONFIG_IP6_NF_FILTER=m |
183 | CONFIG_IP6_NF_TARGET_REJECT=m | 206 | CONFIG_IP6_NF_TARGET_REJECT=m |
207 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
184 | CONFIG_IP6_NF_MANGLE=m | 208 | CONFIG_IP6_NF_MANGLE=m |
185 | CONFIG_IP6_NF_RAW=m | 209 | CONFIG_IP6_NF_RAW=m |
186 | CONFIG_NF_NAT_IPV6=m | 210 | CONFIG_NF_NAT_IPV6=m |
187 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 211 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
188 | CONFIG_IP6_NF_TARGET_NPT=m | 212 | CONFIG_IP6_NF_TARGET_NPT=m |
213 | CONFIG_NF_TABLES_BRIDGE=m | ||
189 | CONFIG_IP_DCCP=m | 214 | CONFIG_IP_DCCP=m |
190 | # CONFIG_IP_DCCP_CCID3 is not set | 215 | # CONFIG_IP_DCCP_CCID3 is not set |
191 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 216 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -193,10 +218,13 @@ CONFIG_RDS=m | |||
193 | CONFIG_RDS_TCP=m | 218 | CONFIG_RDS_TCP=m |
194 | CONFIG_L2TP=m | 219 | CONFIG_L2TP=m |
195 | CONFIG_ATALK=m | 220 | CONFIG_ATALK=m |
221 | CONFIG_DNS_RESOLVER=y | ||
196 | CONFIG_BATMAN_ADV=m | 222 | CONFIG_BATMAN_ADV=m |
197 | CONFIG_BATMAN_ADV_DAT=y | 223 | CONFIG_BATMAN_ADV_DAT=y |
224 | CONFIG_BATMAN_ADV_NC=y | ||
225 | CONFIG_NETLINK_DIAG=m | ||
226 | CONFIG_NET_MPLS_GSO=m | ||
198 | # CONFIG_WIRELESS is not set | 227 | # CONFIG_WIRELESS is not set |
199 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
200 | CONFIG_DEVTMPFS=y | 228 | CONFIG_DEVTMPFS=y |
201 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 229 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
202 | # CONFIG_FW_LOADER_USER_HELPER is not set | 230 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -208,6 +236,7 @@ CONFIG_BLK_DEV_NBD=m | |||
208 | CONFIG_BLK_DEV_RAM=y | 236 | CONFIG_BLK_DEV_RAM=y |
209 | CONFIG_CDROM_PKTCDVD=m | 237 | CONFIG_CDROM_PKTCDVD=m |
210 | CONFIG_ATA_OVER_ETH=m | 238 | CONFIG_ATA_OVER_ETH=m |
239 | CONFIG_DUMMY_IRQ=m | ||
211 | CONFIG_RAID_ATTRS=m | 240 | CONFIG_RAID_ATTRS=m |
212 | CONFIG_SCSI=y | 241 | CONFIG_SCSI=y |
213 | CONFIG_SCSI_TGT=m | 242 | CONFIG_SCSI_TGT=m |
@@ -244,6 +273,7 @@ CONFIG_EQUALIZER=m | |||
244 | CONFIG_NET_TEAM=m | 273 | CONFIG_NET_TEAM=m |
245 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 274 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
246 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 275 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
276 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
247 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 277 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
248 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 278 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
249 | CONFIG_VXLAN=m | 279 | CONFIG_VXLAN=m |
@@ -251,6 +281,7 @@ CONFIG_NETCONSOLE=m | |||
251 | CONFIG_NETCONSOLE_DYNAMIC=y | 281 | CONFIG_NETCONSOLE_DYNAMIC=y |
252 | CONFIG_VETH=m | 282 | CONFIG_VETH=m |
253 | CONFIG_HPLANCE=y | 283 | CONFIG_HPLANCE=y |
284 | # CONFIG_NET_VENDOR_ARC is not set | ||
254 | # CONFIG_NET_CADENCE is not set | 285 | # CONFIG_NET_CADENCE is not set |
255 | # CONFIG_NET_VENDOR_BROADCOM is not set | 286 | # CONFIG_NET_VENDOR_BROADCOM is not set |
256 | # CONFIG_NET_VENDOR_INTEL is not set | 287 | # CONFIG_NET_VENDOR_INTEL is not set |
@@ -259,6 +290,7 @@ CONFIG_HPLANCE=y | |||
259 | # CONFIG_NET_VENDOR_NATSEMI is not set | 290 | # CONFIG_NET_VENDOR_NATSEMI is not set |
260 | # CONFIG_NET_VENDOR_SEEQ is not set | 291 | # CONFIG_NET_VENDOR_SEEQ is not set |
261 | # CONFIG_NET_VENDOR_STMICRO is not set | 292 | # CONFIG_NET_VENDOR_STMICRO is not set |
293 | # CONFIG_NET_VENDOR_VIA is not set | ||
262 | # CONFIG_NET_VENDOR_WIZNET is not set | 294 | # CONFIG_NET_VENDOR_WIZNET is not set |
263 | CONFIG_PPP=m | 295 | CONFIG_PPP=m |
264 | CONFIG_PPP_BSDCOMP=m | 296 | CONFIG_PPP_BSDCOMP=m |
@@ -282,7 +314,6 @@ CONFIG_MOUSE_SERIAL=m | |||
282 | CONFIG_INPUT_MISC=y | 314 | CONFIG_INPUT_MISC=y |
283 | CONFIG_HP_SDC_RTC=m | 315 | CONFIG_HP_SDC_RTC=m |
284 | CONFIG_SERIO_SERPORT=m | 316 | CONFIG_SERIO_SERPORT=m |
285 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
286 | # CONFIG_LEGACY_PTYS is not set | 317 | # CONFIG_LEGACY_PTYS is not set |
287 | # CONFIG_DEVKMEM is not set | 318 | # CONFIG_DEVKMEM is not set |
288 | # CONFIG_HW_RANDOM is not set | 319 | # CONFIG_HW_RANDOM is not set |
@@ -304,10 +335,6 @@ CONFIG_RTC_CLASS=y | |||
304 | CONFIG_RTC_DRV_GENERIC=m | 335 | CONFIG_RTC_DRV_GENERIC=m |
305 | # CONFIG_IOMMU_SUPPORT is not set | 336 | # CONFIG_IOMMU_SUPPORT is not set |
306 | CONFIG_PROC_HARDWARE=y | 337 | CONFIG_PROC_HARDWARE=y |
307 | CONFIG_EXT2_FS=y | ||
308 | CONFIG_EXT3_FS=y | ||
309 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
310 | # CONFIG_EXT3_FS_XATTR is not set | ||
311 | CONFIG_EXT4_FS=y | 338 | CONFIG_EXT4_FS=y |
312 | CONFIG_REISERFS_FS=m | 339 | CONFIG_REISERFS_FS=m |
313 | CONFIG_JFS_FS=m | 340 | CONFIG_JFS_FS=m |
@@ -344,7 +371,7 @@ CONFIG_QNX6FS_FS=m | |||
344 | CONFIG_SYSV_FS=m | 371 | CONFIG_SYSV_FS=m |
345 | CONFIG_UFS_FS=m | 372 | CONFIG_UFS_FS=m |
346 | CONFIG_NFS_FS=y | 373 | CONFIG_NFS_FS=y |
347 | CONFIG_NFS_V4=y | 374 | CONFIG_NFS_V4=m |
348 | CONFIG_NFS_SWAP=y | 375 | CONFIG_NFS_SWAP=y |
349 | CONFIG_ROOT_NFS=y | 376 | CONFIG_ROOT_NFS=y |
350 | CONFIG_NFSD=m | 377 | CONFIG_NFSD=m |
@@ -403,10 +430,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
403 | CONFIG_DLM=m | 430 | CONFIG_DLM=m |
404 | CONFIG_MAGIC_SYSRQ=y | 431 | CONFIG_MAGIC_SYSRQ=y |
405 | CONFIG_ASYNC_RAID6_TEST=m | 432 | CONFIG_ASYNC_RAID6_TEST=m |
433 | CONFIG_TEST_STRING_HELPERS=m | ||
406 | CONFIG_ENCRYPTED_KEYS=m | 434 | CONFIG_ENCRYPTED_KEYS=m |
407 | CONFIG_CRYPTO_MANAGER=y | 435 | CONFIG_CRYPTO_MANAGER=y |
408 | CONFIG_CRYPTO_USER=m | 436 | CONFIG_CRYPTO_USER=m |
409 | CONFIG_CRYPTO_NULL=m | ||
410 | CONFIG_CRYPTO_CRYPTD=m | 437 | CONFIG_CRYPTO_CRYPTD=m |
411 | CONFIG_CRYPTO_TEST=m | 438 | CONFIG_CRYPTO_TEST=m |
412 | CONFIG_CRYPTO_CCM=m | 439 | CONFIG_CRYPTO_CCM=m |
@@ -439,6 +466,8 @@ CONFIG_CRYPTO_TEA=m | |||
439 | CONFIG_CRYPTO_TWOFISH=m | 466 | CONFIG_CRYPTO_TWOFISH=m |
440 | CONFIG_CRYPTO_ZLIB=m | 467 | CONFIG_CRYPTO_ZLIB=m |
441 | CONFIG_CRYPTO_LZO=m | 468 | CONFIG_CRYPTO_LZO=m |
469 | CONFIG_CRYPTO_LZ4=m | ||
470 | CONFIG_CRYPTO_LZ4HC=m | ||
442 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 471 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
443 | CONFIG_CRYPTO_USER_API_HASH=m | 472 | CONFIG_CRYPTO_USER_API_HASH=m |
444 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 473 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 7d46fbec7042..31f5bd061d14 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig | |||
@@ -49,7 +49,6 @@ CONFIG_IP_PNP_RARP=y | |||
49 | CONFIG_NET_IPIP=m | 49 | CONFIG_NET_IPIP=m |
50 | CONFIG_NET_IPGRE_DEMUX=m | 50 | CONFIG_NET_IPGRE_DEMUX=m |
51 | CONFIG_NET_IPGRE=m | 51 | CONFIG_NET_IPGRE=m |
52 | CONFIG_SYN_COOKIES=y | ||
53 | CONFIG_NET_IPVTI=m | 52 | CONFIG_NET_IPVTI=m |
54 | CONFIG_INET_AH=m | 53 | CONFIG_INET_AH=m |
55 | CONFIG_INET_ESP=m | 54 | CONFIG_INET_ESP=m |
@@ -60,11 +59,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
60 | # CONFIG_INET_LRO is not set | 59 | # CONFIG_INET_LRO is not set |
61 | CONFIG_INET_DIAG=m | 60 | CONFIG_INET_DIAG=m |
62 | CONFIG_INET_UDP_DIAG=m | 61 | CONFIG_INET_UDP_DIAG=m |
63 | CONFIG_IPV6_PRIVACY=y | ||
64 | CONFIG_IPV6_ROUTER_PREF=y | 62 | CONFIG_IPV6_ROUTER_PREF=y |
65 | CONFIG_INET6_AH=m | 63 | CONFIG_INET6_AH=m |
66 | CONFIG_INET6_ESP=m | 64 | CONFIG_INET6_ESP=m |
67 | CONFIG_INET6_IPCOMP=m | 65 | CONFIG_INET6_IPCOMP=m |
66 | CONFIG_IPV6_VTI=m | ||
68 | CONFIG_IPV6_GRE=m | 67 | CONFIG_IPV6_GRE=m |
69 | CONFIG_NETFILTER=y | 68 | CONFIG_NETFILTER=y |
70 | CONFIG_NF_CONNTRACK=m | 69 | CONFIG_NF_CONNTRACK=m |
@@ -82,6 +81,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
82 | CONFIG_NF_CONNTRACK_SANE=m | 81 | CONFIG_NF_CONNTRACK_SANE=m |
83 | CONFIG_NF_CONNTRACK_SIP=m | 82 | CONFIG_NF_CONNTRACK_SIP=m |
84 | CONFIG_NF_CONNTRACK_TFTP=m | 83 | CONFIG_NF_CONNTRACK_TFTP=m |
84 | CONFIG_NF_TABLES=m | ||
85 | CONFIG_NFT_EXTHDR=m | ||
86 | CONFIG_NFT_META=m | ||
87 | CONFIG_NFT_CT=m | ||
88 | CONFIG_NFT_RBTREE=m | ||
89 | CONFIG_NFT_HASH=m | ||
90 | CONFIG_NFT_COUNTER=m | ||
91 | CONFIG_NFT_LOG=m | ||
92 | CONFIG_NFT_LIMIT=m | ||
93 | CONFIG_NFT_NAT=m | ||
94 | CONFIG_NFT_COMPAT=m | ||
85 | CONFIG_NETFILTER_XT_SET=m | 95 | CONFIG_NETFILTER_XT_SET=m |
86 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 96 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
87 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 97 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -95,6 +105,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
95 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 105 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
96 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 106 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
97 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 107 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
108 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
98 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 109 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
99 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 110 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
100 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 111 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -127,6 +138,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
127 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 138 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
128 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 139 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
129 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 140 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
141 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
130 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 142 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
131 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 143 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
132 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 144 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -141,11 +153,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
141 | CONFIG_IP_SET_HASH_IPPORT=m | 153 | CONFIG_IP_SET_HASH_IPPORT=m |
142 | CONFIG_IP_SET_HASH_IPPORTIP=m | 154 | CONFIG_IP_SET_HASH_IPPORTIP=m |
143 | CONFIG_IP_SET_HASH_IPPORTNET=m | 155 | CONFIG_IP_SET_HASH_IPPORTNET=m |
156 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
144 | CONFIG_IP_SET_HASH_NET=m | 157 | CONFIG_IP_SET_HASH_NET=m |
158 | CONFIG_IP_SET_HASH_NETNET=m | ||
145 | CONFIG_IP_SET_HASH_NETPORT=m | 159 | CONFIG_IP_SET_HASH_NETPORT=m |
146 | CONFIG_IP_SET_HASH_NETIFACE=m | 160 | CONFIG_IP_SET_HASH_NETIFACE=m |
147 | CONFIG_IP_SET_LIST_SET=m | 161 | CONFIG_IP_SET_LIST_SET=m |
148 | CONFIG_NF_CONNTRACK_IPV4=m | 162 | CONFIG_NF_CONNTRACK_IPV4=m |
163 | CONFIG_NF_TABLES_IPV4=m | ||
164 | CONFIG_NFT_REJECT_IPV4=m | ||
165 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
166 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
167 | CONFIG_NF_TABLES_ARP=m | ||
149 | CONFIG_IP_NF_IPTABLES=m | 168 | CONFIG_IP_NF_IPTABLES=m |
150 | CONFIG_IP_NF_MATCH_AH=m | 169 | CONFIG_IP_NF_MATCH_AH=m |
151 | CONFIG_IP_NF_MATCH_ECN=m | 170 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -153,6 +172,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
153 | CONFIG_IP_NF_MATCH_TTL=m | 172 | CONFIG_IP_NF_MATCH_TTL=m |
154 | CONFIG_IP_NF_FILTER=m | 173 | CONFIG_IP_NF_FILTER=m |
155 | CONFIG_IP_NF_TARGET_REJECT=m | 174 | CONFIG_IP_NF_TARGET_REJECT=m |
175 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
156 | CONFIG_IP_NF_TARGET_ULOG=m | 176 | CONFIG_IP_NF_TARGET_ULOG=m |
157 | CONFIG_NF_NAT_IPV4=m | 177 | CONFIG_NF_NAT_IPV4=m |
158 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 178 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -167,6 +187,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
167 | CONFIG_IP_NF_ARPFILTER=m | 187 | CONFIG_IP_NF_ARPFILTER=m |
168 | CONFIG_IP_NF_ARP_MANGLE=m | 188 | CONFIG_IP_NF_ARP_MANGLE=m |
169 | CONFIG_NF_CONNTRACK_IPV6=m | 189 | CONFIG_NF_CONNTRACK_IPV6=m |
190 | CONFIG_NF_TABLES_IPV6=m | ||
191 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
192 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
170 | CONFIG_IP6_NF_IPTABLES=m | 193 | CONFIG_IP6_NF_IPTABLES=m |
171 | CONFIG_IP6_NF_MATCH_AH=m | 194 | CONFIG_IP6_NF_MATCH_AH=m |
172 | CONFIG_IP6_NF_MATCH_EUI64=m | 195 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -180,11 +203,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
180 | CONFIG_IP6_NF_TARGET_HL=m | 203 | CONFIG_IP6_NF_TARGET_HL=m |
181 | CONFIG_IP6_NF_FILTER=m | 204 | CONFIG_IP6_NF_FILTER=m |
182 | CONFIG_IP6_NF_TARGET_REJECT=m | 205 | CONFIG_IP6_NF_TARGET_REJECT=m |
206 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
183 | CONFIG_IP6_NF_MANGLE=m | 207 | CONFIG_IP6_NF_MANGLE=m |
184 | CONFIG_IP6_NF_RAW=m | 208 | CONFIG_IP6_NF_RAW=m |
185 | CONFIG_NF_NAT_IPV6=m | 209 | CONFIG_NF_NAT_IPV6=m |
186 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 210 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
187 | CONFIG_IP6_NF_TARGET_NPT=m | 211 | CONFIG_IP6_NF_TARGET_NPT=m |
212 | CONFIG_NF_TABLES_BRIDGE=m | ||
188 | CONFIG_IP_DCCP=m | 213 | CONFIG_IP_DCCP=m |
189 | # CONFIG_IP_DCCP_CCID3 is not set | 214 | # CONFIG_IP_DCCP_CCID3 is not set |
190 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 215 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -195,11 +220,13 @@ CONFIG_ATALK=m | |||
195 | CONFIG_DEV_APPLETALK=m | 220 | CONFIG_DEV_APPLETALK=m |
196 | CONFIG_IPDDP=m | 221 | CONFIG_IPDDP=m |
197 | CONFIG_IPDDP_ENCAP=y | 222 | CONFIG_IPDDP_ENCAP=y |
198 | CONFIG_IPDDP_DECAP=y | 223 | CONFIG_DNS_RESOLVER=y |
199 | CONFIG_BATMAN_ADV=m | 224 | CONFIG_BATMAN_ADV=m |
200 | CONFIG_BATMAN_ADV_DAT=y | 225 | CONFIG_BATMAN_ADV_DAT=y |
226 | CONFIG_BATMAN_ADV_NC=y | ||
227 | CONFIG_NETLINK_DIAG=m | ||
228 | CONFIG_NET_MPLS_GSO=m | ||
201 | # CONFIG_WIRELESS is not set | 229 | # CONFIG_WIRELESS is not set |
202 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
203 | CONFIG_DEVTMPFS=y | 230 | CONFIG_DEVTMPFS=y |
204 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 231 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
205 | # CONFIG_FW_LOADER_USER_HELPER is not set | 232 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -212,6 +239,7 @@ CONFIG_BLK_DEV_NBD=m | |||
212 | CONFIG_BLK_DEV_RAM=y | 239 | CONFIG_BLK_DEV_RAM=y |
213 | CONFIG_CDROM_PKTCDVD=m | 240 | CONFIG_CDROM_PKTCDVD=m |
214 | CONFIG_ATA_OVER_ETH=m | 241 | CONFIG_ATA_OVER_ETH=m |
242 | CONFIG_DUMMY_IRQ=m | ||
215 | CONFIG_IDE=y | 243 | CONFIG_IDE=y |
216 | CONFIG_IDE_GD_ATAPI=y | 244 | CONFIG_IDE_GD_ATAPI=y |
217 | CONFIG_BLK_DEV_IDECD=y | 245 | CONFIG_BLK_DEV_IDECD=y |
@@ -261,6 +289,7 @@ CONFIG_EQUALIZER=m | |||
261 | CONFIG_NET_TEAM=m | 289 | CONFIG_NET_TEAM=m |
262 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 290 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
263 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 291 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
292 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
264 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 293 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
265 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 294 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
266 | CONFIG_VXLAN=m | 295 | CONFIG_VXLAN=m |
@@ -268,6 +297,7 @@ CONFIG_NETCONSOLE=m | |||
268 | CONFIG_NETCONSOLE_DYNAMIC=y | 297 | CONFIG_NETCONSOLE_DYNAMIC=y |
269 | CONFIG_VETH=m | 298 | CONFIG_VETH=m |
270 | CONFIG_MACMACE=y | 299 | CONFIG_MACMACE=y |
300 | # CONFIG_NET_VENDOR_ARC is not set | ||
271 | # CONFIG_NET_CADENCE is not set | 301 | # CONFIG_NET_CADENCE is not set |
272 | # CONFIG_NET_VENDOR_BROADCOM is not set | 302 | # CONFIG_NET_VENDOR_BROADCOM is not set |
273 | CONFIG_MAC89x0=y | 303 | CONFIG_MAC89x0=y |
@@ -279,6 +309,7 @@ CONFIG_MAC8390=y | |||
279 | # CONFIG_NET_VENDOR_SEEQ is not set | 309 | # CONFIG_NET_VENDOR_SEEQ is not set |
280 | # CONFIG_NET_VENDOR_SMSC is not set | 310 | # CONFIG_NET_VENDOR_SMSC is not set |
281 | # CONFIG_NET_VENDOR_STMICRO is not set | 311 | # CONFIG_NET_VENDOR_STMICRO is not set |
312 | # CONFIG_NET_VENDOR_VIA is not set | ||
282 | # CONFIG_NET_VENDOR_WIZNET is not set | 313 | # CONFIG_NET_VENDOR_WIZNET is not set |
283 | CONFIG_PPP=m | 314 | CONFIG_PPP=m |
284 | CONFIG_PPP_BSDCOMP=m | 315 | CONFIG_PPP_BSDCOMP=m |
@@ -302,7 +333,6 @@ CONFIG_MOUSE_SERIAL=m | |||
302 | CONFIG_INPUT_MISC=y | 333 | CONFIG_INPUT_MISC=y |
303 | CONFIG_INPUT_M68K_BEEP=m | 334 | CONFIG_INPUT_M68K_BEEP=m |
304 | CONFIG_SERIO=m | 335 | CONFIG_SERIO=m |
305 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
306 | # CONFIG_LEGACY_PTYS is not set | 336 | # CONFIG_LEGACY_PTYS is not set |
307 | # CONFIG_DEVKMEM is not set | 337 | # CONFIG_DEVKMEM is not set |
308 | CONFIG_SERIAL_PMACZILOG=y | 338 | CONFIG_SERIAL_PMACZILOG=y |
@@ -327,10 +357,6 @@ CONFIG_RTC_CLASS=y | |||
327 | CONFIG_RTC_DRV_GENERIC=m | 357 | CONFIG_RTC_DRV_GENERIC=m |
328 | # CONFIG_IOMMU_SUPPORT is not set | 358 | # CONFIG_IOMMU_SUPPORT is not set |
329 | CONFIG_PROC_HARDWARE=y | 359 | CONFIG_PROC_HARDWARE=y |
330 | CONFIG_EXT2_FS=y | ||
331 | CONFIG_EXT3_FS=y | ||
332 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
333 | # CONFIG_EXT3_FS_XATTR is not set | ||
334 | CONFIG_EXT4_FS=y | 360 | CONFIG_EXT4_FS=y |
335 | CONFIG_REISERFS_FS=m | 361 | CONFIG_REISERFS_FS=m |
336 | CONFIG_JFS_FS=m | 362 | CONFIG_JFS_FS=m |
@@ -367,7 +393,7 @@ CONFIG_QNX6FS_FS=m | |||
367 | CONFIG_SYSV_FS=m | 393 | CONFIG_SYSV_FS=m |
368 | CONFIG_UFS_FS=m | 394 | CONFIG_UFS_FS=m |
369 | CONFIG_NFS_FS=y | 395 | CONFIG_NFS_FS=y |
370 | CONFIG_NFS_V4=y | 396 | CONFIG_NFS_V4=m |
371 | CONFIG_NFS_SWAP=y | 397 | CONFIG_NFS_SWAP=y |
372 | CONFIG_ROOT_NFS=y | 398 | CONFIG_ROOT_NFS=y |
373 | CONFIG_NFSD=m | 399 | CONFIG_NFSD=m |
@@ -426,10 +452,11 @@ CONFIG_NLS_MAC_TURKISH=m | |||
426 | CONFIG_DLM=m | 452 | CONFIG_DLM=m |
427 | CONFIG_MAGIC_SYSRQ=y | 453 | CONFIG_MAGIC_SYSRQ=y |
428 | CONFIG_ASYNC_RAID6_TEST=m | 454 | CONFIG_ASYNC_RAID6_TEST=m |
455 | CONFIG_TEST_STRING_HELPERS=m | ||
456 | CONFIG_EARLY_PRINTK=y | ||
429 | CONFIG_ENCRYPTED_KEYS=m | 457 | CONFIG_ENCRYPTED_KEYS=m |
430 | CONFIG_CRYPTO_MANAGER=y | 458 | CONFIG_CRYPTO_MANAGER=y |
431 | CONFIG_CRYPTO_USER=m | 459 | CONFIG_CRYPTO_USER=m |
432 | CONFIG_CRYPTO_NULL=m | ||
433 | CONFIG_CRYPTO_CRYPTD=m | 460 | CONFIG_CRYPTO_CRYPTD=m |
434 | CONFIG_CRYPTO_TEST=m | 461 | CONFIG_CRYPTO_TEST=m |
435 | CONFIG_CRYPTO_CCM=m | 462 | CONFIG_CRYPTO_CCM=m |
@@ -462,6 +489,8 @@ CONFIG_CRYPTO_TEA=m | |||
462 | CONFIG_CRYPTO_TWOFISH=m | 489 | CONFIG_CRYPTO_TWOFISH=m |
463 | CONFIG_CRYPTO_ZLIB=m | 490 | CONFIG_CRYPTO_ZLIB=m |
464 | CONFIG_CRYPTO_LZO=m | 491 | CONFIG_CRYPTO_LZO=m |
492 | CONFIG_CRYPTO_LZ4=m | ||
493 | CONFIG_CRYPTO_LZ4HC=m | ||
465 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 494 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
466 | CONFIG_CRYPTO_USER_API_HASH=m | 495 | CONFIG_CRYPTO_USER_API_HASH=m |
467 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 496 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index b17a8837f0e1..4e5adff326ee 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig | |||
@@ -58,7 +58,6 @@ CONFIG_IP_PNP_RARP=y | |||
58 | CONFIG_NET_IPIP=m | 58 | CONFIG_NET_IPIP=m |
59 | CONFIG_NET_IPGRE_DEMUX=m | 59 | CONFIG_NET_IPGRE_DEMUX=m |
60 | CONFIG_NET_IPGRE=m | 60 | CONFIG_NET_IPGRE=m |
61 | CONFIG_SYN_COOKIES=y | ||
62 | CONFIG_NET_IPVTI=m | 61 | CONFIG_NET_IPVTI=m |
63 | CONFIG_INET_AH=m | 62 | CONFIG_INET_AH=m |
64 | CONFIG_INET_ESP=m | 63 | CONFIG_INET_ESP=m |
@@ -69,11 +68,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
69 | # CONFIG_INET_LRO is not set | 68 | # CONFIG_INET_LRO is not set |
70 | CONFIG_INET_DIAG=m | 69 | CONFIG_INET_DIAG=m |
71 | CONFIG_INET_UDP_DIAG=m | 70 | CONFIG_INET_UDP_DIAG=m |
72 | CONFIG_IPV6_PRIVACY=y | ||
73 | CONFIG_IPV6_ROUTER_PREF=y | 71 | CONFIG_IPV6_ROUTER_PREF=y |
74 | CONFIG_INET6_AH=m | 72 | CONFIG_INET6_AH=m |
75 | CONFIG_INET6_ESP=m | 73 | CONFIG_INET6_ESP=m |
76 | CONFIG_INET6_IPCOMP=m | 74 | CONFIG_INET6_IPCOMP=m |
75 | CONFIG_IPV6_VTI=m | ||
77 | CONFIG_IPV6_GRE=m | 76 | CONFIG_IPV6_GRE=m |
78 | CONFIG_NETFILTER=y | 77 | CONFIG_NETFILTER=y |
79 | CONFIG_NF_CONNTRACK=m | 78 | CONFIG_NF_CONNTRACK=m |
@@ -91,6 +90,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
91 | CONFIG_NF_CONNTRACK_SANE=m | 90 | CONFIG_NF_CONNTRACK_SANE=m |
92 | CONFIG_NF_CONNTRACK_SIP=m | 91 | CONFIG_NF_CONNTRACK_SIP=m |
93 | CONFIG_NF_CONNTRACK_TFTP=m | 92 | CONFIG_NF_CONNTRACK_TFTP=m |
93 | CONFIG_NF_TABLES=m | ||
94 | CONFIG_NFT_EXTHDR=m | ||
95 | CONFIG_NFT_META=m | ||
96 | CONFIG_NFT_CT=m | ||
97 | CONFIG_NFT_RBTREE=m | ||
98 | CONFIG_NFT_HASH=m | ||
99 | CONFIG_NFT_COUNTER=m | ||
100 | CONFIG_NFT_LOG=m | ||
101 | CONFIG_NFT_LIMIT=m | ||
102 | CONFIG_NFT_NAT=m | ||
103 | CONFIG_NFT_COMPAT=m | ||
94 | CONFIG_NETFILTER_XT_SET=m | 104 | CONFIG_NETFILTER_XT_SET=m |
95 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 105 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
96 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 106 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -104,6 +114,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
104 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 114 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
105 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 115 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
106 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 116 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
117 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
107 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 118 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
108 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 119 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
109 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 120 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -136,6 +147,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
136 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 147 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
137 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 148 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
138 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 149 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
150 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
139 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 151 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
140 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 152 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
141 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 153 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -150,11 +162,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
150 | CONFIG_IP_SET_HASH_IPPORT=m | 162 | CONFIG_IP_SET_HASH_IPPORT=m |
151 | CONFIG_IP_SET_HASH_IPPORTIP=m | 163 | CONFIG_IP_SET_HASH_IPPORTIP=m |
152 | CONFIG_IP_SET_HASH_IPPORTNET=m | 164 | CONFIG_IP_SET_HASH_IPPORTNET=m |
165 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
153 | CONFIG_IP_SET_HASH_NET=m | 166 | CONFIG_IP_SET_HASH_NET=m |
167 | CONFIG_IP_SET_HASH_NETNET=m | ||
154 | CONFIG_IP_SET_HASH_NETPORT=m | 168 | CONFIG_IP_SET_HASH_NETPORT=m |
155 | CONFIG_IP_SET_HASH_NETIFACE=m | 169 | CONFIG_IP_SET_HASH_NETIFACE=m |
156 | CONFIG_IP_SET_LIST_SET=m | 170 | CONFIG_IP_SET_LIST_SET=m |
157 | CONFIG_NF_CONNTRACK_IPV4=m | 171 | CONFIG_NF_CONNTRACK_IPV4=m |
172 | CONFIG_NF_TABLES_IPV4=m | ||
173 | CONFIG_NFT_REJECT_IPV4=m | ||
174 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
175 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
176 | CONFIG_NF_TABLES_ARP=m | ||
158 | CONFIG_IP_NF_IPTABLES=m | 177 | CONFIG_IP_NF_IPTABLES=m |
159 | CONFIG_IP_NF_MATCH_AH=m | 178 | CONFIG_IP_NF_MATCH_AH=m |
160 | CONFIG_IP_NF_MATCH_ECN=m | 179 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -162,6 +181,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
162 | CONFIG_IP_NF_MATCH_TTL=m | 181 | CONFIG_IP_NF_MATCH_TTL=m |
163 | CONFIG_IP_NF_FILTER=m | 182 | CONFIG_IP_NF_FILTER=m |
164 | CONFIG_IP_NF_TARGET_REJECT=m | 183 | CONFIG_IP_NF_TARGET_REJECT=m |
184 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
165 | CONFIG_IP_NF_TARGET_ULOG=m | 185 | CONFIG_IP_NF_TARGET_ULOG=m |
166 | CONFIG_NF_NAT_IPV4=m | 186 | CONFIG_NF_NAT_IPV4=m |
167 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 187 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -176,6 +196,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
176 | CONFIG_IP_NF_ARPFILTER=m | 196 | CONFIG_IP_NF_ARPFILTER=m |
177 | CONFIG_IP_NF_ARP_MANGLE=m | 197 | CONFIG_IP_NF_ARP_MANGLE=m |
178 | CONFIG_NF_CONNTRACK_IPV6=m | 198 | CONFIG_NF_CONNTRACK_IPV6=m |
199 | CONFIG_NF_TABLES_IPV6=m | ||
200 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
201 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
179 | CONFIG_IP6_NF_IPTABLES=m | 202 | CONFIG_IP6_NF_IPTABLES=m |
180 | CONFIG_IP6_NF_MATCH_AH=m | 203 | CONFIG_IP6_NF_MATCH_AH=m |
181 | CONFIG_IP6_NF_MATCH_EUI64=m | 204 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -189,11 +212,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
189 | CONFIG_IP6_NF_TARGET_HL=m | 212 | CONFIG_IP6_NF_TARGET_HL=m |
190 | CONFIG_IP6_NF_FILTER=m | 213 | CONFIG_IP6_NF_FILTER=m |
191 | CONFIG_IP6_NF_TARGET_REJECT=m | 214 | CONFIG_IP6_NF_TARGET_REJECT=m |
215 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
192 | CONFIG_IP6_NF_MANGLE=m | 216 | CONFIG_IP6_NF_MANGLE=m |
193 | CONFIG_IP6_NF_RAW=m | 217 | CONFIG_IP6_NF_RAW=m |
194 | CONFIG_NF_NAT_IPV6=m | 218 | CONFIG_NF_NAT_IPV6=m |
195 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 219 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
196 | CONFIG_IP6_NF_TARGET_NPT=m | 220 | CONFIG_IP6_NF_TARGET_NPT=m |
221 | CONFIG_NF_TABLES_BRIDGE=m | ||
197 | CONFIG_IP_DCCP=m | 222 | CONFIG_IP_DCCP=m |
198 | # CONFIG_IP_DCCP_CCID3 is not set | 223 | # CONFIG_IP_DCCP_CCID3 is not set |
199 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 224 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -204,11 +229,13 @@ CONFIG_ATALK=m | |||
204 | CONFIG_DEV_APPLETALK=m | 229 | CONFIG_DEV_APPLETALK=m |
205 | CONFIG_IPDDP=m | 230 | CONFIG_IPDDP=m |
206 | CONFIG_IPDDP_ENCAP=y | 231 | CONFIG_IPDDP_ENCAP=y |
207 | CONFIG_IPDDP_DECAP=y | 232 | CONFIG_DNS_RESOLVER=y |
208 | CONFIG_BATMAN_ADV=m | 233 | CONFIG_BATMAN_ADV=m |
209 | CONFIG_BATMAN_ADV_DAT=y | 234 | CONFIG_BATMAN_ADV_DAT=y |
235 | CONFIG_BATMAN_ADV_NC=y | ||
236 | CONFIG_NETLINK_DIAG=m | ||
237 | CONFIG_NET_MPLS_GSO=m | ||
210 | # CONFIG_WIRELESS is not set | 238 | # CONFIG_WIRELESS is not set |
211 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
212 | CONFIG_DEVTMPFS=y | 239 | CONFIG_DEVTMPFS=y |
213 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 240 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
214 | # CONFIG_FW_LOADER_USER_HELPER is not set | 241 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -230,6 +257,7 @@ CONFIG_BLK_DEV_NBD=m | |||
230 | CONFIG_BLK_DEV_RAM=y | 257 | CONFIG_BLK_DEV_RAM=y |
231 | CONFIG_CDROM_PKTCDVD=m | 258 | CONFIG_CDROM_PKTCDVD=m |
232 | CONFIG_ATA_OVER_ETH=m | 259 | CONFIG_ATA_OVER_ETH=m |
260 | CONFIG_DUMMY_IRQ=m | ||
233 | CONFIG_IDE=y | 261 | CONFIG_IDE=y |
234 | CONFIG_IDE_GD_ATAPI=y | 262 | CONFIG_IDE_GD_ATAPI=y |
235 | CONFIG_BLK_DEV_IDECD=y | 263 | CONFIG_BLK_DEV_IDECD=y |
@@ -290,10 +318,10 @@ CONFIG_MAC_EMUMOUSEBTN=y | |||
290 | CONFIG_NETDEVICES=y | 318 | CONFIG_NETDEVICES=y |
291 | CONFIG_DUMMY=m | 319 | CONFIG_DUMMY=m |
292 | CONFIG_EQUALIZER=m | 320 | CONFIG_EQUALIZER=m |
293 | CONFIG_MII=y | ||
294 | CONFIG_NET_TEAM=m | 321 | CONFIG_NET_TEAM=m |
295 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 322 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
296 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 323 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
324 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
297 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 325 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
298 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 326 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
299 | CONFIG_VXLAN=m | 327 | CONFIG_VXLAN=m |
@@ -308,10 +336,10 @@ CONFIG_HPLANCE=y | |||
308 | CONFIG_MVME147_NET=y | 336 | CONFIG_MVME147_NET=y |
309 | CONFIG_SUN3LANCE=y | 337 | CONFIG_SUN3LANCE=y |
310 | CONFIG_MACMACE=y | 338 | CONFIG_MACMACE=y |
339 | # CONFIG_NET_VENDOR_ARC is not set | ||
311 | # CONFIG_NET_CADENCE is not set | 340 | # CONFIG_NET_CADENCE is not set |
312 | # CONFIG_NET_VENDOR_BROADCOM is not set | 341 | # CONFIG_NET_VENDOR_BROADCOM is not set |
313 | CONFIG_MAC89x0=y | 342 | CONFIG_MAC89x0=y |
314 | # CONFIG_NET_VENDOR_FUJITSU is not set | ||
315 | # CONFIG_NET_VENDOR_HP is not set | 343 | # CONFIG_NET_VENDOR_HP is not set |
316 | CONFIG_BVME6000_NET=y | 344 | CONFIG_BVME6000_NET=y |
317 | CONFIG_MVME16x_NET=y | 345 | CONFIG_MVME16x_NET=y |
@@ -325,6 +353,7 @@ CONFIG_APNE=y | |||
325 | CONFIG_ZORRO8390=y | 353 | CONFIG_ZORRO8390=y |
326 | # CONFIG_NET_VENDOR_SEEQ is not set | 354 | # CONFIG_NET_VENDOR_SEEQ is not set |
327 | # CONFIG_NET_VENDOR_STMICRO is not set | 355 | # CONFIG_NET_VENDOR_STMICRO is not set |
356 | # CONFIG_NET_VENDOR_VIA is not set | ||
328 | # CONFIG_NET_VENDOR_WIZNET is not set | 357 | # CONFIG_NET_VENDOR_WIZNET is not set |
329 | CONFIG_PLIP=m | 358 | CONFIG_PLIP=m |
330 | CONFIG_PPP=m | 359 | CONFIG_PPP=m |
@@ -357,7 +386,6 @@ CONFIG_INPUT_MISC=y | |||
357 | CONFIG_INPUT_M68K_BEEP=m | 386 | CONFIG_INPUT_M68K_BEEP=m |
358 | CONFIG_HP_SDC_RTC=m | 387 | CONFIG_HP_SDC_RTC=m |
359 | CONFIG_SERIO_Q40KBD=y | 388 | CONFIG_SERIO_Q40KBD=y |
360 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
361 | # CONFIG_LEGACY_PTYS is not set | 389 | # CONFIG_LEGACY_PTYS is not set |
362 | # CONFIG_DEVKMEM is not set | 390 | # CONFIG_DEVKMEM is not set |
363 | CONFIG_SERIAL_PMACZILOG=y | 391 | CONFIG_SERIAL_PMACZILOG=y |
@@ -405,10 +433,6 @@ CONFIG_NFETH=y | |||
405 | CONFIG_ATARI_DSP56K=m | 433 | CONFIG_ATARI_DSP56K=m |
406 | CONFIG_AMIGA_BUILTIN_SERIAL=y | 434 | CONFIG_AMIGA_BUILTIN_SERIAL=y |
407 | CONFIG_SERIAL_CONSOLE=y | 435 | CONFIG_SERIAL_CONSOLE=y |
408 | CONFIG_EXT2_FS=y | ||
409 | CONFIG_EXT3_FS=y | ||
410 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
411 | # CONFIG_EXT3_FS_XATTR is not set | ||
412 | CONFIG_EXT4_FS=y | 436 | CONFIG_EXT4_FS=y |
413 | CONFIG_REISERFS_FS=m | 437 | CONFIG_REISERFS_FS=m |
414 | CONFIG_JFS_FS=m | 438 | CONFIG_JFS_FS=m |
@@ -445,7 +469,7 @@ CONFIG_QNX6FS_FS=m | |||
445 | CONFIG_SYSV_FS=m | 469 | CONFIG_SYSV_FS=m |
446 | CONFIG_UFS_FS=m | 470 | CONFIG_UFS_FS=m |
447 | CONFIG_NFS_FS=y | 471 | CONFIG_NFS_FS=y |
448 | CONFIG_NFS_V4=y | 472 | CONFIG_NFS_V4=m |
449 | CONFIG_NFS_SWAP=y | 473 | CONFIG_NFS_SWAP=y |
450 | CONFIG_ROOT_NFS=y | 474 | CONFIG_ROOT_NFS=y |
451 | CONFIG_NFSD=m | 475 | CONFIG_NFSD=m |
@@ -504,10 +528,11 @@ CONFIG_NLS_MAC_TURKISH=m | |||
504 | CONFIG_DLM=m | 528 | CONFIG_DLM=m |
505 | CONFIG_MAGIC_SYSRQ=y | 529 | CONFIG_MAGIC_SYSRQ=y |
506 | CONFIG_ASYNC_RAID6_TEST=m | 530 | CONFIG_ASYNC_RAID6_TEST=m |
531 | CONFIG_TEST_STRING_HELPERS=m | ||
532 | CONFIG_EARLY_PRINTK=y | ||
507 | CONFIG_ENCRYPTED_KEYS=m | 533 | CONFIG_ENCRYPTED_KEYS=m |
508 | CONFIG_CRYPTO_MANAGER=y | 534 | CONFIG_CRYPTO_MANAGER=y |
509 | CONFIG_CRYPTO_USER=m | 535 | CONFIG_CRYPTO_USER=m |
510 | CONFIG_CRYPTO_NULL=m | ||
511 | CONFIG_CRYPTO_CRYPTD=m | 536 | CONFIG_CRYPTO_CRYPTD=m |
512 | CONFIG_CRYPTO_TEST=m | 537 | CONFIG_CRYPTO_TEST=m |
513 | CONFIG_CRYPTO_CCM=m | 538 | CONFIG_CRYPTO_CCM=m |
@@ -540,6 +565,8 @@ CONFIG_CRYPTO_TEA=m | |||
540 | CONFIG_CRYPTO_TWOFISH=m | 565 | CONFIG_CRYPTO_TWOFISH=m |
541 | CONFIG_CRYPTO_ZLIB=m | 566 | CONFIG_CRYPTO_ZLIB=m |
542 | CONFIG_CRYPTO_LZO=m | 567 | CONFIG_CRYPTO_LZO=m |
568 | CONFIG_CRYPTO_LZ4=m | ||
569 | CONFIG_CRYPTO_LZ4HC=m | ||
543 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 570 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
544 | CONFIG_CRYPTO_USER_API_HASH=m | 571 | CONFIG_CRYPTO_USER_API_HASH=m |
545 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 572 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 5586c6529fce..02cdbac5565e 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig | |||
@@ -47,7 +47,6 @@ CONFIG_IP_PNP_RARP=y | |||
47 | CONFIG_NET_IPIP=m | 47 | CONFIG_NET_IPIP=m |
48 | CONFIG_NET_IPGRE_DEMUX=m | 48 | CONFIG_NET_IPGRE_DEMUX=m |
49 | CONFIG_NET_IPGRE=m | 49 | CONFIG_NET_IPGRE=m |
50 | CONFIG_SYN_COOKIES=y | ||
51 | CONFIG_NET_IPVTI=m | 50 | CONFIG_NET_IPVTI=m |
52 | CONFIG_INET_AH=m | 51 | CONFIG_INET_AH=m |
53 | CONFIG_INET_ESP=m | 52 | CONFIG_INET_ESP=m |
@@ -58,11 +57,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
58 | # CONFIG_INET_LRO is not set | 57 | # CONFIG_INET_LRO is not set |
59 | CONFIG_INET_DIAG=m | 58 | CONFIG_INET_DIAG=m |
60 | CONFIG_INET_UDP_DIAG=m | 59 | CONFIG_INET_UDP_DIAG=m |
61 | CONFIG_IPV6_PRIVACY=y | ||
62 | CONFIG_IPV6_ROUTER_PREF=y | 60 | CONFIG_IPV6_ROUTER_PREF=y |
63 | CONFIG_INET6_AH=m | 61 | CONFIG_INET6_AH=m |
64 | CONFIG_INET6_ESP=m | 62 | CONFIG_INET6_ESP=m |
65 | CONFIG_INET6_IPCOMP=m | 63 | CONFIG_INET6_IPCOMP=m |
64 | CONFIG_IPV6_VTI=m | ||
66 | CONFIG_IPV6_GRE=m | 65 | CONFIG_IPV6_GRE=m |
67 | CONFIG_NETFILTER=y | 66 | CONFIG_NETFILTER=y |
68 | CONFIG_NF_CONNTRACK=m | 67 | CONFIG_NF_CONNTRACK=m |
@@ -80,6 +79,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
80 | CONFIG_NF_CONNTRACK_SANE=m | 79 | CONFIG_NF_CONNTRACK_SANE=m |
81 | CONFIG_NF_CONNTRACK_SIP=m | 80 | CONFIG_NF_CONNTRACK_SIP=m |
82 | CONFIG_NF_CONNTRACK_TFTP=m | 81 | CONFIG_NF_CONNTRACK_TFTP=m |
82 | CONFIG_NF_TABLES=m | ||
83 | CONFIG_NFT_EXTHDR=m | ||
84 | CONFIG_NFT_META=m | ||
85 | CONFIG_NFT_CT=m | ||
86 | CONFIG_NFT_RBTREE=m | ||
87 | CONFIG_NFT_HASH=m | ||
88 | CONFIG_NFT_COUNTER=m | ||
89 | CONFIG_NFT_LOG=m | ||
90 | CONFIG_NFT_LIMIT=m | ||
91 | CONFIG_NFT_NAT=m | ||
92 | CONFIG_NFT_COMPAT=m | ||
83 | CONFIG_NETFILTER_XT_SET=m | 93 | CONFIG_NETFILTER_XT_SET=m |
84 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 94 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
85 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 95 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -93,6 +103,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
93 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 103 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
94 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 104 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
95 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 105 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
106 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
96 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 107 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
97 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 108 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
98 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 109 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -125,6 +136,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
125 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 136 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
126 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 137 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
127 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 138 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
139 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
128 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 140 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
129 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 141 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
130 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 142 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -139,11 +151,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
139 | CONFIG_IP_SET_HASH_IPPORT=m | 151 | CONFIG_IP_SET_HASH_IPPORT=m |
140 | CONFIG_IP_SET_HASH_IPPORTIP=m | 152 | CONFIG_IP_SET_HASH_IPPORTIP=m |
141 | CONFIG_IP_SET_HASH_IPPORTNET=m | 153 | CONFIG_IP_SET_HASH_IPPORTNET=m |
154 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
142 | CONFIG_IP_SET_HASH_NET=m | 155 | CONFIG_IP_SET_HASH_NET=m |
156 | CONFIG_IP_SET_HASH_NETNET=m | ||
143 | CONFIG_IP_SET_HASH_NETPORT=m | 157 | CONFIG_IP_SET_HASH_NETPORT=m |
144 | CONFIG_IP_SET_HASH_NETIFACE=m | 158 | CONFIG_IP_SET_HASH_NETIFACE=m |
145 | CONFIG_IP_SET_LIST_SET=m | 159 | CONFIG_IP_SET_LIST_SET=m |
146 | CONFIG_NF_CONNTRACK_IPV4=m | 160 | CONFIG_NF_CONNTRACK_IPV4=m |
161 | CONFIG_NF_TABLES_IPV4=m | ||
162 | CONFIG_NFT_REJECT_IPV4=m | ||
163 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
164 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
165 | CONFIG_NF_TABLES_ARP=m | ||
147 | CONFIG_IP_NF_IPTABLES=m | 166 | CONFIG_IP_NF_IPTABLES=m |
148 | CONFIG_IP_NF_MATCH_AH=m | 167 | CONFIG_IP_NF_MATCH_AH=m |
149 | CONFIG_IP_NF_MATCH_ECN=m | 168 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -151,6 +170,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
151 | CONFIG_IP_NF_MATCH_TTL=m | 170 | CONFIG_IP_NF_MATCH_TTL=m |
152 | CONFIG_IP_NF_FILTER=m | 171 | CONFIG_IP_NF_FILTER=m |
153 | CONFIG_IP_NF_TARGET_REJECT=m | 172 | CONFIG_IP_NF_TARGET_REJECT=m |
173 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
154 | CONFIG_IP_NF_TARGET_ULOG=m | 174 | CONFIG_IP_NF_TARGET_ULOG=m |
155 | CONFIG_NF_NAT_IPV4=m | 175 | CONFIG_NF_NAT_IPV4=m |
156 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 176 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -165,6 +185,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
165 | CONFIG_IP_NF_ARPFILTER=m | 185 | CONFIG_IP_NF_ARPFILTER=m |
166 | CONFIG_IP_NF_ARP_MANGLE=m | 186 | CONFIG_IP_NF_ARP_MANGLE=m |
167 | CONFIG_NF_CONNTRACK_IPV6=m | 187 | CONFIG_NF_CONNTRACK_IPV6=m |
188 | CONFIG_NF_TABLES_IPV6=m | ||
189 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
190 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
168 | CONFIG_IP6_NF_IPTABLES=m | 191 | CONFIG_IP6_NF_IPTABLES=m |
169 | CONFIG_IP6_NF_MATCH_AH=m | 192 | CONFIG_IP6_NF_MATCH_AH=m |
170 | CONFIG_IP6_NF_MATCH_EUI64=m | 193 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -178,11 +201,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
178 | CONFIG_IP6_NF_TARGET_HL=m | 201 | CONFIG_IP6_NF_TARGET_HL=m |
179 | CONFIG_IP6_NF_FILTER=m | 202 | CONFIG_IP6_NF_FILTER=m |
180 | CONFIG_IP6_NF_TARGET_REJECT=m | 203 | CONFIG_IP6_NF_TARGET_REJECT=m |
204 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
181 | CONFIG_IP6_NF_MANGLE=m | 205 | CONFIG_IP6_NF_MANGLE=m |
182 | CONFIG_IP6_NF_RAW=m | 206 | CONFIG_IP6_NF_RAW=m |
183 | CONFIG_NF_NAT_IPV6=m | 207 | CONFIG_NF_NAT_IPV6=m |
184 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 208 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
185 | CONFIG_IP6_NF_TARGET_NPT=m | 209 | CONFIG_IP6_NF_TARGET_NPT=m |
210 | CONFIG_NF_TABLES_BRIDGE=m | ||
186 | CONFIG_IP_DCCP=m | 211 | CONFIG_IP_DCCP=m |
187 | # CONFIG_IP_DCCP_CCID3 is not set | 212 | # CONFIG_IP_DCCP_CCID3 is not set |
188 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 213 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -190,10 +215,13 @@ CONFIG_RDS=m | |||
190 | CONFIG_RDS_TCP=m | 215 | CONFIG_RDS_TCP=m |
191 | CONFIG_L2TP=m | 216 | CONFIG_L2TP=m |
192 | CONFIG_ATALK=m | 217 | CONFIG_ATALK=m |
218 | CONFIG_DNS_RESOLVER=y | ||
193 | CONFIG_BATMAN_ADV=m | 219 | CONFIG_BATMAN_ADV=m |
194 | CONFIG_BATMAN_ADV_DAT=y | 220 | CONFIG_BATMAN_ADV_DAT=y |
221 | CONFIG_BATMAN_ADV_NC=y | ||
222 | CONFIG_NETLINK_DIAG=m | ||
223 | CONFIG_NET_MPLS_GSO=m | ||
195 | # CONFIG_WIRELESS is not set | 224 | # CONFIG_WIRELESS is not set |
196 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
197 | CONFIG_DEVTMPFS=y | 225 | CONFIG_DEVTMPFS=y |
198 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 226 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
199 | # CONFIG_FW_LOADER_USER_HELPER is not set | 227 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -205,6 +233,7 @@ CONFIG_BLK_DEV_NBD=m | |||
205 | CONFIG_BLK_DEV_RAM=y | 233 | CONFIG_BLK_DEV_RAM=y |
206 | CONFIG_CDROM_PKTCDVD=m | 234 | CONFIG_CDROM_PKTCDVD=m |
207 | CONFIG_ATA_OVER_ETH=m | 235 | CONFIG_ATA_OVER_ETH=m |
236 | CONFIG_DUMMY_IRQ=m | ||
208 | CONFIG_RAID_ATTRS=m | 237 | CONFIG_RAID_ATTRS=m |
209 | CONFIG_SCSI=y | 238 | CONFIG_SCSI=y |
210 | CONFIG_SCSI_TGT=m | 239 | CONFIG_SCSI_TGT=m |
@@ -242,6 +271,7 @@ CONFIG_EQUALIZER=m | |||
242 | CONFIG_NET_TEAM=m | 271 | CONFIG_NET_TEAM=m |
243 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 272 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
244 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 273 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
274 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
245 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 275 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
246 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 276 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
247 | CONFIG_VXLAN=m | 277 | CONFIG_VXLAN=m |
@@ -249,6 +279,7 @@ CONFIG_NETCONSOLE=m | |||
249 | CONFIG_NETCONSOLE_DYNAMIC=y | 279 | CONFIG_NETCONSOLE_DYNAMIC=y |
250 | CONFIG_VETH=m | 280 | CONFIG_VETH=m |
251 | CONFIG_MVME147_NET=y | 281 | CONFIG_MVME147_NET=y |
282 | # CONFIG_NET_VENDOR_ARC is not set | ||
252 | # CONFIG_NET_CADENCE is not set | 283 | # CONFIG_NET_CADENCE is not set |
253 | # CONFIG_NET_VENDOR_BROADCOM is not set | 284 | # CONFIG_NET_VENDOR_BROADCOM is not set |
254 | # CONFIG_NET_VENDOR_INTEL is not set | 285 | # CONFIG_NET_VENDOR_INTEL is not set |
@@ -257,6 +288,7 @@ CONFIG_MVME147_NET=y | |||
257 | # CONFIG_NET_VENDOR_NATSEMI is not set | 288 | # CONFIG_NET_VENDOR_NATSEMI is not set |
258 | # CONFIG_NET_VENDOR_SEEQ is not set | 289 | # CONFIG_NET_VENDOR_SEEQ is not set |
259 | # CONFIG_NET_VENDOR_STMICRO is not set | 290 | # CONFIG_NET_VENDOR_STMICRO is not set |
291 | # CONFIG_NET_VENDOR_VIA is not set | ||
260 | # CONFIG_NET_VENDOR_WIZNET is not set | 292 | # CONFIG_NET_VENDOR_WIZNET is not set |
261 | CONFIG_PPP=m | 293 | CONFIG_PPP=m |
262 | CONFIG_PPP_BSDCOMP=m | 294 | CONFIG_PPP_BSDCOMP=m |
@@ -294,10 +326,6 @@ CONFIG_RTC_CLASS=y | |||
294 | CONFIG_RTC_DRV_GENERIC=m | 326 | CONFIG_RTC_DRV_GENERIC=m |
295 | # CONFIG_IOMMU_SUPPORT is not set | 327 | # CONFIG_IOMMU_SUPPORT is not set |
296 | CONFIG_PROC_HARDWARE=y | 328 | CONFIG_PROC_HARDWARE=y |
297 | CONFIG_EXT2_FS=y | ||
298 | CONFIG_EXT3_FS=y | ||
299 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
300 | # CONFIG_EXT3_FS_XATTR is not set | ||
301 | CONFIG_EXT4_FS=y | 329 | CONFIG_EXT4_FS=y |
302 | CONFIG_REISERFS_FS=m | 330 | CONFIG_REISERFS_FS=m |
303 | CONFIG_JFS_FS=m | 331 | CONFIG_JFS_FS=m |
@@ -334,7 +362,7 @@ CONFIG_QNX6FS_FS=m | |||
334 | CONFIG_SYSV_FS=m | 362 | CONFIG_SYSV_FS=m |
335 | CONFIG_UFS_FS=m | 363 | CONFIG_UFS_FS=m |
336 | CONFIG_NFS_FS=y | 364 | CONFIG_NFS_FS=y |
337 | CONFIG_NFS_V4=y | 365 | CONFIG_NFS_V4=m |
338 | CONFIG_NFS_SWAP=y | 366 | CONFIG_NFS_SWAP=y |
339 | CONFIG_ROOT_NFS=y | 367 | CONFIG_ROOT_NFS=y |
340 | CONFIG_NFSD=m | 368 | CONFIG_NFSD=m |
@@ -393,10 +421,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
393 | CONFIG_DLM=m | 421 | CONFIG_DLM=m |
394 | CONFIG_MAGIC_SYSRQ=y | 422 | CONFIG_MAGIC_SYSRQ=y |
395 | CONFIG_ASYNC_RAID6_TEST=m | 423 | CONFIG_ASYNC_RAID6_TEST=m |
424 | CONFIG_TEST_STRING_HELPERS=m | ||
396 | CONFIG_ENCRYPTED_KEYS=m | 425 | CONFIG_ENCRYPTED_KEYS=m |
397 | CONFIG_CRYPTO_MANAGER=y | 426 | CONFIG_CRYPTO_MANAGER=y |
398 | CONFIG_CRYPTO_USER=m | 427 | CONFIG_CRYPTO_USER=m |
399 | CONFIG_CRYPTO_NULL=m | ||
400 | CONFIG_CRYPTO_CRYPTD=m | 428 | CONFIG_CRYPTO_CRYPTD=m |
401 | CONFIG_CRYPTO_TEST=m | 429 | CONFIG_CRYPTO_TEST=m |
402 | CONFIG_CRYPTO_CCM=m | 430 | CONFIG_CRYPTO_CCM=m |
@@ -429,6 +457,8 @@ CONFIG_CRYPTO_TEA=m | |||
429 | CONFIG_CRYPTO_TWOFISH=m | 457 | CONFIG_CRYPTO_TWOFISH=m |
430 | CONFIG_CRYPTO_ZLIB=m | 458 | CONFIG_CRYPTO_ZLIB=m |
431 | CONFIG_CRYPTO_LZO=m | 459 | CONFIG_CRYPTO_LZO=m |
460 | CONFIG_CRYPTO_LZ4=m | ||
461 | CONFIG_CRYPTO_LZ4HC=m | ||
432 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 462 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
433 | CONFIG_CRYPTO_USER_API_HASH=m | 463 | CONFIG_CRYPTO_USER_API_HASH=m |
434 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 464 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index e5e8262bbacd..05a990a9dbd4 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig | |||
@@ -48,7 +48,6 @@ CONFIG_IP_PNP_RARP=y | |||
48 | CONFIG_NET_IPIP=m | 48 | CONFIG_NET_IPIP=m |
49 | CONFIG_NET_IPGRE_DEMUX=m | 49 | CONFIG_NET_IPGRE_DEMUX=m |
50 | CONFIG_NET_IPGRE=m | 50 | CONFIG_NET_IPGRE=m |
51 | CONFIG_SYN_COOKIES=y | ||
52 | CONFIG_NET_IPVTI=m | 51 | CONFIG_NET_IPVTI=m |
53 | CONFIG_INET_AH=m | 52 | CONFIG_INET_AH=m |
54 | CONFIG_INET_ESP=m | 53 | CONFIG_INET_ESP=m |
@@ -59,11 +58,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
59 | # CONFIG_INET_LRO is not set | 58 | # CONFIG_INET_LRO is not set |
60 | CONFIG_INET_DIAG=m | 59 | CONFIG_INET_DIAG=m |
61 | CONFIG_INET_UDP_DIAG=m | 60 | CONFIG_INET_UDP_DIAG=m |
62 | CONFIG_IPV6_PRIVACY=y | ||
63 | CONFIG_IPV6_ROUTER_PREF=y | 61 | CONFIG_IPV6_ROUTER_PREF=y |
64 | CONFIG_INET6_AH=m | 62 | CONFIG_INET6_AH=m |
65 | CONFIG_INET6_ESP=m | 63 | CONFIG_INET6_ESP=m |
66 | CONFIG_INET6_IPCOMP=m | 64 | CONFIG_INET6_IPCOMP=m |
65 | CONFIG_IPV6_VTI=m | ||
67 | CONFIG_IPV6_GRE=m | 66 | CONFIG_IPV6_GRE=m |
68 | CONFIG_NETFILTER=y | 67 | CONFIG_NETFILTER=y |
69 | CONFIG_NF_CONNTRACK=m | 68 | CONFIG_NF_CONNTRACK=m |
@@ -81,6 +80,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
81 | CONFIG_NF_CONNTRACK_SANE=m | 80 | CONFIG_NF_CONNTRACK_SANE=m |
82 | CONFIG_NF_CONNTRACK_SIP=m | 81 | CONFIG_NF_CONNTRACK_SIP=m |
83 | CONFIG_NF_CONNTRACK_TFTP=m | 82 | CONFIG_NF_CONNTRACK_TFTP=m |
83 | CONFIG_NF_TABLES=m | ||
84 | CONFIG_NFT_EXTHDR=m | ||
85 | CONFIG_NFT_META=m | ||
86 | CONFIG_NFT_CT=m | ||
87 | CONFIG_NFT_RBTREE=m | ||
88 | CONFIG_NFT_HASH=m | ||
89 | CONFIG_NFT_COUNTER=m | ||
90 | CONFIG_NFT_LOG=m | ||
91 | CONFIG_NFT_LIMIT=m | ||
92 | CONFIG_NFT_NAT=m | ||
93 | CONFIG_NFT_COMPAT=m | ||
84 | CONFIG_NETFILTER_XT_SET=m | 94 | CONFIG_NETFILTER_XT_SET=m |
85 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 95 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
86 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 96 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -94,6 +104,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
94 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 104 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
95 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 105 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
96 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 106 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
107 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
97 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 108 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
98 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 109 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
99 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 110 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -126,6 +137,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
126 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 137 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
127 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 138 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
128 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 139 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
140 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
129 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 141 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
130 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 142 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
131 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 143 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -140,11 +152,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
140 | CONFIG_IP_SET_HASH_IPPORT=m | 152 | CONFIG_IP_SET_HASH_IPPORT=m |
141 | CONFIG_IP_SET_HASH_IPPORTIP=m | 153 | CONFIG_IP_SET_HASH_IPPORTIP=m |
142 | CONFIG_IP_SET_HASH_IPPORTNET=m | 154 | CONFIG_IP_SET_HASH_IPPORTNET=m |
155 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
143 | CONFIG_IP_SET_HASH_NET=m | 156 | CONFIG_IP_SET_HASH_NET=m |
157 | CONFIG_IP_SET_HASH_NETNET=m | ||
144 | CONFIG_IP_SET_HASH_NETPORT=m | 158 | CONFIG_IP_SET_HASH_NETPORT=m |
145 | CONFIG_IP_SET_HASH_NETIFACE=m | 159 | CONFIG_IP_SET_HASH_NETIFACE=m |
146 | CONFIG_IP_SET_LIST_SET=m | 160 | CONFIG_IP_SET_LIST_SET=m |
147 | CONFIG_NF_CONNTRACK_IPV4=m | 161 | CONFIG_NF_CONNTRACK_IPV4=m |
162 | CONFIG_NF_TABLES_IPV4=m | ||
163 | CONFIG_NFT_REJECT_IPV4=m | ||
164 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
165 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
166 | CONFIG_NF_TABLES_ARP=m | ||
148 | CONFIG_IP_NF_IPTABLES=m | 167 | CONFIG_IP_NF_IPTABLES=m |
149 | CONFIG_IP_NF_MATCH_AH=m | 168 | CONFIG_IP_NF_MATCH_AH=m |
150 | CONFIG_IP_NF_MATCH_ECN=m | 169 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -152,6 +171,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
152 | CONFIG_IP_NF_MATCH_TTL=m | 171 | CONFIG_IP_NF_MATCH_TTL=m |
153 | CONFIG_IP_NF_FILTER=m | 172 | CONFIG_IP_NF_FILTER=m |
154 | CONFIG_IP_NF_TARGET_REJECT=m | 173 | CONFIG_IP_NF_TARGET_REJECT=m |
174 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
155 | CONFIG_IP_NF_TARGET_ULOG=m | 175 | CONFIG_IP_NF_TARGET_ULOG=m |
156 | CONFIG_NF_NAT_IPV4=m | 176 | CONFIG_NF_NAT_IPV4=m |
157 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 177 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -166,6 +186,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
166 | CONFIG_IP_NF_ARPFILTER=m | 186 | CONFIG_IP_NF_ARPFILTER=m |
167 | CONFIG_IP_NF_ARP_MANGLE=m | 187 | CONFIG_IP_NF_ARP_MANGLE=m |
168 | CONFIG_NF_CONNTRACK_IPV6=m | 188 | CONFIG_NF_CONNTRACK_IPV6=m |
189 | CONFIG_NF_TABLES_IPV6=m | ||
190 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
191 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
169 | CONFIG_IP6_NF_IPTABLES=m | 192 | CONFIG_IP6_NF_IPTABLES=m |
170 | CONFIG_IP6_NF_MATCH_AH=m | 193 | CONFIG_IP6_NF_MATCH_AH=m |
171 | CONFIG_IP6_NF_MATCH_EUI64=m | 194 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -179,11 +202,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
179 | CONFIG_IP6_NF_TARGET_HL=m | 202 | CONFIG_IP6_NF_TARGET_HL=m |
180 | CONFIG_IP6_NF_FILTER=m | 203 | CONFIG_IP6_NF_FILTER=m |
181 | CONFIG_IP6_NF_TARGET_REJECT=m | 204 | CONFIG_IP6_NF_TARGET_REJECT=m |
205 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
182 | CONFIG_IP6_NF_MANGLE=m | 206 | CONFIG_IP6_NF_MANGLE=m |
183 | CONFIG_IP6_NF_RAW=m | 207 | CONFIG_IP6_NF_RAW=m |
184 | CONFIG_NF_NAT_IPV6=m | 208 | CONFIG_NF_NAT_IPV6=m |
185 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 209 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
186 | CONFIG_IP6_NF_TARGET_NPT=m | 210 | CONFIG_IP6_NF_TARGET_NPT=m |
211 | CONFIG_NF_TABLES_BRIDGE=m | ||
187 | CONFIG_IP_DCCP=m | 212 | CONFIG_IP_DCCP=m |
188 | # CONFIG_IP_DCCP_CCID3 is not set | 213 | # CONFIG_IP_DCCP_CCID3 is not set |
189 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 214 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -191,10 +216,13 @@ CONFIG_RDS=m | |||
191 | CONFIG_RDS_TCP=m | 216 | CONFIG_RDS_TCP=m |
192 | CONFIG_L2TP=m | 217 | CONFIG_L2TP=m |
193 | CONFIG_ATALK=m | 218 | CONFIG_ATALK=m |
219 | CONFIG_DNS_RESOLVER=y | ||
194 | CONFIG_BATMAN_ADV=m | 220 | CONFIG_BATMAN_ADV=m |
195 | CONFIG_BATMAN_ADV_DAT=y | 221 | CONFIG_BATMAN_ADV_DAT=y |
222 | CONFIG_BATMAN_ADV_NC=y | ||
223 | CONFIG_NETLINK_DIAG=m | ||
224 | CONFIG_NET_MPLS_GSO=m | ||
196 | # CONFIG_WIRELESS is not set | 225 | # CONFIG_WIRELESS is not set |
197 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
198 | CONFIG_DEVTMPFS=y | 226 | CONFIG_DEVTMPFS=y |
199 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 227 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
200 | # CONFIG_FW_LOADER_USER_HELPER is not set | 228 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -206,6 +234,7 @@ CONFIG_BLK_DEV_NBD=m | |||
206 | CONFIG_BLK_DEV_RAM=y | 234 | CONFIG_BLK_DEV_RAM=y |
207 | CONFIG_CDROM_PKTCDVD=m | 235 | CONFIG_CDROM_PKTCDVD=m |
208 | CONFIG_ATA_OVER_ETH=m | 236 | CONFIG_ATA_OVER_ETH=m |
237 | CONFIG_DUMMY_IRQ=m | ||
209 | CONFIG_RAID_ATTRS=m | 238 | CONFIG_RAID_ATTRS=m |
210 | CONFIG_SCSI=y | 239 | CONFIG_SCSI=y |
211 | CONFIG_SCSI_TGT=m | 240 | CONFIG_SCSI_TGT=m |
@@ -243,12 +272,14 @@ CONFIG_EQUALIZER=m | |||
243 | CONFIG_NET_TEAM=m | 272 | CONFIG_NET_TEAM=m |
244 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 273 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
245 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 274 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
275 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
246 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 276 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
247 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 277 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
248 | CONFIG_VXLAN=m | 278 | CONFIG_VXLAN=m |
249 | CONFIG_NETCONSOLE=m | 279 | CONFIG_NETCONSOLE=m |
250 | CONFIG_NETCONSOLE_DYNAMIC=y | 280 | CONFIG_NETCONSOLE_DYNAMIC=y |
251 | CONFIG_VETH=m | 281 | CONFIG_VETH=m |
282 | # CONFIG_NET_VENDOR_ARC is not set | ||
252 | # CONFIG_NET_CADENCE is not set | 283 | # CONFIG_NET_CADENCE is not set |
253 | # CONFIG_NET_VENDOR_BROADCOM is not set | 284 | # CONFIG_NET_VENDOR_BROADCOM is not set |
254 | CONFIG_MVME16x_NET=y | 285 | CONFIG_MVME16x_NET=y |
@@ -257,6 +288,7 @@ CONFIG_MVME16x_NET=y | |||
257 | # CONFIG_NET_VENDOR_NATSEMI is not set | 288 | # CONFIG_NET_VENDOR_NATSEMI is not set |
258 | # CONFIG_NET_VENDOR_SEEQ is not set | 289 | # CONFIG_NET_VENDOR_SEEQ is not set |
259 | # CONFIG_NET_VENDOR_STMICRO is not set | 290 | # CONFIG_NET_VENDOR_STMICRO is not set |
291 | # CONFIG_NET_VENDOR_VIA is not set | ||
260 | # CONFIG_NET_VENDOR_WIZNET is not set | 292 | # CONFIG_NET_VENDOR_WIZNET is not set |
261 | CONFIG_PPP=m | 293 | CONFIG_PPP=m |
262 | CONFIG_PPP_BSDCOMP=m | 294 | CONFIG_PPP_BSDCOMP=m |
@@ -294,10 +326,6 @@ CONFIG_RTC_CLASS=y | |||
294 | CONFIG_RTC_DRV_GENERIC=m | 326 | CONFIG_RTC_DRV_GENERIC=m |
295 | # CONFIG_IOMMU_SUPPORT is not set | 327 | # CONFIG_IOMMU_SUPPORT is not set |
296 | CONFIG_PROC_HARDWARE=y | 328 | CONFIG_PROC_HARDWARE=y |
297 | CONFIG_EXT2_FS=y | ||
298 | CONFIG_EXT3_FS=y | ||
299 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
300 | # CONFIG_EXT3_FS_XATTR is not set | ||
301 | CONFIG_EXT4_FS=y | 329 | CONFIG_EXT4_FS=y |
302 | CONFIG_REISERFS_FS=m | 330 | CONFIG_REISERFS_FS=m |
303 | CONFIG_JFS_FS=m | 331 | CONFIG_JFS_FS=m |
@@ -334,7 +362,7 @@ CONFIG_QNX6FS_FS=m | |||
334 | CONFIG_SYSV_FS=m | 362 | CONFIG_SYSV_FS=m |
335 | CONFIG_UFS_FS=m | 363 | CONFIG_UFS_FS=m |
336 | CONFIG_NFS_FS=y | 364 | CONFIG_NFS_FS=y |
337 | CONFIG_NFS_V4=y | 365 | CONFIG_NFS_V4=m |
338 | CONFIG_NFS_SWAP=y | 366 | CONFIG_NFS_SWAP=y |
339 | CONFIG_ROOT_NFS=y | 367 | CONFIG_ROOT_NFS=y |
340 | CONFIG_NFSD=m | 368 | CONFIG_NFSD=m |
@@ -393,10 +421,11 @@ CONFIG_NLS_MAC_TURKISH=m | |||
393 | CONFIG_DLM=m | 421 | CONFIG_DLM=m |
394 | CONFIG_MAGIC_SYSRQ=y | 422 | CONFIG_MAGIC_SYSRQ=y |
395 | CONFIG_ASYNC_RAID6_TEST=m | 423 | CONFIG_ASYNC_RAID6_TEST=m |
424 | CONFIG_TEST_STRING_HELPERS=m | ||
425 | CONFIG_EARLY_PRINTK=y | ||
396 | CONFIG_ENCRYPTED_KEYS=m | 426 | CONFIG_ENCRYPTED_KEYS=m |
397 | CONFIG_CRYPTO_MANAGER=y | 427 | CONFIG_CRYPTO_MANAGER=y |
398 | CONFIG_CRYPTO_USER=m | 428 | CONFIG_CRYPTO_USER=m |
399 | CONFIG_CRYPTO_NULL=m | ||
400 | CONFIG_CRYPTO_CRYPTD=m | 429 | CONFIG_CRYPTO_CRYPTD=m |
401 | CONFIG_CRYPTO_TEST=m | 430 | CONFIG_CRYPTO_TEST=m |
402 | CONFIG_CRYPTO_CCM=m | 431 | CONFIG_CRYPTO_CCM=m |
@@ -429,6 +458,8 @@ CONFIG_CRYPTO_TEA=m | |||
429 | CONFIG_CRYPTO_TWOFISH=m | 458 | CONFIG_CRYPTO_TWOFISH=m |
430 | CONFIG_CRYPTO_ZLIB=m | 459 | CONFIG_CRYPTO_ZLIB=m |
431 | CONFIG_CRYPTO_LZO=m | 460 | CONFIG_CRYPTO_LZO=m |
461 | CONFIG_CRYPTO_LZ4=m | ||
462 | CONFIG_CRYPTO_LZ4HC=m | ||
432 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 463 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
433 | CONFIG_CRYPTO_USER_API_HASH=m | 464 | CONFIG_CRYPTO_USER_API_HASH=m |
434 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 465 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index be1496ed9b66..568e2a98f976 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig | |||
@@ -48,7 +48,6 @@ CONFIG_IP_PNP_RARP=y | |||
48 | CONFIG_NET_IPIP=m | 48 | CONFIG_NET_IPIP=m |
49 | CONFIG_NET_IPGRE_DEMUX=m | 49 | CONFIG_NET_IPGRE_DEMUX=m |
50 | CONFIG_NET_IPGRE=m | 50 | CONFIG_NET_IPGRE=m |
51 | CONFIG_SYN_COOKIES=y | ||
52 | CONFIG_NET_IPVTI=m | 51 | CONFIG_NET_IPVTI=m |
53 | CONFIG_INET_AH=m | 52 | CONFIG_INET_AH=m |
54 | CONFIG_INET_ESP=m | 53 | CONFIG_INET_ESP=m |
@@ -59,11 +58,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
59 | # CONFIG_INET_LRO is not set | 58 | # CONFIG_INET_LRO is not set |
60 | CONFIG_INET_DIAG=m | 59 | CONFIG_INET_DIAG=m |
61 | CONFIG_INET_UDP_DIAG=m | 60 | CONFIG_INET_UDP_DIAG=m |
62 | CONFIG_IPV6_PRIVACY=y | ||
63 | CONFIG_IPV6_ROUTER_PREF=y | 61 | CONFIG_IPV6_ROUTER_PREF=y |
64 | CONFIG_INET6_AH=m | 62 | CONFIG_INET6_AH=m |
65 | CONFIG_INET6_ESP=m | 63 | CONFIG_INET6_ESP=m |
66 | CONFIG_INET6_IPCOMP=m | 64 | CONFIG_INET6_IPCOMP=m |
65 | CONFIG_IPV6_VTI=m | ||
67 | CONFIG_IPV6_GRE=m | 66 | CONFIG_IPV6_GRE=m |
68 | CONFIG_NETFILTER=y | 67 | CONFIG_NETFILTER=y |
69 | CONFIG_NF_CONNTRACK=m | 68 | CONFIG_NF_CONNTRACK=m |
@@ -81,6 +80,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
81 | CONFIG_NF_CONNTRACK_SANE=m | 80 | CONFIG_NF_CONNTRACK_SANE=m |
82 | CONFIG_NF_CONNTRACK_SIP=m | 81 | CONFIG_NF_CONNTRACK_SIP=m |
83 | CONFIG_NF_CONNTRACK_TFTP=m | 82 | CONFIG_NF_CONNTRACK_TFTP=m |
83 | CONFIG_NF_TABLES=m | ||
84 | CONFIG_NFT_EXTHDR=m | ||
85 | CONFIG_NFT_META=m | ||
86 | CONFIG_NFT_CT=m | ||
87 | CONFIG_NFT_RBTREE=m | ||
88 | CONFIG_NFT_HASH=m | ||
89 | CONFIG_NFT_COUNTER=m | ||
90 | CONFIG_NFT_LOG=m | ||
91 | CONFIG_NFT_LIMIT=m | ||
92 | CONFIG_NFT_NAT=m | ||
93 | CONFIG_NFT_COMPAT=m | ||
84 | CONFIG_NETFILTER_XT_SET=m | 94 | CONFIG_NETFILTER_XT_SET=m |
85 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 95 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
86 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 96 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -94,6 +104,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
94 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 104 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
95 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 105 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
96 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 106 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
107 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
97 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 108 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
98 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 109 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
99 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 110 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -126,6 +137,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
126 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 137 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
127 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 138 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
128 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 139 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
140 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
129 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 141 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
130 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 142 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
131 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 143 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -140,11 +152,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
140 | CONFIG_IP_SET_HASH_IPPORT=m | 152 | CONFIG_IP_SET_HASH_IPPORT=m |
141 | CONFIG_IP_SET_HASH_IPPORTIP=m | 153 | CONFIG_IP_SET_HASH_IPPORTIP=m |
142 | CONFIG_IP_SET_HASH_IPPORTNET=m | 154 | CONFIG_IP_SET_HASH_IPPORTNET=m |
155 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
143 | CONFIG_IP_SET_HASH_NET=m | 156 | CONFIG_IP_SET_HASH_NET=m |
157 | CONFIG_IP_SET_HASH_NETNET=m | ||
144 | CONFIG_IP_SET_HASH_NETPORT=m | 158 | CONFIG_IP_SET_HASH_NETPORT=m |
145 | CONFIG_IP_SET_HASH_NETIFACE=m | 159 | CONFIG_IP_SET_HASH_NETIFACE=m |
146 | CONFIG_IP_SET_LIST_SET=m | 160 | CONFIG_IP_SET_LIST_SET=m |
147 | CONFIG_NF_CONNTRACK_IPV4=m | 161 | CONFIG_NF_CONNTRACK_IPV4=m |
162 | CONFIG_NF_TABLES_IPV4=m | ||
163 | CONFIG_NFT_REJECT_IPV4=m | ||
164 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
165 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
166 | CONFIG_NF_TABLES_ARP=m | ||
148 | CONFIG_IP_NF_IPTABLES=m | 167 | CONFIG_IP_NF_IPTABLES=m |
149 | CONFIG_IP_NF_MATCH_AH=m | 168 | CONFIG_IP_NF_MATCH_AH=m |
150 | CONFIG_IP_NF_MATCH_ECN=m | 169 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -152,6 +171,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
152 | CONFIG_IP_NF_MATCH_TTL=m | 171 | CONFIG_IP_NF_MATCH_TTL=m |
153 | CONFIG_IP_NF_FILTER=m | 172 | CONFIG_IP_NF_FILTER=m |
154 | CONFIG_IP_NF_TARGET_REJECT=m | 173 | CONFIG_IP_NF_TARGET_REJECT=m |
174 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
155 | CONFIG_IP_NF_TARGET_ULOG=m | 175 | CONFIG_IP_NF_TARGET_ULOG=m |
156 | CONFIG_NF_NAT_IPV4=m | 176 | CONFIG_NF_NAT_IPV4=m |
157 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 177 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -166,6 +186,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
166 | CONFIG_IP_NF_ARPFILTER=m | 186 | CONFIG_IP_NF_ARPFILTER=m |
167 | CONFIG_IP_NF_ARP_MANGLE=m | 187 | CONFIG_IP_NF_ARP_MANGLE=m |
168 | CONFIG_NF_CONNTRACK_IPV6=m | 188 | CONFIG_NF_CONNTRACK_IPV6=m |
189 | CONFIG_NF_TABLES_IPV6=m | ||
190 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
191 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
169 | CONFIG_IP6_NF_IPTABLES=m | 192 | CONFIG_IP6_NF_IPTABLES=m |
170 | CONFIG_IP6_NF_MATCH_AH=m | 193 | CONFIG_IP6_NF_MATCH_AH=m |
171 | CONFIG_IP6_NF_MATCH_EUI64=m | 194 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -179,11 +202,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
179 | CONFIG_IP6_NF_TARGET_HL=m | 202 | CONFIG_IP6_NF_TARGET_HL=m |
180 | CONFIG_IP6_NF_FILTER=m | 203 | CONFIG_IP6_NF_FILTER=m |
181 | CONFIG_IP6_NF_TARGET_REJECT=m | 204 | CONFIG_IP6_NF_TARGET_REJECT=m |
205 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
182 | CONFIG_IP6_NF_MANGLE=m | 206 | CONFIG_IP6_NF_MANGLE=m |
183 | CONFIG_IP6_NF_RAW=m | 207 | CONFIG_IP6_NF_RAW=m |
184 | CONFIG_NF_NAT_IPV6=m | 208 | CONFIG_NF_NAT_IPV6=m |
185 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 209 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
186 | CONFIG_IP6_NF_TARGET_NPT=m | 210 | CONFIG_IP6_NF_TARGET_NPT=m |
211 | CONFIG_NF_TABLES_BRIDGE=m | ||
187 | CONFIG_IP_DCCP=m | 212 | CONFIG_IP_DCCP=m |
188 | # CONFIG_IP_DCCP_CCID3 is not set | 213 | # CONFIG_IP_DCCP_CCID3 is not set |
189 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 214 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -191,10 +216,13 @@ CONFIG_RDS=m | |||
191 | CONFIG_RDS_TCP=m | 216 | CONFIG_RDS_TCP=m |
192 | CONFIG_L2TP=m | 217 | CONFIG_L2TP=m |
193 | CONFIG_ATALK=m | 218 | CONFIG_ATALK=m |
219 | CONFIG_DNS_RESOLVER=y | ||
194 | CONFIG_BATMAN_ADV=m | 220 | CONFIG_BATMAN_ADV=m |
195 | CONFIG_BATMAN_ADV_DAT=y | 221 | CONFIG_BATMAN_ADV_DAT=y |
222 | CONFIG_BATMAN_ADV_NC=y | ||
223 | CONFIG_NETLINK_DIAG=m | ||
224 | CONFIG_NET_MPLS_GSO=m | ||
196 | # CONFIG_WIRELESS is not set | 225 | # CONFIG_WIRELESS is not set |
197 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
198 | CONFIG_DEVTMPFS=y | 226 | CONFIG_DEVTMPFS=y |
199 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 227 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
200 | # CONFIG_FW_LOADER_USER_HELPER is not set | 228 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -209,6 +237,7 @@ CONFIG_BLK_DEV_NBD=m | |||
209 | CONFIG_BLK_DEV_RAM=y | 237 | CONFIG_BLK_DEV_RAM=y |
210 | CONFIG_CDROM_PKTCDVD=m | 238 | CONFIG_CDROM_PKTCDVD=m |
211 | CONFIG_ATA_OVER_ETH=m | 239 | CONFIG_ATA_OVER_ETH=m |
240 | CONFIG_DUMMY_IRQ=m | ||
212 | CONFIG_IDE=y | 241 | CONFIG_IDE=y |
213 | CONFIG_IDE_GD_ATAPI=y | 242 | CONFIG_IDE_GD_ATAPI=y |
214 | CONFIG_BLK_DEV_IDECD=y | 243 | CONFIG_BLK_DEV_IDECD=y |
@@ -249,6 +278,7 @@ CONFIG_EQUALIZER=m | |||
249 | CONFIG_NET_TEAM=m | 278 | CONFIG_NET_TEAM=m |
250 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 279 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
251 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 280 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
281 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
252 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 282 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
253 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 283 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
254 | CONFIG_VXLAN=m | 284 | CONFIG_VXLAN=m |
@@ -257,10 +287,10 @@ CONFIG_NETCONSOLE_DYNAMIC=y | |||
257 | CONFIG_VETH=m | 287 | CONFIG_VETH=m |
258 | # CONFIG_NET_VENDOR_3COM is not set | 288 | # CONFIG_NET_VENDOR_3COM is not set |
259 | # CONFIG_NET_VENDOR_AMD is not set | 289 | # CONFIG_NET_VENDOR_AMD is not set |
290 | # CONFIG_NET_VENDOR_ARC is not set | ||
260 | # CONFIG_NET_CADENCE is not set | 291 | # CONFIG_NET_CADENCE is not set |
261 | # CONFIG_NET_VENDOR_BROADCOM is not set | 292 | # CONFIG_NET_VENDOR_BROADCOM is not set |
262 | # CONFIG_NET_VENDOR_CIRRUS is not set | 293 | # CONFIG_NET_VENDOR_CIRRUS is not set |
263 | # CONFIG_NET_VENDOR_FUJITSU is not set | ||
264 | # CONFIG_NET_VENDOR_HP is not set | 294 | # CONFIG_NET_VENDOR_HP is not set |
265 | # CONFIG_NET_VENDOR_INTEL is not set | 295 | # CONFIG_NET_VENDOR_INTEL is not set |
266 | # CONFIG_NET_VENDOR_MARVELL is not set | 296 | # CONFIG_NET_VENDOR_MARVELL is not set |
@@ -269,6 +299,7 @@ CONFIG_NE2000=m | |||
269 | # CONFIG_NET_VENDOR_SEEQ is not set | 299 | # CONFIG_NET_VENDOR_SEEQ is not set |
270 | # CONFIG_NET_VENDOR_SMSC is not set | 300 | # CONFIG_NET_VENDOR_SMSC is not set |
271 | # CONFIG_NET_VENDOR_STMICRO is not set | 301 | # CONFIG_NET_VENDOR_STMICRO is not set |
302 | # CONFIG_NET_VENDOR_VIA is not set | ||
272 | # CONFIG_NET_VENDOR_WIZNET is not set | 303 | # CONFIG_NET_VENDOR_WIZNET is not set |
273 | CONFIG_PLIP=m | 304 | CONFIG_PLIP=m |
274 | CONFIG_PPP=m | 305 | CONFIG_PPP=m |
@@ -293,7 +324,6 @@ CONFIG_MOUSE_SERIAL=m | |||
293 | CONFIG_INPUT_MISC=y | 324 | CONFIG_INPUT_MISC=y |
294 | CONFIG_INPUT_M68K_BEEP=m | 325 | CONFIG_INPUT_M68K_BEEP=m |
295 | CONFIG_SERIO_Q40KBD=y | 326 | CONFIG_SERIO_Q40KBD=y |
296 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
297 | # CONFIG_LEGACY_PTYS is not set | 327 | # CONFIG_LEGACY_PTYS is not set |
298 | # CONFIG_DEVKMEM is not set | 328 | # CONFIG_DEVKMEM is not set |
299 | CONFIG_PRINTER=m | 329 | CONFIG_PRINTER=m |
@@ -318,10 +348,6 @@ CONFIG_RTC_DRV_GENERIC=m | |||
318 | # CONFIG_IOMMU_SUPPORT is not set | 348 | # CONFIG_IOMMU_SUPPORT is not set |
319 | CONFIG_HEARTBEAT=y | 349 | CONFIG_HEARTBEAT=y |
320 | CONFIG_PROC_HARDWARE=y | 350 | CONFIG_PROC_HARDWARE=y |
321 | CONFIG_EXT2_FS=y | ||
322 | CONFIG_EXT3_FS=y | ||
323 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
324 | # CONFIG_EXT3_FS_XATTR is not set | ||
325 | CONFIG_EXT4_FS=y | 351 | CONFIG_EXT4_FS=y |
326 | CONFIG_REISERFS_FS=m | 352 | CONFIG_REISERFS_FS=m |
327 | CONFIG_JFS_FS=m | 353 | CONFIG_JFS_FS=m |
@@ -358,7 +384,7 @@ CONFIG_QNX6FS_FS=m | |||
358 | CONFIG_SYSV_FS=m | 384 | CONFIG_SYSV_FS=m |
359 | CONFIG_UFS_FS=m | 385 | CONFIG_UFS_FS=m |
360 | CONFIG_NFS_FS=y | 386 | CONFIG_NFS_FS=y |
361 | CONFIG_NFS_V4=y | 387 | CONFIG_NFS_V4=m |
362 | CONFIG_NFS_SWAP=y | 388 | CONFIG_NFS_SWAP=y |
363 | CONFIG_ROOT_NFS=y | 389 | CONFIG_ROOT_NFS=y |
364 | CONFIG_NFSD=m | 390 | CONFIG_NFSD=m |
@@ -417,10 +443,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
417 | CONFIG_DLM=m | 443 | CONFIG_DLM=m |
418 | CONFIG_MAGIC_SYSRQ=y | 444 | CONFIG_MAGIC_SYSRQ=y |
419 | CONFIG_ASYNC_RAID6_TEST=m | 445 | CONFIG_ASYNC_RAID6_TEST=m |
446 | CONFIG_TEST_STRING_HELPERS=m | ||
420 | CONFIG_ENCRYPTED_KEYS=m | 447 | CONFIG_ENCRYPTED_KEYS=m |
421 | CONFIG_CRYPTO_MANAGER=y | 448 | CONFIG_CRYPTO_MANAGER=y |
422 | CONFIG_CRYPTO_USER=m | 449 | CONFIG_CRYPTO_USER=m |
423 | CONFIG_CRYPTO_NULL=m | ||
424 | CONFIG_CRYPTO_CRYPTD=m | 450 | CONFIG_CRYPTO_CRYPTD=m |
425 | CONFIG_CRYPTO_TEST=m | 451 | CONFIG_CRYPTO_TEST=m |
426 | CONFIG_CRYPTO_CCM=m | 452 | CONFIG_CRYPTO_CCM=m |
@@ -453,6 +479,8 @@ CONFIG_CRYPTO_TEA=m | |||
453 | CONFIG_CRYPTO_TWOFISH=m | 479 | CONFIG_CRYPTO_TWOFISH=m |
454 | CONFIG_CRYPTO_ZLIB=m | 480 | CONFIG_CRYPTO_ZLIB=m |
455 | CONFIG_CRYPTO_LZO=m | 481 | CONFIG_CRYPTO_LZO=m |
482 | CONFIG_CRYPTO_LZ4=m | ||
483 | CONFIG_CRYPTO_LZ4HC=m | ||
456 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 484 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
457 | CONFIG_CRYPTO_USER_API_HASH=m | 485 | CONFIG_CRYPTO_USER_API_HASH=m |
458 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 486 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 54674d61e001..60b0aeac5742 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig | |||
@@ -45,7 +45,6 @@ CONFIG_IP_PNP_RARP=y | |||
45 | CONFIG_NET_IPIP=m | 45 | CONFIG_NET_IPIP=m |
46 | CONFIG_NET_IPGRE_DEMUX=m | 46 | CONFIG_NET_IPGRE_DEMUX=m |
47 | CONFIG_NET_IPGRE=m | 47 | CONFIG_NET_IPGRE=m |
48 | CONFIG_SYN_COOKIES=y | ||
49 | CONFIG_NET_IPVTI=m | 48 | CONFIG_NET_IPVTI=m |
50 | CONFIG_INET_AH=m | 49 | CONFIG_INET_AH=m |
51 | CONFIG_INET_ESP=m | 50 | CONFIG_INET_ESP=m |
@@ -56,11 +55,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
56 | # CONFIG_INET_LRO is not set | 55 | # CONFIG_INET_LRO is not set |
57 | CONFIG_INET_DIAG=m | 56 | CONFIG_INET_DIAG=m |
58 | CONFIG_INET_UDP_DIAG=m | 57 | CONFIG_INET_UDP_DIAG=m |
59 | CONFIG_IPV6_PRIVACY=y | ||
60 | CONFIG_IPV6_ROUTER_PREF=y | 58 | CONFIG_IPV6_ROUTER_PREF=y |
61 | CONFIG_INET6_AH=m | 59 | CONFIG_INET6_AH=m |
62 | CONFIG_INET6_ESP=m | 60 | CONFIG_INET6_ESP=m |
63 | CONFIG_INET6_IPCOMP=m | 61 | CONFIG_INET6_IPCOMP=m |
62 | CONFIG_IPV6_VTI=m | ||
64 | CONFIG_IPV6_GRE=m | 63 | CONFIG_IPV6_GRE=m |
65 | CONFIG_NETFILTER=y | 64 | CONFIG_NETFILTER=y |
66 | CONFIG_NF_CONNTRACK=m | 65 | CONFIG_NF_CONNTRACK=m |
@@ -78,6 +77,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
78 | CONFIG_NF_CONNTRACK_SANE=m | 77 | CONFIG_NF_CONNTRACK_SANE=m |
79 | CONFIG_NF_CONNTRACK_SIP=m | 78 | CONFIG_NF_CONNTRACK_SIP=m |
80 | CONFIG_NF_CONNTRACK_TFTP=m | 79 | CONFIG_NF_CONNTRACK_TFTP=m |
80 | CONFIG_NF_TABLES=m | ||
81 | CONFIG_NFT_EXTHDR=m | ||
82 | CONFIG_NFT_META=m | ||
83 | CONFIG_NFT_CT=m | ||
84 | CONFIG_NFT_RBTREE=m | ||
85 | CONFIG_NFT_HASH=m | ||
86 | CONFIG_NFT_COUNTER=m | ||
87 | CONFIG_NFT_LOG=m | ||
88 | CONFIG_NFT_LIMIT=m | ||
89 | CONFIG_NFT_NAT=m | ||
90 | CONFIG_NFT_COMPAT=m | ||
81 | CONFIG_NETFILTER_XT_SET=m | 91 | CONFIG_NETFILTER_XT_SET=m |
82 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 92 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
83 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 93 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -91,6 +101,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
91 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 101 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
92 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 102 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
93 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 103 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
104 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
94 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 105 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
95 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 106 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
96 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 107 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -123,6 +134,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
123 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 134 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
124 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 135 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
125 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 136 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
137 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
126 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 138 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
127 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 139 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
128 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 140 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -137,11 +149,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
137 | CONFIG_IP_SET_HASH_IPPORT=m | 149 | CONFIG_IP_SET_HASH_IPPORT=m |
138 | CONFIG_IP_SET_HASH_IPPORTIP=m | 150 | CONFIG_IP_SET_HASH_IPPORTIP=m |
139 | CONFIG_IP_SET_HASH_IPPORTNET=m | 151 | CONFIG_IP_SET_HASH_IPPORTNET=m |
152 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
140 | CONFIG_IP_SET_HASH_NET=m | 153 | CONFIG_IP_SET_HASH_NET=m |
154 | CONFIG_IP_SET_HASH_NETNET=m | ||
141 | CONFIG_IP_SET_HASH_NETPORT=m | 155 | CONFIG_IP_SET_HASH_NETPORT=m |
142 | CONFIG_IP_SET_HASH_NETIFACE=m | 156 | CONFIG_IP_SET_HASH_NETIFACE=m |
143 | CONFIG_IP_SET_LIST_SET=m | 157 | CONFIG_IP_SET_LIST_SET=m |
144 | CONFIG_NF_CONNTRACK_IPV4=m | 158 | CONFIG_NF_CONNTRACK_IPV4=m |
159 | CONFIG_NF_TABLES_IPV4=m | ||
160 | CONFIG_NFT_REJECT_IPV4=m | ||
161 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
162 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
163 | CONFIG_NF_TABLES_ARP=m | ||
145 | CONFIG_IP_NF_IPTABLES=m | 164 | CONFIG_IP_NF_IPTABLES=m |
146 | CONFIG_IP_NF_MATCH_AH=m | 165 | CONFIG_IP_NF_MATCH_AH=m |
147 | CONFIG_IP_NF_MATCH_ECN=m | 166 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -149,6 +168,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
149 | CONFIG_IP_NF_MATCH_TTL=m | 168 | CONFIG_IP_NF_MATCH_TTL=m |
150 | CONFIG_IP_NF_FILTER=m | 169 | CONFIG_IP_NF_FILTER=m |
151 | CONFIG_IP_NF_TARGET_REJECT=m | 170 | CONFIG_IP_NF_TARGET_REJECT=m |
171 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
152 | CONFIG_IP_NF_TARGET_ULOG=m | 172 | CONFIG_IP_NF_TARGET_ULOG=m |
153 | CONFIG_NF_NAT_IPV4=m | 173 | CONFIG_NF_NAT_IPV4=m |
154 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 174 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -163,6 +183,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
163 | CONFIG_IP_NF_ARPFILTER=m | 183 | CONFIG_IP_NF_ARPFILTER=m |
164 | CONFIG_IP_NF_ARP_MANGLE=m | 184 | CONFIG_IP_NF_ARP_MANGLE=m |
165 | CONFIG_NF_CONNTRACK_IPV6=m | 185 | CONFIG_NF_CONNTRACK_IPV6=m |
186 | CONFIG_NF_TABLES_IPV6=m | ||
187 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
188 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
166 | CONFIG_IP6_NF_IPTABLES=m | 189 | CONFIG_IP6_NF_IPTABLES=m |
167 | CONFIG_IP6_NF_MATCH_AH=m | 190 | CONFIG_IP6_NF_MATCH_AH=m |
168 | CONFIG_IP6_NF_MATCH_EUI64=m | 191 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -176,11 +199,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
176 | CONFIG_IP6_NF_TARGET_HL=m | 199 | CONFIG_IP6_NF_TARGET_HL=m |
177 | CONFIG_IP6_NF_FILTER=m | 200 | CONFIG_IP6_NF_FILTER=m |
178 | CONFIG_IP6_NF_TARGET_REJECT=m | 201 | CONFIG_IP6_NF_TARGET_REJECT=m |
202 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
179 | CONFIG_IP6_NF_MANGLE=m | 203 | CONFIG_IP6_NF_MANGLE=m |
180 | CONFIG_IP6_NF_RAW=m | 204 | CONFIG_IP6_NF_RAW=m |
181 | CONFIG_NF_NAT_IPV6=m | 205 | CONFIG_NF_NAT_IPV6=m |
182 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 206 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
183 | CONFIG_IP6_NF_TARGET_NPT=m | 207 | CONFIG_IP6_NF_TARGET_NPT=m |
208 | CONFIG_NF_TABLES_BRIDGE=m | ||
184 | CONFIG_IP_DCCP=m | 209 | CONFIG_IP_DCCP=m |
185 | # CONFIG_IP_DCCP_CCID3 is not set | 210 | # CONFIG_IP_DCCP_CCID3 is not set |
186 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 211 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -188,10 +213,13 @@ CONFIG_RDS=m | |||
188 | CONFIG_RDS_TCP=m | 213 | CONFIG_RDS_TCP=m |
189 | CONFIG_L2TP=m | 214 | CONFIG_L2TP=m |
190 | CONFIG_ATALK=m | 215 | CONFIG_ATALK=m |
216 | CONFIG_DNS_RESOLVER=y | ||
191 | CONFIG_BATMAN_ADV=m | 217 | CONFIG_BATMAN_ADV=m |
192 | CONFIG_BATMAN_ADV_DAT=y | 218 | CONFIG_BATMAN_ADV_DAT=y |
219 | CONFIG_BATMAN_ADV_NC=y | ||
220 | CONFIG_NETLINK_DIAG=m | ||
221 | CONFIG_NET_MPLS_GSO=m | ||
193 | # CONFIG_WIRELESS is not set | 222 | # CONFIG_WIRELESS is not set |
194 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
195 | CONFIG_DEVTMPFS=y | 223 | CONFIG_DEVTMPFS=y |
196 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 224 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
197 | # CONFIG_FW_LOADER_USER_HELPER is not set | 225 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -203,6 +231,7 @@ CONFIG_BLK_DEV_NBD=m | |||
203 | CONFIG_BLK_DEV_RAM=y | 231 | CONFIG_BLK_DEV_RAM=y |
204 | CONFIG_CDROM_PKTCDVD=m | 232 | CONFIG_CDROM_PKTCDVD=m |
205 | CONFIG_ATA_OVER_ETH=m | 233 | CONFIG_ATA_OVER_ETH=m |
234 | CONFIG_DUMMY_IRQ=m | ||
206 | CONFIG_RAID_ATTRS=m | 235 | CONFIG_RAID_ATTRS=m |
207 | CONFIG_SCSI=y | 236 | CONFIG_SCSI=y |
208 | CONFIG_SCSI_TGT=m | 237 | CONFIG_SCSI_TGT=m |
@@ -240,6 +269,7 @@ CONFIG_EQUALIZER=m | |||
240 | CONFIG_NET_TEAM=m | 269 | CONFIG_NET_TEAM=m |
241 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 270 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
242 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 271 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
272 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
243 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 273 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
244 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 274 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
245 | CONFIG_VXLAN=m | 275 | CONFIG_VXLAN=m |
@@ -247,6 +277,7 @@ CONFIG_NETCONSOLE=m | |||
247 | CONFIG_NETCONSOLE_DYNAMIC=y | 277 | CONFIG_NETCONSOLE_DYNAMIC=y |
248 | CONFIG_VETH=m | 278 | CONFIG_VETH=m |
249 | CONFIG_SUN3LANCE=y | 279 | CONFIG_SUN3LANCE=y |
280 | # CONFIG_NET_VENDOR_ARC is not set | ||
250 | # CONFIG_NET_CADENCE is not set | 281 | # CONFIG_NET_CADENCE is not set |
251 | CONFIG_SUN3_82586=y | 282 | CONFIG_SUN3_82586=y |
252 | # CONFIG_NET_VENDOR_MARVELL is not set | 283 | # CONFIG_NET_VENDOR_MARVELL is not set |
@@ -255,6 +286,7 @@ CONFIG_SUN3_82586=y | |||
255 | # CONFIG_NET_VENDOR_SEEQ is not set | 286 | # CONFIG_NET_VENDOR_SEEQ is not set |
256 | # CONFIG_NET_VENDOR_STMICRO is not set | 287 | # CONFIG_NET_VENDOR_STMICRO is not set |
257 | # CONFIG_NET_VENDOR_SUN is not set | 288 | # CONFIG_NET_VENDOR_SUN is not set |
289 | # CONFIG_NET_VENDOR_VIA is not set | ||
258 | # CONFIG_NET_VENDOR_WIZNET is not set | 290 | # CONFIG_NET_VENDOR_WIZNET is not set |
259 | CONFIG_PPP=m | 291 | CONFIG_PPP=m |
260 | CONFIG_PPP_BSDCOMP=m | 292 | CONFIG_PPP_BSDCOMP=m |
@@ -276,7 +308,6 @@ CONFIG_INPUT_EVDEV=m | |||
276 | CONFIG_KEYBOARD_SUNKBD=y | 308 | CONFIG_KEYBOARD_SUNKBD=y |
277 | # CONFIG_MOUSE_PS2 is not set | 309 | # CONFIG_MOUSE_PS2 is not set |
278 | CONFIG_MOUSE_SERIAL=m | 310 | CONFIG_MOUSE_SERIAL=m |
279 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
280 | # CONFIG_LEGACY_PTYS is not set | 311 | # CONFIG_LEGACY_PTYS is not set |
281 | # CONFIG_DEVKMEM is not set | 312 | # CONFIG_DEVKMEM is not set |
282 | # CONFIG_HW_RANDOM is not set | 313 | # CONFIG_HW_RANDOM is not set |
@@ -296,10 +327,6 @@ CONFIG_RTC_CLASS=y | |||
296 | CONFIG_RTC_DRV_GENERIC=m | 327 | CONFIG_RTC_DRV_GENERIC=m |
297 | # CONFIG_IOMMU_SUPPORT is not set | 328 | # CONFIG_IOMMU_SUPPORT is not set |
298 | CONFIG_PROC_HARDWARE=y | 329 | CONFIG_PROC_HARDWARE=y |
299 | CONFIG_EXT2_FS=y | ||
300 | CONFIG_EXT3_FS=y | ||
301 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
302 | # CONFIG_EXT3_FS_XATTR is not set | ||
303 | CONFIG_EXT4_FS=y | 330 | CONFIG_EXT4_FS=y |
304 | CONFIG_REISERFS_FS=m | 331 | CONFIG_REISERFS_FS=m |
305 | CONFIG_JFS_FS=m | 332 | CONFIG_JFS_FS=m |
@@ -336,7 +363,7 @@ CONFIG_QNX6FS_FS=m | |||
336 | CONFIG_SYSV_FS=m | 363 | CONFIG_SYSV_FS=m |
337 | CONFIG_UFS_FS=m | 364 | CONFIG_UFS_FS=m |
338 | CONFIG_NFS_FS=y | 365 | CONFIG_NFS_FS=y |
339 | CONFIG_NFS_V4=y | 366 | CONFIG_NFS_V4=m |
340 | CONFIG_NFS_SWAP=y | 367 | CONFIG_NFS_SWAP=y |
341 | CONFIG_ROOT_NFS=y | 368 | CONFIG_ROOT_NFS=y |
342 | CONFIG_NFSD=m | 369 | CONFIG_NFSD=m |
@@ -395,10 +422,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
395 | CONFIG_DLM=m | 422 | CONFIG_DLM=m |
396 | CONFIG_MAGIC_SYSRQ=y | 423 | CONFIG_MAGIC_SYSRQ=y |
397 | CONFIG_ASYNC_RAID6_TEST=m | 424 | CONFIG_ASYNC_RAID6_TEST=m |
425 | CONFIG_TEST_STRING_HELPERS=m | ||
398 | CONFIG_ENCRYPTED_KEYS=m | 426 | CONFIG_ENCRYPTED_KEYS=m |
399 | CONFIG_CRYPTO_MANAGER=y | 427 | CONFIG_CRYPTO_MANAGER=y |
400 | CONFIG_CRYPTO_USER=m | 428 | CONFIG_CRYPTO_USER=m |
401 | CONFIG_CRYPTO_NULL=m | ||
402 | CONFIG_CRYPTO_CRYPTD=m | 429 | CONFIG_CRYPTO_CRYPTD=m |
403 | CONFIG_CRYPTO_TEST=m | 430 | CONFIG_CRYPTO_TEST=m |
404 | CONFIG_CRYPTO_CCM=m | 431 | CONFIG_CRYPTO_CCM=m |
@@ -431,6 +458,8 @@ CONFIG_CRYPTO_TEA=m | |||
431 | CONFIG_CRYPTO_TWOFISH=m | 458 | CONFIG_CRYPTO_TWOFISH=m |
432 | CONFIG_CRYPTO_ZLIB=m | 459 | CONFIG_CRYPTO_ZLIB=m |
433 | CONFIG_CRYPTO_LZO=m | 460 | CONFIG_CRYPTO_LZO=m |
461 | CONFIG_CRYPTO_LZ4=m | ||
462 | CONFIG_CRYPTO_LZ4HC=m | ||
434 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 463 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
435 | CONFIG_CRYPTO_USER_API_HASH=m | 464 | CONFIG_CRYPTO_USER_API_HASH=m |
436 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 465 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 832d9539f441..21bda331eebb 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig | |||
@@ -45,7 +45,6 @@ CONFIG_IP_PNP_RARP=y | |||
45 | CONFIG_NET_IPIP=m | 45 | CONFIG_NET_IPIP=m |
46 | CONFIG_NET_IPGRE_DEMUX=m | 46 | CONFIG_NET_IPGRE_DEMUX=m |
47 | CONFIG_NET_IPGRE=m | 47 | CONFIG_NET_IPGRE=m |
48 | CONFIG_SYN_COOKIES=y | ||
49 | CONFIG_NET_IPVTI=m | 48 | CONFIG_NET_IPVTI=m |
50 | CONFIG_INET_AH=m | 49 | CONFIG_INET_AH=m |
51 | CONFIG_INET_ESP=m | 50 | CONFIG_INET_ESP=m |
@@ -56,11 +55,11 @@ CONFIG_INET_XFRM_MODE_BEET=m | |||
56 | # CONFIG_INET_LRO is not set | 55 | # CONFIG_INET_LRO is not set |
57 | CONFIG_INET_DIAG=m | 56 | CONFIG_INET_DIAG=m |
58 | CONFIG_INET_UDP_DIAG=m | 57 | CONFIG_INET_UDP_DIAG=m |
59 | CONFIG_IPV6_PRIVACY=y | ||
60 | CONFIG_IPV6_ROUTER_PREF=y | 58 | CONFIG_IPV6_ROUTER_PREF=y |
61 | CONFIG_INET6_AH=m | 59 | CONFIG_INET6_AH=m |
62 | CONFIG_INET6_ESP=m | 60 | CONFIG_INET6_ESP=m |
63 | CONFIG_INET6_IPCOMP=m | 61 | CONFIG_INET6_IPCOMP=m |
62 | CONFIG_IPV6_VTI=m | ||
64 | CONFIG_IPV6_GRE=m | 63 | CONFIG_IPV6_GRE=m |
65 | CONFIG_NETFILTER=y | 64 | CONFIG_NETFILTER=y |
66 | CONFIG_NF_CONNTRACK=m | 65 | CONFIG_NF_CONNTRACK=m |
@@ -78,6 +77,17 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
78 | CONFIG_NF_CONNTRACK_SANE=m | 77 | CONFIG_NF_CONNTRACK_SANE=m |
79 | CONFIG_NF_CONNTRACK_SIP=m | 78 | CONFIG_NF_CONNTRACK_SIP=m |
80 | CONFIG_NF_CONNTRACK_TFTP=m | 79 | CONFIG_NF_CONNTRACK_TFTP=m |
80 | CONFIG_NF_TABLES=m | ||
81 | CONFIG_NFT_EXTHDR=m | ||
82 | CONFIG_NFT_META=m | ||
83 | CONFIG_NFT_CT=m | ||
84 | CONFIG_NFT_RBTREE=m | ||
85 | CONFIG_NFT_HASH=m | ||
86 | CONFIG_NFT_COUNTER=m | ||
87 | CONFIG_NFT_LOG=m | ||
88 | CONFIG_NFT_LIMIT=m | ||
89 | CONFIG_NFT_NAT=m | ||
90 | CONFIG_NFT_COMPAT=m | ||
81 | CONFIG_NETFILTER_XT_SET=m | 91 | CONFIG_NETFILTER_XT_SET=m |
82 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 92 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
83 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 93 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
@@ -91,6 +101,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m | |||
91 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | 101 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
92 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | 102 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m |
93 | CONFIG_NETFILTER_XT_TARGET_TEE=m | 103 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
104 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
94 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | 105 | CONFIG_NETFILTER_XT_TARGET_TRACE=m |
95 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | 106 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
96 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | 107 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
@@ -123,6 +134,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m | |||
123 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | 134 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m |
124 | CONFIG_NETFILTER_XT_MATCH_REALM=m | 135 | CONFIG_NETFILTER_XT_MATCH_REALM=m |
125 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | 136 | CONFIG_NETFILTER_XT_MATCH_RECENT=m |
137 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
126 | CONFIG_NETFILTER_XT_MATCH_STATE=m | 138 | CONFIG_NETFILTER_XT_MATCH_STATE=m |
127 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | 139 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m |
128 | CONFIG_NETFILTER_XT_MATCH_STRING=m | 140 | CONFIG_NETFILTER_XT_MATCH_STRING=m |
@@ -137,11 +149,18 @@ CONFIG_IP_SET_HASH_IP=m | |||
137 | CONFIG_IP_SET_HASH_IPPORT=m | 149 | CONFIG_IP_SET_HASH_IPPORT=m |
138 | CONFIG_IP_SET_HASH_IPPORTIP=m | 150 | CONFIG_IP_SET_HASH_IPPORTIP=m |
139 | CONFIG_IP_SET_HASH_IPPORTNET=m | 151 | CONFIG_IP_SET_HASH_IPPORTNET=m |
152 | CONFIG_IP_SET_HASH_NETPORTNET=m | ||
140 | CONFIG_IP_SET_HASH_NET=m | 153 | CONFIG_IP_SET_HASH_NET=m |
154 | CONFIG_IP_SET_HASH_NETNET=m | ||
141 | CONFIG_IP_SET_HASH_NETPORT=m | 155 | CONFIG_IP_SET_HASH_NETPORT=m |
142 | CONFIG_IP_SET_HASH_NETIFACE=m | 156 | CONFIG_IP_SET_HASH_NETIFACE=m |
143 | CONFIG_IP_SET_LIST_SET=m | 157 | CONFIG_IP_SET_LIST_SET=m |
144 | CONFIG_NF_CONNTRACK_IPV4=m | 158 | CONFIG_NF_CONNTRACK_IPV4=m |
159 | CONFIG_NF_TABLES_IPV4=m | ||
160 | CONFIG_NFT_REJECT_IPV4=m | ||
161 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | ||
162 | CONFIG_NFT_CHAIN_NAT_IPV4=m | ||
163 | CONFIG_NF_TABLES_ARP=m | ||
145 | CONFIG_IP_NF_IPTABLES=m | 164 | CONFIG_IP_NF_IPTABLES=m |
146 | CONFIG_IP_NF_MATCH_AH=m | 165 | CONFIG_IP_NF_MATCH_AH=m |
147 | CONFIG_IP_NF_MATCH_ECN=m | 166 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -149,6 +168,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m | |||
149 | CONFIG_IP_NF_MATCH_TTL=m | 168 | CONFIG_IP_NF_MATCH_TTL=m |
150 | CONFIG_IP_NF_FILTER=m | 169 | CONFIG_IP_NF_FILTER=m |
151 | CONFIG_IP_NF_TARGET_REJECT=m | 170 | CONFIG_IP_NF_TARGET_REJECT=m |
171 | CONFIG_IP_NF_TARGET_SYNPROXY=m | ||
152 | CONFIG_IP_NF_TARGET_ULOG=m | 172 | CONFIG_IP_NF_TARGET_ULOG=m |
153 | CONFIG_NF_NAT_IPV4=m | 173 | CONFIG_NF_NAT_IPV4=m |
154 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 174 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -163,6 +183,9 @@ CONFIG_IP_NF_ARPTABLES=m | |||
163 | CONFIG_IP_NF_ARPFILTER=m | 183 | CONFIG_IP_NF_ARPFILTER=m |
164 | CONFIG_IP_NF_ARP_MANGLE=m | 184 | CONFIG_IP_NF_ARP_MANGLE=m |
165 | CONFIG_NF_CONNTRACK_IPV6=m | 185 | CONFIG_NF_CONNTRACK_IPV6=m |
186 | CONFIG_NF_TABLES_IPV6=m | ||
187 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | ||
188 | CONFIG_NFT_CHAIN_NAT_IPV6=m | ||
166 | CONFIG_IP6_NF_IPTABLES=m | 189 | CONFIG_IP6_NF_IPTABLES=m |
167 | CONFIG_IP6_NF_MATCH_AH=m | 190 | CONFIG_IP6_NF_MATCH_AH=m |
168 | CONFIG_IP6_NF_MATCH_EUI64=m | 191 | CONFIG_IP6_NF_MATCH_EUI64=m |
@@ -176,11 +199,13 @@ CONFIG_IP6_NF_MATCH_RT=m | |||
176 | CONFIG_IP6_NF_TARGET_HL=m | 199 | CONFIG_IP6_NF_TARGET_HL=m |
177 | CONFIG_IP6_NF_FILTER=m | 200 | CONFIG_IP6_NF_FILTER=m |
178 | CONFIG_IP6_NF_TARGET_REJECT=m | 201 | CONFIG_IP6_NF_TARGET_REJECT=m |
202 | CONFIG_IP6_NF_TARGET_SYNPROXY=m | ||
179 | CONFIG_IP6_NF_MANGLE=m | 203 | CONFIG_IP6_NF_MANGLE=m |
180 | CONFIG_IP6_NF_RAW=m | 204 | CONFIG_IP6_NF_RAW=m |
181 | CONFIG_NF_NAT_IPV6=m | 205 | CONFIG_NF_NAT_IPV6=m |
182 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 206 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
183 | CONFIG_IP6_NF_TARGET_NPT=m | 207 | CONFIG_IP6_NF_TARGET_NPT=m |
208 | CONFIG_NF_TABLES_BRIDGE=m | ||
184 | CONFIG_IP_DCCP=m | 209 | CONFIG_IP_DCCP=m |
185 | # CONFIG_IP_DCCP_CCID3 is not set | 210 | # CONFIG_IP_DCCP_CCID3 is not set |
186 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y | 211 | CONFIG_SCTP_COOKIE_HMAC_SHA1=y |
@@ -188,10 +213,13 @@ CONFIG_RDS=m | |||
188 | CONFIG_RDS_TCP=m | 213 | CONFIG_RDS_TCP=m |
189 | CONFIG_L2TP=m | 214 | CONFIG_L2TP=m |
190 | CONFIG_ATALK=m | 215 | CONFIG_ATALK=m |
216 | CONFIG_DNS_RESOLVER=y | ||
191 | CONFIG_BATMAN_ADV=m | 217 | CONFIG_BATMAN_ADV=m |
192 | CONFIG_BATMAN_ADV_DAT=y | 218 | CONFIG_BATMAN_ADV_DAT=y |
219 | CONFIG_BATMAN_ADV_NC=y | ||
220 | CONFIG_NETLINK_DIAG=m | ||
221 | CONFIG_NET_MPLS_GSO=m | ||
193 | # CONFIG_WIRELESS is not set | 222 | # CONFIG_WIRELESS is not set |
194 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
195 | CONFIG_DEVTMPFS=y | 223 | CONFIG_DEVTMPFS=y |
196 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 224 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
197 | # CONFIG_FW_LOADER_USER_HELPER is not set | 225 | # CONFIG_FW_LOADER_USER_HELPER is not set |
@@ -203,6 +231,7 @@ CONFIG_BLK_DEV_NBD=m | |||
203 | CONFIG_BLK_DEV_RAM=y | 231 | CONFIG_BLK_DEV_RAM=y |
204 | CONFIG_CDROM_PKTCDVD=m | 232 | CONFIG_CDROM_PKTCDVD=m |
205 | CONFIG_ATA_OVER_ETH=m | 233 | CONFIG_ATA_OVER_ETH=m |
234 | CONFIG_DUMMY_IRQ=m | ||
206 | CONFIG_RAID_ATTRS=m | 235 | CONFIG_RAID_ATTRS=m |
207 | CONFIG_SCSI=y | 236 | CONFIG_SCSI=y |
208 | CONFIG_SCSI_TGT=m | 237 | CONFIG_SCSI_TGT=m |
@@ -240,6 +269,7 @@ CONFIG_EQUALIZER=m | |||
240 | CONFIG_NET_TEAM=m | 269 | CONFIG_NET_TEAM=m |
241 | CONFIG_NET_TEAM_MODE_BROADCAST=m | 270 | CONFIG_NET_TEAM_MODE_BROADCAST=m |
242 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m | 271 | CONFIG_NET_TEAM_MODE_ROUNDROBIN=m |
272 | CONFIG_NET_TEAM_MODE_RANDOM=m | ||
243 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m | 273 | CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m |
244 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m | 274 | CONFIG_NET_TEAM_MODE_LOADBALANCE=m |
245 | CONFIG_VXLAN=m | 275 | CONFIG_VXLAN=m |
@@ -247,6 +277,7 @@ CONFIG_NETCONSOLE=m | |||
247 | CONFIG_NETCONSOLE_DYNAMIC=y | 277 | CONFIG_NETCONSOLE_DYNAMIC=y |
248 | CONFIG_VETH=m | 278 | CONFIG_VETH=m |
249 | CONFIG_SUN3LANCE=y | 279 | CONFIG_SUN3LANCE=y |
280 | # CONFIG_NET_VENDOR_ARC is not set | ||
250 | # CONFIG_NET_CADENCE is not set | 281 | # CONFIG_NET_CADENCE is not set |
251 | # CONFIG_NET_VENDOR_BROADCOM is not set | 282 | # CONFIG_NET_VENDOR_BROADCOM is not set |
252 | # CONFIG_NET_VENDOR_INTEL is not set | 283 | # CONFIG_NET_VENDOR_INTEL is not set |
@@ -255,6 +286,7 @@ CONFIG_SUN3LANCE=y | |||
255 | # CONFIG_NET_VENDOR_NATSEMI is not set | 286 | # CONFIG_NET_VENDOR_NATSEMI is not set |
256 | # CONFIG_NET_VENDOR_SEEQ is not set | 287 | # CONFIG_NET_VENDOR_SEEQ is not set |
257 | # CONFIG_NET_VENDOR_STMICRO is not set | 288 | # CONFIG_NET_VENDOR_STMICRO is not set |
289 | # CONFIG_NET_VENDOR_VIA is not set | ||
258 | # CONFIG_NET_VENDOR_WIZNET is not set | 290 | # CONFIG_NET_VENDOR_WIZNET is not set |
259 | CONFIG_PPP=m | 291 | CONFIG_PPP=m |
260 | CONFIG_PPP_BSDCOMP=m | 292 | CONFIG_PPP_BSDCOMP=m |
@@ -276,7 +308,6 @@ CONFIG_INPUT_EVDEV=m | |||
276 | CONFIG_KEYBOARD_SUNKBD=y | 308 | CONFIG_KEYBOARD_SUNKBD=y |
277 | # CONFIG_MOUSE_PS2 is not set | 309 | # CONFIG_MOUSE_PS2 is not set |
278 | CONFIG_MOUSE_SERIAL=m | 310 | CONFIG_MOUSE_SERIAL=m |
279 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
280 | # CONFIG_LEGACY_PTYS is not set | 311 | # CONFIG_LEGACY_PTYS is not set |
281 | # CONFIG_DEVKMEM is not set | 312 | # CONFIG_DEVKMEM is not set |
282 | # CONFIG_HW_RANDOM is not set | 313 | # CONFIG_HW_RANDOM is not set |
@@ -296,10 +327,6 @@ CONFIG_RTC_CLASS=y | |||
296 | CONFIG_RTC_DRV_GENERIC=m | 327 | CONFIG_RTC_DRV_GENERIC=m |
297 | # CONFIG_IOMMU_SUPPORT is not set | 328 | # CONFIG_IOMMU_SUPPORT is not set |
298 | CONFIG_PROC_HARDWARE=y | 329 | CONFIG_PROC_HARDWARE=y |
299 | CONFIG_EXT2_FS=y | ||
300 | CONFIG_EXT3_FS=y | ||
301 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
302 | # CONFIG_EXT3_FS_XATTR is not set | ||
303 | CONFIG_EXT4_FS=y | 330 | CONFIG_EXT4_FS=y |
304 | CONFIG_REISERFS_FS=m | 331 | CONFIG_REISERFS_FS=m |
305 | CONFIG_JFS_FS=m | 332 | CONFIG_JFS_FS=m |
@@ -336,7 +363,7 @@ CONFIG_QNX6FS_FS=m | |||
336 | CONFIG_SYSV_FS=m | 363 | CONFIG_SYSV_FS=m |
337 | CONFIG_UFS_FS=m | 364 | CONFIG_UFS_FS=m |
338 | CONFIG_NFS_FS=y | 365 | CONFIG_NFS_FS=y |
339 | CONFIG_NFS_V4=y | 366 | CONFIG_NFS_V4=m |
340 | CONFIG_NFS_SWAP=y | 367 | CONFIG_NFS_SWAP=y |
341 | CONFIG_ROOT_NFS=y | 368 | CONFIG_ROOT_NFS=y |
342 | CONFIG_NFSD=m | 369 | CONFIG_NFSD=m |
@@ -395,10 +422,10 @@ CONFIG_NLS_MAC_TURKISH=m | |||
395 | CONFIG_DLM=m | 422 | CONFIG_DLM=m |
396 | CONFIG_MAGIC_SYSRQ=y | 423 | CONFIG_MAGIC_SYSRQ=y |
397 | CONFIG_ASYNC_RAID6_TEST=m | 424 | CONFIG_ASYNC_RAID6_TEST=m |
425 | CONFIG_TEST_STRING_HELPERS=m | ||
398 | CONFIG_ENCRYPTED_KEYS=m | 426 | CONFIG_ENCRYPTED_KEYS=m |
399 | CONFIG_CRYPTO_MANAGER=y | 427 | CONFIG_CRYPTO_MANAGER=y |
400 | CONFIG_CRYPTO_USER=m | 428 | CONFIG_CRYPTO_USER=m |
401 | CONFIG_CRYPTO_NULL=m | ||
402 | CONFIG_CRYPTO_CRYPTD=m | 429 | CONFIG_CRYPTO_CRYPTD=m |
403 | CONFIG_CRYPTO_TEST=m | 430 | CONFIG_CRYPTO_TEST=m |
404 | CONFIG_CRYPTO_CCM=m | 431 | CONFIG_CRYPTO_CCM=m |
@@ -431,6 +458,8 @@ CONFIG_CRYPTO_TEA=m | |||
431 | CONFIG_CRYPTO_TWOFISH=m | 458 | CONFIG_CRYPTO_TWOFISH=m |
432 | CONFIG_CRYPTO_ZLIB=m | 459 | CONFIG_CRYPTO_ZLIB=m |
433 | CONFIG_CRYPTO_LZO=m | 460 | CONFIG_CRYPTO_LZO=m |
461 | CONFIG_CRYPTO_LZ4=m | ||
462 | CONFIG_CRYPTO_LZ4HC=m | ||
434 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 463 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
435 | CONFIG_CRYPTO_USER_API_HASH=m | 464 | CONFIG_CRYPTO_USER_API_HASH=m |
436 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 465 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c index 121a6660ad4e..71b78ecee75c 100644 --- a/arch/m68k/emu/natfeat.c +++ b/arch/m68k/emu/natfeat.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * the GNU General Public License (GPL), incorporated herein by reference. | 9 | * the GNU General Public License (GPL), incorporated herein by reference. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/init.h> | ||
12 | #include <linux/types.h> | 13 | #include <linux/types.h> |
13 | #include <linux/console.h> | 14 | #include <linux/console.h> |
14 | #include <linux/string.h> | 15 | #include <linux/string.h> |
@@ -70,7 +71,7 @@ static void nf_poweroff(void) | |||
70 | nf_call(id); | 71 | nf_call(id); |
71 | } | 72 | } |
72 | 73 | ||
73 | void nf_init(void) | 74 | void __init nf_init(void) |
74 | { | 75 | { |
75 | unsigned long id, version; | 76 | unsigned long id, version; |
76 | char buf[256]; | 77 | char buf[256]; |
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c index b7609f791522..2e5a787ea11b 100644 --- a/arch/m68k/hp300/config.c +++ b/arch/m68k/hp300/config.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/console.h> | 14 | #include <linux/console.h> |
15 | 15 | ||
16 | #include <asm/bootinfo.h> | 16 | #include <asm/bootinfo.h> |
17 | #include <asm/bootinfo-hp300.h> | ||
18 | #include <asm/byteorder.h> | ||
17 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
18 | #include <asm/blinken.h> | 20 | #include <asm/blinken.h> |
19 | #include <asm/io.h> /* readb() and writeb() */ | 21 | #include <asm/io.h> /* readb() and writeb() */ |
@@ -70,15 +72,15 @@ extern int hp300_setup_serial_console(void) __init; | |||
70 | int __init hp300_parse_bootinfo(const struct bi_record *record) | 72 | int __init hp300_parse_bootinfo(const struct bi_record *record) |
71 | { | 73 | { |
72 | int unknown = 0; | 74 | int unknown = 0; |
73 | const unsigned long *data = record->data; | 75 | const void *data = record->data; |
74 | 76 | ||
75 | switch (record->tag) { | 77 | switch (be16_to_cpu(record->tag)) { |
76 | case BI_HP300_MODEL: | 78 | case BI_HP300_MODEL: |
77 | hp300_model = *data; | 79 | hp300_model = be32_to_cpup(data); |
78 | break; | 80 | break; |
79 | 81 | ||
80 | case BI_HP300_UART_SCODE: | 82 | case BI_HP300_UART_SCODE: |
81 | hp300_uart_scode = *data; | 83 | hp300_uart_scode = be32_to_cpup(data); |
82 | break; | 84 | break; |
83 | 85 | ||
84 | case BI_HP300_UART_ADDR: | 86 | case BI_HP300_UART_ADDR: |
diff --git a/arch/m68k/include/asm/amigahw.h b/arch/m68k/include/asm/amigahw.h index 7a19b5686a4a..5ad568110f17 100644 --- a/arch/m68k/include/asm/amigahw.h +++ b/arch/m68k/include/asm/amigahw.h | |||
@@ -18,26 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/ioport.h> | 19 | #include <linux/ioport.h> |
20 | 20 | ||
21 | /* | 21 | #include <asm/bootinfo-amiga.h> |
22 | * Different Amiga models | ||
23 | */ | ||
24 | |||
25 | #define AMI_UNKNOWN (0) | ||
26 | #define AMI_500 (1) | ||
27 | #define AMI_500PLUS (2) | ||
28 | #define AMI_600 (3) | ||
29 | #define AMI_1000 (4) | ||
30 | #define AMI_1200 (5) | ||
31 | #define AMI_2000 (6) | ||
32 | #define AMI_2500 (7) | ||
33 | #define AMI_3000 (8) | ||
34 | #define AMI_3000T (9) | ||
35 | #define AMI_3000PLUS (10) | ||
36 | #define AMI_4000 (11) | ||
37 | #define AMI_4000T (12) | ||
38 | #define AMI_CDTV (13) | ||
39 | #define AMI_CD32 (14) | ||
40 | #define AMI_DRACO (15) | ||
41 | 22 | ||
42 | 23 | ||
43 | /* | 24 | /* |
@@ -46,11 +27,6 @@ | |||
46 | 27 | ||
47 | extern unsigned long amiga_chipset; | 28 | extern unsigned long amiga_chipset; |
48 | 29 | ||
49 | #define CS_STONEAGE (0) | ||
50 | #define CS_OCS (1) | ||
51 | #define CS_ECS (2) | ||
52 | #define CS_AGA (3) | ||
53 | |||
54 | 30 | ||
55 | /* | 31 | /* |
56 | * Miscellaneous | 32 | * Miscellaneous |
@@ -266,7 +242,7 @@ struct CIA { | |||
266 | 242 | ||
267 | #define zTwoBase (0x80000000) | 243 | #define zTwoBase (0x80000000) |
268 | #define ZTWO_PADDR(x) (((unsigned long)(x))-zTwoBase) | 244 | #define ZTWO_PADDR(x) (((unsigned long)(x))-zTwoBase) |
269 | #define ZTWO_VADDR(x) (((unsigned long)(x))+zTwoBase) | 245 | #define ZTWO_VADDR(x) ((void __iomem *)(((unsigned long)(x))+zTwoBase)) |
270 | 246 | ||
271 | #define CUSTOM_PHYSADDR (0xdff000) | 247 | #define CUSTOM_PHYSADDR (0xdff000) |
272 | #define amiga_custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR))) | 248 | #define amiga_custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR))) |
diff --git a/arch/m68k/include/asm/apollohw.h b/arch/m68k/include/asm/apollohw.h index 6c19e0c22411..87fc899d32ee 100644 --- a/arch/m68k/include/asm/apollohw.h +++ b/arch/m68k/include/asm/apollohw.h | |||
@@ -5,18 +5,11 @@ | |||
5 | 5 | ||
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | 7 | ||
8 | /* | 8 | #include <asm/bootinfo-apollo.h> |
9 | apollo models | 9 | |
10 | */ | ||
11 | 10 | ||
12 | extern u_long apollo_model; | 11 | extern u_long apollo_model; |
13 | 12 | ||
14 | #define APOLLO_UNKNOWN (0) | ||
15 | #define APOLLO_DN3000 (1) | ||
16 | #define APOLLO_DN3010 (2) | ||
17 | #define APOLLO_DN3500 (3) | ||
18 | #define APOLLO_DN4000 (4) | ||
19 | #define APOLLO_DN4500 (5) | ||
20 | 13 | ||
21 | /* | 14 | /* |
22 | see scn2681 data sheet for more info. | 15 | see scn2681 data sheet for more info. |
diff --git a/arch/m68k/include/asm/atarihw.h b/arch/m68k/include/asm/atarihw.h index d887050e6da6..972c8f33f055 100644 --- a/arch/m68k/include/asm/atarihw.h +++ b/arch/m68k/include/asm/atarihw.h | |||
@@ -21,7 +21,7 @@ | |||
21 | #define _LINUX_ATARIHW_H_ | 21 | #define _LINUX_ATARIHW_H_ |
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <asm/bootinfo.h> | 24 | #include <asm/bootinfo-atari.h> |
25 | #include <asm/raw_io.h> | 25 | #include <asm/raw_io.h> |
26 | 26 | ||
27 | extern u_long atari_mch_cookie; | 27 | extern u_long atari_mch_cookie; |
diff --git a/arch/m68k/include/asm/barrier.h b/arch/m68k/include/asm/barrier.h index 445ce22c23cb..15c5f77c1614 100644 --- a/arch/m68k/include/asm/barrier.h +++ b/arch/m68k/include/asm/barrier.h | |||
@@ -1,20 +1,8 @@ | |||
1 | #ifndef _M68K_BARRIER_H | 1 | #ifndef _M68K_BARRIER_H |
2 | #define _M68K_BARRIER_H | 2 | #define _M68K_BARRIER_H |
3 | 3 | ||
4 | /* | ||
5 | * Force strict CPU ordering. | ||
6 | * Not really required on m68k... | ||
7 | */ | ||
8 | #define nop() do { asm volatile ("nop"); barrier(); } while (0) | 4 | #define nop() do { asm volatile ("nop"); barrier(); } while (0) |
9 | #define mb() barrier() | ||
10 | #define rmb() barrier() | ||
11 | #define wmb() barrier() | ||
12 | #define read_barrier_depends() ((void)0) | ||
13 | #define set_mb(var, value) ({ (var) = (value); wmb(); }) | ||
14 | 5 | ||
15 | #define smp_mb() barrier() | 6 | #include <asm-generic/barrier.h> |
16 | #define smp_rmb() barrier() | ||
17 | #define smp_wmb() barrier() | ||
18 | #define smp_read_barrier_depends() ((void)0) | ||
19 | 7 | ||
20 | #endif /* _M68K_BARRIER_H */ | 8 | #endif /* _M68K_BARRIER_H */ |
diff --git a/arch/m68k/include/asm/bootinfo.h b/arch/m68k/include/asm/bootinfo.h index 67e7a78ad96b..8e213267f8e7 100644 --- a/arch/m68k/include/asm/bootinfo.h +++ b/arch/m68k/include/asm/bootinfo.h | |||
@@ -6,373 +6,23 @@ | |||
6 | ** This file is subject to the terms and conditions of the GNU General Public | 6 | ** This file is subject to the terms and conditions of the GNU General Public |
7 | ** License. See the file COPYING in the main directory of this archive | 7 | ** License. See the file COPYING in the main directory of this archive |
8 | ** for more details. | 8 | ** for more details. |
9 | ** | ||
10 | ** Created 09/29/92 by Greg Harp | ||
11 | ** | ||
12 | ** 5/2/94 Roman Hodek: | ||
13 | ** Added bi_atari part of the machine dependent union bi_un; for now it | ||
14 | ** contains just a model field to distinguish between TT and Falcon. | ||
15 | ** 26/7/96 Roman Zippel: | ||
16 | ** Renamed to setup.h; added some useful macros to allow gcc some | ||
17 | ** optimizations if possible. | ||
18 | ** 5/10/96 Geert Uytterhoeven: | ||
19 | ** Redesign of the boot information structure; renamed to bootinfo.h again | ||
20 | ** 27/11/96 Geert Uytterhoeven: | ||
21 | ** Backwards compatibility with bootinfo interface version 1.0 | ||
22 | */ | 9 | */ |
23 | 10 | ||
24 | #ifndef _M68K_BOOTINFO_H | 11 | #ifndef _M68K_BOOTINFO_H |
25 | #define _M68K_BOOTINFO_H | 12 | #define _M68K_BOOTINFO_H |
26 | 13 | ||
14 | #include <uapi/asm/bootinfo.h> | ||
27 | 15 | ||
28 | /* | ||
29 | * Bootinfo definitions | ||
30 | * | ||
31 | * This is an easily parsable and extendable structure containing all | ||
32 | * information to be passed from the bootstrap to the kernel. | ||
33 | * | ||
34 | * This way I hope to keep all future changes back/forewards compatible. | ||
35 | * Thus, keep your fingers crossed... | ||
36 | * | ||
37 | * This structure is copied right after the kernel bss by the bootstrap | ||
38 | * routine. | ||
39 | */ | ||
40 | 16 | ||
41 | #ifndef __ASSEMBLY__ | 17 | #ifndef __ASSEMBLY__ |
42 | 18 | ||
43 | struct bi_record { | 19 | #ifdef CONFIG_BOOTINFO_PROC |
44 | unsigned short tag; /* tag ID */ | 20 | extern void save_bootinfo(const struct bi_record *bi); |
45 | unsigned short size; /* size of record (in bytes) */ | 21 | #else |
46 | unsigned long data[0]; /* data */ | 22 | static inline void save_bootinfo(const struct bi_record *bi) {} |
47 | }; | ||
48 | |||
49 | #endif /* __ASSEMBLY__ */ | ||
50 | |||
51 | |||
52 | /* | ||
53 | * Tag Definitions | ||
54 | * | ||
55 | * Machine independent tags start counting from 0x0000 | ||
56 | * Machine dependent tags start counting from 0x8000 | ||
57 | */ | ||
58 | |||
59 | #define BI_LAST 0x0000 /* last record (sentinel) */ | ||
60 | #define BI_MACHTYPE 0x0001 /* machine type (u_long) */ | ||
61 | #define BI_CPUTYPE 0x0002 /* cpu type (u_long) */ | ||
62 | #define BI_FPUTYPE 0x0003 /* fpu type (u_long) */ | ||
63 | #define BI_MMUTYPE 0x0004 /* mmu type (u_long) */ | ||
64 | #define BI_MEMCHUNK 0x0005 /* memory chunk address and size */ | ||
65 | /* (struct mem_info) */ | ||
66 | #define BI_RAMDISK 0x0006 /* ramdisk address and size */ | ||
67 | /* (struct mem_info) */ | ||
68 | #define BI_COMMAND_LINE 0x0007 /* kernel command line parameters */ | ||
69 | /* (string) */ | ||
70 | |||
71 | /* | ||
72 | * Amiga-specific tags | ||
73 | */ | ||
74 | |||
75 | #define BI_AMIGA_MODEL 0x8000 /* model (u_long) */ | ||
76 | #define BI_AMIGA_AUTOCON 0x8001 /* AutoConfig device */ | ||
77 | /* (struct ConfigDev) */ | ||
78 | #define BI_AMIGA_CHIP_SIZE 0x8002 /* size of Chip RAM (u_long) */ | ||
79 | #define BI_AMIGA_VBLANK 0x8003 /* VBLANK frequency (u_char) */ | ||
80 | #define BI_AMIGA_PSFREQ 0x8004 /* power supply frequency (u_char) */ | ||
81 | #define BI_AMIGA_ECLOCK 0x8005 /* EClock frequency (u_long) */ | ||
82 | #define BI_AMIGA_CHIPSET 0x8006 /* native chipset present (u_long) */ | ||
83 | #define BI_AMIGA_SERPER 0x8007 /* serial port period (u_short) */ | ||
84 | |||
85 | /* | ||
86 | * Atari-specific tags | ||
87 | */ | ||
88 | |||
89 | #define BI_ATARI_MCH_COOKIE 0x8000 /* _MCH cookie from TOS (u_long) */ | ||
90 | #define BI_ATARI_MCH_TYPE 0x8001 /* special machine type (u_long) */ | ||
91 | /* (values are ATARI_MACH_* defines */ | ||
92 | |||
93 | /* mch_cookie values (upper word) */ | ||
94 | #define ATARI_MCH_ST 0 | ||
95 | #define ATARI_MCH_STE 1 | ||
96 | #define ATARI_MCH_TT 2 | ||
97 | #define ATARI_MCH_FALCON 3 | ||
98 | |||
99 | /* mch_type values */ | ||
100 | #define ATARI_MACH_NORMAL 0 /* no special machine type */ | ||
101 | #define ATARI_MACH_MEDUSA 1 /* Medusa 040 */ | ||
102 | #define ATARI_MACH_HADES 2 /* Hades 040 or 060 */ | ||
103 | #define ATARI_MACH_AB40 3 /* Afterburner040 on Falcon */ | ||
104 | |||
105 | /* | ||
106 | * VME-specific tags | ||
107 | */ | ||
108 | |||
109 | #define BI_VME_TYPE 0x8000 /* VME sub-architecture (u_long) */ | ||
110 | #define BI_VME_BRDINFO 0x8001 /* VME board information (struct) */ | ||
111 | |||
112 | /* BI_VME_TYPE codes */ | ||
113 | #define VME_TYPE_TP34V 0x0034 /* Tadpole TP34V */ | ||
114 | #define VME_TYPE_MVME147 0x0147 /* Motorola MVME147 */ | ||
115 | #define VME_TYPE_MVME162 0x0162 /* Motorola MVME162 */ | ||
116 | #define VME_TYPE_MVME166 0x0166 /* Motorola MVME166 */ | ||
117 | #define VME_TYPE_MVME167 0x0167 /* Motorola MVME167 */ | ||
118 | #define VME_TYPE_MVME172 0x0172 /* Motorola MVME172 */ | ||
119 | #define VME_TYPE_MVME177 0x0177 /* Motorola MVME177 */ | ||
120 | #define VME_TYPE_BVME4000 0x4000 /* BVM Ltd. BVME4000 */ | ||
121 | #define VME_TYPE_BVME6000 0x6000 /* BVM Ltd. BVME6000 */ | ||
122 | |||
123 | /* BI_VME_BRDINFO is a 32 byte struct as returned by the Bug code on | ||
124 | * Motorola VME boards. Contains board number, Bug version, board | ||
125 | * configuration options, etc. See include/asm/mvme16xhw.h for details. | ||
126 | */ | ||
127 | |||
128 | |||
129 | /* | ||
130 | * Macintosh-specific tags (all u_long) | ||
131 | */ | ||
132 | |||
133 | #define BI_MAC_MODEL 0x8000 /* Mac Gestalt ID (model type) */ | ||
134 | #define BI_MAC_VADDR 0x8001 /* Mac video base address */ | ||
135 | #define BI_MAC_VDEPTH 0x8002 /* Mac video depth */ | ||
136 | #define BI_MAC_VROW 0x8003 /* Mac video rowbytes */ | ||
137 | #define BI_MAC_VDIM 0x8004 /* Mac video dimensions */ | ||
138 | #define BI_MAC_VLOGICAL 0x8005 /* Mac video logical base */ | ||
139 | #define BI_MAC_SCCBASE 0x8006 /* Mac SCC base address */ | ||
140 | #define BI_MAC_BTIME 0x8007 /* Mac boot time */ | ||
141 | #define BI_MAC_GMTBIAS 0x8008 /* Mac GMT timezone offset */ | ||
142 | #define BI_MAC_MEMSIZE 0x8009 /* Mac RAM size (sanity check) */ | ||
143 | #define BI_MAC_CPUID 0x800a /* Mac CPU type (sanity check) */ | ||
144 | #define BI_MAC_ROMBASE 0x800b /* Mac system ROM base address */ | ||
145 | |||
146 | /* | ||
147 | * Macintosh hardware profile data - unused, see macintosh.h for | ||
148 | * reasonable type values | ||
149 | */ | ||
150 | |||
151 | #define BI_MAC_VIA1BASE 0x8010 /* Mac VIA1 base address (always present) */ | ||
152 | #define BI_MAC_VIA2BASE 0x8011 /* Mac VIA2 base address (type varies) */ | ||
153 | #define BI_MAC_VIA2TYPE 0x8012 /* Mac VIA2 type (VIA, RBV, OSS) */ | ||
154 | #define BI_MAC_ADBTYPE 0x8013 /* Mac ADB interface type */ | ||
155 | #define BI_MAC_ASCBASE 0x8014 /* Mac Apple Sound Chip base address */ | ||
156 | #define BI_MAC_SCSI5380 0x8015 /* Mac NCR 5380 SCSI (base address, multi) */ | ||
157 | #define BI_MAC_SCSIDMA 0x8016 /* Mac SCSI DMA (base address) */ | ||
158 | #define BI_MAC_SCSI5396 0x8017 /* Mac NCR 53C96 SCSI (base address, multi) */ | ||
159 | #define BI_MAC_IDETYPE 0x8018 /* Mac IDE interface type */ | ||
160 | #define BI_MAC_IDEBASE 0x8019 /* Mac IDE interface base address */ | ||
161 | #define BI_MAC_NUBUS 0x801a /* Mac Nubus type (none, regular, pseudo) */ | ||
162 | #define BI_MAC_SLOTMASK 0x801b /* Mac Nubus slots present */ | ||
163 | #define BI_MAC_SCCTYPE 0x801c /* Mac SCC serial type (normal, IOP) */ | ||
164 | #define BI_MAC_ETHTYPE 0x801d /* Mac builtin ethernet type (Sonic, MACE */ | ||
165 | #define BI_MAC_ETHBASE 0x801e /* Mac builtin ethernet base address */ | ||
166 | #define BI_MAC_PMU 0x801f /* Mac power management / poweroff hardware */ | ||
167 | #define BI_MAC_IOP_SWIM 0x8020 /* Mac SWIM floppy IOP */ | ||
168 | #define BI_MAC_IOP_ADB 0x8021 /* Mac ADB IOP */ | ||
169 | |||
170 | /* | ||
171 | * Mac: compatibility with old booter data format (temporarily) | ||
172 | * Fields unused with the new bootinfo can be deleted now; instead of | ||
173 | * adding new fields the struct might be splitted into a hardware address | ||
174 | * part and a hardware type part | ||
175 | */ | ||
176 | |||
177 | #ifndef __ASSEMBLY__ | ||
178 | |||
179 | struct mac_booter_data | ||
180 | { | ||
181 | unsigned long videoaddr; | ||
182 | unsigned long videorow; | ||
183 | unsigned long videodepth; | ||
184 | unsigned long dimensions; | ||
185 | unsigned long args; | ||
186 | unsigned long boottime; | ||
187 | unsigned long gmtbias; | ||
188 | unsigned long bootver; | ||
189 | unsigned long videological; | ||
190 | unsigned long sccbase; | ||
191 | unsigned long id; | ||
192 | unsigned long memsize; | ||
193 | unsigned long serialmf; | ||
194 | unsigned long serialhsk; | ||
195 | unsigned long serialgpi; | ||
196 | unsigned long printmf; | ||
197 | unsigned long printhsk; | ||
198 | unsigned long printgpi; | ||
199 | unsigned long cpuid; | ||
200 | unsigned long rombase; | ||
201 | unsigned long adbdelay; | ||
202 | unsigned long timedbra; | ||
203 | }; | ||
204 | |||
205 | extern struct mac_booter_data | ||
206 | mac_bi_data; | ||
207 | |||
208 | #endif | 23 | #endif |
209 | 24 | ||
210 | /* | ||
211 | * Apollo-specific tags | ||
212 | */ | ||
213 | |||
214 | #define BI_APOLLO_MODEL 0x8000 /* model (u_long) */ | ||
215 | |||
216 | /* | ||
217 | * HP300-specific tags | ||
218 | */ | ||
219 | |||
220 | #define BI_HP300_MODEL 0x8000 /* model (u_long) */ | ||
221 | #define BI_HP300_UART_SCODE 0x8001 /* UART select code (u_long) */ | ||
222 | #define BI_HP300_UART_ADDR 0x8002 /* phys. addr of UART (u_long) */ | ||
223 | |||
224 | /* | ||
225 | * Stuff for bootinfo interface versioning | ||
226 | * | ||
227 | * At the start of kernel code, a 'struct bootversion' is located. | ||
228 | * bootstrap checks for a matching version of the interface before booting | ||
229 | * a kernel, to avoid user confusion if kernel and bootstrap don't work | ||
230 | * together :-) | ||
231 | * | ||
232 | * If incompatible changes are made to the bootinfo interface, the major | ||
233 | * number below should be stepped (and the minor reset to 0) for the | ||
234 | * appropriate machine. If a change is backward-compatible, the minor | ||
235 | * should be stepped. "Backwards-compatible" means that booting will work, | ||
236 | * but certain features may not. | ||
237 | */ | ||
238 | |||
239 | #define BOOTINFOV_MAGIC 0x4249561A /* 'BIV^Z' */ | ||
240 | #define MK_BI_VERSION(major,minor) (((major)<<16)+(minor)) | ||
241 | #define BI_VERSION_MAJOR(v) (((v) >> 16) & 0xffff) | ||
242 | #define BI_VERSION_MINOR(v) ((v) & 0xffff) | ||
243 | |||
244 | #ifndef __ASSEMBLY__ | ||
245 | |||
246 | struct bootversion { | ||
247 | unsigned short branch; | ||
248 | unsigned long magic; | ||
249 | struct { | ||
250 | unsigned long machtype; | ||
251 | unsigned long version; | ||
252 | } machversions[0]; | ||
253 | }; | ||
254 | |||
255 | #endif /* __ASSEMBLY__ */ | 25 | #endif /* __ASSEMBLY__ */ |
256 | 26 | ||
257 | #define AMIGA_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) | ||
258 | #define ATARI_BOOTI_VERSION MK_BI_VERSION( 2, 1 ) | ||
259 | #define MAC_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) | ||
260 | #define MVME147_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) | ||
261 | #define MVME16x_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) | ||
262 | #define BVME6000_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) | ||
263 | #define Q40_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) | ||
264 | #define HP300_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) | ||
265 | |||
266 | #ifdef BOOTINFO_COMPAT_1_0 | ||
267 | |||
268 | /* | ||
269 | * Backwards compatibility with bootinfo interface version 1.0 | ||
270 | */ | ||
271 | |||
272 | #define COMPAT_AMIGA_BOOTI_VERSION MK_BI_VERSION( 1, 0 ) | ||
273 | #define COMPAT_ATARI_BOOTI_VERSION MK_BI_VERSION( 1, 0 ) | ||
274 | #define COMPAT_MAC_BOOTI_VERSION MK_BI_VERSION( 1, 0 ) | ||
275 | |||
276 | #include <linux/zorro.h> | ||
277 | |||
278 | #define COMPAT_NUM_AUTO 16 | ||
279 | |||
280 | struct compat_bi_Amiga { | ||
281 | int model; | ||
282 | int num_autocon; | ||
283 | struct ConfigDev autocon[COMPAT_NUM_AUTO]; | ||
284 | unsigned long chip_size; | ||
285 | unsigned char vblank; | ||
286 | unsigned char psfreq; | ||
287 | unsigned long eclock; | ||
288 | unsigned long chipset; | ||
289 | unsigned long hw_present; | ||
290 | }; | ||
291 | |||
292 | struct compat_bi_Atari { | ||
293 | unsigned long hw_present; | ||
294 | unsigned long mch_cookie; | ||
295 | }; | ||
296 | |||
297 | #ifndef __ASSEMBLY__ | ||
298 | |||
299 | struct compat_bi_Macintosh | ||
300 | { | ||
301 | unsigned long videoaddr; | ||
302 | unsigned long videorow; | ||
303 | unsigned long videodepth; | ||
304 | unsigned long dimensions; | ||
305 | unsigned long args; | ||
306 | unsigned long boottime; | ||
307 | unsigned long gmtbias; | ||
308 | unsigned long bootver; | ||
309 | unsigned long videological; | ||
310 | unsigned long sccbase; | ||
311 | unsigned long id; | ||
312 | unsigned long memsize; | ||
313 | unsigned long serialmf; | ||
314 | unsigned long serialhsk; | ||
315 | unsigned long serialgpi; | ||
316 | unsigned long printmf; | ||
317 | unsigned long printhsk; | ||
318 | unsigned long printgpi; | ||
319 | unsigned long cpuid; | ||
320 | unsigned long rombase; | ||
321 | unsigned long adbdelay; | ||
322 | unsigned long timedbra; | ||
323 | }; | ||
324 | |||
325 | #endif | ||
326 | |||
327 | struct compat_mem_info { | ||
328 | unsigned long addr; | ||
329 | unsigned long size; | ||
330 | }; | ||
331 | |||
332 | #define COMPAT_NUM_MEMINFO 4 | ||
333 | |||
334 | #define COMPAT_CPUB_68020 0 | ||
335 | #define COMPAT_CPUB_68030 1 | ||
336 | #define COMPAT_CPUB_68040 2 | ||
337 | #define COMPAT_CPUB_68060 3 | ||
338 | #define COMPAT_FPUB_68881 5 | ||
339 | #define COMPAT_FPUB_68882 6 | ||
340 | #define COMPAT_FPUB_68040 7 | ||
341 | #define COMPAT_FPUB_68060 8 | ||
342 | |||
343 | #define COMPAT_CPU_68020 (1<<COMPAT_CPUB_68020) | ||
344 | #define COMPAT_CPU_68030 (1<<COMPAT_CPUB_68030) | ||
345 | #define COMPAT_CPU_68040 (1<<COMPAT_CPUB_68040) | ||
346 | #define COMPAT_CPU_68060 (1<<COMPAT_CPUB_68060) | ||
347 | #define COMPAT_CPU_MASK (31) | ||
348 | #define COMPAT_FPU_68881 (1<<COMPAT_FPUB_68881) | ||
349 | #define COMPAT_FPU_68882 (1<<COMPAT_FPUB_68882) | ||
350 | #define COMPAT_FPU_68040 (1<<COMPAT_FPUB_68040) | ||
351 | #define COMPAT_FPU_68060 (1<<COMPAT_FPUB_68060) | ||
352 | #define COMPAT_FPU_MASK (0xfe0) | ||
353 | |||
354 | #define COMPAT_CL_SIZE (256) | ||
355 | |||
356 | struct compat_bootinfo { | ||
357 | unsigned long machtype; | ||
358 | unsigned long cputype; | ||
359 | struct compat_mem_info memory[COMPAT_NUM_MEMINFO]; | ||
360 | int num_memory; | ||
361 | unsigned long ramdisk_size; | ||
362 | unsigned long ramdisk_addr; | ||
363 | char command_line[COMPAT_CL_SIZE]; | ||
364 | union { | ||
365 | struct compat_bi_Amiga bi_ami; | ||
366 | struct compat_bi_Atari bi_ata; | ||
367 | struct compat_bi_Macintosh bi_mac; | ||
368 | } bi_un; | ||
369 | }; | ||
370 | |||
371 | #define bi_amiga bi_un.bi_ami | ||
372 | #define bi_atari bi_un.bi_ata | ||
373 | #define bi_mac bi_un.bi_mac | ||
374 | |||
375 | #endif /* BOOTINFO_COMPAT_1_0 */ | ||
376 | |||
377 | 27 | ||
378 | #endif /* _M68K_BOOTINFO_H */ | 28 | #endif /* _M68K_BOOTINFO_H */ |
diff --git a/arch/m68k/include/asm/hp300hw.h b/arch/m68k/include/asm/hp300hw.h index d998ea67c19c..64f5271dd7be 100644 --- a/arch/m68k/include/asm/hp300hw.h +++ b/arch/m68k/include/asm/hp300hw.h | |||
@@ -1,25 +1,9 @@ | |||
1 | #ifndef _M68K_HP300HW_H | 1 | #ifndef _M68K_HP300HW_H |
2 | #define _M68K_HP300HW_H | 2 | #define _M68K_HP300HW_H |
3 | 3 | ||
4 | extern unsigned long hp300_model; | 4 | #include <asm/bootinfo-hp300.h> |
5 | 5 | ||
6 | /* This information was taken from NetBSD */ | ||
7 | #define HP_320 (0) /* 16MHz 68020+HP MMU+16K external cache */ | ||
8 | #define HP_330 (1) /* 16MHz 68020+68851 MMU */ | ||
9 | #define HP_340 (2) /* 16MHz 68030 */ | ||
10 | #define HP_345 (3) /* 50MHz 68030+32K external cache */ | ||
11 | #define HP_350 (4) /* 25MHz 68020+HP MMU+32K external cache */ | ||
12 | #define HP_360 (5) /* 25MHz 68030 */ | ||
13 | #define HP_370 (6) /* 33MHz 68030+64K external cache */ | ||
14 | #define HP_375 (7) /* 50MHz 68030+32K external cache */ | ||
15 | #define HP_380 (8) /* 25MHz 68040 */ | ||
16 | #define HP_385 (9) /* 33MHz 68040 */ | ||
17 | 6 | ||
18 | #define HP_400 (10) /* 50MHz 68030+32K external cache */ | 7 | extern unsigned long hp300_model; |
19 | #define HP_425T (11) /* 25MHz 68040 - model 425t */ | ||
20 | #define HP_425S (12) /* 25MHz 68040 - model 425s */ | ||
21 | #define HP_425E (13) /* 25MHz 68040 - model 425e */ | ||
22 | #define HP_433T (14) /* 33MHz 68040 - model 433t */ | ||
23 | #define HP_433S (15) /* 33MHz 68040 - model 433s */ | ||
24 | 8 | ||
25 | #endif /* _M68K_HP300HW_H */ | 9 | #endif /* _M68K_HP300HW_H */ |
diff --git a/arch/m68k/include/asm/kexec.h b/arch/m68k/include/asm/kexec.h new file mode 100644 index 000000000000..3df97abac147 --- /dev/null +++ b/arch/m68k/include/asm/kexec.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef _ASM_M68K_KEXEC_H | ||
2 | #define _ASM_M68K_KEXEC_H | ||
3 | |||
4 | #ifdef CONFIG_KEXEC | ||
5 | |||
6 | /* Maximum physical address we can use pages from */ | ||
7 | #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) | ||
8 | /* Maximum address we can reach in physical address mode */ | ||
9 | #define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) | ||
10 | /* Maximum address we can use for the control code buffer */ | ||
11 | #define KEXEC_CONTROL_MEMORY_LIMIT (-1UL) | ||
12 | |||
13 | #define KEXEC_CONTROL_PAGE_SIZE 4096 | ||
14 | |||
15 | #define KEXEC_ARCH KEXEC_ARCH_68K | ||
16 | |||
17 | #ifndef __ASSEMBLY__ | ||
18 | |||
19 | static inline void crash_setup_regs(struct pt_regs *newregs, | ||
20 | struct pt_regs *oldregs) | ||
21 | { | ||
22 | /* Dummy implementation for now */ | ||
23 | } | ||
24 | |||
25 | #endif /* __ASSEMBLY__ */ | ||
26 | |||
27 | #endif /* CONFIG_KEXEC */ | ||
28 | |||
29 | #endif /* _ASM_M68K_KEXEC_H */ | ||
diff --git a/arch/m68k/include/asm/mac_via.h b/arch/m68k/include/asm/mac_via.h index aeeedf8b2d25..fe3fc9ae1b69 100644 --- a/arch/m68k/include/asm/mac_via.h +++ b/arch/m68k/include/asm/mac_via.h | |||
@@ -254,6 +254,8 @@ | |||
254 | extern volatile __u8 *via1,*via2; | 254 | extern volatile __u8 *via1,*via2; |
255 | extern int rbv_present,via_alt_mapping; | 255 | extern int rbv_present,via_alt_mapping; |
256 | 256 | ||
257 | struct irq_desc; | ||
258 | |||
257 | extern void via_register_interrupts(void); | 259 | extern void via_register_interrupts(void); |
258 | extern void via_irq_enable(int); | 260 | extern void via_irq_enable(int); |
259 | extern void via_irq_disable(int); | 261 | extern void via_irq_disable(int); |
diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h index 682a1a2ff55f..d323b2c2d07d 100644 --- a/arch/m68k/include/asm/macintosh.h +++ b/arch/m68k/include/asm/macintosh.h | |||
@@ -4,6 +4,9 @@ | |||
4 | #include <linux/seq_file.h> | 4 | #include <linux/seq_file.h> |
5 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | 6 | ||
7 | #include <asm/bootinfo-mac.h> | ||
8 | |||
9 | |||
7 | /* | 10 | /* |
8 | * Apple Macintoshisms | 11 | * Apple Macintoshisms |
9 | */ | 12 | */ |
@@ -74,65 +77,29 @@ struct mac_model | |||
74 | #define MAC_FLOPPY_SWIM_IOP 3 | 77 | #define MAC_FLOPPY_SWIM_IOP 3 |
75 | #define MAC_FLOPPY_AV 4 | 78 | #define MAC_FLOPPY_AV 4 |
76 | 79 | ||
77 | /* | 80 | extern struct mac_model *macintosh_config; |
78 | * Gestalt numbers | ||
79 | */ | ||
80 | 81 | ||
81 | #define MAC_MODEL_II 6 | ||
82 | #define MAC_MODEL_IIX 7 | ||
83 | #define MAC_MODEL_IICX 8 | ||
84 | #define MAC_MODEL_SE30 9 | ||
85 | #define MAC_MODEL_IICI 11 | ||
86 | #define MAC_MODEL_IIFX 13 /* And well numbered it is too */ | ||
87 | #define MAC_MODEL_IISI 18 | ||
88 | #define MAC_MODEL_LC 19 | ||
89 | #define MAC_MODEL_Q900 20 | ||
90 | #define MAC_MODEL_PB170 21 | ||
91 | #define MAC_MODEL_Q700 22 | ||
92 | #define MAC_MODEL_CLII 23 /* aka: P200 */ | ||
93 | #define MAC_MODEL_PB140 25 | ||
94 | #define MAC_MODEL_Q950 26 /* aka: WGS95 */ | ||
95 | #define MAC_MODEL_LCIII 27 /* aka: P450 */ | ||
96 | #define MAC_MODEL_PB210 29 | ||
97 | #define MAC_MODEL_C650 30 | ||
98 | #define MAC_MODEL_PB230 32 | ||
99 | #define MAC_MODEL_PB180 33 | ||
100 | #define MAC_MODEL_PB160 34 | ||
101 | #define MAC_MODEL_Q800 35 /* aka: WGS80 */ | ||
102 | #define MAC_MODEL_Q650 36 | ||
103 | #define MAC_MODEL_LCII 37 /* aka: P400/405/410/430 */ | ||
104 | #define MAC_MODEL_PB250 38 | ||
105 | #define MAC_MODEL_IIVI 44 | ||
106 | #define MAC_MODEL_P600 45 /* aka: P600CD */ | ||
107 | #define MAC_MODEL_IIVX 48 | ||
108 | #define MAC_MODEL_CCL 49 /* aka: P250 */ | ||
109 | #define MAC_MODEL_PB165C 50 | ||
110 | #define MAC_MODEL_C610 52 /* aka: WGS60 */ | ||
111 | #define MAC_MODEL_Q610 53 | ||
112 | #define MAC_MODEL_PB145 54 /* aka: PB145B */ | ||
113 | #define MAC_MODEL_P520 56 /* aka: LC520 */ | ||
114 | #define MAC_MODEL_C660 60 | ||
115 | #define MAC_MODEL_P460 62 /* aka: LCIII+, P466/P467 */ | ||
116 | #define MAC_MODEL_PB180C 71 | ||
117 | #define MAC_MODEL_PB520 72 /* aka: PB520C, PB540, PB540C, PB550C */ | ||
118 | #define MAC_MODEL_PB270C 77 | ||
119 | #define MAC_MODEL_Q840 78 | ||
120 | #define MAC_MODEL_P550 80 /* aka: LC550, P560 */ | ||
121 | #define MAC_MODEL_CCLII 83 /* aka: P275 */ | ||
122 | #define MAC_MODEL_PB165 84 | ||
123 | #define MAC_MODEL_PB190 85 /* aka: PB190CS */ | ||
124 | #define MAC_MODEL_TV 88 | ||
125 | #define MAC_MODEL_P475 89 /* aka: LC475, P476 */ | ||
126 | #define MAC_MODEL_P475F 90 /* aka: P475 w/ FPU (no LC040) */ | ||
127 | #define MAC_MODEL_P575 92 /* aka: LC575, P577/P578 */ | ||
128 | #define MAC_MODEL_Q605 94 | ||
129 | #define MAC_MODEL_Q605_ACC 95 /* Q605 accelerated to 33 MHz */ | ||
130 | #define MAC_MODEL_Q630 98 /* aka: LC630, P630/631/635/636/637/638/640 */ | ||
131 | #define MAC_MODEL_P588 99 /* aka: LC580, P580 */ | ||
132 | #define MAC_MODEL_PB280 102 | ||
133 | #define MAC_MODEL_PB280C 103 | ||
134 | #define MAC_MODEL_PB150 115 | ||
135 | 82 | ||
136 | extern struct mac_model *macintosh_config; | 83 | /* |
84 | * Internal representation of the Mac hardware, filled in from bootinfo | ||
85 | */ | ||
86 | |||
87 | struct mac_booter_data | ||
88 | { | ||
89 | unsigned long videoaddr; | ||
90 | unsigned long videorow; | ||
91 | unsigned long videodepth; | ||
92 | unsigned long dimensions; | ||
93 | unsigned long boottime; | ||
94 | unsigned long gmtbias; | ||
95 | unsigned long videological; | ||
96 | unsigned long sccbase; | ||
97 | unsigned long id; | ||
98 | unsigned long memsize; | ||
99 | unsigned long cpuid; | ||
100 | unsigned long rombase; | ||
101 | }; | ||
102 | |||
103 | extern struct mac_booter_data mac_bi_data; | ||
137 | 104 | ||
138 | #endif | 105 | #endif |
diff --git a/arch/m68k/include/asm/mc146818rtc.h b/arch/m68k/include/asm/mc146818rtc.h index 9f70a01f73dc..05b43bf5cdf3 100644 --- a/arch/m68k/include/asm/mc146818rtc.h +++ b/arch/m68k/include/asm/mc146818rtc.h | |||
@@ -10,16 +10,16 @@ | |||
10 | 10 | ||
11 | #include <asm/atarihw.h> | 11 | #include <asm/atarihw.h> |
12 | 12 | ||
13 | #define RTC_PORT(x) (TT_RTC_BAS + 2*(x)) | 13 | #define ATARI_RTC_PORT(x) (TT_RTC_BAS + 2*(x)) |
14 | #define RTC_ALWAYS_BCD 0 | 14 | #define RTC_ALWAYS_BCD 0 |
15 | 15 | ||
16 | #define CMOS_READ(addr) ({ \ | 16 | #define CMOS_READ(addr) ({ \ |
17 | atari_outb_p((addr),RTC_PORT(0)); \ | 17 | atari_outb_p((addr), ATARI_RTC_PORT(0)); \ |
18 | atari_inb_p(RTC_PORT(1)); \ | 18 | atari_inb_p(ATARI_RTC_PORT(1)); \ |
19 | }) | 19 | }) |
20 | #define CMOS_WRITE(val, addr) ({ \ | 20 | #define CMOS_WRITE(val, addr) ({ \ |
21 | atari_outb_p((addr),RTC_PORT(0)); \ | 21 | atari_outb_p((addr), ATARI_RTC_PORT(0)); \ |
22 | atari_outb_p((val),RTC_PORT(1)); \ | 22 | atari_outb_p((val), ATARI_RTC_PORT(1)); \ |
23 | }) | 23 | }) |
24 | #endif /* CONFIG_ATARI */ | 24 | #endif /* CONFIG_ATARI */ |
25 | 25 | ||
diff --git a/arch/m68k/include/asm/mvme16xhw.h b/arch/m68k/include/asm/mvme16xhw.h index 6117f56653d2..1eb89de631e5 100644 --- a/arch/m68k/include/asm/mvme16xhw.h +++ b/arch/m68k/include/asm/mvme16xhw.h | |||
@@ -3,23 +3,6 @@ | |||
3 | 3 | ||
4 | #include <asm/irq.h> | 4 | #include <asm/irq.h> |
5 | 5 | ||
6 | /* Board ID data structure - pointer to this retrieved from Bug by head.S */ | ||
7 | |||
8 | /* Note, bytes 12 and 13 are board no in BCD (0162,0166,0167,0177,etc) */ | ||
9 | |||
10 | extern long mvme_bdid_ptr; | ||
11 | |||
12 | typedef struct { | ||
13 | char bdid[4]; | ||
14 | u_char rev, mth, day, yr; | ||
15 | u_short size, reserved; | ||
16 | u_short brdno; | ||
17 | char brdsuffix[2]; | ||
18 | u_long options; | ||
19 | u_short clun, dlun, ctype, dnum; | ||
20 | u_long option2; | ||
21 | } t_bdid, *p_bdid; | ||
22 | |||
23 | 6 | ||
24 | typedef struct { | 7 | typedef struct { |
25 | u_char ack_icr, | 8 | u_char ack_icr, |
diff --git a/arch/m68k/include/asm/setup.h b/arch/m68k/include/asm/setup.h index 65e78a2dad64..8f2023f8c1c4 100644 --- a/arch/m68k/include/asm/setup.h +++ b/arch/m68k/include/asm/setup.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #ifndef _M68K_SETUP_H | 22 | #ifndef _M68K_SETUP_H |
23 | #define _M68K_SETUP_H | 23 | #define _M68K_SETUP_H |
24 | 24 | ||
25 | #include <uapi/asm/bootinfo.h> | ||
25 | #include <uapi/asm/setup.h> | 26 | #include <uapi/asm/setup.h> |
26 | 27 | ||
27 | 28 | ||
@@ -297,14 +298,14 @@ extern int m68k_is040or060; | |||
297 | #define NUM_MEMINFO 4 | 298 | #define NUM_MEMINFO 4 |
298 | 299 | ||
299 | #ifndef __ASSEMBLY__ | 300 | #ifndef __ASSEMBLY__ |
300 | struct mem_info { | 301 | struct m68k_mem_info { |
301 | unsigned long addr; /* physical address of memory chunk */ | 302 | unsigned long addr; /* physical address of memory chunk */ |
302 | unsigned long size; /* length of memory chunk (in bytes) */ | 303 | unsigned long size; /* length of memory chunk (in bytes) */ |
303 | }; | 304 | }; |
304 | 305 | ||
305 | extern int m68k_num_memory; /* # of memory blocks found (and used) */ | 306 | extern int m68k_num_memory; /* # of memory blocks found (and used) */ |
306 | extern int m68k_realnum_memory; /* real # of memory blocks found */ | 307 | extern int m68k_realnum_memory; /* real # of memory blocks found */ |
307 | extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */ | 308 | extern struct m68k_mem_info m68k_memory[NUM_MEMINFO];/* memory description */ |
308 | #endif | 309 | #endif |
309 | 310 | ||
310 | #endif /* _M68K_SETUP_H */ | 311 | #endif /* _M68K_SETUP_H */ |
diff --git a/arch/m68k/include/asm/timex.h b/arch/m68k/include/asm/timex.h index 6759dad954f6..efc1f4892357 100644 --- a/arch/m68k/include/asm/timex.h +++ b/arch/m68k/include/asm/timex.h | |||
@@ -28,4 +28,14 @@ static inline cycles_t get_cycles(void) | |||
28 | return 0; | 28 | return 0; |
29 | } | 29 | } |
30 | 30 | ||
31 | extern unsigned long (*mach_random_get_entropy)(void); | ||
32 | |||
33 | static inline unsigned long random_get_entropy(void) | ||
34 | { | ||
35 | if (mach_random_get_entropy) | ||
36 | return mach_random_get_entropy(); | ||
37 | return 0; | ||
38 | } | ||
39 | #define random_get_entropy random_get_entropy | ||
40 | |||
31 | #endif | 41 | #endif |
diff --git a/arch/m68k/include/uapi/asm/Kbuild b/arch/m68k/include/uapi/asm/Kbuild index 1fef45ada097..6a2d257bdfb2 100644 --- a/arch/m68k/include/uapi/asm/Kbuild +++ b/arch/m68k/include/uapi/asm/Kbuild | |||
@@ -11,6 +11,14 @@ generic-y += termbits.h | |||
11 | generic-y += termios.h | 11 | generic-y += termios.h |
12 | 12 | ||
13 | header-y += a.out.h | 13 | header-y += a.out.h |
14 | header-y += bootinfo.h | ||
15 | header-y += bootinfo-amiga.h | ||
16 | header-y += bootinfo-apollo.h | ||
17 | header-y += bootinfo-atari.h | ||
18 | header-y += bootinfo-hp300.h | ||
19 | header-y += bootinfo-mac.h | ||
20 | header-y += bootinfo-q40.h | ||
21 | header-y += bootinfo-vme.h | ||
14 | header-y += byteorder.h | 22 | header-y += byteorder.h |
15 | header-y += cachectl.h | 23 | header-y += cachectl.h |
16 | header-y += fcntl.h | 24 | header-y += fcntl.h |
diff --git a/arch/m68k/include/uapi/asm/bootinfo-amiga.h b/arch/m68k/include/uapi/asm/bootinfo-amiga.h new file mode 100644 index 000000000000..daad3c58d2da --- /dev/null +++ b/arch/m68k/include/uapi/asm/bootinfo-amiga.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | ** asm/bootinfo-amiga.h -- Amiga-specific boot information definitions | ||
3 | */ | ||
4 | |||
5 | #ifndef _UAPI_ASM_M68K_BOOTINFO_AMIGA_H | ||
6 | #define _UAPI_ASM_M68K_BOOTINFO_AMIGA_H | ||
7 | |||
8 | |||
9 | /* | ||
10 | * Amiga-specific tags | ||
11 | */ | ||
12 | |||
13 | #define BI_AMIGA_MODEL 0x8000 /* model (__be32) */ | ||
14 | #define BI_AMIGA_AUTOCON 0x8001 /* AutoConfig device */ | ||
15 | /* (AmigaOS struct ConfigDev) */ | ||
16 | #define BI_AMIGA_CHIP_SIZE 0x8002 /* size of Chip RAM (__be32) */ | ||
17 | #define BI_AMIGA_VBLANK 0x8003 /* VBLANK frequency (__u8) */ | ||
18 | #define BI_AMIGA_PSFREQ 0x8004 /* power supply frequency (__u8) */ | ||
19 | #define BI_AMIGA_ECLOCK 0x8005 /* EClock frequency (__be32) */ | ||
20 | #define BI_AMIGA_CHIPSET 0x8006 /* native chipset present (__be32) */ | ||
21 | #define BI_AMIGA_SERPER 0x8007 /* serial port period (__be16) */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | * Amiga models (BI_AMIGA_MODEL) | ||
26 | */ | ||
27 | |||
28 | #define AMI_UNKNOWN 0 | ||
29 | #define AMI_500 1 | ||
30 | #define AMI_500PLUS 2 | ||
31 | #define AMI_600 3 | ||
32 | #define AMI_1000 4 | ||
33 | #define AMI_1200 5 | ||
34 | #define AMI_2000 6 | ||
35 | #define AMI_2500 7 | ||
36 | #define AMI_3000 8 | ||
37 | #define AMI_3000T 9 | ||
38 | #define AMI_3000PLUS 10 | ||
39 | #define AMI_4000 11 | ||
40 | #define AMI_4000T 12 | ||
41 | #define AMI_CDTV 13 | ||
42 | #define AMI_CD32 14 | ||
43 | #define AMI_DRACO 15 | ||
44 | |||
45 | |||
46 | /* | ||
47 | * Amiga chipsets (BI_AMIGA_CHIPSET) | ||
48 | */ | ||
49 | |||
50 | #define CS_STONEAGE 0 | ||
51 | #define CS_OCS 1 | ||
52 | #define CS_ECS 2 | ||
53 | #define CS_AGA 3 | ||
54 | |||
55 | |||
56 | /* | ||
57 | * Latest Amiga bootinfo version | ||
58 | */ | ||
59 | |||
60 | #define AMIGA_BOOTI_VERSION MK_BI_VERSION(2, 0) | ||
61 | |||
62 | |||
63 | #endif /* _UAPI_ASM_M68K_BOOTINFO_AMIGA_H */ | ||
diff --git a/arch/m68k/include/uapi/asm/bootinfo-apollo.h b/arch/m68k/include/uapi/asm/bootinfo-apollo.h new file mode 100644 index 000000000000..a93e0af1c6fe --- /dev/null +++ b/arch/m68k/include/uapi/asm/bootinfo-apollo.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | ** asm/bootinfo-apollo.h -- Apollo-specific boot information definitions | ||
3 | */ | ||
4 | |||
5 | #ifndef _UAPI_ASM_M68K_BOOTINFO_APOLLO_H | ||
6 | #define _UAPI_ASM_M68K_BOOTINFO_APOLLO_H | ||
7 | |||
8 | |||
9 | /* | ||
10 | * Apollo-specific tags | ||
11 | */ | ||
12 | |||
13 | #define BI_APOLLO_MODEL 0x8000 /* model (__be32) */ | ||
14 | |||
15 | |||
16 | /* | ||
17 | * Apollo models (BI_APOLLO_MODEL) | ||
18 | */ | ||
19 | |||
20 | #define APOLLO_UNKNOWN 0 | ||
21 | #define APOLLO_DN3000 1 | ||
22 | #define APOLLO_DN3010 2 | ||
23 | #define APOLLO_DN3500 3 | ||
24 | #define APOLLO_DN4000 4 | ||
25 | #define APOLLO_DN4500 5 | ||
26 | |||
27 | |||
28 | #endif /* _UAPI_ASM_M68K_BOOTINFO_APOLLO_H */ | ||
diff --git a/arch/m68k/include/uapi/asm/bootinfo-atari.h b/arch/m68k/include/uapi/asm/bootinfo-atari.h new file mode 100644 index 000000000000..a817854049bb --- /dev/null +++ b/arch/m68k/include/uapi/asm/bootinfo-atari.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | ** asm/bootinfo-atari.h -- Atari-specific boot information definitions | ||
3 | */ | ||
4 | |||
5 | #ifndef _UAPI_ASM_M68K_BOOTINFO_ATARI_H | ||
6 | #define _UAPI_ASM_M68K_BOOTINFO_ATARI_H | ||
7 | |||
8 | |||
9 | /* | ||
10 | * Atari-specific tags | ||
11 | */ | ||
12 | |||
13 | #define BI_ATARI_MCH_COOKIE 0x8000 /* _MCH cookie from TOS (__be32) */ | ||
14 | #define BI_ATARI_MCH_TYPE 0x8001 /* special machine type (__be32) */ | ||
15 | |||
16 | |||
17 | /* | ||
18 | * mch_cookie values (upper word of BI_ATARI_MCH_COOKIE) | ||
19 | */ | ||
20 | |||
21 | #define ATARI_MCH_ST 0 | ||
22 | #define ATARI_MCH_STE 1 | ||
23 | #define ATARI_MCH_TT 2 | ||
24 | #define ATARI_MCH_FALCON 3 | ||
25 | |||
26 | |||
27 | /* | ||
28 | * Atari machine types (BI_ATARI_MCH_TYPE) | ||
29 | */ | ||
30 | |||
31 | #define ATARI_MACH_NORMAL 0 /* no special machine type */ | ||
32 | #define ATARI_MACH_MEDUSA 1 /* Medusa 040 */ | ||
33 | #define ATARI_MACH_HADES 2 /* Hades 040 or 060 */ | ||
34 | #define ATARI_MACH_AB40 3 /* Afterburner040 on Falcon */ | ||
35 | |||
36 | |||
37 | /* | ||
38 | * Latest Atari bootinfo version | ||
39 | */ | ||
40 | |||
41 | #define ATARI_BOOTI_VERSION MK_BI_VERSION(2, 1) | ||
42 | |||
43 | |||
44 | #endif /* _UAPI_ASM_M68K_BOOTINFO_ATARI_H */ | ||
diff --git a/arch/m68k/include/uapi/asm/bootinfo-hp300.h b/arch/m68k/include/uapi/asm/bootinfo-hp300.h new file mode 100644 index 000000000000..c90cb71ed89a --- /dev/null +++ b/arch/m68k/include/uapi/asm/bootinfo-hp300.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | ** asm/bootinfo-hp300.h -- HP9000/300-specific boot information definitions | ||
3 | */ | ||
4 | |||
5 | #ifndef _UAPI_ASM_M68K_BOOTINFO_HP300_H | ||
6 | #define _UAPI_ASM_M68K_BOOTINFO_HP300_H | ||
7 | |||
8 | |||
9 | /* | ||
10 | * HP9000/300-specific tags | ||
11 | */ | ||
12 | |||
13 | #define BI_HP300_MODEL 0x8000 /* model (__be32) */ | ||
14 | #define BI_HP300_UART_SCODE 0x8001 /* UART select code (__be32) */ | ||
15 | #define BI_HP300_UART_ADDR 0x8002 /* phys. addr of UART (__be32) */ | ||
16 | |||
17 | |||
18 | /* | ||
19 | * HP9000/300 and /400 models (BI_HP300_MODEL) | ||
20 | * | ||
21 | * This information was taken from NetBSD | ||
22 | */ | ||
23 | |||
24 | #define HP_320 0 /* 16MHz 68020+HP MMU+16K external cache */ | ||
25 | #define HP_330 1 /* 16MHz 68020+68851 MMU */ | ||
26 | #define HP_340 2 /* 16MHz 68030 */ | ||
27 | #define HP_345 3 /* 50MHz 68030+32K external cache */ | ||
28 | #define HP_350 4 /* 25MHz 68020+HP MMU+32K external cache */ | ||
29 | #define HP_360 5 /* 25MHz 68030 */ | ||
30 | #define HP_370 6 /* 33MHz 68030+64K external cache */ | ||
31 | #define HP_375 7 /* 50MHz 68030+32K external cache */ | ||
32 | #define HP_380 8 /* 25MHz 68040 */ | ||
33 | #define HP_385 9 /* 33MHz 68040 */ | ||
34 | |||
35 | #define HP_400 10 /* 50MHz 68030+32K external cache */ | ||
36 | #define HP_425T 11 /* 25MHz 68040 - model 425t */ | ||
37 | #define HP_425S 12 /* 25MHz 68040 - model 425s */ | ||
38 | #define HP_425E 13 /* 25MHz 68040 - model 425e */ | ||
39 | #define HP_433T 14 /* 33MHz 68040 - model 433t */ | ||
40 | #define HP_433S 15 /* 33MHz 68040 - model 433s */ | ||
41 | |||
42 | |||
43 | /* | ||
44 | * Latest HP9000/300 bootinfo version | ||
45 | */ | ||
46 | |||
47 | #define HP300_BOOTI_VERSION MK_BI_VERSION(2, 0) | ||
48 | |||
49 | |||
50 | #endif /* _UAPI_ASM_M68K_BOOTINFO_HP300_H */ | ||
diff --git a/arch/m68k/include/uapi/asm/bootinfo-mac.h b/arch/m68k/include/uapi/asm/bootinfo-mac.h new file mode 100644 index 000000000000..b44ff73898a9 --- /dev/null +++ b/arch/m68k/include/uapi/asm/bootinfo-mac.h | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | ** asm/bootinfo-mac.h -- Macintosh-specific boot information definitions | ||
3 | */ | ||
4 | |||
5 | #ifndef _UAPI_ASM_M68K_BOOTINFO_MAC_H | ||
6 | #define _UAPI_ASM_M68K_BOOTINFO_MAC_H | ||
7 | |||
8 | |||
9 | /* | ||
10 | * Macintosh-specific tags (all __be32) | ||
11 | */ | ||
12 | |||
13 | #define BI_MAC_MODEL 0x8000 /* Mac Gestalt ID (model type) */ | ||
14 | #define BI_MAC_VADDR 0x8001 /* Mac video base address */ | ||
15 | #define BI_MAC_VDEPTH 0x8002 /* Mac video depth */ | ||
16 | #define BI_MAC_VROW 0x8003 /* Mac video rowbytes */ | ||
17 | #define BI_MAC_VDIM 0x8004 /* Mac video dimensions */ | ||
18 | #define BI_MAC_VLOGICAL 0x8005 /* Mac video logical base */ | ||
19 | #define BI_MAC_SCCBASE 0x8006 /* Mac SCC base address */ | ||
20 | #define BI_MAC_BTIME 0x8007 /* Mac boot time */ | ||
21 | #define BI_MAC_GMTBIAS 0x8008 /* Mac GMT timezone offset */ | ||
22 | #define BI_MAC_MEMSIZE 0x8009 /* Mac RAM size (sanity check) */ | ||
23 | #define BI_MAC_CPUID 0x800a /* Mac CPU type (sanity check) */ | ||
24 | #define BI_MAC_ROMBASE 0x800b /* Mac system ROM base address */ | ||
25 | |||
26 | |||
27 | /* | ||
28 | * Macintosh hardware profile data - unused, see macintosh.h for | ||
29 | * reasonable type values | ||
30 | */ | ||
31 | |||
32 | #define BI_MAC_VIA1BASE 0x8010 /* Mac VIA1 base address (always present) */ | ||
33 | #define BI_MAC_VIA2BASE 0x8011 /* Mac VIA2 base address (type varies) */ | ||
34 | #define BI_MAC_VIA2TYPE 0x8012 /* Mac VIA2 type (VIA, RBV, OSS) */ | ||
35 | #define BI_MAC_ADBTYPE 0x8013 /* Mac ADB interface type */ | ||
36 | #define BI_MAC_ASCBASE 0x8014 /* Mac Apple Sound Chip base address */ | ||
37 | #define BI_MAC_SCSI5380 0x8015 /* Mac NCR 5380 SCSI (base address, multi) */ | ||
38 | #define BI_MAC_SCSIDMA 0x8016 /* Mac SCSI DMA (base address) */ | ||
39 | #define BI_MAC_SCSI5396 0x8017 /* Mac NCR 53C96 SCSI (base address, multi) */ | ||
40 | #define BI_MAC_IDETYPE 0x8018 /* Mac IDE interface type */ | ||
41 | #define BI_MAC_IDEBASE 0x8019 /* Mac IDE interface base address */ | ||
42 | #define BI_MAC_NUBUS 0x801a /* Mac Nubus type (none, regular, pseudo) */ | ||
43 | #define BI_MAC_SLOTMASK 0x801b /* Mac Nubus slots present */ | ||
44 | #define BI_MAC_SCCTYPE 0x801c /* Mac SCC serial type (normal, IOP) */ | ||
45 | #define BI_MAC_ETHTYPE 0x801d /* Mac builtin ethernet type (Sonic, MACE */ | ||
46 | #define BI_MAC_ETHBASE 0x801e /* Mac builtin ethernet base address */ | ||
47 | #define BI_MAC_PMU 0x801f /* Mac power management / poweroff hardware */ | ||
48 | #define BI_MAC_IOP_SWIM 0x8020 /* Mac SWIM floppy IOP */ | ||
49 | #define BI_MAC_IOP_ADB 0x8021 /* Mac ADB IOP */ | ||
50 | |||
51 | |||
52 | /* | ||
53 | * Macintosh Gestalt numbers (BI_MAC_MODEL) | ||
54 | */ | ||
55 | |||
56 | #define MAC_MODEL_II 6 | ||
57 | #define MAC_MODEL_IIX 7 | ||
58 | #define MAC_MODEL_IICX 8 | ||
59 | #define MAC_MODEL_SE30 9 | ||
60 | #define MAC_MODEL_IICI 11 | ||
61 | #define MAC_MODEL_IIFX 13 /* And well numbered it is too */ | ||
62 | #define MAC_MODEL_IISI 18 | ||
63 | #define MAC_MODEL_LC 19 | ||
64 | #define MAC_MODEL_Q900 20 | ||
65 | #define MAC_MODEL_PB170 21 | ||
66 | #define MAC_MODEL_Q700 22 | ||
67 | #define MAC_MODEL_CLII 23 /* aka: P200 */ | ||
68 | #define MAC_MODEL_PB140 25 | ||
69 | #define MAC_MODEL_Q950 26 /* aka: WGS95 */ | ||
70 | #define MAC_MODEL_LCIII 27 /* aka: P450 */ | ||
71 | #define MAC_MODEL_PB210 29 | ||
72 | #define MAC_MODEL_C650 30 | ||
73 | #define MAC_MODEL_PB230 32 | ||
74 | #define MAC_MODEL_PB180 33 | ||
75 | #define MAC_MODEL_PB160 34 | ||
76 | #define MAC_MODEL_Q800 35 /* aka: WGS80 */ | ||
77 | #define MAC_MODEL_Q650 36 | ||
78 | #define MAC_MODEL_LCII 37 /* aka: P400/405/410/430 */ | ||
79 | #define MAC_MODEL_PB250 38 | ||
80 | #define MAC_MODEL_IIVI 44 | ||
81 | #define MAC_MODEL_P600 45 /* aka: P600CD */ | ||
82 | #define MAC_MODEL_IIVX 48 | ||
83 | #define MAC_MODEL_CCL 49 /* aka: P250 */ | ||
84 | #define MAC_MODEL_PB165C 50 | ||
85 | #define MAC_MODEL_C610 52 /* aka: WGS60 */ | ||
86 | #define MAC_MODEL_Q610 53 | ||
87 | #define MAC_MODEL_PB145 54 /* aka: PB145B */ | ||
88 | #define MAC_MODEL_P520 56 /* aka: LC520 */ | ||
89 | #define MAC_MODEL_C660 60 | ||
90 | #define MAC_MODEL_P460 62 /* aka: LCIII+, P466/P467 */ | ||
91 | #define MAC_MODEL_PB180C 71 | ||
92 | #define MAC_MODEL_PB520 72 /* aka: PB520C, PB540, PB540C, PB550C */ | ||
93 | #define MAC_MODEL_PB270C 77 | ||
94 | #define MAC_MODEL_Q840 78 | ||
95 | #define MAC_MODEL_P550 80 /* aka: LC550, P560 */ | ||
96 | #define MAC_MODEL_CCLII 83 /* aka: P275 */ | ||
97 | #define MAC_MODEL_PB165 84 | ||
98 | #define MAC_MODEL_PB190 85 /* aka: PB190CS */ | ||
99 | #define MAC_MODEL_TV 88 | ||
100 | #define MAC_MODEL_P475 89 /* aka: LC475, P476 */ | ||
101 | #define MAC_MODEL_P475F 90 /* aka: P475 w/ FPU (no LC040) */ | ||
102 | #define MAC_MODEL_P575 92 /* aka: LC575, P577/P578 */ | ||
103 | #define MAC_MODEL_Q605 94 | ||
104 | #define MAC_MODEL_Q605_ACC 95 /* Q605 accelerated to 33 MHz */ | ||
105 | #define MAC_MODEL_Q630 98 /* aka: LC630, P630/631/635/636/637/638/640 */ | ||
106 | #define MAC_MODEL_P588 99 /* aka: LC580, P580 */ | ||
107 | #define MAC_MODEL_PB280 102 | ||
108 | #define MAC_MODEL_PB280C 103 | ||
109 | #define MAC_MODEL_PB150 115 | ||
110 | |||
111 | |||
112 | /* | ||
113 | * Latest Macintosh bootinfo version | ||
114 | */ | ||
115 | |||
116 | #define MAC_BOOTI_VERSION MK_BI_VERSION(2, 0) | ||
117 | |||
118 | |||
119 | #endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */ | ||
diff --git a/arch/m68k/include/uapi/asm/bootinfo-q40.h b/arch/m68k/include/uapi/asm/bootinfo-q40.h new file mode 100644 index 000000000000..c79fea7e555b --- /dev/null +++ b/arch/m68k/include/uapi/asm/bootinfo-q40.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | ** asm/bootinfo-q40.h -- Q40-specific boot information definitions | ||
3 | */ | ||
4 | |||
5 | #ifndef _UAPI_ASM_M68K_BOOTINFO_Q40_H | ||
6 | #define _UAPI_ASM_M68K_BOOTINFO_Q40_H | ||
7 | |||
8 | |||
9 | /* | ||
10 | * Latest Q40 bootinfo version | ||
11 | */ | ||
12 | |||
13 | #define Q40_BOOTI_VERSION MK_BI_VERSION(2, 0) | ||
14 | |||
15 | |||
16 | #endif /* _UAPI_ASM_M68K_BOOTINFO_Q40_H */ | ||
diff --git a/arch/m68k/include/uapi/asm/bootinfo-vme.h b/arch/m68k/include/uapi/asm/bootinfo-vme.h new file mode 100644 index 000000000000..a135eb41d672 --- /dev/null +++ b/arch/m68k/include/uapi/asm/bootinfo-vme.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | ** asm/bootinfo-vme.h -- VME-specific boot information definitions | ||
3 | */ | ||
4 | |||
5 | #ifndef _UAPI_ASM_M68K_BOOTINFO_VME_H | ||
6 | #define _UAPI_ASM_M68K_BOOTINFO_VME_H | ||
7 | |||
8 | |||
9 | #include <linux/types.h> | ||
10 | |||
11 | |||
12 | /* | ||
13 | * VME-specific tags | ||
14 | */ | ||
15 | |||
16 | #define BI_VME_TYPE 0x8000 /* VME sub-architecture (__be32) */ | ||
17 | #define BI_VME_BRDINFO 0x8001 /* VME board information (struct) */ | ||
18 | |||
19 | |||
20 | /* | ||
21 | * VME models (BI_VME_TYPE) | ||
22 | */ | ||
23 | |||
24 | #define VME_TYPE_TP34V 0x0034 /* Tadpole TP34V */ | ||
25 | #define VME_TYPE_MVME147 0x0147 /* Motorola MVME147 */ | ||
26 | #define VME_TYPE_MVME162 0x0162 /* Motorola MVME162 */ | ||
27 | #define VME_TYPE_MVME166 0x0166 /* Motorola MVME166 */ | ||
28 | #define VME_TYPE_MVME167 0x0167 /* Motorola MVME167 */ | ||
29 | #define VME_TYPE_MVME172 0x0172 /* Motorola MVME172 */ | ||
30 | #define VME_TYPE_MVME177 0x0177 /* Motorola MVME177 */ | ||
31 | #define VME_TYPE_BVME4000 0x4000 /* BVM Ltd. BVME4000 */ | ||
32 | #define VME_TYPE_BVME6000 0x6000 /* BVM Ltd. BVME6000 */ | ||
33 | |||
34 | |||
35 | #ifndef __ASSEMBLY__ | ||
36 | |||
37 | /* | ||
38 | * Board ID data structure - pointer to this retrieved from Bug by head.S | ||
39 | * | ||
40 | * BI_VME_BRDINFO is a 32 byte struct as returned by the Bug code on | ||
41 | * Motorola VME boards. Contains board number, Bug version, board | ||
42 | * configuration options, etc. | ||
43 | * | ||
44 | * Note, bytes 12 and 13 are board no in BCD (0162,0166,0167,0177,etc) | ||
45 | */ | ||
46 | |||
47 | typedef struct { | ||
48 | char bdid[4]; | ||
49 | __u8 rev, mth, day, yr; | ||
50 | __be16 size, reserved; | ||
51 | __be16 brdno; | ||
52 | char brdsuffix[2]; | ||
53 | __be32 options; | ||
54 | __be16 clun, dlun, ctype, dnum; | ||
55 | __be32 option2; | ||
56 | } t_bdid, *p_bdid; | ||
57 | |||
58 | #endif /* __ASSEMBLY__ */ | ||
59 | |||
60 | |||
61 | /* | ||
62 | * Latest VME bootinfo versions | ||
63 | */ | ||
64 | |||
65 | #define MVME147_BOOTI_VERSION MK_BI_VERSION(2, 0) | ||
66 | #define MVME16x_BOOTI_VERSION MK_BI_VERSION(2, 0) | ||
67 | #define BVME6000_BOOTI_VERSION MK_BI_VERSION(2, 0) | ||
68 | |||
69 | |||
70 | #endif /* _UAPI_ASM_M68K_BOOTINFO_VME_H */ | ||
diff --git a/arch/m68k/include/uapi/asm/bootinfo.h b/arch/m68k/include/uapi/asm/bootinfo.h new file mode 100644 index 000000000000..cdeb26a015b0 --- /dev/null +++ b/arch/m68k/include/uapi/asm/bootinfo.h | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * asm/bootinfo.h -- Definition of the Linux/m68k boot information structure | ||
3 | * | ||
4 | * Copyright 1992 by Greg Harp | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | #ifndef _UAPI_ASM_M68K_BOOTINFO_H | ||
12 | #define _UAPI_ASM_M68K_BOOTINFO_H | ||
13 | |||
14 | |||
15 | #include <linux/types.h> | ||
16 | |||
17 | |||
18 | #ifndef __ASSEMBLY__ | ||
19 | |||
20 | /* | ||
21 | * Bootinfo definitions | ||
22 | * | ||
23 | * This is an easily parsable and extendable structure containing all | ||
24 | * information to be passed from the bootstrap to the kernel. | ||
25 | * | ||
26 | * This way I hope to keep all future changes back/forewards compatible. | ||
27 | * Thus, keep your fingers crossed... | ||
28 | * | ||
29 | * This structure is copied right after the kernel by the bootstrap | ||
30 | * routine. | ||
31 | */ | ||
32 | |||
33 | struct bi_record { | ||
34 | __be16 tag; /* tag ID */ | ||
35 | __be16 size; /* size of record (in bytes) */ | ||
36 | __be32 data[0]; /* data */ | ||
37 | }; | ||
38 | |||
39 | |||
40 | struct mem_info { | ||
41 | __be32 addr; /* physical address of memory chunk */ | ||
42 | __be32 size; /* length of memory chunk (in bytes) */ | ||
43 | }; | ||
44 | |||
45 | #endif /* __ASSEMBLY__ */ | ||
46 | |||
47 | |||
48 | /* | ||
49 | * Tag Definitions | ||
50 | * | ||
51 | * Machine independent tags start counting from 0x0000 | ||
52 | * Machine dependent tags start counting from 0x8000 | ||
53 | */ | ||
54 | |||
55 | #define BI_LAST 0x0000 /* last record (sentinel) */ | ||
56 | #define BI_MACHTYPE 0x0001 /* machine type (__be32) */ | ||
57 | #define BI_CPUTYPE 0x0002 /* cpu type (__be32) */ | ||
58 | #define BI_FPUTYPE 0x0003 /* fpu type (__be32) */ | ||
59 | #define BI_MMUTYPE 0x0004 /* mmu type (__be32) */ | ||
60 | #define BI_MEMCHUNK 0x0005 /* memory chunk address and size */ | ||
61 | /* (struct mem_info) */ | ||
62 | #define BI_RAMDISK 0x0006 /* ramdisk address and size */ | ||
63 | /* (struct mem_info) */ | ||
64 | #define BI_COMMAND_LINE 0x0007 /* kernel command line parameters */ | ||
65 | /* (string) */ | ||
66 | |||
67 | |||
68 | /* | ||
69 | * Linux/m68k Architectures (BI_MACHTYPE) | ||
70 | */ | ||
71 | |||
72 | #define MACH_AMIGA 1 | ||
73 | #define MACH_ATARI 2 | ||
74 | #define MACH_MAC 3 | ||
75 | #define MACH_APOLLO 4 | ||
76 | #define MACH_SUN3 5 | ||
77 | #define MACH_MVME147 6 | ||
78 | #define MACH_MVME16x 7 | ||
79 | #define MACH_BVME6000 8 | ||
80 | #define MACH_HP300 9 | ||
81 | #define MACH_Q40 10 | ||
82 | #define MACH_SUN3X 11 | ||
83 | #define MACH_M54XX 12 | ||
84 | |||
85 | |||
86 | /* | ||
87 | * CPU, FPU and MMU types (BI_CPUTYPE, BI_FPUTYPE, BI_MMUTYPE) | ||
88 | * | ||
89 | * Note: we may rely on the following equalities: | ||
90 | * | ||
91 | * CPU_68020 == MMU_68851 | ||
92 | * CPU_68030 == MMU_68030 | ||
93 | * CPU_68040 == FPU_68040 == MMU_68040 | ||
94 | * CPU_68060 == FPU_68060 == MMU_68060 | ||
95 | */ | ||
96 | |||
97 | #define CPUB_68020 0 | ||
98 | #define CPUB_68030 1 | ||
99 | #define CPUB_68040 2 | ||
100 | #define CPUB_68060 3 | ||
101 | #define CPUB_COLDFIRE 4 | ||
102 | |||
103 | #define CPU_68020 (1 << CPUB_68020) | ||
104 | #define CPU_68030 (1 << CPUB_68030) | ||
105 | #define CPU_68040 (1 << CPUB_68040) | ||
106 | #define CPU_68060 (1 << CPUB_68060) | ||
107 | #define CPU_COLDFIRE (1 << CPUB_COLDFIRE) | ||
108 | |||
109 | #define FPUB_68881 0 | ||
110 | #define FPUB_68882 1 | ||
111 | #define FPUB_68040 2 /* Internal FPU */ | ||
112 | #define FPUB_68060 3 /* Internal FPU */ | ||
113 | #define FPUB_SUNFPA 4 /* Sun-3 FPA */ | ||
114 | #define FPUB_COLDFIRE 5 /* ColdFire FPU */ | ||
115 | |||
116 | #define FPU_68881 (1 << FPUB_68881) | ||
117 | #define FPU_68882 (1 << FPUB_68882) | ||
118 | #define FPU_68040 (1 << FPUB_68040) | ||
119 | #define FPU_68060 (1 << FPUB_68060) | ||
120 | #define FPU_SUNFPA (1 << FPUB_SUNFPA) | ||
121 | #define FPU_COLDFIRE (1 << FPUB_COLDFIRE) | ||
122 | |||
123 | #define MMUB_68851 0 | ||
124 | #define MMUB_68030 1 /* Internal MMU */ | ||
125 | #define MMUB_68040 2 /* Internal MMU */ | ||
126 | #define MMUB_68060 3 /* Internal MMU */ | ||
127 | #define MMUB_APOLLO 4 /* Custom Apollo */ | ||
128 | #define MMUB_SUN3 5 /* Custom Sun-3 */ | ||
129 | #define MMUB_COLDFIRE 6 /* Internal MMU */ | ||
130 | |||
131 | #define MMU_68851 (1 << MMUB_68851) | ||
132 | #define MMU_68030 (1 << MMUB_68030) | ||
133 | #define MMU_68040 (1 << MMUB_68040) | ||
134 | #define MMU_68060 (1 << MMUB_68060) | ||
135 | #define MMU_SUN3 (1 << MMUB_SUN3) | ||
136 | #define MMU_APOLLO (1 << MMUB_APOLLO) | ||
137 | #define MMU_COLDFIRE (1 << MMUB_COLDFIRE) | ||
138 | |||
139 | |||
140 | /* | ||
141 | * Stuff for bootinfo interface versioning | ||
142 | * | ||
143 | * At the start of kernel code, a 'struct bootversion' is located. | ||
144 | * bootstrap checks for a matching version of the interface before booting | ||
145 | * a kernel, to avoid user confusion if kernel and bootstrap don't work | ||
146 | * together :-) | ||
147 | * | ||
148 | * If incompatible changes are made to the bootinfo interface, the major | ||
149 | * number below should be stepped (and the minor reset to 0) for the | ||
150 | * appropriate machine. If a change is backward-compatible, the minor | ||
151 | * should be stepped. "Backwards-compatible" means that booting will work, | ||
152 | * but certain features may not. | ||
153 | */ | ||
154 | |||
155 | #define BOOTINFOV_MAGIC 0x4249561A /* 'BIV^Z' */ | ||
156 | #define MK_BI_VERSION(major, minor) (((major) << 16) + (minor)) | ||
157 | #define BI_VERSION_MAJOR(v) (((v) >> 16) & 0xffff) | ||
158 | #define BI_VERSION_MINOR(v) ((v) & 0xffff) | ||
159 | |||
160 | #ifndef __ASSEMBLY__ | ||
161 | |||
162 | struct bootversion { | ||
163 | __be16 branch; | ||
164 | __be32 magic; | ||
165 | struct { | ||
166 | __be32 machtype; | ||
167 | __be32 version; | ||
168 | } machversions[0]; | ||
169 | } __packed; | ||
170 | |||
171 | #endif /* __ASSEMBLY__ */ | ||
172 | |||
173 | |||
174 | #endif /* _UAPI_ASM_M68K_BOOTINFO_H */ | ||
diff --git a/arch/m68k/include/uapi/asm/setup.h b/arch/m68k/include/uapi/asm/setup.h index 85579bff455c..6a6dc636761e 100644 --- a/arch/m68k/include/uapi/asm/setup.h +++ b/arch/m68k/include/uapi/asm/setup.h | |||
@@ -6,98 +6,11 @@ | |||
6 | ** This file is subject to the terms and conditions of the GNU General Public | 6 | ** This file is subject to the terms and conditions of the GNU General Public |
7 | ** License. See the file COPYING in the main directory of this archive | 7 | ** License. See the file COPYING in the main directory of this archive |
8 | ** for more details. | 8 | ** for more details. |
9 | ** | ||
10 | ** Created 09/29/92 by Greg Harp | ||
11 | ** | ||
12 | ** 5/2/94 Roman Hodek: | ||
13 | ** Added bi_atari part of the machine dependent union bi_un; for now it | ||
14 | ** contains just a model field to distinguish between TT and Falcon. | ||
15 | ** 26/7/96 Roman Zippel: | ||
16 | ** Renamed to setup.h; added some useful macros to allow gcc some | ||
17 | ** optimizations if possible. | ||
18 | ** 5/10/96 Geert Uytterhoeven: | ||
19 | ** Redesign of the boot information structure; moved boot information | ||
20 | ** structure to bootinfo.h | ||
21 | */ | 9 | */ |
22 | 10 | ||
23 | #ifndef _UAPI_M68K_SETUP_H | 11 | #ifndef _UAPI_M68K_SETUP_H |
24 | #define _UAPI_M68K_SETUP_H | 12 | #define _UAPI_M68K_SETUP_H |
25 | 13 | ||
26 | |||
27 | |||
28 | /* | ||
29 | * Linux/m68k Architectures | ||
30 | */ | ||
31 | |||
32 | #define MACH_AMIGA 1 | ||
33 | #define MACH_ATARI 2 | ||
34 | #define MACH_MAC 3 | ||
35 | #define MACH_APOLLO 4 | ||
36 | #define MACH_SUN3 5 | ||
37 | #define MACH_MVME147 6 | ||
38 | #define MACH_MVME16x 7 | ||
39 | #define MACH_BVME6000 8 | ||
40 | #define MACH_HP300 9 | ||
41 | #define MACH_Q40 10 | ||
42 | #define MACH_SUN3X 11 | ||
43 | #define MACH_M54XX 12 | ||
44 | |||
45 | #define COMMAND_LINE_SIZE 256 | 14 | #define COMMAND_LINE_SIZE 256 |
46 | 15 | ||
47 | |||
48 | |||
49 | /* | ||
50 | * CPU, FPU and MMU types | ||
51 | * | ||
52 | * Note: we may rely on the following equalities: | ||
53 | * | ||
54 | * CPU_68020 == MMU_68851 | ||
55 | * CPU_68030 == MMU_68030 | ||
56 | * CPU_68040 == FPU_68040 == MMU_68040 | ||
57 | * CPU_68060 == FPU_68060 == MMU_68060 | ||
58 | */ | ||
59 | |||
60 | #define CPUB_68020 0 | ||
61 | #define CPUB_68030 1 | ||
62 | #define CPUB_68040 2 | ||
63 | #define CPUB_68060 3 | ||
64 | #define CPUB_COLDFIRE 4 | ||
65 | |||
66 | #define CPU_68020 (1<<CPUB_68020) | ||
67 | #define CPU_68030 (1<<CPUB_68030) | ||
68 | #define CPU_68040 (1<<CPUB_68040) | ||
69 | #define CPU_68060 (1<<CPUB_68060) | ||
70 | #define CPU_COLDFIRE (1<<CPUB_COLDFIRE) | ||
71 | |||
72 | #define FPUB_68881 0 | ||
73 | #define FPUB_68882 1 | ||
74 | #define FPUB_68040 2 /* Internal FPU */ | ||
75 | #define FPUB_68060 3 /* Internal FPU */ | ||
76 | #define FPUB_SUNFPA 4 /* Sun-3 FPA */ | ||
77 | #define FPUB_COLDFIRE 5 /* ColdFire FPU */ | ||
78 | |||
79 | #define FPU_68881 (1<<FPUB_68881) | ||
80 | #define FPU_68882 (1<<FPUB_68882) | ||
81 | #define FPU_68040 (1<<FPUB_68040) | ||
82 | #define FPU_68060 (1<<FPUB_68060) | ||
83 | #define FPU_SUNFPA (1<<FPUB_SUNFPA) | ||
84 | #define FPU_COLDFIRE (1<<FPUB_COLDFIRE) | ||
85 | |||
86 | #define MMUB_68851 0 | ||
87 | #define MMUB_68030 1 /* Internal MMU */ | ||
88 | #define MMUB_68040 2 /* Internal MMU */ | ||
89 | #define MMUB_68060 3 /* Internal MMU */ | ||
90 | #define MMUB_APOLLO 4 /* Custom Apollo */ | ||
91 | #define MMUB_SUN3 5 /* Custom Sun-3 */ | ||
92 | #define MMUB_COLDFIRE 6 /* Internal MMU */ | ||
93 | |||
94 | #define MMU_68851 (1<<MMUB_68851) | ||
95 | #define MMU_68030 (1<<MMUB_68030) | ||
96 | #define MMU_68040 (1<<MMUB_68040) | ||
97 | #define MMU_68060 (1<<MMUB_68060) | ||
98 | #define MMU_SUN3 (1<<MMUB_SUN3) | ||
99 | #define MMU_APOLLO (1<<MMUB_APOLLO) | ||
100 | #define MMU_COLDFIRE (1<<MMUB_COLDFIRE) | ||
101 | |||
102 | |||
103 | #endif /* _UAPI_M68K_SETUP_H */ | 16 | #endif /* _UAPI_M68K_SETUP_H */ |
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 655347d80780..2d5d9be16273 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile | |||
@@ -22,3 +22,6 @@ obj-$(CONFIG_PCI) += pcibios.o | |||
22 | 22 | ||
23 | obj-$(CONFIG_HAS_DMA) += dma.o | 23 | obj-$(CONFIG_HAS_DMA) += dma.o |
24 | 24 | ||
25 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | ||
26 | obj-$(CONFIG_BOOTINFO_PROC) += bootinfo_proc.o | ||
27 | |||
diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index 8b7b22846366..3a386341aa6e 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c | |||
@@ -98,6 +98,9 @@ int main(void) | |||
98 | DEFINE(CIABBASE, &ciab); | 98 | DEFINE(CIABBASE, &ciab); |
99 | DEFINE(C_PRA, offsetof(struct CIA, pra)); | 99 | DEFINE(C_PRA, offsetof(struct CIA, pra)); |
100 | DEFINE(ZTWOBASE, zTwoBase); | 100 | DEFINE(ZTWOBASE, zTwoBase); |
101 | |||
102 | /* enum m68k_fixup_type */ | ||
103 | DEFINE(M68K_FIXUP_MEMOFFSET, m68k_fixup_memoffset); | ||
101 | #endif | 104 | #endif |
102 | 105 | ||
103 | return 0; | 106 | return 0; |
diff --git a/arch/m68k/kernel/bootinfo_proc.c b/arch/m68k/kernel/bootinfo_proc.c new file mode 100644 index 000000000000..7ee853e1432b --- /dev/null +++ b/arch/m68k/kernel/bootinfo_proc.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/atags_proc.c | ||
3 | */ | ||
4 | |||
5 | #include <linux/fs.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/printk.h> | ||
8 | #include <linux/proc_fs.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/string.h> | ||
11 | |||
12 | #include <asm/bootinfo.h> | ||
13 | #include <asm/byteorder.h> | ||
14 | |||
15 | |||
16 | static char bootinfo_tmp[1536] __initdata; | ||
17 | |||
18 | static void *bootinfo_copy; | ||
19 | static size_t bootinfo_size; | ||
20 | |||
21 | static ssize_t bootinfo_read(struct file *file, char __user *buf, | ||
22 | size_t count, loff_t *ppos) | ||
23 | { | ||
24 | return simple_read_from_buffer(buf, count, ppos, bootinfo_copy, | ||
25 | bootinfo_size); | ||
26 | } | ||
27 | |||
28 | static const struct file_operations bootinfo_fops = { | ||
29 | .read = bootinfo_read, | ||
30 | .llseek = default_llseek, | ||
31 | }; | ||
32 | |||
33 | void __init save_bootinfo(const struct bi_record *bi) | ||
34 | { | ||
35 | const void *start = bi; | ||
36 | size_t size = sizeof(bi->tag); | ||
37 | |||
38 | while (be16_to_cpu(bi->tag) != BI_LAST) { | ||
39 | uint16_t n = be16_to_cpu(bi->size); | ||
40 | size += n; | ||
41 | bi = (struct bi_record *)((unsigned long)bi + n); | ||
42 | } | ||
43 | |||
44 | if (size > sizeof(bootinfo_tmp)) { | ||
45 | pr_err("Cannot save %zu bytes of bootinfo\n", size); | ||
46 | return; | ||
47 | } | ||
48 | |||
49 | pr_info("Saving %zu bytes of bootinfo\n", size); | ||
50 | memcpy(bootinfo_tmp, start, size); | ||
51 | bootinfo_size = size; | ||
52 | } | ||
53 | |||
54 | static int __init init_bootinfo_procfs(void) | ||
55 | { | ||
56 | /* | ||
57 | * This cannot go into save_bootinfo() because kmalloc and proc don't | ||
58 | * work yet when it is called. | ||
59 | */ | ||
60 | struct proc_dir_entry *pde; | ||
61 | |||
62 | if (!bootinfo_size) | ||
63 | return -EINVAL; | ||
64 | |||
65 | bootinfo_copy = kmalloc(bootinfo_size, GFP_KERNEL); | ||
66 | if (!bootinfo_copy) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | memcpy(bootinfo_copy, bootinfo_tmp, bootinfo_size); | ||
70 | |||
71 | pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL); | ||
72 | if (!pde) { | ||
73 | kfree(bootinfo_copy); | ||
74 | return -ENOMEM; | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | arch_initcall(init_bootinfo_procfs); | ||
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index ac85f16534af..4c99bab7e664 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S | |||
@@ -23,7 +23,7 @@ | |||
23 | ** 98/04/25 Phil Blundell: added HP300 support | 23 | ** 98/04/25 Phil Blundell: added HP300 support |
24 | ** 1998/08/30 David Kilzer: Added support for font_desc structures | 24 | ** 1998/08/30 David Kilzer: Added support for font_desc structures |
25 | ** for linux-2.1.115 | 25 | ** for linux-2.1.115 |
26 | ** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01) | 26 | ** 1999/02/11 Richard Zidlicky: added Q40 support (initial version 99/01/01) |
27 | ** 2004/05/13 Kars de Jong: Finalised HP300 support | 27 | ** 2004/05/13 Kars de Jong: Finalised HP300 support |
28 | ** | 28 | ** |
29 | ** This file is subject to the terms and conditions of the GNU General Public | 29 | ** This file is subject to the terms and conditions of the GNU General Public |
@@ -257,6 +257,12 @@ | |||
257 | #include <linux/linkage.h> | 257 | #include <linux/linkage.h> |
258 | #include <linux/init.h> | 258 | #include <linux/init.h> |
259 | #include <asm/bootinfo.h> | 259 | #include <asm/bootinfo.h> |
260 | #include <asm/bootinfo-amiga.h> | ||
261 | #include <asm/bootinfo-atari.h> | ||
262 | #include <asm/bootinfo-hp300.h> | ||
263 | #include <asm/bootinfo-mac.h> | ||
264 | #include <asm/bootinfo-q40.h> | ||
265 | #include <asm/bootinfo-vme.h> | ||
260 | #include <asm/setup.h> | 266 | #include <asm/setup.h> |
261 | #include <asm/entry.h> | 267 | #include <asm/entry.h> |
262 | #include <asm/pgtable.h> | 268 | #include <asm/pgtable.h> |
@@ -1532,7 +1538,7 @@ L(cache_done): | |||
1532 | 1538 | ||
1533 | /* | 1539 | /* |
1534 | * Find a tag record in the bootinfo structure | 1540 | * Find a tag record in the bootinfo structure |
1535 | * The bootinfo structure is located right after the kernel bss | 1541 | * The bootinfo structure is located right after the kernel |
1536 | * Returns: d0: size (-1 if not found) | 1542 | * Returns: d0: size (-1 if not found) |
1537 | * a0: data pointer (end-of-records if not found) | 1543 | * a0: data pointer (end-of-records if not found) |
1538 | */ | 1544 | */ |
@@ -2909,7 +2915,9 @@ func_start serial_init,%d0/%d1/%a0/%a1 | |||
2909 | 2915 | ||
2910 | #if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B) | 2916 | #if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B) |
2911 | movel %pc@(L(mac_sccbase)),%a0 | 2917 | movel %pc@(L(mac_sccbase)),%a0 |
2912 | /* Reset SCC device */ | 2918 | /* Reset SCC register pointer */ |
2919 | moveb %a0@(mac_scc_cha_a_ctrl_offset),%d0 | ||
2920 | /* Reset SCC device: write register pointer then register value */ | ||
2913 | moveb #9,%a0@(mac_scc_cha_a_ctrl_offset) | 2921 | moveb #9,%a0@(mac_scc_cha_a_ctrl_offset) |
2914 | moveb #0xc0,%a0@(mac_scc_cha_a_ctrl_offset) | 2922 | moveb #0xc0,%a0@(mac_scc_cha_a_ctrl_offset) |
2915 | /* Wait for 5 PCLK cycles, which is about 68 CPU cycles */ | 2923 | /* Wait for 5 PCLK cycles, which is about 68 CPU cycles */ |
@@ -3896,8 +3904,6 @@ BVME_SCC_DATA_A = 0xffb0000f | |||
3896 | #endif | 3904 | #endif |
3897 | 3905 | ||
3898 | #if defined(CONFIG_MAC) | 3906 | #if defined(CONFIG_MAC) |
3899 | L(mac_booter_data): | ||
3900 | .long 0 | ||
3901 | L(mac_videobase): | 3907 | L(mac_videobase): |
3902 | .long 0 | 3908 | .long 0 |
3903 | L(mac_videodepth): | 3909 | L(mac_videodepth): |
diff --git a/arch/m68k/kernel/machine_kexec.c b/arch/m68k/kernel/machine_kexec.c new file mode 100644 index 000000000000..d4affc917d9d --- /dev/null +++ b/arch/m68k/kernel/machine_kexec.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * machine_kexec.c - handle transition of Linux booting another kernel | ||
3 | */ | ||
4 | #include <linux/compiler.h> | ||
5 | #include <linux/kexec.h> | ||
6 | #include <linux/mm.h> | ||
7 | #include <linux/delay.h> | ||
8 | |||
9 | #include <asm/cacheflush.h> | ||
10 | #include <asm/page.h> | ||
11 | #include <asm/setup.h> | ||
12 | |||
13 | extern const unsigned char relocate_new_kernel[]; | ||
14 | extern const size_t relocate_new_kernel_size; | ||
15 | |||
16 | int machine_kexec_prepare(struct kimage *kimage) | ||
17 | { | ||
18 | return 0; | ||
19 | } | ||
20 | |||
21 | void machine_kexec_cleanup(struct kimage *kimage) | ||
22 | { | ||
23 | } | ||
24 | |||
25 | void machine_shutdown(void) | ||
26 | { | ||
27 | } | ||
28 | |||
29 | void machine_crash_shutdown(struct pt_regs *regs) | ||
30 | { | ||
31 | } | ||
32 | |||
33 | typedef void (*relocate_kernel_t)(unsigned long ptr, | ||
34 | unsigned long start, | ||
35 | unsigned long cpu_mmu_flags) __noreturn; | ||
36 | |||
37 | void machine_kexec(struct kimage *image) | ||
38 | { | ||
39 | void *reboot_code_buffer; | ||
40 | unsigned long cpu_mmu_flags; | ||
41 | |||
42 | reboot_code_buffer = page_address(image->control_code_page); | ||
43 | |||
44 | memcpy(reboot_code_buffer, relocate_new_kernel, | ||
45 | relocate_new_kernel_size); | ||
46 | |||
47 | /* | ||
48 | * we do not want to be bothered. | ||
49 | */ | ||
50 | local_irq_disable(); | ||
51 | |||
52 | pr_info("Will call new kernel at 0x%08lx. Bye...\n", image->start); | ||
53 | __flush_cache_all(); | ||
54 | cpu_mmu_flags = m68k_cputype | m68k_mmutype << 8; | ||
55 | ((relocate_kernel_t) reboot_code_buffer)(image->head & PAGE_MASK, | ||
56 | image->start, | ||
57 | cpu_mmu_flags); | ||
58 | } | ||
diff --git a/arch/m68k/kernel/relocate_kernel.S b/arch/m68k/kernel/relocate_kernel.S new file mode 100644 index 000000000000..3e09a89067ad --- /dev/null +++ b/arch/m68k/kernel/relocate_kernel.S | |||
@@ -0,0 +1,159 @@ | |||
1 | #include <linux/linkage.h> | ||
2 | |||
3 | #include <asm/asm-offsets.h> | ||
4 | #include <asm/page.h> | ||
5 | #include <asm/setup.h> | ||
6 | |||
7 | |||
8 | #define MMU_BASE 8 /* MMU flags base in cpu_mmu_flags */ | ||
9 | |||
10 | .text | ||
11 | |||
12 | ENTRY(relocate_new_kernel) | ||
13 | movel %sp@(4),%a0 /* a0 = ptr */ | ||
14 | movel %sp@(8),%a1 /* a1 = start */ | ||
15 | movel %sp@(12),%d1 /* d1 = cpu_mmu_flags */ | ||
16 | movew #PAGE_MASK,%d2 /* d2 = PAGE_MASK */ | ||
17 | |||
18 | /* Disable MMU */ | ||
19 | |||
20 | btst #MMU_BASE + MMUB_68851,%d1 | ||
21 | jeq 3f | ||
22 | |||
23 | 1: /* 68851 or 68030 */ | ||
24 | |||
25 | lea %pc@(.Lcopy),%a4 | ||
26 | 2: addl #0x00000000,%a4 /* virt_to_phys() */ | ||
27 | |||
28 | .section ".m68k_fixup","aw" | ||
29 | .long M68K_FIXUP_MEMOFFSET, 2b+2 | ||
30 | .previous | ||
31 | |||
32 | .chip 68030 | ||
33 | pmove %tc,%d0 /* Disable MMU */ | ||
34 | bclr #7,%d0 | ||
35 | pmove %d0,%tc | ||
36 | jmp %a4@ /* Jump to physical .Lcopy */ | ||
37 | .chip 68k | ||
38 | |||
39 | 3: | ||
40 | btst #MMU_BASE + MMUB_68030,%d1 | ||
41 | jne 1b | ||
42 | |||
43 | btst #MMU_BASE + MMUB_68040,%d1 | ||
44 | jeq 6f | ||
45 | |||
46 | 4: /* 68040 or 68060 */ | ||
47 | |||
48 | lea %pc@(.Lcont040),%a4 | ||
49 | 5: addl #0x00000000,%a4 /* virt_to_phys() */ | ||
50 | |||
51 | .section ".m68k_fixup","aw" | ||
52 | .long M68K_FIXUP_MEMOFFSET, 5b+2 | ||
53 | .previous | ||
54 | |||
55 | movel %a4,%d0 | ||
56 | andl #0xff000000,%d0 | ||
57 | orw #0xe020,%d0 /* Map 16 MiB, enable, cacheable */ | ||
58 | .chip 68040 | ||
59 | movec %d0,%itt0 | ||
60 | movec %d0,%dtt0 | ||
61 | .chip 68k | ||
62 | jmp %a4@ /* Jump to physical .Lcont040 */ | ||
63 | |||
64 | .Lcont040: | ||
65 | moveq #0,%d0 | ||
66 | .chip 68040 | ||
67 | movec %d0,%tc /* Disable MMU */ | ||
68 | movec %d0,%itt0 | ||
69 | movec %d0,%itt1 | ||
70 | movec %d0,%dtt0 | ||
71 | movec %d0,%dtt1 | ||
72 | .chip 68k | ||
73 | jra .Lcopy | ||
74 | |||
75 | 6: | ||
76 | btst #MMU_BASE + MMUB_68060,%d1 | ||
77 | jne 4b | ||
78 | |||
79 | .Lcopy: | ||
80 | movel %a0@+,%d0 /* d0 = entry = *ptr */ | ||
81 | jeq .Lflush | ||
82 | |||
83 | btst #2,%d0 /* entry & IND_DONE? */ | ||
84 | jne .Lflush | ||
85 | |||
86 | btst #1,%d0 /* entry & IND_INDIRECTION? */ | ||
87 | jeq 1f | ||
88 | andw %d2,%d0 | ||
89 | movel %d0,%a0 /* ptr = entry & PAGE_MASK */ | ||
90 | jra .Lcopy | ||
91 | |||
92 | 1: | ||
93 | btst #0,%d0 /* entry & IND_DESTINATION? */ | ||
94 | jeq 2f | ||
95 | andw %d2,%d0 | ||
96 | movel %d0,%a2 /* a2 = dst = entry & PAGE_MASK */ | ||
97 | jra .Lcopy | ||
98 | |||
99 | 2: | ||
100 | btst #3,%d0 /* entry & IND_SOURCE? */ | ||
101 | jeq .Lcopy | ||
102 | |||
103 | andw %d2,%d0 | ||
104 | movel %d0,%a3 /* a3 = src = entry & PAGE_MASK */ | ||
105 | movew #PAGE_SIZE/32 - 1,%d0 /* d0 = PAGE_SIZE/32 - 1 */ | ||
106 | 3: | ||
107 | movel %a3@+,%a2@+ /* *dst++ = *src++ */ | ||
108 | movel %a3@+,%a2@+ /* *dst++ = *src++ */ | ||
109 | movel %a3@+,%a2@+ /* *dst++ = *src++ */ | ||
110 | movel %a3@+,%a2@+ /* *dst++ = *src++ */ | ||
111 | movel %a3@+,%a2@+ /* *dst++ = *src++ */ | ||
112 | movel %a3@+,%a2@+ /* *dst++ = *src++ */ | ||
113 | movel %a3@+,%a2@+ /* *dst++ = *src++ */ | ||
114 | movel %a3@+,%a2@+ /* *dst++ = *src++ */ | ||
115 | dbf %d0, 3b | ||
116 | jra .Lcopy | ||
117 | |||
118 | .Lflush: | ||
119 | /* Flush all caches */ | ||
120 | |||
121 | btst #CPUB_68020,%d1 | ||
122 | jeq 2f | ||
123 | |||
124 | 1: /* 68020 or 68030 */ | ||
125 | .chip 68030 | ||
126 | movec %cacr,%d0 | ||
127 | orw #0x808,%d0 | ||
128 | movec %d0,%cacr | ||
129 | .chip 68k | ||
130 | jra .Lreincarnate | ||
131 | |||
132 | 2: | ||
133 | btst #CPUB_68030,%d1 | ||
134 | jne 1b | ||
135 | |||
136 | btst #CPUB_68040,%d1 | ||
137 | jeq 4f | ||
138 | |||
139 | 3: /* 68040 or 68060 */ | ||
140 | .chip 68040 | ||
141 | nop | ||
142 | cpusha %bc | ||
143 | nop | ||
144 | cinva %bc | ||
145 | nop | ||
146 | .chip 68k | ||
147 | jra .Lreincarnate | ||
148 | |||
149 | 4: | ||
150 | btst #CPUB_68060,%d1 | ||
151 | jne 3b | ||
152 | |||
153 | .Lreincarnate: | ||
154 | jmp %a1@ | ||
155 | |||
156 | relocate_new_kernel_end: | ||
157 | |||
158 | ENTRY(relocate_new_kernel_size) | ||
159 | .long relocate_new_kernel_end - relocate_new_kernel | ||
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c index e67e53159573..5b8ec4d5f8e8 100644 --- a/arch/m68k/kernel/setup_mm.c +++ b/arch/m68k/kernel/setup_mm.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/initrd.h> | 26 | #include <linux/initrd.h> |
27 | 27 | ||
28 | #include <asm/bootinfo.h> | 28 | #include <asm/bootinfo.h> |
29 | #include <asm/byteorder.h> | ||
29 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
30 | #include <asm/setup.h> | 31 | #include <asm/setup.h> |
31 | #include <asm/fpu.h> | 32 | #include <asm/fpu.h> |
@@ -71,12 +72,12 @@ EXPORT_SYMBOL(m68k_num_memory); | |||
71 | int m68k_realnum_memory; | 72 | int m68k_realnum_memory; |
72 | EXPORT_SYMBOL(m68k_realnum_memory); | 73 | EXPORT_SYMBOL(m68k_realnum_memory); |
73 | unsigned long m68k_memoffset; | 74 | unsigned long m68k_memoffset; |
74 | struct mem_info m68k_memory[NUM_MEMINFO]; | 75 | struct m68k_mem_info m68k_memory[NUM_MEMINFO]; |
75 | EXPORT_SYMBOL(m68k_memory); | 76 | EXPORT_SYMBOL(m68k_memory); |
76 | 77 | ||
77 | struct mem_info m68k_ramdisk; | 78 | static struct m68k_mem_info m68k_ramdisk __initdata; |
78 | 79 | ||
79 | static char m68k_command_line[CL_SIZE]; | 80 | static char m68k_command_line[CL_SIZE] __initdata; |
80 | 81 | ||
81 | void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL; | 82 | void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL; |
82 | /* machine dependent irq functions */ | 83 | /* machine dependent irq functions */ |
@@ -143,11 +144,16 @@ extern void paging_init(void); | |||
143 | 144 | ||
144 | static void __init m68k_parse_bootinfo(const struct bi_record *record) | 145 | static void __init m68k_parse_bootinfo(const struct bi_record *record) |
145 | { | 146 | { |
146 | while (record->tag != BI_LAST) { | 147 | uint16_t tag; |
148 | |||
149 | save_bootinfo(record); | ||
150 | |||
151 | while ((tag = be16_to_cpu(record->tag)) != BI_LAST) { | ||
147 | int unknown = 0; | 152 | int unknown = 0; |
148 | const unsigned long *data = record->data; | 153 | const void *data = record->data; |
154 | uint16_t size = be16_to_cpu(record->size); | ||
149 | 155 | ||
150 | switch (record->tag) { | 156 | switch (tag) { |
151 | case BI_MACHTYPE: | 157 | case BI_MACHTYPE: |
152 | case BI_CPUTYPE: | 158 | case BI_CPUTYPE: |
153 | case BI_FPUTYPE: | 159 | case BI_FPUTYPE: |
@@ -157,20 +163,27 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record) | |||
157 | 163 | ||
158 | case BI_MEMCHUNK: | 164 | case BI_MEMCHUNK: |
159 | if (m68k_num_memory < NUM_MEMINFO) { | 165 | if (m68k_num_memory < NUM_MEMINFO) { |
160 | m68k_memory[m68k_num_memory].addr = data[0]; | 166 | const struct mem_info *m = data; |
161 | m68k_memory[m68k_num_memory].size = data[1]; | 167 | m68k_memory[m68k_num_memory].addr = |
168 | be32_to_cpu(m->addr); | ||
169 | m68k_memory[m68k_num_memory].size = | ||
170 | be32_to_cpu(m->size); | ||
162 | m68k_num_memory++; | 171 | m68k_num_memory++; |
163 | } else | 172 | } else |
164 | printk("m68k_parse_bootinfo: too many memory chunks\n"); | 173 | pr_warn("%s: too many memory chunks\n", |
174 | __func__); | ||
165 | break; | 175 | break; |
166 | 176 | ||
167 | case BI_RAMDISK: | 177 | case BI_RAMDISK: |
168 | m68k_ramdisk.addr = data[0]; | 178 | { |
169 | m68k_ramdisk.size = data[1]; | 179 | const struct mem_info *m = data; |
180 | m68k_ramdisk.addr = be32_to_cpu(m->addr); | ||
181 | m68k_ramdisk.size = be32_to_cpu(m->size); | ||
182 | } | ||
170 | break; | 183 | break; |
171 | 184 | ||
172 | case BI_COMMAND_LINE: | 185 | case BI_COMMAND_LINE: |
173 | strlcpy(m68k_command_line, (const char *)data, | 186 | strlcpy(m68k_command_line, data, |
174 | sizeof(m68k_command_line)); | 187 | sizeof(m68k_command_line)); |
175 | break; | 188 | break; |
176 | 189 | ||
@@ -197,17 +210,16 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record) | |||
197 | unknown = 1; | 210 | unknown = 1; |
198 | } | 211 | } |
199 | if (unknown) | 212 | if (unknown) |
200 | printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n", | 213 | pr_warn("%s: unknown tag 0x%04x ignored\n", __func__, |
201 | record->tag); | 214 | tag); |
202 | record = (struct bi_record *)((unsigned long)record + | 215 | record = (struct bi_record *)((unsigned long)record + size); |
203 | record->size); | ||
204 | } | 216 | } |
205 | 217 | ||
206 | m68k_realnum_memory = m68k_num_memory; | 218 | m68k_realnum_memory = m68k_num_memory; |
207 | #ifdef CONFIG_SINGLE_MEMORY_CHUNK | 219 | #ifdef CONFIG_SINGLE_MEMORY_CHUNK |
208 | if (m68k_num_memory > 1) { | 220 | if (m68k_num_memory > 1) { |
209 | printk("Ignoring last %i chunks of physical memory\n", | 221 | pr_warn("%s: ignoring last %i chunks of physical memory\n", |
210 | (m68k_num_memory - 1)); | 222 | __func__, (m68k_num_memory - 1)); |
211 | m68k_num_memory = 1; | 223 | m68k_num_memory = 1; |
212 | } | 224 | } |
213 | #endif | 225 | #endif |
@@ -219,7 +231,7 @@ void __init setup_arch(char **cmdline_p) | |||
219 | int i; | 231 | int i; |
220 | #endif | 232 | #endif |
221 | 233 | ||
222 | /* The bootinfo is located right after the kernel bss */ | 234 | /* The bootinfo is located right after the kernel */ |
223 | if (!CPU_IS_COLDFIRE) | 235 | if (!CPU_IS_COLDFIRE) |
224 | m68k_parse_bootinfo((const struct bi_record *)_end); | 236 | m68k_parse_bootinfo((const struct bi_record *)_end); |
225 | 237 | ||
@@ -247,7 +259,7 @@ void __init setup_arch(char **cmdline_p) | |||
247 | asm (".chip 68060; movec %%pcr,%0; .chip 68k" | 259 | asm (".chip 68060; movec %%pcr,%0; .chip 68k" |
248 | : "=d" (pcr)); | 260 | : "=d" (pcr)); |
249 | if (((pcr >> 8) & 0xff) <= 5) { | 261 | if (((pcr >> 8) & 0xff) <= 5) { |
250 | printk("Enabling workaround for errata I14\n"); | 262 | pr_warn("Enabling workaround for errata I14\n"); |
251 | asm (".chip 68060; movec %0,%%pcr; .chip 68k" | 263 | asm (".chip 68060; movec %0,%%pcr; .chip 68k" |
252 | : : "d" (pcr | 0x20)); | 264 | : : "d" (pcr | 0x20)); |
253 | } | 265 | } |
@@ -336,12 +348,12 @@ void __init setup_arch(char **cmdline_p) | |||
336 | panic("No configuration setup"); | 348 | panic("No configuration setup"); |
337 | } | 349 | } |
338 | 350 | ||
351 | paging_init(); | ||
352 | |||
339 | #ifdef CONFIG_NATFEAT | 353 | #ifdef CONFIG_NATFEAT |
340 | nf_init(); | 354 | nf_init(); |
341 | #endif | 355 | #endif |
342 | 356 | ||
343 | paging_init(); | ||
344 | |||
345 | #ifndef CONFIG_SUN3 | 357 | #ifndef CONFIG_SUN3 |
346 | for (i = 1; i < m68k_num_memory; i++) | 358 | for (i = 1; i < m68k_num_memory; i++) |
347 | free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr, | 359 | free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr, |
@@ -353,7 +365,7 @@ void __init setup_arch(char **cmdline_p) | |||
353 | BOOTMEM_DEFAULT); | 365 | BOOTMEM_DEFAULT); |
354 | initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); | 366 | initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); |
355 | initrd_end = initrd_start + m68k_ramdisk.size; | 367 | initrd_end = initrd_start + m68k_ramdisk.size; |
356 | printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end); | 368 | pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end); |
357 | } | 369 | } |
358 | #endif | 370 | #endif |
359 | 371 | ||
@@ -538,9 +550,9 @@ void check_bugs(void) | |||
538 | { | 550 | { |
539 | #ifndef CONFIG_M68KFPU_EMU | 551 | #ifndef CONFIG_M68KFPU_EMU |
540 | if (m68k_fputype == 0) { | 552 | if (m68k_fputype == 0) { |
541 | printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, " | 553 | pr_emerg("*** YOU DO NOT HAVE A FLOATING POINT UNIT, " |
542 | "WHICH IS REQUIRED BY LINUX/M68K ***\n"); | 554 | "WHICH IS REQUIRED BY LINUX/M68K ***\n"); |
543 | printk(KERN_EMERG "Upgrade your hardware or join the FPU " | 555 | pr_emerg("Upgrade your hardware or join the FPU " |
544 | "emulation project\n"); | 556 | "emulation project\n"); |
545 | panic("no FPU"); | 557 | panic("no FPU"); |
546 | } | 558 | } |
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index 7eb9792009f8..958f1adb9d0c 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c | |||
@@ -28,6 +28,10 @@ | |||
28 | #include <linux/timex.h> | 28 | #include <linux/timex.h> |
29 | #include <linux/profile.h> | 29 | #include <linux/profile.h> |
30 | 30 | ||
31 | |||
32 | unsigned long (*mach_random_get_entropy)(void); | ||
33 | |||
34 | |||
31 | /* | 35 | /* |
32 | * timer_interrupt() needs to keep up the real-time clock, | 36 | * timer_interrupt() needs to keep up the real-time clock, |
33 | * as well as call the "xtime_update()" routine every clocktick | 37 | * as well as call the "xtime_update()" routine every clocktick |
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index 88fcd8c70e7b..6c9ca24830e9 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c | |||
@@ -133,9 +133,7 @@ static inline void access_error060 (struct frame *fp) | |||
133 | { | 133 | { |
134 | unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */ | 134 | unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */ |
135 | 135 | ||
136 | #ifdef DEBUG | 136 | pr_debug("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr); |
137 | printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr); | ||
138 | #endif | ||
139 | 137 | ||
140 | if (fslw & MMU060_BPE) { | 138 | if (fslw & MMU060_BPE) { |
141 | /* branch prediction error -> clear branch cache */ | 139 | /* branch prediction error -> clear branch cache */ |
@@ -162,9 +160,7 @@ static inline void access_error060 (struct frame *fp) | |||
162 | } | 160 | } |
163 | if (fslw & MMU060_W) | 161 | if (fslw & MMU060_W) |
164 | errorcode |= 2; | 162 | errorcode |= 2; |
165 | #ifdef DEBUG | 163 | pr_debug("errorcode = %ld\n", errorcode); |
166 | printk("errorcode = %d\n", errorcode ); | ||
167 | #endif | ||
168 | do_page_fault(&fp->ptregs, addr, errorcode); | 164 | do_page_fault(&fp->ptregs, addr, errorcode); |
169 | } else if (fslw & (MMU060_SEE)){ | 165 | } else if (fslw & (MMU060_SEE)){ |
170 | /* Software Emulation Error. | 166 | /* Software Emulation Error. |
@@ -173,8 +169,9 @@ static inline void access_error060 (struct frame *fp) | |||
173 | send_fault_sig(&fp->ptregs); | 169 | send_fault_sig(&fp->ptregs); |
174 | } else if (!(fslw & (MMU060_RE|MMU060_WE)) || | 170 | } else if (!(fslw & (MMU060_RE|MMU060_WE)) || |
175 | send_fault_sig(&fp->ptregs) > 0) { | 171 | send_fault_sig(&fp->ptregs) > 0) { |
176 | printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); | 172 | pr_err("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, |
177 | printk( "68060 access error, fslw=%lx\n", fslw ); | 173 | fp->un.fmt4.effaddr); |
174 | pr_err("68060 access error, fslw=%lx\n", fslw); | ||
178 | trap_c( fp ); | 175 | trap_c( fp ); |
179 | } | 176 | } |
180 | } | 177 | } |
@@ -225,9 +222,7 @@ static inline int do_040writeback1(unsigned short wbs, unsigned long wba, | |||
225 | set_fs(old_fs); | 222 | set_fs(old_fs); |
226 | 223 | ||
227 | 224 | ||
228 | #ifdef DEBUG | 225 | pr_debug("do_040writeback1, res=%d\n", res); |
229 | printk("do_040writeback1, res=%d\n",res); | ||
230 | #endif | ||
231 | 226 | ||
232 | return res; | 227 | return res; |
233 | } | 228 | } |
@@ -249,7 +244,7 @@ static inline void do_040writebacks(struct frame *fp) | |||
249 | int res = 0; | 244 | int res = 0; |
250 | #if 0 | 245 | #if 0 |
251 | if (fp->un.fmt7.wb1s & WBV_040) | 246 | if (fp->un.fmt7.wb1s & WBV_040) |
252 | printk("access_error040: cannot handle 1st writeback. oops.\n"); | 247 | pr_err("access_error040: cannot handle 1st writeback. oops.\n"); |
253 | #endif | 248 | #endif |
254 | 249 | ||
255 | if ((fp->un.fmt7.wb2s & WBV_040) && | 250 | if ((fp->un.fmt7.wb2s & WBV_040) && |
@@ -302,14 +297,12 @@ static inline void access_error040(struct frame *fp) | |||
302 | unsigned short ssw = fp->un.fmt7.ssw; | 297 | unsigned short ssw = fp->un.fmt7.ssw; |
303 | unsigned long mmusr; | 298 | unsigned long mmusr; |
304 | 299 | ||
305 | #ifdef DEBUG | 300 | pr_debug("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); |
306 | printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); | 301 | pr_debug("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s, |
307 | printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s, | ||
308 | fp->un.fmt7.wb2s, fp->un.fmt7.wb3s); | 302 | fp->un.fmt7.wb2s, fp->un.fmt7.wb3s); |
309 | printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", | 303 | pr_debug("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", |
310 | fp->un.fmt7.wb2a, fp->un.fmt7.wb3a, | 304 | fp->un.fmt7.wb2a, fp->un.fmt7.wb3a, |
311 | fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); | 305 | fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); |
312 | #endif | ||
313 | 306 | ||
314 | if (ssw & ATC_040) { | 307 | if (ssw & ATC_040) { |
315 | unsigned long addr = fp->un.fmt7.faddr; | 308 | unsigned long addr = fp->un.fmt7.faddr; |
@@ -324,9 +317,7 @@ static inline void access_error040(struct frame *fp) | |||
324 | 317 | ||
325 | /* MMU error, get the MMUSR info for this access */ | 318 | /* MMU error, get the MMUSR info for this access */ |
326 | mmusr = probe040(!(ssw & RW_040), addr, ssw); | 319 | mmusr = probe040(!(ssw & RW_040), addr, ssw); |
327 | #ifdef DEBUG | 320 | pr_debug("mmusr = %lx\n", mmusr); |
328 | printk("mmusr = %lx\n", mmusr); | ||
329 | #endif | ||
330 | errorcode = 1; | 321 | errorcode = 1; |
331 | if (!(mmusr & MMU_R_040)) { | 322 | if (!(mmusr & MMU_R_040)) { |
332 | /* clear the invalid atc entry */ | 323 | /* clear the invalid atc entry */ |
@@ -340,14 +331,10 @@ static inline void access_error040(struct frame *fp) | |||
340 | errorcode |= 2; | 331 | errorcode |= 2; |
341 | 332 | ||
342 | if (do_page_fault(&fp->ptregs, addr, errorcode)) { | 333 | if (do_page_fault(&fp->ptregs, addr, errorcode)) { |
343 | #ifdef DEBUG | 334 | pr_debug("do_page_fault() !=0\n"); |
344 | printk("do_page_fault() !=0\n"); | ||
345 | #endif | ||
346 | if (user_mode(&fp->ptregs)){ | 335 | if (user_mode(&fp->ptregs)){ |
347 | /* delay writebacks after signal delivery */ | 336 | /* delay writebacks after signal delivery */ |
348 | #ifdef DEBUG | 337 | pr_debug(".. was usermode - return\n"); |
349 | printk(".. was usermode - return\n"); | ||
350 | #endif | ||
351 | return; | 338 | return; |
352 | } | 339 | } |
353 | /* disable writeback into user space from kernel | 340 | /* disable writeback into user space from kernel |
@@ -355,9 +342,7 @@ static inline void access_error040(struct frame *fp) | |||
355 | * the writeback won't do good) | 342 | * the writeback won't do good) |
356 | */ | 343 | */ |
357 | disable_wb: | 344 | disable_wb: |
358 | #ifdef DEBUG | 345 | pr_debug(".. disabling wb2\n"); |
359 | printk(".. disabling wb2\n"); | ||
360 | #endif | ||
361 | if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) | 346 | if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) |
362 | fp->un.fmt7.wb2s &= ~WBV_040; | 347 | fp->un.fmt7.wb2s &= ~WBV_040; |
363 | if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr) | 348 | if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr) |
@@ -371,7 +356,7 @@ disable_wb: | |||
371 | current->thread.signo = SIGBUS; | 356 | current->thread.signo = SIGBUS; |
372 | current->thread.faddr = fp->un.fmt7.faddr; | 357 | current->thread.faddr = fp->un.fmt7.faddr; |
373 | if (send_fault_sig(&fp->ptregs) >= 0) | 358 | if (send_fault_sig(&fp->ptregs) >= 0) |
374 | printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw, | 359 | pr_err("68040 bus error (ssw=%x, faddr=%lx)\n", ssw, |
375 | fp->un.fmt7.faddr); | 360 | fp->un.fmt7.faddr); |
376 | goto disable_wb; | 361 | goto disable_wb; |
377 | } | 362 | } |
@@ -394,19 +379,17 @@ static inline void bus_error030 (struct frame *fp) | |||
394 | unsigned short ssw = fp->un.fmtb.ssw; | 379 | unsigned short ssw = fp->un.fmtb.ssw; |
395 | extern unsigned long _sun3_map_test_start, _sun3_map_test_end; | 380 | extern unsigned long _sun3_map_test_start, _sun3_map_test_end; |
396 | 381 | ||
397 | #ifdef DEBUG | ||
398 | if (ssw & (FC | FB)) | 382 | if (ssw & (FC | FB)) |
399 | printk ("Instruction fault at %#010lx\n", | 383 | pr_debug("Instruction fault at %#010lx\n", |
400 | ssw & FC ? | 384 | ssw & FC ? |
401 | fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 | 385 | fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 |
402 | : | 386 | : |
403 | fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); | 387 | fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); |
404 | if (ssw & DF) | 388 | if (ssw & DF) |
405 | printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", | 389 | pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n", |
406 | ssw & RW ? "read" : "write", | 390 | ssw & RW ? "read" : "write", |
407 | fp->un.fmtb.daddr, | 391 | fp->un.fmtb.daddr, |
408 | space_names[ssw & DFC], fp->ptregs.pc); | 392 | space_names[ssw & DFC], fp->ptregs.pc); |
409 | #endif | ||
410 | 393 | ||
411 | /* | 394 | /* |
412 | * Check if this page should be demand-mapped. This needs to go before | 395 | * Check if this page should be demand-mapped. This needs to go before |
@@ -429,7 +412,7 @@ static inline void bus_error030 (struct frame *fp) | |||
429 | return; | 412 | return; |
430 | /* instruction fault or kernel data fault! */ | 413 | /* instruction fault or kernel data fault! */ |
431 | if (ssw & (FC | FB)) | 414 | if (ssw & (FC | FB)) |
432 | printk ("Instruction fault at %#010lx\n", | 415 | pr_err("Instruction fault at %#010lx\n", |
433 | fp->ptregs.pc); | 416 | fp->ptregs.pc); |
434 | if (ssw & DF) { | 417 | if (ssw & DF) { |
435 | /* was this fault incurred testing bus mappings? */ | 418 | /* was this fault incurred testing bus mappings? */ |
@@ -439,12 +422,12 @@ static inline void bus_error030 (struct frame *fp) | |||
439 | return; | 422 | return; |
440 | } | 423 | } |
441 | 424 | ||
442 | printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", | 425 | pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", |
443 | ssw & RW ? "read" : "write", | 426 | ssw & RW ? "read" : "write", |
444 | fp->un.fmtb.daddr, | 427 | fp->un.fmtb.daddr, |
445 | space_names[ssw & DFC], fp->ptregs.pc); | 428 | space_names[ssw & DFC], fp->ptregs.pc); |
446 | } | 429 | } |
447 | printk ("BAD KERNEL BUSERR\n"); | 430 | pr_err("BAD KERNEL BUSERR\n"); |
448 | 431 | ||
449 | die_if_kernel("Oops", &fp->ptregs,0); | 432 | die_if_kernel("Oops", &fp->ptregs,0); |
450 | force_sig(SIGKILL, current); | 433 | force_sig(SIGKILL, current); |
@@ -473,12 +456,11 @@ static inline void bus_error030 (struct frame *fp) | |||
473 | else if (buserr_type & SUN3_BUSERR_INVALID) | 456 | else if (buserr_type & SUN3_BUSERR_INVALID) |
474 | errorcode = 0x00; | 457 | errorcode = 0x00; |
475 | else { | 458 | else { |
476 | #ifdef DEBUG | 459 | pr_debug("*** unexpected busfault type=%#04x\n", |
477 | printk ("*** unexpected busfault type=%#04x\n", buserr_type); | 460 | buserr_type); |
478 | printk ("invalid %s access at %#lx from pc %#lx\n", | 461 | pr_debug("invalid %s access at %#lx from pc %#lx\n", |
479 | !(ssw & RW) ? "write" : "read", addr, | 462 | !(ssw & RW) ? "write" : "read", addr, |
480 | fp->ptregs.pc); | 463 | fp->ptregs.pc); |
481 | #endif | ||
482 | die_if_kernel ("Oops", &fp->ptregs, buserr_type); | 464 | die_if_kernel ("Oops", &fp->ptregs, buserr_type); |
483 | force_sig (SIGBUS, current); | 465 | force_sig (SIGBUS, current); |
484 | return; | 466 | return; |
@@ -509,9 +491,7 @@ static inline void bus_error030 (struct frame *fp) | |||
509 | if (!mmu_emu_handle_fault(addr, 1, 0)) | 491 | if (!mmu_emu_handle_fault(addr, 1, 0)) |
510 | do_page_fault (&fp->ptregs, addr, 0); | 492 | do_page_fault (&fp->ptregs, addr, 0); |
511 | } else { | 493 | } else { |
512 | #ifdef DEBUG | 494 | pr_debug("protection fault on insn access (segv).\n"); |
513 | printk ("protection fault on insn access (segv).\n"); | ||
514 | #endif | ||
515 | force_sig (SIGSEGV, current); | 495 | force_sig (SIGSEGV, current); |
516 | } | 496 | } |
517 | } | 497 | } |
@@ -525,22 +505,22 @@ static inline void bus_error030 (struct frame *fp) | |||
525 | unsigned short ssw = fp->un.fmtb.ssw; | 505 | unsigned short ssw = fp->un.fmtb.ssw; |
526 | #ifdef DEBUG | 506 | #ifdef DEBUG |
527 | unsigned long desc; | 507 | unsigned long desc; |
508 | #endif | ||
528 | 509 | ||
529 | printk ("pid = %x ", current->pid); | 510 | pr_debug("pid = %x ", current->pid); |
530 | printk ("SSW=%#06x ", ssw); | 511 | pr_debug("SSW=%#06x ", ssw); |
531 | 512 | ||
532 | if (ssw & (FC | FB)) | 513 | if (ssw & (FC | FB)) |
533 | printk ("Instruction fault at %#010lx\n", | 514 | pr_debug("Instruction fault at %#010lx\n", |
534 | ssw & FC ? | 515 | ssw & FC ? |
535 | fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 | 516 | fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 |
536 | : | 517 | : |
537 | fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); | 518 | fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); |
538 | if (ssw & DF) | 519 | if (ssw & DF) |
539 | printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", | 520 | pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n", |
540 | ssw & RW ? "read" : "write", | 521 | ssw & RW ? "read" : "write", |
541 | fp->un.fmtb.daddr, | 522 | fp->un.fmtb.daddr, |
542 | space_names[ssw & DFC], fp->ptregs.pc); | 523 | space_names[ssw & DFC], fp->ptregs.pc); |
543 | #endif | ||
544 | 524 | ||
545 | /* ++andreas: If a data fault and an instruction fault happen | 525 | /* ++andreas: If a data fault and an instruction fault happen |
546 | at the same time map in both pages. */ | 526 | at the same time map in both pages. */ |
@@ -554,27 +534,23 @@ static inline void bus_error030 (struct frame *fp) | |||
554 | "pmove %%psr,%1" | 534 | "pmove %%psr,%1" |
555 | : "=a&" (desc), "=m" (temp) | 535 | : "=a&" (desc), "=m" (temp) |
556 | : "a" (addr), "d" (ssw)); | 536 | : "a" (addr), "d" (ssw)); |
537 | pr_debug("mmusr is %#x for addr %#lx in task %p\n", | ||
538 | temp, addr, current); | ||
539 | pr_debug("descriptor address is 0x%p, contents %#lx\n", | ||
540 | __va(desc), *(unsigned long *)__va(desc)); | ||
557 | #else | 541 | #else |
558 | asm volatile ("ptestr %2,%1@,#7\n\t" | 542 | asm volatile ("ptestr %2,%1@,#7\n\t" |
559 | "pmove %%psr,%0" | 543 | "pmove %%psr,%0" |
560 | : "=m" (temp) : "a" (addr), "d" (ssw)); | 544 | : "=m" (temp) : "a" (addr), "d" (ssw)); |
561 | #endif | 545 | #endif |
562 | mmusr = temp; | 546 | mmusr = temp; |
563 | |||
564 | #ifdef DEBUG | ||
565 | printk("mmusr is %#x for addr %#lx in task %p\n", | ||
566 | mmusr, addr, current); | ||
567 | printk("descriptor address is %#lx, contents %#lx\n", | ||
568 | __va(desc), *(unsigned long *)__va(desc)); | ||
569 | #endif | ||
570 | |||
571 | errorcode = (mmusr & MMU_I) ? 0 : 1; | 547 | errorcode = (mmusr & MMU_I) ? 0 : 1; |
572 | if (!(ssw & RW) || (ssw & RM)) | 548 | if (!(ssw & RW) || (ssw & RM)) |
573 | errorcode |= 2; | 549 | errorcode |= 2; |
574 | 550 | ||
575 | if (mmusr & (MMU_I | MMU_WP)) { | 551 | if (mmusr & (MMU_I | MMU_WP)) { |
576 | if (ssw & 4) { | 552 | if (ssw & 4) { |
577 | printk("Data %s fault at %#010lx in %s (pc=%#lx)\n", | 553 | pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", |
578 | ssw & RW ? "read" : "write", | 554 | ssw & RW ? "read" : "write", |
579 | fp->un.fmtb.daddr, | 555 | fp->un.fmtb.daddr, |
580 | space_names[ssw & DFC], fp->ptregs.pc); | 556 | space_names[ssw & DFC], fp->ptregs.pc); |
@@ -587,9 +563,10 @@ static inline void bus_error030 (struct frame *fp) | |||
587 | } else if (!(mmusr & MMU_I)) { | 563 | } else if (!(mmusr & MMU_I)) { |
588 | /* probably a 020 cas fault */ | 564 | /* probably a 020 cas fault */ |
589 | if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) | 565 | if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) |
590 | printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); | 566 | pr_err("unexpected bus error (%#x,%#x)\n", ssw, |
567 | mmusr); | ||
591 | } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { | 568 | } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { |
592 | printk("invalid %s access at %#lx from pc %#lx\n", | 569 | pr_err("invalid %s access at %#lx from pc %#lx\n", |
593 | !(ssw & RW) ? "write" : "read", addr, | 570 | !(ssw & RW) ? "write" : "read", addr, |
594 | fp->ptregs.pc); | 571 | fp->ptregs.pc); |
595 | die_if_kernel("Oops",&fp->ptregs,mmusr); | 572 | die_if_kernel("Oops",&fp->ptregs,mmusr); |
@@ -600,7 +577,7 @@ static inline void bus_error030 (struct frame *fp) | |||
600 | static volatile long tlong; | 577 | static volatile long tlong; |
601 | #endif | 578 | #endif |
602 | 579 | ||
603 | printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", | 580 | pr_err("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", |
604 | !(ssw & RW) ? "write" : "read", addr, | 581 | !(ssw & RW) ? "write" : "read", addr, |
605 | fp->ptregs.pc, ssw); | 582 | fp->ptregs.pc, ssw); |
606 | asm volatile ("ptestr #1,%1@,#0\n\t" | 583 | asm volatile ("ptestr #1,%1@,#0\n\t" |
@@ -609,18 +586,16 @@ static inline void bus_error030 (struct frame *fp) | |||
609 | : "a" (addr)); | 586 | : "a" (addr)); |
610 | mmusr = temp; | 587 | mmusr = temp; |
611 | 588 | ||
612 | printk ("level 0 mmusr is %#x\n", mmusr); | 589 | pr_err("level 0 mmusr is %#x\n", mmusr); |
613 | #if 0 | 590 | #if 0 |
614 | asm volatile ("pmove %%tt0,%0" | 591 | asm volatile ("pmove %%tt0,%0" |
615 | : "=m" (tlong)); | 592 | : "=m" (tlong)); |
616 | printk("tt0 is %#lx, ", tlong); | 593 | pr_debug("tt0 is %#lx, ", tlong); |
617 | asm volatile ("pmove %%tt1,%0" | 594 | asm volatile ("pmove %%tt1,%0" |
618 | : "=m" (tlong)); | 595 | : "=m" (tlong)); |
619 | printk("tt1 is %#lx\n", tlong); | 596 | pr_debug("tt1 is %#lx\n", tlong); |
620 | #endif | ||
621 | #ifdef DEBUG | ||
622 | printk("Unknown SIGSEGV - 1\n"); | ||
623 | #endif | 597 | #endif |
598 | pr_debug("Unknown SIGSEGV - 1\n"); | ||
624 | die_if_kernel("Oops",&fp->ptregs,mmusr); | 599 | die_if_kernel("Oops",&fp->ptregs,mmusr); |
625 | force_sig(SIGSEGV, current); | 600 | force_sig(SIGSEGV, current); |
626 | return; | 601 | return; |
@@ -641,10 +616,9 @@ static inline void bus_error030 (struct frame *fp) | |||
641 | return; | 616 | return; |
642 | 617 | ||
643 | if (fp->ptregs.sr & PS_S) { | 618 | if (fp->ptregs.sr & PS_S) { |
644 | printk("Instruction fault at %#010lx\n", | 619 | pr_err("Instruction fault at %#010lx\n", fp->ptregs.pc); |
645 | fp->ptregs.pc); | ||
646 | buserr: | 620 | buserr: |
647 | printk ("BAD KERNEL BUSERR\n"); | 621 | pr_err("BAD KERNEL BUSERR\n"); |
648 | die_if_kernel("Oops",&fp->ptregs,0); | 622 | die_if_kernel("Oops",&fp->ptregs,0); |
649 | force_sig(SIGKILL, current); | 623 | force_sig(SIGKILL, current); |
650 | return; | 624 | return; |
@@ -668,28 +642,22 @@ static inline void bus_error030 (struct frame *fp) | |||
668 | "pmove %%psr,%1" | 642 | "pmove %%psr,%1" |
669 | : "=a&" (desc), "=m" (temp) | 643 | : "=a&" (desc), "=m" (temp) |
670 | : "a" (addr)); | 644 | : "a" (addr)); |
645 | pr_debug("mmusr is %#x for addr %#lx in task %p\n", | ||
646 | temp, addr, current); | ||
647 | pr_debug("descriptor address is 0x%p, contents %#lx\n", | ||
648 | __va(desc), *(unsigned long *)__va(desc)); | ||
671 | #else | 649 | #else |
672 | asm volatile ("ptestr #1,%1@,#7\n\t" | 650 | asm volatile ("ptestr #1,%1@,#7\n\t" |
673 | "pmove %%psr,%0" | 651 | "pmove %%psr,%0" |
674 | : "=m" (temp) : "a" (addr)); | 652 | : "=m" (temp) : "a" (addr)); |
675 | #endif | 653 | #endif |
676 | mmusr = temp; | 654 | mmusr = temp; |
677 | |||
678 | #ifdef DEBUG | ||
679 | printk ("mmusr is %#x for addr %#lx in task %p\n", | ||
680 | mmusr, addr, current); | ||
681 | printk ("descriptor address is %#lx, contents %#lx\n", | ||
682 | __va(desc), *(unsigned long *)__va(desc)); | ||
683 | #endif | ||
684 | |||
685 | if (mmusr & MMU_I) | 655 | if (mmusr & MMU_I) |
686 | do_page_fault (&fp->ptregs, addr, 0); | 656 | do_page_fault (&fp->ptregs, addr, 0); |
687 | else if (mmusr & (MMU_B|MMU_L|MMU_S)) { | 657 | else if (mmusr & (MMU_B|MMU_L|MMU_S)) { |
688 | printk ("invalid insn access at %#lx from pc %#lx\n", | 658 | pr_err("invalid insn access at %#lx from pc %#lx\n", |
689 | addr, fp->ptregs.pc); | 659 | addr, fp->ptregs.pc); |
690 | #ifdef DEBUG | 660 | pr_debug("Unknown SIGSEGV - 2\n"); |
691 | printk("Unknown SIGSEGV - 2\n"); | ||
692 | #endif | ||
693 | die_if_kernel("Oops",&fp->ptregs,mmusr); | 661 | die_if_kernel("Oops",&fp->ptregs,mmusr); |
694 | force_sig(SIGSEGV, current); | 662 | force_sig(SIGSEGV, current); |
695 | return; | 663 | return; |
@@ -791,9 +759,7 @@ asmlinkage void buserr_c(struct frame *fp) | |||
791 | if (user_mode(&fp->ptregs)) | 759 | if (user_mode(&fp->ptregs)) |
792 | current->thread.esp0 = (unsigned long) fp; | 760 | current->thread.esp0 = (unsigned long) fp; |
793 | 761 | ||
794 | #ifdef DEBUG | 762 | pr_debug("*** Bus Error *** Format is %x\n", fp->ptregs.format); |
795 | printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); | ||
796 | #endif | ||
797 | 763 | ||
798 | #if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) | 764 | #if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) |
799 | if (CPU_IS_COLDFIRE) { | 765 | if (CPU_IS_COLDFIRE) { |
@@ -836,9 +802,7 @@ asmlinkage void buserr_c(struct frame *fp) | |||
836 | #endif | 802 | #endif |
837 | default: | 803 | default: |
838 | die_if_kernel("bad frame format",&fp->ptregs,0); | 804 | die_if_kernel("bad frame format",&fp->ptregs,0); |
839 | #ifdef DEBUG | 805 | pr_debug("Unknown SIGSEGV - 4\n"); |
840 | printk("Unknown SIGSEGV - 4\n"); | ||
841 | #endif | ||
842 | force_sig(SIGSEGV, current); | 806 | force_sig(SIGSEGV, current); |
843 | } | 807 | } |
844 | } | 808 | } |
@@ -852,7 +816,7 @@ void show_trace(unsigned long *stack) | |||
852 | unsigned long addr; | 816 | unsigned long addr; |
853 | int i; | 817 | int i; |
854 | 818 | ||
855 | printk("Call Trace:"); | 819 | pr_info("Call Trace:"); |
856 | addr = (unsigned long)stack + THREAD_SIZE - 1; | 820 | addr = (unsigned long)stack + THREAD_SIZE - 1; |
857 | endstack = (unsigned long *)(addr & -THREAD_SIZE); | 821 | endstack = (unsigned long *)(addr & -THREAD_SIZE); |
858 | i = 0; | 822 | i = 0; |
@@ -869,13 +833,13 @@ void show_trace(unsigned long *stack) | |||
869 | if (__kernel_text_address(addr)) { | 833 | if (__kernel_text_address(addr)) { |
870 | #ifndef CONFIG_KALLSYMS | 834 | #ifndef CONFIG_KALLSYMS |
871 | if (i % 5 == 0) | 835 | if (i % 5 == 0) |
872 | printk("\n "); | 836 | pr_cont("\n "); |
873 | #endif | 837 | #endif |
874 | printk(" [<%08lx>] %pS\n", addr, (void *)addr); | 838 | pr_cont(" [<%08lx>] %pS\n", addr, (void *)addr); |
875 | i++; | 839 | i++; |
876 | } | 840 | } |
877 | } | 841 | } |
878 | printk("\n"); | 842 | pr_cont("\n"); |
879 | } | 843 | } |
880 | 844 | ||
881 | void show_registers(struct pt_regs *regs) | 845 | void show_registers(struct pt_regs *regs) |
@@ -887,81 +851,87 @@ void show_registers(struct pt_regs *regs) | |||
887 | int i; | 851 | int i; |
888 | 852 | ||
889 | print_modules(); | 853 | print_modules(); |
890 | printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); | 854 | pr_info("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); |
891 | printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2); | 855 | pr_info("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2); |
892 | printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", | 856 | pr_info("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", |
893 | regs->d0, regs->d1, regs->d2, regs->d3); | 857 | regs->d0, regs->d1, regs->d2, regs->d3); |
894 | printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", | 858 | pr_info("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", |
895 | regs->d4, regs->d5, regs->a0, regs->a1); | 859 | regs->d4, regs->d5, regs->a0, regs->a1); |
896 | 860 | ||
897 | printk("Process %s (pid: %d, task=%p)\n", | 861 | pr_info("Process %s (pid: %d, task=%p)\n", |
898 | current->comm, task_pid_nr(current), current); | 862 | current->comm, task_pid_nr(current), current); |
899 | addr = (unsigned long)&fp->un; | 863 | addr = (unsigned long)&fp->un; |
900 | printk("Frame format=%X ", regs->format); | 864 | pr_info("Frame format=%X ", regs->format); |
901 | switch (regs->format) { | 865 | switch (regs->format) { |
902 | case 0x2: | 866 | case 0x2: |
903 | printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); | 867 | pr_cont("instr addr=%08lx\n", fp->un.fmt2.iaddr); |
904 | addr += sizeof(fp->un.fmt2); | 868 | addr += sizeof(fp->un.fmt2); |
905 | break; | 869 | break; |
906 | case 0x3: | 870 | case 0x3: |
907 | printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); | 871 | pr_cont("eff addr=%08lx\n", fp->un.fmt3.effaddr); |
908 | addr += sizeof(fp->un.fmt3); | 872 | addr += sizeof(fp->un.fmt3); |
909 | break; | 873 | break; |
910 | case 0x4: | 874 | case 0x4: |
911 | printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" | 875 | if (CPU_IS_060) |
912 | : "eff addr=%08lx pc=%08lx\n"), | 876 | pr_cont("fault addr=%08lx fslw=%08lx\n", |
913 | fp->un.fmt4.effaddr, fp->un.fmt4.pc); | 877 | fp->un.fmt4.effaddr, fp->un.fmt4.pc); |
878 | else | ||
879 | pr_cont("eff addr=%08lx pc=%08lx\n", | ||
880 | fp->un.fmt4.effaddr, fp->un.fmt4.pc); | ||
914 | addr += sizeof(fp->un.fmt4); | 881 | addr += sizeof(fp->un.fmt4); |
915 | break; | 882 | break; |
916 | case 0x7: | 883 | case 0x7: |
917 | printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", | 884 | pr_cont("eff addr=%08lx ssw=%04x faddr=%08lx\n", |
918 | fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); | 885 | fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); |
919 | printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", | 886 | pr_info("wb 1 stat/addr/data: %04x %08lx %08lx\n", |
920 | fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); | 887 | fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); |
921 | printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", | 888 | pr_info("wb 2 stat/addr/data: %04x %08lx %08lx\n", |
922 | fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); | 889 | fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); |
923 | printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", | 890 | pr_info("wb 3 stat/addr/data: %04x %08lx %08lx\n", |
924 | fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); | 891 | fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); |
925 | printk("push data: %08lx %08lx %08lx %08lx\n", | 892 | pr_info("push data: %08lx %08lx %08lx %08lx\n", |
926 | fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, | 893 | fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, |
927 | fp->un.fmt7.pd3); | 894 | fp->un.fmt7.pd3); |
928 | addr += sizeof(fp->un.fmt7); | 895 | addr += sizeof(fp->un.fmt7); |
929 | break; | 896 | break; |
930 | case 0x9: | 897 | case 0x9: |
931 | printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); | 898 | pr_cont("instr addr=%08lx\n", fp->un.fmt9.iaddr); |
932 | addr += sizeof(fp->un.fmt9); | 899 | addr += sizeof(fp->un.fmt9); |
933 | break; | 900 | break; |
934 | case 0xa: | 901 | case 0xa: |
935 | printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", | 902 | pr_cont("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", |
936 | fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, | 903 | fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, |
937 | fp->un.fmta.daddr, fp->un.fmta.dobuf); | 904 | fp->un.fmta.daddr, fp->un.fmta.dobuf); |
938 | addr += sizeof(fp->un.fmta); | 905 | addr += sizeof(fp->un.fmta); |
939 | break; | 906 | break; |
940 | case 0xb: | 907 | case 0xb: |
941 | printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", | 908 | pr_cont("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", |
942 | fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, | 909 | fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, |
943 | fp->un.fmtb.daddr, fp->un.fmtb.dobuf); | 910 | fp->un.fmtb.daddr, fp->un.fmtb.dobuf); |
944 | printk("baddr=%08lx dibuf=%08lx ver=%x\n", | 911 | pr_info("baddr=%08lx dibuf=%08lx ver=%x\n", |
945 | fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); | 912 | fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); |
946 | addr += sizeof(fp->un.fmtb); | 913 | addr += sizeof(fp->un.fmtb); |
947 | break; | 914 | break; |
948 | default: | 915 | default: |
949 | printk("\n"); | 916 | pr_cont("\n"); |
950 | } | 917 | } |
951 | show_stack(NULL, (unsigned long *)addr); | 918 | show_stack(NULL, (unsigned long *)addr); |
952 | 919 | ||
953 | printk("Code:"); | 920 | pr_info("Code:"); |
954 | set_fs(KERNEL_DS); | 921 | set_fs(KERNEL_DS); |
955 | cp = (u16 *)regs->pc; | 922 | cp = (u16 *)regs->pc; |
956 | for (i = -8; i < 16; i++) { | 923 | for (i = -8; i < 16; i++) { |
957 | if (get_user(c, cp + i) && i >= 0) { | 924 | if (get_user(c, cp + i) && i >= 0) { |
958 | printk(" Bad PC value."); | 925 | pr_cont(" Bad PC value."); |
959 | break; | 926 | break; |
960 | } | 927 | } |
961 | printk(i ? " %04x" : " <%04x>", c); | 928 | if (i) |
929 | pr_cont(" %04x", c); | ||
930 | else | ||
931 | pr_cont(" <%04x>", c); | ||
962 | } | 932 | } |
963 | set_fs(old_fs); | 933 | set_fs(old_fs); |
964 | printk ("\n"); | 934 | pr_cont("\n"); |
965 | } | 935 | } |
966 | 936 | ||
967 | void show_stack(struct task_struct *task, unsigned long *stack) | 937 | void show_stack(struct task_struct *task, unsigned long *stack) |
@@ -978,16 +948,16 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
978 | } | 948 | } |
979 | endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); | 949 | endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); |
980 | 950 | ||
981 | printk("Stack from %08lx:", (unsigned long)stack); | 951 | pr_info("Stack from %08lx:", (unsigned long)stack); |
982 | p = stack; | 952 | p = stack; |
983 | for (i = 0; i < kstack_depth_to_print; i++) { | 953 | for (i = 0; i < kstack_depth_to_print; i++) { |
984 | if (p + 1 > endstack) | 954 | if (p + 1 > endstack) |
985 | break; | 955 | break; |
986 | if (i % 8 == 0) | 956 | if (i % 8 == 0) |
987 | printk("\n "); | 957 | pr_cont("\n "); |
988 | printk(" %08lx", *p++); | 958 | pr_cont(" %08lx", *p++); |
989 | } | 959 | } |
990 | printk("\n"); | 960 | pr_cont("\n"); |
991 | show_trace(stack); | 961 | show_trace(stack); |
992 | } | 962 | } |
993 | 963 | ||
@@ -1005,32 +975,32 @@ void bad_super_trap (struct frame *fp) | |||
1005 | 975 | ||
1006 | console_verbose(); | 976 | console_verbose(); |
1007 | if (vector < ARRAY_SIZE(vec_names)) | 977 | if (vector < ARRAY_SIZE(vec_names)) |
1008 | printk ("*** %s *** FORMAT=%X\n", | 978 | pr_err("*** %s *** FORMAT=%X\n", |
1009 | vec_names[vector], | 979 | vec_names[vector], |
1010 | fp->ptregs.format); | 980 | fp->ptregs.format); |
1011 | else | 981 | else |
1012 | printk ("*** Exception %d *** FORMAT=%X\n", | 982 | pr_err("*** Exception %d *** FORMAT=%X\n", |
1013 | vector, fp->ptregs.format); | 983 | vector, fp->ptregs.format); |
1014 | if (vector == VEC_ADDRERR && CPU_IS_020_OR_030) { | 984 | if (vector == VEC_ADDRERR && CPU_IS_020_OR_030) { |
1015 | unsigned short ssw = fp->un.fmtb.ssw; | 985 | unsigned short ssw = fp->un.fmtb.ssw; |
1016 | 986 | ||
1017 | printk ("SSW=%#06x ", ssw); | 987 | pr_err("SSW=%#06x ", ssw); |
1018 | 988 | ||
1019 | if (ssw & RC) | 989 | if (ssw & RC) |
1020 | printk ("Pipe stage C instruction fault at %#010lx\n", | 990 | pr_err("Pipe stage C instruction fault at %#010lx\n", |
1021 | (fp->ptregs.format) == 0xA ? | 991 | (fp->ptregs.format) == 0xA ? |
1022 | fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2); | 992 | fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2); |
1023 | if (ssw & RB) | 993 | if (ssw & RB) |
1024 | printk ("Pipe stage B instruction fault at %#010lx\n", | 994 | pr_err("Pipe stage B instruction fault at %#010lx\n", |
1025 | (fp->ptregs.format) == 0xA ? | 995 | (fp->ptregs.format) == 0xA ? |
1026 | fp->ptregs.pc + 4 : fp->un.fmtb.baddr); | 996 | fp->ptregs.pc + 4 : fp->un.fmtb.baddr); |
1027 | if (ssw & DF) | 997 | if (ssw & DF) |
1028 | printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", | 998 | pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", |
1029 | ssw & RW ? "read" : "write", | 999 | ssw & RW ? "read" : "write", |
1030 | fp->un.fmtb.daddr, space_names[ssw & DFC], | 1000 | fp->un.fmtb.daddr, space_names[ssw & DFC], |
1031 | fp->ptregs.pc); | 1001 | fp->ptregs.pc); |
1032 | } | 1002 | } |
1033 | printk ("Current process id is %d\n", task_pid_nr(current)); | 1003 | pr_err("Current process id is %d\n", task_pid_nr(current)); |
1034 | die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); | 1004 | die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); |
1035 | } | 1005 | } |
1036 | 1006 | ||
@@ -1162,7 +1132,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr) | |||
1162 | return; | 1132 | return; |
1163 | 1133 | ||
1164 | console_verbose(); | 1134 | console_verbose(); |
1165 | printk("%s: %08x\n",str,nr); | 1135 | pr_crit("%s: %08x\n", str, nr); |
1166 | show_registers(fp); | 1136 | show_registers(fp); |
1167 | add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); | 1137 | add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); |
1168 | do_exit(SIGSEGV); | 1138 | do_exit(SIGSEGV); |
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index afb95d5fb26b..982c3fe73c4a 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c | |||
@@ -26,9 +26,10 @@ | |||
26 | #include <linux/adb.h> | 26 | #include <linux/adb.h> |
27 | #include <linux/cuda.h> | 27 | #include <linux/cuda.h> |
28 | 28 | ||
29 | #define BOOTINFO_COMPAT_1_0 | ||
30 | #include <asm/setup.h> | 29 | #include <asm/setup.h> |
31 | #include <asm/bootinfo.h> | 30 | #include <asm/bootinfo.h> |
31 | #include <asm/bootinfo-mac.h> | ||
32 | #include <asm/byteorder.h> | ||
32 | 33 | ||
33 | #include <asm/io.h> | 34 | #include <asm/io.h> |
34 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
@@ -107,45 +108,46 @@ static void __init mac_sched_init(irq_handler_t vector) | |||
107 | int __init mac_parse_bootinfo(const struct bi_record *record) | 108 | int __init mac_parse_bootinfo(const struct bi_record *record) |
108 | { | 109 | { |
109 | int unknown = 0; | 110 | int unknown = 0; |
110 | const u_long *data = record->data; | 111 | const void *data = record->data; |
111 | 112 | ||
112 | switch (record->tag) { | 113 | switch (be16_to_cpu(record->tag)) { |
113 | case BI_MAC_MODEL: | 114 | case BI_MAC_MODEL: |
114 | mac_bi_data.id = *data; | 115 | mac_bi_data.id = be32_to_cpup(data); |
115 | break; | 116 | break; |
116 | case BI_MAC_VADDR: | 117 | case BI_MAC_VADDR: |
117 | mac_bi_data.videoaddr = *data; | 118 | mac_bi_data.videoaddr = be32_to_cpup(data); |
118 | break; | 119 | break; |
119 | case BI_MAC_VDEPTH: | 120 | case BI_MAC_VDEPTH: |
120 | mac_bi_data.videodepth = *data; | 121 | mac_bi_data.videodepth = be32_to_cpup(data); |
121 | break; | 122 | break; |
122 | case BI_MAC_VROW: | 123 | case BI_MAC_VROW: |
123 | mac_bi_data.videorow = *data; | 124 | mac_bi_data.videorow = be32_to_cpup(data); |
124 | break; | 125 | break; |
125 | case BI_MAC_VDIM: | 126 | case BI_MAC_VDIM: |
126 | mac_bi_data.dimensions = *data; | 127 | mac_bi_data.dimensions = be32_to_cpup(data); |
127 | break; | 128 | break; |
128 | case BI_MAC_VLOGICAL: | 129 | case BI_MAC_VLOGICAL: |
129 | mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK); | 130 | mac_orig_videoaddr = be32_to_cpup(data); |
130 | mac_orig_videoaddr = *data; | 131 | mac_bi_data.videological = |
132 | VIDEOMEMBASE + (mac_orig_videoaddr & ~VIDEOMEMMASK); | ||
131 | break; | 133 | break; |
132 | case BI_MAC_SCCBASE: | 134 | case BI_MAC_SCCBASE: |
133 | mac_bi_data.sccbase = *data; | 135 | mac_bi_data.sccbase = be32_to_cpup(data); |
134 | break; | 136 | break; |
135 | case BI_MAC_BTIME: | 137 | case BI_MAC_BTIME: |
136 | mac_bi_data.boottime = *data; | 138 | mac_bi_data.boottime = be32_to_cpup(data); |
137 | break; | 139 | break; |
138 | case BI_MAC_GMTBIAS: | 140 | case BI_MAC_GMTBIAS: |
139 | mac_bi_data.gmtbias = *data; | 141 | mac_bi_data.gmtbias = be32_to_cpup(data); |
140 | break; | 142 | break; |
141 | case BI_MAC_MEMSIZE: | 143 | case BI_MAC_MEMSIZE: |
142 | mac_bi_data.memsize = *data; | 144 | mac_bi_data.memsize = be32_to_cpup(data); |
143 | break; | 145 | break; |
144 | case BI_MAC_CPUID: | 146 | case BI_MAC_CPUID: |
145 | mac_bi_data.cpuid = *data; | 147 | mac_bi_data.cpuid = be32_to_cpup(data); |
146 | break; | 148 | break; |
147 | case BI_MAC_ROMBASE: | 149 | case BI_MAC_ROMBASE: |
148 | mac_bi_data.rombase = *data; | 150 | mac_bi_data.rombase = be32_to_cpup(data); |
149 | break; | 151 | break; |
150 | default: | 152 | default: |
151 | unknown = 1; | 153 | unknown = 1; |
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 7d8d46127ad9..4d2adfb32a2a 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c | |||
@@ -111,16 +111,15 @@ | |||
111 | #include <linux/init.h> | 111 | #include <linux/init.h> |
112 | #include <linux/interrupt.h> | 112 | #include <linux/interrupt.h> |
113 | 113 | ||
114 | #include <asm/bootinfo.h> | ||
115 | #include <asm/macintosh.h> | 114 | #include <asm/macintosh.h> |
116 | #include <asm/macints.h> | 115 | #include <asm/macints.h> |
117 | #include <asm/mac_iop.h> | 116 | #include <asm/mac_iop.h> |
118 | 117 | ||
119 | /*#define DEBUG_IOP*/ | 118 | /*#define DEBUG_IOP*/ |
120 | 119 | ||
121 | /* Set to non-zero if the IOPs are present. Set by iop_init() */ | 120 | /* Non-zero if the IOPs are present */ |
122 | 121 | ||
123 | int iop_scc_present,iop_ism_present; | 122 | int iop_scc_present, iop_ism_present; |
124 | 123 | ||
125 | /* structure for tracking channel listeners */ | 124 | /* structure for tracking channel listeners */ |
126 | 125 | ||
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 5e085554ac7f..707b61aea203 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c | |||
@@ -25,8 +25,6 @@ | |||
25 | #include <asm/mac_via.h> | 25 | #include <asm/mac_via.h> |
26 | #include <asm/mac_oss.h> | 26 | #include <asm/mac_oss.h> |
27 | 27 | ||
28 | #define BOOTINFO_COMPAT_1_0 | ||
29 | #include <asm/bootinfo.h> | ||
30 | #include <asm/machdep.h> | 28 | #include <asm/machdep.h> |
31 | 29 | ||
32 | /* Offset between Unix time (1970-based) and Mac time (1904-based) */ | 30 | /* Offset between Unix time (1970-based) and Mac time (1904-based) */ |
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index 6c4c882c126e..54037125ebf8 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | 23 | ||
24 | #include <asm/bootinfo.h> | ||
25 | #include <asm/macintosh.h> | 24 | #include <asm/macintosh.h> |
26 | #include <asm/macints.h> | 25 | #include <asm/macints.h> |
27 | #include <asm/mac_via.h> | 26 | #include <asm/mac_via.h> |
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index 6f026fc302fa..835fa04511c8 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | 22 | ||
23 | #include <asm/traps.h> | 23 | #include <asm/traps.h> |
24 | #include <asm/bootinfo.h> | ||
25 | #include <asm/macintosh.h> | 24 | #include <asm/macintosh.h> |
26 | #include <asm/macints.h> | 25 | #include <asm/macints.h> |
27 | #include <asm/mac_psc.h> | 26 | #include <asm/mac_psc.h> |
@@ -54,7 +53,7 @@ static void psc_debug_dump(void) | |||
54 | * expanded to cover what I think are the other 7 channels. | 53 | * expanded to cover what I think are the other 7 channels. |
55 | */ | 54 | */ |
56 | 55 | ||
57 | static void psc_dma_die_die_die(void) | 56 | static __init void psc_dma_die_die_die(void) |
58 | { | 57 | { |
59 | int i; | 58 | int i; |
60 | 59 | ||
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 5d1458bb871b..e198dec868e4 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/irq.h> | 31 | #include <linux/irq.h> |
32 | 32 | ||
33 | #include <asm/bootinfo.h> | ||
34 | #include <asm/macintosh.h> | 33 | #include <asm/macintosh.h> |
35 | #include <asm/macints.h> | 34 | #include <asm/macints.h> |
36 | #include <asm/mac_via.h> | 35 | #include <asm/mac_via.h> |
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index eb1d61f68725..2bd7487440c4 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c | |||
@@ -25,9 +25,8 @@ int send_fault_sig(struct pt_regs *regs) | |||
25 | siginfo.si_signo = current->thread.signo; | 25 | siginfo.si_signo = current->thread.signo; |
26 | siginfo.si_code = current->thread.code; | 26 | siginfo.si_code = current->thread.code; |
27 | siginfo.si_addr = (void *)current->thread.faddr; | 27 | siginfo.si_addr = (void *)current->thread.faddr; |
28 | #ifdef DEBUG | 28 | pr_debug("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, |
29 | printk("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, siginfo.si_signo, siginfo.si_code); | 29 | siginfo.si_signo, siginfo.si_code); |
30 | #endif | ||
31 | 30 | ||
32 | if (user_mode(regs)) { | 31 | if (user_mode(regs)) { |
33 | force_sig_info(siginfo.si_signo, | 32 | force_sig_info(siginfo.si_signo, |
@@ -45,10 +44,10 @@ int send_fault_sig(struct pt_regs *regs) | |||
45 | * terminate things with extreme prejudice. | 44 | * terminate things with extreme prejudice. |
46 | */ | 45 | */ |
47 | if ((unsigned long)siginfo.si_addr < PAGE_SIZE) | 46 | if ((unsigned long)siginfo.si_addr < PAGE_SIZE) |
48 | printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); | 47 | pr_alert("Unable to handle kernel NULL pointer dereference"); |
49 | else | 48 | else |
50 | printk(KERN_ALERT "Unable to handle kernel access"); | 49 | pr_alert("Unable to handle kernel access"); |
51 | printk(" at virtual address %p\n", siginfo.si_addr); | 50 | pr_cont(" at virtual address %p\n", siginfo.si_addr); |
52 | die_if_kernel("Oops", regs, 0 /*error_code*/); | 51 | die_if_kernel("Oops", regs, 0 /*error_code*/); |
53 | do_exit(SIGKILL); | 52 | do_exit(SIGKILL); |
54 | } | 53 | } |
@@ -75,11 +74,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, | |||
75 | int fault; | 74 | int fault; |
76 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | 75 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; |
77 | 76 | ||
78 | #ifdef DEBUG | 77 | pr_debug("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", |
79 | printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", | 78 | regs->sr, regs->pc, address, error_code, mm ? mm->pgd : NULL); |
80 | regs->sr, regs->pc, address, error_code, | ||
81 | current->mm->pgd); | ||
82 | #endif | ||
83 | 79 | ||
84 | /* | 80 | /* |
85 | * If we're in an interrupt or have no user | 81 | * If we're in an interrupt or have no user |
@@ -118,9 +114,7 @@ retry: | |||
118 | * we can handle it.. | 114 | * we can handle it.. |
119 | */ | 115 | */ |
120 | good_area: | 116 | good_area: |
121 | #ifdef DEBUG | 117 | pr_debug("do_page_fault: good_area\n"); |
122 | printk("do_page_fault: good_area\n"); | ||
123 | #endif | ||
124 | switch (error_code & 3) { | 118 | switch (error_code & 3) { |
125 | default: /* 3: write, present */ | 119 | default: /* 3: write, present */ |
126 | /* fall through */ | 120 | /* fall through */ |
@@ -143,9 +137,7 @@ good_area: | |||
143 | */ | 137 | */ |
144 | 138 | ||
145 | fault = handle_mm_fault(mm, vma, address, flags); | 139 | fault = handle_mm_fault(mm, vma, address, flags); |
146 | #ifdef DEBUG | 140 | pr_debug("handle_mm_fault returns %d\n", fault); |
147 | printk("handle_mm_fault returns %d\n",fault); | ||
148 | #endif | ||
149 | 141 | ||
150 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | 142 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) |
151 | return 0; | 143 | return 0; |
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index 6b4baa6e4d31..acaff6a49e35 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c | |||
@@ -59,7 +59,7 @@ EXPORT_SYMBOL(pg_data_table); | |||
59 | void __init m68k_setup_node(int node) | 59 | void __init m68k_setup_node(int node) |
60 | { | 60 | { |
61 | #ifndef CONFIG_SINGLE_MEMORY_CHUNK | 61 | #ifndef CONFIG_SINGLE_MEMORY_CHUNK |
62 | struct mem_info *info = m68k_memory + node; | 62 | struct m68k_mem_info *info = m68k_memory + node; |
63 | int i, end; | 63 | int i, end; |
64 | 64 | ||
65 | i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift(); | 65 | i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift(); |
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index 568cfad3ceb8..6e4955bc542b 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c | |||
@@ -27,9 +27,9 @@ | |||
27 | 27 | ||
28 | /* | 28 | /* |
29 | * For 040/060 we can use the virtual memory area like other architectures, | 29 | * For 040/060 we can use the virtual memory area like other architectures, |
30 | * but for 020/030 we want to use early termination page descriptor and we | 30 | * but for 020/030 we want to use early termination page descriptors and we |
31 | * can't mix this with normal page descriptors, so we have to copy that code | 31 | * can't mix this with normal page descriptors, so we have to copy that code |
32 | * (mm/vmalloc.c) and return appriorate aligned addresses. | 32 | * (mm/vmalloc.c) and return appropriately aligned addresses. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #ifdef CPU_M68040_OR_M68060_ONLY | 35 | #ifdef CPU_M68040_OR_M68060_ONLY |
@@ -224,7 +224,7 @@ void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla | |||
224 | EXPORT_SYMBOL(__ioremap); | 224 | EXPORT_SYMBOL(__ioremap); |
225 | 225 | ||
226 | /* | 226 | /* |
227 | * Unmap a ioremap()ed region again | 227 | * Unmap an ioremap()ed region again |
228 | */ | 228 | */ |
229 | void iounmap(void __iomem *addr) | 229 | void iounmap(void __iomem *addr) |
230 | { | 230 | { |
@@ -241,8 +241,8 @@ EXPORT_SYMBOL(iounmap); | |||
241 | 241 | ||
242 | /* | 242 | /* |
243 | * __iounmap unmaps nearly everything, so be careful | 243 | * __iounmap unmaps nearly everything, so be careful |
244 | * it doesn't free currently pointer/page tables anymore but it | 244 | * Currently it doesn't free pointer/page tables anymore but this |
245 | * wans't used anyway and might be added later. | 245 | * wasn't used anyway and might be added later. |
246 | */ | 246 | */ |
247 | void __iounmap(void *addr, unsigned long size) | 247 | void __iounmap(void *addr, unsigned long size) |
248 | { | 248 | { |
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index 251c5437787b..7d4024432163 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c | |||
@@ -233,7 +233,7 @@ void __init paging_init(void) | |||
233 | printk("Fix your bootloader or use a memfile to make use of this area!\n"); | 233 | printk("Fix your bootloader or use a memfile to make use of this area!\n"); |
234 | m68k_num_memory--; | 234 | m68k_num_memory--; |
235 | memmove(m68k_memory + i, m68k_memory + i + 1, | 235 | memmove(m68k_memory + i, m68k_memory + i + 1, |
236 | (m68k_num_memory - i) * sizeof(struct mem_info)); | 236 | (m68k_num_memory - i) * sizeof(struct m68k_mem_info)); |
237 | continue; | 237 | continue; |
238 | } | 238 | } |
239 | addr = m68k_memory[i].addr + m68k_memory[i].size; | 239 | addr = m68k_memory[i].addr + m68k_memory[i].size; |
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index 1c6262803b94..1bb3ce6634d3 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | 27 | ||
28 | #include <asm/bootinfo.h> | 28 | #include <asm/bootinfo.h> |
29 | #include <asm/bootinfo-vme.h> | ||
30 | #include <asm/byteorder.h> | ||
29 | #include <asm/pgtable.h> | 31 | #include <asm/pgtable.h> |
30 | #include <asm/setup.h> | 32 | #include <asm/setup.h> |
31 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
@@ -51,9 +53,10 @@ static int bcd2int (unsigned char b); | |||
51 | irq_handler_t tick_handler; | 53 | irq_handler_t tick_handler; |
52 | 54 | ||
53 | 55 | ||
54 | int mvme147_parse_bootinfo(const struct bi_record *bi) | 56 | int __init mvme147_parse_bootinfo(const struct bi_record *bi) |
55 | { | 57 | { |
56 | if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO) | 58 | uint16_t tag = be16_to_cpu(bi->tag); |
59 | if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO) | ||
57 | return 0; | 60 | return 0; |
58 | else | 61 | else |
59 | return 1; | 62 | return 1; |
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 080a342458a1..eab7d342757e 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | 30 | ||
31 | #include <asm/bootinfo.h> | 31 | #include <asm/bootinfo.h> |
32 | #include <asm/bootinfo-vme.h> | ||
33 | #include <asm/byteorder.h> | ||
32 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
33 | #include <asm/setup.h> | 35 | #include <asm/setup.h> |
34 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
@@ -60,9 +62,10 @@ unsigned short mvme16x_config; | |||
60 | EXPORT_SYMBOL(mvme16x_config); | 62 | EXPORT_SYMBOL(mvme16x_config); |
61 | 63 | ||
62 | 64 | ||
63 | int mvme16x_parse_bootinfo(const struct bi_record *bi) | 65 | int __init mvme16x_parse_bootinfo(const struct bi_record *bi) |
64 | { | 66 | { |
65 | if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO) | 67 | uint16_t tag = be16_to_cpu(bi->tag); |
68 | if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO) | ||
66 | return 0; | 69 | return 0; |
67 | else | 70 | else |
68 | return 1; | 71 | return 1; |
@@ -87,15 +90,15 @@ static void mvme16x_get_model(char *model) | |||
87 | suf[3] = '\0'; | 90 | suf[3] = '\0'; |
88 | suf[0] = suf[1] ? '-' : '\0'; | 91 | suf[0] = suf[1] ? '-' : '\0'; |
89 | 92 | ||
90 | sprintf(model, "Motorola MVME%x%s", p->brdno, suf); | 93 | sprintf(model, "Motorola MVME%x%s", be16_to_cpu(p->brdno), suf); |
91 | } | 94 | } |
92 | 95 | ||
93 | 96 | ||
94 | static void mvme16x_get_hardware_list(struct seq_file *m) | 97 | static void mvme16x_get_hardware_list(struct seq_file *m) |
95 | { | 98 | { |
96 | p_bdid p = &mvme_bdid; | 99 | uint16_t brdno = be16_to_cpu(mvme_bdid.brdno); |
97 | 100 | ||
98 | if (p->brdno == 0x0162 || p->brdno == 0x0172) | 101 | if (brdno == 0x0162 || brdno == 0x0172) |
99 | { | 102 | { |
100 | unsigned char rev = *(unsigned char *)MVME162_VERSION_REG; | 103 | unsigned char rev = *(unsigned char *)MVME162_VERSION_REG; |
101 | 104 | ||
@@ -285,6 +288,7 @@ void __init config_mvme16x(void) | |||
285 | { | 288 | { |
286 | p_bdid p = &mvme_bdid; | 289 | p_bdid p = &mvme_bdid; |
287 | char id[40]; | 290 | char id[40]; |
291 | uint16_t brdno = be16_to_cpu(p->brdno); | ||
288 | 292 | ||
289 | mach_max_dma_address = 0xffffffff; | 293 | mach_max_dma_address = 0xffffffff; |
290 | mach_sched_init = mvme16x_sched_init; | 294 | mach_sched_init = mvme16x_sched_init; |
@@ -306,18 +310,18 @@ void __init config_mvme16x(void) | |||
306 | } | 310 | } |
307 | /* Board type is only set by newer versions of vmelilo/tftplilo */ | 311 | /* Board type is only set by newer versions of vmelilo/tftplilo */ |
308 | if (vme_brdtype == 0) | 312 | if (vme_brdtype == 0) |
309 | vme_brdtype = p->brdno; | 313 | vme_brdtype = brdno; |
310 | 314 | ||
311 | mvme16x_get_model(id); | 315 | mvme16x_get_model(id); |
312 | printk ("\nBRD_ID: %s BUG %x.%x %02x/%02x/%02x\n", id, p->rev>>4, | 316 | printk ("\nBRD_ID: %s BUG %x.%x %02x/%02x/%02x\n", id, p->rev>>4, |
313 | p->rev&0xf, p->yr, p->mth, p->day); | 317 | p->rev&0xf, p->yr, p->mth, p->day); |
314 | if (p->brdno == 0x0162 || p->brdno == 0x172) | 318 | if (brdno == 0x0162 || brdno == 0x172) |
315 | { | 319 | { |
316 | unsigned char rev = *(unsigned char *)MVME162_VERSION_REG; | 320 | unsigned char rev = *(unsigned char *)MVME162_VERSION_REG; |
317 | 321 | ||
318 | mvme16x_config = rev | MVME16x_CONFIG_GOT_SCCA; | 322 | mvme16x_config = rev | MVME16x_CONFIG_GOT_SCCA; |
319 | 323 | ||
320 | printk ("MVME%x Hardware status:\n", p->brdno); | 324 | printk ("MVME%x Hardware status:\n", brdno); |
321 | printk (" CPU Type 68%s040\n", | 325 | printk (" CPU Type 68%s040\n", |
322 | rev & MVME16x_CONFIG_GOT_FPU ? "" : "LC"); | 326 | rev & MVME16x_CONFIG_GOT_FPU ? "" : "LC"); |
323 | printk (" CPU clock %dMHz\n", | 327 | printk (" CPU clock %dMHz\n", |
@@ -347,12 +351,12 @@ void __init config_mvme16x(void) | |||
347 | 351 | ||
348 | static irqreturn_t mvme16x_abort_int (int irq, void *dev_id) | 352 | static irqreturn_t mvme16x_abort_int (int irq, void *dev_id) |
349 | { | 353 | { |
350 | p_bdid p = &mvme_bdid; | ||
351 | unsigned long *new = (unsigned long *)vectors; | 354 | unsigned long *new = (unsigned long *)vectors; |
352 | unsigned long *old = (unsigned long *)0xffe00000; | 355 | unsigned long *old = (unsigned long *)0xffe00000; |
353 | volatile unsigned char uc, *ucp; | 356 | volatile unsigned char uc, *ucp; |
357 | uint16_t brdno = be16_to_cpu(mvme_bdid.brdno); | ||
354 | 358 | ||
355 | if (p->brdno == 0x0162 || p->brdno == 0x172) | 359 | if (brdno == 0x0162 || brdno == 0x172) |
356 | { | 360 | { |
357 | ucp = (volatile unsigned char *)0xfff42043; | 361 | ucp = (volatile unsigned char *)0xfff42043; |
358 | uc = *ucp | 8; | 362 | uc = *ucp | 8; |
@@ -366,7 +370,7 @@ static irqreturn_t mvme16x_abort_int (int irq, void *dev_id) | |||
366 | *(new+9) = *(old+9); /* Trace */ | 370 | *(new+9) = *(old+9); /* Trace */ |
367 | *(new+47) = *(old+47); /* Trap #15 */ | 371 | *(new+47) = *(old+47); /* Trap #15 */ |
368 | 372 | ||
369 | if (p->brdno == 0x0162 || p->brdno == 0x172) | 373 | if (brdno == 0x0162 || brdno == 0x172) |
370 | *(new+0x5e) = *(old+0x5e); /* ABORT switch */ | 374 | *(new+0x5e) = *(old+0x5e); /* ABORT switch */ |
371 | else | 375 | else |
372 | *(new+0x6e) = *(old+0x6e); /* ABORT switch */ | 376 | *(new+0x6e) = *(old+0x6e); /* ABORT switch */ |
@@ -381,7 +385,7 @@ static irqreturn_t mvme16x_timer_int (int irq, void *dev_id) | |||
381 | 385 | ||
382 | void mvme16x_sched_init (irq_handler_t timer_routine) | 386 | void mvme16x_sched_init (irq_handler_t timer_routine) |
383 | { | 387 | { |
384 | p_bdid p = &mvme_bdid; | 388 | uint16_t brdno = be16_to_cpu(mvme_bdid.brdno); |
385 | int irq; | 389 | int irq; |
386 | 390 | ||
387 | tick_handler = timer_routine; | 391 | tick_handler = timer_routine; |
@@ -394,7 +398,7 @@ void mvme16x_sched_init (irq_handler_t timer_routine) | |||
394 | "timer", mvme16x_timer_int)) | 398 | "timer", mvme16x_timer_int)) |
395 | panic ("Couldn't register timer int"); | 399 | panic ("Couldn't register timer int"); |
396 | 400 | ||
397 | if (p->brdno == 0x0162 || p->brdno == 0x172) | 401 | if (brdno == 0x0162 || brdno == 0x172) |
398 | irq = MVME162_IRQ_ABORT; | 402 | irq = MVME162_IRQ_ABORT; |
399 | else | 403 | else |
400 | irq = MVME167_IRQ_ABORT; | 404 | irq = MVME167_IRQ_ABORT; |
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 078bb744b5fe..e90fe903613e 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c | |||
@@ -154,7 +154,7 @@ static unsigned int serports[] = | |||
154 | 0x3f8,0x2f8,0x3e8,0x2e8,0 | 154 | 0x3f8,0x2f8,0x3e8,0x2e8,0 |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static void q40_disable_irqs(void) | 157 | static void __init q40_disable_irqs(void) |
158 | { | 158 | { |
159 | unsigned i, j; | 159 | unsigned i, j; |
160 | 160 | ||
@@ -198,7 +198,7 @@ void __init config_q40(void) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | 200 | ||
201 | int q40_parse_bootinfo(const struct bi_record *rec) | 201 | int __init q40_parse_bootinfo(const struct bi_record *rec) |
202 | { | 202 | { |
203 | return 1; | 203 | return 1; |
204 | } | 204 | } |
diff --git a/arch/m68k/sun3/dvma.c b/arch/m68k/sun3/dvma.c index d522eaab4551..d95506e06c2a 100644 --- a/arch/m68k/sun3/dvma.c +++ b/arch/m68k/sun3/dvma.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/init.h> | ||
10 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
11 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
12 | #include <linux/bootmem.h> | 13 | #include <linux/bootmem.h> |
@@ -62,10 +63,7 @@ int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, | |||
62 | 63 | ||
63 | } | 64 | } |
64 | 65 | ||
65 | void sun3_dvma_init(void) | 66 | void __init sun3_dvma_init(void) |
66 | { | 67 | { |
67 | |||
68 | memset(ptelist, 0, sizeof(ptelist)); | 68 | memset(ptelist, 0, sizeof(ptelist)); |
69 | |||
70 | |||
71 | } | 69 | } |
diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c index 8edc510a21be..3f258e230ba5 100644 --- a/arch/m68k/sun3/mmu_emu.c +++ b/arch/m68k/sun3/mmu_emu.c | |||
@@ -6,6 +6,7 @@ | |||
6 | ** Started 1/16/98 @ 2:22 am | 6 | ** Started 1/16/98 @ 2:22 am |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/init.h> | ||
9 | #include <linux/mman.h> | 10 | #include <linux/mman.h> |
10 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
@@ -122,7 +123,7 @@ void print_pte_vaddr (unsigned long vaddr) | |||
122 | /* | 123 | /* |
123 | * Initialise the MMU emulator. | 124 | * Initialise the MMU emulator. |
124 | */ | 125 | */ |
125 | void mmu_emu_init(unsigned long bootmem_end) | 126 | void __init mmu_emu_init(unsigned long bootmem_end) |
126 | { | 127 | { |
127 | unsigned long seg, num; | 128 | unsigned long seg, num; |
128 | int i,j; | 129 | int i,j; |
diff --git a/arch/m68k/sun3/sun3dvma.c b/arch/m68k/sun3/sun3dvma.c index cab54482ca34..b37521a5259d 100644 --- a/arch/m68k/sun3/sun3dvma.c +++ b/arch/m68k/sun3/sun3dvma.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * Contains common routines for sun3/sun3x DVMA management. | 6 | * Contains common routines for sun3/sun3x DVMA management. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/bootmem.h> | ||
10 | #include <linux/init.h> | ||
9 | #include <linux/module.h> | 11 | #include <linux/module.h> |
10 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
11 | #include <linux/gfp.h> | 13 | #include <linux/gfp.h> |
@@ -30,7 +32,7 @@ static inline void dvma_unmap_iommu(unsigned long a, int b) | |||
30 | extern void sun3_dvma_init(void); | 32 | extern void sun3_dvma_init(void); |
31 | #endif | 33 | #endif |
32 | 34 | ||
33 | static unsigned long iommu_use[IOMMU_TOTAL_ENTRIES]; | 35 | static unsigned long *iommu_use; |
34 | 36 | ||
35 | #define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT) | 37 | #define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT) |
36 | 38 | ||
@@ -245,7 +247,7 @@ static inline int free_baddr(unsigned long baddr) | |||
245 | 247 | ||
246 | } | 248 | } |
247 | 249 | ||
248 | void dvma_init(void) | 250 | void __init dvma_init(void) |
249 | { | 251 | { |
250 | 252 | ||
251 | struct hole *hole; | 253 | struct hole *hole; |
@@ -265,7 +267,7 @@ void dvma_init(void) | |||
265 | 267 | ||
266 | list_add(&(hole->list), &hole_list); | 268 | list_add(&(hole->list), &hole_list); |
267 | 269 | ||
268 | memset(iommu_use, 0, sizeof(iommu_use)); | 270 | iommu_use = alloc_bootmem(IOMMU_TOTAL_ENTRIES * sizeof(unsigned long)); |
269 | 271 | ||
270 | dvma_unmap_iommu(DVMA_START, DVMA_SIZE); | 272 | dvma_unmap_iommu(DVMA_START, DVMA_SIZE); |
271 | 273 | ||
diff --git a/arch/m68k/sun3x/prom.c b/arch/m68k/sun3x/prom.c index a7b7e818d627..0898c3f81508 100644 --- a/arch/m68k/sun3x/prom.c +++ b/arch/m68k/sun3x/prom.c | |||
@@ -10,7 +10,6 @@ | |||
10 | 10 | ||
11 | #include <asm/page.h> | 11 | #include <asm/page.h> |
12 | #include <asm/pgtable.h> | 12 | #include <asm/pgtable.h> |
13 | #include <asm/bootinfo.h> | ||
14 | #include <asm/setup.h> | 13 | #include <asm/setup.h> |
15 | #include <asm/traps.h> | 14 | #include <asm/traps.h> |
16 | #include <asm/sun3xprom.h> | 15 | #include <asm/sun3xprom.h> |
diff --git a/arch/metag/include/asm/barrier.h b/arch/metag/include/asm/barrier.h index c90bfc6bf648..5d6b4b407dda 100644 --- a/arch/metag/include/asm/barrier.h +++ b/arch/metag/include/asm/barrier.h | |||
@@ -82,4 +82,19 @@ static inline void fence(void) | |||
82 | #define smp_read_barrier_depends() do { } while (0) | 82 | #define smp_read_barrier_depends() do { } while (0) |
83 | #define set_mb(var, value) do { var = value; smp_mb(); } while (0) | 83 | #define set_mb(var, value) do { var = value; smp_mb(); } while (0) |
84 | 84 | ||
85 | #define smp_store_release(p, v) \ | ||
86 | do { \ | ||
87 | compiletime_assert_atomic_type(*p); \ | ||
88 | smp_mb(); \ | ||
89 | ACCESS_ONCE(*p) = (v); \ | ||
90 | } while (0) | ||
91 | |||
92 | #define smp_load_acquire(p) \ | ||
93 | ({ \ | ||
94 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
95 | compiletime_assert_atomic_type(*p); \ | ||
96 | smp_mb(); \ | ||
97 | ___p1; \ | ||
98 | }) | ||
99 | |||
85 | #endif /* _ASM_METAG_BARRIER_H */ | 100 | #endif /* _ASM_METAG_BARRIER_H */ |
diff --git a/arch/metag/include/asm/smp.h b/arch/metag/include/asm/smp.h index e0373f81a117..1d7e770f7a54 100644 --- a/arch/metag/include/asm/smp.h +++ b/arch/metag/include/asm/smp.h | |||
@@ -7,13 +7,11 @@ | |||
7 | 7 | ||
8 | enum ipi_msg_type { | 8 | enum ipi_msg_type { |
9 | IPI_CALL_FUNC, | 9 | IPI_CALL_FUNC, |
10 | IPI_CALL_FUNC_SINGLE, | ||
11 | IPI_RESCHEDULE, | 10 | IPI_RESCHEDULE, |
12 | }; | 11 | }; |
13 | 12 | ||
14 | extern void arch_send_call_function_single_ipi(int cpu); | 13 | extern void arch_send_call_function_single_ipi(int cpu); |
15 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | 14 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); |
16 | #define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask | ||
17 | 15 | ||
18 | asmlinkage void secondary_start_kernel(void); | 16 | asmlinkage void secondary_start_kernel(void); |
19 | 17 | ||
diff --git a/arch/metag/kernel/dma.c b/arch/metag/kernel/dma.c index db589ad5dbc4..c700d625067a 100644 --- a/arch/metag/kernel/dma.c +++ b/arch/metag/kernel/dma.c | |||
@@ -399,11 +399,6 @@ static int __init dma_alloc_init(void) | |||
399 | pgd = pgd_offset(&init_mm, CONSISTENT_START); | 399 | pgd = pgd_offset(&init_mm, CONSISTENT_START); |
400 | pud = pud_alloc(&init_mm, pgd, CONSISTENT_START); | 400 | pud = pud_alloc(&init_mm, pgd, CONSISTENT_START); |
401 | pmd = pmd_alloc(&init_mm, pud, CONSISTENT_START); | 401 | pmd = pmd_alloc(&init_mm, pud, CONSISTENT_START); |
402 | if (!pmd) { | ||
403 | pr_err("%s: no pmd tables\n", __func__); | ||
404 | ret = -ENOMEM; | ||
405 | break; | ||
406 | } | ||
407 | WARN_ON(!pmd_none(*pmd)); | 402 | WARN_ON(!pmd_none(*pmd)); |
408 | 403 | ||
409 | pte = pte_alloc_kernel(pmd, CONSISTENT_START); | 404 | pte = pte_alloc_kernel(pmd, CONSISTENT_START); |
diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c index 7c0113142981..f006d2276f40 100644 --- a/arch/metag/kernel/smp.c +++ b/arch/metag/kernel/smp.c | |||
@@ -68,7 +68,7 @@ static DECLARE_COMPLETION(cpu_running); | |||
68 | /* | 68 | /* |
69 | * "thread" is assumed to be a valid Meta hardware thread ID. | 69 | * "thread" is assumed to be a valid Meta hardware thread ID. |
70 | */ | 70 | */ |
71 | int boot_secondary(unsigned int thread, struct task_struct *idle) | 71 | static int boot_secondary(unsigned int thread, struct task_struct *idle) |
72 | { | 72 | { |
73 | u32 val; | 73 | u32 val; |
74 | 74 | ||
@@ -491,7 +491,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) | |||
491 | 491 | ||
492 | void arch_send_call_function_single_ipi(int cpu) | 492 | void arch_send_call_function_single_ipi(int cpu) |
493 | { | 493 | { |
494 | send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); | 494 | send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC); |
495 | } | 495 | } |
496 | 496 | ||
497 | void show_ipi_list(struct seq_file *p) | 497 | void show_ipi_list(struct seq_file *p) |
@@ -517,11 +517,10 @@ static DEFINE_SPINLOCK(stop_lock); | |||
517 | * | 517 | * |
518 | * Bit 0 - Inter-processor function call | 518 | * Bit 0 - Inter-processor function call |
519 | */ | 519 | */ |
520 | static int do_IPI(struct pt_regs *regs) | 520 | static int do_IPI(void) |
521 | { | 521 | { |
522 | unsigned int cpu = smp_processor_id(); | 522 | unsigned int cpu = smp_processor_id(); |
523 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | 523 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); |
524 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
525 | unsigned long msgs, nextmsg; | 524 | unsigned long msgs, nextmsg; |
526 | int handled = 0; | 525 | int handled = 0; |
527 | 526 | ||
@@ -546,10 +545,6 @@ static int do_IPI(struct pt_regs *regs) | |||
546 | generic_smp_call_function_interrupt(); | 545 | generic_smp_call_function_interrupt(); |
547 | break; | 546 | break; |
548 | 547 | ||
549 | case IPI_CALL_FUNC_SINGLE: | ||
550 | generic_smp_call_function_single_interrupt(); | ||
551 | break; | ||
552 | |||
553 | default: | 548 | default: |
554 | pr_crit("CPU%u: Unknown IPI message 0x%lx\n", | 549 | pr_crit("CPU%u: Unknown IPI message 0x%lx\n", |
555 | cpu, nextmsg); | 550 | cpu, nextmsg); |
@@ -557,8 +552,6 @@ static int do_IPI(struct pt_regs *regs) | |||
557 | } | 552 | } |
558 | } | 553 | } |
559 | 554 | ||
560 | set_irq_regs(old_regs); | ||
561 | |||
562 | return handled; | 555 | return handled; |
563 | } | 556 | } |
564 | 557 | ||
@@ -624,7 +617,7 @@ static void kick_raise_softirq(cpumask_t callmap, unsigned int irq) | |||
624 | static TBIRES ipi_handler(TBIRES State, int SigNum, int Triggers, | 617 | static TBIRES ipi_handler(TBIRES State, int SigNum, int Triggers, |
625 | int Inst, PTBI pTBI, int *handled) | 618 | int Inst, PTBI pTBI, int *handled) |
626 | { | 619 | { |
627 | *handled = do_IPI((struct pt_regs *)State.Sig.pCtx); | 620 | *handled = do_IPI(); |
628 | 621 | ||
629 | return State; | 622 | return State; |
630 | } | 623 | } |
diff --git a/arch/metag/kernel/topology.c b/arch/metag/kernel/topology.c index bec3dec4922e..4ba595701f7d 100644 --- a/arch/metag/kernel/topology.c +++ b/arch/metag/kernel/topology.c | |||
@@ -19,6 +19,7 @@ | |||
19 | DEFINE_PER_CPU(struct cpuinfo_metag, cpu_data); | 19 | DEFINE_PER_CPU(struct cpuinfo_metag, cpu_data); |
20 | 20 | ||
21 | cpumask_t cpu_core_map[NR_CPUS]; | 21 | cpumask_t cpu_core_map[NR_CPUS]; |
22 | EXPORT_SYMBOL(cpu_core_map); | ||
22 | 23 | ||
23 | static cpumask_t cpu_coregroup_map(unsigned int cpu) | 24 | static cpumask_t cpu_coregroup_map(unsigned int cpu) |
24 | { | 25 | { |
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index ce0bbf8f5640..a82426589fff 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild | |||
@@ -1,4 +1,5 @@ | |||
1 | 1 | ||
2 | generic-y += barrier.h | ||
2 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
3 | generic-y += exec.h | 4 | generic-y += exec.h |
4 | generic-y += trace_clock.h | 5 | generic-y += trace_clock.h |
diff --git a/arch/microblaze/include/asm/barrier.h b/arch/microblaze/include/asm/barrier.h deleted file mode 100644 index df5be3e87044..000000000000 --- a/arch/microblaze/include/asm/barrier.h +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ASM_MICROBLAZE_BARRIER_H | ||
10 | #define _ASM_MICROBLAZE_BARRIER_H | ||
11 | |||
12 | #define nop() asm volatile ("nop") | ||
13 | |||
14 | #define smp_read_barrier_depends() do {} while (0) | ||
15 | #define read_barrier_depends() do {} while (0) | ||
16 | |||
17 | #define mb() barrier() | ||
18 | #define rmb() mb() | ||
19 | #define wmb() mb() | ||
20 | #define set_mb(var, value) do { var = value; mb(); } while (0) | ||
21 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
22 | |||
23 | #define smp_mb() mb() | ||
24 | #define smp_rmb() rmb() | ||
25 | #define smp_wmb() wmb() | ||
26 | |||
27 | #endif /* _ASM_MICROBLAZE_BARRIER_H */ | ||
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 650de3976e7a..c93d92beb3d6 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -47,6 +47,7 @@ config MIPS | |||
47 | select MODULES_USE_ELF_RELA if MODULES && 64BIT | 47 | select MODULES_USE_ELF_RELA if MODULES && 64BIT |
48 | select CLONE_BACKWARDS | 48 | select CLONE_BACKWARDS |
49 | select HAVE_DEBUG_STACKOVERFLOW | 49 | select HAVE_DEBUG_STACKOVERFLOW |
50 | select HAVE_CC_STACKPROTECTOR | ||
50 | 51 | ||
51 | menu "Machine selection" | 52 | menu "Machine selection" |
52 | 53 | ||
@@ -2322,19 +2323,6 @@ config SECCOMP | |||
2322 | 2323 | ||
2323 | If unsure, say Y. Only embedded should say N here. | 2324 | If unsure, say Y. Only embedded should say N here. |
2324 | 2325 | ||
2325 | config CC_STACKPROTECTOR | ||
2326 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" | ||
2327 | help | ||
2328 | This option turns on the -fstack-protector GCC feature. This | ||
2329 | feature puts, at the beginning of functions, a canary value on | ||
2330 | the stack just before the return address, and validates | ||
2331 | the value just before actually returning. Stack based buffer | ||
2332 | overflows (that need to overwrite this return address) now also | ||
2333 | overwrite the canary, which gets detected and the attack is then | ||
2334 | neutralized via a kernel panic. | ||
2335 | |||
2336 | This feature requires gcc version 4.2 or above. | ||
2337 | |||
2338 | config USE_OF | 2326 | config USE_OF |
2339 | bool | 2327 | bool |
2340 | select OF | 2328 | select OF |
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index de300b993607..efe50787cd89 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile | |||
@@ -232,10 +232,6 @@ bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) \ | |||
232 | 232 | ||
233 | LDFLAGS += -m $(ld-emul) | 233 | LDFLAGS += -m $(ld-emul) |
234 | 234 | ||
235 | ifdef CONFIG_CC_STACKPROTECTOR | ||
236 | KBUILD_CFLAGS += -fstack-protector | ||
237 | endif | ||
238 | |||
239 | ifdef CONFIG_MIPS | 235 | ifdef CONFIG_MIPS |
240 | CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ | 236 | CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ |
241 | egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ | 237 | egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ |
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c index 9a357fffcfbe..820b7a313d9b 100644 --- a/arch/mips/ar7/setup.c +++ b/arch/mips/ar7/setup.c | |||
@@ -92,7 +92,6 @@ void __init plat_mem_setup(void) | |||
92 | _machine_restart = ar7_machine_restart; | 92 | _machine_restart = ar7_machine_restart; |
93 | _machine_halt = ar7_machine_halt; | 93 | _machine_halt = ar7_machine_halt; |
94 | pm_power_off = ar7_machine_power_off; | 94 | pm_power_off = ar7_machine_power_off; |
95 | panic_timeout = 3; | ||
96 | 95 | ||
97 | io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000); | 96 | io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000); |
98 | if (!io_base) | 97 | if (!io_base) |
diff --git a/arch/mips/emma/markeins/setup.c b/arch/mips/emma/markeins/setup.c index d71005835c00..9100122e5cef 100644 --- a/arch/mips/emma/markeins/setup.c +++ b/arch/mips/emma/markeins/setup.c | |||
@@ -111,9 +111,6 @@ void __init plat_mem_setup(void) | |||
111 | iomem_resource.start = EMMA2RH_IO_BASE; | 111 | iomem_resource.start = EMMA2RH_IO_BASE; |
112 | iomem_resource.end = EMMA2RH_ROM_BASE - 1; | 112 | iomem_resource.end = EMMA2RH_ROM_BASE - 1; |
113 | 113 | ||
114 | /* Reboot on panic */ | ||
115 | panic_timeout = 180; | ||
116 | |||
117 | markeins_sio_setup(); | 114 | markeins_sio_setup(); |
118 | } | 115 | } |
119 | 116 | ||
diff --git a/arch/mips/include/asm/barrier.h b/arch/mips/include/asm/barrier.h index f26d8e1bf3c3..e1aa4e4c2984 100644 --- a/arch/mips/include/asm/barrier.h +++ b/arch/mips/include/asm/barrier.h | |||
@@ -180,4 +180,19 @@ | |||
180 | #define nudge_writes() mb() | 180 | #define nudge_writes() mb() |
181 | #endif | 181 | #endif |
182 | 182 | ||
183 | #define smp_store_release(p, v) \ | ||
184 | do { \ | ||
185 | compiletime_assert_atomic_type(*p); \ | ||
186 | smp_mb(); \ | ||
187 | ACCESS_ONCE(*p) = (v); \ | ||
188 | } while (0) | ||
189 | |||
190 | #define smp_load_acquire(p) \ | ||
191 | ({ \ | ||
192 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
193 | compiletime_assert_atomic_type(*p); \ | ||
194 | smp_mb(); \ | ||
195 | ___p1; \ | ||
196 | }) | ||
197 | |||
183 | #endif /* __ASM_BARRIER_H */ | 198 | #endif /* __ASM_BARRIER_H */ |
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h index c75025f27c20..06b9bc7ea14b 100644 --- a/arch/mips/include/asm/cacheops.h +++ b/arch/mips/include/asm/cacheops.h | |||
@@ -83,6 +83,6 @@ | |||
83 | /* | 83 | /* |
84 | * Loongson2-specific cacheops | 84 | * Loongson2-specific cacheops |
85 | */ | 85 | */ |
86 | #define Hit_Invalidate_I_Loongson23 0x00 | 86 | #define Hit_Invalidate_I_Loongson2 0x00 |
87 | 87 | ||
88 | #endif /* __ASM_CACHEOPS_H */ | 88 | #endif /* __ASM_CACHEOPS_H */ |
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h index 34d1a1917125..c84caddb8bde 100644 --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h | |||
@@ -165,7 +165,7 @@ static inline void flush_icache_line(unsigned long addr) | |||
165 | __iflush_prologue | 165 | __iflush_prologue |
166 | switch (boot_cpu_type()) { | 166 | switch (boot_cpu_type()) { |
167 | case CPU_LOONGSON2: | 167 | case CPU_LOONGSON2: |
168 | cache_op(Hit_Invalidate_I_Loongson23, addr); | 168 | cache_op(Hit_Invalidate_I_Loongson2, addr); |
169 | break; | 169 | break; |
170 | 170 | ||
171 | default: | 171 | default: |
@@ -219,7 +219,7 @@ static inline void protected_flush_icache_line(unsigned long addr) | |||
219 | { | 219 | { |
220 | switch (boot_cpu_type()) { | 220 | switch (boot_cpu_type()) { |
221 | case CPU_LOONGSON2: | 221 | case CPU_LOONGSON2: |
222 | protected_cache_op(Hit_Invalidate_I_Loongson23, addr); | 222 | protected_cache_op(Hit_Invalidate_I_Loongson2, addr); |
223 | break; | 223 | break; |
224 | 224 | ||
225 | default: | 225 | default: |
@@ -357,8 +357,8 @@ static inline void invalidate_tcache_page(unsigned long addr) | |||
357 | "i" (op)); | 357 | "i" (op)); |
358 | 358 | ||
359 | /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ | 359 | /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ |
360 | #define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \ | 360 | #define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \ |
361 | static inline void blast_##pfx##cache##lsize(void) \ | 361 | static inline void extra##blast_##pfx##cache##lsize(void) \ |
362 | { \ | 362 | { \ |
363 | unsigned long start = INDEX_BASE; \ | 363 | unsigned long start = INDEX_BASE; \ |
364 | unsigned long end = start + current_cpu_data.desc.waysize; \ | 364 | unsigned long end = start + current_cpu_data.desc.waysize; \ |
@@ -376,7 +376,7 @@ static inline void blast_##pfx##cache##lsize(void) \ | |||
376 | __##pfx##flush_epilogue \ | 376 | __##pfx##flush_epilogue \ |
377 | } \ | 377 | } \ |
378 | \ | 378 | \ |
379 | static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \ | 379 | static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \ |
380 | { \ | 380 | { \ |
381 | unsigned long start = page; \ | 381 | unsigned long start = page; \ |
382 | unsigned long end = page + PAGE_SIZE; \ | 382 | unsigned long end = page + PAGE_SIZE; \ |
@@ -391,7 +391,7 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \ | |||
391 | __##pfx##flush_epilogue \ | 391 | __##pfx##flush_epilogue \ |
392 | } \ | 392 | } \ |
393 | \ | 393 | \ |
394 | static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ | 394 | static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ |
395 | { \ | 395 | { \ |
396 | unsigned long indexmask = current_cpu_data.desc.waysize - 1; \ | 396 | unsigned long indexmask = current_cpu_data.desc.waysize - 1; \ |
397 | unsigned long start = INDEX_BASE + (page & indexmask); \ | 397 | unsigned long start = INDEX_BASE + (page & indexmask); \ |
@@ -410,23 +410,24 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) | |||
410 | __##pfx##flush_epilogue \ | 410 | __##pfx##flush_epilogue \ |
411 | } | 411 | } |
412 | 412 | ||
413 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16) | 413 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, ) |
414 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16) | 414 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, ) |
415 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16) | 415 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, ) |
416 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32) | 416 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, ) |
417 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32) | 417 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, ) |
418 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) | 418 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_) |
419 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64) | 419 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, ) |
420 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) | 420 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, ) |
421 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) | 421 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, ) |
422 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) | 422 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, ) |
423 | 423 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, ) | |
424 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16) | 424 | |
425 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32) | 425 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, ) |
426 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16) | 426 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, ) |
427 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32) | 427 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, ) |
428 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64) | 428 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, ) |
429 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128) | 429 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, ) |
430 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, ) | ||
430 | 431 | ||
431 | /* build blast_xxx_range, protected_blast_xxx_range */ | 432 | /* build blast_xxx_range, protected_blast_xxx_range */ |
432 | #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \ | 433 | #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \ |
@@ -452,8 +453,8 @@ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, | |||
452 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, ) | 453 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, ) |
453 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, ) | 454 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, ) |
454 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, ) | 455 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, ) |
455 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson23, \ | 456 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \ |
456 | protected_, loongson23_) | 457 | protected_, loongson2_) |
457 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , ) | 458 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , ) |
458 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) | 459 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) |
459 | /* blast_inv_dcache_range */ | 460 | /* blast_inv_dcache_range */ |
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 62ffd20ea869..49e572d879e1 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
@@ -237,6 +237,8 @@ static void r4k_blast_icache_page_setup(void) | |||
237 | r4k_blast_icache_page = (void *)cache_noop; | 237 | r4k_blast_icache_page = (void *)cache_noop; |
238 | else if (ic_lsize == 16) | 238 | else if (ic_lsize == 16) |
239 | r4k_blast_icache_page = blast_icache16_page; | 239 | r4k_blast_icache_page = blast_icache16_page; |
240 | else if (ic_lsize == 32 && current_cpu_type() == CPU_LOONGSON2) | ||
241 | r4k_blast_icache_page = loongson2_blast_icache32_page; | ||
240 | else if (ic_lsize == 32) | 242 | else if (ic_lsize == 32) |
241 | r4k_blast_icache_page = blast_icache32_page; | 243 | r4k_blast_icache_page = blast_icache32_page; |
242 | else if (ic_lsize == 64) | 244 | else if (ic_lsize == 64) |
@@ -261,6 +263,9 @@ static void r4k_blast_icache_page_indexed_setup(void) | |||
261 | else if (TX49XX_ICACHE_INDEX_INV_WAR) | 263 | else if (TX49XX_ICACHE_INDEX_INV_WAR) |
262 | r4k_blast_icache_page_indexed = | 264 | r4k_blast_icache_page_indexed = |
263 | tx49_blast_icache32_page_indexed; | 265 | tx49_blast_icache32_page_indexed; |
266 | else if (current_cpu_type() == CPU_LOONGSON2) | ||
267 | r4k_blast_icache_page_indexed = | ||
268 | loongson2_blast_icache32_page_indexed; | ||
264 | else | 269 | else |
265 | r4k_blast_icache_page_indexed = | 270 | r4k_blast_icache_page_indexed = |
266 | blast_icache32_page_indexed; | 271 | blast_icache32_page_indexed; |
@@ -284,6 +289,8 @@ static void r4k_blast_icache_setup(void) | |||
284 | r4k_blast_icache = blast_r4600_v1_icache32; | 289 | r4k_blast_icache = blast_r4600_v1_icache32; |
285 | else if (TX49XX_ICACHE_INDEX_INV_WAR) | 290 | else if (TX49XX_ICACHE_INDEX_INV_WAR) |
286 | r4k_blast_icache = tx49_blast_icache32; | 291 | r4k_blast_icache = tx49_blast_icache32; |
292 | else if (current_cpu_type() == CPU_LOONGSON2) | ||
293 | r4k_blast_icache = loongson2_blast_icache32; | ||
287 | else | 294 | else |
288 | r4k_blast_icache = blast_icache32; | 295 | r4k_blast_icache = blast_icache32; |
289 | } else if (ic_lsize == 64) | 296 | } else if (ic_lsize == 64) |
@@ -580,11 +587,11 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo | |||
580 | else { | 587 | else { |
581 | switch (boot_cpu_type()) { | 588 | switch (boot_cpu_type()) { |
582 | case CPU_LOONGSON2: | 589 | case CPU_LOONGSON2: |
583 | protected_blast_icache_range(start, end); | 590 | protected_loongson2_blast_icache_range(start, end); |
584 | break; | 591 | break; |
585 | 592 | ||
586 | default: | 593 | default: |
587 | protected_loongson23_blast_icache_range(start, end); | 594 | protected_blast_icache_range(start, end); |
588 | break; | 595 | break; |
589 | } | 596 | } |
590 | } | 597 | } |
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 6d981bb337ec..54e75c77184b 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c | |||
@@ -92,7 +92,6 @@ static void __init xlp_init_mem_from_bars(void) | |||
92 | 92 | ||
93 | void __init plat_mem_setup(void) | 93 | void __init plat_mem_setup(void) |
94 | { | 94 | { |
95 | panic_timeout = 5; | ||
96 | _machine_restart = (void (*)(char *))nlm_linux_exit; | 95 | _machine_restart = (void (*)(char *))nlm_linux_exit; |
97 | _machine_halt = nlm_linux_exit; | 96 | _machine_halt = nlm_linux_exit; |
98 | pm_power_off = nlm_linux_exit; | 97 | pm_power_off = nlm_linux_exit; |
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index 214d123b79fa..921be5f77797 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c | |||
@@ -92,7 +92,6 @@ static void nlm_linux_exit(void) | |||
92 | 92 | ||
93 | void __init plat_mem_setup(void) | 93 | void __init plat_mem_setup(void) |
94 | { | 94 | { |
95 | panic_timeout = 5; | ||
96 | _machine_restart = (void (*)(char *))nlm_linux_exit; | 95 | _machine_restart = (void (*)(char *))nlm_linux_exit; |
97 | _machine_halt = nlm_linux_exit; | 96 | _machine_halt = nlm_linux_exit; |
98 | pm_power_off = nlm_linux_exit; | 97 | pm_power_off = nlm_linux_exit; |
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index 41707a245dea..3462c831d0ea 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c | |||
@@ -134,8 +134,6 @@ void __init plat_mem_setup(void) | |||
134 | #error invalid SiByte board configuration | 134 | #error invalid SiByte board configuration |
135 | #endif | 135 | #endif |
136 | 136 | ||
137 | panic_timeout = 5; /* For debug. */ | ||
138 | |||
139 | board_be_handler = swarm_be_handler; | 137 | board_be_handler = swarm_be_handler; |
140 | 138 | ||
141 | if (xicor_probe()) | 139 | if (xicor_probe()) |
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index 74742dc6a3da..032143ec2324 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild | |||
@@ -1,4 +1,5 @@ | |||
1 | 1 | ||
2 | generic-y += barrier.h | ||
2 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
3 | generic-y += exec.h | 4 | generic-y += exec.h |
4 | generic-y += trace_clock.h | 5 | generic-y += trace_clock.h |
diff --git a/arch/mn10300/include/asm/barrier.h b/arch/mn10300/include/asm/barrier.h deleted file mode 100644 index 2bd97a5c8af7..000000000000 --- a/arch/mn10300/include/asm/barrier.h +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | /* MN10300 memory barrier definitions | ||
2 | * | ||
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | #ifndef _ASM_BARRIER_H | ||
12 | #define _ASM_BARRIER_H | ||
13 | |||
14 | #define nop() asm volatile ("nop") | ||
15 | |||
16 | #define mb() asm volatile ("": : :"memory") | ||
17 | #define rmb() mb() | ||
18 | #define wmb() asm volatile ("": : :"memory") | ||
19 | |||
20 | #ifdef CONFIG_SMP | ||
21 | #define smp_mb() mb() | ||
22 | #define smp_rmb() rmb() | ||
23 | #define smp_wmb() wmb() | ||
24 | #define set_mb(var, value) do { xchg(&var, value); } while (0) | ||
25 | #else /* CONFIG_SMP */ | ||
26 | #define smp_mb() barrier() | ||
27 | #define smp_rmb() barrier() | ||
28 | #define smp_wmb() barrier() | ||
29 | #define set_mb(var, value) do { var = value; mb(); } while (0) | ||
30 | #endif /* CONFIG_SMP */ | ||
31 | |||
32 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
33 | |||
34 | #define read_barrier_depends() do {} while (0) | ||
35 | #define smp_read_barrier_depends() do {} while (0) | ||
36 | |||
37 | #endif /* _ASM_BARRIER_H */ | ||
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild index a603b9ebe54c..34b0be4ca52d 100644 --- a/arch/parisc/include/asm/Kbuild +++ b/arch/parisc/include/asm/Kbuild | |||
@@ -1,4 +1,5 @@ | |||
1 | 1 | ||
2 | generic-y += barrier.h | ||
2 | generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \ | 3 | generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \ |
3 | segment.h topology.h vga.h device.h percpu.h hw_irq.h mutex.h \ | 4 | segment.h topology.h vga.h device.h percpu.h hw_irq.h mutex.h \ |
4 | div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \ | 5 | div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \ |
diff --git a/arch/parisc/include/asm/barrier.h b/arch/parisc/include/asm/barrier.h deleted file mode 100644 index e77d834aa803..000000000000 --- a/arch/parisc/include/asm/barrier.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | #ifndef __PARISC_BARRIER_H | ||
2 | #define __PARISC_BARRIER_H | ||
3 | |||
4 | /* | ||
5 | ** This is simply the barrier() macro from linux/kernel.h but when serial.c | ||
6 | ** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h | ||
7 | ** hasn't yet been included yet so it fails, thus repeating the macro here. | ||
8 | ** | ||
9 | ** PA-RISC architecture allows for weakly ordered memory accesses although | ||
10 | ** none of the processors use it. There is a strong ordered bit that is | ||
11 | ** set in the O-bit of the page directory entry. Operating systems that | ||
12 | ** can not tolerate out of order accesses should set this bit when mapping | ||
13 | ** pages. The O-bit of the PSW should also be set to 1 (I don't believe any | ||
14 | ** of the processor implemented the PSW O-bit). The PCX-W ERS states that | ||
15 | ** the TLB O-bit is not implemented so the page directory does not need to | ||
16 | ** have the O-bit set when mapping pages (section 3.1). This section also | ||
17 | ** states that the PSW Y, Z, G, and O bits are not implemented. | ||
18 | ** So it looks like nothing needs to be done for parisc-linux (yet). | ||
19 | ** (thanks to chada for the above comment -ggg) | ||
20 | ** | ||
21 | ** The __asm__ op below simple prevents gcc/ld from reordering | ||
22 | ** instructions across the mb() "call". | ||
23 | */ | ||
24 | #define mb() __asm__ __volatile__("":::"memory") /* barrier() */ | ||
25 | #define rmb() mb() | ||
26 | #define wmb() mb() | ||
27 | #define smp_mb() mb() | ||
28 | #define smp_rmb() mb() | ||
29 | #define smp_wmb() mb() | ||
30 | #define smp_read_barrier_depends() do { } while(0) | ||
31 | #define read_barrier_depends() do { } while(0) | ||
32 | |||
33 | #define set_mb(var, value) do { var = value; mb(); } while (0) | ||
34 | |||
35 | #endif /* __PARISC_BARRIER_H */ | ||
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index f33113a6141e..70b3674dac4e 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h | |||
@@ -75,6 +75,6 @@ | |||
75 | 75 | ||
76 | #define SO_BUSY_POLL 0x4027 | 76 | #define SO_BUSY_POLL 0x4027 |
77 | 77 | ||
78 | #define SO_MAX_PACING_RATE 0x4048 | 78 | #define SO_MAX_PACING_RATE 0x4028 |
79 | 79 | ||
80 | #endif /* _UAPI_ASM_SOCKET_H */ | 80 | #endif /* _UAPI_ASM_SOCKET_H */ |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index b44b52c0a8f0..b2be8e8cb5c7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -147,6 +147,10 @@ config EARLY_PRINTK | |||
147 | bool | 147 | bool |
148 | default y | 148 | default y |
149 | 149 | ||
150 | config PANIC_TIMEOUT | ||
151 | int | ||
152 | default 180 | ||
153 | |||
150 | config COMPAT | 154 | config COMPAT |
151 | bool | 155 | bool |
152 | default y if PPC64 | 156 | default y if PPC64 |
diff --git a/arch/powerpc/include/asm/barrier.h b/arch/powerpc/include/asm/barrier.h index ae782254e731..f89da808ce31 100644 --- a/arch/powerpc/include/asm/barrier.h +++ b/arch/powerpc/include/asm/barrier.h | |||
@@ -45,11 +45,15 @@ | |||
45 | # define SMPWMB eieio | 45 | # define SMPWMB eieio |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #define __lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory") | ||
49 | |||
48 | #define smp_mb() mb() | 50 | #define smp_mb() mb() |
49 | #define smp_rmb() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory") | 51 | #define smp_rmb() __lwsync() |
50 | #define smp_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory") | 52 | #define smp_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory") |
51 | #define smp_read_barrier_depends() read_barrier_depends() | 53 | #define smp_read_barrier_depends() read_barrier_depends() |
52 | #else | 54 | #else |
55 | #define __lwsync() barrier() | ||
56 | |||
53 | #define smp_mb() barrier() | 57 | #define smp_mb() barrier() |
54 | #define smp_rmb() barrier() | 58 | #define smp_rmb() barrier() |
55 | #define smp_wmb() barrier() | 59 | #define smp_wmb() barrier() |
@@ -65,4 +69,19 @@ | |||
65 | #define data_barrier(x) \ | 69 | #define data_barrier(x) \ |
66 | asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory"); | 70 | asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory"); |
67 | 71 | ||
72 | #define smp_store_release(p, v) \ | ||
73 | do { \ | ||
74 | compiletime_assert_atomic_type(*p); \ | ||
75 | __lwsync(); \ | ||
76 | ACCESS_ONCE(*p) = (v); \ | ||
77 | } while (0) | ||
78 | |||
79 | #define smp_load_acquire(p) \ | ||
80 | ({ \ | ||
81 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
82 | compiletime_assert_atomic_type(*p); \ | ||
83 | __lwsync(); \ | ||
84 | ___p1; \ | ||
85 | }) | ||
86 | |||
68 | #endif /* _ASM_POWERPC_BARRIER_H */ | 87 | #endif /* _ASM_POWERPC_BARRIER_H */ |
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h index 703a8412dac2..11ba86e17631 100644 --- a/arch/powerpc/include/asm/setup.h +++ b/arch/powerpc/include/asm/setup.h | |||
@@ -26,6 +26,7 @@ extern void reloc_got2(unsigned long); | |||
26 | void check_for_initrd(void); | 26 | void check_for_initrd(void); |
27 | void do_init_bootmem(void); | 27 | void do_init_bootmem(void); |
28 | void setup_panic(void); | 28 | void setup_panic(void); |
29 | #define ARCH_PANIC_TIMEOUT 180 | ||
29 | 30 | ||
30 | #endif /* !__ASSEMBLY__ */ | 31 | #endif /* !__ASSEMBLY__ */ |
31 | 32 | ||
diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h index 5f54a744dcc5..f6e78d63fb6a 100644 --- a/arch/powerpc/include/asm/spinlock.h +++ b/arch/powerpc/include/asm/spinlock.h | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <asm/synch.h> | 28 | #include <asm/synch.h> |
29 | #include <asm/ppc-opcode.h> | 29 | #include <asm/ppc-opcode.h> |
30 | 30 | ||
31 | #define smp_mb__after_unlock_lock() smp_mb() /* Full ordering for lock. */ | ||
32 | |||
31 | #define arch_spin_is_locked(x) ((x)->slock != 0) | 33 | #define arch_spin_is_locked(x) ((x)->slock != 0) |
32 | 34 | ||
33 | #ifdef CONFIG_PPC64 | 35 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h index 75c6ecdb8f37..7422a999a39a 100644 --- a/arch/powerpc/include/asm/uprobes.h +++ b/arch/powerpc/include/asm/uprobes.h | |||
@@ -36,9 +36,8 @@ typedef ppc_opcode_t uprobe_opcode_t; | |||
36 | 36 | ||
37 | struct arch_uprobe { | 37 | struct arch_uprobe { |
38 | union { | 38 | union { |
39 | u8 insn[MAX_UINSN_BYTES]; | 39 | u32 insn; |
40 | u8 ixol[MAX_UINSN_BYTES]; | 40 | u32 ixol; |
41 | u32 ainsn; | ||
42 | }; | 41 | }; |
43 | }; | 42 | }; |
44 | 43 | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index b903dc5cf944..2b0da27eaee4 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -296,9 +296,6 @@ void __init setup_arch(char **cmdline_p) | |||
296 | if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) | 296 | if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) |
297 | ucache_bsize = icache_bsize = dcache_bsize; | 297 | ucache_bsize = icache_bsize = dcache_bsize; |
298 | 298 | ||
299 | /* reboot on panic */ | ||
300 | panic_timeout = 180; | ||
301 | |||
302 | if (ppc_md.panic) | 299 | if (ppc_md.panic) |
303 | setup_panic(); | 300 | setup_panic(); |
304 | 301 | ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4085aaa9478f..856dd4e99bfe 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -588,9 +588,6 @@ void __init setup_arch(char **cmdline_p) | |||
588 | dcache_bsize = ppc64_caches.dline_size; | 588 | dcache_bsize = ppc64_caches.dline_size; |
589 | icache_bsize = ppc64_caches.iline_size; | 589 | icache_bsize = ppc64_caches.iline_size; |
590 | 590 | ||
591 | /* reboot on panic */ | ||
592 | panic_timeout = 180; | ||
593 | |||
594 | if (ppc_md.panic) | 591 | if (ppc_md.panic) |
595 | setup_panic(); | 592 | setup_panic(); |
596 | 593 | ||
diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c index 59f419b935f2..003b20964ea0 100644 --- a/arch/powerpc/kernel/uprobes.c +++ b/arch/powerpc/kernel/uprobes.c | |||
@@ -186,7 +186,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
186 | * emulate_step() returns 1 if the insn was successfully emulated. | 186 | * emulate_step() returns 1 if the insn was successfully emulated. |
187 | * For all other cases, we need to single-step in hardware. | 187 | * For all other cases, we need to single-step in hardware. |
188 | */ | 188 | */ |
189 | ret = emulate_step(regs, auprobe->ainsn); | 189 | ret = emulate_step(regs, auprobe->insn); |
190 | if (ret > 0) | 190 | if (ret > 0) |
191 | return true; | 191 | return true; |
192 | 192 | ||
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index ac3c2a10dafd..555034f8505e 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c | |||
@@ -223,10 +223,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | |||
223 | } | 223 | } |
224 | PPC_DIVWU(r_A, r_A, r_X); | 224 | PPC_DIVWU(r_A, r_A, r_X); |
225 | break; | 225 | break; |
226 | case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ | 226 | case BPF_S_ALU_DIV_K: /* A /= K */ |
227 | if (K == 1) | ||
228 | break; | ||
227 | PPC_LI32(r_scratch1, K); | 229 | PPC_LI32(r_scratch1, K); |
228 | /* Top 32 bits of 64bit result -> A */ | 230 | PPC_DIVWU(r_A, r_A, r_scratch1); |
229 | PPC_MULHWU(r_A, r_A, r_scratch1); | ||
230 | break; | 231 | break; |
231 | case BPF_S_ALU_AND_X: | 232 | case BPF_S_ALU_AND_X: |
232 | ctx->seen |= SEEN_XREG; | 233 | ctx->seen |= SEEN_XREG; |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index c1f190858701..6f76ae417f47 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -470,7 +470,7 @@ static long pseries_little_endian_exceptions(void) | |||
470 | 470 | ||
471 | static void __init pSeries_setup_arch(void) | 471 | static void __init pSeries_setup_arch(void) |
472 | { | 472 | { |
473 | panic_timeout = 10; | 473 | set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); |
474 | 474 | ||
475 | /* Discover PIC type and setup ppc_md accordingly */ | 475 | /* Discover PIC type and setup ppc_md accordingly */ |
476 | pseries_discover_pic(); | 476 | pseries_discover_pic(); |
diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h index 16760eeb79b0..578680f6207a 100644 --- a/arch/s390/include/asm/barrier.h +++ b/arch/s390/include/asm/barrier.h | |||
@@ -32,4 +32,19 @@ | |||
32 | 32 | ||
33 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 33 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
34 | 34 | ||
35 | #define smp_store_release(p, v) \ | ||
36 | do { \ | ||
37 | compiletime_assert_atomic_type(*p); \ | ||
38 | barrier(); \ | ||
39 | ACCESS_ONCE(*p) = (v); \ | ||
40 | } while (0) | ||
41 | |||
42 | #define smp_load_acquire(p) \ | ||
43 | ({ \ | ||
44 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
45 | compiletime_assert_atomic_type(*p); \ | ||
46 | barrier(); \ | ||
47 | ___p1; \ | ||
48 | }) | ||
49 | |||
35 | #endif /* __ASM_BARRIER_H */ | 50 | #endif /* __ASM_BARRIER_H */ |
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 4bf9da03591e..5d7e8cf83bd6 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h | |||
@@ -38,7 +38,8 @@ | |||
38 | 38 | ||
39 | #define PSW32_USER_BITS (PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT | \ | 39 | #define PSW32_USER_BITS (PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT | \ |
40 | PSW32_DEFAULT_KEY | PSW32_MASK_BASE | \ | 40 | PSW32_DEFAULT_KEY | PSW32_MASK_BASE | \ |
41 | PSW32_MASK_MCHECK | PSW32_MASK_PSTATE | PSW32_ASC_HOME) | 41 | PSW32_MASK_MCHECK | PSW32_MASK_PSTATE | \ |
42 | PSW32_ASC_PRIMARY) | ||
42 | 43 | ||
43 | #define COMPAT_USER_HZ 100 | 44 | #define COMPAT_USER_HZ 100 |
44 | #define COMPAT_UTS_MACHINE "s390\0\0\0\0" | 45 | #define COMPAT_UTS_MACHINE "s390\0\0\0\0" |
diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h index c879fad404c8..cb700d54bd83 100644 --- a/arch/s390/include/asm/cpu_mf.h +++ b/arch/s390/include/asm/cpu_mf.h | |||
@@ -56,6 +56,96 @@ struct cpumf_ctr_info { | |||
56 | u32 reserved2[12]; | 56 | u32 reserved2[12]; |
57 | } __packed; | 57 | } __packed; |
58 | 58 | ||
59 | /* QUERY SAMPLING INFORMATION block */ | ||
60 | struct hws_qsi_info_block { /* Bit(s) */ | ||
61 | unsigned int b0_13:14; /* 0-13: zeros */ | ||
62 | unsigned int as:1; /* 14: basic-sampling authorization */ | ||
63 | unsigned int ad:1; /* 15: diag-sampling authorization */ | ||
64 | unsigned int b16_21:6; /* 16-21: zeros */ | ||
65 | unsigned int es:1; /* 22: basic-sampling enable control */ | ||
66 | unsigned int ed:1; /* 23: diag-sampling enable control */ | ||
67 | unsigned int b24_29:6; /* 24-29: zeros */ | ||
68 | unsigned int cs:1; /* 30: basic-sampling activation control */ | ||
69 | unsigned int cd:1; /* 31: diag-sampling activation control */ | ||
70 | unsigned int bsdes:16; /* 4-5: size of basic sampling entry */ | ||
71 | unsigned int dsdes:16; /* 6-7: size of diagnostic sampling entry */ | ||
72 | unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */ | ||
73 | unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/ | ||
74 | unsigned long tear; /* 24-31: TEAR contents */ | ||
75 | unsigned long dear; /* 32-39: DEAR contents */ | ||
76 | unsigned int rsvrd0; /* 40-43: reserved */ | ||
77 | unsigned int cpu_speed; /* 44-47: CPU speed */ | ||
78 | unsigned long long rsvrd1; /* 48-55: reserved */ | ||
79 | unsigned long long rsvrd2; /* 56-63: reserved */ | ||
80 | } __packed; | ||
81 | |||
82 | /* SET SAMPLING CONTROLS request block */ | ||
83 | struct hws_lsctl_request_block { | ||
84 | unsigned int s:1; /* 0: maximum buffer indicator */ | ||
85 | unsigned int h:1; /* 1: part. level reserved for VM use*/ | ||
86 | unsigned long long b2_53:52;/* 2-53: zeros */ | ||
87 | unsigned int es:1; /* 54: basic-sampling enable control */ | ||
88 | unsigned int ed:1; /* 55: diag-sampling enable control */ | ||
89 | unsigned int b56_61:6; /* 56-61: - zeros */ | ||
90 | unsigned int cs:1; /* 62: basic-sampling activation control */ | ||
91 | unsigned int cd:1; /* 63: diag-sampling activation control */ | ||
92 | unsigned long interval; /* 8-15: sampling interval */ | ||
93 | unsigned long tear; /* 16-23: TEAR contents */ | ||
94 | unsigned long dear; /* 24-31: DEAR contents */ | ||
95 | /* 32-63: */ | ||
96 | unsigned long rsvrd1; /* reserved */ | ||
97 | unsigned long rsvrd2; /* reserved */ | ||
98 | unsigned long rsvrd3; /* reserved */ | ||
99 | unsigned long rsvrd4; /* reserved */ | ||
100 | } __packed; | ||
101 | |||
102 | struct hws_basic_entry { | ||
103 | unsigned int def:16; /* 0-15 Data Entry Format */ | ||
104 | unsigned int R:4; /* 16-19 reserved */ | ||
105 | unsigned int U:4; /* 20-23 Number of unique instruct. */ | ||
106 | unsigned int z:2; /* zeros */ | ||
107 | unsigned int T:1; /* 26 PSW DAT mode */ | ||
108 | unsigned int W:1; /* 27 PSW wait state */ | ||
109 | unsigned int P:1; /* 28 PSW Problem state */ | ||
110 | unsigned int AS:2; /* 29-30 PSW address-space control */ | ||
111 | unsigned int I:1; /* 31 entry valid or invalid */ | ||
112 | unsigned int:16; | ||
113 | unsigned int prim_asn:16; /* primary ASN */ | ||
114 | unsigned long long ia; /* Instruction Address */ | ||
115 | unsigned long long gpp; /* Guest Program Parameter */ | ||
116 | unsigned long long hpp; /* Host Program Parameter */ | ||
117 | } __packed; | ||
118 | |||
119 | struct hws_diag_entry { | ||
120 | unsigned int def:16; /* 0-15 Data Entry Format */ | ||
121 | unsigned int R:14; /* 16-19 and 20-30 reserved */ | ||
122 | unsigned int I:1; /* 31 entry valid or invalid */ | ||
123 | u8 data[]; /* Machine-dependent sample data */ | ||
124 | } __packed; | ||
125 | |||
126 | struct hws_combined_entry { | ||
127 | struct hws_basic_entry basic; /* Basic-sampling data entry */ | ||
128 | struct hws_diag_entry diag; /* Diagnostic-sampling data entry */ | ||
129 | } __packed; | ||
130 | |||
131 | struct hws_trailer_entry { | ||
132 | union { | ||
133 | struct { | ||
134 | unsigned int f:1; /* 0 - Block Full Indicator */ | ||
135 | unsigned int a:1; /* 1 - Alert request control */ | ||
136 | unsigned int t:1; /* 2 - Timestamp format */ | ||
137 | unsigned long long:61; /* 3 - 63: Reserved */ | ||
138 | }; | ||
139 | unsigned long long flags; /* 0 - 63: All indicators */ | ||
140 | }; | ||
141 | unsigned long long overflow; /* 64 - sample Overflow count */ | ||
142 | unsigned char timestamp[16]; /* 16 - 31 timestamp */ | ||
143 | unsigned long long reserved1; /* 32 -Reserved */ | ||
144 | unsigned long long reserved2; /* */ | ||
145 | unsigned long long progusage1; /* 48 - reserved for programming use */ | ||
146 | unsigned long long progusage2; /* */ | ||
147 | } __packed; | ||
148 | |||
59 | /* Query counter information */ | 149 | /* Query counter information */ |
60 | static inline int qctri(struct cpumf_ctr_info *info) | 150 | static inline int qctri(struct cpumf_ctr_info *info) |
61 | { | 151 | { |
@@ -99,4 +189,95 @@ static inline int ecctr(u64 ctr, u64 *val) | |||
99 | return cc; | 189 | return cc; |
100 | } | 190 | } |
101 | 191 | ||
192 | /* Query sampling information */ | ||
193 | static inline int qsi(struct hws_qsi_info_block *info) | ||
194 | { | ||
195 | int cc; | ||
196 | cc = 1; | ||
197 | |||
198 | asm volatile( | ||
199 | "0: .insn s,0xb2860000,0(%1)\n" | ||
200 | "1: lhi %0,0\n" | ||
201 | "2:\n" | ||
202 | EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) | ||
203 | : "=d" (cc), "+a" (info) | ||
204 | : "m" (*info) | ||
205 | : "cc", "memory"); | ||
206 | |||
207 | return cc ? -EINVAL : 0; | ||
208 | } | ||
209 | |||
210 | /* Load sampling controls */ | ||
211 | static inline int lsctl(struct hws_lsctl_request_block *req) | ||
212 | { | ||
213 | int cc; | ||
214 | |||
215 | cc = 1; | ||
216 | asm volatile( | ||
217 | "0: .insn s,0xb2870000,0(%1)\n" | ||
218 | "1: ipm %0\n" | ||
219 | " srl %0,28\n" | ||
220 | "2:\n" | ||
221 | EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) | ||
222 | : "+d" (cc), "+a" (req) | ||
223 | : "m" (*req) | ||
224 | : "cc", "memory"); | ||
225 | |||
226 | return cc ? -EINVAL : 0; | ||
227 | } | ||
228 | |||
229 | /* Sampling control helper functions */ | ||
230 | |||
231 | #include <linux/time.h> | ||
232 | |||
233 | static inline unsigned long freq_to_sample_rate(struct hws_qsi_info_block *qsi, | ||
234 | unsigned long freq) | ||
235 | { | ||
236 | return (USEC_PER_SEC / freq) * qsi->cpu_speed; | ||
237 | } | ||
238 | |||
239 | static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi, | ||
240 | unsigned long rate) | ||
241 | { | ||
242 | return USEC_PER_SEC * qsi->cpu_speed / rate; | ||
243 | } | ||
244 | |||
245 | #define SDB_TE_ALERT_REQ_MASK 0x4000000000000000UL | ||
246 | #define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL | ||
247 | |||
248 | /* Return TOD timestamp contained in an trailer entry */ | ||
249 | static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te) | ||
250 | { | ||
251 | /* TOD in STCKE format */ | ||
252 | if (te->t) | ||
253 | return *((unsigned long long *) &te->timestamp[1]); | ||
254 | |||
255 | /* TOD in STCK format */ | ||
256 | return *((unsigned long long *) &te->timestamp[0]); | ||
257 | } | ||
258 | |||
259 | /* Return pointer to trailer entry of an sample data block */ | ||
260 | static inline unsigned long *trailer_entry_ptr(unsigned long v) | ||
261 | { | ||
262 | void *ret; | ||
263 | |||
264 | ret = (void *) v; | ||
265 | ret += PAGE_SIZE; | ||
266 | ret -= sizeof(struct hws_trailer_entry); | ||
267 | |||
268 | return (unsigned long *) ret; | ||
269 | } | ||
270 | |||
271 | /* Return if the entry in the sample data block table (sdbt) | ||
272 | * is a link to the next sdbt */ | ||
273 | static inline int is_link_entry(unsigned long *s) | ||
274 | { | ||
275 | return *s & 0x1ul ? 1 : 0; | ||
276 | } | ||
277 | |||
278 | /* Return pointer to the linked sdbt */ | ||
279 | static inline unsigned long *get_next_sdbt(unsigned long *s) | ||
280 | { | ||
281 | return (unsigned long *) (*s & ~0x1ul); | ||
282 | } | ||
102 | #endif /* _ASM_S390_CPU_MF_H */ | 283 | #endif /* _ASM_S390_CPU_MF_H */ |
diff --git a/arch/s390/include/asm/css_chars.h b/arch/s390/include/asm/css_chars.h index 7e1c917bbba2..09d1dd46bd57 100644 --- a/arch/s390/include/asm/css_chars.h +++ b/arch/s390/include/asm/css_chars.h | |||
@@ -29,6 +29,8 @@ struct css_general_char { | |||
29 | u32 fcx : 1; /* bit 88 */ | 29 | u32 fcx : 1; /* bit 88 */ |
30 | u32 : 19; | 30 | u32 : 19; |
31 | u32 alt_ssi : 1; /* bit 108 */ | 31 | u32 alt_ssi : 1; /* bit 108 */ |
32 | u32:1; | ||
33 | u32 narf:1; /* bit 110 */ | ||
32 | } __packed; | 34 | } __packed; |
33 | 35 | ||
34 | extern struct css_general_char css_general_characteristics; | 36 | extern struct css_general_char css_general_characteristics; |
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index c129ab2ac731..2583466f576b 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h | |||
@@ -144,6 +144,7 @@ int clp_disable_fh(struct zpci_dev *); | |||
144 | void zpci_event_error(void *); | 144 | void zpci_event_error(void *); |
145 | void zpci_event_availability(void *); | 145 | void zpci_event_availability(void *); |
146 | void zpci_rescan(void); | 146 | void zpci_rescan(void); |
147 | bool zpci_is_enabled(void); | ||
147 | #else /* CONFIG_PCI */ | 148 | #else /* CONFIG_PCI */ |
148 | static inline void zpci_event_error(void *e) {} | 149 | static inline void zpci_event_error(void *e) {} |
149 | static inline void zpci_event_availability(void *e) {} | 150 | static inline void zpci_event_availability(void *e) {} |
diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h index 1141fb3e7b21..159a8ec6da9a 100644 --- a/arch/s390/include/asm/perf_event.h +++ b/arch/s390/include/asm/perf_event.h | |||
@@ -1,21 +1,40 @@ | |||
1 | /* | 1 | /* |
2 | * Performance event support - s390 specific definitions. | 2 | * Performance event support - s390 specific definitions. |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2009, 2012 | 4 | * Copyright IBM Corp. 2009, 2013 |
5 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | 5 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> |
6 | * Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 6 | * Hendrik Brueckner <brueckner@linux.vnet.ibm.com> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <asm/cpu_mf.h> | 9 | #ifndef _ASM_S390_PERF_EVENT_H |
10 | #define _ASM_S390_PERF_EVENT_H | ||
10 | 11 | ||
11 | /* CPU-measurement counter facility */ | 12 | #ifdef CONFIG_64BIT |
12 | #define PERF_CPUM_CF_MAX_CTR 256 | 13 | |
14 | #include <linux/perf_event.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <asm/cpu_mf.h> | ||
13 | 17 | ||
14 | /* Per-CPU flags for PMU states */ | 18 | /* Per-CPU flags for PMU states */ |
15 | #define PMU_F_RESERVED 0x1000 | 19 | #define PMU_F_RESERVED 0x1000 |
16 | #define PMU_F_ENABLED 0x2000 | 20 | #define PMU_F_ENABLED 0x2000 |
21 | #define PMU_F_IN_USE 0x4000 | ||
22 | #define PMU_F_ERR_IBE 0x0100 | ||
23 | #define PMU_F_ERR_LSDA 0x0200 | ||
24 | #define PMU_F_ERR_MASK (PMU_F_ERR_IBE|PMU_F_ERR_LSDA) | ||
25 | |||
26 | /* Perf defintions for PMU event attributes in sysfs */ | ||
27 | extern __init const struct attribute_group **cpumf_cf_event_group(void); | ||
28 | extern ssize_t cpumf_events_sysfs_show(struct device *dev, | ||
29 | struct device_attribute *attr, | ||
30 | char *page); | ||
31 | #define EVENT_VAR(_cat, _name) event_attr_##_cat##_##_name | ||
32 | #define EVENT_PTR(_cat, _name) (&EVENT_VAR(_cat, _name).attr.attr) | ||
33 | |||
34 | #define CPUMF_EVENT_ATTR(cat, name, id) \ | ||
35 | PMU_EVENT_ATTR(name, EVENT_VAR(cat, name), id, cpumf_events_sysfs_show) | ||
36 | #define CPUMF_EVENT_PTR(cat, name) EVENT_PTR(cat, name) | ||
17 | 37 | ||
18 | #ifdef CONFIG_64BIT | ||
19 | 38 | ||
20 | /* Perf callbacks */ | 39 | /* Perf callbacks */ |
21 | struct pt_regs; | 40 | struct pt_regs; |
@@ -23,4 +42,55 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs); | |||
23 | extern unsigned long perf_misc_flags(struct pt_regs *regs); | 42 | extern unsigned long perf_misc_flags(struct pt_regs *regs); |
24 | #define perf_misc_flags(regs) perf_misc_flags(regs) | 43 | #define perf_misc_flags(regs) perf_misc_flags(regs) |
25 | 44 | ||
45 | /* Perf pt_regs extension for sample-data-entry indicators */ | ||
46 | struct perf_sf_sde_regs { | ||
47 | unsigned char in_guest:1; /* guest sample */ | ||
48 | unsigned long reserved:63; /* reserved */ | ||
49 | }; | ||
50 | |||
51 | /* Perf PMU definitions for the counter facility */ | ||
52 | #define PERF_CPUM_CF_MAX_CTR 256 | ||
53 | |||
54 | /* Perf PMU definitions for the sampling facility */ | ||
55 | #define PERF_CPUM_SF_MAX_CTR 2 | ||
56 | #define PERF_EVENT_CPUM_SF 0xB0000UL /* Event: Basic-sampling */ | ||
57 | #define PERF_EVENT_CPUM_SF_DIAG 0xBD000UL /* Event: Combined-sampling */ | ||
58 | #define PERF_CPUM_SF_BASIC_MODE 0x0001 /* Basic-sampling flag */ | ||
59 | #define PERF_CPUM_SF_DIAG_MODE 0x0002 /* Diagnostic-sampling flag */ | ||
60 | #define PERF_CPUM_SF_MODE_MASK (PERF_CPUM_SF_BASIC_MODE| \ | ||
61 | PERF_CPUM_SF_DIAG_MODE) | ||
62 | #define PERF_CPUM_SF_FULL_BLOCKS 0x0004 /* Process full SDBs only */ | ||
63 | |||
64 | #define REG_NONE 0 | ||
65 | #define REG_OVERFLOW 1 | ||
66 | #define OVERFLOW_REG(hwc) ((hwc)->extra_reg.config) | ||
67 | #define SFB_ALLOC_REG(hwc) ((hwc)->extra_reg.alloc) | ||
68 | #define RAWSAMPLE_REG(hwc) ((hwc)->config) | ||
69 | #define TEAR_REG(hwc) ((hwc)->last_tag) | ||
70 | #define SAMPL_RATE(hwc) ((hwc)->event_base) | ||
71 | #define SAMPL_FLAGS(hwc) ((hwc)->config_base) | ||
72 | #define SAMPL_DIAG_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_DIAG_MODE) | ||
73 | #define SDB_FULL_BLOCKS(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FULL_BLOCKS) | ||
74 | |||
75 | /* Structure for sampling data entries to be passed as perf raw sample data | ||
76 | * to user space. Note that raw sample data must be aligned and, thus, might | ||
77 | * be padded with zeros. | ||
78 | */ | ||
79 | struct sf_raw_sample { | ||
80 | #define SF_RAW_SAMPLE_BASIC PERF_CPUM_SF_BASIC_MODE | ||
81 | #define SF_RAW_SAMPLE_DIAG PERF_CPUM_SF_DIAG_MODE | ||
82 | u64 format; | ||
83 | u32 size; /* Size of sf_raw_sample */ | ||
84 | u16 bsdes; /* Basic-sampling data entry size */ | ||
85 | u16 dsdes; /* Diagnostic-sampling data entry size */ | ||
86 | struct hws_basic_entry basic; /* Basic-sampling data entry */ | ||
87 | struct hws_diag_entry diag; /* Diagnostic-sampling data entry */ | ||
88 | u8 padding[]; /* Padding to next multiple of 8 */ | ||
89 | } __packed; | ||
90 | |||
91 | /* Perf hardware reserve and release functions */ | ||
92 | int perf_reserve_sampling(void); | ||
93 | void perf_release_sampling(void); | ||
94 | |||
26 | #endif /* CONFIG_64BIT */ | 95 | #endif /* CONFIG_64BIT */ |
96 | #endif /* _ASM_S390_PERF_EVENT_H */ | ||
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 57d0d7e794b1..d786c634e052 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h | |||
@@ -336,7 +336,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, | |||
336 | #define QDIO_FLAG_CLEANUP_USING_HALT 0x02 | 336 | #define QDIO_FLAG_CLEANUP_USING_HALT 0x02 |
337 | 337 | ||
338 | /** | 338 | /** |
339 | * struct qdio_initialize - qdio initalization data | 339 | * struct qdio_initialize - qdio initialization data |
340 | * @cdev: associated ccw device | 340 | * @cdev: associated ccw device |
341 | * @q_format: queue format | 341 | * @q_format: queue format |
342 | * @adapter_name: name for the adapter | 342 | * @adapter_name: name for the adapter |
@@ -378,6 +378,34 @@ struct qdio_initialize { | |||
378 | struct qdio_outbuf_state *output_sbal_state_array; | 378 | struct qdio_outbuf_state *output_sbal_state_array; |
379 | }; | 379 | }; |
380 | 380 | ||
381 | /** | ||
382 | * enum qdio_brinfo_entry_type - type of address entry for qdio_brinfo_desc() | ||
383 | * @l3_ipv6_addr: entry contains IPv6 address | ||
384 | * @l3_ipv4_addr: entry contains IPv4 address | ||
385 | * @l2_addr_lnid: entry contains MAC address and VLAN ID | ||
386 | */ | ||
387 | enum qdio_brinfo_entry_type {l3_ipv6_addr, l3_ipv4_addr, l2_addr_lnid}; | ||
388 | |||
389 | /** | ||
390 | * struct qdio_brinfo_entry_XXX - Address entry for qdio_brinfo_desc() | ||
391 | * @nit: Network interface token | ||
392 | * @addr: Address of one of the three types | ||
393 | * | ||
394 | * The struct is passed to the callback function by qdio_brinfo_desc() | ||
395 | */ | ||
396 | struct qdio_brinfo_entry_l3_ipv6 { | ||
397 | u64 nit; | ||
398 | struct { unsigned char _s6_addr[16]; } addr; | ||
399 | } __packed; | ||
400 | struct qdio_brinfo_entry_l3_ipv4 { | ||
401 | u64 nit; | ||
402 | struct { uint32_t _s_addr; } addr; | ||
403 | } __packed; | ||
404 | struct qdio_brinfo_entry_l2 { | ||
405 | u64 nit; | ||
406 | struct { u8 mac[6]; u16 lnid; } addr_lnid; | ||
407 | } __packed; | ||
408 | |||
381 | #define QDIO_STATE_INACTIVE 0x00000002 /* after qdio_cleanup */ | 409 | #define QDIO_STATE_INACTIVE 0x00000002 /* after qdio_cleanup */ |
382 | #define QDIO_STATE_ESTABLISHED 0x00000004 /* after qdio_establish */ | 410 | #define QDIO_STATE_ESTABLISHED 0x00000004 /* after qdio_establish */ |
383 | #define QDIO_STATE_ACTIVE 0x00000008 /* after qdio_activate */ | 411 | #define QDIO_STATE_ACTIVE 0x00000008 /* after qdio_activate */ |
@@ -399,5 +427,10 @@ extern int qdio_get_next_buffers(struct ccw_device *, int, int *, int *); | |||
399 | extern int qdio_shutdown(struct ccw_device *, int); | 427 | extern int qdio_shutdown(struct ccw_device *, int); |
400 | extern int qdio_free(struct ccw_device *); | 428 | extern int qdio_free(struct ccw_device *); |
401 | extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *); | 429 | extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *); |
430 | extern int qdio_pnso_brinfo(struct subchannel_id schid, | ||
431 | int cnc, u16 *response, | ||
432 | void (*cb)(void *priv, enum qdio_brinfo_entry_type type, | ||
433 | void *entry), | ||
434 | void *priv); | ||
402 | 435 | ||
403 | #endif /* __QDIO_H__ */ | 436 | #endif /* __QDIO_H__ */ |
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 2f390956c7c1..220e171413f8 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h | |||
@@ -52,8 +52,8 @@ int sclp_chp_configure(struct chp_id chpid); | |||
52 | int sclp_chp_deconfigure(struct chp_id chpid); | 52 | int sclp_chp_deconfigure(struct chp_id chpid); |
53 | int sclp_chp_read_info(struct sclp_chp_info *info); | 53 | int sclp_chp_read_info(struct sclp_chp_info *info); |
54 | void sclp_get_ipl_info(struct sclp_ipl_info *info); | 54 | void sclp_get_ipl_info(struct sclp_ipl_info *info); |
55 | bool sclp_has_linemode(void); | 55 | bool __init sclp_has_linemode(void); |
56 | bool sclp_has_vt220(void); | 56 | bool __init sclp_has_vt220(void); |
57 | int sclp_pci_configure(u32 fid); | 57 | int sclp_pci_configure(u32 fid); |
58 | int sclp_pci_deconfigure(u32 fid); | 58 | int sclp_pci_deconfigure(u32 fid); |
59 | int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); | 59 | int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); |
diff --git a/arch/s390/include/uapi/asm/zcrypt.h b/arch/s390/include/uapi/asm/zcrypt.h index e83fc116f5bf..f2b18eacaca8 100644 --- a/arch/s390/include/uapi/asm/zcrypt.h +++ b/arch/s390/include/uapi/asm/zcrypt.h | |||
@@ -154,6 +154,67 @@ struct ica_xcRB { | |||
154 | unsigned short priority_window; | 154 | unsigned short priority_window; |
155 | unsigned int status; | 155 | unsigned int status; |
156 | } __attribute__((packed)); | 156 | } __attribute__((packed)); |
157 | |||
158 | /** | ||
159 | * struct ep11_cprb - EP11 connectivity programming request block | ||
160 | * @cprb_len: CPRB header length [0x0020] | ||
161 | * @cprb_ver_id: CPRB version id. [0x04] | ||
162 | * @pad_000: Alignment pad bytes | ||
163 | * @flags: Admin cmd [0x80] or functional cmd [0x00] | ||
164 | * @func_id: Function id / subtype [0x5434] | ||
165 | * @source_id: Source id [originator id] | ||
166 | * @target_id: Target id [usage/ctrl domain id] | ||
167 | * @ret_code: Return code | ||
168 | * @reserved1: Reserved | ||
169 | * @reserved2: Reserved | ||
170 | * @payload_len: Payload length | ||
171 | */ | ||
172 | struct ep11_cprb { | ||
173 | uint16_t cprb_len; | ||
174 | unsigned char cprb_ver_id; | ||
175 | unsigned char pad_000[2]; | ||
176 | unsigned char flags; | ||
177 | unsigned char func_id[2]; | ||
178 | uint32_t source_id; | ||
179 | uint32_t target_id; | ||
180 | uint32_t ret_code; | ||
181 | uint32_t reserved1; | ||
182 | uint32_t reserved2; | ||
183 | uint32_t payload_len; | ||
184 | } __attribute__((packed)); | ||
185 | |||
186 | /** | ||
187 | * struct ep11_target_dev - EP11 target device list | ||
188 | * @ap_id: AP device id | ||
189 | * @dom_id: Usage domain id | ||
190 | */ | ||
191 | struct ep11_target_dev { | ||
192 | uint16_t ap_id; | ||
193 | uint16_t dom_id; | ||
194 | }; | ||
195 | |||
196 | /** | ||
197 | * struct ep11_urb - EP11 user request block | ||
198 | * @targets_num: Number of target adapters | ||
199 | * @targets: Addr to target adapter list | ||
200 | * @weight: Level of request priority | ||
201 | * @req_no: Request id/number | ||
202 | * @req_len: Request length | ||
203 | * @req: Addr to request block | ||
204 | * @resp_len: Response length | ||
205 | * @resp: Addr to response block | ||
206 | */ | ||
207 | struct ep11_urb { | ||
208 | uint16_t targets_num; | ||
209 | uint64_t targets; | ||
210 | uint64_t weight; | ||
211 | uint64_t req_no; | ||
212 | uint64_t req_len; | ||
213 | uint64_t req; | ||
214 | uint64_t resp_len; | ||
215 | uint64_t resp; | ||
216 | } __attribute__((packed)); | ||
217 | |||
157 | #define AUTOSELECT ((unsigned int)0xFFFFFFFF) | 218 | #define AUTOSELECT ((unsigned int)0xFFFFFFFF) |
158 | 219 | ||
159 | #define ZCRYPT_IOCTL_MAGIC 'z' | 220 | #define ZCRYPT_IOCTL_MAGIC 'z' |
@@ -183,6 +244,9 @@ struct ica_xcRB { | |||
183 | * ZSECSENDCPRB | 244 | * ZSECSENDCPRB |
184 | * Send an arbitrary CPRB to a crypto card. | 245 | * Send an arbitrary CPRB to a crypto card. |
185 | * | 246 | * |
247 | * ZSENDEP11CPRB | ||
248 | * Send an arbitrary EP11 CPRB to an EP11 coprocessor crypto card. | ||
249 | * | ||
186 | * Z90STAT_STATUS_MASK | 250 | * Z90STAT_STATUS_MASK |
187 | * Return an 64 element array of unsigned chars for the status of | 251 | * Return an 64 element array of unsigned chars for the status of |
188 | * all devices. | 252 | * all devices. |
@@ -256,6 +320,7 @@ struct ica_xcRB { | |||
256 | #define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x05, 0) | 320 | #define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x05, 0) |
257 | #define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x06, 0) | 321 | #define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x06, 0) |
258 | #define ZSECSENDCPRB _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x81, 0) | 322 | #define ZSECSENDCPRB _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x81, 0) |
323 | #define ZSENDEP11CPRB _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x04, 0) | ||
259 | 324 | ||
260 | /* New status calls */ | 325 | /* New status calls */ |
261 | #define Z90STAT_TOTALCOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x40, int) | 326 | #define Z90STAT_TOTALCOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x40, int) |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 2403303cfed7..1b3ac09c11b6 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -60,7 +60,8 @@ obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o | |||
60 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 60 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
61 | 61 | ||
62 | ifdef CONFIG_64BIT | 62 | ifdef CONFIG_64BIT |
63 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o | 63 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o \ |
64 | perf_cpum_cf_events.o | ||
64 | obj-y += runtime_instr.o cache.o | 65 | obj-y += runtime_instr.o cache.o |
65 | endif | 66 | endif |
66 | 67 | ||
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 95e7ba0fbb7e..8b84bc373e94 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c | |||
@@ -412,8 +412,9 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
412 | regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE; | 412 | regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE; |
413 | } else { | 413 | } else { |
414 | regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE; | 414 | regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE; |
415 | err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, | 415 | if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, |
416 | (u16 __force __user *)(frame->retcode)); | 416 | (u16 __force __user *)(frame->retcode))) |
417 | goto give_sigsegv; | ||
417 | } | 418 | } |
418 | 419 | ||
419 | /* Set up backchain. */ | 420 | /* Set up backchain. */ |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index e5b43c97a834..384e609b4711 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -74,7 +74,7 @@ _TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ | |||
74 | .endm | 74 | .endm |
75 | 75 | ||
76 | .macro LPP newpp | 76 | .macro LPP newpp |
77 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 77 | #if IS_ENABLED(CONFIG_KVM) |
78 | tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_LPP | 78 | tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_LPP |
79 | jz .+8 | 79 | jz .+8 |
80 | .insn s,0xb2800000,\newpp | 80 | .insn s,0xb2800000,\newpp |
@@ -82,7 +82,7 @@ _TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ | |||
82 | .endm | 82 | .endm |
83 | 83 | ||
84 | .macro HANDLE_SIE_INTERCEPT scratch,reason | 84 | .macro HANDLE_SIE_INTERCEPT scratch,reason |
85 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 85 | #if IS_ENABLED(CONFIG_KVM) |
86 | tmhh %r8,0x0001 # interrupting from user ? | 86 | tmhh %r8,0x0001 # interrupting from user ? |
87 | jnz .+62 | 87 | jnz .+62 |
88 | lgr \scratch,%r9 | 88 | lgr \scratch,%r9 |
@@ -946,7 +946,7 @@ cleanup_idle_insn: | |||
946 | .quad __critical_end - __critical_start | 946 | .quad __critical_end - __critical_start |
947 | 947 | ||
948 | 948 | ||
949 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 949 | #if IS_ENABLED(CONFIG_KVM) |
950 | /* | 950 | /* |
951 | * sie64a calling convention: | 951 | * sie64a calling convention: |
952 | * %r2 pointer to sie control block | 952 | * %r2 pointer to sie control block |
@@ -975,7 +975,7 @@ sie_done: | |||
975 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 975 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
976 | # some program checks are suppressing. C code (e.g. do_protection_exception) | 976 | # some program checks are suppressing. C code (e.g. do_protection_exception) |
977 | # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other | 977 | # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other |
978 | # instructions beween sie64a and sie_done should not cause program | 978 | # instructions between sie64a and sie_done should not cause program |
979 | # interrupts. So lets use a nop (47 00 00 00) as a landing pad. | 979 | # interrupts. So lets use a nop (47 00 00 00) as a landing pad. |
980 | # See also HANDLE_SIE_INTERCEPT | 980 | # See also HANDLE_SIE_INTERCEPT |
981 | rewind_pad: | 981 | rewind_pad: |
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 1105502bf6e9..f51214c04858 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c | |||
@@ -680,6 +680,7 @@ static int __init cpumf_pmu_init(void) | |||
680 | goto out; | 680 | goto out; |
681 | } | 681 | } |
682 | 682 | ||
683 | cpumf_pmu.attr_groups = cpumf_cf_event_group(); | ||
683 | rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW); | 684 | rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW); |
684 | if (rc) { | 685 | if (rc) { |
685 | pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc); | 686 | pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc); |
diff --git a/arch/s390/kernel/perf_cpum_cf_events.c b/arch/s390/kernel/perf_cpum_cf_events.c new file mode 100644 index 000000000000..4554a4bae39e --- /dev/null +++ b/arch/s390/kernel/perf_cpum_cf_events.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | * Perf PMU sysfs events attributes for available CPU-measurement counters | ||
3 | * | ||
4 | */ | ||
5 | |||
6 | #include <linux/slab.h> | ||
7 | #include <linux/perf_event.h> | ||
8 | |||
9 | |||
10 | /* BEGIN: CPUM_CF COUNTER DEFINITIONS =================================== */ | ||
11 | |||
12 | CPUMF_EVENT_ATTR(cf, CPU_CYCLES, 0x0000); | ||
13 | CPUMF_EVENT_ATTR(cf, INSTRUCTIONS, 0x0001); | ||
14 | CPUMF_EVENT_ATTR(cf, L1I_DIR_WRITES, 0x0002); | ||
15 | CPUMF_EVENT_ATTR(cf, L1I_PENALTY_CYCLES, 0x0003); | ||
16 | CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_CPU_CYCLES, 0x0020); | ||
17 | CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_INSTRUCTIONS, 0x0021); | ||
18 | CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1I_DIR_WRITES, 0x0022); | ||
19 | CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1I_PENALTY_CYCLES, 0x0023); | ||
20 | CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1D_DIR_WRITES, 0x0024); | ||
21 | CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1D_PENALTY_CYCLES, 0x0025); | ||
22 | CPUMF_EVENT_ATTR(cf, L1D_DIR_WRITES, 0x0004); | ||
23 | CPUMF_EVENT_ATTR(cf, L1D_PENALTY_CYCLES, 0x0005); | ||
24 | CPUMF_EVENT_ATTR(cf, PRNG_FUNCTIONS, 0x0040); | ||
25 | CPUMF_EVENT_ATTR(cf, PRNG_CYCLES, 0x0041); | ||
26 | CPUMF_EVENT_ATTR(cf, PRNG_BLOCKED_FUNCTIONS, 0x0042); | ||
27 | CPUMF_EVENT_ATTR(cf, PRNG_BLOCKED_CYCLES, 0x0043); | ||
28 | CPUMF_EVENT_ATTR(cf, SHA_FUNCTIONS, 0x0044); | ||
29 | CPUMF_EVENT_ATTR(cf, SHA_CYCLES, 0x0045); | ||
30 | CPUMF_EVENT_ATTR(cf, SHA_BLOCKED_FUNCTIONS, 0x0046); | ||
31 | CPUMF_EVENT_ATTR(cf, SHA_BLOCKED_CYCLES, 0x0047); | ||
32 | CPUMF_EVENT_ATTR(cf, DEA_FUNCTIONS, 0x0048); | ||
33 | CPUMF_EVENT_ATTR(cf, DEA_CYCLES, 0x0049); | ||
34 | CPUMF_EVENT_ATTR(cf, DEA_BLOCKED_FUNCTIONS, 0x004a); | ||
35 | CPUMF_EVENT_ATTR(cf, DEA_BLOCKED_CYCLES, 0x004b); | ||
36 | CPUMF_EVENT_ATTR(cf, AES_FUNCTIONS, 0x004c); | ||
37 | CPUMF_EVENT_ATTR(cf, AES_CYCLES, 0x004d); | ||
38 | CPUMF_EVENT_ATTR(cf, AES_BLOCKED_FUNCTIONS, 0x004e); | ||
39 | CPUMF_EVENT_ATTR(cf, AES_BLOCKED_CYCLES, 0x004f); | ||
40 | CPUMF_EVENT_ATTR(cf_z10, L1I_L2_SOURCED_WRITES, 0x0080); | ||
41 | CPUMF_EVENT_ATTR(cf_z10, L1D_L2_SOURCED_WRITES, 0x0081); | ||
42 | CPUMF_EVENT_ATTR(cf_z10, L1I_L3_LOCAL_WRITES, 0x0082); | ||
43 | CPUMF_EVENT_ATTR(cf_z10, L1D_L3_LOCAL_WRITES, 0x0083); | ||
44 | CPUMF_EVENT_ATTR(cf_z10, L1I_L3_REMOTE_WRITES, 0x0084); | ||
45 | CPUMF_EVENT_ATTR(cf_z10, L1D_L3_REMOTE_WRITES, 0x0085); | ||
46 | CPUMF_EVENT_ATTR(cf_z10, L1D_LMEM_SOURCED_WRITES, 0x0086); | ||
47 | CPUMF_EVENT_ATTR(cf_z10, L1I_LMEM_SOURCED_WRITES, 0x0087); | ||
48 | CPUMF_EVENT_ATTR(cf_z10, L1D_RO_EXCL_WRITES, 0x0088); | ||
49 | CPUMF_EVENT_ATTR(cf_z10, L1I_CACHELINE_INVALIDATES, 0x0089); | ||
50 | CPUMF_EVENT_ATTR(cf_z10, ITLB1_WRITES, 0x008a); | ||
51 | CPUMF_EVENT_ATTR(cf_z10, DTLB1_WRITES, 0x008b); | ||
52 | CPUMF_EVENT_ATTR(cf_z10, TLB2_PTE_WRITES, 0x008c); | ||
53 | CPUMF_EVENT_ATTR(cf_z10, TLB2_CRSTE_WRITES, 0x008d); | ||
54 | CPUMF_EVENT_ATTR(cf_z10, TLB2_CRSTE_HPAGE_WRITES, 0x008e); | ||
55 | CPUMF_EVENT_ATTR(cf_z10, ITLB1_MISSES, 0x0091); | ||
56 | CPUMF_EVENT_ATTR(cf_z10, DTLB1_MISSES, 0x0092); | ||
57 | CPUMF_EVENT_ATTR(cf_z10, L2C_STORES_SENT, 0x0093); | ||
58 | CPUMF_EVENT_ATTR(cf_z196, L1D_L2_SOURCED_WRITES, 0x0080); | ||
59 | CPUMF_EVENT_ATTR(cf_z196, L1I_L2_SOURCED_WRITES, 0x0081); | ||
60 | CPUMF_EVENT_ATTR(cf_z196, DTLB1_MISSES, 0x0082); | ||
61 | CPUMF_EVENT_ATTR(cf_z196, ITLB1_MISSES, 0x0083); | ||
62 | CPUMF_EVENT_ATTR(cf_z196, L2C_STORES_SENT, 0x0085); | ||
63 | CPUMF_EVENT_ATTR(cf_z196, L1D_OFFBOOK_L3_SOURCED_WRITES, 0x0086); | ||
64 | CPUMF_EVENT_ATTR(cf_z196, L1D_ONBOOK_L4_SOURCED_WRITES, 0x0087); | ||
65 | CPUMF_EVENT_ATTR(cf_z196, L1I_ONBOOK_L4_SOURCED_WRITES, 0x0088); | ||
66 | CPUMF_EVENT_ATTR(cf_z196, L1D_RO_EXCL_WRITES, 0x0089); | ||
67 | CPUMF_EVENT_ATTR(cf_z196, L1D_OFFBOOK_L4_SOURCED_WRITES, 0x008a); | ||
68 | CPUMF_EVENT_ATTR(cf_z196, L1I_OFFBOOK_L4_SOURCED_WRITES, 0x008b); | ||
69 | CPUMF_EVENT_ATTR(cf_z196, DTLB1_HPAGE_WRITES, 0x008c); | ||
70 | CPUMF_EVENT_ATTR(cf_z196, L1D_LMEM_SOURCED_WRITES, 0x008d); | ||
71 | CPUMF_EVENT_ATTR(cf_z196, L1I_LMEM_SOURCED_WRITES, 0x008e); | ||
72 | CPUMF_EVENT_ATTR(cf_z196, L1I_OFFBOOK_L3_SOURCED_WRITES, 0x008f); | ||
73 | CPUMF_EVENT_ATTR(cf_z196, DTLB1_WRITES, 0x0090); | ||
74 | CPUMF_EVENT_ATTR(cf_z196, ITLB1_WRITES, 0x0091); | ||
75 | CPUMF_EVENT_ATTR(cf_z196, TLB2_PTE_WRITES, 0x0092); | ||
76 | CPUMF_EVENT_ATTR(cf_z196, TLB2_CRSTE_HPAGE_WRITES, 0x0093); | ||
77 | CPUMF_EVENT_ATTR(cf_z196, TLB2_CRSTE_WRITES, 0x0094); | ||
78 | CPUMF_EVENT_ATTR(cf_z196, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0096); | ||
79 | CPUMF_EVENT_ATTR(cf_z196, L1D_OFFCHIP_L3_SOURCED_WRITES, 0x0098); | ||
80 | CPUMF_EVENT_ATTR(cf_z196, L1I_ONCHIP_L3_SOURCED_WRITES, 0x0099); | ||
81 | CPUMF_EVENT_ATTR(cf_z196, L1I_OFFCHIP_L3_SOURCED_WRITES, 0x009b); | ||
82 | CPUMF_EVENT_ATTR(cf_zec12, DTLB1_MISSES, 0x0080); | ||
83 | CPUMF_EVENT_ATTR(cf_zec12, ITLB1_MISSES, 0x0081); | ||
84 | CPUMF_EVENT_ATTR(cf_zec12, L1D_L2I_SOURCED_WRITES, 0x0082); | ||
85 | CPUMF_EVENT_ATTR(cf_zec12, L1I_L2I_SOURCED_WRITES, 0x0083); | ||
86 | CPUMF_EVENT_ATTR(cf_zec12, L1D_L2D_SOURCED_WRITES, 0x0084); | ||
87 | CPUMF_EVENT_ATTR(cf_zec12, DTLB1_WRITES, 0x0085); | ||
88 | CPUMF_EVENT_ATTR(cf_zec12, L1D_LMEM_SOURCED_WRITES, 0x0087); | ||
89 | CPUMF_EVENT_ATTR(cf_zec12, L1I_LMEM_SOURCED_WRITES, 0x0089); | ||
90 | CPUMF_EVENT_ATTR(cf_zec12, L1D_RO_EXCL_WRITES, 0x008a); | ||
91 | CPUMF_EVENT_ATTR(cf_zec12, DTLB1_HPAGE_WRITES, 0x008b); | ||
92 | CPUMF_EVENT_ATTR(cf_zec12, ITLB1_WRITES, 0x008c); | ||
93 | CPUMF_EVENT_ATTR(cf_zec12, TLB2_PTE_WRITES, 0x008d); | ||
94 | CPUMF_EVENT_ATTR(cf_zec12, TLB2_CRSTE_HPAGE_WRITES, 0x008e); | ||
95 | CPUMF_EVENT_ATTR(cf_zec12, TLB2_CRSTE_WRITES, 0x008f); | ||
96 | CPUMF_EVENT_ATTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0090); | ||
97 | CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES, 0x0091); | ||
98 | CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES, 0x0092); | ||
99 | CPUMF_EVENT_ATTR(cf_zec12, L1D_ONBOOK_L4_SOURCED_WRITES, 0x0093); | ||
100 | CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L4_SOURCED_WRITES, 0x0094); | ||
101 | CPUMF_EVENT_ATTR(cf_zec12, TX_NC_TEND, 0x0095); | ||
102 | CPUMF_EVENT_ATTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES_IV, 0x0096); | ||
103 | CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES_IV, 0x0097); | ||
104 | CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES_IV, 0x0098); | ||
105 | CPUMF_EVENT_ATTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES, 0x0099); | ||
106 | CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES, 0x009a); | ||
107 | CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES, 0x009b); | ||
108 | CPUMF_EVENT_ATTR(cf_zec12, L1I_ONBOOK_L4_SOURCED_WRITES, 0x009c); | ||
109 | CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L4_SOURCED_WRITES, 0x009d); | ||
110 | CPUMF_EVENT_ATTR(cf_zec12, TX_C_TEND, 0x009e); | ||
111 | CPUMF_EVENT_ATTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES_IV, 0x009f); | ||
112 | CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES_IV, 0x00a0); | ||
113 | CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES_IV, 0x00a1); | ||
114 | CPUMF_EVENT_ATTR(cf_zec12, TX_NC_TABORT, 0x00b1); | ||
115 | CPUMF_EVENT_ATTR(cf_zec12, TX_C_TABORT_NO_SPECIAL, 0x00b2); | ||
116 | CPUMF_EVENT_ATTR(cf_zec12, TX_C_TABORT_SPECIAL, 0x00b3); | ||
117 | |||
118 | static struct attribute *cpumcf_pmu_event_attr[] = { | ||
119 | CPUMF_EVENT_PTR(cf, CPU_CYCLES), | ||
120 | CPUMF_EVENT_PTR(cf, INSTRUCTIONS), | ||
121 | CPUMF_EVENT_PTR(cf, L1I_DIR_WRITES), | ||
122 | CPUMF_EVENT_PTR(cf, L1I_PENALTY_CYCLES), | ||
123 | CPUMF_EVENT_PTR(cf, PROBLEM_STATE_CPU_CYCLES), | ||
124 | CPUMF_EVENT_PTR(cf, PROBLEM_STATE_INSTRUCTIONS), | ||
125 | CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1I_DIR_WRITES), | ||
126 | CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1I_PENALTY_CYCLES), | ||
127 | CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1D_DIR_WRITES), | ||
128 | CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1D_PENALTY_CYCLES), | ||
129 | CPUMF_EVENT_PTR(cf, L1D_DIR_WRITES), | ||
130 | CPUMF_EVENT_PTR(cf, L1D_PENALTY_CYCLES), | ||
131 | CPUMF_EVENT_PTR(cf, PRNG_FUNCTIONS), | ||
132 | CPUMF_EVENT_PTR(cf, PRNG_CYCLES), | ||
133 | CPUMF_EVENT_PTR(cf, PRNG_BLOCKED_FUNCTIONS), | ||
134 | CPUMF_EVENT_PTR(cf, PRNG_BLOCKED_CYCLES), | ||
135 | CPUMF_EVENT_PTR(cf, SHA_FUNCTIONS), | ||
136 | CPUMF_EVENT_PTR(cf, SHA_CYCLES), | ||
137 | CPUMF_EVENT_PTR(cf, SHA_BLOCKED_FUNCTIONS), | ||
138 | CPUMF_EVENT_PTR(cf, SHA_BLOCKED_CYCLES), | ||
139 | CPUMF_EVENT_PTR(cf, DEA_FUNCTIONS), | ||
140 | CPUMF_EVENT_PTR(cf, DEA_CYCLES), | ||
141 | CPUMF_EVENT_PTR(cf, DEA_BLOCKED_FUNCTIONS), | ||
142 | CPUMF_EVENT_PTR(cf, DEA_BLOCKED_CYCLES), | ||
143 | CPUMF_EVENT_PTR(cf, AES_FUNCTIONS), | ||
144 | CPUMF_EVENT_PTR(cf, AES_CYCLES), | ||
145 | CPUMF_EVENT_PTR(cf, AES_BLOCKED_FUNCTIONS), | ||
146 | CPUMF_EVENT_PTR(cf, AES_BLOCKED_CYCLES), | ||
147 | NULL, | ||
148 | }; | ||
149 | |||
150 | static struct attribute *cpumcf_z10_pmu_event_attr[] __initdata = { | ||
151 | CPUMF_EVENT_PTR(cf_z10, L1I_L2_SOURCED_WRITES), | ||
152 | CPUMF_EVENT_PTR(cf_z10, L1D_L2_SOURCED_WRITES), | ||
153 | CPUMF_EVENT_PTR(cf_z10, L1I_L3_LOCAL_WRITES), | ||
154 | CPUMF_EVENT_PTR(cf_z10, L1D_L3_LOCAL_WRITES), | ||
155 | CPUMF_EVENT_PTR(cf_z10, L1I_L3_REMOTE_WRITES), | ||
156 | CPUMF_EVENT_PTR(cf_z10, L1D_L3_REMOTE_WRITES), | ||
157 | CPUMF_EVENT_PTR(cf_z10, L1D_LMEM_SOURCED_WRITES), | ||
158 | CPUMF_EVENT_PTR(cf_z10, L1I_LMEM_SOURCED_WRITES), | ||
159 | CPUMF_EVENT_PTR(cf_z10, L1D_RO_EXCL_WRITES), | ||
160 | CPUMF_EVENT_PTR(cf_z10, L1I_CACHELINE_INVALIDATES), | ||
161 | CPUMF_EVENT_PTR(cf_z10, ITLB1_WRITES), | ||
162 | CPUMF_EVENT_PTR(cf_z10, DTLB1_WRITES), | ||
163 | CPUMF_EVENT_PTR(cf_z10, TLB2_PTE_WRITES), | ||
164 | CPUMF_EVENT_PTR(cf_z10, TLB2_CRSTE_WRITES), | ||
165 | CPUMF_EVENT_PTR(cf_z10, TLB2_CRSTE_HPAGE_WRITES), | ||
166 | CPUMF_EVENT_PTR(cf_z10, ITLB1_MISSES), | ||
167 | CPUMF_EVENT_PTR(cf_z10, DTLB1_MISSES), | ||
168 | CPUMF_EVENT_PTR(cf_z10, L2C_STORES_SENT), | ||
169 | NULL, | ||
170 | }; | ||
171 | |||
172 | static struct attribute *cpumcf_z196_pmu_event_attr[] __initdata = { | ||
173 | CPUMF_EVENT_PTR(cf_z196, L1D_L2_SOURCED_WRITES), | ||
174 | CPUMF_EVENT_PTR(cf_z196, L1I_L2_SOURCED_WRITES), | ||
175 | CPUMF_EVENT_PTR(cf_z196, DTLB1_MISSES), | ||
176 | CPUMF_EVENT_PTR(cf_z196, ITLB1_MISSES), | ||
177 | CPUMF_EVENT_PTR(cf_z196, L2C_STORES_SENT), | ||
178 | CPUMF_EVENT_PTR(cf_z196, L1D_OFFBOOK_L3_SOURCED_WRITES), | ||
179 | CPUMF_EVENT_PTR(cf_z196, L1D_ONBOOK_L4_SOURCED_WRITES), | ||
180 | CPUMF_EVENT_PTR(cf_z196, L1I_ONBOOK_L4_SOURCED_WRITES), | ||
181 | CPUMF_EVENT_PTR(cf_z196, L1D_RO_EXCL_WRITES), | ||
182 | CPUMF_EVENT_PTR(cf_z196, L1D_OFFBOOK_L4_SOURCED_WRITES), | ||
183 | CPUMF_EVENT_PTR(cf_z196, L1I_OFFBOOK_L4_SOURCED_WRITES), | ||
184 | CPUMF_EVENT_PTR(cf_z196, DTLB1_HPAGE_WRITES), | ||
185 | CPUMF_EVENT_PTR(cf_z196, L1D_LMEM_SOURCED_WRITES), | ||
186 | CPUMF_EVENT_PTR(cf_z196, L1I_LMEM_SOURCED_WRITES), | ||
187 | CPUMF_EVENT_PTR(cf_z196, L1I_OFFBOOK_L3_SOURCED_WRITES), | ||
188 | CPUMF_EVENT_PTR(cf_z196, DTLB1_WRITES), | ||
189 | CPUMF_EVENT_PTR(cf_z196, ITLB1_WRITES), | ||
190 | CPUMF_EVENT_PTR(cf_z196, TLB2_PTE_WRITES), | ||
191 | CPUMF_EVENT_PTR(cf_z196, TLB2_CRSTE_HPAGE_WRITES), | ||
192 | CPUMF_EVENT_PTR(cf_z196, TLB2_CRSTE_WRITES), | ||
193 | CPUMF_EVENT_PTR(cf_z196, L1D_ONCHIP_L3_SOURCED_WRITES), | ||
194 | CPUMF_EVENT_PTR(cf_z196, L1D_OFFCHIP_L3_SOURCED_WRITES), | ||
195 | CPUMF_EVENT_PTR(cf_z196, L1I_ONCHIP_L3_SOURCED_WRITES), | ||
196 | CPUMF_EVENT_PTR(cf_z196, L1I_OFFCHIP_L3_SOURCED_WRITES), | ||
197 | NULL, | ||
198 | }; | ||
199 | |||
200 | static struct attribute *cpumcf_zec12_pmu_event_attr[] __initdata = { | ||
201 | CPUMF_EVENT_PTR(cf_zec12, DTLB1_MISSES), | ||
202 | CPUMF_EVENT_PTR(cf_zec12, ITLB1_MISSES), | ||
203 | CPUMF_EVENT_PTR(cf_zec12, L1D_L2I_SOURCED_WRITES), | ||
204 | CPUMF_EVENT_PTR(cf_zec12, L1I_L2I_SOURCED_WRITES), | ||
205 | CPUMF_EVENT_PTR(cf_zec12, L1D_L2D_SOURCED_WRITES), | ||
206 | CPUMF_EVENT_PTR(cf_zec12, DTLB1_WRITES), | ||
207 | CPUMF_EVENT_PTR(cf_zec12, L1D_LMEM_SOURCED_WRITES), | ||
208 | CPUMF_EVENT_PTR(cf_zec12, L1I_LMEM_SOURCED_WRITES), | ||
209 | CPUMF_EVENT_PTR(cf_zec12, L1D_RO_EXCL_WRITES), | ||
210 | CPUMF_EVENT_PTR(cf_zec12, DTLB1_HPAGE_WRITES), | ||
211 | CPUMF_EVENT_PTR(cf_zec12, ITLB1_WRITES), | ||
212 | CPUMF_EVENT_PTR(cf_zec12, TLB2_PTE_WRITES), | ||
213 | CPUMF_EVENT_PTR(cf_zec12, TLB2_CRSTE_HPAGE_WRITES), | ||
214 | CPUMF_EVENT_PTR(cf_zec12, TLB2_CRSTE_WRITES), | ||
215 | CPUMF_EVENT_PTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES), | ||
216 | CPUMF_EVENT_PTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES), | ||
217 | CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES), | ||
218 | CPUMF_EVENT_PTR(cf_zec12, L1D_ONBOOK_L4_SOURCED_WRITES), | ||
219 | CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L4_SOURCED_WRITES), | ||
220 | CPUMF_EVENT_PTR(cf_zec12, TX_NC_TEND), | ||
221 | CPUMF_EVENT_PTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES_IV), | ||
222 | CPUMF_EVENT_PTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES_IV), | ||
223 | CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES_IV), | ||
224 | CPUMF_EVENT_PTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES), | ||
225 | CPUMF_EVENT_PTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES), | ||
226 | CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES), | ||
227 | CPUMF_EVENT_PTR(cf_zec12, L1I_ONBOOK_L4_SOURCED_WRITES), | ||
228 | CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L4_SOURCED_WRITES), | ||
229 | CPUMF_EVENT_PTR(cf_zec12, TX_C_TEND), | ||
230 | CPUMF_EVENT_PTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES_IV), | ||
231 | CPUMF_EVENT_PTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES_IV), | ||
232 | CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES_IV), | ||
233 | CPUMF_EVENT_PTR(cf_zec12, TX_NC_TABORT), | ||
234 | CPUMF_EVENT_PTR(cf_zec12, TX_C_TABORT_NO_SPECIAL), | ||
235 | CPUMF_EVENT_PTR(cf_zec12, TX_C_TABORT_SPECIAL), | ||
236 | NULL, | ||
237 | }; | ||
238 | |||
239 | /* END: CPUM_CF COUNTER DEFINITIONS ===================================== */ | ||
240 | |||
241 | static struct attribute_group cpumsf_pmu_events_group = { | ||
242 | .name = "events", | ||
243 | .attrs = cpumcf_pmu_event_attr, | ||
244 | }; | ||
245 | |||
246 | PMU_FORMAT_ATTR(event, "config:0-63"); | ||
247 | |||
248 | static struct attribute *cpumsf_pmu_format_attr[] = { | ||
249 | &format_attr_event.attr, | ||
250 | NULL, | ||
251 | }; | ||
252 | |||
253 | static struct attribute_group cpumsf_pmu_format_group = { | ||
254 | .name = "format", | ||
255 | .attrs = cpumsf_pmu_format_attr, | ||
256 | }; | ||
257 | |||
258 | static const struct attribute_group *cpumsf_pmu_attr_groups[] = { | ||
259 | &cpumsf_pmu_events_group, | ||
260 | &cpumsf_pmu_format_group, | ||
261 | NULL, | ||
262 | }; | ||
263 | |||
264 | |||
265 | static __init struct attribute **merge_attr(struct attribute **a, | ||
266 | struct attribute **b) | ||
267 | { | ||
268 | struct attribute **new; | ||
269 | int j, i; | ||
270 | |||
271 | for (j = 0; a[j]; j++) | ||
272 | ; | ||
273 | for (i = 0; b[i]; i++) | ||
274 | j++; | ||
275 | j++; | ||
276 | |||
277 | new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL); | ||
278 | if (!new) | ||
279 | return NULL; | ||
280 | j = 0; | ||
281 | for (i = 0; a[i]; i++) | ||
282 | new[j++] = a[i]; | ||
283 | for (i = 0; b[i]; i++) | ||
284 | new[j++] = b[i]; | ||
285 | new[j] = NULL; | ||
286 | |||
287 | return new; | ||
288 | } | ||
289 | |||
290 | __init const struct attribute_group **cpumf_cf_event_group(void) | ||
291 | { | ||
292 | struct attribute **combined, **model; | ||
293 | struct cpuid cpu_id; | ||
294 | |||
295 | get_cpu_id(&cpu_id); | ||
296 | switch (cpu_id.machine) { | ||
297 | case 0x2097: | ||
298 | case 0x2098: | ||
299 | model = cpumcf_z10_pmu_event_attr; | ||
300 | break; | ||
301 | case 0x2817: | ||
302 | case 0x2818: | ||
303 | model = cpumcf_z196_pmu_event_attr; | ||
304 | break; | ||
305 | case 0x2827: | ||
306 | case 0x2828: | ||
307 | model = cpumcf_zec12_pmu_event_attr; | ||
308 | break; | ||
309 | default: | ||
310 | model = NULL; | ||
311 | break; | ||
312 | }; | ||
313 | |||
314 | if (!model) | ||
315 | goto out; | ||
316 | |||
317 | combined = merge_attr(cpumcf_pmu_event_attr, model); | ||
318 | if (combined) | ||
319 | cpumsf_pmu_events_group.attrs = combined; | ||
320 | out: | ||
321 | return cpumsf_pmu_attr_groups; | ||
322 | } | ||
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c new file mode 100644 index 000000000000..6c0d29827cb6 --- /dev/null +++ b/arch/s390/kernel/perf_cpum_sf.c | |||
@@ -0,0 +1,1641 @@ | |||
1 | /* | ||
2 | * Performance event support for the System z CPU-measurement Sampling Facility | ||
3 | * | ||
4 | * Copyright IBM Corp. 2013 | ||
5 | * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License (version 2 only) | ||
9 | * as published by the Free Software Foundation. | ||
10 | */ | ||
11 | #define KMSG_COMPONENT "cpum_sf" | ||
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/kernel_stat.h> | ||
16 | #include <linux/perf_event.h> | ||
17 | #include <linux/percpu.h> | ||
18 | #include <linux/notifier.h> | ||
19 | #include <linux/export.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <asm/cpu_mf.h> | ||
24 | #include <asm/irq.h> | ||
25 | #include <asm/debug.h> | ||
26 | #include <asm/timex.h> | ||
27 | |||
28 | /* Minimum number of sample-data-block-tables: | ||
29 | * At least one table is required for the sampling buffer structure. | ||
30 | * A single table contains up to 511 pointers to sample-data-blocks. | ||
31 | */ | ||
32 | #define CPUM_SF_MIN_SDBT 1 | ||
33 | |||
34 | /* Number of sample-data-blocks per sample-data-block-table (SDBT): | ||
35 | * A table contains SDB pointers (8 bytes) and one table-link entry | ||
36 | * that points to the origin of the next SDBT. | ||
37 | */ | ||
38 | #define CPUM_SF_SDB_PER_TABLE ((PAGE_SIZE - 8) / 8) | ||
39 | |||
40 | /* Maximum page offset for an SDBT table-link entry: | ||
41 | * If this page offset is reached, a table-link entry to the next SDBT | ||
42 | * must be added. | ||
43 | */ | ||
44 | #define CPUM_SF_SDBT_TL_OFFSET (CPUM_SF_SDB_PER_TABLE * 8) | ||
45 | static inline int require_table_link(const void *sdbt) | ||
46 | { | ||
47 | return ((unsigned long) sdbt & ~PAGE_MASK) == CPUM_SF_SDBT_TL_OFFSET; | ||
48 | } | ||
49 | |||
50 | /* Minimum and maximum sampling buffer sizes: | ||
51 | * | ||
52 | * This number represents the maximum size of the sampling buffer taking | ||
53 | * the number of sample-data-block-tables into account. Note that these | ||
54 | * numbers apply to the basic-sampling function only. | ||
55 | * The maximum number of SDBs is increased by CPUM_SF_SDB_DIAG_FACTOR if | ||
56 | * the diagnostic-sampling function is active. | ||
57 | * | ||
58 | * Sampling buffer size Buffer characteristics | ||
59 | * --------------------------------------------------- | ||
60 | * 64KB == 16 pages (4KB per page) | ||
61 | * 1 page for SDB-tables | ||
62 | * 15 pages for SDBs | ||
63 | * | ||
64 | * 32MB == 8192 pages (4KB per page) | ||
65 | * 16 pages for SDB-tables | ||
66 | * 8176 pages for SDBs | ||
67 | */ | ||
68 | static unsigned long __read_mostly CPUM_SF_MIN_SDB = 15; | ||
69 | static unsigned long __read_mostly CPUM_SF_MAX_SDB = 8176; | ||
70 | static unsigned long __read_mostly CPUM_SF_SDB_DIAG_FACTOR = 1; | ||
71 | |||
72 | struct sf_buffer { | ||
73 | unsigned long *sdbt; /* Sample-data-block-table origin */ | ||
74 | /* buffer characteristics (required for buffer increments) */ | ||
75 | unsigned long num_sdb; /* Number of sample-data-blocks */ | ||
76 | unsigned long num_sdbt; /* Number of sample-data-block-tables */ | ||
77 | unsigned long *tail; /* last sample-data-block-table */ | ||
78 | }; | ||
79 | |||
80 | struct cpu_hw_sf { | ||
81 | /* CPU-measurement sampling information block */ | ||
82 | struct hws_qsi_info_block qsi; | ||
83 | /* CPU-measurement sampling control block */ | ||
84 | struct hws_lsctl_request_block lsctl; | ||
85 | struct sf_buffer sfb; /* Sampling buffer */ | ||
86 | unsigned int flags; /* Status flags */ | ||
87 | struct perf_event *event; /* Scheduled perf event */ | ||
88 | }; | ||
89 | static DEFINE_PER_CPU(struct cpu_hw_sf, cpu_hw_sf); | ||
90 | |||
91 | /* Debug feature */ | ||
92 | static debug_info_t *sfdbg; | ||
93 | |||
94 | /* | ||
95 | * sf_disable() - Switch off sampling facility | ||
96 | */ | ||
97 | static int sf_disable(void) | ||
98 | { | ||
99 | struct hws_lsctl_request_block sreq; | ||
100 | |||
101 | memset(&sreq, 0, sizeof(sreq)); | ||
102 | return lsctl(&sreq); | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * sf_buffer_available() - Check for an allocated sampling buffer | ||
107 | */ | ||
108 | static int sf_buffer_available(struct cpu_hw_sf *cpuhw) | ||
109 | { | ||
110 | return !!cpuhw->sfb.sdbt; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * deallocate sampling facility buffer | ||
115 | */ | ||
116 | static void free_sampling_buffer(struct sf_buffer *sfb) | ||
117 | { | ||
118 | unsigned long *sdbt, *curr; | ||
119 | |||
120 | if (!sfb->sdbt) | ||
121 | return; | ||
122 | |||
123 | sdbt = sfb->sdbt; | ||
124 | curr = sdbt; | ||
125 | |||
126 | /* Free the SDBT after all SDBs are processed... */ | ||
127 | while (1) { | ||
128 | if (!*curr || !sdbt) | ||
129 | break; | ||
130 | |||
131 | /* Process table-link entries */ | ||
132 | if (is_link_entry(curr)) { | ||
133 | curr = get_next_sdbt(curr); | ||
134 | if (sdbt) | ||
135 | free_page((unsigned long) sdbt); | ||
136 | |||
137 | /* If the origin is reached, sampling buffer is freed */ | ||
138 | if (curr == sfb->sdbt) | ||
139 | break; | ||
140 | else | ||
141 | sdbt = curr; | ||
142 | } else { | ||
143 | /* Process SDB pointer */ | ||
144 | if (*curr) { | ||
145 | free_page(*curr); | ||
146 | curr++; | ||
147 | } | ||
148 | } | ||
149 | } | ||
150 | |||
151 | debug_sprintf_event(sfdbg, 5, | ||
152 | "free_sampling_buffer: freed sdbt=%p\n", sfb->sdbt); | ||
153 | memset(sfb, 0, sizeof(*sfb)); | ||
154 | } | ||
155 | |||
156 | static int alloc_sample_data_block(unsigned long *sdbt, gfp_t gfp_flags) | ||
157 | { | ||
158 | unsigned long sdb, *trailer; | ||
159 | |||
160 | /* Allocate and initialize sample-data-block */ | ||
161 | sdb = get_zeroed_page(gfp_flags); | ||
162 | if (!sdb) | ||
163 | return -ENOMEM; | ||
164 | trailer = trailer_entry_ptr(sdb); | ||
165 | *trailer = SDB_TE_ALERT_REQ_MASK; | ||
166 | |||
167 | /* Link SDB into the sample-data-block-table */ | ||
168 | *sdbt = sdb; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * realloc_sampling_buffer() - extend sampler memory | ||
175 | * | ||
176 | * Allocates new sample-data-blocks and adds them to the specified sampling | ||
177 | * buffer memory. | ||
178 | * | ||
179 | * Important: This modifies the sampling buffer and must be called when the | ||
180 | * sampling facility is disabled. | ||
181 | * | ||
182 | * Returns zero on success, non-zero otherwise. | ||
183 | */ | ||
184 | static int realloc_sampling_buffer(struct sf_buffer *sfb, | ||
185 | unsigned long num_sdb, gfp_t gfp_flags) | ||
186 | { | ||
187 | int i, rc; | ||
188 | unsigned long *new, *tail; | ||
189 | |||
190 | if (!sfb->sdbt || !sfb->tail) | ||
191 | return -EINVAL; | ||
192 | |||
193 | if (!is_link_entry(sfb->tail)) | ||
194 | return -EINVAL; | ||
195 | |||
196 | /* Append to the existing sampling buffer, overwriting the table-link | ||
197 | * register. | ||
198 | * The tail variables always points to the "tail" (last and table-link) | ||
199 | * entry in an SDB-table. | ||
200 | */ | ||
201 | tail = sfb->tail; | ||
202 | |||
203 | /* Do a sanity check whether the table-link entry points to | ||
204 | * the sampling buffer origin. | ||
205 | */ | ||
206 | if (sfb->sdbt != get_next_sdbt(tail)) { | ||
207 | debug_sprintf_event(sfdbg, 3, "realloc_sampling_buffer: " | ||
208 | "sampling buffer is not linked: origin=%p" | ||
209 | "tail=%p\n", | ||
210 | (void *) sfb->sdbt, (void *) tail); | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | /* Allocate remaining SDBs */ | ||
215 | rc = 0; | ||
216 | for (i = 0; i < num_sdb; i++) { | ||
217 | /* Allocate a new SDB-table if it is full. */ | ||
218 | if (require_table_link(tail)) { | ||
219 | new = (unsigned long *) get_zeroed_page(gfp_flags); | ||
220 | if (!new) { | ||
221 | rc = -ENOMEM; | ||
222 | break; | ||
223 | } | ||
224 | sfb->num_sdbt++; | ||
225 | /* Link current page to tail of chain */ | ||
226 | *tail = (unsigned long)(void *) new + 1; | ||
227 | tail = new; | ||
228 | } | ||
229 | |||
230 | /* Allocate a new sample-data-block. | ||
231 | * If there is not enough memory, stop the realloc process | ||
232 | * and simply use what was allocated. If this is a temporary | ||
233 | * issue, a new realloc call (if required) might succeed. | ||
234 | */ | ||
235 | rc = alloc_sample_data_block(tail, gfp_flags); | ||
236 | if (rc) | ||
237 | break; | ||
238 | sfb->num_sdb++; | ||
239 | tail++; | ||
240 | } | ||
241 | |||
242 | /* Link sampling buffer to its origin */ | ||
243 | *tail = (unsigned long) sfb->sdbt + 1; | ||
244 | sfb->tail = tail; | ||
245 | |||
246 | debug_sprintf_event(sfdbg, 4, "realloc_sampling_buffer: new buffer" | ||
247 | " settings: sdbt=%lu sdb=%lu\n", | ||
248 | sfb->num_sdbt, sfb->num_sdb); | ||
249 | return rc; | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * allocate_sampling_buffer() - allocate sampler memory | ||
254 | * | ||
255 | * Allocates and initializes a sampling buffer structure using the | ||
256 | * specified number of sample-data-blocks (SDB). For each allocation, | ||
257 | * a 4K page is used. The number of sample-data-block-tables (SDBT) | ||
258 | * are calculated from SDBs. | ||
259 | * Also set the ALERT_REQ mask in each SDBs trailer. | ||
260 | * | ||
261 | * Returns zero on success, non-zero otherwise. | ||
262 | */ | ||
263 | static int alloc_sampling_buffer(struct sf_buffer *sfb, unsigned long num_sdb) | ||
264 | { | ||
265 | int rc; | ||
266 | |||
267 | if (sfb->sdbt) | ||
268 | return -EINVAL; | ||
269 | |||
270 | /* Allocate the sample-data-block-table origin */ | ||
271 | sfb->sdbt = (unsigned long *) get_zeroed_page(GFP_KERNEL); | ||
272 | if (!sfb->sdbt) | ||
273 | return -ENOMEM; | ||
274 | sfb->num_sdb = 0; | ||
275 | sfb->num_sdbt = 1; | ||
276 | |||
277 | /* Link the table origin to point to itself to prepare for | ||
278 | * realloc_sampling_buffer() invocation. | ||
279 | */ | ||
280 | sfb->tail = sfb->sdbt; | ||
281 | *sfb->tail = (unsigned long)(void *) sfb->sdbt + 1; | ||
282 | |||
283 | /* Allocate requested number of sample-data-blocks */ | ||
284 | rc = realloc_sampling_buffer(sfb, num_sdb, GFP_KERNEL); | ||
285 | if (rc) { | ||
286 | free_sampling_buffer(sfb); | ||
287 | debug_sprintf_event(sfdbg, 4, "alloc_sampling_buffer: " | ||
288 | "realloc_sampling_buffer failed with rc=%i\n", rc); | ||
289 | } else | ||
290 | debug_sprintf_event(sfdbg, 4, | ||
291 | "alloc_sampling_buffer: tear=%p dear=%p\n", | ||
292 | sfb->sdbt, (void *) *sfb->sdbt); | ||
293 | return rc; | ||
294 | } | ||
295 | |||
296 | static void sfb_set_limits(unsigned long min, unsigned long max) | ||
297 | { | ||
298 | struct hws_qsi_info_block si; | ||
299 | |||
300 | CPUM_SF_MIN_SDB = min; | ||
301 | CPUM_SF_MAX_SDB = max; | ||
302 | |||
303 | memset(&si, 0, sizeof(si)); | ||
304 | if (!qsi(&si)) | ||
305 | CPUM_SF_SDB_DIAG_FACTOR = DIV_ROUND_UP(si.dsdes, si.bsdes); | ||
306 | } | ||
307 | |||
308 | static unsigned long sfb_max_limit(struct hw_perf_event *hwc) | ||
309 | { | ||
310 | return SAMPL_DIAG_MODE(hwc) ? CPUM_SF_MAX_SDB * CPUM_SF_SDB_DIAG_FACTOR | ||
311 | : CPUM_SF_MAX_SDB; | ||
312 | } | ||
313 | |||
314 | static unsigned long sfb_pending_allocs(struct sf_buffer *sfb, | ||
315 | struct hw_perf_event *hwc) | ||
316 | { | ||
317 | if (!sfb->sdbt) | ||
318 | return SFB_ALLOC_REG(hwc); | ||
319 | if (SFB_ALLOC_REG(hwc) > sfb->num_sdb) | ||
320 | return SFB_ALLOC_REG(hwc) - sfb->num_sdb; | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int sfb_has_pending_allocs(struct sf_buffer *sfb, | ||
325 | struct hw_perf_event *hwc) | ||
326 | { | ||
327 | return sfb_pending_allocs(sfb, hwc) > 0; | ||
328 | } | ||
329 | |||
330 | static void sfb_account_allocs(unsigned long num, struct hw_perf_event *hwc) | ||
331 | { | ||
332 | /* Limit the number of SDBs to not exceed the maximum */ | ||
333 | num = min_t(unsigned long, num, sfb_max_limit(hwc) - SFB_ALLOC_REG(hwc)); | ||
334 | if (num) | ||
335 | SFB_ALLOC_REG(hwc) += num; | ||
336 | } | ||
337 | |||
338 | static void sfb_init_allocs(unsigned long num, struct hw_perf_event *hwc) | ||
339 | { | ||
340 | SFB_ALLOC_REG(hwc) = 0; | ||
341 | sfb_account_allocs(num, hwc); | ||
342 | } | ||
343 | |||
344 | static size_t event_sample_size(struct hw_perf_event *hwc) | ||
345 | { | ||
346 | struct sf_raw_sample *sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(hwc); | ||
347 | size_t sample_size; | ||
348 | |||
349 | /* The sample size depends on the sampling function: The basic-sampling | ||
350 | * function must be always enabled, diagnostic-sampling function is | ||
351 | * optional. | ||
352 | */ | ||
353 | sample_size = sfr->bsdes; | ||
354 | if (SAMPL_DIAG_MODE(hwc)) | ||
355 | sample_size += sfr->dsdes; | ||
356 | |||
357 | return sample_size; | ||
358 | } | ||
359 | |||
360 | static void deallocate_buffers(struct cpu_hw_sf *cpuhw) | ||
361 | { | ||
362 | if (cpuhw->sfb.sdbt) | ||
363 | free_sampling_buffer(&cpuhw->sfb); | ||
364 | } | ||
365 | |||
366 | static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc) | ||
367 | { | ||
368 | unsigned long n_sdb, freq, factor; | ||
369 | size_t sfr_size, sample_size; | ||
370 | struct sf_raw_sample *sfr; | ||
371 | |||
372 | /* Allocate raw sample buffer | ||
373 | * | ||
374 | * The raw sample buffer is used to temporarily store sampling data | ||
375 | * entries for perf raw sample processing. The buffer size mainly | ||
376 | * depends on the size of diagnostic-sampling data entries which is | ||
377 | * machine-specific. The exact size calculation includes: | ||
378 | * 1. The first 4 bytes of diagnostic-sampling data entries are | ||
379 | * already reflected in the sf_raw_sample structure. Subtract | ||
380 | * these bytes. | ||
381 | * 2. The perf raw sample data must be 8-byte aligned (u64) and | ||
382 | * perf's internal data size must be considered too. So add | ||
383 | * an additional u32 for correct alignment and subtract before | ||
384 | * allocating the buffer. | ||
385 | * 3. Store the raw sample buffer pointer in the perf event | ||
386 | * hardware structure. | ||
387 | */ | ||
388 | sfr_size = ALIGN((sizeof(*sfr) - sizeof(sfr->diag) + cpuhw->qsi.dsdes) + | ||
389 | sizeof(u32), sizeof(u64)); | ||
390 | sfr_size -= sizeof(u32); | ||
391 | sfr = kzalloc(sfr_size, GFP_KERNEL); | ||
392 | if (!sfr) | ||
393 | return -ENOMEM; | ||
394 | sfr->size = sfr_size; | ||
395 | sfr->bsdes = cpuhw->qsi.bsdes; | ||
396 | sfr->dsdes = cpuhw->qsi.dsdes; | ||
397 | RAWSAMPLE_REG(hwc) = (unsigned long) sfr; | ||
398 | |||
399 | /* Calculate sampling buffers using 4K pages | ||
400 | * | ||
401 | * 1. Determine the sample data size which depends on the used | ||
402 | * sampling functions, for example, basic-sampling or | ||
403 | * basic-sampling with diagnostic-sampling. | ||
404 | * | ||
405 | * 2. Use the sampling frequency as input. The sampling buffer is | ||
406 | * designed for almost one second. This can be adjusted through | ||
407 | * the "factor" variable. | ||
408 | * In any case, alloc_sampling_buffer() sets the Alert Request | ||
409 | * Control indicator to trigger a measurement-alert to harvest | ||
410 | * sample-data-blocks (sdb). | ||
411 | * | ||
412 | * 3. Compute the number of sample-data-blocks and ensure a minimum | ||
413 | * of CPUM_SF_MIN_SDB. Also ensure the upper limit does not | ||
414 | * exceed a "calculated" maximum. The symbolic maximum is | ||
415 | * designed for basic-sampling only and needs to be increased if | ||
416 | * diagnostic-sampling is active. | ||
417 | * See also the remarks for these symbolic constants. | ||
418 | * | ||
419 | * 4. Compute the number of sample-data-block-tables (SDBT) and | ||
420 | * ensure a minimum of CPUM_SF_MIN_SDBT (one table can manage up | ||
421 | * to 511 SDBs). | ||
422 | */ | ||
423 | sample_size = event_sample_size(hwc); | ||
424 | freq = sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc)); | ||
425 | factor = 1; | ||
426 | n_sdb = DIV_ROUND_UP(freq, factor * ((PAGE_SIZE-64) / sample_size)); | ||
427 | if (n_sdb < CPUM_SF_MIN_SDB) | ||
428 | n_sdb = CPUM_SF_MIN_SDB; | ||
429 | |||
430 | /* If there is already a sampling buffer allocated, it is very likely | ||
431 | * that the sampling facility is enabled too. If the event to be | ||
432 | * initialized requires a greater sampling buffer, the allocation must | ||
433 | * be postponed. Changing the sampling buffer requires the sampling | ||
434 | * facility to be in the disabled state. So, account the number of | ||
435 | * required SDBs and let cpumsf_pmu_enable() resize the buffer just | ||
436 | * before the event is started. | ||
437 | */ | ||
438 | sfb_init_allocs(n_sdb, hwc); | ||
439 | if (sf_buffer_available(cpuhw)) | ||
440 | return 0; | ||
441 | |||
442 | debug_sprintf_event(sfdbg, 3, | ||
443 | "allocate_buffers: rate=%lu f=%lu sdb=%lu/%lu" | ||
444 | " sample_size=%lu cpuhw=%p\n", | ||
445 | SAMPL_RATE(hwc), freq, n_sdb, sfb_max_limit(hwc), | ||
446 | sample_size, cpuhw); | ||
447 | |||
448 | return alloc_sampling_buffer(&cpuhw->sfb, | ||
449 | sfb_pending_allocs(&cpuhw->sfb, hwc)); | ||
450 | } | ||
451 | |||
452 | static unsigned long min_percent(unsigned int percent, unsigned long base, | ||
453 | unsigned long min) | ||
454 | { | ||
455 | return min_t(unsigned long, min, DIV_ROUND_UP(percent * base, 100)); | ||
456 | } | ||
457 | |||
458 | static unsigned long compute_sfb_extent(unsigned long ratio, unsigned long base) | ||
459 | { | ||
460 | /* Use a percentage-based approach to extend the sampling facility | ||
461 | * buffer. Accept up to 5% sample data loss. | ||
462 | * Vary the extents between 1% to 5% of the current number of | ||
463 | * sample-data-blocks. | ||
464 | */ | ||
465 | if (ratio <= 5) | ||
466 | return 0; | ||
467 | if (ratio <= 25) | ||
468 | return min_percent(1, base, 1); | ||
469 | if (ratio <= 50) | ||
470 | return min_percent(1, base, 1); | ||
471 | if (ratio <= 75) | ||
472 | return min_percent(2, base, 2); | ||
473 | if (ratio <= 100) | ||
474 | return min_percent(3, base, 3); | ||
475 | if (ratio <= 250) | ||
476 | return min_percent(4, base, 4); | ||
477 | |||
478 | return min_percent(5, base, 8); | ||
479 | } | ||
480 | |||
481 | static void sfb_account_overflows(struct cpu_hw_sf *cpuhw, | ||
482 | struct hw_perf_event *hwc) | ||
483 | { | ||
484 | unsigned long ratio, num; | ||
485 | |||
486 | if (!OVERFLOW_REG(hwc)) | ||
487 | return; | ||
488 | |||
489 | /* The sample_overflow contains the average number of sample data | ||
490 | * that has been lost because sample-data-blocks were full. | ||
491 | * | ||
492 | * Calculate the total number of sample data entries that has been | ||
493 | * discarded. Then calculate the ratio of lost samples to total samples | ||
494 | * per second in percent. | ||
495 | */ | ||
496 | ratio = DIV_ROUND_UP(100 * OVERFLOW_REG(hwc) * cpuhw->sfb.num_sdb, | ||
497 | sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc))); | ||
498 | |||
499 | /* Compute number of sample-data-blocks */ | ||
500 | num = compute_sfb_extent(ratio, cpuhw->sfb.num_sdb); | ||
501 | if (num) | ||
502 | sfb_account_allocs(num, hwc); | ||
503 | |||
504 | debug_sprintf_event(sfdbg, 5, "sfb: overflow: overflow=%llu ratio=%lu" | ||
505 | " num=%lu\n", OVERFLOW_REG(hwc), ratio, num); | ||
506 | OVERFLOW_REG(hwc) = 0; | ||
507 | } | ||
508 | |||
509 | /* extend_sampling_buffer() - Extend sampling buffer | ||
510 | * @sfb: Sampling buffer structure (for local CPU) | ||
511 | * @hwc: Perf event hardware structure | ||
512 | * | ||
513 | * Use this function to extend the sampling buffer based on the overflow counter | ||
514 | * and postponed allocation extents stored in the specified Perf event hardware. | ||
515 | * | ||
516 | * Important: This function disables the sampling facility in order to safely | ||
517 | * change the sampling buffer structure. Do not call this function | ||
518 | * when the PMU is active. | ||
519 | */ | ||
520 | static void extend_sampling_buffer(struct sf_buffer *sfb, | ||
521 | struct hw_perf_event *hwc) | ||
522 | { | ||
523 | unsigned long num, num_old; | ||
524 | int rc; | ||
525 | |||
526 | num = sfb_pending_allocs(sfb, hwc); | ||
527 | if (!num) | ||
528 | return; | ||
529 | num_old = sfb->num_sdb; | ||
530 | |||
531 | /* Disable the sampling facility to reset any states and also | ||
532 | * clear pending measurement alerts. | ||
533 | */ | ||
534 | sf_disable(); | ||
535 | |||
536 | /* Extend the sampling buffer. | ||
537 | * This memory allocation typically happens in an atomic context when | ||
538 | * called by perf. Because this is a reallocation, it is fine if the | ||
539 | * new SDB-request cannot be satisfied immediately. | ||
540 | */ | ||
541 | rc = realloc_sampling_buffer(sfb, num, GFP_ATOMIC); | ||
542 | if (rc) | ||
543 | debug_sprintf_event(sfdbg, 5, "sfb: extend: realloc " | ||
544 | "failed with rc=%i\n", rc); | ||
545 | |||
546 | if (sfb_has_pending_allocs(sfb, hwc)) | ||
547 | debug_sprintf_event(sfdbg, 5, "sfb: extend: " | ||
548 | "req=%lu alloc=%lu remaining=%lu\n", | ||
549 | num, sfb->num_sdb - num_old, | ||
550 | sfb_pending_allocs(sfb, hwc)); | ||
551 | } | ||
552 | |||
553 | |||
554 | /* Number of perf events counting hardware events */ | ||
555 | static atomic_t num_events; | ||
556 | /* Used to avoid races in calling reserve/release_cpumf_hardware */ | ||
557 | static DEFINE_MUTEX(pmc_reserve_mutex); | ||
558 | |||
559 | #define PMC_INIT 0 | ||
560 | #define PMC_RELEASE 1 | ||
561 | #define PMC_FAILURE 2 | ||
562 | static void setup_pmc_cpu(void *flags) | ||
563 | { | ||
564 | int err; | ||
565 | struct cpu_hw_sf *cpusf = &__get_cpu_var(cpu_hw_sf); | ||
566 | |||
567 | err = 0; | ||
568 | switch (*((int *) flags)) { | ||
569 | case PMC_INIT: | ||
570 | memset(cpusf, 0, sizeof(*cpusf)); | ||
571 | err = qsi(&cpusf->qsi); | ||
572 | if (err) | ||
573 | break; | ||
574 | cpusf->flags |= PMU_F_RESERVED; | ||
575 | err = sf_disable(); | ||
576 | if (err) | ||
577 | pr_err("Switching off the sampling facility failed " | ||
578 | "with rc=%i\n", err); | ||
579 | debug_sprintf_event(sfdbg, 5, | ||
580 | "setup_pmc_cpu: initialized: cpuhw=%p\n", cpusf); | ||
581 | break; | ||
582 | case PMC_RELEASE: | ||
583 | cpusf->flags &= ~PMU_F_RESERVED; | ||
584 | err = sf_disable(); | ||
585 | if (err) { | ||
586 | pr_err("Switching off the sampling facility failed " | ||
587 | "with rc=%i\n", err); | ||
588 | } else | ||
589 | deallocate_buffers(cpusf); | ||
590 | debug_sprintf_event(sfdbg, 5, | ||
591 | "setup_pmc_cpu: released: cpuhw=%p\n", cpusf); | ||
592 | break; | ||
593 | } | ||
594 | if (err) | ||
595 | *((int *) flags) |= PMC_FAILURE; | ||
596 | } | ||
597 | |||
598 | static void release_pmc_hardware(void) | ||
599 | { | ||
600 | int flags = PMC_RELEASE; | ||
601 | |||
602 | irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); | ||
603 | on_each_cpu(setup_pmc_cpu, &flags, 1); | ||
604 | perf_release_sampling(); | ||
605 | } | ||
606 | |||
607 | static int reserve_pmc_hardware(void) | ||
608 | { | ||
609 | int flags = PMC_INIT; | ||
610 | int err; | ||
611 | |||
612 | err = perf_reserve_sampling(); | ||
613 | if (err) | ||
614 | return err; | ||
615 | on_each_cpu(setup_pmc_cpu, &flags, 1); | ||
616 | if (flags & PMC_FAILURE) { | ||
617 | release_pmc_hardware(); | ||
618 | return -ENODEV; | ||
619 | } | ||
620 | irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static void hw_perf_event_destroy(struct perf_event *event) | ||
626 | { | ||
627 | /* Free raw sample buffer */ | ||
628 | if (RAWSAMPLE_REG(&event->hw)) | ||
629 | kfree((void *) RAWSAMPLE_REG(&event->hw)); | ||
630 | |||
631 | /* Release PMC if this is the last perf event */ | ||
632 | if (!atomic_add_unless(&num_events, -1, 1)) { | ||
633 | mutex_lock(&pmc_reserve_mutex); | ||
634 | if (atomic_dec_return(&num_events) == 0) | ||
635 | release_pmc_hardware(); | ||
636 | mutex_unlock(&pmc_reserve_mutex); | ||
637 | } | ||
638 | } | ||
639 | |||
640 | static void hw_init_period(struct hw_perf_event *hwc, u64 period) | ||
641 | { | ||
642 | hwc->sample_period = period; | ||
643 | hwc->last_period = hwc->sample_period; | ||
644 | local64_set(&hwc->period_left, hwc->sample_period); | ||
645 | } | ||
646 | |||
647 | static void hw_reset_registers(struct hw_perf_event *hwc, | ||
648 | unsigned long *sdbt_origin) | ||
649 | { | ||
650 | struct sf_raw_sample *sfr; | ||
651 | |||
652 | /* (Re)set to first sample-data-block-table */ | ||
653 | TEAR_REG(hwc) = (unsigned long) sdbt_origin; | ||
654 | |||
655 | /* (Re)set raw sampling buffer register */ | ||
656 | sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(hwc); | ||
657 | memset(&sfr->basic, 0, sizeof(sfr->basic)); | ||
658 | memset(&sfr->diag, 0, sfr->dsdes); | ||
659 | } | ||
660 | |||
661 | static unsigned long hw_limit_rate(const struct hws_qsi_info_block *si, | ||
662 | unsigned long rate) | ||
663 | { | ||
664 | return clamp_t(unsigned long, rate, | ||
665 | si->min_sampl_rate, si->max_sampl_rate); | ||
666 | } | ||
667 | |||
668 | static int __hw_perf_event_init(struct perf_event *event) | ||
669 | { | ||
670 | struct cpu_hw_sf *cpuhw; | ||
671 | struct hws_qsi_info_block si; | ||
672 | struct perf_event_attr *attr = &event->attr; | ||
673 | struct hw_perf_event *hwc = &event->hw; | ||
674 | unsigned long rate; | ||
675 | int cpu, err; | ||
676 | |||
677 | /* Reserve CPU-measurement sampling facility */ | ||
678 | err = 0; | ||
679 | if (!atomic_inc_not_zero(&num_events)) { | ||
680 | mutex_lock(&pmc_reserve_mutex); | ||
681 | if (atomic_read(&num_events) == 0 && reserve_pmc_hardware()) | ||
682 | err = -EBUSY; | ||
683 | else | ||
684 | atomic_inc(&num_events); | ||
685 | mutex_unlock(&pmc_reserve_mutex); | ||
686 | } | ||
687 | event->destroy = hw_perf_event_destroy; | ||
688 | |||
689 | if (err) | ||
690 | goto out; | ||
691 | |||
692 | /* Access per-CPU sampling information (query sampling info) */ | ||
693 | /* | ||
694 | * The event->cpu value can be -1 to count on every CPU, for example, | ||
695 | * when attaching to a task. If this is specified, use the query | ||
696 | * sampling info from the current CPU, otherwise use event->cpu to | ||
697 | * retrieve the per-CPU information. | ||
698 | * Later, cpuhw indicates whether to allocate sampling buffers for a | ||
699 | * particular CPU (cpuhw!=NULL) or each online CPU (cpuw==NULL). | ||
700 | */ | ||
701 | memset(&si, 0, sizeof(si)); | ||
702 | cpuhw = NULL; | ||
703 | if (event->cpu == -1) | ||
704 | qsi(&si); | ||
705 | else { | ||
706 | /* Event is pinned to a particular CPU, retrieve the per-CPU | ||
707 | * sampling structure for accessing the CPU-specific QSI. | ||
708 | */ | ||
709 | cpuhw = &per_cpu(cpu_hw_sf, event->cpu); | ||
710 | si = cpuhw->qsi; | ||
711 | } | ||
712 | |||
713 | /* Check sampling facility authorization and, if not authorized, | ||
714 | * fall back to other PMUs. It is safe to check any CPU because | ||
715 | * the authorization is identical for all configured CPUs. | ||
716 | */ | ||
717 | if (!si.as) { | ||
718 | err = -ENOENT; | ||
719 | goto out; | ||
720 | } | ||
721 | |||
722 | /* Always enable basic sampling */ | ||
723 | SAMPL_FLAGS(hwc) = PERF_CPUM_SF_BASIC_MODE; | ||
724 | |||
725 | /* Check if diagnostic sampling is requested. Deny if the required | ||
726 | * sampling authorization is missing. | ||
727 | */ | ||
728 | if (attr->config == PERF_EVENT_CPUM_SF_DIAG) { | ||
729 | if (!si.ad) { | ||
730 | err = -EPERM; | ||
731 | goto out; | ||
732 | } | ||
733 | SAMPL_FLAGS(hwc) |= PERF_CPUM_SF_DIAG_MODE; | ||
734 | } | ||
735 | |||
736 | /* Check and set other sampling flags */ | ||
737 | if (attr->config1 & PERF_CPUM_SF_FULL_BLOCKS) | ||
738 | SAMPL_FLAGS(hwc) |= PERF_CPUM_SF_FULL_BLOCKS; | ||
739 | |||
740 | /* The sampling information (si) contains information about the | ||
741 | * min/max sampling intervals and the CPU speed. So calculate the | ||
742 | * correct sampling interval and avoid the whole period adjust | ||
743 | * feedback loop. | ||
744 | */ | ||
745 | rate = 0; | ||
746 | if (attr->freq) { | ||
747 | rate = freq_to_sample_rate(&si, attr->sample_freq); | ||
748 | rate = hw_limit_rate(&si, rate); | ||
749 | attr->freq = 0; | ||
750 | attr->sample_period = rate; | ||
751 | } else { | ||
752 | /* The min/max sampling rates specifies the valid range | ||
753 | * of sample periods. If the specified sample period is | ||
754 | * out of range, limit the period to the range boundary. | ||
755 | */ | ||
756 | rate = hw_limit_rate(&si, hwc->sample_period); | ||
757 | |||
758 | /* The perf core maintains a maximum sample rate that is | ||
759 | * configurable through the sysctl interface. Ensure the | ||
760 | * sampling rate does not exceed this value. This also helps | ||
761 | * to avoid throttling when pushing samples with | ||
762 | * perf_event_overflow(). | ||
763 | */ | ||
764 | if (sample_rate_to_freq(&si, rate) > | ||
765 | sysctl_perf_event_sample_rate) { | ||
766 | err = -EINVAL; | ||
767 | debug_sprintf_event(sfdbg, 1, "Sampling rate exceeds maximum perf sample rate\n"); | ||
768 | goto out; | ||
769 | } | ||
770 | } | ||
771 | SAMPL_RATE(hwc) = rate; | ||
772 | hw_init_period(hwc, SAMPL_RATE(hwc)); | ||
773 | |||
774 | /* Initialize sample data overflow accounting */ | ||
775 | hwc->extra_reg.reg = REG_OVERFLOW; | ||
776 | OVERFLOW_REG(hwc) = 0; | ||
777 | |||
778 | /* Allocate the per-CPU sampling buffer using the CPU information | ||
779 | * from the event. If the event is not pinned to a particular | ||
780 | * CPU (event->cpu == -1; or cpuhw == NULL), allocate sampling | ||
781 | * buffers for each online CPU. | ||
782 | */ | ||
783 | if (cpuhw) | ||
784 | /* Event is pinned to a particular CPU */ | ||
785 | err = allocate_buffers(cpuhw, hwc); | ||
786 | else { | ||
787 | /* Event is not pinned, allocate sampling buffer on | ||
788 | * each online CPU | ||
789 | */ | ||
790 | for_each_online_cpu(cpu) { | ||
791 | cpuhw = &per_cpu(cpu_hw_sf, cpu); | ||
792 | err = allocate_buffers(cpuhw, hwc); | ||
793 | if (err) | ||
794 | break; | ||
795 | } | ||
796 | } | ||
797 | out: | ||
798 | return err; | ||
799 | } | ||
800 | |||
801 | static int cpumsf_pmu_event_init(struct perf_event *event) | ||
802 | { | ||
803 | int err; | ||
804 | |||
805 | /* No support for taken branch sampling */ | ||
806 | if (has_branch_stack(event)) | ||
807 | return -EOPNOTSUPP; | ||
808 | |||
809 | switch (event->attr.type) { | ||
810 | case PERF_TYPE_RAW: | ||
811 | if ((event->attr.config != PERF_EVENT_CPUM_SF) && | ||
812 | (event->attr.config != PERF_EVENT_CPUM_SF_DIAG)) | ||
813 | return -ENOENT; | ||
814 | break; | ||
815 | case PERF_TYPE_HARDWARE: | ||
816 | /* Support sampling of CPU cycles in addition to the | ||
817 | * counter facility. However, the counter facility | ||
818 | * is more precise and, hence, restrict this PMU to | ||
819 | * sampling events only. | ||
820 | */ | ||
821 | if (event->attr.config != PERF_COUNT_HW_CPU_CYCLES) | ||
822 | return -ENOENT; | ||
823 | if (!is_sampling_event(event)) | ||
824 | return -ENOENT; | ||
825 | break; | ||
826 | default: | ||
827 | return -ENOENT; | ||
828 | } | ||
829 | |||
830 | /* Check online status of the CPU to which the event is pinned */ | ||
831 | if (event->cpu >= nr_cpumask_bits || | ||
832 | (event->cpu >= 0 && !cpu_online(event->cpu))) | ||
833 | return -ENODEV; | ||
834 | |||
835 | /* Force reset of idle/hv excludes regardless of what the | ||
836 | * user requested. | ||
837 | */ | ||
838 | if (event->attr.exclude_hv) | ||
839 | event->attr.exclude_hv = 0; | ||
840 | if (event->attr.exclude_idle) | ||
841 | event->attr.exclude_idle = 0; | ||
842 | |||
843 | err = __hw_perf_event_init(event); | ||
844 | if (unlikely(err)) | ||
845 | if (event->destroy) | ||
846 | event->destroy(event); | ||
847 | return err; | ||
848 | } | ||
849 | |||
850 | static void cpumsf_pmu_enable(struct pmu *pmu) | ||
851 | { | ||
852 | struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); | ||
853 | struct hw_perf_event *hwc; | ||
854 | int err; | ||
855 | |||
856 | if (cpuhw->flags & PMU_F_ENABLED) | ||
857 | return; | ||
858 | |||
859 | if (cpuhw->flags & PMU_F_ERR_MASK) | ||
860 | return; | ||
861 | |||
862 | /* Check whether to extent the sampling buffer. | ||
863 | * | ||
864 | * Two conditions trigger an increase of the sampling buffer for a | ||
865 | * perf event: | ||
866 | * 1. Postponed buffer allocations from the event initialization. | ||
867 | * 2. Sampling overflows that contribute to pending allocations. | ||
868 | * | ||
869 | * Note that the extend_sampling_buffer() function disables the sampling | ||
870 | * facility, but it can be fully re-enabled using sampling controls that | ||
871 | * have been saved in cpumsf_pmu_disable(). | ||
872 | */ | ||
873 | if (cpuhw->event) { | ||
874 | hwc = &cpuhw->event->hw; | ||
875 | /* Account number of overflow-designated buffer extents */ | ||
876 | sfb_account_overflows(cpuhw, hwc); | ||
877 | if (sfb_has_pending_allocs(&cpuhw->sfb, hwc)) | ||
878 | extend_sampling_buffer(&cpuhw->sfb, hwc); | ||
879 | } | ||
880 | |||
881 | /* (Re)enable the PMU and sampling facility */ | ||
882 | cpuhw->flags |= PMU_F_ENABLED; | ||
883 | barrier(); | ||
884 | |||
885 | err = lsctl(&cpuhw->lsctl); | ||
886 | if (err) { | ||
887 | cpuhw->flags &= ~PMU_F_ENABLED; | ||
888 | pr_err("Loading sampling controls failed: op=%i err=%i\n", | ||
889 | 1, err); | ||
890 | return; | ||
891 | } | ||
892 | |||
893 | debug_sprintf_event(sfdbg, 6, "pmu_enable: es=%i cs=%i ed=%i cd=%i " | ||
894 | "tear=%p dear=%p\n", cpuhw->lsctl.es, cpuhw->lsctl.cs, | ||
895 | cpuhw->lsctl.ed, cpuhw->lsctl.cd, | ||
896 | (void *) cpuhw->lsctl.tear, (void *) cpuhw->lsctl.dear); | ||
897 | } | ||
898 | |||
899 | static void cpumsf_pmu_disable(struct pmu *pmu) | ||
900 | { | ||
901 | struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); | ||
902 | struct hws_lsctl_request_block inactive; | ||
903 | struct hws_qsi_info_block si; | ||
904 | int err; | ||
905 | |||
906 | if (!(cpuhw->flags & PMU_F_ENABLED)) | ||
907 | return; | ||
908 | |||
909 | if (cpuhw->flags & PMU_F_ERR_MASK) | ||
910 | return; | ||
911 | |||
912 | /* Switch off sampling activation control */ | ||
913 | inactive = cpuhw->lsctl; | ||
914 | inactive.cs = 0; | ||
915 | inactive.cd = 0; | ||
916 | |||
917 | err = lsctl(&inactive); | ||
918 | if (err) { | ||
919 | pr_err("Loading sampling controls failed: op=%i err=%i\n", | ||
920 | 2, err); | ||
921 | return; | ||
922 | } | ||
923 | |||
924 | /* Save state of TEAR and DEAR register contents */ | ||
925 | if (!qsi(&si)) { | ||
926 | /* TEAR/DEAR values are valid only if the sampling facility is | ||
927 | * enabled. Note that cpumsf_pmu_disable() might be called even | ||
928 | * for a disabled sampling facility because cpumsf_pmu_enable() | ||
929 | * controls the enable/disable state. | ||
930 | */ | ||
931 | if (si.es) { | ||
932 | cpuhw->lsctl.tear = si.tear; | ||
933 | cpuhw->lsctl.dear = si.dear; | ||
934 | } | ||
935 | } else | ||
936 | debug_sprintf_event(sfdbg, 3, "cpumsf_pmu_disable: " | ||
937 | "qsi() failed with err=%i\n", err); | ||
938 | |||
939 | cpuhw->flags &= ~PMU_F_ENABLED; | ||
940 | } | ||
941 | |||
942 | /* perf_exclude_event() - Filter event | ||
943 | * @event: The perf event | ||
944 | * @regs: pt_regs structure | ||
945 | * @sde_regs: Sample-data-entry (sde) regs structure | ||
946 | * | ||
947 | * Filter perf events according to their exclude specification. | ||
948 | * | ||
949 | * Return non-zero if the event shall be excluded. | ||
950 | */ | ||
951 | static int perf_exclude_event(struct perf_event *event, struct pt_regs *regs, | ||
952 | struct perf_sf_sde_regs *sde_regs) | ||
953 | { | ||
954 | if (event->attr.exclude_user && user_mode(regs)) | ||
955 | return 1; | ||
956 | if (event->attr.exclude_kernel && !user_mode(regs)) | ||
957 | return 1; | ||
958 | if (event->attr.exclude_guest && sde_regs->in_guest) | ||
959 | return 1; | ||
960 | if (event->attr.exclude_host && !sde_regs->in_guest) | ||
961 | return 1; | ||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | /* perf_push_sample() - Push samples to perf | ||
966 | * @event: The perf event | ||
967 | * @sample: Hardware sample data | ||
968 | * | ||
969 | * Use the hardware sample data to create perf event sample. The sample | ||
970 | * is the pushed to the event subsystem and the function checks for | ||
971 | * possible event overflows. If an event overflow occurs, the PMU is | ||
972 | * stopped. | ||
973 | * | ||
974 | * Return non-zero if an event overflow occurred. | ||
975 | */ | ||
976 | static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr) | ||
977 | { | ||
978 | int overflow; | ||
979 | struct pt_regs regs; | ||
980 | struct perf_sf_sde_regs *sde_regs; | ||
981 | struct perf_sample_data data; | ||
982 | struct perf_raw_record raw; | ||
983 | |||
984 | /* Setup perf sample */ | ||
985 | perf_sample_data_init(&data, 0, event->hw.last_period); | ||
986 | raw.size = sfr->size; | ||
987 | raw.data = sfr; | ||
988 | data.raw = &raw; | ||
989 | |||
990 | /* Setup pt_regs to look like an CPU-measurement external interrupt | ||
991 | * using the Program Request Alert code. The regs.int_parm_long | ||
992 | * field which is unused contains additional sample-data-entry related | ||
993 | * indicators. | ||
994 | */ | ||
995 | memset(®s, 0, sizeof(regs)); | ||
996 | regs.int_code = 0x1407; | ||
997 | regs.int_parm = CPU_MF_INT_SF_PRA; | ||
998 | sde_regs = (struct perf_sf_sde_regs *) ®s.int_parm_long; | ||
999 | |||
1000 | regs.psw.addr = sfr->basic.ia; | ||
1001 | if (sfr->basic.T) | ||
1002 | regs.psw.mask |= PSW_MASK_DAT; | ||
1003 | if (sfr->basic.W) | ||
1004 | regs.psw.mask |= PSW_MASK_WAIT; | ||
1005 | if (sfr->basic.P) | ||
1006 | regs.psw.mask |= PSW_MASK_PSTATE; | ||
1007 | switch (sfr->basic.AS) { | ||
1008 | case 0x0: | ||
1009 | regs.psw.mask |= PSW_ASC_PRIMARY; | ||
1010 | break; | ||
1011 | case 0x1: | ||
1012 | regs.psw.mask |= PSW_ASC_ACCREG; | ||
1013 | break; | ||
1014 | case 0x2: | ||
1015 | regs.psw.mask |= PSW_ASC_SECONDARY; | ||
1016 | break; | ||
1017 | case 0x3: | ||
1018 | regs.psw.mask |= PSW_ASC_HOME; | ||
1019 | break; | ||
1020 | } | ||
1021 | |||
1022 | /* The host-program-parameter (hpp) contains the sie control | ||
1023 | * block that is set by sie64a() in entry64.S. Check if hpp | ||
1024 | * refers to a valid control block and set sde_regs flags | ||
1025 | * accordingly. This would allow to use hpp values for other | ||
1026 | * purposes too. | ||
1027 | * For now, simply use a non-zero value as guest indicator. | ||
1028 | */ | ||
1029 | if (sfr->basic.hpp) | ||
1030 | sde_regs->in_guest = 1; | ||
1031 | |||
1032 | overflow = 0; | ||
1033 | if (perf_exclude_event(event, ®s, sde_regs)) | ||
1034 | goto out; | ||
1035 | if (perf_event_overflow(event, &data, ®s)) { | ||
1036 | overflow = 1; | ||
1037 | event->pmu->stop(event, 0); | ||
1038 | } | ||
1039 | perf_event_update_userpage(event); | ||
1040 | out: | ||
1041 | return overflow; | ||
1042 | } | ||
1043 | |||
1044 | static void perf_event_count_update(struct perf_event *event, u64 count) | ||
1045 | { | ||
1046 | local64_add(count, &event->count); | ||
1047 | } | ||
1048 | |||
1049 | static int sample_format_is_valid(struct hws_combined_entry *sample, | ||
1050 | unsigned int flags) | ||
1051 | { | ||
1052 | if (likely(flags & PERF_CPUM_SF_BASIC_MODE)) | ||
1053 | /* Only basic-sampling data entries with data-entry-format | ||
1054 | * version of 0x0001 can be processed. | ||
1055 | */ | ||
1056 | if (sample->basic.def != 0x0001) | ||
1057 | return 0; | ||
1058 | if (flags & PERF_CPUM_SF_DIAG_MODE) | ||
1059 | /* The data-entry-format number of diagnostic-sampling data | ||
1060 | * entries can vary. Because diagnostic data is just passed | ||
1061 | * through, do only a sanity check on the DEF. | ||
1062 | */ | ||
1063 | if (sample->diag.def < 0x8001) | ||
1064 | return 0; | ||
1065 | return 1; | ||
1066 | } | ||
1067 | |||
1068 | static int sample_is_consistent(struct hws_combined_entry *sample, | ||
1069 | unsigned long flags) | ||
1070 | { | ||
1071 | /* This check applies only to basic-sampling data entries of potentially | ||
1072 | * combined-sampling data entries. Invalid entries cannot be processed | ||
1073 | * by the PMU and, thus, do not deliver an associated | ||
1074 | * diagnostic-sampling data entry. | ||
1075 | */ | ||
1076 | if (unlikely(!(flags & PERF_CPUM_SF_BASIC_MODE))) | ||
1077 | return 0; | ||
1078 | /* | ||
1079 | * Samples are skipped, if they are invalid or for which the | ||
1080 | * instruction address is not predictable, i.e., the wait-state bit is | ||
1081 | * set. | ||
1082 | */ | ||
1083 | if (sample->basic.I || sample->basic.W) | ||
1084 | return 0; | ||
1085 | return 1; | ||
1086 | } | ||
1087 | |||
1088 | static void reset_sample_slot(struct hws_combined_entry *sample, | ||
1089 | unsigned long flags) | ||
1090 | { | ||
1091 | if (likely(flags & PERF_CPUM_SF_BASIC_MODE)) | ||
1092 | sample->basic.def = 0; | ||
1093 | if (flags & PERF_CPUM_SF_DIAG_MODE) | ||
1094 | sample->diag.def = 0; | ||
1095 | } | ||
1096 | |||
1097 | static void sfr_store_sample(struct sf_raw_sample *sfr, | ||
1098 | struct hws_combined_entry *sample) | ||
1099 | { | ||
1100 | if (likely(sfr->format & PERF_CPUM_SF_BASIC_MODE)) | ||
1101 | sfr->basic = sample->basic; | ||
1102 | if (sfr->format & PERF_CPUM_SF_DIAG_MODE) | ||
1103 | memcpy(&sfr->diag, &sample->diag, sfr->dsdes); | ||
1104 | } | ||
1105 | |||
1106 | static void debug_sample_entry(struct hws_combined_entry *sample, | ||
1107 | struct hws_trailer_entry *te, | ||
1108 | unsigned long flags) | ||
1109 | { | ||
1110 | debug_sprintf_event(sfdbg, 4, "hw_collect_samples: Found unknown " | ||
1111 | "sampling data entry: te->f=%i basic.def=%04x (%p)" | ||
1112 | " diag.def=%04x (%p)\n", te->f, | ||
1113 | sample->basic.def, &sample->basic, | ||
1114 | (flags & PERF_CPUM_SF_DIAG_MODE) | ||
1115 | ? sample->diag.def : 0xFFFF, | ||
1116 | (flags & PERF_CPUM_SF_DIAG_MODE) | ||
1117 | ? &sample->diag : NULL); | ||
1118 | } | ||
1119 | |||
1120 | /* hw_collect_samples() - Walk through a sample-data-block and collect samples | ||
1121 | * @event: The perf event | ||
1122 | * @sdbt: Sample-data-block table | ||
1123 | * @overflow: Event overflow counter | ||
1124 | * | ||
1125 | * Walks through a sample-data-block and collects sampling data entries that are | ||
1126 | * then pushed to the perf event subsystem. Depending on the sampling function, | ||
1127 | * there can be either basic-sampling or combined-sampling data entries. A | ||
1128 | * combined-sampling data entry consists of a basic- and a diagnostic-sampling | ||
1129 | * data entry. The sampling function is determined by the flags in the perf | ||
1130 | * event hardware structure. The function always works with a combined-sampling | ||
1131 | * data entry but ignores the the diagnostic portion if it is not available. | ||
1132 | * | ||
1133 | * Note that the implementation focuses on basic-sampling data entries and, if | ||
1134 | * such an entry is not valid, the entire combined-sampling data entry is | ||
1135 | * ignored. | ||
1136 | * | ||
1137 | * The overflow variables counts the number of samples that has been discarded | ||
1138 | * due to a perf event overflow. | ||
1139 | */ | ||
1140 | static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, | ||
1141 | unsigned long long *overflow) | ||
1142 | { | ||
1143 | unsigned long flags = SAMPL_FLAGS(&event->hw); | ||
1144 | struct hws_combined_entry *sample; | ||
1145 | struct hws_trailer_entry *te; | ||
1146 | struct sf_raw_sample *sfr; | ||
1147 | size_t sample_size; | ||
1148 | |||
1149 | /* Prepare and initialize raw sample data */ | ||
1150 | sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(&event->hw); | ||
1151 | sfr->format = flags & PERF_CPUM_SF_MODE_MASK; | ||
1152 | |||
1153 | sample_size = event_sample_size(&event->hw); | ||
1154 | te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt); | ||
1155 | sample = (struct hws_combined_entry *) *sdbt; | ||
1156 | while ((unsigned long *) sample < (unsigned long *) te) { | ||
1157 | /* Check for an empty sample */ | ||
1158 | if (!sample->basic.def) | ||
1159 | break; | ||
1160 | |||
1161 | /* Update perf event period */ | ||
1162 | perf_event_count_update(event, SAMPL_RATE(&event->hw)); | ||
1163 | |||
1164 | /* Check sampling data entry */ | ||
1165 | if (sample_format_is_valid(sample, flags)) { | ||
1166 | /* If an event overflow occurred, the PMU is stopped to | ||
1167 | * throttle event delivery. Remaining sample data is | ||
1168 | * discarded. | ||
1169 | */ | ||
1170 | if (!*overflow) { | ||
1171 | if (sample_is_consistent(sample, flags)) { | ||
1172 | /* Deliver sample data to perf */ | ||
1173 | sfr_store_sample(sfr, sample); | ||
1174 | *overflow = perf_push_sample(event, sfr); | ||
1175 | } | ||
1176 | } else | ||
1177 | /* Count discarded samples */ | ||
1178 | *overflow += 1; | ||
1179 | } else { | ||
1180 | debug_sample_entry(sample, te, flags); | ||
1181 | /* Sample slot is not yet written or other record. | ||
1182 | * | ||
1183 | * This condition can occur if the buffer was reused | ||
1184 | * from a combined basic- and diagnostic-sampling. | ||
1185 | * If only basic-sampling is then active, entries are | ||
1186 | * written into the larger diagnostic entries. | ||
1187 | * This is typically the case for sample-data-blocks | ||
1188 | * that are not full. Stop processing if the first | ||
1189 | * invalid format was detected. | ||
1190 | */ | ||
1191 | if (!te->f) | ||
1192 | break; | ||
1193 | } | ||
1194 | |||
1195 | /* Reset sample slot and advance to next sample */ | ||
1196 | reset_sample_slot(sample, flags); | ||
1197 | sample += sample_size; | ||
1198 | } | ||
1199 | } | ||
1200 | |||
1201 | /* hw_perf_event_update() - Process sampling buffer | ||
1202 | * @event: The perf event | ||
1203 | * @flush_all: Flag to also flush partially filled sample-data-blocks | ||
1204 | * | ||
1205 | * Processes the sampling buffer and create perf event samples. | ||
1206 | * The sampling buffer position are retrieved and saved in the TEAR_REG | ||
1207 | * register of the specified perf event. | ||
1208 | * | ||
1209 | * Only full sample-data-blocks are processed. Specify the flash_all flag | ||
1210 | * to also walk through partially filled sample-data-blocks. It is ignored | ||
1211 | * if PERF_CPUM_SF_FULL_BLOCKS is set. The PERF_CPUM_SF_FULL_BLOCKS flag | ||
1212 | * enforces the processing of full sample-data-blocks only (trailer entries | ||
1213 | * with the block-full-indicator bit set). | ||
1214 | */ | ||
1215 | static void hw_perf_event_update(struct perf_event *event, int flush_all) | ||
1216 | { | ||
1217 | struct hw_perf_event *hwc = &event->hw; | ||
1218 | struct hws_trailer_entry *te; | ||
1219 | unsigned long *sdbt; | ||
1220 | unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags; | ||
1221 | int done; | ||
1222 | |||
1223 | if (flush_all && SDB_FULL_BLOCKS(hwc)) | ||
1224 | flush_all = 0; | ||
1225 | |||
1226 | sdbt = (unsigned long *) TEAR_REG(hwc); | ||
1227 | done = event_overflow = sampl_overflow = num_sdb = 0; | ||
1228 | while (!done) { | ||
1229 | /* Get the trailer entry of the sample-data-block */ | ||
1230 | te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt); | ||
1231 | |||
1232 | /* Leave loop if no more work to do (block full indicator) */ | ||
1233 | if (!te->f) { | ||
1234 | done = 1; | ||
1235 | if (!flush_all) | ||
1236 | break; | ||
1237 | } | ||
1238 | |||
1239 | /* Check the sample overflow count */ | ||
1240 | if (te->overflow) | ||
1241 | /* Account sample overflows and, if a particular limit | ||
1242 | * is reached, extend the sampling buffer. | ||
1243 | * For details, see sfb_account_overflows(). | ||
1244 | */ | ||
1245 | sampl_overflow += te->overflow; | ||
1246 | |||
1247 | /* Timestamps are valid for full sample-data-blocks only */ | ||
1248 | debug_sprintf_event(sfdbg, 6, "hw_perf_event_update: sdbt=%p " | ||
1249 | "overflow=%llu timestamp=0x%llx\n", | ||
1250 | sdbt, te->overflow, | ||
1251 | (te->f) ? trailer_timestamp(te) : 0ULL); | ||
1252 | |||
1253 | /* Collect all samples from a single sample-data-block and | ||
1254 | * flag if an (perf) event overflow happened. If so, the PMU | ||
1255 | * is stopped and remaining samples will be discarded. | ||
1256 | */ | ||
1257 | hw_collect_samples(event, sdbt, &event_overflow); | ||
1258 | num_sdb++; | ||
1259 | |||
1260 | /* Reset trailer (using compare-double-and-swap) */ | ||
1261 | do { | ||
1262 | te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK; | ||
1263 | te_flags |= SDB_TE_ALERT_REQ_MASK; | ||
1264 | } while (!cmpxchg_double(&te->flags, &te->overflow, | ||
1265 | te->flags, te->overflow, | ||
1266 | te_flags, 0ULL)); | ||
1267 | |||
1268 | /* Advance to next sample-data-block */ | ||
1269 | sdbt++; | ||
1270 | if (is_link_entry(sdbt)) | ||
1271 | sdbt = get_next_sdbt(sdbt); | ||
1272 | |||
1273 | /* Update event hardware registers */ | ||
1274 | TEAR_REG(hwc) = (unsigned long) sdbt; | ||
1275 | |||
1276 | /* Stop processing sample-data if all samples of the current | ||
1277 | * sample-data-block were flushed even if it was not full. | ||
1278 | */ | ||
1279 | if (flush_all && done) | ||
1280 | break; | ||
1281 | |||
1282 | /* If an event overflow happened, discard samples by | ||
1283 | * processing any remaining sample-data-blocks. | ||
1284 | */ | ||
1285 | if (event_overflow) | ||
1286 | flush_all = 1; | ||
1287 | } | ||
1288 | |||
1289 | /* Account sample overflows in the event hardware structure */ | ||
1290 | if (sampl_overflow) | ||
1291 | OVERFLOW_REG(hwc) = DIV_ROUND_UP(OVERFLOW_REG(hwc) + | ||
1292 | sampl_overflow, 1 + num_sdb); | ||
1293 | if (sampl_overflow || event_overflow) | ||
1294 | debug_sprintf_event(sfdbg, 4, "hw_perf_event_update: " | ||
1295 | "overflow stats: sample=%llu event=%llu\n", | ||
1296 | sampl_overflow, event_overflow); | ||
1297 | } | ||
1298 | |||
1299 | static void cpumsf_pmu_read(struct perf_event *event) | ||
1300 | { | ||
1301 | /* Nothing to do ... updates are interrupt-driven */ | ||
1302 | } | ||
1303 | |||
1304 | /* Activate sampling control. | ||
1305 | * Next call of pmu_enable() starts sampling. | ||
1306 | */ | ||
1307 | static void cpumsf_pmu_start(struct perf_event *event, int flags) | ||
1308 | { | ||
1309 | struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); | ||
1310 | |||
1311 | if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) | ||
1312 | return; | ||
1313 | |||
1314 | if (flags & PERF_EF_RELOAD) | ||
1315 | WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); | ||
1316 | |||
1317 | perf_pmu_disable(event->pmu); | ||
1318 | event->hw.state = 0; | ||
1319 | cpuhw->lsctl.cs = 1; | ||
1320 | if (SAMPL_DIAG_MODE(&event->hw)) | ||
1321 | cpuhw->lsctl.cd = 1; | ||
1322 | perf_pmu_enable(event->pmu); | ||
1323 | } | ||
1324 | |||
1325 | /* Deactivate sampling control. | ||
1326 | * Next call of pmu_enable() stops sampling. | ||
1327 | */ | ||
1328 | static void cpumsf_pmu_stop(struct perf_event *event, int flags) | ||
1329 | { | ||
1330 | struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); | ||
1331 | |||
1332 | if (event->hw.state & PERF_HES_STOPPED) | ||
1333 | return; | ||
1334 | |||
1335 | perf_pmu_disable(event->pmu); | ||
1336 | cpuhw->lsctl.cs = 0; | ||
1337 | cpuhw->lsctl.cd = 0; | ||
1338 | event->hw.state |= PERF_HES_STOPPED; | ||
1339 | |||
1340 | if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) { | ||
1341 | hw_perf_event_update(event, 1); | ||
1342 | event->hw.state |= PERF_HES_UPTODATE; | ||
1343 | } | ||
1344 | perf_pmu_enable(event->pmu); | ||
1345 | } | ||
1346 | |||
1347 | static int cpumsf_pmu_add(struct perf_event *event, int flags) | ||
1348 | { | ||
1349 | struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); | ||
1350 | int err; | ||
1351 | |||
1352 | if (cpuhw->flags & PMU_F_IN_USE) | ||
1353 | return -EAGAIN; | ||
1354 | |||
1355 | if (!cpuhw->sfb.sdbt) | ||
1356 | return -EINVAL; | ||
1357 | |||
1358 | err = 0; | ||
1359 | perf_pmu_disable(event->pmu); | ||
1360 | |||
1361 | event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED; | ||
1362 | |||
1363 | /* Set up sampling controls. Always program the sampling register | ||
1364 | * using the SDB-table start. Reset TEAR_REG event hardware register | ||
1365 | * that is used by hw_perf_event_update() to store the sampling buffer | ||
1366 | * position after samples have been flushed. | ||
1367 | */ | ||
1368 | cpuhw->lsctl.s = 0; | ||
1369 | cpuhw->lsctl.h = 1; | ||
1370 | cpuhw->lsctl.tear = (unsigned long) cpuhw->sfb.sdbt; | ||
1371 | cpuhw->lsctl.dear = *(unsigned long *) cpuhw->sfb.sdbt; | ||
1372 | cpuhw->lsctl.interval = SAMPL_RATE(&event->hw); | ||
1373 | hw_reset_registers(&event->hw, cpuhw->sfb.sdbt); | ||
1374 | |||
1375 | /* Ensure sampling functions are in the disabled state. If disabled, | ||
1376 | * switch on sampling enable control. */ | ||
1377 | if (WARN_ON_ONCE(cpuhw->lsctl.es == 1 || cpuhw->lsctl.ed == 1)) { | ||
1378 | err = -EAGAIN; | ||
1379 | goto out; | ||
1380 | } | ||
1381 | cpuhw->lsctl.es = 1; | ||
1382 | if (SAMPL_DIAG_MODE(&event->hw)) | ||
1383 | cpuhw->lsctl.ed = 1; | ||
1384 | |||
1385 | /* Set in_use flag and store event */ | ||
1386 | event->hw.idx = 0; /* only one sampling event per CPU supported */ | ||
1387 | cpuhw->event = event; | ||
1388 | cpuhw->flags |= PMU_F_IN_USE; | ||
1389 | |||
1390 | if (flags & PERF_EF_START) | ||
1391 | cpumsf_pmu_start(event, PERF_EF_RELOAD); | ||
1392 | out: | ||
1393 | perf_event_update_userpage(event); | ||
1394 | perf_pmu_enable(event->pmu); | ||
1395 | return err; | ||
1396 | } | ||
1397 | |||
1398 | static void cpumsf_pmu_del(struct perf_event *event, int flags) | ||
1399 | { | ||
1400 | struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf); | ||
1401 | |||
1402 | perf_pmu_disable(event->pmu); | ||
1403 | cpumsf_pmu_stop(event, PERF_EF_UPDATE); | ||
1404 | |||
1405 | cpuhw->lsctl.es = 0; | ||
1406 | cpuhw->lsctl.ed = 0; | ||
1407 | cpuhw->flags &= ~PMU_F_IN_USE; | ||
1408 | cpuhw->event = NULL; | ||
1409 | |||
1410 | perf_event_update_userpage(event); | ||
1411 | perf_pmu_enable(event->pmu); | ||
1412 | } | ||
1413 | |||
1414 | static int cpumsf_pmu_event_idx(struct perf_event *event) | ||
1415 | { | ||
1416 | return event->hw.idx; | ||
1417 | } | ||
1418 | |||
1419 | CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC, PERF_EVENT_CPUM_SF); | ||
1420 | CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC_DIAG, PERF_EVENT_CPUM_SF_DIAG); | ||
1421 | |||
1422 | static struct attribute *cpumsf_pmu_events_attr[] = { | ||
1423 | CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC), | ||
1424 | CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC_DIAG), | ||
1425 | NULL, | ||
1426 | }; | ||
1427 | |||
1428 | PMU_FORMAT_ATTR(event, "config:0-63"); | ||
1429 | |||
1430 | static struct attribute *cpumsf_pmu_format_attr[] = { | ||
1431 | &format_attr_event.attr, | ||
1432 | NULL, | ||
1433 | }; | ||
1434 | |||
1435 | static struct attribute_group cpumsf_pmu_events_group = { | ||
1436 | .name = "events", | ||
1437 | .attrs = cpumsf_pmu_events_attr, | ||
1438 | }; | ||
1439 | static struct attribute_group cpumsf_pmu_format_group = { | ||
1440 | .name = "format", | ||
1441 | .attrs = cpumsf_pmu_format_attr, | ||
1442 | }; | ||
1443 | static const struct attribute_group *cpumsf_pmu_attr_groups[] = { | ||
1444 | &cpumsf_pmu_events_group, | ||
1445 | &cpumsf_pmu_format_group, | ||
1446 | NULL, | ||
1447 | }; | ||
1448 | |||
1449 | static struct pmu cpumf_sampling = { | ||
1450 | .pmu_enable = cpumsf_pmu_enable, | ||
1451 | .pmu_disable = cpumsf_pmu_disable, | ||
1452 | |||
1453 | .event_init = cpumsf_pmu_event_init, | ||
1454 | .add = cpumsf_pmu_add, | ||
1455 | .del = cpumsf_pmu_del, | ||
1456 | |||
1457 | .start = cpumsf_pmu_start, | ||
1458 | .stop = cpumsf_pmu_stop, | ||
1459 | .read = cpumsf_pmu_read, | ||
1460 | |||
1461 | .event_idx = cpumsf_pmu_event_idx, | ||
1462 | .attr_groups = cpumsf_pmu_attr_groups, | ||
1463 | }; | ||
1464 | |||
1465 | static void cpumf_measurement_alert(struct ext_code ext_code, | ||
1466 | unsigned int alert, unsigned long unused) | ||
1467 | { | ||
1468 | struct cpu_hw_sf *cpuhw; | ||
1469 | |||
1470 | if (!(alert & CPU_MF_INT_SF_MASK)) | ||
1471 | return; | ||
1472 | inc_irq_stat(IRQEXT_CMS); | ||
1473 | cpuhw = &__get_cpu_var(cpu_hw_sf); | ||
1474 | |||
1475 | /* Measurement alerts are shared and might happen when the PMU | ||
1476 | * is not reserved. Ignore these alerts in this case. */ | ||
1477 | if (!(cpuhw->flags & PMU_F_RESERVED)) | ||
1478 | return; | ||
1479 | |||
1480 | /* The processing below must take care of multiple alert events that | ||
1481 | * might be indicated concurrently. */ | ||
1482 | |||
1483 | /* Program alert request */ | ||
1484 | if (alert & CPU_MF_INT_SF_PRA) { | ||
1485 | if (cpuhw->flags & PMU_F_IN_USE) | ||
1486 | hw_perf_event_update(cpuhw->event, 0); | ||
1487 | else | ||
1488 | WARN_ON_ONCE(!(cpuhw->flags & PMU_F_IN_USE)); | ||
1489 | } | ||
1490 | |||
1491 | /* Report measurement alerts only for non-PRA codes */ | ||
1492 | if (alert != CPU_MF_INT_SF_PRA) | ||
1493 | debug_sprintf_event(sfdbg, 6, "measurement alert: 0x%x\n", alert); | ||
1494 | |||
1495 | /* Sampling authorization change request */ | ||
1496 | if (alert & CPU_MF_INT_SF_SACA) | ||
1497 | qsi(&cpuhw->qsi); | ||
1498 | |||
1499 | /* Loss of sample data due to high-priority machine activities */ | ||
1500 | if (alert & CPU_MF_INT_SF_LSDA) { | ||
1501 | pr_err("Sample data was lost\n"); | ||
1502 | cpuhw->flags |= PMU_F_ERR_LSDA; | ||
1503 | sf_disable(); | ||
1504 | } | ||
1505 | |||
1506 | /* Invalid sampling buffer entry */ | ||
1507 | if (alert & (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE)) { | ||
1508 | pr_err("A sampling buffer entry is incorrect (alert=0x%x)\n", | ||
1509 | alert); | ||
1510 | cpuhw->flags |= PMU_F_ERR_IBE; | ||
1511 | sf_disable(); | ||
1512 | } | ||
1513 | } | ||
1514 | |||
1515 | static int cpumf_pmu_notifier(struct notifier_block *self, | ||
1516 | unsigned long action, void *hcpu) | ||
1517 | { | ||
1518 | unsigned int cpu = (long) hcpu; | ||
1519 | int flags; | ||
1520 | |||
1521 | /* Ignore the notification if no events are scheduled on the PMU. | ||
1522 | * This might be racy... | ||
1523 | */ | ||
1524 | if (!atomic_read(&num_events)) | ||
1525 | return NOTIFY_OK; | ||
1526 | |||
1527 | switch (action & ~CPU_TASKS_FROZEN) { | ||
1528 | case CPU_ONLINE: | ||
1529 | case CPU_ONLINE_FROZEN: | ||
1530 | flags = PMC_INIT; | ||
1531 | smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1); | ||
1532 | break; | ||
1533 | case CPU_DOWN_PREPARE: | ||
1534 | flags = PMC_RELEASE; | ||
1535 | smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1); | ||
1536 | break; | ||
1537 | default: | ||
1538 | break; | ||
1539 | } | ||
1540 | |||
1541 | return NOTIFY_OK; | ||
1542 | } | ||
1543 | |||
1544 | static int param_get_sfb_size(char *buffer, const struct kernel_param *kp) | ||
1545 | { | ||
1546 | if (!cpum_sf_avail()) | ||
1547 | return -ENODEV; | ||
1548 | return sprintf(buffer, "%lu,%lu", CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB); | ||
1549 | } | ||
1550 | |||
1551 | static int param_set_sfb_size(const char *val, const struct kernel_param *kp) | ||
1552 | { | ||
1553 | int rc; | ||
1554 | unsigned long min, max; | ||
1555 | |||
1556 | if (!cpum_sf_avail()) | ||
1557 | return -ENODEV; | ||
1558 | if (!val || !strlen(val)) | ||
1559 | return -EINVAL; | ||
1560 | |||
1561 | /* Valid parameter values: "min,max" or "max" */ | ||
1562 | min = CPUM_SF_MIN_SDB; | ||
1563 | max = CPUM_SF_MAX_SDB; | ||
1564 | if (strchr(val, ',')) | ||
1565 | rc = (sscanf(val, "%lu,%lu", &min, &max) == 2) ? 0 : -EINVAL; | ||
1566 | else | ||
1567 | rc = kstrtoul(val, 10, &max); | ||
1568 | |||
1569 | if (min < 2 || min >= max || max > get_num_physpages()) | ||
1570 | rc = -EINVAL; | ||
1571 | if (rc) | ||
1572 | return rc; | ||
1573 | |||
1574 | sfb_set_limits(min, max); | ||
1575 | pr_info("The sampling buffer limits have changed to: " | ||
1576 | "min=%lu max=%lu (diag=x%lu)\n", | ||
1577 | CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB, CPUM_SF_SDB_DIAG_FACTOR); | ||
1578 | return 0; | ||
1579 | } | ||
1580 | |||
1581 | #define param_check_sfb_size(name, p) __param_check(name, p, void) | ||
1582 | static struct kernel_param_ops param_ops_sfb_size = { | ||
1583 | .set = param_set_sfb_size, | ||
1584 | .get = param_get_sfb_size, | ||
1585 | }; | ||
1586 | |||
1587 | #define RS_INIT_FAILURE_QSI 0x0001 | ||
1588 | #define RS_INIT_FAILURE_BSDES 0x0002 | ||
1589 | #define RS_INIT_FAILURE_ALRT 0x0003 | ||
1590 | #define RS_INIT_FAILURE_PERF 0x0004 | ||
1591 | static void __init pr_cpumsf_err(unsigned int reason) | ||
1592 | { | ||
1593 | pr_err("Sampling facility support for perf is not available: " | ||
1594 | "reason=%04x\n", reason); | ||
1595 | } | ||
1596 | |||
1597 | static int __init init_cpum_sampling_pmu(void) | ||
1598 | { | ||
1599 | struct hws_qsi_info_block si; | ||
1600 | int err; | ||
1601 | |||
1602 | if (!cpum_sf_avail()) | ||
1603 | return -ENODEV; | ||
1604 | |||
1605 | memset(&si, 0, sizeof(si)); | ||
1606 | if (qsi(&si)) { | ||
1607 | pr_cpumsf_err(RS_INIT_FAILURE_QSI); | ||
1608 | return -ENODEV; | ||
1609 | } | ||
1610 | |||
1611 | if (si.bsdes != sizeof(struct hws_basic_entry)) { | ||
1612 | pr_cpumsf_err(RS_INIT_FAILURE_BSDES); | ||
1613 | return -EINVAL; | ||
1614 | } | ||
1615 | |||
1616 | if (si.ad) | ||
1617 | sfb_set_limits(CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB); | ||
1618 | |||
1619 | sfdbg = debug_register(KMSG_COMPONENT, 2, 1, 80); | ||
1620 | if (!sfdbg) | ||
1621 | pr_err("Registering for s390dbf failed\n"); | ||
1622 | debug_register_view(sfdbg, &debug_sprintf_view); | ||
1623 | |||
1624 | err = register_external_interrupt(0x1407, cpumf_measurement_alert); | ||
1625 | if (err) { | ||
1626 | pr_cpumsf_err(RS_INIT_FAILURE_ALRT); | ||
1627 | goto out; | ||
1628 | } | ||
1629 | |||
1630 | err = perf_pmu_register(&cpumf_sampling, "cpum_sf", PERF_TYPE_RAW); | ||
1631 | if (err) { | ||
1632 | pr_cpumsf_err(RS_INIT_FAILURE_PERF); | ||
1633 | unregister_external_interrupt(0x1407, cpumf_measurement_alert); | ||
1634 | goto out; | ||
1635 | } | ||
1636 | perf_cpu_notifier(cpumf_pmu_notifier); | ||
1637 | out: | ||
1638 | return err; | ||
1639 | } | ||
1640 | arch_initcall(init_cpum_sampling_pmu); | ||
1641 | core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0640); | ||
diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c index 2343c218b8f9..5d2dfa31c4ef 100644 --- a/arch/s390/kernel/perf_event.c +++ b/arch/s390/kernel/perf_event.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Performance event support for s390x | 2 | * Performance event support for s390x |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2012 | 4 | * Copyright IBM Corp. 2012, 2013 |
5 | * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 5 | * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -16,15 +16,19 @@ | |||
16 | #include <linux/kvm_host.h> | 16 | #include <linux/kvm_host.h> |
17 | #include <linux/percpu.h> | 17 | #include <linux/percpu.h> |
18 | #include <linux/export.h> | 18 | #include <linux/export.h> |
19 | #include <linux/seq_file.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/sysfs.h> | ||
19 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
20 | #include <asm/cpu_mf.h> | 23 | #include <asm/cpu_mf.h> |
21 | #include <asm/lowcore.h> | 24 | #include <asm/lowcore.h> |
22 | #include <asm/processor.h> | 25 | #include <asm/processor.h> |
26 | #include <asm/sysinfo.h> | ||
23 | 27 | ||
24 | const char *perf_pmu_name(void) | 28 | const char *perf_pmu_name(void) |
25 | { | 29 | { |
26 | if (cpum_cf_avail() || cpum_sf_avail()) | 30 | if (cpum_cf_avail() || cpum_sf_avail()) |
27 | return "CPU-measurement facilities (CPUMF)"; | 31 | return "CPU-Measurement Facilities (CPU-MF)"; |
28 | return "pmu"; | 32 | return "pmu"; |
29 | } | 33 | } |
30 | EXPORT_SYMBOL(perf_pmu_name); | 34 | EXPORT_SYMBOL(perf_pmu_name); |
@@ -35,6 +39,8 @@ int perf_num_counters(void) | |||
35 | 39 | ||
36 | if (cpum_cf_avail()) | 40 | if (cpum_cf_avail()) |
37 | num += PERF_CPUM_CF_MAX_CTR; | 41 | num += PERF_CPUM_CF_MAX_CTR; |
42 | if (cpum_sf_avail()) | ||
43 | num += PERF_CPUM_SF_MAX_CTR; | ||
38 | 44 | ||
39 | return num; | 45 | return num; |
40 | } | 46 | } |
@@ -54,7 +60,7 @@ static bool is_in_guest(struct pt_regs *regs) | |||
54 | { | 60 | { |
55 | if (user_mode(regs)) | 61 | if (user_mode(regs)) |
56 | return false; | 62 | return false; |
57 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 63 | #if IS_ENABLED(CONFIG_KVM) |
58 | return instruction_pointer(regs) == (unsigned long) &sie_exit; | 64 | return instruction_pointer(regs) == (unsigned long) &sie_exit; |
59 | #else | 65 | #else |
60 | return false; | 66 | return false; |
@@ -83,8 +89,31 @@ static unsigned long perf_misc_guest_flags(struct pt_regs *regs) | |||
83 | : PERF_RECORD_MISC_GUEST_KERNEL; | 89 | : PERF_RECORD_MISC_GUEST_KERNEL; |
84 | } | 90 | } |
85 | 91 | ||
92 | static unsigned long perf_misc_flags_sf(struct pt_regs *regs) | ||
93 | { | ||
94 | struct perf_sf_sde_regs *sde_regs; | ||
95 | unsigned long flags; | ||
96 | |||
97 | sde_regs = (struct perf_sf_sde_regs *) ®s->int_parm_long; | ||
98 | if (sde_regs->in_guest) | ||
99 | flags = user_mode(regs) ? PERF_RECORD_MISC_GUEST_USER | ||
100 | : PERF_RECORD_MISC_GUEST_KERNEL; | ||
101 | else | ||
102 | flags = user_mode(regs) ? PERF_RECORD_MISC_USER | ||
103 | : PERF_RECORD_MISC_KERNEL; | ||
104 | return flags; | ||
105 | } | ||
106 | |||
86 | unsigned long perf_misc_flags(struct pt_regs *regs) | 107 | unsigned long perf_misc_flags(struct pt_regs *regs) |
87 | { | 108 | { |
109 | /* Check if the cpum_sf PMU has created the pt_regs structure. | ||
110 | * In this case, perf misc flags can be easily extracted. Otherwise, | ||
111 | * do regular checks on the pt_regs content. | ||
112 | */ | ||
113 | if (regs->int_code == 0x1407 && regs->int_parm == CPU_MF_INT_SF_PRA) | ||
114 | if (!regs->gprs[15]) | ||
115 | return perf_misc_flags_sf(regs); | ||
116 | |||
88 | if (is_in_guest(regs)) | 117 | if (is_in_guest(regs)) |
89 | return perf_misc_guest_flags(regs); | 118 | return perf_misc_guest_flags(regs); |
90 | 119 | ||
@@ -92,27 +121,107 @@ unsigned long perf_misc_flags(struct pt_regs *regs) | |||
92 | : PERF_RECORD_MISC_KERNEL; | 121 | : PERF_RECORD_MISC_KERNEL; |
93 | } | 122 | } |
94 | 123 | ||
95 | void perf_event_print_debug(void) | 124 | void print_debug_cf(void) |
96 | { | 125 | { |
97 | struct cpumf_ctr_info cf_info; | 126 | struct cpumf_ctr_info cf_info; |
98 | unsigned long flags; | 127 | int cpu = smp_processor_id(); |
99 | int cpu; | ||
100 | |||
101 | if (!cpum_cf_avail()) | ||
102 | return; | ||
103 | |||
104 | local_irq_save(flags); | ||
105 | 128 | ||
106 | cpu = smp_processor_id(); | ||
107 | memset(&cf_info, 0, sizeof(cf_info)); | 129 | memset(&cf_info, 0, sizeof(cf_info)); |
108 | if (!qctri(&cf_info)) | 130 | if (!qctri(&cf_info)) |
109 | pr_info("CPU[%i] CPUM_CF: ver=%u.%u A=%04x E=%04x C=%04x\n", | 131 | pr_info("CPU[%i] CPUM_CF: ver=%u.%u A=%04x E=%04x C=%04x\n", |
110 | cpu, cf_info.cfvn, cf_info.csvn, | 132 | cpu, cf_info.cfvn, cf_info.csvn, |
111 | cf_info.auth_ctl, cf_info.enable_ctl, cf_info.act_ctl); | 133 | cf_info.auth_ctl, cf_info.enable_ctl, cf_info.act_ctl); |
134 | } | ||
135 | |||
136 | static void print_debug_sf(void) | ||
137 | { | ||
138 | struct hws_qsi_info_block si; | ||
139 | int cpu = smp_processor_id(); | ||
112 | 140 | ||
141 | memset(&si, 0, sizeof(si)); | ||
142 | if (qsi(&si)) | ||
143 | return; | ||
144 | |||
145 | pr_info("CPU[%i] CPUM_SF: basic=%i diag=%i min=%lu max=%lu cpu_speed=%u\n", | ||
146 | cpu, si.as, si.ad, si.min_sampl_rate, si.max_sampl_rate, | ||
147 | si.cpu_speed); | ||
148 | |||
149 | if (si.as) | ||
150 | pr_info("CPU[%i] CPUM_SF: Basic-sampling: a=%i e=%i c=%i" | ||
151 | " bsdes=%i tear=%016lx dear=%016lx\n", cpu, | ||
152 | si.as, si.es, si.cs, si.bsdes, si.tear, si.dear); | ||
153 | if (si.ad) | ||
154 | pr_info("CPU[%i] CPUM_SF: Diagnostic-sampling: a=%i e=%i c=%i" | ||
155 | " dsdes=%i tear=%016lx dear=%016lx\n", cpu, | ||
156 | si.ad, si.ed, si.cd, si.dsdes, si.tear, si.dear); | ||
157 | } | ||
158 | |||
159 | void perf_event_print_debug(void) | ||
160 | { | ||
161 | unsigned long flags; | ||
162 | |||
163 | local_irq_save(flags); | ||
164 | if (cpum_cf_avail()) | ||
165 | print_debug_cf(); | ||
166 | if (cpum_sf_avail()) | ||
167 | print_debug_sf(); | ||
113 | local_irq_restore(flags); | 168 | local_irq_restore(flags); |
114 | } | 169 | } |
115 | 170 | ||
171 | /* Service level infrastructure */ | ||
172 | static void sl_print_counter(struct seq_file *m) | ||
173 | { | ||
174 | struct cpumf_ctr_info ci; | ||
175 | |||
176 | memset(&ci, 0, sizeof(ci)); | ||
177 | if (qctri(&ci)) | ||
178 | return; | ||
179 | |||
180 | seq_printf(m, "CPU-MF: Counter facility: version=%u.%u " | ||
181 | "authorization=%04x\n", ci.cfvn, ci.csvn, ci.auth_ctl); | ||
182 | } | ||
183 | |||
184 | static void sl_print_sampling(struct seq_file *m) | ||
185 | { | ||
186 | struct hws_qsi_info_block si; | ||
187 | |||
188 | memset(&si, 0, sizeof(si)); | ||
189 | if (qsi(&si)) | ||
190 | return; | ||
191 | |||
192 | if (!si.as && !si.ad) | ||
193 | return; | ||
194 | |||
195 | seq_printf(m, "CPU-MF: Sampling facility: min_rate=%lu max_rate=%lu" | ||
196 | " cpu_speed=%u\n", si.min_sampl_rate, si.max_sampl_rate, | ||
197 | si.cpu_speed); | ||
198 | if (si.as) | ||
199 | seq_printf(m, "CPU-MF: Sampling facility: mode=basic" | ||
200 | " sample_size=%u\n", si.bsdes); | ||
201 | if (si.ad) | ||
202 | seq_printf(m, "CPU-MF: Sampling facility: mode=diagnostic" | ||
203 | " sample_size=%u\n", si.dsdes); | ||
204 | } | ||
205 | |||
206 | static void service_level_perf_print(struct seq_file *m, | ||
207 | struct service_level *sl) | ||
208 | { | ||
209 | if (cpum_cf_avail()) | ||
210 | sl_print_counter(m); | ||
211 | if (cpum_sf_avail()) | ||
212 | sl_print_sampling(m); | ||
213 | } | ||
214 | |||
215 | static struct service_level service_level_perf = { | ||
216 | .seq_print = service_level_perf_print, | ||
217 | }; | ||
218 | |||
219 | static int __init service_level_perf_register(void) | ||
220 | { | ||
221 | return register_service_level(&service_level_perf); | ||
222 | } | ||
223 | arch_initcall(service_level_perf_register); | ||
224 | |||
116 | /* See also arch/s390/kernel/traps.c */ | 225 | /* See also arch/s390/kernel/traps.c */ |
117 | static unsigned long __store_trace(struct perf_callchain_entry *entry, | 226 | static unsigned long __store_trace(struct perf_callchain_entry *entry, |
118 | unsigned long sp, | 227 | unsigned long sp, |
@@ -172,3 +281,44 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, | |||
172 | __store_trace(entry, head, S390_lowcore.thread_info, | 281 | __store_trace(entry, head, S390_lowcore.thread_info, |
173 | S390_lowcore.thread_info + THREAD_SIZE); | 282 | S390_lowcore.thread_info + THREAD_SIZE); |
174 | } | 283 | } |
284 | |||
285 | /* Perf defintions for PMU event attributes in sysfs */ | ||
286 | ssize_t cpumf_events_sysfs_show(struct device *dev, | ||
287 | struct device_attribute *attr, char *page) | ||
288 | { | ||
289 | struct perf_pmu_events_attr *pmu_attr; | ||
290 | |||
291 | pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); | ||
292 | return sprintf(page, "event=0x%04llx,name=%s\n", | ||
293 | pmu_attr->id, attr->attr.name); | ||
294 | } | ||
295 | |||
296 | /* Reserve/release functions for sharing perf hardware */ | ||
297 | static DEFINE_SPINLOCK(perf_hw_owner_lock); | ||
298 | static void *perf_sampling_owner; | ||
299 | |||
300 | int perf_reserve_sampling(void) | ||
301 | { | ||
302 | int err; | ||
303 | |||
304 | err = 0; | ||
305 | spin_lock(&perf_hw_owner_lock); | ||
306 | if (perf_sampling_owner) { | ||
307 | pr_warn("The sampling facility is already reserved by %p\n", | ||
308 | perf_sampling_owner); | ||
309 | err = -EBUSY; | ||
310 | } else | ||
311 | perf_sampling_owner = __builtin_return_address(0); | ||
312 | spin_unlock(&perf_hw_owner_lock); | ||
313 | return err; | ||
314 | } | ||
315 | EXPORT_SYMBOL(perf_reserve_sampling); | ||
316 | |||
317 | void perf_release_sampling(void) | ||
318 | { | ||
319 | spin_lock(&perf_hw_owner_lock); | ||
320 | WARN_ON(!perf_sampling_owner); | ||
321 | perf_sampling_owner = NULL; | ||
322 | spin_unlock(&perf_hw_owner_lock); | ||
323 | } | ||
324 | EXPORT_SYMBOL(perf_release_sampling); | ||
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 7ed0d4e2a435..dd145321d215 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -261,20 +261,18 @@ static inline unsigned long brk_rnd(void) | |||
261 | 261 | ||
262 | unsigned long arch_randomize_brk(struct mm_struct *mm) | 262 | unsigned long arch_randomize_brk(struct mm_struct *mm) |
263 | { | 263 | { |
264 | unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); | 264 | unsigned long ret; |
265 | 265 | ||
266 | if (ret < mm->brk) | 266 | ret = PAGE_ALIGN(mm->brk + brk_rnd()); |
267 | return mm->brk; | 267 | return (ret > mm->brk) ? ret : mm->brk; |
268 | return ret; | ||
269 | } | 268 | } |
270 | 269 | ||
271 | unsigned long randomize_et_dyn(unsigned long base) | 270 | unsigned long randomize_et_dyn(unsigned long base) |
272 | { | 271 | { |
273 | unsigned long ret = PAGE_ALIGN(base + brk_rnd()); | 272 | unsigned long ret; |
274 | 273 | ||
275 | if (!(current->flags & PF_RANDOMIZE)) | 274 | if (!(current->flags & PF_RANDOMIZE)) |
276 | return base; | 275 | return base; |
277 | if (ret < base) | 276 | ret = PAGE_ALIGN(base + brk_rnd()); |
278 | return base; | 277 | return (ret > base) ? ret : base; |
279 | return ret; | ||
280 | } | 278 | } |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index e65c91c591e8..f6be6087a0e9 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -56,25 +56,26 @@ void update_cr_regs(struct task_struct *task) | |||
56 | #ifdef CONFIG_64BIT | 56 | #ifdef CONFIG_64BIT |
57 | /* Take care of the enable/disable of transactional execution. */ | 57 | /* Take care of the enable/disable of transactional execution. */ |
58 | if (MACHINE_HAS_TE) { | 58 | if (MACHINE_HAS_TE) { |
59 | unsigned long cr[3], cr_new[3]; | 59 | unsigned long cr, cr_new; |
60 | 60 | ||
61 | __ctl_store(cr, 0, 2); | 61 | __ctl_store(cr, 0, 0); |
62 | cr_new[1] = cr[1]; | ||
63 | /* Set or clear transaction execution TXC bit 8. */ | 62 | /* Set or clear transaction execution TXC bit 8. */ |
63 | cr_new = cr | (1UL << 55); | ||
64 | if (task->thread.per_flags & PER_FLAG_NO_TE) | 64 | if (task->thread.per_flags & PER_FLAG_NO_TE) |
65 | cr_new[0] = cr[0] & ~(1UL << 55); | 65 | cr_new &= ~(1UL << 55); |
66 | else | 66 | if (cr_new != cr) |
67 | cr_new[0] = cr[0] | (1UL << 55); | 67 | __ctl_load(cr, 0, 0); |
68 | /* Set or clear transaction execution TDC bits 62 and 63. */ | 68 | /* Set or clear transaction execution TDC bits 62 and 63. */ |
69 | cr_new[2] = cr[2] & ~3UL; | 69 | __ctl_store(cr, 2, 2); |
70 | cr_new = cr & ~3UL; | ||
70 | if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) { | 71 | if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) { |
71 | if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND) | 72 | if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND) |
72 | cr_new[2] |= 1UL; | 73 | cr_new |= 1UL; |
73 | else | 74 | else |
74 | cr_new[2] |= 2UL; | 75 | cr_new |= 2UL; |
75 | } | 76 | } |
76 | if (memcmp(&cr_new, &cr, sizeof(cr))) | 77 | if (cr_new != cr) |
77 | __ctl_load(cr_new, 0, 2); | 78 | __ctl_load(cr_new, 2, 2); |
78 | } | 79 | } |
79 | #endif | 80 | #endif |
80 | /* Copy user specified PER registers */ | 81 | /* Copy user specified PER registers */ |
@@ -107,15 +108,11 @@ void update_cr_regs(struct task_struct *task) | |||
107 | void user_enable_single_step(struct task_struct *task) | 108 | void user_enable_single_step(struct task_struct *task) |
108 | { | 109 | { |
109 | set_tsk_thread_flag(task, TIF_SINGLE_STEP); | 110 | set_tsk_thread_flag(task, TIF_SINGLE_STEP); |
110 | if (task == current) | ||
111 | update_cr_regs(task); | ||
112 | } | 111 | } |
113 | 112 | ||
114 | void user_disable_single_step(struct task_struct *task) | 113 | void user_disable_single_step(struct task_struct *task) |
115 | { | 114 | { |
116 | clear_tsk_thread_flag(task, TIF_SINGLE_STEP); | 115 | clear_tsk_thread_flag(task, TIF_SINGLE_STEP); |
117 | if (task == current) | ||
118 | update_cr_regs(task); | ||
119 | } | 116 | } |
120 | 117 | ||
121 | /* | 118 | /* |
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 3bac589844a7..9f60467938d1 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c | |||
@@ -5,7 +5,7 @@ | |||
5 | #ifdef CONFIG_FUNCTION_TRACER | 5 | #ifdef CONFIG_FUNCTION_TRACER |
6 | EXPORT_SYMBOL(_mcount); | 6 | EXPORT_SYMBOL(_mcount); |
7 | #endif | 7 | #endif |
8 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 8 | #if IS_ENABLED(CONFIG_KVM) |
9 | EXPORT_SYMBOL(sie64a); | 9 | EXPORT_SYMBOL(sie64a); |
10 | EXPORT_SYMBOL(sie_exit); | 10 | EXPORT_SYMBOL(sie_exit); |
11 | #endif | 11 | #endif |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 0f3d44ecbfc6..09e2f468f48b 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -373,7 +373,7 @@ static void __init setup_lowcore(void) | |||
373 | 373 | ||
374 | /* | 374 | /* |
375 | * Set up PSW restart to call ipl.c:do_restart(). Copy the relevant | 375 | * Set up PSW restart to call ipl.c:do_restart(). Copy the relevant |
376 | * restart data to the absolute zero lowcore. This is necesary if | 376 | * restart data to the absolute zero lowcore. This is necessary if |
377 | * PSW restart is done on an offline CPU that has lowcore zero. | 377 | * PSW restart is done on an offline CPU that has lowcore zero. |
378 | */ | 378 | */ |
379 | lc->restart_stack = (unsigned long) restart_stack; | 379 | lc->restart_stack = (unsigned long) restart_stack; |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 958704798f4a..a7125b62a9a6 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -59,7 +59,7 @@ enum { | |||
59 | }; | 59 | }; |
60 | 60 | ||
61 | struct pcpu { | 61 | struct pcpu { |
62 | struct cpu cpu; | 62 | struct cpu *cpu; |
63 | struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ | 63 | struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ |
64 | unsigned long async_stack; /* async stack for the cpu */ | 64 | unsigned long async_stack; /* async stack for the cpu */ |
65 | unsigned long panic_stack; /* panic stack for the cpu */ | 65 | unsigned long panic_stack; /* panic stack for the cpu */ |
@@ -159,9 +159,9 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) | |||
159 | { | 159 | { |
160 | int order; | 160 | int order; |
161 | 161 | ||
162 | set_bit(ec_bit, &pcpu->ec_mask); | 162 | if (test_and_set_bit(ec_bit, &pcpu->ec_mask)) |
163 | order = pcpu_running(pcpu) ? | 163 | return; |
164 | SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL; | 164 | order = pcpu_running(pcpu) ? SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL; |
165 | pcpu_sigp_retry(pcpu, order, 0); | 165 | pcpu_sigp_retry(pcpu, order, 0); |
166 | } | 166 | } |
167 | 167 | ||
@@ -965,7 +965,7 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action, | |||
965 | void *hcpu) | 965 | void *hcpu) |
966 | { | 966 | { |
967 | unsigned int cpu = (unsigned int)(long)hcpu; | 967 | unsigned int cpu = (unsigned int)(long)hcpu; |
968 | struct cpu *c = &pcpu_devices[cpu].cpu; | 968 | struct cpu *c = pcpu_devices[cpu].cpu; |
969 | struct device *s = &c->dev; | 969 | struct device *s = &c->dev; |
970 | int err = 0; | 970 | int err = 0; |
971 | 971 | ||
@@ -982,10 +982,15 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action, | |||
982 | 982 | ||
983 | static int smp_add_present_cpu(int cpu) | 983 | static int smp_add_present_cpu(int cpu) |
984 | { | 984 | { |
985 | struct cpu *c = &pcpu_devices[cpu].cpu; | 985 | struct device *s; |
986 | struct device *s = &c->dev; | 986 | struct cpu *c; |
987 | int rc; | 987 | int rc; |
988 | 988 | ||
989 | c = kzalloc(sizeof(*c), GFP_KERNEL); | ||
990 | if (!c) | ||
991 | return -ENOMEM; | ||
992 | pcpu_devices[cpu].cpu = c; | ||
993 | s = &c->dev; | ||
989 | c->hotpluggable = 1; | 994 | c->hotpluggable = 1; |
990 | rc = register_cpu(c, cpu); | 995 | rc = register_cpu(c, cpu); |
991 | if (rc) | 996 | if (rc) |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 2440602e6df1..d101dae62771 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -275,7 +275,7 @@ static int handle_io_inst(struct kvm_vcpu *vcpu) | |||
275 | return -EOPNOTSUPP; | 275 | return -EOPNOTSUPP; |
276 | } else { | 276 | } else { |
277 | /* | 277 | /* |
278 | * Set condition code 3 to stop the guest from issueing channel | 278 | * Set condition code 3 to stop the guest from issuing channel |
279 | * I/O instructions. | 279 | * I/O instructions. |
280 | */ | 280 | */ |
281 | kvm_s390_set_psw_cc(vcpu, 3); | 281 | kvm_s390_set_psw_cc(vcpu, 3); |
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index dbdab3e7a1a6..0632dc50da78 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c | |||
@@ -74,8 +74,8 @@ static size_t copy_in_kernel(size_t count, void __user *to, | |||
74 | 74 | ||
75 | /* | 75 | /* |
76 | * Returns kernel address for user virtual address. If the returned address is | 76 | * Returns kernel address for user virtual address. If the returned address is |
77 | * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address | 77 | * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occurred and the |
78 | * contains the (negative) exception code. | 78 | * address contains the (negative) exception code. |
79 | */ | 79 | */ |
80 | #ifdef CONFIG_64BIT | 80 | #ifdef CONFIG_64BIT |
81 | 81 | ||
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index e794c88f699a..3584ed9b20a1 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
@@ -293,7 +293,7 @@ static int gmap_alloc_table(struct gmap *gmap, | |||
293 | * @addr: address in the guest address space | 293 | * @addr: address in the guest address space |
294 | * @len: length of the memory area to unmap | 294 | * @len: length of the memory area to unmap |
295 | * | 295 | * |
296 | * Returns 0 if the unmap succeded, -EINVAL if not. | 296 | * Returns 0 if the unmap succeeded, -EINVAL if not. |
297 | */ | 297 | */ |
298 | int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len) | 298 | int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len) |
299 | { | 299 | { |
@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(gmap_unmap_segment); | |||
344 | * @from: source address in the parent address space | 344 | * @from: source address in the parent address space |
345 | * @to: target address in the guest address space | 345 | * @to: target address in the guest address space |
346 | * | 346 | * |
347 | * Returns 0 if the mmap succeded, -EINVAL or -ENOMEM if not. | 347 | * Returns 0 if the mmap succeeded, -EINVAL or -ENOMEM if not. |
348 | */ | 348 | */ |
349 | int gmap_map_segment(struct gmap *gmap, unsigned long from, | 349 | int gmap_map_segment(struct gmap *gmap, unsigned long from, |
350 | unsigned long to, unsigned long len) | 350 | unsigned long to, unsigned long len) |
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 16871da37371..708d60e40066 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c | |||
@@ -368,14 +368,16 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter, | |||
368 | EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg)); | 368 | EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg)); |
369 | /* lhi %r4,0 */ | 369 | /* lhi %r4,0 */ |
370 | EMIT4(0xa7480000); | 370 | EMIT4(0xa7480000); |
371 | /* dr %r4,%r12 */ | 371 | /* dlr %r4,%r12 */ |
372 | EMIT2(0x1d4c); | 372 | EMIT4(0xb997004c); |
373 | break; | 373 | break; |
374 | case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */ | 374 | case BPF_S_ALU_DIV_K: /* A /= K */ |
375 | /* m %r4,<d(K)>(%r13) */ | 375 | if (K == 1) |
376 | EMIT4_DISP(0x5c40d000, EMIT_CONST(K)); | 376 | break; |
377 | /* lr %r5,%r4 */ | 377 | /* lhi %r4,0 */ |
378 | EMIT2(0x1854); | 378 | EMIT4(0xa7480000); |
379 | /* dl %r4,<d(K)>(%r13) */ | ||
380 | EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K)); | ||
379 | break; | 381 | break; |
380 | case BPF_S_ALU_MOD_X: /* A %= X */ | 382 | case BPF_S_ALU_MOD_X: /* A %= X */ |
381 | jit->seen |= SEEN_XREG | SEEN_RET0; | 383 | jit->seen |= SEEN_XREG | SEEN_RET0; |
@@ -385,16 +387,21 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter, | |||
385 | EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg)); | 387 | EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg)); |
386 | /* lhi %r4,0 */ | 388 | /* lhi %r4,0 */ |
387 | EMIT4(0xa7480000); | 389 | EMIT4(0xa7480000); |
388 | /* dr %r4,%r12 */ | 390 | /* dlr %r4,%r12 */ |
389 | EMIT2(0x1d4c); | 391 | EMIT4(0xb997004c); |
390 | /* lr %r5,%r4 */ | 392 | /* lr %r5,%r4 */ |
391 | EMIT2(0x1854); | 393 | EMIT2(0x1854); |
392 | break; | 394 | break; |
393 | case BPF_S_ALU_MOD_K: /* A %= K */ | 395 | case BPF_S_ALU_MOD_K: /* A %= K */ |
396 | if (K == 1) { | ||
397 | /* lhi %r5,0 */ | ||
398 | EMIT4(0xa7580000); | ||
399 | break; | ||
400 | } | ||
394 | /* lhi %r4,0 */ | 401 | /* lhi %r4,0 */ |
395 | EMIT4(0xa7480000); | 402 | EMIT4(0xa7480000); |
396 | /* d %r4,<d(K)>(%r13) */ | 403 | /* dl %r4,<d(K)>(%r13) */ |
397 | EMIT4_DISP(0x5d40d000, EMIT_CONST(K)); | 404 | EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K)); |
398 | /* lr %r5,%r4 */ | 405 | /* lr %r5,%r4 */ |
399 | EMIT2(0x1854); | 406 | EMIT2(0x1854); |
400 | break; | 407 | break; |
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c index 231cecafc2f1..a32c96761eab 100644 --- a/arch/s390/oprofile/hwsampler.c +++ b/arch/s390/oprofile/hwsampler.c | |||
@@ -26,9 +26,6 @@ | |||
26 | #define MAX_NUM_SDB 511 | 26 | #define MAX_NUM_SDB 511 |
27 | #define MIN_NUM_SDB 1 | 27 | #define MIN_NUM_SDB 1 |
28 | 28 | ||
29 | #define ALERT_REQ_MASK 0x4000000000000000ul | ||
30 | #define BUFFER_FULL_MASK 0x8000000000000000ul | ||
31 | |||
32 | DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer); | 29 | DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer); |
33 | 30 | ||
34 | struct hws_execute_parms { | 31 | struct hws_execute_parms { |
@@ -44,6 +41,7 @@ static DEFINE_MUTEX(hws_sem_oom); | |||
44 | 41 | ||
45 | static unsigned char hws_flush_all; | 42 | static unsigned char hws_flush_all; |
46 | static unsigned int hws_oom; | 43 | static unsigned int hws_oom; |
44 | static unsigned int hws_alert; | ||
47 | static struct workqueue_struct *hws_wq; | 45 | static struct workqueue_struct *hws_wq; |
48 | 46 | ||
49 | static unsigned int hws_state; | 47 | static unsigned int hws_state; |
@@ -65,43 +63,6 @@ static unsigned long interval; | |||
65 | static unsigned long min_sampler_rate; | 63 | static unsigned long min_sampler_rate; |
66 | static unsigned long max_sampler_rate; | 64 | static unsigned long max_sampler_rate; |
67 | 65 | ||
68 | static int ssctl(void *buffer) | ||
69 | { | ||
70 | int cc; | ||
71 | |||
72 | /* set in order to detect a program check */ | ||
73 | cc = 1; | ||
74 | |||
75 | asm volatile( | ||
76 | "0: .insn s,0xB2870000,0(%1)\n" | ||
77 | "1: ipm %0\n" | ||
78 | " srl %0,28\n" | ||
79 | "2:\n" | ||
80 | EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) | ||
81 | : "+d" (cc), "+a" (buffer) | ||
82 | : "m" (*((struct hws_ssctl_request_block *)buffer)) | ||
83 | : "cc", "memory"); | ||
84 | |||
85 | return cc ? -EINVAL : 0 ; | ||
86 | } | ||
87 | |||
88 | static int qsi(void *buffer) | ||
89 | { | ||
90 | int cc; | ||
91 | cc = 1; | ||
92 | |||
93 | asm volatile( | ||
94 | "0: .insn s,0xB2860000,0(%1)\n" | ||
95 | "1: lhi %0,0\n" | ||
96 | "2:\n" | ||
97 | EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) | ||
98 | : "=d" (cc), "+a" (buffer) | ||
99 | : "m" (*((struct hws_qsi_info_block *)buffer)) | ||
100 | : "cc", "memory"); | ||
101 | |||
102 | return cc ? -EINVAL : 0; | ||
103 | } | ||
104 | |||
105 | static void execute_qsi(void *parms) | 66 | static void execute_qsi(void *parms) |
106 | { | 67 | { |
107 | struct hws_execute_parms *ep = parms; | 68 | struct hws_execute_parms *ep = parms; |
@@ -113,7 +74,7 @@ static void execute_ssctl(void *parms) | |||
113 | { | 74 | { |
114 | struct hws_execute_parms *ep = parms; | 75 | struct hws_execute_parms *ep = parms; |
115 | 76 | ||
116 | ep->rc = ssctl(ep->buffer); | 77 | ep->rc = lsctl(ep->buffer); |
117 | } | 78 | } |
118 | 79 | ||
119 | static int smp_ctl_ssctl_stop(int cpu) | 80 | static int smp_ctl_ssctl_stop(int cpu) |
@@ -214,17 +175,6 @@ static int smp_ctl_qsi(int cpu) | |||
214 | return ep.rc; | 175 | return ep.rc; |
215 | } | 176 | } |
216 | 177 | ||
217 | static inline unsigned long *trailer_entry_ptr(unsigned long v) | ||
218 | { | ||
219 | void *ret; | ||
220 | |||
221 | ret = (void *)v; | ||
222 | ret += PAGE_SIZE; | ||
223 | ret -= sizeof(struct hws_trailer_entry); | ||
224 | |||
225 | return (unsigned long *) ret; | ||
226 | } | ||
227 | |||
228 | static void hws_ext_handler(struct ext_code ext_code, | 178 | static void hws_ext_handler(struct ext_code ext_code, |
229 | unsigned int param32, unsigned long param64) | 179 | unsigned int param32, unsigned long param64) |
230 | { | 180 | { |
@@ -233,6 +183,9 @@ static void hws_ext_handler(struct ext_code ext_code, | |||
233 | if (!(param32 & CPU_MF_INT_SF_MASK)) | 183 | if (!(param32 & CPU_MF_INT_SF_MASK)) |
234 | return; | 184 | return; |
235 | 185 | ||
186 | if (!hws_alert) | ||
187 | return; | ||
188 | |||
236 | inc_irq_stat(IRQEXT_CMS); | 189 | inc_irq_stat(IRQEXT_CMS); |
237 | atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); | 190 | atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); |
238 | 191 | ||
@@ -256,16 +209,6 @@ static void init_all_cpu_buffers(void) | |||
256 | } | 209 | } |
257 | } | 210 | } |
258 | 211 | ||
259 | static int is_link_entry(unsigned long *s) | ||
260 | { | ||
261 | return *s & 0x1ul ? 1 : 0; | ||
262 | } | ||
263 | |||
264 | static unsigned long *get_next_sdbt(unsigned long *s) | ||
265 | { | ||
266 | return (unsigned long *) (*s & ~0x1ul); | ||
267 | } | ||
268 | |||
269 | static int prepare_cpu_buffers(void) | 212 | static int prepare_cpu_buffers(void) |
270 | { | 213 | { |
271 | int cpu; | 214 | int cpu; |
@@ -353,7 +296,7 @@ static int allocate_sdbt(int cpu) | |||
353 | } | 296 | } |
354 | *sdbt = sdb; | 297 | *sdbt = sdb; |
355 | trailer = trailer_entry_ptr(*sdbt); | 298 | trailer = trailer_entry_ptr(*sdbt); |
356 | *trailer = ALERT_REQ_MASK; | 299 | *trailer = SDB_TE_ALERT_REQ_MASK; |
357 | sdbt++; | 300 | sdbt++; |
358 | mutex_unlock(&hws_sem_oom); | 301 | mutex_unlock(&hws_sem_oom); |
359 | } | 302 | } |
@@ -829,7 +772,7 @@ static void worker_on_interrupt(unsigned int cpu) | |||
829 | 772 | ||
830 | trailer = trailer_entry_ptr(*sdbt); | 773 | trailer = trailer_entry_ptr(*sdbt); |
831 | /* leave loop if no more work to do */ | 774 | /* leave loop if no more work to do */ |
832 | if (!(*trailer & BUFFER_FULL_MASK)) { | 775 | if (!(*trailer & SDB_TE_BUFFER_FULL_MASK)) { |
833 | done = 1; | 776 | done = 1; |
834 | if (!hws_flush_all) | 777 | if (!hws_flush_all) |
835 | continue; | 778 | continue; |
@@ -856,7 +799,7 @@ static void worker_on_interrupt(unsigned int cpu) | |||
856 | static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt, | 799 | static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt, |
857 | unsigned long *dear) | 800 | unsigned long *dear) |
858 | { | 801 | { |
859 | struct hws_data_entry *sample_data_ptr; | 802 | struct hws_basic_entry *sample_data_ptr; |
860 | unsigned long *trailer; | 803 | unsigned long *trailer; |
861 | 804 | ||
862 | trailer = trailer_entry_ptr(*sdbt); | 805 | trailer = trailer_entry_ptr(*sdbt); |
@@ -866,7 +809,7 @@ static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt, | |||
866 | trailer = dear; | 809 | trailer = dear; |
867 | } | 810 | } |
868 | 811 | ||
869 | sample_data_ptr = (struct hws_data_entry *)(*sdbt); | 812 | sample_data_ptr = (struct hws_basic_entry *)(*sdbt); |
870 | 813 | ||
871 | while ((unsigned long *)sample_data_ptr < trailer) { | 814 | while ((unsigned long *)sample_data_ptr < trailer) { |
872 | struct pt_regs *regs = NULL; | 815 | struct pt_regs *regs = NULL; |
@@ -1002,6 +945,7 @@ int hwsampler_deallocate(void) | |||
1002 | goto deallocate_exit; | 945 | goto deallocate_exit; |
1003 | 946 | ||
1004 | irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); | 947 | irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); |
948 | hws_alert = 0; | ||
1005 | deallocate_sdbt(); | 949 | deallocate_sdbt(); |
1006 | 950 | ||
1007 | hws_state = HWS_DEALLOCATED; | 951 | hws_state = HWS_DEALLOCATED; |
@@ -1116,6 +1060,7 @@ int hwsampler_shutdown(void) | |||
1116 | 1060 | ||
1117 | if (hws_state == HWS_STOPPED) { | 1061 | if (hws_state == HWS_STOPPED) { |
1118 | irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); | 1062 | irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); |
1063 | hws_alert = 0; | ||
1119 | deallocate_sdbt(); | 1064 | deallocate_sdbt(); |
1120 | } | 1065 | } |
1121 | if (hws_wq) { | 1066 | if (hws_wq) { |
@@ -1190,6 +1135,7 @@ start_all_exit: | |||
1190 | hws_oom = 1; | 1135 | hws_oom = 1; |
1191 | hws_flush_all = 0; | 1136 | hws_flush_all = 0; |
1192 | /* now let them in, 1407 CPUMF external interrupts */ | 1137 | /* now let them in, 1407 CPUMF external interrupts */ |
1138 | hws_alert = 1; | ||
1193 | irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); | 1139 | irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); |
1194 | 1140 | ||
1195 | return 0; | 1141 | return 0; |
diff --git a/arch/s390/oprofile/hwsampler.h b/arch/s390/oprofile/hwsampler.h index 0022e1ebfbde..a483d06f2fa7 100644 --- a/arch/s390/oprofile/hwsampler.h +++ b/arch/s390/oprofile/hwsampler.h | |||
@@ -9,27 +9,7 @@ | |||
9 | #define HWSAMPLER_H_ | 9 | #define HWSAMPLER_H_ |
10 | 10 | ||
11 | #include <linux/workqueue.h> | 11 | #include <linux/workqueue.h> |
12 | 12 | #include <asm/cpu_mf.h> | |
13 | struct hws_qsi_info_block /* QUERY SAMPLING information block */ | ||
14 | { /* Bit(s) */ | ||
15 | unsigned int b0_13:14; /* 0-13: zeros */ | ||
16 | unsigned int as:1; /* 14: sampling authorisation control*/ | ||
17 | unsigned int b15_21:7; /* 15-21: zeros */ | ||
18 | unsigned int es:1; /* 22: sampling enable control */ | ||
19 | unsigned int b23_29:7; /* 23-29: zeros */ | ||
20 | unsigned int cs:1; /* 30: sampling activation control */ | ||
21 | unsigned int:1; /* 31: reserved */ | ||
22 | unsigned int bsdes:16; /* 4-5: size of sampling entry */ | ||
23 | unsigned int:16; /* 6-7: reserved */ | ||
24 | unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */ | ||
25 | unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/ | ||
26 | unsigned long tear; /* 24-31: TEAR contents */ | ||
27 | unsigned long dear; /* 32-39: DEAR contents */ | ||
28 | unsigned int rsvrd0; /* 40-43: reserved */ | ||
29 | unsigned int cpu_speed; /* 44-47: CPU speed */ | ||
30 | unsigned long long rsvrd1; /* 48-55: reserved */ | ||
31 | unsigned long long rsvrd2; /* 56-63: reserved */ | ||
32 | }; | ||
33 | 13 | ||
34 | struct hws_ssctl_request_block /* SET SAMPLING CONTROLS req block */ | 14 | struct hws_ssctl_request_block /* SET SAMPLING CONTROLS req block */ |
35 | { /* bytes 0 - 7 Bit(s) */ | 15 | { /* bytes 0 - 7 Bit(s) */ |
@@ -68,36 +48,6 @@ struct hws_cpu_buffer { | |||
68 | unsigned int stop_mode:1; | 48 | unsigned int stop_mode:1; |
69 | }; | 49 | }; |
70 | 50 | ||
71 | struct hws_data_entry { | ||
72 | unsigned int def:16; /* 0-15 Data Entry Format */ | ||
73 | unsigned int R:4; /* 16-19 reserved */ | ||
74 | unsigned int U:4; /* 20-23 Number of unique instruct. */ | ||
75 | unsigned int z:2; /* zeros */ | ||
76 | unsigned int T:1; /* 26 PSW DAT mode */ | ||
77 | unsigned int W:1; /* 27 PSW wait state */ | ||
78 | unsigned int P:1; /* 28 PSW Problem state */ | ||
79 | unsigned int AS:2; /* 29-30 PSW address-space control */ | ||
80 | unsigned int I:1; /* 31 entry valid or invalid */ | ||
81 | unsigned int:16; | ||
82 | unsigned int prim_asn:16; /* primary ASN */ | ||
83 | unsigned long long ia; /* Instruction Address */ | ||
84 | unsigned long long gpp; /* Guest Program Parameter */ | ||
85 | unsigned long long hpp; /* Host Program Parameter */ | ||
86 | }; | ||
87 | |||
88 | struct hws_trailer_entry { | ||
89 | unsigned int f:1; /* 0 - Block Full Indicator */ | ||
90 | unsigned int a:1; /* 1 - Alert request control */ | ||
91 | unsigned long:62; /* 2 - 63: Reserved */ | ||
92 | unsigned long overflow; /* 64 - sample Overflow count */ | ||
93 | unsigned long timestamp; /* 16 - time-stamp */ | ||
94 | unsigned long timestamp1; /* */ | ||
95 | unsigned long reserved1; /* 32 -Reserved */ | ||
96 | unsigned long reserved2; /* */ | ||
97 | unsigned long progusage1; /* 48 - reserved for programming use */ | ||
98 | unsigned long progusage2; /* */ | ||
99 | }; | ||
100 | |||
101 | int hwsampler_setup(void); | 51 | int hwsampler_setup(void); |
102 | int hwsampler_shutdown(void); | 52 | int hwsampler_shutdown(void); |
103 | int hwsampler_allocate(unsigned long sdbt, unsigned long sdb); | 53 | int hwsampler_allocate(unsigned long sdbt, unsigned long sdb); |
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index 04e1b6a85362..9ffe645d5989 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/oprofile.h> | 12 | #include <linux/oprofile.h> |
13 | #include <linux/perf_event.h> | ||
13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
14 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
15 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
@@ -67,6 +68,21 @@ module_param_call(cpu_type, set_cpu_type, NULL, NULL, 0); | |||
67 | MODULE_PARM_DESC(cpu_type, "Force legacy basic mode sampling" | 68 | MODULE_PARM_DESC(cpu_type, "Force legacy basic mode sampling" |
68 | "(report cpu_type \"timer\""); | 69 | "(report cpu_type \"timer\""); |
69 | 70 | ||
71 | static int __oprofile_hwsampler_start(void) | ||
72 | { | ||
73 | int retval; | ||
74 | |||
75 | retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks); | ||
76 | if (retval) | ||
77 | return retval; | ||
78 | |||
79 | retval = hwsampler_start_all(oprofile_hw_interval); | ||
80 | if (retval) | ||
81 | hwsampler_deallocate(); | ||
82 | |||
83 | return retval; | ||
84 | } | ||
85 | |||
70 | static int oprofile_hwsampler_start(void) | 86 | static int oprofile_hwsampler_start(void) |
71 | { | 87 | { |
72 | int retval; | 88 | int retval; |
@@ -76,13 +92,13 @@ static int oprofile_hwsampler_start(void) | |||
76 | if (!hwsampler_running) | 92 | if (!hwsampler_running) |
77 | return timer_ops.start(); | 93 | return timer_ops.start(); |
78 | 94 | ||
79 | retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks); | 95 | retval = perf_reserve_sampling(); |
80 | if (retval) | 96 | if (retval) |
81 | return retval; | 97 | return retval; |
82 | 98 | ||
83 | retval = hwsampler_start_all(oprofile_hw_interval); | 99 | retval = __oprofile_hwsampler_start(); |
84 | if (retval) | 100 | if (retval) |
85 | hwsampler_deallocate(); | 101 | perf_release_sampling(); |
86 | 102 | ||
87 | return retval; | 103 | return retval; |
88 | } | 104 | } |
@@ -96,6 +112,7 @@ static void oprofile_hwsampler_stop(void) | |||
96 | 112 | ||
97 | hwsampler_stop_all(); | 113 | hwsampler_stop_all(); |
98 | hwsampler_deallocate(); | 114 | hwsampler_deallocate(); |
115 | perf_release_sampling(); | ||
99 | return; | 116 | return; |
100 | } | 117 | } |
101 | 118 | ||
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index bf7c73d71eef..0820362c7b0f 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
@@ -919,17 +919,23 @@ static void zpci_mem_exit(void) | |||
919 | kmem_cache_destroy(zdev_fmb_cache); | 919 | kmem_cache_destroy(zdev_fmb_cache); |
920 | } | 920 | } |
921 | 921 | ||
922 | static unsigned int s390_pci_probe; | 922 | static unsigned int s390_pci_probe = 1; |
923 | static unsigned int s390_pci_initialized; | ||
923 | 924 | ||
924 | char * __init pcibios_setup(char *str) | 925 | char * __init pcibios_setup(char *str) |
925 | { | 926 | { |
926 | if (!strcmp(str, "on")) { | 927 | if (!strcmp(str, "off")) { |
927 | s390_pci_probe = 1; | 928 | s390_pci_probe = 0; |
928 | return NULL; | 929 | return NULL; |
929 | } | 930 | } |
930 | return str; | 931 | return str; |
931 | } | 932 | } |
932 | 933 | ||
934 | bool zpci_is_enabled(void) | ||
935 | { | ||
936 | return s390_pci_initialized; | ||
937 | } | ||
938 | |||
933 | static int __init pci_base_init(void) | 939 | static int __init pci_base_init(void) |
934 | { | 940 | { |
935 | int rc; | 941 | int rc; |
@@ -961,6 +967,7 @@ static int __init pci_base_init(void) | |||
961 | if (rc) | 967 | if (rc) |
962 | goto out_find; | 968 | goto out_find; |
963 | 969 | ||
970 | s390_pci_initialized = 1; | ||
964 | return 0; | 971 | return 0; |
965 | 972 | ||
966 | out_find: | 973 | out_find: |
@@ -978,5 +985,6 @@ subsys_initcall_sync(pci_base_init); | |||
978 | 985 | ||
979 | void zpci_rescan(void) | 986 | void zpci_rescan(void) |
980 | { | 987 | { |
981 | clp_rescan_pci_devices_simple(); | 988 | if (zpci_is_enabled()) |
989 | clp_rescan_pci_devices_simple(); | ||
982 | } | 990 | } |
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index 9b83d080902d..60c11a629d96 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c | |||
@@ -285,7 +285,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page, | |||
285 | flags |= ZPCI_TABLE_PROTECTED; | 285 | flags |= ZPCI_TABLE_PROTECTED; |
286 | 286 | ||
287 | if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) { | 287 | if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) { |
288 | atomic64_add(nr_pages, (atomic64_t *) &zdev->fmb->mapped_pages); | 288 | atomic64_add(nr_pages, &zdev->fmb->mapped_pages); |
289 | return dma_addr + (offset & ~PAGE_MASK); | 289 | return dma_addr + (offset & ~PAGE_MASK); |
290 | } | 290 | } |
291 | 291 | ||
@@ -313,7 +313,7 @@ static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr, | |||
313 | zpci_err_hex(&dma_addr, sizeof(dma_addr)); | 313 | zpci_err_hex(&dma_addr, sizeof(dma_addr)); |
314 | } | 314 | } |
315 | 315 | ||
316 | atomic64_add(npages, (atomic64_t *) &zdev->fmb->unmapped_pages); | 316 | atomic64_add(npages, &zdev->fmb->unmapped_pages); |
317 | iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT; | 317 | iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT; |
318 | dma_free_iommu(zdev, iommu_page_index, npages); | 318 | dma_free_iommu(zdev, iommu_page_index, npages); |
319 | } | 319 | } |
@@ -332,7 +332,6 @@ static void *s390_dma_alloc(struct device *dev, size_t size, | |||
332 | if (!page) | 332 | if (!page) |
333 | return NULL; | 333 | return NULL; |
334 | 334 | ||
335 | atomic64_add(size / PAGE_SIZE, (atomic64_t *) &zdev->fmb->allocated_pages); | ||
336 | pa = page_to_phys(page); | 335 | pa = page_to_phys(page); |
337 | memset((void *) pa, 0, size); | 336 | memset((void *) pa, 0, size); |
338 | 337 | ||
@@ -343,6 +342,7 @@ static void *s390_dma_alloc(struct device *dev, size_t size, | |||
343 | return NULL; | 342 | return NULL; |
344 | } | 343 | } |
345 | 344 | ||
345 | atomic64_add(size / PAGE_SIZE, &zdev->fmb->allocated_pages); | ||
346 | if (dma_handle) | 346 | if (dma_handle) |
347 | *dma_handle = map; | 347 | *dma_handle = map; |
348 | return (void *) pa; | 348 | return (void *) pa; |
@@ -352,8 +352,11 @@ static void s390_dma_free(struct device *dev, size_t size, | |||
352 | void *pa, dma_addr_t dma_handle, | 352 | void *pa, dma_addr_t dma_handle, |
353 | struct dma_attrs *attrs) | 353 | struct dma_attrs *attrs) |
354 | { | 354 | { |
355 | s390_dma_unmap_pages(dev, dma_handle, PAGE_ALIGN(size), | 355 | struct zpci_dev *zdev = get_zdev(to_pci_dev(dev)); |
356 | DMA_BIDIRECTIONAL, NULL); | 356 | |
357 | size = PAGE_ALIGN(size); | ||
358 | atomic64_sub(size / PAGE_SIZE, &zdev->fmb->allocated_pages); | ||
359 | s390_dma_unmap_pages(dev, dma_handle, size, DMA_BIDIRECTIONAL, NULL); | ||
357 | free_pages((unsigned long) pa, get_order(size)); | 360 | free_pages((unsigned long) pa, get_order(size)); |
358 | } | 361 | } |
359 | 362 | ||
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c index 069607209a30..01e251b1da0c 100644 --- a/arch/s390/pci/pci_event.c +++ b/arch/s390/pci/pci_event.c | |||
@@ -43,9 +43,8 @@ struct zpci_ccdf_avail { | |||
43 | u16 pec; /* PCI event code */ | 43 | u16 pec; /* PCI event code */ |
44 | } __packed; | 44 | } __packed; |
45 | 45 | ||
46 | void zpci_event_error(void *data) | 46 | static void __zpci_event_error(struct zpci_ccdf_err *ccdf) |
47 | { | 47 | { |
48 | struct zpci_ccdf_err *ccdf = data; | ||
49 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); | 48 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); |
50 | 49 | ||
51 | zpci_err("error CCDF:\n"); | 50 | zpci_err("error CCDF:\n"); |
@@ -58,9 +57,14 @@ void zpci_event_error(void *data) | |||
58 | pci_name(zdev->pdev), ccdf->pec, ccdf->fid); | 57 | pci_name(zdev->pdev), ccdf->pec, ccdf->fid); |
59 | } | 58 | } |
60 | 59 | ||
61 | void zpci_event_availability(void *data) | 60 | void zpci_event_error(void *data) |
61 | { | ||
62 | if (zpci_is_enabled()) | ||
63 | __zpci_event_error(data); | ||
64 | } | ||
65 | |||
66 | static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) | ||
62 | { | 67 | { |
63 | struct zpci_ccdf_avail *ccdf = data; | ||
64 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); | 68 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); |
65 | struct pci_dev *pdev = zdev ? zdev->pdev : NULL; | 69 | struct pci_dev *pdev = zdev ? zdev->pdev : NULL; |
66 | int ret; | 70 | int ret; |
@@ -99,8 +103,12 @@ void zpci_event_availability(void *data) | |||
99 | 103 | ||
100 | break; | 104 | break; |
101 | case 0x0304: /* Configured -> Standby */ | 105 | case 0x0304: /* Configured -> Standby */ |
102 | if (pdev) | 106 | if (pdev) { |
107 | /* Give the driver a hint that the function is | ||
108 | * already unusable. */ | ||
109 | pdev->error_state = pci_channel_io_perm_failure; | ||
103 | pci_stop_and_remove_bus_device(pdev); | 110 | pci_stop_and_remove_bus_device(pdev); |
111 | } | ||
104 | 112 | ||
105 | zdev->fh = ccdf->fh; | 113 | zdev->fh = ccdf->fh; |
106 | zpci_disable_device(zdev); | 114 | zpci_disable_device(zdev); |
@@ -110,6 +118,8 @@ void zpci_event_availability(void *data) | |||
110 | clp_rescan_pci_devices(); | 118 | clp_rescan_pci_devices(); |
111 | break; | 119 | break; |
112 | case 0x0308: /* Standby -> Reserved */ | 120 | case 0x0308: /* Standby -> Reserved */ |
121 | if (!zdev) | ||
122 | break; | ||
113 | pci_stop_root_bus(zdev->bus); | 123 | pci_stop_root_bus(zdev->bus); |
114 | pci_remove_root_bus(zdev->bus); | 124 | pci_remove_root_bus(zdev->bus); |
115 | break; | 125 | break; |
@@ -117,3 +127,9 @@ void zpci_event_availability(void *data) | |||
117 | break; | 127 | break; |
118 | } | 128 | } |
119 | } | 129 | } |
130 | |||
131 | void zpci_event_availability(void *data) | ||
132 | { | ||
133 | if (zpci_is_enabled()) | ||
134 | __zpci_event_availability(data); | ||
135 | } | ||
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index f3414ade77a3..fe7471eb0167 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild | |||
@@ -1,6 +1,7 @@ | |||
1 | 1 | ||
2 | header-y += | 2 | header-y += |
3 | 3 | ||
4 | generic-y += barrier.h | ||
4 | generic-y += clkdev.h | 5 | generic-y += clkdev.h |
5 | generic-y += trace_clock.h | 6 | generic-y += trace_clock.h |
6 | generic-y += xor.h | 7 | generic-y += xor.h |
diff --git a/arch/score/include/asm/barrier.h b/arch/score/include/asm/barrier.h deleted file mode 100644 index 0eacb6471e6d..000000000000 --- a/arch/score/include/asm/barrier.h +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | #ifndef _ASM_SCORE_BARRIER_H | ||
2 | #define _ASM_SCORE_BARRIER_H | ||
3 | |||
4 | #define mb() barrier() | ||
5 | #define rmb() barrier() | ||
6 | #define wmb() barrier() | ||
7 | #define smp_mb() barrier() | ||
8 | #define smp_rmb() barrier() | ||
9 | #define smp_wmb() barrier() | ||
10 | |||
11 | #define read_barrier_depends() do {} while (0) | ||
12 | #define smp_read_barrier_depends() do {} while (0) | ||
13 | |||
14 | #define set_mb(var, value) do {var = value; wmb(); } while (0) | ||
15 | |||
16 | #endif /* _ASM_SCORE_BARRIER_H */ | ||
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 9b0979f4df7a..ce298317a73e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -66,6 +66,7 @@ config SUPERH32 | |||
66 | select PERF_EVENTS | 66 | select PERF_EVENTS |
67 | select ARCH_HIBERNATION_POSSIBLE if MMU | 67 | select ARCH_HIBERNATION_POSSIBLE if MMU |
68 | select SPARSE_IRQ | 68 | select SPARSE_IRQ |
69 | select HAVE_CC_STACKPROTECTOR | ||
69 | 70 | ||
70 | config SUPERH64 | 71 | config SUPERH64 |
71 | def_bool ARCH = "sh64" | 72 | def_bool ARCH = "sh64" |
@@ -695,20 +696,6 @@ config SECCOMP | |||
695 | 696 | ||
696 | If unsure, say N. | 697 | If unsure, say N. |
697 | 698 | ||
698 | config CC_STACKPROTECTOR | ||
699 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" | ||
700 | depends on SUPERH32 | ||
701 | help | ||
702 | This option turns on the -fstack-protector GCC feature. This | ||
703 | feature puts, at the beginning of functions, a canary value on | ||
704 | the stack just before the return address, and validates | ||
705 | the value just before actually returning. Stack based buffer | ||
706 | overflows (that need to overwrite this return address) now also | ||
707 | overwrite the canary, which gets detected and the attack is then | ||
708 | neutralized via a kernel panic. | ||
709 | |||
710 | This feature requires gcc version 4.2 or above. | ||
711 | |||
712 | config SMP | 699 | config SMP |
713 | bool "Symmetric multi-processing support" | 700 | bool "Symmetric multi-processing support" |
714 | depends on SYS_SUPPORTS_SMP | 701 | depends on SYS_SUPPORTS_SMP |
diff --git a/arch/sh/Makefile b/arch/sh/Makefile index aed701c7b11b..d4d16e4be07c 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile | |||
@@ -199,10 +199,6 @@ ifeq ($(CONFIG_DWARF_UNWINDER),y) | |||
199 | KBUILD_CFLAGS += -fasynchronous-unwind-tables | 199 | KBUILD_CFLAGS += -fasynchronous-unwind-tables |
200 | endif | 200 | endif |
201 | 201 | ||
202 | ifeq ($(CONFIG_CC_STACKPROTECTOR),y) | ||
203 | KBUILD_CFLAGS += -fstack-protector | ||
204 | endif | ||
205 | |||
206 | libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) | 202 | libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) |
207 | libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) | 203 | libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) |
208 | 204 | ||
diff --git a/arch/sh/include/asm/barrier.h b/arch/sh/include/asm/barrier.h index 72c103dae300..43715308b068 100644 --- a/arch/sh/include/asm/barrier.h +++ b/arch/sh/include/asm/barrier.h | |||
@@ -26,29 +26,14 @@ | |||
26 | #if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5) | 26 | #if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5) |
27 | #define mb() __asm__ __volatile__ ("synco": : :"memory") | 27 | #define mb() __asm__ __volatile__ ("synco": : :"memory") |
28 | #define rmb() mb() | 28 | #define rmb() mb() |
29 | #define wmb() __asm__ __volatile__ ("synco": : :"memory") | 29 | #define wmb() mb() |
30 | #define ctrl_barrier() __icbi(PAGE_OFFSET) | 30 | #define ctrl_barrier() __icbi(PAGE_OFFSET) |
31 | #define read_barrier_depends() do { } while(0) | ||
32 | #else | 31 | #else |
33 | #define mb() __asm__ __volatile__ ("": : :"memory") | ||
34 | #define rmb() mb() | ||
35 | #define wmb() __asm__ __volatile__ ("": : :"memory") | ||
36 | #define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop") | 32 | #define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop") |
37 | #define read_barrier_depends() do { } while(0) | ||
38 | #endif | ||
39 | |||
40 | #ifdef CONFIG_SMP | ||
41 | #define smp_mb() mb() | ||
42 | #define smp_rmb() rmb() | ||
43 | #define smp_wmb() wmb() | ||
44 | #define smp_read_barrier_depends() read_barrier_depends() | ||
45 | #else | ||
46 | #define smp_mb() barrier() | ||
47 | #define smp_rmb() barrier() | ||
48 | #define smp_wmb() barrier() | ||
49 | #define smp_read_barrier_depends() do { } while(0) | ||
50 | #endif | 33 | #endif |
51 | 34 | ||
52 | #define set_mb(var, value) do { (void)xchg(&var, value); } while (0) | 35 | #define set_mb(var, value) do { (void)xchg(&var, value); } while (0) |
53 | 36 | ||
37 | #include <asm-generic/barrier.h> | ||
38 | |||
54 | #endif /* __ASM_SH_BARRIER_H */ | 39 | #endif /* __ASM_SH_BARRIER_H */ |
diff --git a/arch/sparc/include/asm/barrier_32.h b/arch/sparc/include/asm/barrier_32.h index c1b76654ee76..ae69eda288f4 100644 --- a/arch/sparc/include/asm/barrier_32.h +++ b/arch/sparc/include/asm/barrier_32.h | |||
@@ -1,15 +1,7 @@ | |||
1 | #ifndef __SPARC_BARRIER_H | 1 | #ifndef __SPARC_BARRIER_H |
2 | #define __SPARC_BARRIER_H | 2 | #define __SPARC_BARRIER_H |
3 | 3 | ||
4 | /* XXX Change this if we ever use a PSO mode kernel. */ | 4 | #include <asm/processor.h> /* for nop() */ |
5 | #define mb() __asm__ __volatile__ ("" : : : "memory") | 5 | #include <asm-generic/barrier.h> |
6 | #define rmb() mb() | ||
7 | #define wmb() mb() | ||
8 | #define read_barrier_depends() do { } while(0) | ||
9 | #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) | ||
10 | #define smp_mb() __asm__ __volatile__("":::"memory") | ||
11 | #define smp_rmb() __asm__ __volatile__("":::"memory") | ||
12 | #define smp_wmb() __asm__ __volatile__("":::"memory") | ||
13 | #define smp_read_barrier_depends() do { } while(0) | ||
14 | 6 | ||
15 | #endif /* !(__SPARC_BARRIER_H) */ | 7 | #endif /* !(__SPARC_BARRIER_H) */ |
diff --git a/arch/sparc/include/asm/barrier_64.h b/arch/sparc/include/asm/barrier_64.h index 95d45986f908..b5aad964558e 100644 --- a/arch/sparc/include/asm/barrier_64.h +++ b/arch/sparc/include/asm/barrier_64.h | |||
@@ -53,4 +53,19 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ | |||
53 | 53 | ||
54 | #define smp_read_barrier_depends() do { } while(0) | 54 | #define smp_read_barrier_depends() do { } while(0) |
55 | 55 | ||
56 | #define smp_store_release(p, v) \ | ||
57 | do { \ | ||
58 | compiletime_assert_atomic_type(*p); \ | ||
59 | barrier(); \ | ||
60 | ACCESS_ONCE(*p) = (v); \ | ||
61 | } while (0) | ||
62 | |||
63 | #define smp_load_acquire(p) \ | ||
64 | ({ \ | ||
65 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
66 | compiletime_assert_atomic_type(*p); \ | ||
67 | barrier(); \ | ||
68 | ___p1; \ | ||
69 | }) | ||
70 | |||
56 | #endif /* !(__SPARC64_BARRIER_H) */ | 71 | #endif /* !(__SPARC64_BARRIER_H) */ |
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index 218b6b23c378..01fe9946d388 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c | |||
@@ -497,9 +497,20 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
497 | case BPF_S_ALU_MUL_K: /* A *= K */ | 497 | case BPF_S_ALU_MUL_K: /* A *= K */ |
498 | emit_alu_K(MUL, K); | 498 | emit_alu_K(MUL, K); |
499 | break; | 499 | break; |
500 | case BPF_S_ALU_DIV_K: /* A /= K */ | 500 | case BPF_S_ALU_DIV_K: /* A /= K with K != 0*/ |
501 | emit_alu_K(MUL, K); | 501 | if (K == 1) |
502 | emit_read_y(r_A); | 502 | break; |
503 | emit_write_y(G0); | ||
504 | #ifdef CONFIG_SPARC32 | ||
505 | /* The Sparc v8 architecture requires | ||
506 | * three instructions between a %y | ||
507 | * register write and the first use. | ||
508 | */ | ||
509 | emit_nop(); | ||
510 | emit_nop(); | ||
511 | emit_nop(); | ||
512 | #endif | ||
513 | emit_alu_K(DIV, K); | ||
503 | break; | 514 | break; |
504 | case BPF_S_ALU_DIV_X: /* A /= X; */ | 515 | case BPF_S_ALU_DIV_X: /* A /= X; */ |
505 | emit_cmpi(r_X, 0); | 516 | emit_cmpi(r_X, 0); |
diff --git a/arch/tile/include/asm/barrier.h b/arch/tile/include/asm/barrier.h index a9a73da5865d..b5a05d050a8f 100644 --- a/arch/tile/include/asm/barrier.h +++ b/arch/tile/include/asm/barrier.h | |||
@@ -22,59 +22,6 @@ | |||
22 | #include <arch/spr_def.h> | 22 | #include <arch/spr_def.h> |
23 | #include <asm/timex.h> | 23 | #include <asm/timex.h> |
24 | 24 | ||
25 | /* | ||
26 | * read_barrier_depends - Flush all pending reads that subsequents reads | ||
27 | * depend on. | ||
28 | * | ||
29 | * No data-dependent reads from memory-like regions are ever reordered | ||
30 | * over this barrier. All reads preceding this primitive are guaranteed | ||
31 | * to access memory (but not necessarily other CPUs' caches) before any | ||
32 | * reads following this primitive that depend on the data return by | ||
33 | * any of the preceding reads. This primitive is much lighter weight than | ||
34 | * rmb() on most CPUs, and is never heavier weight than is | ||
35 | * rmb(). | ||
36 | * | ||
37 | * These ordering constraints are respected by both the local CPU | ||
38 | * and the compiler. | ||
39 | * | ||
40 | * Ordering is not guaranteed by anything other than these primitives, | ||
41 | * not even by data dependencies. See the documentation for | ||
42 | * memory_barrier() for examples and URLs to more information. | ||
43 | * | ||
44 | * For example, the following code would force ordering (the initial | ||
45 | * value of "a" is zero, "b" is one, and "p" is "&a"): | ||
46 | * | ||
47 | * <programlisting> | ||
48 | * CPU 0 CPU 1 | ||
49 | * | ||
50 | * b = 2; | ||
51 | * memory_barrier(); | ||
52 | * p = &b; q = p; | ||
53 | * read_barrier_depends(); | ||
54 | * d = *q; | ||
55 | * </programlisting> | ||
56 | * | ||
57 | * because the read of "*q" depends on the read of "p" and these | ||
58 | * two reads are separated by a read_barrier_depends(). However, | ||
59 | * the following code, with the same initial values for "a" and "b": | ||
60 | * | ||
61 | * <programlisting> | ||
62 | * CPU 0 CPU 1 | ||
63 | * | ||
64 | * a = 2; | ||
65 | * memory_barrier(); | ||
66 | * b = 3; y = b; | ||
67 | * read_barrier_depends(); | ||
68 | * x = a; | ||
69 | * </programlisting> | ||
70 | * | ||
71 | * does not enforce ordering, since there is no data dependency between | ||
72 | * the read of "a" and the read of "b". Therefore, on some CPUs, such | ||
73 | * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() | ||
74 | * in cases like this where there are no data dependencies. | ||
75 | */ | ||
76 | #define read_barrier_depends() do { } while (0) | ||
77 | |||
78 | #define __sync() __insn_mf() | 25 | #define __sync() __insn_mf() |
79 | 26 | ||
80 | #include <hv/syscall_public.h> | 27 | #include <hv/syscall_public.h> |
@@ -125,20 +72,7 @@ mb_incoherent(void) | |||
125 | #define mb() fast_mb() | 72 | #define mb() fast_mb() |
126 | #define iob() fast_iob() | 73 | #define iob() fast_iob() |
127 | 74 | ||
128 | #ifdef CONFIG_SMP | 75 | #include <asm-generic/barrier.h> |
129 | #define smp_mb() mb() | ||
130 | #define smp_rmb() rmb() | ||
131 | #define smp_wmb() wmb() | ||
132 | #define smp_read_barrier_depends() read_barrier_depends() | ||
133 | #else | ||
134 | #define smp_mb() barrier() | ||
135 | #define smp_rmb() barrier() | ||
136 | #define smp_wmb() barrier() | ||
137 | #define smp_read_barrier_depends() do { } while (0) | ||
138 | #endif | ||
139 | |||
140 | #define set_mb(var, value) \ | ||
141 | do { var = value; mb(); } while (0) | ||
142 | 76 | ||
143 | #endif /* !__ASSEMBLY__ */ | 77 | #endif /* !__ASSEMBLY__ */ |
144 | #endif /* _ASM_TILE_BARRIER_H */ | 78 | #endif /* _ASM_TILE_BARRIER_H */ |
diff --git a/arch/unicore32/include/asm/barrier.h b/arch/unicore32/include/asm/barrier.h index a6620e5336b6..83d6a520f4bd 100644 --- a/arch/unicore32/include/asm/barrier.h +++ b/arch/unicore32/include/asm/barrier.h | |||
@@ -14,15 +14,6 @@ | |||
14 | #define dsb() __asm__ __volatile__ ("" : : : "memory") | 14 | #define dsb() __asm__ __volatile__ ("" : : : "memory") |
15 | #define dmb() __asm__ __volatile__ ("" : : : "memory") | 15 | #define dmb() __asm__ __volatile__ ("" : : : "memory") |
16 | 16 | ||
17 | #define mb() barrier() | 17 | #include <asm-generic/barrier.h> |
18 | #define rmb() barrier() | ||
19 | #define wmb() barrier() | ||
20 | #define smp_mb() barrier() | ||
21 | #define smp_rmb() barrier() | ||
22 | #define smp_wmb() barrier() | ||
23 | #define read_barrier_depends() do { } while (0) | ||
24 | #define smp_read_barrier_depends() do { } while (0) | ||
25 | |||
26 | #define set_mb(var, value) do { var = value; smp_mb(); } while (0) | ||
27 | 18 | ||
28 | #endif /* __UNICORE_BARRIER_H__ */ | 19 | #endif /* __UNICORE_BARRIER_H__ */ |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 64199bc08d66..cb9af474dfca 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -125,6 +125,7 @@ config X86 | |||
125 | select RTC_LIB | 125 | select RTC_LIB |
126 | select HAVE_DEBUG_STACKOVERFLOW | 126 | select HAVE_DEBUG_STACKOVERFLOW |
127 | select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 | 127 | select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 |
128 | select HAVE_CC_STACKPROTECTOR | ||
128 | 129 | ||
129 | config INSTRUCTION_DECODER | 130 | config INSTRUCTION_DECODER |
130 | def_bool y | 131 | def_bool y |
@@ -438,42 +439,26 @@ config X86_INTEL_CE | |||
438 | This option compiles in support for the CE4100 SOC for settop | 439 | This option compiles in support for the CE4100 SOC for settop |
439 | boxes and media devices. | 440 | boxes and media devices. |
440 | 441 | ||
441 | config X86_WANT_INTEL_MID | 442 | config X86_INTEL_MID |
442 | bool "Intel MID platform support" | 443 | bool "Intel MID platform support" |
443 | depends on X86_32 | 444 | depends on X86_32 |
444 | depends on X86_EXTENDED_PLATFORM | 445 | depends on X86_EXTENDED_PLATFORM |
445 | ---help--- | ||
446 | Select to build a kernel capable of supporting Intel MID platform | ||
447 | systems which do not have the PCI legacy interfaces (Moorestown, | ||
448 | Medfield). If you are building for a PC class system say N here. | ||
449 | |||
450 | if X86_WANT_INTEL_MID | ||
451 | |||
452 | config X86_INTEL_MID | ||
453 | bool | ||
454 | |||
455 | config X86_MDFLD | ||
456 | bool "Medfield MID platform" | ||
457 | depends on PCI | 446 | depends on PCI |
458 | depends on PCI_GOANY | 447 | depends on PCI_GOANY |
459 | depends on X86_IO_APIC | 448 | depends on X86_IO_APIC |
460 | select X86_INTEL_MID | ||
461 | select SFI | 449 | select SFI |
450 | select I2C | ||
462 | select DW_APB_TIMER | 451 | select DW_APB_TIMER |
463 | select APB_TIMER | 452 | select APB_TIMER |
464 | select I2C | ||
465 | select SPI | ||
466 | select INTEL_SCU_IPC | 453 | select INTEL_SCU_IPC |
467 | select X86_PLATFORM_DEVICES | ||
468 | select MFD_INTEL_MSIC | 454 | select MFD_INTEL_MSIC |
469 | ---help--- | 455 | ---help--- |
470 | Medfield is Intel's Low Power Intel Architecture (LPIA) based Moblin | 456 | Select to build a kernel capable of supporting Intel MID (Mobile |
471 | Internet Device(MID) platform. | 457 | Internet Device) platform systems which do not have the PCI legacy |
472 | Unlike standard x86 PCs, Medfield does not have many legacy devices | 458 | interfaces. If you are building for a PC class system say N here. |
473 | nor standard legacy replacement devices/features. e.g. Medfield does | ||
474 | not contain i8259, i8254, HPET, legacy BIOS, most of the io ports. | ||
475 | 459 | ||
476 | endif | 460 | Intel MID platforms are based on an Intel processor and chipset which |
461 | consume less power than most of the x86 derivatives. | ||
477 | 462 | ||
478 | config X86_INTEL_LPSS | 463 | config X86_INTEL_LPSS |
479 | bool "Intel Low Power Subsystem Support" | 464 | bool "Intel Low Power Subsystem Support" |
@@ -1080,10 +1065,6 @@ config MICROCODE_OLD_INTERFACE | |||
1080 | def_bool y | 1065 | def_bool y |
1081 | depends on MICROCODE | 1066 | depends on MICROCODE |
1082 | 1067 | ||
1083 | config MICROCODE_INTEL_LIB | ||
1084 | def_bool y | ||
1085 | depends on MICROCODE_INTEL | ||
1086 | |||
1087 | config MICROCODE_INTEL_EARLY | 1068 | config MICROCODE_INTEL_EARLY |
1088 | def_bool n | 1069 | def_bool n |
1089 | 1070 | ||
@@ -1617,22 +1598,6 @@ config SECCOMP | |||
1617 | 1598 | ||
1618 | If unsure, say Y. Only embedded should say N here. | 1599 | If unsure, say Y. Only embedded should say N here. |
1619 | 1600 | ||
1620 | config CC_STACKPROTECTOR | ||
1621 | bool "Enable -fstack-protector buffer overflow detection" | ||
1622 | ---help--- | ||
1623 | This option turns on the -fstack-protector GCC feature. This | ||
1624 | feature puts, at the beginning of functions, a canary value on | ||
1625 | the stack just before the return address, and validates | ||
1626 | the value just before actually returning. Stack based buffer | ||
1627 | overflows (that need to overwrite this return address) now also | ||
1628 | overwrite the canary, which gets detected and the attack is then | ||
1629 | neutralized via a kernel panic. | ||
1630 | |||
1631 | This feature requires gcc version 4.2 or above, or a distribution | ||
1632 | gcc with the feature backported. Older versions are automatically | ||
1633 | detected and for those versions, this configuration option is | ||
1634 | ignored. (and a warning is printed during bootup) | ||
1635 | |||
1636 | source kernel/Kconfig.hz | 1601 | source kernel/Kconfig.hz |
1637 | 1602 | ||
1638 | config KEXEC | 1603 | config KEXEC |
@@ -1728,16 +1693,67 @@ config RELOCATABLE | |||
1728 | 1693 | ||
1729 | Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address | 1694 | Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address |
1730 | it has been loaded at and the compile time physical address | 1695 | it has been loaded at and the compile time physical address |
1731 | (CONFIG_PHYSICAL_START) is ignored. | 1696 | (CONFIG_PHYSICAL_START) is used as the minimum location. |
1732 | 1697 | ||
1733 | # Relocation on x86-32 needs some additional build support | 1698 | config RANDOMIZE_BASE |
1699 | bool "Randomize the address of the kernel image" | ||
1700 | depends on RELOCATABLE | ||
1701 | depends on !HIBERNATION | ||
1702 | default n | ||
1703 | ---help--- | ||
1704 | Randomizes the physical and virtual address at which the | ||
1705 | kernel image is decompressed, as a security feature that | ||
1706 | deters exploit attempts relying on knowledge of the location | ||
1707 | of kernel internals. | ||
1708 | |||
1709 | Entropy is generated using the RDRAND instruction if it is | ||
1710 | supported. If RDTSC is supported, it is used as well. If | ||
1711 | neither RDRAND nor RDTSC are supported, then randomness is | ||
1712 | read from the i8254 timer. | ||
1713 | |||
1714 | The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET, | ||
1715 | and aligned according to PHYSICAL_ALIGN. Since the kernel is | ||
1716 | built using 2GiB addressing, and PHYSICAL_ALGIN must be at a | ||
1717 | minimum of 2MiB, only 10 bits of entropy is theoretically | ||
1718 | possible. At best, due to page table layouts, 64-bit can use | ||
1719 | 9 bits of entropy and 32-bit uses 8 bits. | ||
1720 | |||
1721 | If unsure, say N. | ||
1722 | |||
1723 | config RANDOMIZE_BASE_MAX_OFFSET | ||
1724 | hex "Maximum kASLR offset allowed" if EXPERT | ||
1725 | depends on RANDOMIZE_BASE | ||
1726 | range 0x0 0x20000000 if X86_32 | ||
1727 | default "0x20000000" if X86_32 | ||
1728 | range 0x0 0x40000000 if X86_64 | ||
1729 | default "0x40000000" if X86_64 | ||
1730 | ---help--- | ||
1731 | The lesser of RANDOMIZE_BASE_MAX_OFFSET and available physical | ||
1732 | memory is used to determine the maximal offset in bytes that will | ||
1733 | be applied to the kernel when kernel Address Space Layout | ||
1734 | Randomization (kASLR) is active. This must be a multiple of | ||
1735 | PHYSICAL_ALIGN. | ||
1736 | |||
1737 | On 32-bit this is limited to 512MiB by page table layouts. The | ||
1738 | default is 512MiB. | ||
1739 | |||
1740 | On 64-bit this is limited by how the kernel fixmap page table is | ||
1741 | positioned, so this cannot be larger than 1GiB currently. Without | ||
1742 | RANDOMIZE_BASE, there is a 512MiB to 1.5GiB split between kernel | ||
1743 | and modules. When RANDOMIZE_BASE_MAX_OFFSET is above 512MiB, the | ||
1744 | modules area will shrink to compensate, up to the current maximum | ||
1745 | 1GiB to 1GiB split. The default is 1GiB. | ||
1746 | |||
1747 | If unsure, leave at the default value. | ||
1748 | |||
1749 | # Relocation on x86 needs some additional build support | ||
1734 | config X86_NEED_RELOCS | 1750 | config X86_NEED_RELOCS |
1735 | def_bool y | 1751 | def_bool y |
1736 | depends on X86_32 && RELOCATABLE | 1752 | depends on RANDOMIZE_BASE || (X86_32 && RELOCATABLE) |
1737 | 1753 | ||
1738 | config PHYSICAL_ALIGN | 1754 | config PHYSICAL_ALIGN |
1739 | hex "Alignment value to which kernel should be aligned" | 1755 | hex "Alignment value to which kernel should be aligned" |
1740 | default "0x1000000" | 1756 | default "0x200000" |
1741 | range 0x2000 0x1000000 if X86_32 | 1757 | range 0x2000 0x1000000 if X86_32 |
1742 | range 0x200000 0x1000000 if X86_64 | 1758 | range 0x200000 0x1000000 if X86_64 |
1743 | ---help--- | 1759 | ---help--- |
@@ -2393,6 +2409,14 @@ config X86_DMA_REMAP | |||
2393 | bool | 2409 | bool |
2394 | depends on STA2X11 | 2410 | depends on STA2X11 |
2395 | 2411 | ||
2412 | config IOSF_MBI | ||
2413 | bool | ||
2414 | depends on PCI | ||
2415 | ---help--- | ||
2416 | To be selected by modules requiring access to the Intel OnChip System | ||
2417 | Fabric (IOSF) Sideband MailBox Interface (MBI). For MBI platforms | ||
2418 | enumerable by PCI. | ||
2419 | |||
2396 | source "net/Kconfig" | 2420 | source "net/Kconfig" |
2397 | 2421 | ||
2398 | source "drivers/Kconfig" | 2422 | source "drivers/Kconfig" |
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 57d021507120..13b22e0f681d 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile | |||
@@ -89,13 +89,11 @@ else | |||
89 | KBUILD_CFLAGS += -maccumulate-outgoing-args | 89 | KBUILD_CFLAGS += -maccumulate-outgoing-args |
90 | endif | 90 | endif |
91 | 91 | ||
92 | # Make sure compiler does not have buggy stack-protector support. | ||
92 | ifdef CONFIG_CC_STACKPROTECTOR | 93 | ifdef CONFIG_CC_STACKPROTECTOR |
93 | cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh | 94 | cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh |
94 | ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y) | 95 | ifneq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y) |
95 | stackp-y := -fstack-protector | 96 | $(warning stack-protector enabled but compiler support broken) |
96 | KBUILD_CFLAGS += $(stackp-y) | ||
97 | else | ||
98 | $(warning stack protector enabled but no compiler support) | ||
99 | endif | 97 | endif |
100 | endif | 98 | endif |
101 | 99 | ||
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index d9c11956fce0..de7066918005 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile | |||
@@ -20,7 +20,7 @@ targets := vmlinux.bin setup.bin setup.elf bzImage | |||
20 | targets += fdimage fdimage144 fdimage288 image.iso mtools.conf | 20 | targets += fdimage fdimage144 fdimage288 image.iso mtools.conf |
21 | subdir- := compressed | 21 | subdir- := compressed |
22 | 22 | ||
23 | setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o | 23 | setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpuflags.o cpucheck.o |
24 | setup-y += early_serial_console.o edd.o header.o main.o mca.o memory.o | 24 | setup-y += early_serial_console.o edd.o header.o main.o mca.o memory.o |
25 | setup-y += pm.o pmjump.o printf.o regs.o string.o tty.o video.o | 25 | setup-y += pm.o pmjump.o printf.o regs.o string.o tty.o video.o |
26 | setup-y += video-mode.o version.o | 26 | setup-y += video-mode.o version.o |
diff --git a/arch/x86/boot/bioscall.S b/arch/x86/boot/bioscall.S index 1dfbf64e52a2..d401b4a262b0 100644 --- a/arch/x86/boot/bioscall.S +++ b/arch/x86/boot/bioscall.S | |||
@@ -1,6 +1,6 @@ | |||
1 | /* ----------------------------------------------------------------------- | 1 | /* ----------------------------------------------------------------------- |
2 | * | 2 | * |
3 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | 3 | * Copyright 2009-2014 Intel Corporation; author H. Peter Anvin |
4 | * | 4 | * |
5 | * This file is part of the Linux kernel, and is made available under | 5 | * This file is part of the Linux kernel, and is made available under |
6 | * the terms of the GNU General Public License version 2 or (at your | 6 | * the terms of the GNU General Public License version 2 or (at your |
@@ -13,8 +13,8 @@ | |||
13 | * touching registers they shouldn't be. | 13 | * touching registers they shouldn't be. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | .code16gcc | 16 | .code16 |
17 | .text | 17 | .section ".inittext","ax" |
18 | .globl intcall | 18 | .globl intcall |
19 | .type intcall, @function | 19 | .type intcall, @function |
20 | intcall: | 20 | intcall: |
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index ef72baeff484..50f8c5e0f37e 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h | |||
@@ -26,9 +26,8 @@ | |||
26 | #include <asm/boot.h> | 26 | #include <asm/boot.h> |
27 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
28 | #include "bitops.h" | 28 | #include "bitops.h" |
29 | #include <asm/cpufeature.h> | ||
30 | #include <asm/processor-flags.h> | ||
31 | #include "ctype.h" | 29 | #include "ctype.h" |
30 | #include "cpuflags.h" | ||
32 | 31 | ||
33 | /* Useful macros */ | 32 | /* Useful macros */ |
34 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) | 33 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) |
@@ -307,14 +306,7 @@ static inline int cmdline_find_option_bool(const char *option) | |||
307 | return __cmdline_find_option_bool(cmd_line_ptr, option); | 306 | return __cmdline_find_option_bool(cmd_line_ptr, option); |
308 | } | 307 | } |
309 | 308 | ||
310 | |||
311 | /* cpu.c, cpucheck.c */ | 309 | /* cpu.c, cpucheck.c */ |
312 | struct cpu_features { | ||
313 | int level; /* Family, or 64 for x86-64 */ | ||
314 | int model; | ||
315 | u32 flags[NCAPINTS]; | ||
316 | }; | ||
317 | extern struct cpu_features cpu; | ||
318 | int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr); | 310 | int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr); |
319 | int validate_cpu(void); | 311 | int validate_cpu(void); |
320 | 312 | ||
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index c8a6792e7842..0fcd9133790c 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -28,7 +28,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include | |||
28 | 28 | ||
29 | VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ | 29 | VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ |
30 | $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ | 30 | $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ |
31 | $(obj)/piggy.o | 31 | $(obj)/piggy.o $(obj)/cpuflags.o $(obj)/aslr.o |
32 | 32 | ||
33 | $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone | 33 | $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone |
34 | 34 | ||
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c new file mode 100644 index 000000000000..90a21f430117 --- /dev/null +++ b/arch/x86/boot/compressed/aslr.c | |||
@@ -0,0 +1,316 @@ | |||
1 | #include "misc.h" | ||
2 | |||
3 | #ifdef CONFIG_RANDOMIZE_BASE | ||
4 | #include <asm/msr.h> | ||
5 | #include <asm/archrandom.h> | ||
6 | #include <asm/e820.h> | ||
7 | |||
8 | #include <generated/compile.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/uts.h> | ||
11 | #include <linux/utsname.h> | ||
12 | #include <generated/utsrelease.h> | ||
13 | |||
14 | /* Simplified build-specific string for starting entropy. */ | ||
15 | static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@" | ||
16 | LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION; | ||
17 | |||
18 | #define I8254_PORT_CONTROL 0x43 | ||
19 | #define I8254_PORT_COUNTER0 0x40 | ||
20 | #define I8254_CMD_READBACK 0xC0 | ||
21 | #define I8254_SELECT_COUNTER0 0x02 | ||
22 | #define I8254_STATUS_NOTREADY 0x40 | ||
23 | static inline u16 i8254(void) | ||
24 | { | ||
25 | u16 status, timer; | ||
26 | |||
27 | do { | ||
28 | outb(I8254_PORT_CONTROL, | ||
29 | I8254_CMD_READBACK | I8254_SELECT_COUNTER0); | ||
30 | status = inb(I8254_PORT_COUNTER0); | ||
31 | timer = inb(I8254_PORT_COUNTER0); | ||
32 | timer |= inb(I8254_PORT_COUNTER0) << 8; | ||
33 | } while (status & I8254_STATUS_NOTREADY); | ||
34 | |||
35 | return timer; | ||
36 | } | ||
37 | |||
38 | static unsigned long rotate_xor(unsigned long hash, const void *area, | ||
39 | size_t size) | ||
40 | { | ||
41 | size_t i; | ||
42 | unsigned long *ptr = (unsigned long *)area; | ||
43 | |||
44 | for (i = 0; i < size / sizeof(hash); i++) { | ||
45 | /* Rotate by odd number of bits and XOR. */ | ||
46 | hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7); | ||
47 | hash ^= ptr[i]; | ||
48 | } | ||
49 | |||
50 | return hash; | ||
51 | } | ||
52 | |||
53 | /* Attempt to create a simple but unpredictable starting entropy. */ | ||
54 | static unsigned long get_random_boot(void) | ||
55 | { | ||
56 | unsigned long hash = 0; | ||
57 | |||
58 | hash = rotate_xor(hash, build_str, sizeof(build_str)); | ||
59 | hash = rotate_xor(hash, real_mode, sizeof(*real_mode)); | ||
60 | |||
61 | return hash; | ||
62 | } | ||
63 | |||
64 | static unsigned long get_random_long(void) | ||
65 | { | ||
66 | #ifdef CONFIG_X86_64 | ||
67 | const unsigned long mix_const = 0x5d6008cbf3848dd3UL; | ||
68 | #else | ||
69 | const unsigned long mix_const = 0x3f39e593UL; | ||
70 | #endif | ||
71 | unsigned long raw, random = get_random_boot(); | ||
72 | bool use_i8254 = true; | ||
73 | |||
74 | debug_putstr("KASLR using"); | ||
75 | |||
76 | if (has_cpuflag(X86_FEATURE_RDRAND)) { | ||
77 | debug_putstr(" RDRAND"); | ||
78 | if (rdrand_long(&raw)) { | ||
79 | random ^= raw; | ||
80 | use_i8254 = false; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | if (has_cpuflag(X86_FEATURE_TSC)) { | ||
85 | debug_putstr(" RDTSC"); | ||
86 | rdtscll(raw); | ||
87 | |||
88 | random ^= raw; | ||
89 | use_i8254 = false; | ||
90 | } | ||
91 | |||
92 | if (use_i8254) { | ||
93 | debug_putstr(" i8254"); | ||
94 | random ^= i8254(); | ||
95 | } | ||
96 | |||
97 | /* Circular multiply for better bit diffusion */ | ||
98 | asm("mul %3" | ||
99 | : "=a" (random), "=d" (raw) | ||
100 | : "a" (random), "rm" (mix_const)); | ||
101 | random += raw; | ||
102 | |||
103 | debug_putstr("...\n"); | ||
104 | |||
105 | return random; | ||
106 | } | ||
107 | |||
108 | struct mem_vector { | ||
109 | unsigned long start; | ||
110 | unsigned long size; | ||
111 | }; | ||
112 | |||
113 | #define MEM_AVOID_MAX 5 | ||
114 | struct mem_vector mem_avoid[MEM_AVOID_MAX]; | ||
115 | |||
116 | static bool mem_contains(struct mem_vector *region, struct mem_vector *item) | ||
117 | { | ||
118 | /* Item at least partially before region. */ | ||
119 | if (item->start < region->start) | ||
120 | return false; | ||
121 | /* Item at least partially after region. */ | ||
122 | if (item->start + item->size > region->start + region->size) | ||
123 | return false; | ||
124 | return true; | ||
125 | } | ||
126 | |||
127 | static bool mem_overlaps(struct mem_vector *one, struct mem_vector *two) | ||
128 | { | ||
129 | /* Item one is entirely before item two. */ | ||
130 | if (one->start + one->size <= two->start) | ||
131 | return false; | ||
132 | /* Item one is entirely after item two. */ | ||
133 | if (one->start >= two->start + two->size) | ||
134 | return false; | ||
135 | return true; | ||
136 | } | ||
137 | |||
138 | static void mem_avoid_init(unsigned long input, unsigned long input_size, | ||
139 | unsigned long output, unsigned long output_size) | ||
140 | { | ||
141 | u64 initrd_start, initrd_size; | ||
142 | u64 cmd_line, cmd_line_size; | ||
143 | unsigned long unsafe, unsafe_len; | ||
144 | char *ptr; | ||
145 | |||
146 | /* | ||
147 | * Avoid the region that is unsafe to overlap during | ||
148 | * decompression (see calculations at top of misc.c). | ||
149 | */ | ||
150 | unsafe_len = (output_size >> 12) + 32768 + 18; | ||
151 | unsafe = (unsigned long)input + input_size - unsafe_len; | ||
152 | mem_avoid[0].start = unsafe; | ||
153 | mem_avoid[0].size = unsafe_len; | ||
154 | |||
155 | /* Avoid initrd. */ | ||
156 | initrd_start = (u64)real_mode->ext_ramdisk_image << 32; | ||
157 | initrd_start |= real_mode->hdr.ramdisk_image; | ||
158 | initrd_size = (u64)real_mode->ext_ramdisk_size << 32; | ||
159 | initrd_size |= real_mode->hdr.ramdisk_size; | ||
160 | mem_avoid[1].start = initrd_start; | ||
161 | mem_avoid[1].size = initrd_size; | ||
162 | |||
163 | /* Avoid kernel command line. */ | ||
164 | cmd_line = (u64)real_mode->ext_cmd_line_ptr << 32; | ||
165 | cmd_line |= real_mode->hdr.cmd_line_ptr; | ||
166 | /* Calculate size of cmd_line. */ | ||
167 | ptr = (char *)(unsigned long)cmd_line; | ||
168 | for (cmd_line_size = 0; ptr[cmd_line_size++]; ) | ||
169 | ; | ||
170 | mem_avoid[2].start = cmd_line; | ||
171 | mem_avoid[2].size = cmd_line_size; | ||
172 | |||
173 | /* Avoid heap memory. */ | ||
174 | mem_avoid[3].start = (unsigned long)free_mem_ptr; | ||
175 | mem_avoid[3].size = BOOT_HEAP_SIZE; | ||
176 | |||
177 | /* Avoid stack memory. */ | ||
178 | mem_avoid[4].start = (unsigned long)free_mem_end_ptr; | ||
179 | mem_avoid[4].size = BOOT_STACK_SIZE; | ||
180 | } | ||
181 | |||
182 | /* Does this memory vector overlap a known avoided area? */ | ||
183 | bool mem_avoid_overlap(struct mem_vector *img) | ||
184 | { | ||
185 | int i; | ||
186 | |||
187 | for (i = 0; i < MEM_AVOID_MAX; i++) { | ||
188 | if (mem_overlaps(img, &mem_avoid[i])) | ||
189 | return true; | ||
190 | } | ||
191 | |||
192 | return false; | ||
193 | } | ||
194 | |||
195 | unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / CONFIG_PHYSICAL_ALIGN]; | ||
196 | unsigned long slot_max = 0; | ||
197 | |||
198 | static void slots_append(unsigned long addr) | ||
199 | { | ||
200 | /* Overflowing the slots list should be impossible. */ | ||
201 | if (slot_max >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET / | ||
202 | CONFIG_PHYSICAL_ALIGN) | ||
203 | return; | ||
204 | |||
205 | slots[slot_max++] = addr; | ||
206 | } | ||
207 | |||
208 | static unsigned long slots_fetch_random(void) | ||
209 | { | ||
210 | /* Handle case of no slots stored. */ | ||
211 | if (slot_max == 0) | ||
212 | return 0; | ||
213 | |||
214 | return slots[get_random_long() % slot_max]; | ||
215 | } | ||
216 | |||
217 | static void process_e820_entry(struct e820entry *entry, | ||
218 | unsigned long minimum, | ||
219 | unsigned long image_size) | ||
220 | { | ||
221 | struct mem_vector region, img; | ||
222 | |||
223 | /* Skip non-RAM entries. */ | ||
224 | if (entry->type != E820_RAM) | ||
225 | return; | ||
226 | |||
227 | /* Ignore entries entirely above our maximum. */ | ||
228 | if (entry->addr >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET) | ||
229 | return; | ||
230 | |||
231 | /* Ignore entries entirely below our minimum. */ | ||
232 | if (entry->addr + entry->size < minimum) | ||
233 | return; | ||
234 | |||
235 | region.start = entry->addr; | ||
236 | region.size = entry->size; | ||
237 | |||
238 | /* Potentially raise address to minimum location. */ | ||
239 | if (region.start < minimum) | ||
240 | region.start = minimum; | ||
241 | |||
242 | /* Potentially raise address to meet alignment requirements. */ | ||
243 | region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN); | ||
244 | |||
245 | /* Did we raise the address above the bounds of this e820 region? */ | ||
246 | if (region.start > entry->addr + entry->size) | ||
247 | return; | ||
248 | |||
249 | /* Reduce size by any delta from the original address. */ | ||
250 | region.size -= region.start - entry->addr; | ||
251 | |||
252 | /* Reduce maximum size to fit end of image within maximum limit. */ | ||
253 | if (region.start + region.size > CONFIG_RANDOMIZE_BASE_MAX_OFFSET) | ||
254 | region.size = CONFIG_RANDOMIZE_BASE_MAX_OFFSET - region.start; | ||
255 | |||
256 | /* Walk each aligned slot and check for avoided areas. */ | ||
257 | for (img.start = region.start, img.size = image_size ; | ||
258 | mem_contains(®ion, &img) ; | ||
259 | img.start += CONFIG_PHYSICAL_ALIGN) { | ||
260 | if (mem_avoid_overlap(&img)) | ||
261 | continue; | ||
262 | slots_append(img.start); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static unsigned long find_random_addr(unsigned long minimum, | ||
267 | unsigned long size) | ||
268 | { | ||
269 | int i; | ||
270 | unsigned long addr; | ||
271 | |||
272 | /* Make sure minimum is aligned. */ | ||
273 | minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN); | ||
274 | |||
275 | /* Verify potential e820 positions, appending to slots list. */ | ||
276 | for (i = 0; i < real_mode->e820_entries; i++) { | ||
277 | process_e820_entry(&real_mode->e820_map[i], minimum, size); | ||
278 | } | ||
279 | |||
280 | return slots_fetch_random(); | ||
281 | } | ||
282 | |||
283 | unsigned char *choose_kernel_location(unsigned char *input, | ||
284 | unsigned long input_size, | ||
285 | unsigned char *output, | ||
286 | unsigned long output_size) | ||
287 | { | ||
288 | unsigned long choice = (unsigned long)output; | ||
289 | unsigned long random; | ||
290 | |||
291 | if (cmdline_find_option_bool("nokaslr")) { | ||
292 | debug_putstr("KASLR disabled...\n"); | ||
293 | goto out; | ||
294 | } | ||
295 | |||
296 | /* Record the various known unsafe memory ranges. */ | ||
297 | mem_avoid_init((unsigned long)input, input_size, | ||
298 | (unsigned long)output, output_size); | ||
299 | |||
300 | /* Walk e820 and find a random address. */ | ||
301 | random = find_random_addr(choice, output_size); | ||
302 | if (!random) { | ||
303 | debug_putstr("KASLR could not find suitable E820 region...\n"); | ||
304 | goto out; | ||
305 | } | ||
306 | |||
307 | /* Always enforce the minimum. */ | ||
308 | if (random < choice) | ||
309 | goto out; | ||
310 | |||
311 | choice = random; | ||
312 | out: | ||
313 | return (unsigned char *)choice; | ||
314 | } | ||
315 | |||
316 | #endif /* CONFIG_RANDOMIZE_BASE */ | ||
diff --git a/arch/x86/boot/compressed/cmdline.c b/arch/x86/boot/compressed/cmdline.c index bffd73b45b1f..b68e3033e6b9 100644 --- a/arch/x86/boot/compressed/cmdline.c +++ b/arch/x86/boot/compressed/cmdline.c | |||
@@ -1,6 +1,6 @@ | |||
1 | #include "misc.h" | 1 | #include "misc.h" |
2 | 2 | ||
3 | #ifdef CONFIG_EARLY_PRINTK | 3 | #if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE |
4 | 4 | ||
5 | static unsigned long fs; | 5 | static unsigned long fs; |
6 | static inline void set_fs(unsigned long seg) | 6 | static inline void set_fs(unsigned long seg) |
diff --git a/arch/x86/boot/compressed/cpuflags.c b/arch/x86/boot/compressed/cpuflags.c new file mode 100644 index 000000000000..aa313466118b --- /dev/null +++ b/arch/x86/boot/compressed/cpuflags.c | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifdef CONFIG_RANDOMIZE_BASE | ||
2 | |||
3 | #include "../cpuflags.c" | ||
4 | |||
5 | bool has_cpuflag(int flag) | ||
6 | { | ||
7 | get_cpuflags(); | ||
8 | |||
9 | return test_bit(flag, cpu.flags); | ||
10 | } | ||
11 | |||
12 | #endif | ||
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index 5d6f6891b188..9116aac232c7 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S | |||
@@ -117,9 +117,11 @@ preferred_addr: | |||
117 | addl %eax, %ebx | 117 | addl %eax, %ebx |
118 | notl %eax | 118 | notl %eax |
119 | andl %eax, %ebx | 119 | andl %eax, %ebx |
120 | #else | 120 | cmpl $LOAD_PHYSICAL_ADDR, %ebx |
121 | movl $LOAD_PHYSICAL_ADDR, %ebx | 121 | jge 1f |
122 | #endif | 122 | #endif |
123 | movl $LOAD_PHYSICAL_ADDR, %ebx | ||
124 | 1: | ||
123 | 125 | ||
124 | /* Target address to relocate to for decompression */ | 126 | /* Target address to relocate to for decompression */ |
125 | addl $z_extract_offset, %ebx | 127 | addl $z_extract_offset, %ebx |
@@ -191,14 +193,14 @@ relocated: | |||
191 | leal boot_heap(%ebx), %eax | 193 | leal boot_heap(%ebx), %eax |
192 | pushl %eax /* heap area */ | 194 | pushl %eax /* heap area */ |
193 | pushl %esi /* real mode pointer */ | 195 | pushl %esi /* real mode pointer */ |
194 | call decompress_kernel | 196 | call decompress_kernel /* returns kernel location in %eax */ |
195 | addl $24, %esp | 197 | addl $24, %esp |
196 | 198 | ||
197 | /* | 199 | /* |
198 | * Jump to the decompressed kernel. | 200 | * Jump to the decompressed kernel. |
199 | */ | 201 | */ |
200 | xorl %ebx, %ebx | 202 | xorl %ebx, %ebx |
201 | jmp *%ebp | 203 | jmp *%eax |
202 | 204 | ||
203 | /* | 205 | /* |
204 | * Stack and heap for uncompression | 206 | * Stack and heap for uncompression |
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index c337422b575d..c5c1ae0997e7 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S | |||
@@ -94,9 +94,11 @@ ENTRY(startup_32) | |||
94 | addl %eax, %ebx | 94 | addl %eax, %ebx |
95 | notl %eax | 95 | notl %eax |
96 | andl %eax, %ebx | 96 | andl %eax, %ebx |
97 | #else | 97 | cmpl $LOAD_PHYSICAL_ADDR, %ebx |
98 | movl $LOAD_PHYSICAL_ADDR, %ebx | 98 | jge 1f |
99 | #endif | 99 | #endif |
100 | movl $LOAD_PHYSICAL_ADDR, %ebx | ||
101 | 1: | ||
100 | 102 | ||
101 | /* Target address to relocate to for decompression */ | 103 | /* Target address to relocate to for decompression */ |
102 | addl $z_extract_offset, %ebx | 104 | addl $z_extract_offset, %ebx |
@@ -269,9 +271,11 @@ preferred_addr: | |||
269 | addq %rax, %rbp | 271 | addq %rax, %rbp |
270 | notq %rax | 272 | notq %rax |
271 | andq %rax, %rbp | 273 | andq %rax, %rbp |
272 | #else | 274 | cmpq $LOAD_PHYSICAL_ADDR, %rbp |
273 | movq $LOAD_PHYSICAL_ADDR, %rbp | 275 | jge 1f |
274 | #endif | 276 | #endif |
277 | movq $LOAD_PHYSICAL_ADDR, %rbp | ||
278 | 1: | ||
275 | 279 | ||
276 | /* Target address to relocate to for decompression */ | 280 | /* Target address to relocate to for decompression */ |
277 | leaq z_extract_offset(%rbp), %rbx | 281 | leaq z_extract_offset(%rbp), %rbx |
@@ -339,13 +343,13 @@ relocated: | |||
339 | movl $z_input_len, %ecx /* input_len */ | 343 | movl $z_input_len, %ecx /* input_len */ |
340 | movq %rbp, %r8 /* output target address */ | 344 | movq %rbp, %r8 /* output target address */ |
341 | movq $z_output_len, %r9 /* decompressed length */ | 345 | movq $z_output_len, %r9 /* decompressed length */ |
342 | call decompress_kernel | 346 | call decompress_kernel /* returns kernel location in %rax */ |
343 | popq %rsi | 347 | popq %rsi |
344 | 348 | ||
345 | /* | 349 | /* |
346 | * Jump to the decompressed kernel. | 350 | * Jump to the decompressed kernel. |
347 | */ | 351 | */ |
348 | jmp *%rbp | 352 | jmp *%rax |
349 | 353 | ||
350 | .code32 | 354 | .code32 |
351 | no_longmode: | 355 | no_longmode: |
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 434f077d2c4d..196eaf373a06 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
@@ -112,14 +112,8 @@ struct boot_params *real_mode; /* Pointer to real-mode data */ | |||
112 | void *memset(void *s, int c, size_t n); | 112 | void *memset(void *s, int c, size_t n); |
113 | void *memcpy(void *dest, const void *src, size_t n); | 113 | void *memcpy(void *dest, const void *src, size_t n); |
114 | 114 | ||
115 | #ifdef CONFIG_X86_64 | 115 | memptr free_mem_ptr; |
116 | #define memptr long | 116 | memptr free_mem_end_ptr; |
117 | #else | ||
118 | #define memptr unsigned | ||
119 | #endif | ||
120 | |||
121 | static memptr free_mem_ptr; | ||
122 | static memptr free_mem_end_ptr; | ||
123 | 117 | ||
124 | static char *vidmem; | 118 | static char *vidmem; |
125 | static int vidport; | 119 | static int vidport; |
@@ -395,7 +389,7 @@ static void parse_elf(void *output) | |||
395 | free(phdrs); | 389 | free(phdrs); |
396 | } | 390 | } |
397 | 391 | ||
398 | asmlinkage void decompress_kernel(void *rmode, memptr heap, | 392 | asmlinkage void *decompress_kernel(void *rmode, memptr heap, |
399 | unsigned char *input_data, | 393 | unsigned char *input_data, |
400 | unsigned long input_len, | 394 | unsigned long input_len, |
401 | unsigned char *output, | 395 | unsigned char *output, |
@@ -422,6 +416,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, | |||
422 | free_mem_ptr = heap; /* Heap */ | 416 | free_mem_ptr = heap; /* Heap */ |
423 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; | 417 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; |
424 | 418 | ||
419 | output = choose_kernel_location(input_data, input_len, | ||
420 | output, output_len); | ||
421 | |||
422 | /* Validate memory location choices. */ | ||
425 | if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) | 423 | if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) |
426 | error("Destination address inappropriately aligned"); | 424 | error("Destination address inappropriately aligned"); |
427 | #ifdef CONFIG_X86_64 | 425 | #ifdef CONFIG_X86_64 |
@@ -441,5 +439,5 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, | |||
441 | parse_elf(output); | 439 | parse_elf(output); |
442 | handle_relocations(output, output_len); | 440 | handle_relocations(output, output_len); |
443 | debug_putstr("done.\nBooting the kernel.\n"); | 441 | debug_putstr("done.\nBooting the kernel.\n"); |
444 | return; | 442 | return output; |
445 | } | 443 | } |
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 674019d8e235..24e3e569a13c 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h | |||
@@ -23,7 +23,15 @@ | |||
23 | #define BOOT_BOOT_H | 23 | #define BOOT_BOOT_H |
24 | #include "../ctype.h" | 24 | #include "../ctype.h" |
25 | 25 | ||
26 | #ifdef CONFIG_X86_64 | ||
27 | #define memptr long | ||
28 | #else | ||
29 | #define memptr unsigned | ||
30 | #endif | ||
31 | |||
26 | /* misc.c */ | 32 | /* misc.c */ |
33 | extern memptr free_mem_ptr; | ||
34 | extern memptr free_mem_end_ptr; | ||
27 | extern struct boot_params *real_mode; /* Pointer to real-mode data */ | 35 | extern struct boot_params *real_mode; /* Pointer to real-mode data */ |
28 | void __putstr(const char *s); | 36 | void __putstr(const char *s); |
29 | #define error_putstr(__x) __putstr(__x) | 37 | #define error_putstr(__x) __putstr(__x) |
@@ -39,23 +47,40 @@ static inline void debug_putstr(const char *s) | |||
39 | 47 | ||
40 | #endif | 48 | #endif |
41 | 49 | ||
42 | #ifdef CONFIG_EARLY_PRINTK | 50 | #if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE |
43 | |||
44 | /* cmdline.c */ | 51 | /* cmdline.c */ |
45 | int cmdline_find_option(const char *option, char *buffer, int bufsize); | 52 | int cmdline_find_option(const char *option, char *buffer, int bufsize); |
46 | int cmdline_find_option_bool(const char *option); | 53 | int cmdline_find_option_bool(const char *option); |
54 | #endif | ||
47 | 55 | ||
48 | /* early_serial_console.c */ | ||
49 | extern int early_serial_base; | ||
50 | void console_init(void); | ||
51 | 56 | ||
57 | #if CONFIG_RANDOMIZE_BASE | ||
58 | /* aslr.c */ | ||
59 | unsigned char *choose_kernel_location(unsigned char *input, | ||
60 | unsigned long input_size, | ||
61 | unsigned char *output, | ||
62 | unsigned long output_size); | ||
63 | /* cpuflags.c */ | ||
64 | bool has_cpuflag(int flag); | ||
52 | #else | 65 | #else |
66 | static inline | ||
67 | unsigned char *choose_kernel_location(unsigned char *input, | ||
68 | unsigned long input_size, | ||
69 | unsigned char *output, | ||
70 | unsigned long output_size) | ||
71 | { | ||
72 | return output; | ||
73 | } | ||
74 | #endif | ||
53 | 75 | ||
76 | #ifdef CONFIG_EARLY_PRINTK | ||
54 | /* early_serial_console.c */ | 77 | /* early_serial_console.c */ |
78 | extern int early_serial_base; | ||
79 | void console_init(void); | ||
80 | #else | ||
55 | static const int early_serial_base; | 81 | static const int early_serial_base; |
56 | static inline void console_init(void) | 82 | static inline void console_init(void) |
57 | { } | 83 | { } |
58 | |||
59 | #endif | 84 | #endif |
60 | 85 | ||
61 | #endif | 86 | #endif |
diff --git a/arch/x86/boot/copy.S b/arch/x86/boot/copy.S index 11f272c6f5e9..1eb7d298b47d 100644 --- a/arch/x86/boot/copy.S +++ b/arch/x86/boot/copy.S | |||
@@ -14,7 +14,7 @@ | |||
14 | * Memory copy routines | 14 | * Memory copy routines |
15 | */ | 15 | */ |
16 | 16 | ||
17 | .code16gcc | 17 | .code16 |
18 | .text | 18 | .text |
19 | 19 | ||
20 | GLOBAL(memcpy) | 20 | GLOBAL(memcpy) |
@@ -30,7 +30,7 @@ GLOBAL(memcpy) | |||
30 | rep; movsb | 30 | rep; movsb |
31 | popw %di | 31 | popw %di |
32 | popw %si | 32 | popw %si |
33 | ret | 33 | retl |
34 | ENDPROC(memcpy) | 34 | ENDPROC(memcpy) |
35 | 35 | ||
36 | GLOBAL(memset) | 36 | GLOBAL(memset) |
@@ -45,25 +45,25 @@ GLOBAL(memset) | |||
45 | andw $3, %cx | 45 | andw $3, %cx |
46 | rep; stosb | 46 | rep; stosb |
47 | popw %di | 47 | popw %di |
48 | ret | 48 | retl |
49 | ENDPROC(memset) | 49 | ENDPROC(memset) |
50 | 50 | ||
51 | GLOBAL(copy_from_fs) | 51 | GLOBAL(copy_from_fs) |
52 | pushw %ds | 52 | pushw %ds |
53 | pushw %fs | 53 | pushw %fs |
54 | popw %ds | 54 | popw %ds |
55 | call memcpy | 55 | calll memcpy |
56 | popw %ds | 56 | popw %ds |
57 | ret | 57 | retl |
58 | ENDPROC(copy_from_fs) | 58 | ENDPROC(copy_from_fs) |
59 | 59 | ||
60 | GLOBAL(copy_to_fs) | 60 | GLOBAL(copy_to_fs) |
61 | pushw %es | 61 | pushw %es |
62 | pushw %fs | 62 | pushw %fs |
63 | popw %es | 63 | popw %es |
64 | call memcpy | 64 | calll memcpy |
65 | popw %es | 65 | popw %es |
66 | ret | 66 | retl |
67 | ENDPROC(copy_to_fs) | 67 | ENDPROC(copy_to_fs) |
68 | 68 | ||
69 | #if 0 /* Not currently used, but can be enabled as needed */ | 69 | #if 0 /* Not currently used, but can be enabled as needed */ |
@@ -71,17 +71,17 @@ GLOBAL(copy_from_gs) | |||
71 | pushw %ds | 71 | pushw %ds |
72 | pushw %gs | 72 | pushw %gs |
73 | popw %ds | 73 | popw %ds |
74 | call memcpy | 74 | calll memcpy |
75 | popw %ds | 75 | popw %ds |
76 | ret | 76 | retl |
77 | ENDPROC(copy_from_gs) | 77 | ENDPROC(copy_from_gs) |
78 | 78 | ||
79 | GLOBAL(copy_to_gs) | 79 | GLOBAL(copy_to_gs) |
80 | pushw %es | 80 | pushw %es |
81 | pushw %gs | 81 | pushw %gs |
82 | popw %es | 82 | popw %es |
83 | call memcpy | 83 | calll memcpy |
84 | popw %es | 84 | popw %es |
85 | ret | 85 | retl |
86 | ENDPROC(copy_to_gs) | 86 | ENDPROC(copy_to_gs) |
87 | #endif | 87 | #endif |
diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c index 4d3ff037201f..100a9a10076a 100644 --- a/arch/x86/boot/cpucheck.c +++ b/arch/x86/boot/cpucheck.c | |||
@@ -28,8 +28,6 @@ | |||
28 | #include <asm/required-features.h> | 28 | #include <asm/required-features.h> |
29 | #include <asm/msr-index.h> | 29 | #include <asm/msr-index.h> |
30 | 30 | ||
31 | struct cpu_features cpu; | ||
32 | static u32 cpu_vendor[3]; | ||
33 | static u32 err_flags[NCAPINTS]; | 31 | static u32 err_flags[NCAPINTS]; |
34 | 32 | ||
35 | static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY; | 33 | static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY; |
@@ -69,92 +67,8 @@ static int is_transmeta(void) | |||
69 | cpu_vendor[2] == A32('M', 'x', '8', '6'); | 67 | cpu_vendor[2] == A32('M', 'x', '8', '6'); |
70 | } | 68 | } |
71 | 69 | ||
72 | static int has_fpu(void) | ||
73 | { | ||
74 | u16 fcw = -1, fsw = -1; | ||
75 | u32 cr0; | ||
76 | |||
77 | asm("movl %%cr0,%0" : "=r" (cr0)); | ||
78 | if (cr0 & (X86_CR0_EM|X86_CR0_TS)) { | ||
79 | cr0 &= ~(X86_CR0_EM|X86_CR0_TS); | ||
80 | asm volatile("movl %0,%%cr0" : : "r" (cr0)); | ||
81 | } | ||
82 | |||
83 | asm volatile("fninit ; fnstsw %0 ; fnstcw %1" | ||
84 | : "+m" (fsw), "+m" (fcw)); | ||
85 | |||
86 | return fsw == 0 && (fcw & 0x103f) == 0x003f; | ||
87 | } | ||
88 | |||
89 | static int has_eflag(u32 mask) | ||
90 | { | ||
91 | u32 f0, f1; | ||
92 | |||
93 | asm("pushfl ; " | ||
94 | "pushfl ; " | ||
95 | "popl %0 ; " | ||
96 | "movl %0,%1 ; " | ||
97 | "xorl %2,%1 ; " | ||
98 | "pushl %1 ; " | ||
99 | "popfl ; " | ||
100 | "pushfl ; " | ||
101 | "popl %1 ; " | ||
102 | "popfl" | ||
103 | : "=&r" (f0), "=&r" (f1) | ||
104 | : "ri" (mask)); | ||
105 | |||
106 | return !!((f0^f1) & mask); | ||
107 | } | ||
108 | |||
109 | static void get_flags(void) | ||
110 | { | ||
111 | u32 max_intel_level, max_amd_level; | ||
112 | u32 tfms; | ||
113 | |||
114 | if (has_fpu()) | ||
115 | set_bit(X86_FEATURE_FPU, cpu.flags); | ||
116 | |||
117 | if (has_eflag(X86_EFLAGS_ID)) { | ||
118 | asm("cpuid" | ||
119 | : "=a" (max_intel_level), | ||
120 | "=b" (cpu_vendor[0]), | ||
121 | "=d" (cpu_vendor[1]), | ||
122 | "=c" (cpu_vendor[2]) | ||
123 | : "a" (0)); | ||
124 | |||
125 | if (max_intel_level >= 0x00000001 && | ||
126 | max_intel_level <= 0x0000ffff) { | ||
127 | asm("cpuid" | ||
128 | : "=a" (tfms), | ||
129 | "=c" (cpu.flags[4]), | ||
130 | "=d" (cpu.flags[0]) | ||
131 | : "a" (0x00000001) | ||
132 | : "ebx"); | ||
133 | cpu.level = (tfms >> 8) & 15; | ||
134 | cpu.model = (tfms >> 4) & 15; | ||
135 | if (cpu.level >= 6) | ||
136 | cpu.model += ((tfms >> 16) & 0xf) << 4; | ||
137 | } | ||
138 | |||
139 | asm("cpuid" | ||
140 | : "=a" (max_amd_level) | ||
141 | : "a" (0x80000000) | ||
142 | : "ebx", "ecx", "edx"); | ||
143 | |||
144 | if (max_amd_level >= 0x80000001 && | ||
145 | max_amd_level <= 0x8000ffff) { | ||
146 | u32 eax = 0x80000001; | ||
147 | asm("cpuid" | ||
148 | : "+a" (eax), | ||
149 | "=c" (cpu.flags[6]), | ||
150 | "=d" (cpu.flags[1]) | ||
151 | : : "ebx"); | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /* Returns a bitmask of which words we have error bits in */ | 70 | /* Returns a bitmask of which words we have error bits in */ |
157 | static int check_flags(void) | 71 | static int check_cpuflags(void) |
158 | { | 72 | { |
159 | u32 err; | 73 | u32 err; |
160 | int i; | 74 | int i; |
@@ -187,8 +101,8 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) | |||
187 | if (has_eflag(X86_EFLAGS_AC)) | 101 | if (has_eflag(X86_EFLAGS_AC)) |
188 | cpu.level = 4; | 102 | cpu.level = 4; |
189 | 103 | ||
190 | get_flags(); | 104 | get_cpuflags(); |
191 | err = check_flags(); | 105 | err = check_cpuflags(); |
192 | 106 | ||
193 | if (test_bit(X86_FEATURE_LM, cpu.flags)) | 107 | if (test_bit(X86_FEATURE_LM, cpu.flags)) |
194 | cpu.level = 64; | 108 | cpu.level = 64; |
@@ -207,8 +121,8 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) | |||
207 | eax &= ~(1 << 15); | 121 | eax &= ~(1 << 15); |
208 | asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); | 122 | asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
209 | 123 | ||
210 | get_flags(); /* Make sure it really did something */ | 124 | get_cpuflags(); /* Make sure it really did something */ |
211 | err = check_flags(); | 125 | err = check_cpuflags(); |
212 | } else if (err == 0x01 && | 126 | } else if (err == 0x01 && |
213 | !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) && | 127 | !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) && |
214 | is_centaur() && cpu.model >= 6) { | 128 | is_centaur() && cpu.model >= 6) { |
@@ -223,7 +137,7 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) | |||
223 | asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); | 137 | asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
224 | 138 | ||
225 | set_bit(X86_FEATURE_CX8, cpu.flags); | 139 | set_bit(X86_FEATURE_CX8, cpu.flags); |
226 | err = check_flags(); | 140 | err = check_cpuflags(); |
227 | } else if (err == 0x01 && is_transmeta()) { | 141 | } else if (err == 0x01 && is_transmeta()) { |
228 | /* Transmeta might have masked feature bits in word 0 */ | 142 | /* Transmeta might have masked feature bits in word 0 */ |
229 | 143 | ||
@@ -238,7 +152,7 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) | |||
238 | : : "ecx", "ebx"); | 152 | : : "ecx", "ebx"); |
239 | asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); | 153 | asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
240 | 154 | ||
241 | err = check_flags(); | 155 | err = check_cpuflags(); |
242 | } | 156 | } |
243 | 157 | ||
244 | if (err_flags_ptr) | 158 | if (err_flags_ptr) |
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c new file mode 100644 index 000000000000..a9fcb7cfb241 --- /dev/null +++ b/arch/x86/boot/cpuflags.c | |||
@@ -0,0 +1,104 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include "bitops.h" | ||
3 | |||
4 | #include <asm/processor-flags.h> | ||
5 | #include <asm/required-features.h> | ||
6 | #include <asm/msr-index.h> | ||
7 | #include "cpuflags.h" | ||
8 | |||
9 | struct cpu_features cpu; | ||
10 | u32 cpu_vendor[3]; | ||
11 | |||
12 | static bool loaded_flags; | ||
13 | |||
14 | static int has_fpu(void) | ||
15 | { | ||
16 | u16 fcw = -1, fsw = -1; | ||
17 | unsigned long cr0; | ||
18 | |||
19 | asm volatile("mov %%cr0,%0" : "=r" (cr0)); | ||
20 | if (cr0 & (X86_CR0_EM|X86_CR0_TS)) { | ||
21 | cr0 &= ~(X86_CR0_EM|X86_CR0_TS); | ||
22 | asm volatile("mov %0,%%cr0" : : "r" (cr0)); | ||
23 | } | ||
24 | |||
25 | asm volatile("fninit ; fnstsw %0 ; fnstcw %1" | ||
26 | : "+m" (fsw), "+m" (fcw)); | ||
27 | |||
28 | return fsw == 0 && (fcw & 0x103f) == 0x003f; | ||
29 | } | ||
30 | |||
31 | int has_eflag(unsigned long mask) | ||
32 | { | ||
33 | unsigned long f0, f1; | ||
34 | |||
35 | asm volatile("pushf \n\t" | ||
36 | "pushf \n\t" | ||
37 | "pop %0 \n\t" | ||
38 | "mov %0,%1 \n\t" | ||
39 | "xor %2,%1 \n\t" | ||
40 | "push %1 \n\t" | ||
41 | "popf \n\t" | ||
42 | "pushf \n\t" | ||
43 | "pop %1 \n\t" | ||
44 | "popf" | ||
45 | : "=&r" (f0), "=&r" (f1) | ||
46 | : "ri" (mask)); | ||
47 | |||
48 | return !!((f0^f1) & mask); | ||
49 | } | ||
50 | |||
51 | /* Handle x86_32 PIC using ebx. */ | ||
52 | #if defined(__i386__) && defined(__PIC__) | ||
53 | # define EBX_REG "=r" | ||
54 | #else | ||
55 | # define EBX_REG "=b" | ||
56 | #endif | ||
57 | |||
58 | static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d) | ||
59 | { | ||
60 | asm volatile(".ifnc %%ebx,%3 ; movl %%ebx,%3 ; .endif \n\t" | ||
61 | "cpuid \n\t" | ||
62 | ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif \n\t" | ||
63 | : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b) | ||
64 | : "a" (id) | ||
65 | ); | ||
66 | } | ||
67 | |||
68 | void get_cpuflags(void) | ||
69 | { | ||
70 | u32 max_intel_level, max_amd_level; | ||
71 | u32 tfms; | ||
72 | u32 ignored; | ||
73 | |||
74 | if (loaded_flags) | ||
75 | return; | ||
76 | loaded_flags = true; | ||
77 | |||
78 | if (has_fpu()) | ||
79 | set_bit(X86_FEATURE_FPU, cpu.flags); | ||
80 | |||
81 | if (has_eflag(X86_EFLAGS_ID)) { | ||
82 | cpuid(0x0, &max_intel_level, &cpu_vendor[0], &cpu_vendor[2], | ||
83 | &cpu_vendor[1]); | ||
84 | |||
85 | if (max_intel_level >= 0x00000001 && | ||
86 | max_intel_level <= 0x0000ffff) { | ||
87 | cpuid(0x1, &tfms, &ignored, &cpu.flags[4], | ||
88 | &cpu.flags[0]); | ||
89 | cpu.level = (tfms >> 8) & 15; | ||
90 | cpu.model = (tfms >> 4) & 15; | ||
91 | if (cpu.level >= 6) | ||
92 | cpu.model += ((tfms >> 16) & 0xf) << 4; | ||
93 | } | ||
94 | |||
95 | cpuid(0x80000000, &max_amd_level, &ignored, &ignored, | ||
96 | &ignored); | ||
97 | |||
98 | if (max_amd_level >= 0x80000001 && | ||
99 | max_amd_level <= 0x8000ffff) { | ||
100 | cpuid(0x80000001, &ignored, &ignored, &cpu.flags[6], | ||
101 | &cpu.flags[1]); | ||
102 | } | ||
103 | } | ||
104 | } | ||
diff --git a/arch/x86/boot/cpuflags.h b/arch/x86/boot/cpuflags.h new file mode 100644 index 000000000000..ea97697e51e4 --- /dev/null +++ b/arch/x86/boot/cpuflags.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef BOOT_CPUFLAGS_H | ||
2 | #define BOOT_CPUFLAGS_H | ||
3 | |||
4 | #include <asm/cpufeature.h> | ||
5 | #include <asm/processor-flags.h> | ||
6 | |||
7 | struct cpu_features { | ||
8 | int level; /* Family, or 64 for x86-64 */ | ||
9 | int model; | ||
10 | u32 flags[NCAPINTS]; | ||
11 | }; | ||
12 | |||
13 | extern struct cpu_features cpu; | ||
14 | extern u32 cpu_vendor[3]; | ||
15 | |||
16 | int has_eflag(unsigned long mask); | ||
17 | void get_cpuflags(void); | ||
18 | |||
19 | #endif | ||
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 9ec06a1f6d61..ec3b8ba68096 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -391,7 +391,14 @@ xloadflags: | |||
391 | #else | 391 | #else |
392 | # define XLF23 0 | 392 | # define XLF23 0 |
393 | #endif | 393 | #endif |
394 | .word XLF0 | XLF1 | XLF23 | 394 | |
395 | #if defined(CONFIG_X86_64) && defined(CONFIG_EFI) && defined(CONFIG_KEXEC) | ||
396 | # define XLF4 XLF_EFI_KEXEC | ||
397 | #else | ||
398 | # define XLF4 0 | ||
399 | #endif | ||
400 | |||
401 | .word XLF0 | XLF1 | XLF23 | XLF4 | ||
395 | 402 | ||
396 | cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, | 403 | cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, |
397 | #added with boot protocol | 404 | #added with boot protocol |
diff --git a/arch/x86/include/asm/archrandom.h b/arch/x86/include/asm/archrandom.h index 0d9ec770f2f8..e6a92455740e 100644 --- a/arch/x86/include/asm/archrandom.h +++ b/arch/x86/include/asm/archrandom.h | |||
@@ -39,6 +39,20 @@ | |||
39 | 39 | ||
40 | #ifdef CONFIG_ARCH_RANDOM | 40 | #ifdef CONFIG_ARCH_RANDOM |
41 | 41 | ||
42 | /* Instead of arch_get_random_long() when alternatives haven't run. */ | ||
43 | static inline int rdrand_long(unsigned long *v) | ||
44 | { | ||
45 | int ok; | ||
46 | asm volatile("1: " RDRAND_LONG "\n\t" | ||
47 | "jc 2f\n\t" | ||
48 | "decl %0\n\t" | ||
49 | "jnz 1b\n\t" | ||
50 | "2:" | ||
51 | : "=r" (ok), "=a" (*v) | ||
52 | : "0" (RDRAND_RETRY_LOOPS)); | ||
53 | return ok; | ||
54 | } | ||
55 | |||
42 | #define GET_RANDOM(name, type, rdrand, nop) \ | 56 | #define GET_RANDOM(name, type, rdrand, nop) \ |
43 | static inline int name(type *v) \ | 57 | static inline int name(type *v) \ |
44 | { \ | 58 | { \ |
@@ -68,6 +82,13 @@ GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3); | |||
68 | 82 | ||
69 | #endif /* CONFIG_X86_64 */ | 83 | #endif /* CONFIG_X86_64 */ |
70 | 84 | ||
85 | #else | ||
86 | |||
87 | static inline int rdrand_long(unsigned long *v) | ||
88 | { | ||
89 | return 0; | ||
90 | } | ||
91 | |||
71 | #endif /* CONFIG_ARCH_RANDOM */ | 92 | #endif /* CONFIG_ARCH_RANDOM */ |
72 | 93 | ||
73 | extern void x86_init_rdrand(struct cpuinfo_x86 *c); | 94 | extern void x86_init_rdrand(struct cpuinfo_x86 *c); |
diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index c6cd358a1eec..04a48903b2eb 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h | |||
@@ -92,12 +92,53 @@ | |||
92 | #endif | 92 | #endif |
93 | #define smp_read_barrier_depends() read_barrier_depends() | 93 | #define smp_read_barrier_depends() read_barrier_depends() |
94 | #define set_mb(var, value) do { (void)xchg(&var, value); } while (0) | 94 | #define set_mb(var, value) do { (void)xchg(&var, value); } while (0) |
95 | #else | 95 | #else /* !SMP */ |
96 | #define smp_mb() barrier() | 96 | #define smp_mb() barrier() |
97 | #define smp_rmb() barrier() | 97 | #define smp_rmb() barrier() |
98 | #define smp_wmb() barrier() | 98 | #define smp_wmb() barrier() |
99 | #define smp_read_barrier_depends() do { } while (0) | 99 | #define smp_read_barrier_depends() do { } while (0) |
100 | #define set_mb(var, value) do { var = value; barrier(); } while (0) | 100 | #define set_mb(var, value) do { var = value; barrier(); } while (0) |
101 | #endif /* SMP */ | ||
102 | |||
103 | #if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE) | ||
104 | |||
105 | /* | ||
106 | * For either of these options x86 doesn't have a strong TSO memory | ||
107 | * model and we should fall back to full barriers. | ||
108 | */ | ||
109 | |||
110 | #define smp_store_release(p, v) \ | ||
111 | do { \ | ||
112 | compiletime_assert_atomic_type(*p); \ | ||
113 | smp_mb(); \ | ||
114 | ACCESS_ONCE(*p) = (v); \ | ||
115 | } while (0) | ||
116 | |||
117 | #define smp_load_acquire(p) \ | ||
118 | ({ \ | ||
119 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
120 | compiletime_assert_atomic_type(*p); \ | ||
121 | smp_mb(); \ | ||
122 | ___p1; \ | ||
123 | }) | ||
124 | |||
125 | #else /* regular x86 TSO memory ordering */ | ||
126 | |||
127 | #define smp_store_release(p, v) \ | ||
128 | do { \ | ||
129 | compiletime_assert_atomic_type(*p); \ | ||
130 | barrier(); \ | ||
131 | ACCESS_ONCE(*p) = (v); \ | ||
132 | } while (0) | ||
133 | |||
134 | #define smp_load_acquire(p) \ | ||
135 | ({ \ | ||
136 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
137 | compiletime_assert_atomic_type(*p); \ | ||
138 | barrier(); \ | ||
139 | ___p1; \ | ||
140 | }) | ||
141 | |||
101 | #endif | 142 | #endif |
102 | 143 | ||
103 | /* | 144 | /* |
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 89270b4318db..e099f9502ace 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
@@ -216,6 +216,7 @@ | |||
216 | #define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */ | 216 | #define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */ |
217 | #define X86_FEATURE_INVPCID (9*32+10) /* Invalidate Processor Context ID */ | 217 | #define X86_FEATURE_INVPCID (9*32+10) /* Invalidate Processor Context ID */ |
218 | #define X86_FEATURE_RTM (9*32+11) /* Restricted Transactional Memory */ | 218 | #define X86_FEATURE_RTM (9*32+11) /* Restricted Transactional Memory */ |
219 | #define X86_FEATURE_MPX (9*32+14) /* Memory Protection Extension */ | ||
219 | #define X86_FEATURE_RDSEED (9*32+18) /* The RDSEED instruction */ | 220 | #define X86_FEATURE_RDSEED (9*32+18) /* The RDSEED instruction */ |
220 | #define X86_FEATURE_ADX (9*32+19) /* The ADCX and ADOX instructions */ | 221 | #define X86_FEATURE_ADX (9*32+19) /* The ADCX and ADOX instructions */ |
221 | #define X86_FEATURE_SMAP (9*32+20) /* Supervisor Mode Access Prevention */ | 222 | #define X86_FEATURE_SMAP (9*32+20) /* Supervisor Mode Access Prevention */ |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 65c6e6e3a552..3b978c472d08 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
@@ -1,6 +1,24 @@ | |||
1 | #ifndef _ASM_X86_EFI_H | 1 | #ifndef _ASM_X86_EFI_H |
2 | #define _ASM_X86_EFI_H | 2 | #define _ASM_X86_EFI_H |
3 | 3 | ||
4 | /* | ||
5 | * We map the EFI regions needed for runtime services non-contiguously, | ||
6 | * with preserved alignment on virtual addresses starting from -4G down | ||
7 | * for a total max space of 64G. This way, we provide for stable runtime | ||
8 | * services addresses across kernels so that a kexec'd kernel can still | ||
9 | * use them. | ||
10 | * | ||
11 | * This is the main reason why we're doing stable VA mappings for RT | ||
12 | * services. | ||
13 | * | ||
14 | * This flag is used in conjuction with a chicken bit called | ||
15 | * "efi=old_map" which can be used as a fallback to the old runtime | ||
16 | * services mapping method in case there's some b0rkage with a | ||
17 | * particular EFI implementation (haha, it is hard to hold up the | ||
18 | * sarcasm here...). | ||
19 | */ | ||
20 | #define EFI_OLD_MEMMAP EFI_ARCH_1 | ||
21 | |||
4 | #ifdef CONFIG_X86_32 | 22 | #ifdef CONFIG_X86_32 |
5 | 23 | ||
6 | #define EFI_LOADER_SIGNATURE "EL32" | 24 | #define EFI_LOADER_SIGNATURE "EL32" |
@@ -69,24 +87,31 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, | |||
69 | efi_call6((f), (u64)(a1), (u64)(a2), (u64)(a3), \ | 87 | efi_call6((f), (u64)(a1), (u64)(a2), (u64)(a3), \ |
70 | (u64)(a4), (u64)(a5), (u64)(a6)) | 88 | (u64)(a4), (u64)(a5), (u64)(a6)) |
71 | 89 | ||
90 | #define _efi_call_virtX(x, f, ...) \ | ||
91 | ({ \ | ||
92 | efi_status_t __s; \ | ||
93 | \ | ||
94 | efi_sync_low_kernel_mappings(); \ | ||
95 | preempt_disable(); \ | ||
96 | __s = efi_call##x((void *)efi.systab->runtime->f, __VA_ARGS__); \ | ||
97 | preempt_enable(); \ | ||
98 | __s; \ | ||
99 | }) | ||
100 | |||
72 | #define efi_call_virt0(f) \ | 101 | #define efi_call_virt0(f) \ |
73 | efi_call0((efi.systab->runtime->f)) | 102 | _efi_call_virtX(0, f) |
74 | #define efi_call_virt1(f, a1) \ | 103 | #define efi_call_virt1(f, a1) \ |
75 | efi_call1((efi.systab->runtime->f), (u64)(a1)) | 104 | _efi_call_virtX(1, f, (u64)(a1)) |
76 | #define efi_call_virt2(f, a1, a2) \ | 105 | #define efi_call_virt2(f, a1, a2) \ |
77 | efi_call2((efi.systab->runtime->f), (u64)(a1), (u64)(a2)) | 106 | _efi_call_virtX(2, f, (u64)(a1), (u64)(a2)) |
78 | #define efi_call_virt3(f, a1, a2, a3) \ | 107 | #define efi_call_virt3(f, a1, a2, a3) \ |
79 | efi_call3((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ | 108 | _efi_call_virtX(3, f, (u64)(a1), (u64)(a2), (u64)(a3)) |
80 | (u64)(a3)) | 109 | #define efi_call_virt4(f, a1, a2, a3, a4) \ |
81 | #define efi_call_virt4(f, a1, a2, a3, a4) \ | 110 | _efi_call_virtX(4, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4)) |
82 | efi_call4((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ | 111 | #define efi_call_virt5(f, a1, a2, a3, a4, a5) \ |
83 | (u64)(a3), (u64)(a4)) | 112 | _efi_call_virtX(5, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4), (u64)(a5)) |
84 | #define efi_call_virt5(f, a1, a2, a3, a4, a5) \ | 113 | #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ |
85 | efi_call5((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ | 114 | _efi_call_virtX(6, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) |
86 | (u64)(a3), (u64)(a4), (u64)(a5)) | ||
87 | #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ | ||
88 | efi_call6((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ | ||
89 | (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) | ||
90 | 115 | ||
91 | extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, | 116 | extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, |
92 | u32 type, u64 attribute); | 117 | u32 type, u64 attribute); |
@@ -95,12 +120,28 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, | |||
95 | 120 | ||
96 | extern int add_efi_memmap; | 121 | extern int add_efi_memmap; |
97 | extern unsigned long x86_efi_facility; | 122 | extern unsigned long x86_efi_facility; |
123 | extern struct efi_scratch efi_scratch; | ||
98 | extern void efi_set_executable(efi_memory_desc_t *md, bool executable); | 124 | extern void efi_set_executable(efi_memory_desc_t *md, bool executable); |
99 | extern int efi_memblock_x86_reserve_range(void); | 125 | extern int efi_memblock_x86_reserve_range(void); |
100 | extern void efi_call_phys_prelog(void); | 126 | extern void efi_call_phys_prelog(void); |
101 | extern void efi_call_phys_epilog(void); | 127 | extern void efi_call_phys_epilog(void); |
102 | extern void efi_unmap_memmap(void); | 128 | extern void efi_unmap_memmap(void); |
103 | extern void efi_memory_uc(u64 addr, unsigned long size); | 129 | extern void efi_memory_uc(u64 addr, unsigned long size); |
130 | extern void __init efi_map_region(efi_memory_desc_t *md); | ||
131 | extern void __init efi_map_region_fixed(efi_memory_desc_t *md); | ||
132 | extern void efi_sync_low_kernel_mappings(void); | ||
133 | extern void efi_setup_page_tables(void); | ||
134 | extern void __init old_map_region(efi_memory_desc_t *md); | ||
135 | |||
136 | struct efi_setup_data { | ||
137 | u64 fw_vendor; | ||
138 | u64 runtime; | ||
139 | u64 tables; | ||
140 | u64 smbios; | ||
141 | u64 reserved[8]; | ||
142 | }; | ||
143 | |||
144 | extern u64 efi_setup; | ||
104 | 145 | ||
105 | #ifdef CONFIG_EFI | 146 | #ifdef CONFIG_EFI |
106 | 147 | ||
@@ -110,7 +151,7 @@ static inline bool efi_is_native(void) | |||
110 | } | 151 | } |
111 | 152 | ||
112 | extern struct console early_efi_console; | 153 | extern struct console early_efi_console; |
113 | 154 | extern void parse_efi_setup(u64 phys_addr, u32 data_len); | |
114 | #else | 155 | #else |
115 | /* | 156 | /* |
116 | * IF EFI is not configured, have the EFI calls return -ENOSYS. | 157 | * IF EFI is not configured, have the EFI calls return -ENOSYS. |
@@ -122,6 +163,7 @@ extern struct console early_efi_console; | |||
122 | #define efi_call4(_f, _a1, _a2, _a3, _a4) (-ENOSYS) | 163 | #define efi_call4(_f, _a1, _a2, _a3, _a4) (-ENOSYS) |
123 | #define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS) | 164 | #define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS) |
124 | #define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS) | 165 | #define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS) |
166 | static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} | ||
125 | #endif /* CONFIG_EFI */ | 167 | #endif /* CONFIG_EFI */ |
126 | 168 | ||
127 | #endif /* _ASM_X86_EFI_H */ | 169 | #endif /* _ASM_X86_EFI_H */ |
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h index be27ba1e947a..b4c1f5453436 100644 --- a/arch/x86/include/asm/futex.h +++ b/arch/x86/include/asm/futex.h | |||
@@ -110,26 +110,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) | |||
110 | static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | 110 | static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
111 | u32 oldval, u32 newval) | 111 | u32 oldval, u32 newval) |
112 | { | 112 | { |
113 | int ret = 0; | 113 | return user_atomic_cmpxchg_inatomic(uval, uaddr, oldval, newval); |
114 | |||
115 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) | ||
116 | return -EFAULT; | ||
117 | |||
118 | asm volatile("\t" ASM_STAC "\n" | ||
119 | "1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n" | ||
120 | "2:\t" ASM_CLAC "\n" | ||
121 | "\t.section .fixup, \"ax\"\n" | ||
122 | "3:\tmov %3, %0\n" | ||
123 | "\tjmp 2b\n" | ||
124 | "\t.previous\n" | ||
125 | _ASM_EXTABLE(1b, 3b) | ||
126 | : "+r" (ret), "=a" (oldval), "+m" (*uaddr) | ||
127 | : "i" (-EFAULT), "r" (newval), "1" (oldval) | ||
128 | : "memory" | ||
129 | ); | ||
130 | |||
131 | *uval = oldval; | ||
132 | return ret; | ||
133 | } | 114 | } |
134 | 115 | ||
135 | #endif | 116 | #endif |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index cba45d99ac1a..67d69b8e2d20 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -191,6 +191,9 @@ extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void); | |||
191 | #define trace_interrupt interrupt | 191 | #define trace_interrupt interrupt |
192 | #endif | 192 | #endif |
193 | 193 | ||
194 | #define VECTOR_UNDEFINED -1 | ||
195 | #define VECTOR_RETRIGGERED -2 | ||
196 | |||
194 | typedef int vector_irq_t[NR_VECTORS]; | 197 | typedef int vector_irq_t[NR_VECTORS]; |
195 | DECLARE_PER_CPU(vector_irq_t, vector_irq); | 198 | DECLARE_PER_CPU(vector_irq_t, vector_irq); |
196 | extern void setup_vector_irq(int cpu); | 199 | extern void setup_vector_irq(int cpu); |
diff --git a/arch/x86/include/asm/intel-mid.h b/arch/x86/include/asm/intel-mid.h index 459769d39263..e34e097b6f9d 100644 --- a/arch/x86/include/asm/intel-mid.h +++ b/arch/x86/include/asm/intel-mid.h | |||
@@ -51,10 +51,41 @@ struct devs_id { | |||
51 | enum intel_mid_cpu_type { | 51 | enum intel_mid_cpu_type { |
52 | /* 1 was Moorestown */ | 52 | /* 1 was Moorestown */ |
53 | INTEL_MID_CPU_CHIP_PENWELL = 2, | 53 | INTEL_MID_CPU_CHIP_PENWELL = 2, |
54 | INTEL_MID_CPU_CHIP_CLOVERVIEW, | ||
55 | INTEL_MID_CPU_CHIP_TANGIER, | ||
54 | }; | 56 | }; |
55 | 57 | ||
56 | extern enum intel_mid_cpu_type __intel_mid_cpu_chip; | 58 | extern enum intel_mid_cpu_type __intel_mid_cpu_chip; |
57 | 59 | ||
60 | /** | ||
61 | * struct intel_mid_ops - Interface between intel-mid & sub archs | ||
62 | * @arch_setup: arch_setup function to re-initialize platform | ||
63 | * structures (x86_init, x86_platform_init) | ||
64 | * | ||
65 | * This structure can be extended if any new interface is required | ||
66 | * between intel-mid & its sub arch files. | ||
67 | */ | ||
68 | struct intel_mid_ops { | ||
69 | void (*arch_setup)(void); | ||
70 | }; | ||
71 | |||
72 | /* Helper API's for INTEL_MID_OPS_INIT */ | ||
73 | #define DECLARE_INTEL_MID_OPS_INIT(cpuname, cpuid) \ | ||
74 | [cpuid] = get_##cpuname##_ops | ||
75 | |||
76 | /* Maximum number of CPU ops */ | ||
77 | #define MAX_CPU_OPS(a) (sizeof(a)/sizeof(void *)) | ||
78 | |||
79 | /* | ||
80 | * For every new cpu addition, a weak get_<cpuname>_ops() function needs be | ||
81 | * declared in arch/x86/platform/intel_mid/intel_mid_weak_decls.h. | ||
82 | */ | ||
83 | #define INTEL_MID_OPS_INIT {\ | ||
84 | DECLARE_INTEL_MID_OPS_INIT(penwell, INTEL_MID_CPU_CHIP_PENWELL), \ | ||
85 | DECLARE_INTEL_MID_OPS_INIT(cloverview, INTEL_MID_CPU_CHIP_CLOVERVIEW), \ | ||
86 | DECLARE_INTEL_MID_OPS_INIT(tangier, INTEL_MID_CPU_CHIP_TANGIER) \ | ||
87 | }; | ||
88 | |||
58 | #ifdef CONFIG_X86_INTEL_MID | 89 | #ifdef CONFIG_X86_INTEL_MID |
59 | 90 | ||
60 | static inline enum intel_mid_cpu_type intel_mid_identify_cpu(void) | 91 | static inline enum intel_mid_cpu_type intel_mid_identify_cpu(void) |
@@ -86,8 +117,21 @@ extern enum intel_mid_timer_options intel_mid_timer_options; | |||
86 | * Penwell uses spread spectrum clock, so the freq number is not exactly | 117 | * Penwell uses spread spectrum clock, so the freq number is not exactly |
87 | * the same as reported by MSR based on SDM. | 118 | * the same as reported by MSR based on SDM. |
88 | */ | 119 | */ |
89 | #define PENWELL_FSB_FREQ_83SKU 83200 | 120 | #define FSB_FREQ_83SKU 83200 |
90 | #define PENWELL_FSB_FREQ_100SKU 99840 | 121 | #define FSB_FREQ_100SKU 99840 |
122 | #define FSB_FREQ_133SKU 133000 | ||
123 | |||
124 | #define FSB_FREQ_167SKU 167000 | ||
125 | #define FSB_FREQ_200SKU 200000 | ||
126 | #define FSB_FREQ_267SKU 267000 | ||
127 | #define FSB_FREQ_333SKU 333000 | ||
128 | #define FSB_FREQ_400SKU 400000 | ||
129 | |||
130 | /* Bus Select SoC Fuse value */ | ||
131 | #define BSEL_SOC_FUSE_MASK 0x7 | ||
132 | #define BSEL_SOC_FUSE_001 0x1 /* FSB 133MHz */ | ||
133 | #define BSEL_SOC_FUSE_101 0x5 /* FSB 100MHz */ | ||
134 | #define BSEL_SOC_FUSE_111 0x7 /* FSB 83MHz */ | ||
91 | 135 | ||
92 | #define SFI_MTMR_MAX_NUM 8 | 136 | #define SFI_MTMR_MAX_NUM 8 |
93 | #define SFI_MRTC_MAX 8 | 137 | #define SFI_MRTC_MAX 8 |
diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h new file mode 100644 index 000000000000..8e71c7941767 --- /dev/null +++ b/arch/x86/include/asm/iosf_mbi.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * iosf_mbi.h: Intel OnChip System Fabric MailBox access support | ||
3 | */ | ||
4 | |||
5 | #ifndef IOSF_MBI_SYMS_H | ||
6 | #define IOSF_MBI_SYMS_H | ||
7 | |||
8 | #define MBI_MCR_OFFSET 0xD0 | ||
9 | #define MBI_MDR_OFFSET 0xD4 | ||
10 | #define MBI_MCRX_OFFSET 0xD8 | ||
11 | |||
12 | #define MBI_RD_MASK 0xFEFFFFFF | ||
13 | #define MBI_WR_MASK 0X01000000 | ||
14 | |||
15 | #define MBI_MASK_HI 0xFFFFFF00 | ||
16 | #define MBI_MASK_LO 0x000000FF | ||
17 | #define MBI_ENABLE 0xF0 | ||
18 | |||
19 | /* Baytrail available units */ | ||
20 | #define BT_MBI_UNIT_AUNIT 0x00 | ||
21 | #define BT_MBI_UNIT_SMC 0x01 | ||
22 | #define BT_MBI_UNIT_CPU 0x02 | ||
23 | #define BT_MBI_UNIT_BUNIT 0x03 | ||
24 | #define BT_MBI_UNIT_PMC 0x04 | ||
25 | #define BT_MBI_UNIT_GFX 0x06 | ||
26 | #define BT_MBI_UNIT_SMI 0x0C | ||
27 | #define BT_MBI_UNIT_USB 0x43 | ||
28 | #define BT_MBI_UNIT_SATA 0xA3 | ||
29 | #define BT_MBI_UNIT_PCIE 0xA6 | ||
30 | |||
31 | /* Baytrail read/write opcodes */ | ||
32 | #define BT_MBI_AUNIT_READ 0x10 | ||
33 | #define BT_MBI_AUNIT_WRITE 0x11 | ||
34 | #define BT_MBI_SMC_READ 0x10 | ||
35 | #define BT_MBI_SMC_WRITE 0x11 | ||
36 | #define BT_MBI_CPU_READ 0x10 | ||
37 | #define BT_MBI_CPU_WRITE 0x11 | ||
38 | #define BT_MBI_BUNIT_READ 0x10 | ||
39 | #define BT_MBI_BUNIT_WRITE 0x11 | ||
40 | #define BT_MBI_PMC_READ 0x06 | ||
41 | #define BT_MBI_PMC_WRITE 0x07 | ||
42 | #define BT_MBI_GFX_READ 0x00 | ||
43 | #define BT_MBI_GFX_WRITE 0x01 | ||
44 | #define BT_MBI_SMIO_READ 0x06 | ||
45 | #define BT_MBI_SMIO_WRITE 0x07 | ||
46 | #define BT_MBI_USB_READ 0x06 | ||
47 | #define BT_MBI_USB_WRITE 0x07 | ||
48 | #define BT_MBI_SATA_READ 0x00 | ||
49 | #define BT_MBI_SATA_WRITE 0x01 | ||
50 | #define BT_MBI_PCIE_READ 0x00 | ||
51 | #define BT_MBI_PCIE_WRITE 0x01 | ||
52 | |||
53 | /** | ||
54 | * iosf_mbi_read() - MailBox Interface read command | ||
55 | * @port: port indicating subunit being accessed | ||
56 | * @opcode: port specific read or write opcode | ||
57 | * @offset: register address offset | ||
58 | * @mdr: register data to be read | ||
59 | * | ||
60 | * Locking is handled by spinlock - cannot sleep. | ||
61 | * Return: Nonzero on error | ||
62 | */ | ||
63 | int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr); | ||
64 | |||
65 | /** | ||
66 | * iosf_mbi_write() - MailBox unmasked write command | ||
67 | * @port: port indicating subunit being accessed | ||
68 | * @opcode: port specific read or write opcode | ||
69 | * @offset: register address offset | ||
70 | * @mdr: register data to be written | ||
71 | * | ||
72 | * Locking is handled by spinlock - cannot sleep. | ||
73 | * Return: Nonzero on error | ||
74 | */ | ||
75 | int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr); | ||
76 | |||
77 | /** | ||
78 | * iosf_mbi_modify() - MailBox masked write command | ||
79 | * @port: port indicating subunit being accessed | ||
80 | * @opcode: port specific read or write opcode | ||
81 | * @offset: register address offset | ||
82 | * @mdr: register data being modified | ||
83 | * @mask: mask indicating bits in mdr to be modified | ||
84 | * | ||
85 | * Locking is handled by spinlock - cannot sleep. | ||
86 | * Return: Nonzero on error | ||
87 | */ | ||
88 | int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask); | ||
89 | |||
90 | #endif /* IOSF_MBI_SYMS_H */ | ||
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index c696a8687567..6e4ce2df87cf 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
@@ -118,7 +118,6 @@ extern void mce_register_decode_chain(struct notifier_block *nb); | |||
118 | extern void mce_unregister_decode_chain(struct notifier_block *nb); | 118 | extern void mce_unregister_decode_chain(struct notifier_block *nb); |
119 | 119 | ||
120 | #include <linux/percpu.h> | 120 | #include <linux/percpu.h> |
121 | #include <linux/init.h> | ||
122 | #include <linux/atomic.h> | 121 | #include <linux/atomic.h> |
123 | 122 | ||
124 | extern int mce_p5_enabled; | 123 | extern int mce_p5_enabled; |
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index f98bd6625318..b59827e76529 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
@@ -1,6 +1,21 @@ | |||
1 | #ifndef _ASM_X86_MICROCODE_H | 1 | #ifndef _ASM_X86_MICROCODE_H |
2 | #define _ASM_X86_MICROCODE_H | 2 | #define _ASM_X86_MICROCODE_H |
3 | 3 | ||
4 | #define native_rdmsr(msr, val1, val2) \ | ||
5 | do { \ | ||
6 | u64 __val = native_read_msr((msr)); \ | ||
7 | (void)((val1) = (u32)__val); \ | ||
8 | (void)((val2) = (u32)(__val >> 32)); \ | ||
9 | } while (0) | ||
10 | |||
11 | #define native_wrmsr(msr, low, high) \ | ||
12 | native_write_msr(msr, low, high) | ||
13 | |||
14 | #define native_wrmsrl(msr, val) \ | ||
15 | native_write_msr((msr), \ | ||
16 | (u32)((u64)(val)), \ | ||
17 | (u32)((u64)(val) >> 32)) | ||
18 | |||
4 | struct cpu_signature { | 19 | struct cpu_signature { |
5 | unsigned int sig; | 20 | unsigned int sig; |
6 | unsigned int pf; | 21 | unsigned int pf; |
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h index 4c019179a57d..b7b10b82d3e5 100644 --- a/arch/x86/include/asm/microcode_amd.h +++ b/arch/x86/include/asm/microcode_amd.h | |||
@@ -61,11 +61,10 @@ extern int __apply_microcode_amd(struct microcode_amd *mc_amd); | |||
61 | extern int apply_microcode_amd(int cpu); | 61 | extern int apply_microcode_amd(int cpu); |
62 | extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); | 62 | extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); |
63 | 63 | ||
64 | #define PATCH_MAX_SIZE PAGE_SIZE | ||
65 | extern u8 amd_ucode_patch[PATCH_MAX_SIZE]; | ||
66 | |||
64 | #ifdef CONFIG_MICROCODE_AMD_EARLY | 67 | #ifdef CONFIG_MICROCODE_AMD_EARLY |
65 | #ifdef CONFIG_X86_32 | ||
66 | #define MPB_MAX_SIZE PAGE_SIZE | ||
67 | extern u8 amd_bsp_mpb[MPB_MAX_SIZE]; | ||
68 | #endif | ||
69 | extern void __init load_ucode_amd_bsp(void); | 68 | extern void __init load_ucode_amd_bsp(void); |
70 | extern void load_ucode_amd_ap(void); | 69 | extern void load_ucode_amd_ap(void); |
71 | extern int __init save_microcode_in_initrd_amd(void); | 70 | extern int __init save_microcode_in_initrd_amd(void); |
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 3142a94c7b4b..3e6b4920ef5d 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h | |||
@@ -1,7 +1,6 @@ | |||
1 | #ifndef _ASM_X86_MPSPEC_H | 1 | #ifndef _ASM_X86_MPSPEC_H |
2 | #define _ASM_X86_MPSPEC_H | 2 | #define _ASM_X86_MPSPEC_H |
3 | 3 | ||
4 | #include <linux/init.h> | ||
5 | 4 | ||
6 | #include <asm/mpspec_def.h> | 5 | #include <asm/mpspec_def.h> |
7 | #include <asm/x86_init.h> | 6 | #include <asm/x86_init.h> |
diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h index 2f366d0ac6b4..1da25a5f96f9 100644 --- a/arch/x86/include/asm/mwait.h +++ b/arch/x86/include/asm/mwait.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef _ASM_X86_MWAIT_H | 1 | #ifndef _ASM_X86_MWAIT_H |
2 | #define _ASM_X86_MWAIT_H | 2 | #define _ASM_X86_MWAIT_H |
3 | 3 | ||
4 | #include <linux/sched.h> | ||
5 | |||
4 | #define MWAIT_SUBSTATE_MASK 0xf | 6 | #define MWAIT_SUBSTATE_MASK 0xf |
5 | #define MWAIT_CSTATE_MASK 0xf | 7 | #define MWAIT_CSTATE_MASK 0xf |
6 | #define MWAIT_SUBSTATE_SIZE 4 | 8 | #define MWAIT_SUBSTATE_SIZE 4 |
@@ -13,4 +15,45 @@ | |||
13 | 15 | ||
14 | #define MWAIT_ECX_INTERRUPT_BREAK 0x1 | 16 | #define MWAIT_ECX_INTERRUPT_BREAK 0x1 |
15 | 17 | ||
18 | static inline void __monitor(const void *eax, unsigned long ecx, | ||
19 | unsigned long edx) | ||
20 | { | ||
21 | /* "monitor %eax, %ecx, %edx;" */ | ||
22 | asm volatile(".byte 0x0f, 0x01, 0xc8;" | ||
23 | :: "a" (eax), "c" (ecx), "d"(edx)); | ||
24 | } | ||
25 | |||
26 | static inline void __mwait(unsigned long eax, unsigned long ecx) | ||
27 | { | ||
28 | /* "mwait %eax, %ecx;" */ | ||
29 | asm volatile(".byte 0x0f, 0x01, 0xc9;" | ||
30 | :: "a" (eax), "c" (ecx)); | ||
31 | } | ||
32 | |||
33 | /* | ||
34 | * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, | ||
35 | * which can obviate IPI to trigger checking of need_resched. | ||
36 | * We execute MONITOR against need_resched and enter optimized wait state | ||
37 | * through MWAIT. Whenever someone changes need_resched, we would be woken | ||
38 | * up from MWAIT (without an IPI). | ||
39 | * | ||
40 | * New with Core Duo processors, MWAIT can take some hints based on CPU | ||
41 | * capability. | ||
42 | */ | ||
43 | static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) | ||
44 | { | ||
45 | if (!current_set_polling_and_test()) { | ||
46 | if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) { | ||
47 | mb(); | ||
48 | clflush((void *)¤t_thread_info()->flags); | ||
49 | mb(); | ||
50 | } | ||
51 | |||
52 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
53 | if (!need_resched()) | ||
54 | __mwait(eax, ecx); | ||
55 | } | ||
56 | current_clr_polling(); | ||
57 | } | ||
58 | |||
16 | #endif /* _ASM_X86_MWAIT_H */ | 59 | #endif /* _ASM_X86_MWAIT_H */ |
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index c87892442e53..775873d3be55 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h | |||
@@ -71,6 +71,7 @@ extern bool __virt_addr_valid(unsigned long kaddr); | |||
71 | #include <asm-generic/getorder.h> | 71 | #include <asm-generic/getorder.h> |
72 | 72 | ||
73 | #define __HAVE_ARCH_GATE_AREA 1 | 73 | #define __HAVE_ARCH_GATE_AREA 1 |
74 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA | ||
74 | 75 | ||
75 | #endif /* __KERNEL__ */ | 76 | #endif /* __KERNEL__ */ |
76 | #endif /* _ASM_X86_PAGE_H */ | 77 | #endif /* _ASM_X86_PAGE_H */ |
diff --git a/arch/x86/include/asm/page_32.h b/arch/x86/include/asm/page_32.h index 4d550d04b609..904f528cc8e8 100644 --- a/arch/x86/include/asm/page_32.h +++ b/arch/x86/include/asm/page_32.h | |||
@@ -5,10 +5,6 @@ | |||
5 | 5 | ||
6 | #ifndef __ASSEMBLY__ | 6 | #ifndef __ASSEMBLY__ |
7 | 7 | ||
8 | #ifdef CONFIG_HUGETLB_PAGE | ||
9 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA | ||
10 | #endif | ||
11 | |||
12 | #define __phys_addr_nodebug(x) ((x) - PAGE_OFFSET) | 8 | #define __phys_addr_nodebug(x) ((x) - PAGE_OFFSET) |
13 | #ifdef CONFIG_DEBUG_VIRTUAL | 9 | #ifdef CONFIG_DEBUG_VIRTUAL |
14 | extern unsigned long __phys_addr(unsigned long); | 10 | extern unsigned long __phys_addr(unsigned long); |
diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h index 43dcd804ebd5..8de6d9cf3b95 100644 --- a/arch/x86/include/asm/page_64_types.h +++ b/arch/x86/include/asm/page_64_types.h | |||
@@ -39,9 +39,18 @@ | |||
39 | #define __VIRTUAL_MASK_SHIFT 47 | 39 | #define __VIRTUAL_MASK_SHIFT 47 |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Kernel image size is limited to 512 MB (see level2_kernel_pgt in | 42 | * Kernel image size is limited to 1GiB due to the fixmap living in the |
43 | * arch/x86/kernel/head_64.S), and it is mapped here: | 43 | * next 1GiB (see level2_kernel_pgt in arch/x86/kernel/head_64.S). Use |
44 | * 512MiB by default, leaving 1.5GiB for modules once the page tables | ||
45 | * are fully set up. If kernel ASLR is configured, it can extend the | ||
46 | * kernel page table mapping, reducing the size of the modules area. | ||
44 | */ | 47 | */ |
45 | #define KERNEL_IMAGE_SIZE (512 * 1024 * 1024) | 48 | #define KERNEL_IMAGE_SIZE_DEFAULT (512 * 1024 * 1024) |
49 | #if defined(CONFIG_RANDOMIZE_BASE) && \ | ||
50 | CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE_DEFAULT | ||
51 | #define KERNEL_IMAGE_SIZE CONFIG_RANDOMIZE_BASE_MAX_OFFSET | ||
52 | #else | ||
53 | #define KERNEL_IMAGE_SIZE KERNEL_IMAGE_SIZE_DEFAULT | ||
54 | #endif | ||
46 | 55 | ||
47 | #endif /* _ASM_X86_PAGE_64_DEFS_H */ | 56 | #endif /* _ASM_X86_PAGE_64_DEFS_H */ |
diff --git a/arch/x86/include/asm/pgtable-2level.h b/arch/x86/include/asm/pgtable-2level.h index 3bf2dd0cf61f..0d193e234647 100644 --- a/arch/x86/include/asm/pgtable-2level.h +++ b/arch/x86/include/asm/pgtable-2level.h | |||
@@ -55,6 +55,13 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) | |||
55 | #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp) | 55 | #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp) |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | /* Bit manipulation helper on pte/pgoff entry */ | ||
59 | static inline unsigned long pte_bitop(unsigned long value, unsigned int rightshift, | ||
60 | unsigned long mask, unsigned int leftshift) | ||
61 | { | ||
62 | return ((value >> rightshift) & mask) << leftshift; | ||
63 | } | ||
64 | |||
58 | #ifdef CONFIG_MEM_SOFT_DIRTY | 65 | #ifdef CONFIG_MEM_SOFT_DIRTY |
59 | 66 | ||
60 | /* | 67 | /* |
@@ -71,31 +78,34 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) | |||
71 | #define PTE_FILE_BITS2 (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1) | 78 | #define PTE_FILE_BITS2 (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1) |
72 | #define PTE_FILE_BITS3 (PTE_FILE_SHIFT4 - PTE_FILE_SHIFT3 - 1) | 79 | #define PTE_FILE_BITS3 (PTE_FILE_SHIFT4 - PTE_FILE_SHIFT3 - 1) |
73 | 80 | ||
74 | #define pte_to_pgoff(pte) \ | 81 | #define PTE_FILE_MASK1 ((1U << PTE_FILE_BITS1) - 1) |
75 | ((((pte).pte_low >> (PTE_FILE_SHIFT1)) \ | 82 | #define PTE_FILE_MASK2 ((1U << PTE_FILE_BITS2) - 1) |
76 | & ((1U << PTE_FILE_BITS1) - 1))) \ | 83 | #define PTE_FILE_MASK3 ((1U << PTE_FILE_BITS3) - 1) |
77 | + ((((pte).pte_low >> (PTE_FILE_SHIFT2)) \ | 84 | |
78 | & ((1U << PTE_FILE_BITS2) - 1)) \ | 85 | #define PTE_FILE_LSHIFT2 (PTE_FILE_BITS1) |
79 | << (PTE_FILE_BITS1)) \ | 86 | #define PTE_FILE_LSHIFT3 (PTE_FILE_BITS1 + PTE_FILE_BITS2) |
80 | + ((((pte).pte_low >> (PTE_FILE_SHIFT3)) \ | 87 | #define PTE_FILE_LSHIFT4 (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3) |
81 | & ((1U << PTE_FILE_BITS3) - 1)) \ | 88 | |
82 | << (PTE_FILE_BITS1 + PTE_FILE_BITS2)) \ | 89 | static __always_inline pgoff_t pte_to_pgoff(pte_t pte) |
83 | + ((((pte).pte_low >> (PTE_FILE_SHIFT4))) \ | 90 | { |
84 | << (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3)) | 91 | return (pgoff_t) |
85 | 92 | (pte_bitop(pte.pte_low, PTE_FILE_SHIFT1, PTE_FILE_MASK1, 0) + | |
86 | #define pgoff_to_pte(off) \ | 93 | pte_bitop(pte.pte_low, PTE_FILE_SHIFT2, PTE_FILE_MASK2, PTE_FILE_LSHIFT2) + |
87 | ((pte_t) { .pte_low = \ | 94 | pte_bitop(pte.pte_low, PTE_FILE_SHIFT3, PTE_FILE_MASK3, PTE_FILE_LSHIFT3) + |
88 | ((((off)) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1) \ | 95 | pte_bitop(pte.pte_low, PTE_FILE_SHIFT4, -1UL, PTE_FILE_LSHIFT4)); |
89 | + ((((off) >> PTE_FILE_BITS1) \ | 96 | } |
90 | & ((1U << PTE_FILE_BITS2) - 1)) \ | 97 | |
91 | << PTE_FILE_SHIFT2) \ | 98 | static __always_inline pte_t pgoff_to_pte(pgoff_t off) |
92 | + ((((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2)) \ | 99 | { |
93 | & ((1U << PTE_FILE_BITS3) - 1)) \ | 100 | return (pte_t){ |
94 | << PTE_FILE_SHIFT3) \ | 101 | .pte_low = |
95 | + ((((off) >> \ | 102 | pte_bitop(off, 0, PTE_FILE_MASK1, PTE_FILE_SHIFT1) + |
96 | (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3))) \ | 103 | pte_bitop(off, PTE_FILE_LSHIFT2, PTE_FILE_MASK2, PTE_FILE_SHIFT2) + |
97 | << PTE_FILE_SHIFT4) \ | 104 | pte_bitop(off, PTE_FILE_LSHIFT3, PTE_FILE_MASK3, PTE_FILE_SHIFT3) + |
98 | + _PAGE_FILE }) | 105 | pte_bitop(off, PTE_FILE_LSHIFT4, -1UL, PTE_FILE_SHIFT4) + |
106 | _PAGE_FILE, | ||
107 | }; | ||
108 | } | ||
99 | 109 | ||
100 | #else /* CONFIG_MEM_SOFT_DIRTY */ | 110 | #else /* CONFIG_MEM_SOFT_DIRTY */ |
101 | 111 | ||
@@ -115,22 +125,30 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) | |||
115 | #define PTE_FILE_BITS1 (PTE_FILE_SHIFT2 - PTE_FILE_SHIFT1 - 1) | 125 | #define PTE_FILE_BITS1 (PTE_FILE_SHIFT2 - PTE_FILE_SHIFT1 - 1) |
116 | #define PTE_FILE_BITS2 (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1) | 126 | #define PTE_FILE_BITS2 (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1) |
117 | 127 | ||
118 | #define pte_to_pgoff(pte) \ | 128 | #define PTE_FILE_MASK1 ((1U << PTE_FILE_BITS1) - 1) |
119 | ((((pte).pte_low >> PTE_FILE_SHIFT1) \ | 129 | #define PTE_FILE_MASK2 ((1U << PTE_FILE_BITS2) - 1) |
120 | & ((1U << PTE_FILE_BITS1) - 1)) \ | 130 | |
121 | + ((((pte).pte_low >> PTE_FILE_SHIFT2) \ | 131 | #define PTE_FILE_LSHIFT2 (PTE_FILE_BITS1) |
122 | & ((1U << PTE_FILE_BITS2) - 1)) << PTE_FILE_BITS1) \ | 132 | #define PTE_FILE_LSHIFT3 (PTE_FILE_BITS1 + PTE_FILE_BITS2) |
123 | + (((pte).pte_low >> PTE_FILE_SHIFT3) \ | 133 | |
124 | << (PTE_FILE_BITS1 + PTE_FILE_BITS2))) | 134 | static __always_inline pgoff_t pte_to_pgoff(pte_t pte) |
125 | 135 | { | |
126 | #define pgoff_to_pte(off) \ | 136 | return (pgoff_t) |
127 | ((pte_t) { .pte_low = \ | 137 | (pte_bitop(pte.pte_low, PTE_FILE_SHIFT1, PTE_FILE_MASK1, 0) + |
128 | (((off) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1) \ | 138 | pte_bitop(pte.pte_low, PTE_FILE_SHIFT2, PTE_FILE_MASK2, PTE_FILE_LSHIFT2) + |
129 | + ((((off) >> PTE_FILE_BITS1) & ((1U << PTE_FILE_BITS2) - 1)) \ | 139 | pte_bitop(pte.pte_low, PTE_FILE_SHIFT3, -1UL, PTE_FILE_LSHIFT3)); |
130 | << PTE_FILE_SHIFT2) \ | 140 | } |
131 | + (((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2)) \ | 141 | |
132 | << PTE_FILE_SHIFT3) \ | 142 | static __always_inline pte_t pgoff_to_pte(pgoff_t off) |
133 | + _PAGE_FILE }) | 143 | { |
144 | return (pte_t){ | ||
145 | .pte_low = | ||
146 | pte_bitop(off, 0, PTE_FILE_MASK1, PTE_FILE_SHIFT1) + | ||
147 | pte_bitop(off, PTE_FILE_LSHIFT2, PTE_FILE_MASK2, PTE_FILE_SHIFT2) + | ||
148 | pte_bitop(off, PTE_FILE_LSHIFT3, -1UL, PTE_FILE_SHIFT3) + | ||
149 | _PAGE_FILE, | ||
150 | }; | ||
151 | } | ||
134 | 152 | ||
135 | #endif /* CONFIG_MEM_SOFT_DIRTY */ | 153 | #endif /* CONFIG_MEM_SOFT_DIRTY */ |
136 | 154 | ||
diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h index 2d883440cb9a..c883bf726398 100644 --- a/arch/x86/include/asm/pgtable_64_types.h +++ b/arch/x86/include/asm/pgtable_64_types.h | |||
@@ -58,7 +58,7 @@ typedef struct { pteval_t pte; } pte_t; | |||
58 | #define VMALLOC_START _AC(0xffffc90000000000, UL) | 58 | #define VMALLOC_START _AC(0xffffc90000000000, UL) |
59 | #define VMALLOC_END _AC(0xffffe8ffffffffff, UL) | 59 | #define VMALLOC_END _AC(0xffffe8ffffffffff, UL) |
60 | #define VMEMMAP_START _AC(0xffffea0000000000, UL) | 60 | #define VMEMMAP_START _AC(0xffffea0000000000, UL) |
61 | #define MODULES_VADDR _AC(0xffffffffa0000000, UL) | 61 | #define MODULES_VADDR (__START_KERNEL_map + KERNEL_IMAGE_SIZE) |
62 | #define MODULES_END _AC(0xffffffffff000000, UL) | 62 | #define MODULES_END _AC(0xffffffffff000000, UL) |
63 | #define MODULES_LEN (MODULES_END - MODULES_VADDR) | 63 | #define MODULES_LEN (MODULES_END - MODULES_VADDR) |
64 | 64 | ||
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 0ecac257fb26..a83aa44bb1fb 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h | |||
@@ -382,7 +382,8 @@ static inline void update_page_count(int level, unsigned long pages) { } | |||
382 | */ | 382 | */ |
383 | extern pte_t *lookup_address(unsigned long address, unsigned int *level); | 383 | extern pte_t *lookup_address(unsigned long address, unsigned int *level); |
384 | extern phys_addr_t slow_virt_to_phys(void *__address); | 384 | extern phys_addr_t slow_virt_to_phys(void *__address); |
385 | 385 | extern int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address, | |
386 | unsigned numpages, unsigned long page_flags); | ||
386 | #endif /* !__ASSEMBLY__ */ | 387 | #endif /* !__ASSEMBLY__ */ |
387 | 388 | ||
388 | #endif /* _ASM_X86_PGTABLE_DEFS_H */ | 389 | #endif /* _ASM_X86_PGTABLE_DEFS_H */ |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 7b034a4057f9..fdedd38fd0fc 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -27,7 +27,6 @@ struct mm_struct; | |||
27 | #include <linux/cache.h> | 27 | #include <linux/cache.h> |
28 | #include <linux/threads.h> | 28 | #include <linux/threads.h> |
29 | #include <linux/math64.h> | 29 | #include <linux/math64.h> |
30 | #include <linux/init.h> | ||
31 | #include <linux/err.h> | 30 | #include <linux/err.h> |
32 | #include <linux/irqflags.h> | 31 | #include <linux/irqflags.h> |
33 | 32 | ||
@@ -72,6 +71,7 @@ extern u16 __read_mostly tlb_lli_4m[NR_INFO]; | |||
72 | extern u16 __read_mostly tlb_lld_4k[NR_INFO]; | 71 | extern u16 __read_mostly tlb_lld_4k[NR_INFO]; |
73 | extern u16 __read_mostly tlb_lld_2m[NR_INFO]; | 72 | extern u16 __read_mostly tlb_lld_2m[NR_INFO]; |
74 | extern u16 __read_mostly tlb_lld_4m[NR_INFO]; | 73 | extern u16 __read_mostly tlb_lld_4m[NR_INFO]; |
74 | extern u16 __read_mostly tlb_lld_1g[NR_INFO]; | ||
75 | extern s8 __read_mostly tlb_flushall_shift; | 75 | extern s8 __read_mostly tlb_flushall_shift; |
76 | 76 | ||
77 | /* | 77 | /* |
@@ -370,6 +370,20 @@ struct ymmh_struct { | |||
370 | u32 ymmh_space[64]; | 370 | u32 ymmh_space[64]; |
371 | }; | 371 | }; |
372 | 372 | ||
373 | /* We don't support LWP yet: */ | ||
374 | struct lwp_struct { | ||
375 | u8 reserved[128]; | ||
376 | }; | ||
377 | |||
378 | struct bndregs_struct { | ||
379 | u64 bndregs[8]; | ||
380 | } __packed; | ||
381 | |||
382 | struct bndcsr_struct { | ||
383 | u64 cfg_reg_u; | ||
384 | u64 status_reg; | ||
385 | } __packed; | ||
386 | |||
373 | struct xsave_hdr_struct { | 387 | struct xsave_hdr_struct { |
374 | u64 xstate_bv; | 388 | u64 xstate_bv; |
375 | u64 reserved1[2]; | 389 | u64 reserved1[2]; |
@@ -380,6 +394,9 @@ struct xsave_struct { | |||
380 | struct i387_fxsave_struct i387; | 394 | struct i387_fxsave_struct i387; |
381 | struct xsave_hdr_struct xsave_hdr; | 395 | struct xsave_hdr_struct xsave_hdr; |
382 | struct ymmh_struct ymmh; | 396 | struct ymmh_struct ymmh; |
397 | struct lwp_struct lwp; | ||
398 | struct bndregs_struct bndregs; | ||
399 | struct bndcsr_struct bndcsr; | ||
383 | /* new processor state extensions will go here */ | 400 | /* new processor state extensions will go here */ |
384 | } __attribute__ ((packed, aligned (64))); | 401 | } __attribute__ ((packed, aligned (64))); |
385 | 402 | ||
@@ -700,29 +717,6 @@ static inline void sync_core(void) | |||
700 | #endif | 717 | #endif |
701 | } | 718 | } |
702 | 719 | ||
703 | static inline void __monitor(const void *eax, unsigned long ecx, | ||
704 | unsigned long edx) | ||
705 | { | ||
706 | /* "monitor %eax, %ecx, %edx;" */ | ||
707 | asm volatile(".byte 0x0f, 0x01, 0xc8;" | ||
708 | :: "a" (eax), "c" (ecx), "d"(edx)); | ||
709 | } | ||
710 | |||
711 | static inline void __mwait(unsigned long eax, unsigned long ecx) | ||
712 | { | ||
713 | /* "mwait %eax, %ecx;" */ | ||
714 | asm volatile(".byte 0x0f, 0x01, 0xc9;" | ||
715 | :: "a" (eax), "c" (ecx)); | ||
716 | } | ||
717 | |||
718 | static inline void __sti_mwait(unsigned long eax, unsigned long ecx) | ||
719 | { | ||
720 | trace_hardirqs_on(); | ||
721 | /* "mwait %eax, %ecx;" */ | ||
722 | asm volatile("sti; .byte 0x0f, 0x01, 0xc9;" | ||
723 | :: "a" (eax), "c" (ecx)); | ||
724 | } | ||
725 | |||
726 | extern void select_idle_routine(const struct cpuinfo_x86 *c); | 720 | extern void select_idle_routine(const struct cpuinfo_x86 *c); |
727 | extern void init_amd_e400_c1e_mask(void); | 721 | extern void init_amd_e400_c1e_mask(void); |
728 | 722 | ||
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 942a08623a1a..14fd6fd75a19 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h | |||
@@ -60,7 +60,6 @@ struct pt_regs { | |||
60 | 60 | ||
61 | #endif /* !__i386__ */ | 61 | #endif /* !__i386__ */ |
62 | 62 | ||
63 | #include <linux/init.h> | ||
64 | #ifdef CONFIG_PARAVIRT | 63 | #ifdef CONFIG_PARAVIRT |
65 | #include <asm/paravirt_types.h> | 64 | #include <asm/paravirt_types.h> |
66 | #endif | 65 | #endif |
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 59bcf4e22418..d62c9f809bc5 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h | |||
@@ -3,7 +3,6 @@ | |||
3 | 3 | ||
4 | #include <uapi/asm/setup.h> | 4 | #include <uapi/asm/setup.h> |
5 | 5 | ||
6 | |||
7 | #define COMMAND_LINE_SIZE 2048 | 6 | #define COMMAND_LINE_SIZE 2048 |
8 | 7 | ||
9 | #include <linux/linkage.h> | 8 | #include <linux/linkage.h> |
@@ -29,6 +28,8 @@ | |||
29 | #include <asm/bootparam.h> | 28 | #include <asm/bootparam.h> |
30 | #include <asm/x86_init.h> | 29 | #include <asm/x86_init.h> |
31 | 30 | ||
31 | extern u64 relocated_ramdisk; | ||
32 | |||
32 | /* Interrupt control for vSMPowered x86_64 systems */ | 33 | /* Interrupt control for vSMPowered x86_64 systems */ |
33 | #ifdef CONFIG_X86_64 | 34 | #ifdef CONFIG_X86_64 |
34 | void vsmp_init(void); | 35 | void vsmp_init(void); |
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 4137890e88e3..8cd27e08e23c 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #define _ASM_X86_SMP_H | 2 | #define _ASM_X86_SMP_H |
3 | #ifndef __ASSEMBLY__ | 3 | #ifndef __ASSEMBLY__ |
4 | #include <linux/cpumask.h> | 4 | #include <linux/cpumask.h> |
5 | #include <linux/init.h> | ||
6 | #include <asm/percpu.h> | 5 | #include <asm/percpu.h> |
7 | 6 | ||
8 | /* | 7 | /* |
diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h index 34baa0eb5d0c..a04eabd43d06 100644 --- a/arch/x86/include/asm/timer.h +++ b/arch/x86/include/asm/timer.h | |||
@@ -1,9 +1,9 @@ | |||
1 | #ifndef _ASM_X86_TIMER_H | 1 | #ifndef _ASM_X86_TIMER_H |
2 | #define _ASM_X86_TIMER_H | 2 | #define _ASM_X86_TIMER_H |
3 | #include <linux/init.h> | ||
4 | #include <linux/pm.h> | 3 | #include <linux/pm.h> |
5 | #include <linux/percpu.h> | 4 | #include <linux/percpu.h> |
6 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/math64.h> | ||
7 | 7 | ||
8 | #define TICK_SIZE (tick_nsec / 1000) | 8 | #define TICK_SIZE (tick_nsec / 1000) |
9 | 9 | ||
@@ -12,68 +12,26 @@ extern int recalibrate_cpu_khz(void); | |||
12 | 12 | ||
13 | extern int no_timer_check; | 13 | extern int no_timer_check; |
14 | 14 | ||
15 | /* Accelerators for sched_clock() | 15 | /* |
16 | * convert from cycles(64bits) => nanoseconds (64bits) | 16 | * We use the full linear equation: f(x) = a + b*x, in order to allow |
17 | * basic equation: | 17 | * a continuous function in the face of dynamic freq changes. |
18 | * ns = cycles / (freq / ns_per_sec) | ||
19 | * ns = cycles * (ns_per_sec / freq) | ||
20 | * ns = cycles * (10^9 / (cpu_khz * 10^3)) | ||
21 | * ns = cycles * (10^6 / cpu_khz) | ||
22 | * | 18 | * |
23 | * Then we use scaling math (suggested by george@mvista.com) to get: | 19 | * Continuity means that when our frequency changes our slope (b); we want to |
24 | * ns = cycles * (10^6 * SC / cpu_khz) / SC | 20 | * ensure that: f(t) == f'(t), which gives: a + b*t == a' + b'*t. |
25 | * ns = cycles * cyc2ns_scale / SC | ||
26 | * | 21 | * |
27 | * And since SC is a constant power of two, we can convert the div | 22 | * Without an offset (a) the above would not be possible. |
28 | * into a shift. | ||
29 | * | 23 | * |
30 | * We can use khz divisor instead of mhz to keep a better precision, since | 24 | * See the comment near cycles_2_ns() for details on how we compute (b). |
31 | * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. | ||
32 | * (mathieu.desnoyers@polymtl.ca) | ||
33 | * | ||
34 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" | ||
35 | * | ||
36 | * In: | ||
37 | * | ||
38 | * ns = cycles * cyc2ns_scale / SC | ||
39 | * | ||
40 | * Although we may still have enough bits to store the value of ns, | ||
41 | * in some cases, we may not have enough bits to store cycles * cyc2ns_scale, | ||
42 | * leading to an incorrect result. | ||
43 | * | ||
44 | * To avoid this, we can decompose 'cycles' into quotient and remainder | ||
45 | * of division by SC. Then, | ||
46 | * | ||
47 | * ns = (quot * SC + rem) * cyc2ns_scale / SC | ||
48 | * = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC | ||
49 | * | ||
50 | * - sqazi@google.com | ||
51 | */ | 25 | */ |
52 | 26 | struct cyc2ns_data { | |
53 | DECLARE_PER_CPU(unsigned long, cyc2ns); | 27 | u32 cyc2ns_mul; |
54 | DECLARE_PER_CPU(unsigned long long, cyc2ns_offset); | 28 | u32 cyc2ns_shift; |
55 | 29 | u64 cyc2ns_offset; | |
56 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ | 30 | u32 __count; |
57 | 31 | /* u32 hole */ | |
58 | static inline unsigned long long __cycles_2_ns(unsigned long long cyc) | 32 | }; /* 24 bytes -- do not grow */ |
59 | { | 33 | |
60 | int cpu = smp_processor_id(); | 34 | extern struct cyc2ns_data *cyc2ns_read_begin(void); |
61 | unsigned long long ns = per_cpu(cyc2ns_offset, cpu); | 35 | extern void cyc2ns_read_end(struct cyc2ns_data *); |
62 | ns += mult_frac(cyc, per_cpu(cyc2ns, cpu), | ||
63 | (1UL << CYC2NS_SCALE_FACTOR)); | ||
64 | return ns; | ||
65 | } | ||
66 | |||
67 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) | ||
68 | { | ||
69 | unsigned long long ns; | ||
70 | unsigned long flags; | ||
71 | |||
72 | local_irq_save(flags); | ||
73 | ns = __cycles_2_ns(cyc); | ||
74 | local_irq_restore(flags); | ||
75 | |||
76 | return ns; | ||
77 | } | ||
78 | 36 | ||
79 | #endif /* _ASM_X86_TIMER_H */ | 37 | #endif /* _ASM_X86_TIMER_H */ |
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index 235be70d5bb4..57ae63cd6ee2 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h | |||
@@ -65,4 +65,7 @@ extern int notsc_setup(char *); | |||
65 | extern void tsc_save_sched_clock_state(void); | 65 | extern void tsc_save_sched_clock_state(void); |
66 | extern void tsc_restore_sched_clock_state(void); | 66 | extern void tsc_restore_sched_clock_state(void); |
67 | 67 | ||
68 | /* MSR based TSC calibration for Intel Atom SoC platforms */ | ||
69 | int try_msr_calibrate_tsc(unsigned long *fast_calibrate); | ||
70 | |||
68 | #endif /* _ASM_X86_TSC_H */ | 71 | #endif /* _ASM_X86_TSC_H */ |
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 8ec57c07b125..0d592e0a5b84 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h | |||
@@ -40,22 +40,30 @@ | |||
40 | /* | 40 | /* |
41 | * Test whether a block of memory is a valid user space address. | 41 | * Test whether a block of memory is a valid user space address. |
42 | * Returns 0 if the range is valid, nonzero otherwise. | 42 | * Returns 0 if the range is valid, nonzero otherwise. |
43 | * | ||
44 | * This is equivalent to the following test: | ||
45 | * (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64) | ||
46 | * | ||
47 | * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... | ||
48 | */ | 43 | */ |
44 | static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, unsigned long limit) | ||
45 | { | ||
46 | /* | ||
47 | * If we have used "sizeof()" for the size, | ||
48 | * we know it won't overflow the limit (but | ||
49 | * it might overflow the 'addr', so it's | ||
50 | * important to subtract the size from the | ||
51 | * limit, not add it to the address). | ||
52 | */ | ||
53 | if (__builtin_constant_p(size)) | ||
54 | return addr > limit - size; | ||
55 | |||
56 | /* Arbitrary sizes? Be careful about overflow */ | ||
57 | addr += size; | ||
58 | if (addr < size) | ||
59 | return true; | ||
60 | return addr > limit; | ||
61 | } | ||
49 | 62 | ||
50 | #define __range_not_ok(addr, size, limit) \ | 63 | #define __range_not_ok(addr, size, limit) \ |
51 | ({ \ | 64 | ({ \ |
52 | unsigned long flag, roksum; \ | ||
53 | __chk_user_ptr(addr); \ | 65 | __chk_user_ptr(addr); \ |
54 | asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \ | 66 | __chk_range_not_ok((unsigned long __force)(addr), size, limit); \ |
55 | : "=&r" (flag), "=r" (roksum) \ | ||
56 | : "1" (addr), "g" ((long)(size)), \ | ||
57 | "rm" (limit)); \ | ||
58 | flag; \ | ||
59 | }) | 67 | }) |
60 | 68 | ||
61 | /** | 69 | /** |
@@ -78,7 +86,7 @@ | |||
78 | * this function, memory access functions may still return -EFAULT. | 86 | * this function, memory access functions may still return -EFAULT. |
79 | */ | 87 | */ |
80 | #define access_ok(type, addr, size) \ | 88 | #define access_ok(type, addr, size) \ |
81 | (likely(__range_not_ok(addr, size, user_addr_max()) == 0)) | 89 | likely(!__range_not_ok(addr, size, user_addr_max())) |
82 | 90 | ||
83 | /* | 91 | /* |
84 | * The exception table consists of pairs of addresses relative to the | 92 | * The exception table consists of pairs of addresses relative to the |
@@ -525,6 +533,98 @@ extern __must_check long strnlen_user(const char __user *str, long n); | |||
525 | unsigned long __must_check clear_user(void __user *mem, unsigned long len); | 533 | unsigned long __must_check clear_user(void __user *mem, unsigned long len); |
526 | unsigned long __must_check __clear_user(void __user *mem, unsigned long len); | 534 | unsigned long __must_check __clear_user(void __user *mem, unsigned long len); |
527 | 535 | ||
536 | extern void __cmpxchg_wrong_size(void) | ||
537 | __compiletime_error("Bad argument size for cmpxchg"); | ||
538 | |||
539 | #define __user_atomic_cmpxchg_inatomic(uval, ptr, old, new, size) \ | ||
540 | ({ \ | ||
541 | int __ret = 0; \ | ||
542 | __typeof__(ptr) __uval = (uval); \ | ||
543 | __typeof__(*(ptr)) __old = (old); \ | ||
544 | __typeof__(*(ptr)) __new = (new); \ | ||
545 | switch (size) { \ | ||
546 | case 1: \ | ||
547 | { \ | ||
548 | asm volatile("\t" ASM_STAC "\n" \ | ||
549 | "1:\t" LOCK_PREFIX "cmpxchgb %4, %2\n" \ | ||
550 | "2:\t" ASM_CLAC "\n" \ | ||
551 | "\t.section .fixup, \"ax\"\n" \ | ||
552 | "3:\tmov %3, %0\n" \ | ||
553 | "\tjmp 2b\n" \ | ||
554 | "\t.previous\n" \ | ||
555 | _ASM_EXTABLE(1b, 3b) \ | ||
556 | : "+r" (__ret), "=a" (__old), "+m" (*(ptr)) \ | ||
557 | : "i" (-EFAULT), "q" (__new), "1" (__old) \ | ||
558 | : "memory" \ | ||
559 | ); \ | ||
560 | break; \ | ||
561 | } \ | ||
562 | case 2: \ | ||
563 | { \ | ||
564 | asm volatile("\t" ASM_STAC "\n" \ | ||
565 | "1:\t" LOCK_PREFIX "cmpxchgw %4, %2\n" \ | ||
566 | "2:\t" ASM_CLAC "\n" \ | ||
567 | "\t.section .fixup, \"ax\"\n" \ | ||
568 | "3:\tmov %3, %0\n" \ | ||
569 | "\tjmp 2b\n" \ | ||
570 | "\t.previous\n" \ | ||
571 | _ASM_EXTABLE(1b, 3b) \ | ||
572 | : "+r" (__ret), "=a" (__old), "+m" (*(ptr)) \ | ||
573 | : "i" (-EFAULT), "r" (__new), "1" (__old) \ | ||
574 | : "memory" \ | ||
575 | ); \ | ||
576 | break; \ | ||
577 | } \ | ||
578 | case 4: \ | ||
579 | { \ | ||
580 | asm volatile("\t" ASM_STAC "\n" \ | ||
581 | "1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n" \ | ||
582 | "2:\t" ASM_CLAC "\n" \ | ||
583 | "\t.section .fixup, \"ax\"\n" \ | ||
584 | "3:\tmov %3, %0\n" \ | ||
585 | "\tjmp 2b\n" \ | ||
586 | "\t.previous\n" \ | ||
587 | _ASM_EXTABLE(1b, 3b) \ | ||
588 | : "+r" (__ret), "=a" (__old), "+m" (*(ptr)) \ | ||
589 | : "i" (-EFAULT), "r" (__new), "1" (__old) \ | ||
590 | : "memory" \ | ||
591 | ); \ | ||
592 | break; \ | ||
593 | } \ | ||
594 | case 8: \ | ||
595 | { \ | ||
596 | if (!IS_ENABLED(CONFIG_X86_64)) \ | ||
597 | __cmpxchg_wrong_size(); \ | ||
598 | \ | ||
599 | asm volatile("\t" ASM_STAC "\n" \ | ||
600 | "1:\t" LOCK_PREFIX "cmpxchgq %4, %2\n" \ | ||
601 | "2:\t" ASM_CLAC "\n" \ | ||
602 | "\t.section .fixup, \"ax\"\n" \ | ||
603 | "3:\tmov %3, %0\n" \ | ||
604 | "\tjmp 2b\n" \ | ||
605 | "\t.previous\n" \ | ||
606 | _ASM_EXTABLE(1b, 3b) \ | ||
607 | : "+r" (__ret), "=a" (__old), "+m" (*(ptr)) \ | ||
608 | : "i" (-EFAULT), "r" (__new), "1" (__old) \ | ||
609 | : "memory" \ | ||
610 | ); \ | ||
611 | break; \ | ||
612 | } \ | ||
613 | default: \ | ||
614 | __cmpxchg_wrong_size(); \ | ||
615 | } \ | ||
616 | *__uval = __old; \ | ||
617 | __ret; \ | ||
618 | }) | ||
619 | |||
620 | #define user_atomic_cmpxchg_inatomic(uval, ptr, old, new) \ | ||
621 | ({ \ | ||
622 | access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) ? \ | ||
623 | __user_atomic_cmpxchg_inatomic((uval), (ptr), \ | ||
624 | (old), (new), sizeof(*(ptr))) : \ | ||
625 | -EFAULT; \ | ||
626 | }) | ||
627 | |||
528 | /* | 628 | /* |
529 | * movsl can be slow when source and dest are not both 8-byte aligned | 629 | * movsl can be slow when source and dest are not both 8-byte aligned |
530 | */ | 630 | */ |
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 190413d0de57..12a26b979bf1 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h | |||
@@ -204,13 +204,13 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) | |||
204 | static __must_check __always_inline int | 204 | static __must_check __always_inline int |
205 | __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) | 205 | __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) |
206 | { | 206 | { |
207 | return __copy_from_user_nocheck(dst, (__force const void *)src, size); | 207 | return __copy_from_user_nocheck(dst, src, size); |
208 | } | 208 | } |
209 | 209 | ||
210 | static __must_check __always_inline int | 210 | static __must_check __always_inline int |
211 | __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) | 211 | __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) |
212 | { | 212 | { |
213 | return __copy_to_user_nocheck((__force void *)dst, src, size); | 213 | return __copy_to_user_nocheck(dst, src, size); |
214 | } | 214 | } |
215 | 215 | ||
216 | extern long __copy_user_nocache(void *dst, const void __user *src, | 216 | extern long __copy_user_nocache(void *dst, const void __user *src, |
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h index 0415cdabb5a6..554738963b28 100644 --- a/arch/x86/include/asm/xsave.h +++ b/arch/x86/include/asm/xsave.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #define XSTATE_FP 0x1 | 9 | #define XSTATE_FP 0x1 |
10 | #define XSTATE_SSE 0x2 | 10 | #define XSTATE_SSE 0x2 |
11 | #define XSTATE_YMM 0x4 | 11 | #define XSTATE_YMM 0x4 |
12 | #define XSTATE_BNDREGS 0x8 | ||
13 | #define XSTATE_BNDCSR 0x10 | ||
12 | 14 | ||
13 | #define XSTATE_FPSSE (XSTATE_FP | XSTATE_SSE) | 15 | #define XSTATE_FPSSE (XSTATE_FP | XSTATE_SSE) |
14 | 16 | ||
@@ -20,10 +22,14 @@ | |||
20 | #define XSAVE_YMM_SIZE 256 | 22 | #define XSAVE_YMM_SIZE 256 |
21 | #define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET) | 23 | #define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET) |
22 | 24 | ||
23 | /* | 25 | /* Supported features which support lazy state saving */ |
24 | * These are the features that the OS can handle currently. | 26 | #define XSTATE_LAZY (XSTATE_FP | XSTATE_SSE | XSTATE_YMM) |
25 | */ | 27 | |
26 | #define XCNTXT_MASK (XSTATE_FP | XSTATE_SSE | XSTATE_YMM) | 28 | /* Supported features which require eager state saving */ |
29 | #define XSTATE_EAGER (XSTATE_BNDREGS | XSTATE_BNDCSR) | ||
30 | |||
31 | /* All currently supported features */ | ||
32 | #define XCNTXT_MASK (XSTATE_LAZY | XSTATE_EAGER) | ||
27 | 33 | ||
28 | #ifdef CONFIG_X86_64 | 34 | #ifdef CONFIG_X86_64 |
29 | #define REX_PREFIX "0x48, " | 35 | #define REX_PREFIX "0x48, " |
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index 9c3733c5f8f7..225b0988043a 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #define SETUP_E820_EXT 1 | 6 | #define SETUP_E820_EXT 1 |
7 | #define SETUP_DTB 2 | 7 | #define SETUP_DTB 2 |
8 | #define SETUP_PCI 3 | 8 | #define SETUP_PCI 3 |
9 | #define SETUP_EFI 4 | ||
9 | 10 | ||
10 | /* ram_size flags */ | 11 | /* ram_size flags */ |
11 | #define RAMDISK_IMAGE_START_MASK 0x07FF | 12 | #define RAMDISK_IMAGE_START_MASK 0x07FF |
@@ -23,6 +24,7 @@ | |||
23 | #define XLF_CAN_BE_LOADED_ABOVE_4G (1<<1) | 24 | #define XLF_CAN_BE_LOADED_ABOVE_4G (1<<1) |
24 | #define XLF_EFI_HANDOVER_32 (1<<2) | 25 | #define XLF_EFI_HANDOVER_32 (1<<2) |
25 | #define XLF_EFI_HANDOVER_64 (1<<3) | 26 | #define XLF_EFI_HANDOVER_64 (1<<3) |
27 | #define XLF_EFI_KEXEC (1<<4) | ||
26 | 28 | ||
27 | #ifndef __ASSEMBLY__ | 29 | #ifndef __ASSEMBLY__ |
28 | 30 | ||
diff --git a/arch/x86/include/uapi/asm/stat.h b/arch/x86/include/uapi/asm/stat.h index 7b3ddc348585..bc03eb5d6360 100644 --- a/arch/x86/include/uapi/asm/stat.h +++ b/arch/x86/include/uapi/asm/stat.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef _ASM_X86_STAT_H | 1 | #ifndef _ASM_X86_STAT_H |
2 | #define _ASM_X86_STAT_H | 2 | #define _ASM_X86_STAT_H |
3 | 3 | ||
4 | #include <asm/posix_types.h> | ||
5 | |||
4 | #define STAT_HAVE_NSEC 1 | 6 | #define STAT_HAVE_NSEC 1 |
5 | 7 | ||
6 | #ifdef __i386__ | 8 | #ifdef __i386__ |
@@ -78,26 +80,26 @@ struct stat64 { | |||
78 | #else /* __i386__ */ | 80 | #else /* __i386__ */ |
79 | 81 | ||
80 | struct stat { | 82 | struct stat { |
81 | unsigned long st_dev; | 83 | __kernel_ulong_t st_dev; |
82 | unsigned long st_ino; | 84 | __kernel_ulong_t st_ino; |
83 | unsigned long st_nlink; | 85 | __kernel_ulong_t st_nlink; |
84 | 86 | ||
85 | unsigned int st_mode; | 87 | unsigned int st_mode; |
86 | unsigned int st_uid; | 88 | unsigned int st_uid; |
87 | unsigned int st_gid; | 89 | unsigned int st_gid; |
88 | unsigned int __pad0; | 90 | unsigned int __pad0; |
89 | unsigned long st_rdev; | 91 | __kernel_ulong_t st_rdev; |
90 | long st_size; | 92 | __kernel_long_t st_size; |
91 | long st_blksize; | 93 | __kernel_long_t st_blksize; |
92 | long st_blocks; /* Number 512-byte blocks allocated. */ | 94 | __kernel_long_t st_blocks; /* Number 512-byte blocks allocated. */ |
93 | 95 | ||
94 | unsigned long st_atime; | 96 | __kernel_ulong_t st_atime; |
95 | unsigned long st_atime_nsec; | 97 | __kernel_ulong_t st_atime_nsec; |
96 | unsigned long st_mtime; | 98 | __kernel_ulong_t st_mtime; |
97 | unsigned long st_mtime_nsec; | 99 | __kernel_ulong_t st_mtime_nsec; |
98 | unsigned long st_ctime; | 100 | __kernel_ulong_t st_ctime; |
99 | unsigned long st_ctime_nsec; | 101 | __kernel_ulong_t st_ctime_nsec; |
100 | long __unused[3]; | 102 | __kernel_long_t __unused[3]; |
101 | }; | 103 | }; |
102 | 104 | ||
103 | /* We don't need to memset the whole thing just to initialize the padding */ | 105 | /* We don't need to memset the whole thing just to initialize the padding */ |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 9b0a34e2cd79..cb648c84b327 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -29,10 +29,11 @@ obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o | |||
29 | obj-y += syscall_$(BITS).o | 29 | obj-y += syscall_$(BITS).o |
30 | obj-$(CONFIG_X86_64) += vsyscall_64.o | 30 | obj-$(CONFIG_X86_64) += vsyscall_64.o |
31 | obj-$(CONFIG_X86_64) += vsyscall_emu_64.o | 31 | obj-$(CONFIG_X86_64) += vsyscall_emu_64.o |
32 | obj-$(CONFIG_SYSFS) += ksysfs.o | ||
32 | obj-y += bootflag.o e820.o | 33 | obj-y += bootflag.o e820.o |
33 | obj-y += pci-dma.o quirks.o topology.o kdebugfs.o | 34 | obj-y += pci-dma.o quirks.o topology.o kdebugfs.o |
34 | obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o | 35 | obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o |
35 | obj-y += tsc.o io_delay.o rtc.o | 36 | obj-y += tsc.o tsc_msr.o io_delay.o rtc.o |
36 | obj-y += pci-iommu_table.o | 37 | obj-y += pci-iommu_table.o |
37 | obj-y += resource.o | 38 | obj-y += resource.o |
38 | 39 | ||
@@ -91,15 +92,6 @@ obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o | |||
91 | 92 | ||
92 | obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o | 93 | obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o |
93 | 94 | ||
94 | obj-$(CONFIG_MICROCODE_EARLY) += microcode_core_early.o | ||
95 | obj-$(CONFIG_MICROCODE_INTEL_EARLY) += microcode_intel_early.o | ||
96 | obj-$(CONFIG_MICROCODE_INTEL_LIB) += microcode_intel_lib.o | ||
97 | microcode-y := microcode_core.o | ||
98 | microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o | ||
99 | microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o | ||
100 | obj-$(CONFIG_MICROCODE_AMD_EARLY) += microcode_amd_early.o | ||
101 | obj-$(CONFIG_MICROCODE) += microcode.o | ||
102 | |||
103 | obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o | 95 | obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o |
104 | 96 | ||
105 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o | 97 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o |
@@ -111,6 +103,7 @@ obj-$(CONFIG_EFI) += sysfb_efi.o | |||
111 | 103 | ||
112 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o | 104 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o |
113 | obj-$(CONFIG_TRACING) += tracepoint.o | 105 | obj-$(CONFIG_TRACING) += tracepoint.o |
106 | obj-$(CONFIG_IOSF_MBI) += iosf_mbi.o | ||
114 | 107 | ||
115 | ### | 108 | ### |
116 | # 64 bit specific files | 109 | # 64 bit specific files |
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index d2b7f27781bc..e69182fd01cf 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c | |||
@@ -150,29 +150,6 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu, | |||
150 | } | 150 | } |
151 | EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe); | 151 | EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe); |
152 | 152 | ||
153 | /* | ||
154 | * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, | ||
155 | * which can obviate IPI to trigger checking of need_resched. | ||
156 | * We execute MONITOR against need_resched and enter optimized wait state | ||
157 | * through MWAIT. Whenever someone changes need_resched, we would be woken | ||
158 | * up from MWAIT (without an IPI). | ||
159 | * | ||
160 | * New with Core Duo processors, MWAIT can take some hints based on CPU | ||
161 | * capability. | ||
162 | */ | ||
163 | void mwait_idle_with_hints(unsigned long ax, unsigned long cx) | ||
164 | { | ||
165 | if (!need_resched()) { | ||
166 | if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) | ||
167 | clflush((void *)¤t_thread_info()->flags); | ||
168 | |||
169 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
170 | smp_mb(); | ||
171 | if (!need_resched()) | ||
172 | __mwait(ax, cx); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx) | 153 | void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx) |
177 | { | 154 | { |
178 | unsigned int cpu = smp_processor_id(); | 155 | unsigned int cpu = smp_processor_id(); |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index d278736bf774..7f26c9a70a9e 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -75,6 +75,13 @@ unsigned int max_physical_apicid; | |||
75 | physid_mask_t phys_cpu_present_map; | 75 | physid_mask_t phys_cpu_present_map; |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * Processor to be disabled specified by kernel parameter | ||
79 | * disable_cpu_apicid=<int>, mostly used for the kdump 2nd kernel to | ||
80 | * avoid undefined behaviour caused by sending INIT from AP to BSP. | ||
81 | */ | ||
82 | static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID; | ||
83 | |||
84 | /* | ||
78 | * Map cpu index to physical APIC ID | 85 | * Map cpu index to physical APIC ID |
79 | */ | 86 | */ |
80 | DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID); | 87 | DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID); |
@@ -1968,7 +1975,7 @@ __visible void smp_trace_spurious_interrupt(struct pt_regs *regs) | |||
1968 | */ | 1975 | */ |
1969 | static inline void __smp_error_interrupt(struct pt_regs *regs) | 1976 | static inline void __smp_error_interrupt(struct pt_regs *regs) |
1970 | { | 1977 | { |
1971 | u32 v0, v1; | 1978 | u32 v; |
1972 | u32 i = 0; | 1979 | u32 i = 0; |
1973 | static const char * const error_interrupt_reason[] = { | 1980 | static const char * const error_interrupt_reason[] = { |
1974 | "Send CS error", /* APIC Error Bit 0 */ | 1981 | "Send CS error", /* APIC Error Bit 0 */ |
@@ -1982,21 +1989,20 @@ static inline void __smp_error_interrupt(struct pt_regs *regs) | |||
1982 | }; | 1989 | }; |
1983 | 1990 | ||
1984 | /* First tickle the hardware, only then report what went on. -- REW */ | 1991 | /* First tickle the hardware, only then report what went on. -- REW */ |
1985 | v0 = apic_read(APIC_ESR); | ||
1986 | apic_write(APIC_ESR, 0); | 1992 | apic_write(APIC_ESR, 0); |
1987 | v1 = apic_read(APIC_ESR); | 1993 | v = apic_read(APIC_ESR); |
1988 | ack_APIC_irq(); | 1994 | ack_APIC_irq(); |
1989 | atomic_inc(&irq_err_count); | 1995 | atomic_inc(&irq_err_count); |
1990 | 1996 | ||
1991 | apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)", | 1997 | apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x", |
1992 | smp_processor_id(), v0 , v1); | 1998 | smp_processor_id(), v); |
1993 | 1999 | ||
1994 | v1 = v1 & 0xff; | 2000 | v &= 0xff; |
1995 | while (v1) { | 2001 | while (v) { |
1996 | if (v1 & 0x1) | 2002 | if (v & 0x1) |
1997 | apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); | 2003 | apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); |
1998 | i++; | 2004 | i++; |
1999 | v1 >>= 1; | 2005 | v >>= 1; |
2000 | } | 2006 | } |
2001 | 2007 | ||
2002 | apic_printk(APIC_DEBUG, KERN_CONT "\n"); | 2008 | apic_printk(APIC_DEBUG, KERN_CONT "\n"); |
@@ -2115,6 +2121,39 @@ int generic_processor_info(int apicid, int version) | |||
2115 | phys_cpu_present_map); | 2121 | phys_cpu_present_map); |
2116 | 2122 | ||
2117 | /* | 2123 | /* |
2124 | * boot_cpu_physical_apicid is designed to have the apicid | ||
2125 | * returned by read_apic_id(), i.e, the apicid of the | ||
2126 | * currently booting-up processor. However, on some platforms, | ||
2127 | * it is temporarily modified by the apicid reported as BSP | ||
2128 | * through MP table. Concretely: | ||
2129 | * | ||
2130 | * - arch/x86/kernel/mpparse.c: MP_processor_info() | ||
2131 | * - arch/x86/mm/amdtopology.c: amd_numa_init() | ||
2132 | * - arch/x86/platform/visws/visws_quirks.c: MP_processor_info() | ||
2133 | * | ||
2134 | * This function is executed with the modified | ||
2135 | * boot_cpu_physical_apicid. So, disabled_cpu_apicid kernel | ||
2136 | * parameter doesn't work to disable APs on kdump 2nd kernel. | ||
2137 | * | ||
2138 | * Since fixing handling of boot_cpu_physical_apicid requires | ||
2139 | * another discussion and tests on each platform, we leave it | ||
2140 | * for now and here we use read_apic_id() directly in this | ||
2141 | * function, generic_processor_info(). | ||
2142 | */ | ||
2143 | if (disabled_cpu_apicid != BAD_APICID && | ||
2144 | disabled_cpu_apicid != read_apic_id() && | ||
2145 | disabled_cpu_apicid == apicid) { | ||
2146 | int thiscpu = num_processors + disabled_cpus; | ||
2147 | |||
2148 | pr_warning("APIC: Disabling requested cpu." | ||
2149 | " Processor %d/0x%x ignored.\n", | ||
2150 | thiscpu, apicid); | ||
2151 | |||
2152 | disabled_cpus++; | ||
2153 | return -ENODEV; | ||
2154 | } | ||
2155 | |||
2156 | /* | ||
2118 | * If boot cpu has not been detected yet, then only allow upto | 2157 | * If boot cpu has not been detected yet, then only allow upto |
2119 | * nr_cpu_ids - 1 processors and keep one slot free for boot cpu | 2158 | * nr_cpu_ids - 1 processors and keep one slot free for boot cpu |
2120 | */ | 2159 | */ |
@@ -2592,3 +2631,12 @@ static int __init lapic_insert_resource(void) | |||
2592 | * that is using request_resource | 2631 | * that is using request_resource |
2593 | */ | 2632 | */ |
2594 | late_initcall(lapic_insert_resource); | 2633 | late_initcall(lapic_insert_resource); |
2634 | |||
2635 | static int __init apic_set_disabled_cpu_apicid(char *arg) | ||
2636 | { | ||
2637 | if (!arg || !get_option(&arg, &disabled_cpu_apicid)) | ||
2638 | return -EINVAL; | ||
2639 | |||
2640 | return 0; | ||
2641 | } | ||
2642 | early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid); | ||
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 00c77cf78e9e..5d5b9eb2b7a4 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/string.h> | 14 | #include <linux/string.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/ctype.h> | 16 | #include <linux/ctype.h> |
17 | #include <linux/init.h> | ||
18 | #include <linux/hardirq.h> | 17 | #include <linux/hardirq.h> |
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <asm/smp.h> | 19 | #include <asm/smp.h> |
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index e145f28b4099..191ce75c0e54 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
18 | #include <linux/init.h> | ||
19 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
20 | #include <asm/fixmap.h> | 19 | #include <asm/fixmap.h> |
21 | #include <asm/mpspec.h> | 20 | #include <asm/mpspec.h> |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e63a5bd2a78f..a43f068ebec1 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1142,9 +1142,10 @@ next: | |||
1142 | if (test_bit(vector, used_vectors)) | 1142 | if (test_bit(vector, used_vectors)) |
1143 | goto next; | 1143 | goto next; |
1144 | 1144 | ||
1145 | for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) | 1145 | for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) { |
1146 | if (per_cpu(vector_irq, new_cpu)[vector] != -1) | 1146 | if (per_cpu(vector_irq, new_cpu)[vector] > VECTOR_UNDEFINED) |
1147 | goto next; | 1147 | goto next; |
1148 | } | ||
1148 | /* Found one! */ | 1149 | /* Found one! */ |
1149 | current_vector = vector; | 1150 | current_vector = vector; |
1150 | current_offset = offset; | 1151 | current_offset = offset; |
@@ -1183,7 +1184,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) | |||
1183 | 1184 | ||
1184 | vector = cfg->vector; | 1185 | vector = cfg->vector; |
1185 | for_each_cpu_and(cpu, cfg->domain, cpu_online_mask) | 1186 | for_each_cpu_and(cpu, cfg->domain, cpu_online_mask) |
1186 | per_cpu(vector_irq, cpu)[vector] = -1; | 1187 | per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED; |
1187 | 1188 | ||
1188 | cfg->vector = 0; | 1189 | cfg->vector = 0; |
1189 | cpumask_clear(cfg->domain); | 1190 | cpumask_clear(cfg->domain); |
@@ -1191,11 +1192,10 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) | |||
1191 | if (likely(!cfg->move_in_progress)) | 1192 | if (likely(!cfg->move_in_progress)) |
1192 | return; | 1193 | return; |
1193 | for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) { | 1194 | for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) { |
1194 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; | 1195 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { |
1195 | vector++) { | ||
1196 | if (per_cpu(vector_irq, cpu)[vector] != irq) | 1196 | if (per_cpu(vector_irq, cpu)[vector] != irq) |
1197 | continue; | 1197 | continue; |
1198 | per_cpu(vector_irq, cpu)[vector] = -1; | 1198 | per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED; |
1199 | break; | 1199 | break; |
1200 | } | 1200 | } |
1201 | } | 1201 | } |
@@ -1228,12 +1228,12 @@ void __setup_vector_irq(int cpu) | |||
1228 | /* Mark the free vectors */ | 1228 | /* Mark the free vectors */ |
1229 | for (vector = 0; vector < NR_VECTORS; ++vector) { | 1229 | for (vector = 0; vector < NR_VECTORS; ++vector) { |
1230 | irq = per_cpu(vector_irq, cpu)[vector]; | 1230 | irq = per_cpu(vector_irq, cpu)[vector]; |
1231 | if (irq < 0) | 1231 | if (irq <= VECTOR_UNDEFINED) |
1232 | continue; | 1232 | continue; |
1233 | 1233 | ||
1234 | cfg = irq_cfg(irq); | 1234 | cfg = irq_cfg(irq); |
1235 | if (!cpumask_test_cpu(cpu, cfg->domain)) | 1235 | if (!cpumask_test_cpu(cpu, cfg->domain)) |
1236 | per_cpu(vector_irq, cpu)[vector] = -1; | 1236 | per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED; |
1237 | } | 1237 | } |
1238 | raw_spin_unlock(&vector_lock); | 1238 | raw_spin_unlock(&vector_lock); |
1239 | } | 1239 | } |
@@ -2202,13 +2202,13 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) | |||
2202 | 2202 | ||
2203 | me = smp_processor_id(); | 2203 | me = smp_processor_id(); |
2204 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { | 2204 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { |
2205 | unsigned int irq; | 2205 | int irq; |
2206 | unsigned int irr; | 2206 | unsigned int irr; |
2207 | struct irq_desc *desc; | 2207 | struct irq_desc *desc; |
2208 | struct irq_cfg *cfg; | 2208 | struct irq_cfg *cfg; |
2209 | irq = __this_cpu_read(vector_irq[vector]); | 2209 | irq = __this_cpu_read(vector_irq[vector]); |
2210 | 2210 | ||
2211 | if (irq == -1) | 2211 | if (irq <= VECTOR_UNDEFINED) |
2212 | continue; | 2212 | continue; |
2213 | 2213 | ||
2214 | desc = irq_to_desc(irq); | 2214 | desc = irq_to_desc(irq); |
diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 7434d8556d09..62071569bd50 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #include <linux/cpumask.h> | 1 | #include <linux/cpumask.h> |
2 | #include <linux/interrupt.h> | 2 | #include <linux/interrupt.h> |
3 | #include <linux/init.h> | ||
4 | 3 | ||
5 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
6 | #include <linux/delay.h> | 5 | #include <linux/delay.h> |
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 77c95c0e1bf7..00146f9b0254 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #define pr_fmt(fmt) "summit: %s: " fmt, __func__ | 29 | #define pr_fmt(fmt) "summit: %s: " fmt, __func__ |
30 | 30 | ||
31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
32 | #include <linux/init.h> | ||
33 | #include <asm/io.h> | 32 | #include <asm/io.h> |
34 | #include <asm/bios_ebda.h> | 33 | #include <asm/bios_ebda.h> |
35 | 34 | ||
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 140e29db478d..cac85ee6913f 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c | |||
@@ -3,7 +3,6 @@ | |||
3 | #include <linux/string.h> | 3 | #include <linux/string.h> |
4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
5 | #include <linux/ctype.h> | 5 | #include <linux/ctype.h> |
6 | #include <linux/init.h> | ||
7 | #include <linux/dmar.h> | 6 | #include <linux/dmar.h> |
8 | #include <linux/cpu.h> | 7 | #include <linux/cpu.h> |
9 | 8 | ||
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 562a76d433c8..de231e328cae 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c | |||
@@ -3,7 +3,6 @@ | |||
3 | #include <linux/string.h> | 3 | #include <linux/string.h> |
4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
5 | #include <linux/ctype.h> | 5 | #include <linux/ctype.h> |
6 | #include <linux/init.h> | ||
7 | #include <linux/dmar.h> | 6 | #include <linux/dmar.h> |
8 | 7 | ||
9 | #include <asm/smp.h> | 8 | #include <asm/smp.h> |
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 47b56a7e99cb..7fd54f09b011 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
@@ -36,12 +36,13 @@ obj-$(CONFIG_CPU_SUP_AMD) += perf_event_amd_iommu.o | |||
36 | endif | 36 | endif |
37 | obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_p6.o perf_event_knc.o perf_event_p4.o | 37 | obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_p6.o perf_event_knc.o perf_event_p4.o |
38 | obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o | 38 | obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o |
39 | obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_uncore.o | 39 | obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_uncore.o perf_event_intel_rapl.o |
40 | endif | 40 | endif |
41 | 41 | ||
42 | 42 | ||
43 | obj-$(CONFIG_X86_MCE) += mcheck/ | 43 | obj-$(CONFIG_X86_MCE) += mcheck/ |
44 | obj-$(CONFIG_MTRR) += mtrr/ | 44 | obj-$(CONFIG_MTRR) += mtrr/ |
45 | obj-$(CONFIG_MICROCODE) += microcode/ | ||
45 | 46 | ||
46 | obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o perf_event_amd_ibs.o | 47 | obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o perf_event_amd_ibs.o |
47 | 48 | ||
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 96abccaada33..c67ffa686064 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -1,5 +1,4 @@ | |||
1 | #include <linux/export.h> | 1 | #include <linux/export.h> |
2 | #include <linux/init.h> | ||
3 | #include <linux/bitops.h> | 2 | #include <linux/bitops.h> |
4 | #include <linux/elf.h> | 3 | #include <linux/elf.h> |
5 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
@@ -487,7 +486,7 @@ static void early_init_amd(struct cpuinfo_x86 *c) | |||
487 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 486 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
488 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); | 487 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); |
489 | if (!check_tsc_unstable()) | 488 | if (!check_tsc_unstable()) |
490 | sched_clock_stable = 1; | 489 | set_sched_clock_stable(); |
491 | } | 490 | } |
492 | 491 | ||
493 | #ifdef CONFIG_X86_64 | 492 | #ifdef CONFIG_X86_64 |
@@ -797,14 +796,10 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) | |||
797 | } | 796 | } |
798 | 797 | ||
799 | /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ | 798 | /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ |
800 | if (!((eax >> 16) & mask)) { | 799 | if (!((eax >> 16) & mask)) |
801 | u32 a, b, c, d; | 800 | tlb_lld_2m[ENTRIES] = (cpuid_eax(0x80000005) >> 16) & 0xff; |
802 | 801 | else | |
803 | cpuid(0x80000005, &a, &b, &c, &d); | ||
804 | tlb_lld_2m[ENTRIES] = (a >> 16) & 0xff; | ||
805 | } else { | ||
806 | tlb_lld_2m[ENTRIES] = (eax >> 16) & mask; | 802 | tlb_lld_2m[ENTRIES] = (eax >> 16) & mask; |
807 | } | ||
808 | 803 | ||
809 | /* a 4M entry uses two 2M entries */ | 804 | /* a 4M entry uses two 2M entries */ |
810 | tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1; | 805 | tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1; |
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index 8d5652dc99dd..8779edab684e 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #include <linux/bitops.h> | 1 | #include <linux/bitops.h> |
2 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
3 | #include <linux/init.h> | ||
4 | 3 | ||
5 | #include <asm/processor.h> | 4 | #include <asm/processor.h> |
6 | #include <asm/e820.h> | 5 | #include <asm/e820.h> |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 6abc172b8258..24b6fd10625a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -472,6 +472,7 @@ u16 __read_mostly tlb_lli_4m[NR_INFO]; | |||
472 | u16 __read_mostly tlb_lld_4k[NR_INFO]; | 472 | u16 __read_mostly tlb_lld_4k[NR_INFO]; |
473 | u16 __read_mostly tlb_lld_2m[NR_INFO]; | 473 | u16 __read_mostly tlb_lld_2m[NR_INFO]; |
474 | u16 __read_mostly tlb_lld_4m[NR_INFO]; | 474 | u16 __read_mostly tlb_lld_4m[NR_INFO]; |
475 | u16 __read_mostly tlb_lld_1g[NR_INFO]; | ||
475 | 476 | ||
476 | /* | 477 | /* |
477 | * tlb_flushall_shift shows the balance point in replacing cr3 write | 478 | * tlb_flushall_shift shows the balance point in replacing cr3 write |
@@ -486,13 +487,13 @@ void cpu_detect_tlb(struct cpuinfo_x86 *c) | |||
486 | if (this_cpu->c_detect_tlb) | 487 | if (this_cpu->c_detect_tlb) |
487 | this_cpu->c_detect_tlb(c); | 488 | this_cpu->c_detect_tlb(c); |
488 | 489 | ||
489 | printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ | 490 | printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" |
490 | "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ | 491 | "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d, 1GB %d\n" |
491 | "tlb_flushall_shift: %d\n", | 492 | "tlb_flushall_shift: %d\n", |
492 | tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES], | 493 | tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES], |
493 | tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES], | 494 | tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES], |
494 | tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES], | 495 | tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES], |
495 | tlb_flushall_shift); | 496 | tlb_lld_1g[ENTRIES], tlb_flushall_shift); |
496 | } | 497 | } |
497 | 498 | ||
498 | void detect_ht(struct cpuinfo_x86 *c) | 499 | void detect_ht(struct cpuinfo_x86 *c) |
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index d0969c75ab54..aaf152e79637 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/bitops.h> | 1 | #include <linux/bitops.h> |
3 | #include <linux/delay.h> | 2 | #include <linux/delay.h> |
4 | #include <linux/pci.h> | 3 | #include <linux/pci.h> |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index d358a3928b8f..5cd9bfabd645 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
3 | 2 | ||
4 | #include <linux/string.h> | 3 | #include <linux/string.h> |
@@ -93,7 +92,7 @@ static void early_init_intel(struct cpuinfo_x86 *c) | |||
93 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 92 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
94 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); | 93 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); |
95 | if (!check_tsc_unstable()) | 94 | if (!check_tsc_unstable()) |
96 | sched_clock_stable = 1; | 95 | set_sched_clock_stable(); |
97 | } | 96 | } |
98 | 97 | ||
99 | /* Penwell and Cloverview have the TSC which doesn't sleep on S3 */ | 98 | /* Penwell and Cloverview have the TSC which doesn't sleep on S3 */ |
@@ -506,6 +505,7 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) | |||
506 | #define TLB_DATA0_2M_4M 0x23 | 505 | #define TLB_DATA0_2M_4M 0x23 |
507 | 506 | ||
508 | #define STLB_4K 0x41 | 507 | #define STLB_4K 0x41 |
508 | #define STLB_4K_2M 0x42 | ||
509 | 509 | ||
510 | static const struct _tlb_table intel_tlb_table[] = { | 510 | static const struct _tlb_table intel_tlb_table[] = { |
511 | { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages, 4-way set associative" }, | 511 | { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages, 4-way set associative" }, |
@@ -526,13 +526,20 @@ static const struct _tlb_table intel_tlb_table[] = { | |||
526 | { 0x5b, TLB_DATA_4K_4M, 64, " TLB_DATA 4 KByte and 4 MByte pages" }, | 526 | { 0x5b, TLB_DATA_4K_4M, 64, " TLB_DATA 4 KByte and 4 MByte pages" }, |
527 | { 0x5c, TLB_DATA_4K_4M, 128, " TLB_DATA 4 KByte and 4 MByte pages" }, | 527 | { 0x5c, TLB_DATA_4K_4M, 128, " TLB_DATA 4 KByte and 4 MByte pages" }, |
528 | { 0x5d, TLB_DATA_4K_4M, 256, " TLB_DATA 4 KByte and 4 MByte pages" }, | 528 | { 0x5d, TLB_DATA_4K_4M, 256, " TLB_DATA 4 KByte and 4 MByte pages" }, |
529 | { 0x61, TLB_INST_4K, 48, " TLB_INST 4 KByte pages, full associative" }, | ||
530 | { 0x63, TLB_DATA_1G, 4, " TLB_DATA 1 GByte pages, 4-way set associative" }, | ||
531 | { 0x76, TLB_INST_2M_4M, 8, " TLB_INST 2-MByte or 4-MByte pages, fully associative" }, | ||
529 | { 0xb0, TLB_INST_4K, 128, " TLB_INST 4 KByte pages, 4-way set associative" }, | 532 | { 0xb0, TLB_INST_4K, 128, " TLB_INST 4 KByte pages, 4-way set associative" }, |
530 | { 0xb1, TLB_INST_2M_4M, 4, " TLB_INST 2M pages, 4-way, 8 entries or 4M pages, 4-way entries" }, | 533 | { 0xb1, TLB_INST_2M_4M, 4, " TLB_INST 2M pages, 4-way, 8 entries or 4M pages, 4-way entries" }, |
531 | { 0xb2, TLB_INST_4K, 64, " TLB_INST 4KByte pages, 4-way set associative" }, | 534 | { 0xb2, TLB_INST_4K, 64, " TLB_INST 4KByte pages, 4-way set associative" }, |
532 | { 0xb3, TLB_DATA_4K, 128, " TLB_DATA 4 KByte pages, 4-way set associative" }, | 535 | { 0xb3, TLB_DATA_4K, 128, " TLB_DATA 4 KByte pages, 4-way set associative" }, |
533 | { 0xb4, TLB_DATA_4K, 256, " TLB_DATA 4 KByte pages, 4-way associative" }, | 536 | { 0xb4, TLB_DATA_4K, 256, " TLB_DATA 4 KByte pages, 4-way associative" }, |
537 | { 0xb5, TLB_INST_4K, 64, " TLB_INST 4 KByte pages, 8-way set ssociative" }, | ||
538 | { 0xb6, TLB_INST_4K, 128, " TLB_INST 4 KByte pages, 8-way set ssociative" }, | ||
534 | { 0xba, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way associative" }, | 539 | { 0xba, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way associative" }, |
535 | { 0xc0, TLB_DATA_4K_4M, 8, " TLB_DATA 4 KByte and 4 MByte pages, 4-way associative" }, | 540 | { 0xc0, TLB_DATA_4K_4M, 8, " TLB_DATA 4 KByte and 4 MByte pages, 4-way associative" }, |
541 | { 0xc1, STLB_4K_2M, 1024, " STLB 4 KByte and 2 MByte pages, 8-way associative" }, | ||
542 | { 0xc2, TLB_DATA_2M_4M, 16, " DTLB 2 MByte/4MByte pages, 4-way associative" }, | ||
536 | { 0xca, STLB_4K, 512, " STLB 4 KByte pages, 4-way associative" }, | 543 | { 0xca, STLB_4K, 512, " STLB 4 KByte pages, 4-way associative" }, |
537 | { 0x00, 0, 0 } | 544 | { 0x00, 0, 0 } |
538 | }; | 545 | }; |
@@ -558,6 +565,20 @@ static void intel_tlb_lookup(const unsigned char desc) | |||
558 | if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries) | 565 | if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries) |
559 | tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries; | 566 | tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries; |
560 | break; | 567 | break; |
568 | case STLB_4K_2M: | ||
569 | if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries) | ||
570 | tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries; | ||
571 | if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries) | ||
572 | tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries; | ||
573 | if (tlb_lli_2m[ENTRIES] < intel_tlb_table[k].entries) | ||
574 | tlb_lli_2m[ENTRIES] = intel_tlb_table[k].entries; | ||
575 | if (tlb_lld_2m[ENTRIES] < intel_tlb_table[k].entries) | ||
576 | tlb_lld_2m[ENTRIES] = intel_tlb_table[k].entries; | ||
577 | if (tlb_lli_4m[ENTRIES] < intel_tlb_table[k].entries) | ||
578 | tlb_lli_4m[ENTRIES] = intel_tlb_table[k].entries; | ||
579 | if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries) | ||
580 | tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries; | ||
581 | break; | ||
561 | case TLB_INST_ALL: | 582 | case TLB_INST_ALL: |
562 | if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries) | 583 | if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries) |
563 | tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries; | 584 | tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries; |
@@ -603,6 +624,10 @@ static void intel_tlb_lookup(const unsigned char desc) | |||
603 | if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries) | 624 | if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries) |
604 | tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries; | 625 | tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries; |
605 | break; | 626 | break; |
627 | case TLB_DATA_1G: | ||
628 | if (tlb_lld_1g[ENTRIES] < intel_tlb_table[k].entries) | ||
629 | tlb_lld_1g[ENTRIES] = intel_tlb_table[k].entries; | ||
630 | break; | ||
606 | } | 631 | } |
607 | } | 632 | } |
608 | 633 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-apei.c b/arch/x86/kernel/cpu/mcheck/mce-apei.c index de8b60a53f69..a1aef9533154 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-apei.c +++ b/arch/x86/kernel/cpu/mcheck/mce-apei.c | |||
@@ -33,22 +33,28 @@ | |||
33 | #include <linux/acpi.h> | 33 | #include <linux/acpi.h> |
34 | #include <linux/cper.h> | 34 | #include <linux/cper.h> |
35 | #include <acpi/apei.h> | 35 | #include <acpi/apei.h> |
36 | #include <acpi/ghes.h> | ||
36 | #include <asm/mce.h> | 37 | #include <asm/mce.h> |
37 | 38 | ||
38 | #include "mce-internal.h" | 39 | #include "mce-internal.h" |
39 | 40 | ||
40 | void apei_mce_report_mem_error(int corrected, struct cper_sec_mem_err *mem_err) | 41 | void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err) |
41 | { | 42 | { |
42 | struct mce m; | 43 | struct mce m; |
43 | 44 | ||
44 | /* Only corrected MC is reported */ | 45 | if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) |
45 | if (!corrected || !(mem_err->validation_bits & CPER_MEM_VALID_PA)) | ||
46 | return; | 46 | return; |
47 | 47 | ||
48 | mce_setup(&m); | 48 | mce_setup(&m); |
49 | m.bank = 1; | 49 | m.bank = 1; |
50 | /* Fake a memory read corrected error with unknown channel */ | 50 | /* Fake a memory read error with unknown channel */ |
51 | m.status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | 0x9f; | 51 | m.status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | 0x9f; |
52 | |||
53 | if (severity >= GHES_SEV_RECOVERABLE) | ||
54 | m.status |= MCI_STATUS_UC; | ||
55 | if (severity >= GHES_SEV_PANIC) | ||
56 | m.status |= MCI_STATUS_PCC; | ||
57 | |||
52 | m.addr = mem_err->physical_addr; | 58 | m.addr = mem_err->physical_addr; |
53 | mce_log(&m); | 59 | mce_log(&m); |
54 | mce_notify_irq(); | 60 | mce_notify_irq(); |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index b3218cdee95f..4d5419b249da 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -1638,15 +1638,15 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) | |||
1638 | 1638 | ||
1639 | static void mce_start_timer(unsigned int cpu, struct timer_list *t) | 1639 | static void mce_start_timer(unsigned int cpu, struct timer_list *t) |
1640 | { | 1640 | { |
1641 | unsigned long iv = mce_adjust_timer(check_interval * HZ); | 1641 | unsigned long iv = check_interval * HZ; |
1642 | |||
1643 | __this_cpu_write(mce_next_interval, iv); | ||
1644 | 1642 | ||
1645 | if (mca_cfg.ignore_ce || !iv) | 1643 | if (mca_cfg.ignore_ce || !iv) |
1646 | return; | 1644 | return; |
1647 | 1645 | ||
1646 | per_cpu(mce_next_interval, cpu) = iv; | ||
1647 | |||
1648 | t->expires = round_jiffies(jiffies + iv); | 1648 | t->expires = round_jiffies(jiffies + iv); |
1649 | add_timer_on(t, smp_processor_id()); | 1649 | add_timer_on(t, cpu); |
1650 | } | 1650 | } |
1651 | 1651 | ||
1652 | static void __mcheck_cpu_init_timer(void) | 1652 | static void __mcheck_cpu_init_timer(void) |
@@ -2272,8 +2272,10 @@ static int mce_device_create(unsigned int cpu) | |||
2272 | dev->release = &mce_device_release; | 2272 | dev->release = &mce_device_release; |
2273 | 2273 | ||
2274 | err = device_register(dev); | 2274 | err = device_register(dev); |
2275 | if (err) | 2275 | if (err) { |
2276 | put_device(dev); | ||
2276 | return err; | 2277 | return err; |
2278 | } | ||
2277 | 2279 | ||
2278 | for (i = 0; mce_device_attrs[i]; i++) { | 2280 | for (i = 0; mce_device_attrs[i]; i++) { |
2279 | err = device_create_file(dev, mce_device_attrs[i]); | 2281 | err = device_create_file(dev, mce_device_attrs[i]); |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 4cfe0458ca66..fb6156fee6f7 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c | |||
@@ -6,7 +6,6 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/gfp.h> | 8 | #include <linux/gfp.h> |
9 | #include <linux/init.h> | ||
10 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
11 | #include <linux/percpu.h> | 10 | #include <linux/percpu.h> |
12 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c index 1c044b1ccc59..a3042989398c 100644 --- a/arch/x86/kernel/cpu/mcheck/p5.c +++ b/arch/x86/kernel/cpu/mcheck/p5.c | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <linux/init.h> | ||
9 | #include <linux/smp.h> | 8 | #include <linux/smp.h> |
10 | 9 | ||
11 | #include <asm/processor.h> | 10 | #include <asm/processor.h> |
diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c index e9a701aecaa1..7dc5564d0cdf 100644 --- a/arch/x86/kernel/cpu/mcheck/winchip.c +++ b/arch/x86/kernel/cpu/mcheck/winchip.c | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <linux/init.h> | ||
9 | 8 | ||
10 | #include <asm/processor.h> | 9 | #include <asm/processor.h> |
11 | #include <asm/mce.h> | 10 | #include <asm/mce.h> |
diff --git a/arch/x86/kernel/cpu/microcode/Makefile b/arch/x86/kernel/cpu/microcode/Makefile new file mode 100644 index 000000000000..285c85427c32 --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | microcode-y := core.o | ||
2 | obj-$(CONFIG_MICROCODE) += microcode.o | ||
3 | microcode-$(CONFIG_MICROCODE_INTEL) += intel.o intel_lib.o | ||
4 | microcode-$(CONFIG_MICROCODE_AMD) += amd.o | ||
5 | obj-$(CONFIG_MICROCODE_EARLY) += core_early.o | ||
6 | obj-$(CONFIG_MICROCODE_INTEL_EARLY) += intel_early.o | ||
7 | obj-$(CONFIG_MICROCODE_AMD_EARLY) += amd_early.o | ||
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/cpu/microcode/amd.c index c3d4cc972eca..4a6ff747aaad 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c | |||
@@ -182,10 +182,10 @@ int __apply_microcode_amd(struct microcode_amd *mc_amd) | |||
182 | { | 182 | { |
183 | u32 rev, dummy; | 183 | u32 rev, dummy; |
184 | 184 | ||
185 | wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); | 185 | native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); |
186 | 186 | ||
187 | /* verify patch application was successful */ | 187 | /* verify patch application was successful */ |
188 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); | 188 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); |
189 | if (rev != mc_amd->hdr.patch_id) | 189 | if (rev != mc_amd->hdr.patch_id) |
190 | return -1; | 190 | return -1; |
191 | 191 | ||
@@ -332,6 +332,9 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover) | |||
332 | patch->patch_id = mc_hdr->patch_id; | 332 | patch->patch_id = mc_hdr->patch_id; |
333 | patch->equiv_cpu = proc_id; | 333 | patch->equiv_cpu = proc_id; |
334 | 334 | ||
335 | pr_debug("%s: Added patch_id: 0x%08x, proc_id: 0x%04x\n", | ||
336 | __func__, patch->patch_id, proc_id); | ||
337 | |||
335 | /* ... and add to cache. */ | 338 | /* ... and add to cache. */ |
336 | update_cache(patch); | 339 | update_cache(patch); |
337 | 340 | ||
@@ -390,9 +393,9 @@ enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) | |||
390 | if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) { | 393 | if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) { |
391 | struct ucode_patch *p = find_patch(smp_processor_id()); | 394 | struct ucode_patch *p = find_patch(smp_processor_id()); |
392 | if (p) { | 395 | if (p) { |
393 | memset(amd_bsp_mpb, 0, MPB_MAX_SIZE); | 396 | memset(amd_ucode_patch, 0, PATCH_MAX_SIZE); |
394 | memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data), | 397 | memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), |
395 | MPB_MAX_SIZE)); | 398 | PATCH_MAX_SIZE)); |
396 | } | 399 | } |
397 | } | 400 | } |
398 | #endif | 401 | #endif |
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c index 6073104ccaa3..8384c0fa206f 100644 --- a/arch/x86/kernel/microcode_amd_early.c +++ b/arch/x86/kernel/cpu/microcode/amd_early.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Copyright (C) 2013 Advanced Micro Devices, Inc. | 2 | * Copyright (C) 2013 Advanced Micro Devices, Inc. |
3 | * | 3 | * |
4 | * Author: Jacob Shin <jacob.shin@amd.com> | 4 | * Author: Jacob Shin <jacob.shin@amd.com> |
5 | * Fixes: Borislav Petkov <bp@suse.de> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -15,10 +16,18 @@ | |||
15 | #include <asm/setup.h> | 16 | #include <asm/setup.h> |
16 | #include <asm/microcode_amd.h> | 17 | #include <asm/microcode_amd.h> |
17 | 18 | ||
18 | static bool ucode_loaded; | 19 | /* |
20 | * This points to the current valid container of microcode patches which we will | ||
21 | * save from the initrd before jettisoning its contents. | ||
22 | */ | ||
23 | static u8 *container; | ||
24 | static size_t container_size; | ||
25 | |||
19 | static u32 ucode_new_rev; | 26 | static u32 ucode_new_rev; |
20 | static unsigned long ucode_offset; | 27 | u8 amd_ucode_patch[PATCH_MAX_SIZE]; |
21 | static size_t ucode_size; | 28 | static u16 this_equiv_id; |
29 | |||
30 | struct cpio_data ucode_cpio; | ||
22 | 31 | ||
23 | /* | 32 | /* |
24 | * Microcode patch container file is prepended to the initrd in cpio format. | 33 | * Microcode patch container file is prepended to the initrd in cpio format. |
@@ -32,9 +41,6 @@ static struct cpio_data __init find_ucode_in_initrd(void) | |||
32 | char *path; | 41 | char *path; |
33 | void *start; | 42 | void *start; |
34 | size_t size; | 43 | size_t size; |
35 | unsigned long *uoffset; | ||
36 | size_t *usize; | ||
37 | struct cpio_data cd; | ||
38 | 44 | ||
39 | #ifdef CONFIG_X86_32 | 45 | #ifdef CONFIG_X86_32 |
40 | struct boot_params *p; | 46 | struct boot_params *p; |
@@ -47,30 +53,50 @@ static struct cpio_data __init find_ucode_in_initrd(void) | |||
47 | path = (char *)__pa_nodebug(ucode_path); | 53 | path = (char *)__pa_nodebug(ucode_path); |
48 | start = (void *)p->hdr.ramdisk_image; | 54 | start = (void *)p->hdr.ramdisk_image; |
49 | size = p->hdr.ramdisk_size; | 55 | size = p->hdr.ramdisk_size; |
50 | uoffset = (unsigned long *)__pa_nodebug(&ucode_offset); | ||
51 | usize = (size_t *)__pa_nodebug(&ucode_size); | ||
52 | #else | 56 | #else |
53 | path = ucode_path; | 57 | path = ucode_path; |
54 | start = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET); | 58 | start = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET); |
55 | size = boot_params.hdr.ramdisk_size; | 59 | size = boot_params.hdr.ramdisk_size; |
56 | uoffset = &ucode_offset; | ||
57 | usize = &ucode_size; | ||
58 | #endif | 60 | #endif |
59 | 61 | ||
60 | cd = find_cpio_data(path, start, size, &offset); | 62 | return find_cpio_data(path, start, size, &offset); |
61 | if (!cd.data) | 63 | } |
62 | return cd; | ||
63 | 64 | ||
64 | if (*(u32 *)cd.data != UCODE_MAGIC) { | 65 | static size_t compute_container_size(u8 *data, u32 total_size) |
65 | cd.data = NULL; | 66 | { |
66 | cd.size = 0; | 67 | size_t size = 0; |
67 | return cd; | 68 | u32 *header = (u32 *)data; |
68 | } | ||
69 | 69 | ||
70 | *uoffset = (u8 *)cd.data - (u8 *)start; | 70 | if (header[0] != UCODE_MAGIC || |
71 | *usize = cd.size; | 71 | header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */ |
72 | header[2] == 0) /* size */ | ||
73 | return size; | ||
72 | 74 | ||
73 | return cd; | 75 | size = header[2] + CONTAINER_HDR_SZ; |
76 | total_size -= size; | ||
77 | data += size; | ||
78 | |||
79 | while (total_size) { | ||
80 | u16 patch_size; | ||
81 | |||
82 | header = (u32 *)data; | ||
83 | |||
84 | if (header[0] != UCODE_UCODE_TYPE) | ||
85 | break; | ||
86 | |||
87 | /* | ||
88 | * Sanity-check patch size. | ||
89 | */ | ||
90 | patch_size = header[1]; | ||
91 | if (patch_size > PATCH_MAX_SIZE) | ||
92 | break; | ||
93 | |||
94 | size += patch_size + SECTION_HDR_SIZE; | ||
95 | data += patch_size + SECTION_HDR_SIZE; | ||
96 | total_size -= patch_size + SECTION_HDR_SIZE; | ||
97 | } | ||
98 | |||
99 | return size; | ||
74 | } | 100 | } |
75 | 101 | ||
76 | /* | 102 | /* |
@@ -85,23 +111,22 @@ static struct cpio_data __init find_ucode_in_initrd(void) | |||
85 | static void apply_ucode_in_initrd(void *ucode, size_t size) | 111 | static void apply_ucode_in_initrd(void *ucode, size_t size) |
86 | { | 112 | { |
87 | struct equiv_cpu_entry *eq; | 113 | struct equiv_cpu_entry *eq; |
114 | size_t *cont_sz; | ||
88 | u32 *header; | 115 | u32 *header; |
89 | u8 *data; | 116 | u8 *data, **cont; |
90 | u16 eq_id = 0; | 117 | u16 eq_id = 0; |
91 | int offset, left; | 118 | int offset, left; |
92 | u32 rev, eax; | 119 | u32 rev, eax, ebx, ecx, edx; |
93 | u32 *new_rev; | 120 | u32 *new_rev; |
94 | unsigned long *uoffset; | ||
95 | size_t *usize; | ||
96 | 121 | ||
97 | #ifdef CONFIG_X86_32 | 122 | #ifdef CONFIG_X86_32 |
98 | new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); | 123 | new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); |
99 | uoffset = (unsigned long *)__pa_nodebug(&ucode_offset); | 124 | cont_sz = (size_t *)__pa_nodebug(&container_size); |
100 | usize = (size_t *)__pa_nodebug(&ucode_size); | 125 | cont = (u8 **)__pa_nodebug(&container); |
101 | #else | 126 | #else |
102 | new_rev = &ucode_new_rev; | 127 | new_rev = &ucode_new_rev; |
103 | uoffset = &ucode_offset; | 128 | cont_sz = &container_size; |
104 | usize = &ucode_size; | 129 | cont = &container; |
105 | #endif | 130 | #endif |
106 | 131 | ||
107 | data = ucode; | 132 | data = ucode; |
@@ -109,23 +134,37 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) | |||
109 | header = (u32 *)data; | 134 | header = (u32 *)data; |
110 | 135 | ||
111 | /* find equiv cpu table */ | 136 | /* find equiv cpu table */ |
112 | 137 | if (header[0] != UCODE_MAGIC || | |
113 | if (header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */ | 138 | header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */ |
114 | header[2] == 0) /* size */ | 139 | header[2] == 0) /* size */ |
115 | return; | 140 | return; |
116 | 141 | ||
117 | eax = cpuid_eax(0x00000001); | 142 | eax = 0x00000001; |
143 | ecx = 0; | ||
144 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
118 | 145 | ||
119 | while (left > 0) { | 146 | while (left > 0) { |
120 | eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ); | 147 | eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ); |
121 | 148 | ||
149 | *cont = data; | ||
150 | |||
151 | /* Advance past the container header */ | ||
122 | offset = header[2] + CONTAINER_HDR_SZ; | 152 | offset = header[2] + CONTAINER_HDR_SZ; |
123 | data += offset; | 153 | data += offset; |
124 | left -= offset; | 154 | left -= offset; |
125 | 155 | ||
126 | eq_id = find_equiv_id(eq, eax); | 156 | eq_id = find_equiv_id(eq, eax); |
127 | if (eq_id) | 157 | if (eq_id) { |
158 | this_equiv_id = eq_id; | ||
159 | *cont_sz = compute_container_size(*cont, left + offset); | ||
160 | |||
161 | /* | ||
162 | * truncate how much we need to iterate over in the | ||
163 | * ucode update loop below | ||
164 | */ | ||
165 | left = *cont_sz - offset; | ||
128 | break; | 166 | break; |
167 | } | ||
129 | 168 | ||
130 | /* | 169 | /* |
131 | * support multiple container files appended together. if this | 170 | * support multiple container files appended together. if this |
@@ -145,19 +184,18 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) | |||
145 | 184 | ||
146 | /* mark where the next microcode container file starts */ | 185 | /* mark where the next microcode container file starts */ |
147 | offset = data - (u8 *)ucode; | 186 | offset = data - (u8 *)ucode; |
148 | *uoffset += offset; | ||
149 | *usize -= offset; | ||
150 | ucode = data; | 187 | ucode = data; |
151 | } | 188 | } |
152 | 189 | ||
153 | if (!eq_id) { | 190 | if (!eq_id) { |
154 | *usize = 0; | 191 | *cont = NULL; |
192 | *cont_sz = 0; | ||
155 | return; | 193 | return; |
156 | } | 194 | } |
157 | 195 | ||
158 | /* find ucode and update if needed */ | 196 | /* find ucode and update if needed */ |
159 | 197 | ||
160 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | 198 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); |
161 | 199 | ||
162 | while (left > 0) { | 200 | while (left > 0) { |
163 | struct microcode_amd *mc; | 201 | struct microcode_amd *mc; |
@@ -168,73 +206,83 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) | |||
168 | break; | 206 | break; |
169 | 207 | ||
170 | mc = (struct microcode_amd *)(data + SECTION_HDR_SIZE); | 208 | mc = (struct microcode_amd *)(data + SECTION_HDR_SIZE); |
171 | if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id) | 209 | |
172 | if (__apply_microcode_amd(mc) == 0) { | 210 | if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id) { |
211 | |||
212 | if (!__apply_microcode_amd(mc)) { | ||
173 | rev = mc->hdr.patch_id; | 213 | rev = mc->hdr.patch_id; |
174 | *new_rev = rev; | 214 | *new_rev = rev; |
215 | |||
216 | /* save ucode patch */ | ||
217 | memcpy(amd_ucode_patch, mc, | ||
218 | min_t(u32, header[1], PATCH_MAX_SIZE)); | ||
175 | } | 219 | } |
220 | } | ||
176 | 221 | ||
177 | offset = header[1] + SECTION_HDR_SIZE; | 222 | offset = header[1] + SECTION_HDR_SIZE; |
178 | data += offset; | 223 | data += offset; |
179 | left -= offset; | 224 | left -= offset; |
180 | } | 225 | } |
181 | |||
182 | /* mark where this microcode container file ends */ | ||
183 | offset = *usize - (data - (u8 *)ucode); | ||
184 | *usize -= offset; | ||
185 | |||
186 | if (!(*new_rev)) | ||
187 | *usize = 0; | ||
188 | } | 226 | } |
189 | 227 | ||
190 | void __init load_ucode_amd_bsp(void) | 228 | void __init load_ucode_amd_bsp(void) |
191 | { | 229 | { |
192 | struct cpio_data cd = find_ucode_in_initrd(); | 230 | struct cpio_data cp; |
193 | if (!cd.data) | 231 | void **data; |
232 | size_t *size; | ||
233 | |||
234 | #ifdef CONFIG_X86_32 | ||
235 | data = (void **)__pa_nodebug(&ucode_cpio.data); | ||
236 | size = (size_t *)__pa_nodebug(&ucode_cpio.size); | ||
237 | #else | ||
238 | data = &ucode_cpio.data; | ||
239 | size = &ucode_cpio.size; | ||
240 | #endif | ||
241 | |||
242 | cp = find_ucode_in_initrd(); | ||
243 | if (!cp.data) | ||
194 | return; | 244 | return; |
195 | 245 | ||
196 | apply_ucode_in_initrd(cd.data, cd.size); | 246 | *data = cp.data; |
247 | *size = cp.size; | ||
248 | |||
249 | apply_ucode_in_initrd(cp.data, cp.size); | ||
197 | } | 250 | } |
198 | 251 | ||
199 | #ifdef CONFIG_X86_32 | 252 | #ifdef CONFIG_X86_32 |
200 | u8 amd_bsp_mpb[MPB_MAX_SIZE]; | ||
201 | |||
202 | /* | 253 | /* |
203 | * On 32-bit, since AP's early load occurs before paging is turned on, we | 254 | * On 32-bit, since AP's early load occurs before paging is turned on, we |
204 | * cannot traverse cpu_equiv_table and pcache in kernel heap memory. So during | 255 | * cannot traverse cpu_equiv_table and pcache in kernel heap memory. So during |
205 | * cold boot, AP will apply_ucode_in_initrd() just like the BSP. During | 256 | * cold boot, AP will apply_ucode_in_initrd() just like the BSP. During |
206 | * save_microcode_in_initrd_amd() BSP's patch is copied to amd_bsp_mpb, which | 257 | * save_microcode_in_initrd_amd() BSP's patch is copied to amd_ucode_patch, |
207 | * is used upon resume from suspend. | 258 | * which is used upon resume from suspend. |
208 | */ | 259 | */ |
209 | void load_ucode_amd_ap(void) | 260 | void load_ucode_amd_ap(void) |
210 | { | 261 | { |
211 | struct microcode_amd *mc; | 262 | struct microcode_amd *mc; |
212 | unsigned long *initrd; | ||
213 | unsigned long *uoffset; | ||
214 | size_t *usize; | 263 | size_t *usize; |
215 | void *ucode; | 264 | void **ucode; |
216 | 265 | ||
217 | mc = (struct microcode_amd *)__pa(amd_bsp_mpb); | 266 | mc = (struct microcode_amd *)__pa(amd_ucode_patch); |
218 | if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { | 267 | if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { |
219 | __apply_microcode_amd(mc); | 268 | __apply_microcode_amd(mc); |
220 | return; | 269 | return; |
221 | } | 270 | } |
222 | 271 | ||
223 | initrd = (unsigned long *)__pa(&initrd_start); | 272 | ucode = (void *)__pa_nodebug(&container); |
224 | uoffset = (unsigned long *)__pa(&ucode_offset); | 273 | usize = (size_t *)__pa_nodebug(&container_size); |
225 | usize = (size_t *)__pa(&ucode_size); | ||
226 | 274 | ||
227 | if (!*usize || !*initrd) | 275 | if (!*ucode || !*usize) |
228 | return; | 276 | return; |
229 | 277 | ||
230 | ucode = (void *)((unsigned long)__pa(*initrd) + *uoffset); | 278 | apply_ucode_in_initrd(*ucode, *usize); |
231 | apply_ucode_in_initrd(ucode, *usize); | ||
232 | } | 279 | } |
233 | 280 | ||
234 | static void __init collect_cpu_sig_on_bsp(void *arg) | 281 | static void __init collect_cpu_sig_on_bsp(void *arg) |
235 | { | 282 | { |
236 | unsigned int cpu = smp_processor_id(); | 283 | unsigned int cpu = smp_processor_id(); |
237 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 284 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
285 | |||
238 | uci->cpu_sig.sig = cpuid_eax(0x00000001); | 286 | uci->cpu_sig.sig = cpuid_eax(0x00000001); |
239 | } | 287 | } |
240 | #else | 288 | #else |
@@ -242,36 +290,54 @@ void load_ucode_amd_ap(void) | |||
242 | { | 290 | { |
243 | unsigned int cpu = smp_processor_id(); | 291 | unsigned int cpu = smp_processor_id(); |
244 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 292 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
293 | struct equiv_cpu_entry *eq; | ||
294 | struct microcode_amd *mc; | ||
245 | u32 rev, eax; | 295 | u32 rev, eax; |
296 | u16 eq_id; | ||
297 | |||
298 | /* Exit if called on the BSP. */ | ||
299 | if (!cpu) | ||
300 | return; | ||
301 | |||
302 | if (!container) | ||
303 | return; | ||
246 | 304 | ||
247 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | 305 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); |
248 | eax = cpuid_eax(0x00000001); | ||
249 | 306 | ||
250 | uci->cpu_sig.rev = rev; | 307 | uci->cpu_sig.rev = rev; |
251 | uci->cpu_sig.sig = eax; | 308 | uci->cpu_sig.sig = eax; |
252 | 309 | ||
253 | if (cpu && !ucode_loaded) { | 310 | eax = cpuid_eax(0x00000001); |
254 | void *ucode; | 311 | eq = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ); |
255 | 312 | ||
256 | if (!ucode_size || !initrd_start) | 313 | eq_id = find_equiv_id(eq, eax); |
257 | return; | 314 | if (!eq_id) |
315 | return; | ||
316 | |||
317 | if (eq_id == this_equiv_id) { | ||
318 | mc = (struct microcode_amd *)amd_ucode_patch; | ||
258 | 319 | ||
259 | ucode = (void *)(initrd_start + ucode_offset); | 320 | if (mc && rev < mc->hdr.patch_id) { |
260 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); | 321 | if (!__apply_microcode_amd(mc)) |
261 | if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK) | 322 | ucode_new_rev = mc->hdr.patch_id; |
323 | } | ||
324 | |||
325 | } else { | ||
326 | if (!ucode_cpio.data) | ||
262 | return; | 327 | return; |
263 | 328 | ||
264 | ucode_loaded = true; | 329 | /* |
330 | * AP has a different equivalence ID than BSP, looks like | ||
331 | * mixed-steppings silicon so go through the ucode blob anew. | ||
332 | */ | ||
333 | apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size); | ||
265 | } | 334 | } |
266 | |||
267 | apply_microcode_amd(cpu); | ||
268 | } | 335 | } |
269 | #endif | 336 | #endif |
270 | 337 | ||
271 | int __init save_microcode_in_initrd_amd(void) | 338 | int __init save_microcode_in_initrd_amd(void) |
272 | { | 339 | { |
273 | enum ucode_state ret; | 340 | enum ucode_state ret; |
274 | void *ucode; | ||
275 | u32 eax; | 341 | u32 eax; |
276 | 342 | ||
277 | #ifdef CONFIG_X86_32 | 343 | #ifdef CONFIG_X86_32 |
@@ -280,22 +346,35 @@ int __init save_microcode_in_initrd_amd(void) | |||
280 | 346 | ||
281 | if (!uci->cpu_sig.sig) | 347 | if (!uci->cpu_sig.sig) |
282 | smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1); | 348 | smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1); |
349 | |||
350 | /* | ||
351 | * Take into account the fact that the ramdisk might get relocated | ||
352 | * and therefore we need to recompute the container's position in | ||
353 | * virtual memory space. | ||
354 | */ | ||
355 | container = (u8 *)(__va((u32)relocated_ramdisk) + | ||
356 | ((u32)container - boot_params.hdr.ramdisk_image)); | ||
283 | #endif | 357 | #endif |
284 | if (ucode_new_rev) | 358 | if (ucode_new_rev) |
285 | pr_info("microcode: updated early to new patch_level=0x%08x\n", | 359 | pr_info("microcode: updated early to new patch_level=0x%08x\n", |
286 | ucode_new_rev); | 360 | ucode_new_rev); |
287 | 361 | ||
288 | if (ucode_loaded || !ucode_size || !initrd_start) | 362 | if (!container) |
289 | return 0; | 363 | return -EINVAL; |
290 | 364 | ||
291 | ucode = (void *)(initrd_start + ucode_offset); | ||
292 | eax = cpuid_eax(0x00000001); | 365 | eax = cpuid_eax(0x00000001); |
293 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); | 366 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); |
294 | 367 | ||
295 | ret = load_microcode_amd(eax, ucode, ucode_size); | 368 | ret = load_microcode_amd(eax, container, container_size); |
296 | if (ret != UCODE_OK) | 369 | if (ret != UCODE_OK) |
297 | return -EINVAL; | 370 | return -EINVAL; |
298 | 371 | ||
299 | ucode_loaded = true; | 372 | /* |
373 | * This will be freed any msec now, stash patches for the current | ||
374 | * family and switch to patch cache for cpu hotplug, etc later. | ||
375 | */ | ||
376 | container = NULL; | ||
377 | container_size = 0; | ||
378 | |||
300 | return 0; | 379 | return 0; |
301 | } | 380 | } |
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/cpu/microcode/core.c index 15c987698b0f..15c987698b0f 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/cpu/microcode/core.c | |||
diff --git a/arch/x86/kernel/microcode_core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c index be7f8514f577..be7f8514f577 100644 --- a/arch/x86/kernel/microcode_core_early.c +++ b/arch/x86/kernel/cpu/microcode/core_early.c | |||
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 5fb2cebf556b..5fb2cebf556b 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c | |||
diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 1575deb2e636..18f739129e72 100644 --- a/arch/x86/kernel/microcode_intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c | |||
@@ -365,16 +365,6 @@ out: | |||
365 | return state; | 365 | return state; |
366 | } | 366 | } |
367 | 367 | ||
368 | #define native_rdmsr(msr, val1, val2) \ | ||
369 | do { \ | ||
370 | u64 __val = native_read_msr((msr)); \ | ||
371 | (void)((val1) = (u32)__val); \ | ||
372 | (void)((val2) = (u32)(__val >> 32)); \ | ||
373 | } while (0) | ||
374 | |||
375 | #define native_wrmsr(msr, low, high) \ | ||
376 | native_write_msr(msr, low, high); | ||
377 | |||
378 | static int collect_cpu_info_early(struct ucode_cpu_info *uci) | 368 | static int collect_cpu_info_early(struct ucode_cpu_info *uci) |
379 | { | 369 | { |
380 | unsigned int val[2]; | 370 | unsigned int val[2]; |
diff --git a/arch/x86/kernel/microcode_intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c index ce69320d0179..ce69320d0179 100644 --- a/arch/x86/kernel/microcode_intel_lib.c +++ b/arch/x86/kernel/cpu/microcode/intel_lib.c | |||
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 8e132931614d..b88645191fe5 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1883,21 +1883,27 @@ static struct pmu pmu = { | |||
1883 | 1883 | ||
1884 | void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) | 1884 | void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) |
1885 | { | 1885 | { |
1886 | struct cyc2ns_data *data; | ||
1887 | |||
1886 | userpg->cap_user_time = 0; | 1888 | userpg->cap_user_time = 0; |
1887 | userpg->cap_user_time_zero = 0; | 1889 | userpg->cap_user_time_zero = 0; |
1888 | userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc; | 1890 | userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc; |
1889 | userpg->pmc_width = x86_pmu.cntval_bits; | 1891 | userpg->pmc_width = x86_pmu.cntval_bits; |
1890 | 1892 | ||
1891 | if (!sched_clock_stable) | 1893 | if (!sched_clock_stable()) |
1892 | return; | 1894 | return; |
1893 | 1895 | ||
1896 | data = cyc2ns_read_begin(); | ||
1897 | |||
1894 | userpg->cap_user_time = 1; | 1898 | userpg->cap_user_time = 1; |
1895 | userpg->time_mult = this_cpu_read(cyc2ns); | 1899 | userpg->time_mult = data->cyc2ns_mul; |
1896 | userpg->time_shift = CYC2NS_SCALE_FACTOR; | 1900 | userpg->time_shift = data->cyc2ns_shift; |
1897 | userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; | 1901 | userpg->time_offset = data->cyc2ns_offset - now; |
1898 | 1902 | ||
1899 | userpg->cap_user_time_zero = 1; | 1903 | userpg->cap_user_time_zero = 1; |
1900 | userpg->time_zero = this_cpu_read(cyc2ns_offset); | 1904 | userpg->time_zero = data->cyc2ns_offset; |
1905 | |||
1906 | cyc2ns_read_end(data); | ||
1901 | } | 1907 | } |
1902 | 1908 | ||
1903 | /* | 1909 | /* |
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index e09f0bfb7b8f..4b8e4d3cd6ea 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
12 | #include <linux/ptrace.h> | 12 | #include <linux/ptrace.h> |
13 | #include <linux/syscore_ops.h> | ||
13 | 14 | ||
14 | #include <asm/apic.h> | 15 | #include <asm/apic.h> |
15 | 16 | ||
@@ -816,6 +817,18 @@ out: | |||
816 | return ret; | 817 | return ret; |
817 | } | 818 | } |
818 | 819 | ||
820 | static void ibs_eilvt_setup(void) | ||
821 | { | ||
822 | /* | ||
823 | * Force LVT offset assignment for family 10h: The offsets are | ||
824 | * not assigned by the BIOS for this family, so the OS is | ||
825 | * responsible for doing it. If the OS assignment fails, fall | ||
826 | * back to BIOS settings and try to setup this. | ||
827 | */ | ||
828 | if (boot_cpu_data.x86 == 0x10) | ||
829 | force_ibs_eilvt_setup(); | ||
830 | } | ||
831 | |||
819 | static inline int get_ibs_lvt_offset(void) | 832 | static inline int get_ibs_lvt_offset(void) |
820 | { | 833 | { |
821 | u64 val; | 834 | u64 val; |
@@ -851,6 +864,36 @@ static void clear_APIC_ibs(void *dummy) | |||
851 | setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); | 864 | setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); |
852 | } | 865 | } |
853 | 866 | ||
867 | #ifdef CONFIG_PM | ||
868 | |||
869 | static int perf_ibs_suspend(void) | ||
870 | { | ||
871 | clear_APIC_ibs(NULL); | ||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | static void perf_ibs_resume(void) | ||
876 | { | ||
877 | ibs_eilvt_setup(); | ||
878 | setup_APIC_ibs(NULL); | ||
879 | } | ||
880 | |||
881 | static struct syscore_ops perf_ibs_syscore_ops = { | ||
882 | .resume = perf_ibs_resume, | ||
883 | .suspend = perf_ibs_suspend, | ||
884 | }; | ||
885 | |||
886 | static void perf_ibs_pm_init(void) | ||
887 | { | ||
888 | register_syscore_ops(&perf_ibs_syscore_ops); | ||
889 | } | ||
890 | |||
891 | #else | ||
892 | |||
893 | static inline void perf_ibs_pm_init(void) { } | ||
894 | |||
895 | #endif | ||
896 | |||
854 | static int | 897 | static int |
855 | perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) | 898 | perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) |
856 | { | 899 | { |
@@ -877,18 +920,12 @@ static __init int amd_ibs_init(void) | |||
877 | if (!caps) | 920 | if (!caps) |
878 | return -ENODEV; /* ibs not supported by the cpu */ | 921 | return -ENODEV; /* ibs not supported by the cpu */ |
879 | 922 | ||
880 | /* | 923 | ibs_eilvt_setup(); |
881 | * Force LVT offset assignment for family 10h: The offsets are | ||
882 | * not assigned by the BIOS for this family, so the OS is | ||
883 | * responsible for doing it. If the OS assignment fails, fall | ||
884 | * back to BIOS settings and try to setup this. | ||
885 | */ | ||
886 | if (boot_cpu_data.x86 == 0x10) | ||
887 | force_ibs_eilvt_setup(); | ||
888 | 924 | ||
889 | if (!ibs_eilvt_valid()) | 925 | if (!ibs_eilvt_valid()) |
890 | goto out; | 926 | goto out; |
891 | 927 | ||
928 | perf_ibs_pm_init(); | ||
892 | get_online_cpus(); | 929 | get_online_cpus(); |
893 | ibs_caps = caps; | 930 | ibs_caps = caps; |
894 | /* make ibs_caps visible to other cpus: */ | 931 | /* make ibs_caps visible to other cpus: */ |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c new file mode 100644 index 000000000000..5ad35ad94d0f --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c | |||
@@ -0,0 +1,679 @@ | |||
1 | /* | ||
2 | * perf_event_intel_rapl.c: support Intel RAPL energy consumption counters | ||
3 | * Copyright (C) 2013 Google, Inc., Stephane Eranian | ||
4 | * | ||
5 | * Intel RAPL interface is specified in the IA-32 Manual Vol3b | ||
6 | * section 14.7.1 (September 2013) | ||
7 | * | ||
8 | * RAPL provides more controls than just reporting energy consumption | ||
9 | * however here we only expose the 3 energy consumption free running | ||
10 | * counters (pp0, pkg, dram). | ||
11 | * | ||
12 | * Each of those counters increments in a power unit defined by the | ||
13 | * RAPL_POWER_UNIT MSR. On SandyBridge, this unit is 1/(2^16) Joules | ||
14 | * but it can vary. | ||
15 | * | ||
16 | * Counter to rapl events mappings: | ||
17 | * | ||
18 | * pp0 counter: consumption of all physical cores (power plane 0) | ||
19 | * event: rapl_energy_cores | ||
20 | * perf code: 0x1 | ||
21 | * | ||
22 | * pkg counter: consumption of the whole processor package | ||
23 | * event: rapl_energy_pkg | ||
24 | * perf code: 0x2 | ||
25 | * | ||
26 | * dram counter: consumption of the dram domain (servers only) | ||
27 | * event: rapl_energy_dram | ||
28 | * perf code: 0x3 | ||
29 | * | ||
30 | * dram counter: consumption of the builtin-gpu domain (client only) | ||
31 | * event: rapl_energy_gpu | ||
32 | * perf code: 0x4 | ||
33 | * | ||
34 | * We manage those counters as free running (read-only). They may be | ||
35 | * use simultaneously by other tools, such as turbostat. | ||
36 | * | ||
37 | * The events only support system-wide mode counting. There is no | ||
38 | * sampling support because it does not make sense and is not | ||
39 | * supported by the RAPL hardware. | ||
40 | * | ||
41 | * Because we want to avoid floating-point operations in the kernel, | ||
42 | * the events are all reported in fixed point arithmetic (32.32). | ||
43 | * Tools must adjust the counts to convert them to Watts using | ||
44 | * the duration of the measurement. Tools may use a function such as | ||
45 | * ldexp(raw_count, -32); | ||
46 | */ | ||
47 | #include <linux/module.h> | ||
48 | #include <linux/slab.h> | ||
49 | #include <linux/perf_event.h> | ||
50 | #include <asm/cpu_device_id.h> | ||
51 | #include "perf_event.h" | ||
52 | |||
53 | /* | ||
54 | * RAPL energy status counters | ||
55 | */ | ||
56 | #define RAPL_IDX_PP0_NRG_STAT 0 /* all cores */ | ||
57 | #define INTEL_RAPL_PP0 0x1 /* pseudo-encoding */ | ||
58 | #define RAPL_IDX_PKG_NRG_STAT 1 /* entire package */ | ||
59 | #define INTEL_RAPL_PKG 0x2 /* pseudo-encoding */ | ||
60 | #define RAPL_IDX_RAM_NRG_STAT 2 /* DRAM */ | ||
61 | #define INTEL_RAPL_RAM 0x3 /* pseudo-encoding */ | ||
62 | #define RAPL_IDX_PP1_NRG_STAT 3 /* DRAM */ | ||
63 | #define INTEL_RAPL_PP1 0x4 /* pseudo-encoding */ | ||
64 | |||
65 | /* Clients have PP0, PKG */ | ||
66 | #define RAPL_IDX_CLN (1<<RAPL_IDX_PP0_NRG_STAT|\ | ||
67 | 1<<RAPL_IDX_PKG_NRG_STAT|\ | ||
68 | 1<<RAPL_IDX_PP1_NRG_STAT) | ||
69 | |||
70 | /* Servers have PP0, PKG, RAM */ | ||
71 | #define RAPL_IDX_SRV (1<<RAPL_IDX_PP0_NRG_STAT|\ | ||
72 | 1<<RAPL_IDX_PKG_NRG_STAT|\ | ||
73 | 1<<RAPL_IDX_RAM_NRG_STAT) | ||
74 | |||
75 | /* | ||
76 | * event code: LSB 8 bits, passed in attr->config | ||
77 | * any other bit is reserved | ||
78 | */ | ||
79 | #define RAPL_EVENT_MASK 0xFFULL | ||
80 | |||
81 | #define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format) \ | ||
82 | static ssize_t __rapl_##_var##_show(struct kobject *kobj, \ | ||
83 | struct kobj_attribute *attr, \ | ||
84 | char *page) \ | ||
85 | { \ | ||
86 | BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ | ||
87 | return sprintf(page, _format "\n"); \ | ||
88 | } \ | ||
89 | static struct kobj_attribute format_attr_##_var = \ | ||
90 | __ATTR(_name, 0444, __rapl_##_var##_show, NULL) | ||
91 | |||
92 | #define RAPL_EVENT_DESC(_name, _config) \ | ||
93 | { \ | ||
94 | .attr = __ATTR(_name, 0444, rapl_event_show, NULL), \ | ||
95 | .config = _config, \ | ||
96 | } | ||
97 | |||
98 | #define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */ | ||
99 | |||
100 | struct rapl_pmu { | ||
101 | spinlock_t lock; | ||
102 | int hw_unit; /* 1/2^hw_unit Joule */ | ||
103 | int n_active; /* number of active events */ | ||
104 | struct list_head active_list; | ||
105 | struct pmu *pmu; /* pointer to rapl_pmu_class */ | ||
106 | ktime_t timer_interval; /* in ktime_t unit */ | ||
107 | struct hrtimer hrtimer; | ||
108 | }; | ||
109 | |||
110 | static struct pmu rapl_pmu_class; | ||
111 | static cpumask_t rapl_cpu_mask; | ||
112 | static int rapl_cntr_mask; | ||
113 | |||
114 | static DEFINE_PER_CPU(struct rapl_pmu *, rapl_pmu); | ||
115 | static DEFINE_PER_CPU(struct rapl_pmu *, rapl_pmu_to_free); | ||
116 | |||
117 | static inline u64 rapl_read_counter(struct perf_event *event) | ||
118 | { | ||
119 | u64 raw; | ||
120 | rdmsrl(event->hw.event_base, raw); | ||
121 | return raw; | ||
122 | } | ||
123 | |||
124 | static inline u64 rapl_scale(u64 v) | ||
125 | { | ||
126 | /* | ||
127 | * scale delta to smallest unit (1/2^32) | ||
128 | * users must then scale back: count * 1/(1e9*2^32) to get Joules | ||
129 | * or use ldexp(count, -32). | ||
130 | * Watts = Joules/Time delta | ||
131 | */ | ||
132 | return v << (32 - __get_cpu_var(rapl_pmu)->hw_unit); | ||
133 | } | ||
134 | |||
135 | static u64 rapl_event_update(struct perf_event *event) | ||
136 | { | ||
137 | struct hw_perf_event *hwc = &event->hw; | ||
138 | u64 prev_raw_count, new_raw_count; | ||
139 | s64 delta, sdelta; | ||
140 | int shift = RAPL_CNTR_WIDTH; | ||
141 | |||
142 | again: | ||
143 | prev_raw_count = local64_read(&hwc->prev_count); | ||
144 | rdmsrl(event->hw.event_base, new_raw_count); | ||
145 | |||
146 | if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, | ||
147 | new_raw_count) != prev_raw_count) { | ||
148 | cpu_relax(); | ||
149 | goto again; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Now we have the new raw value and have updated the prev | ||
154 | * timestamp already. We can now calculate the elapsed delta | ||
155 | * (event-)time and add that to the generic event. | ||
156 | * | ||
157 | * Careful, not all hw sign-extends above the physical width | ||
158 | * of the count. | ||
159 | */ | ||
160 | delta = (new_raw_count << shift) - (prev_raw_count << shift); | ||
161 | delta >>= shift; | ||
162 | |||
163 | sdelta = rapl_scale(delta); | ||
164 | |||
165 | local64_add(sdelta, &event->count); | ||
166 | |||
167 | return new_raw_count; | ||
168 | } | ||
169 | |||
170 | static void rapl_start_hrtimer(struct rapl_pmu *pmu) | ||
171 | { | ||
172 | __hrtimer_start_range_ns(&pmu->hrtimer, | ||
173 | pmu->timer_interval, 0, | ||
174 | HRTIMER_MODE_REL_PINNED, 0); | ||
175 | } | ||
176 | |||
177 | static void rapl_stop_hrtimer(struct rapl_pmu *pmu) | ||
178 | { | ||
179 | hrtimer_cancel(&pmu->hrtimer); | ||
180 | } | ||
181 | |||
182 | static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer) | ||
183 | { | ||
184 | struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu); | ||
185 | struct perf_event *event; | ||
186 | unsigned long flags; | ||
187 | |||
188 | if (!pmu->n_active) | ||
189 | return HRTIMER_NORESTART; | ||
190 | |||
191 | spin_lock_irqsave(&pmu->lock, flags); | ||
192 | |||
193 | list_for_each_entry(event, &pmu->active_list, active_entry) { | ||
194 | rapl_event_update(event); | ||
195 | } | ||
196 | |||
197 | spin_unlock_irqrestore(&pmu->lock, flags); | ||
198 | |||
199 | hrtimer_forward_now(hrtimer, pmu->timer_interval); | ||
200 | |||
201 | return HRTIMER_RESTART; | ||
202 | } | ||
203 | |||
204 | static void rapl_hrtimer_init(struct rapl_pmu *pmu) | ||
205 | { | ||
206 | struct hrtimer *hr = &pmu->hrtimer; | ||
207 | |||
208 | hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
209 | hr->function = rapl_hrtimer_handle; | ||
210 | } | ||
211 | |||
212 | static void __rapl_pmu_event_start(struct rapl_pmu *pmu, | ||
213 | struct perf_event *event) | ||
214 | { | ||
215 | if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) | ||
216 | return; | ||
217 | |||
218 | event->hw.state = 0; | ||
219 | |||
220 | list_add_tail(&event->active_entry, &pmu->active_list); | ||
221 | |||
222 | local64_set(&event->hw.prev_count, rapl_read_counter(event)); | ||
223 | |||
224 | pmu->n_active++; | ||
225 | if (pmu->n_active == 1) | ||
226 | rapl_start_hrtimer(pmu); | ||
227 | } | ||
228 | |||
229 | static void rapl_pmu_event_start(struct perf_event *event, int mode) | ||
230 | { | ||
231 | struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu); | ||
232 | unsigned long flags; | ||
233 | |||
234 | spin_lock_irqsave(&pmu->lock, flags); | ||
235 | __rapl_pmu_event_start(pmu, event); | ||
236 | spin_unlock_irqrestore(&pmu->lock, flags); | ||
237 | } | ||
238 | |||
239 | static void rapl_pmu_event_stop(struct perf_event *event, int mode) | ||
240 | { | ||
241 | struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu); | ||
242 | struct hw_perf_event *hwc = &event->hw; | ||
243 | unsigned long flags; | ||
244 | |||
245 | spin_lock_irqsave(&pmu->lock, flags); | ||
246 | |||
247 | /* mark event as deactivated and stopped */ | ||
248 | if (!(hwc->state & PERF_HES_STOPPED)) { | ||
249 | WARN_ON_ONCE(pmu->n_active <= 0); | ||
250 | pmu->n_active--; | ||
251 | if (pmu->n_active == 0) | ||
252 | rapl_stop_hrtimer(pmu); | ||
253 | |||
254 | list_del(&event->active_entry); | ||
255 | |||
256 | WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); | ||
257 | hwc->state |= PERF_HES_STOPPED; | ||
258 | } | ||
259 | |||
260 | /* check if update of sw counter is necessary */ | ||
261 | if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { | ||
262 | /* | ||
263 | * Drain the remaining delta count out of a event | ||
264 | * that we are disabling: | ||
265 | */ | ||
266 | rapl_event_update(event); | ||
267 | hwc->state |= PERF_HES_UPTODATE; | ||
268 | } | ||
269 | |||
270 | spin_unlock_irqrestore(&pmu->lock, flags); | ||
271 | } | ||
272 | |||
273 | static int rapl_pmu_event_add(struct perf_event *event, int mode) | ||
274 | { | ||
275 | struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu); | ||
276 | struct hw_perf_event *hwc = &event->hw; | ||
277 | unsigned long flags; | ||
278 | |||
279 | spin_lock_irqsave(&pmu->lock, flags); | ||
280 | |||
281 | hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED; | ||
282 | |||
283 | if (mode & PERF_EF_START) | ||
284 | __rapl_pmu_event_start(pmu, event); | ||
285 | |||
286 | spin_unlock_irqrestore(&pmu->lock, flags); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static void rapl_pmu_event_del(struct perf_event *event, int flags) | ||
292 | { | ||
293 | rapl_pmu_event_stop(event, PERF_EF_UPDATE); | ||
294 | } | ||
295 | |||
296 | static int rapl_pmu_event_init(struct perf_event *event) | ||
297 | { | ||
298 | u64 cfg = event->attr.config & RAPL_EVENT_MASK; | ||
299 | int bit, msr, ret = 0; | ||
300 | |||
301 | /* only look at RAPL events */ | ||
302 | if (event->attr.type != rapl_pmu_class.type) | ||
303 | return -ENOENT; | ||
304 | |||
305 | /* check only supported bits are set */ | ||
306 | if (event->attr.config & ~RAPL_EVENT_MASK) | ||
307 | return -EINVAL; | ||
308 | |||
309 | /* | ||
310 | * check event is known (determines counter) | ||
311 | */ | ||
312 | switch (cfg) { | ||
313 | case INTEL_RAPL_PP0: | ||
314 | bit = RAPL_IDX_PP0_NRG_STAT; | ||
315 | msr = MSR_PP0_ENERGY_STATUS; | ||
316 | break; | ||
317 | case INTEL_RAPL_PKG: | ||
318 | bit = RAPL_IDX_PKG_NRG_STAT; | ||
319 | msr = MSR_PKG_ENERGY_STATUS; | ||
320 | break; | ||
321 | case INTEL_RAPL_RAM: | ||
322 | bit = RAPL_IDX_RAM_NRG_STAT; | ||
323 | msr = MSR_DRAM_ENERGY_STATUS; | ||
324 | break; | ||
325 | case INTEL_RAPL_PP1: | ||
326 | bit = RAPL_IDX_PP1_NRG_STAT; | ||
327 | msr = MSR_PP1_ENERGY_STATUS; | ||
328 | break; | ||
329 | default: | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | /* check event supported */ | ||
333 | if (!(rapl_cntr_mask & (1 << bit))) | ||
334 | return -EINVAL; | ||
335 | |||
336 | /* unsupported modes and filters */ | ||
337 | if (event->attr.exclude_user || | ||
338 | event->attr.exclude_kernel || | ||
339 | event->attr.exclude_hv || | ||
340 | event->attr.exclude_idle || | ||
341 | event->attr.exclude_host || | ||
342 | event->attr.exclude_guest || | ||
343 | event->attr.sample_period) /* no sampling */ | ||
344 | return -EINVAL; | ||
345 | |||
346 | /* must be done before validate_group */ | ||
347 | event->hw.event_base = msr; | ||
348 | event->hw.config = cfg; | ||
349 | event->hw.idx = bit; | ||
350 | |||
351 | return ret; | ||
352 | } | ||
353 | |||
354 | static void rapl_pmu_event_read(struct perf_event *event) | ||
355 | { | ||
356 | rapl_event_update(event); | ||
357 | } | ||
358 | |||
359 | static ssize_t rapl_get_attr_cpumask(struct device *dev, | ||
360 | struct device_attribute *attr, char *buf) | ||
361 | { | ||
362 | int n = cpulist_scnprintf(buf, PAGE_SIZE - 2, &rapl_cpu_mask); | ||
363 | |||
364 | buf[n++] = '\n'; | ||
365 | buf[n] = '\0'; | ||
366 | return n; | ||
367 | } | ||
368 | |||
369 | static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL); | ||
370 | |||
371 | static struct attribute *rapl_pmu_attrs[] = { | ||
372 | &dev_attr_cpumask.attr, | ||
373 | NULL, | ||
374 | }; | ||
375 | |||
376 | static struct attribute_group rapl_pmu_attr_group = { | ||
377 | .attrs = rapl_pmu_attrs, | ||
378 | }; | ||
379 | |||
380 | EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01"); | ||
381 | EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02"); | ||
382 | EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03"); | ||
383 | EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04"); | ||
384 | |||
385 | EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules"); | ||
386 | EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules"); | ||
387 | EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules"); | ||
388 | EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules"); | ||
389 | |||
390 | /* | ||
391 | * we compute in 0.23 nJ increments regardless of MSR | ||
392 | */ | ||
393 | EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10"); | ||
394 | EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10"); | ||
395 | EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10"); | ||
396 | EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10"); | ||
397 | |||
398 | static struct attribute *rapl_events_srv_attr[] = { | ||
399 | EVENT_PTR(rapl_cores), | ||
400 | EVENT_PTR(rapl_pkg), | ||
401 | EVENT_PTR(rapl_ram), | ||
402 | |||
403 | EVENT_PTR(rapl_cores_unit), | ||
404 | EVENT_PTR(rapl_pkg_unit), | ||
405 | EVENT_PTR(rapl_ram_unit), | ||
406 | |||
407 | EVENT_PTR(rapl_cores_scale), | ||
408 | EVENT_PTR(rapl_pkg_scale), | ||
409 | EVENT_PTR(rapl_ram_scale), | ||
410 | NULL, | ||
411 | }; | ||
412 | |||
413 | static struct attribute *rapl_events_cln_attr[] = { | ||
414 | EVENT_PTR(rapl_cores), | ||
415 | EVENT_PTR(rapl_pkg), | ||
416 | EVENT_PTR(rapl_gpu), | ||
417 | |||
418 | EVENT_PTR(rapl_cores_unit), | ||
419 | EVENT_PTR(rapl_pkg_unit), | ||
420 | EVENT_PTR(rapl_gpu_unit), | ||
421 | |||
422 | EVENT_PTR(rapl_cores_scale), | ||
423 | EVENT_PTR(rapl_pkg_scale), | ||
424 | EVENT_PTR(rapl_gpu_scale), | ||
425 | NULL, | ||
426 | }; | ||
427 | |||
428 | static struct attribute_group rapl_pmu_events_group = { | ||
429 | .name = "events", | ||
430 | .attrs = NULL, /* patched at runtime */ | ||
431 | }; | ||
432 | |||
433 | DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7"); | ||
434 | static struct attribute *rapl_formats_attr[] = { | ||
435 | &format_attr_event.attr, | ||
436 | NULL, | ||
437 | }; | ||
438 | |||
439 | static struct attribute_group rapl_pmu_format_group = { | ||
440 | .name = "format", | ||
441 | .attrs = rapl_formats_attr, | ||
442 | }; | ||
443 | |||
444 | const struct attribute_group *rapl_attr_groups[] = { | ||
445 | &rapl_pmu_attr_group, | ||
446 | &rapl_pmu_format_group, | ||
447 | &rapl_pmu_events_group, | ||
448 | NULL, | ||
449 | }; | ||
450 | |||
451 | static struct pmu rapl_pmu_class = { | ||
452 | .attr_groups = rapl_attr_groups, | ||
453 | .task_ctx_nr = perf_invalid_context, /* system-wide only */ | ||
454 | .event_init = rapl_pmu_event_init, | ||
455 | .add = rapl_pmu_event_add, /* must have */ | ||
456 | .del = rapl_pmu_event_del, /* must have */ | ||
457 | .start = rapl_pmu_event_start, | ||
458 | .stop = rapl_pmu_event_stop, | ||
459 | .read = rapl_pmu_event_read, | ||
460 | }; | ||
461 | |||
462 | static void rapl_cpu_exit(int cpu) | ||
463 | { | ||
464 | struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu); | ||
465 | int i, phys_id = topology_physical_package_id(cpu); | ||
466 | int target = -1; | ||
467 | |||
468 | /* find a new cpu on same package */ | ||
469 | for_each_online_cpu(i) { | ||
470 | if (i == cpu) | ||
471 | continue; | ||
472 | if (phys_id == topology_physical_package_id(i)) { | ||
473 | target = i; | ||
474 | break; | ||
475 | } | ||
476 | } | ||
477 | /* | ||
478 | * clear cpu from cpumask | ||
479 | * if was set in cpumask and still some cpu on package, | ||
480 | * then move to new cpu | ||
481 | */ | ||
482 | if (cpumask_test_and_clear_cpu(cpu, &rapl_cpu_mask) && target >= 0) | ||
483 | cpumask_set_cpu(target, &rapl_cpu_mask); | ||
484 | |||
485 | WARN_ON(cpumask_empty(&rapl_cpu_mask)); | ||
486 | /* | ||
487 | * migrate events and context to new cpu | ||
488 | */ | ||
489 | if (target >= 0) | ||
490 | perf_pmu_migrate_context(pmu->pmu, cpu, target); | ||
491 | |||
492 | /* cancel overflow polling timer for CPU */ | ||
493 | rapl_stop_hrtimer(pmu); | ||
494 | } | ||
495 | |||
496 | static void rapl_cpu_init(int cpu) | ||
497 | { | ||
498 | int i, phys_id = topology_physical_package_id(cpu); | ||
499 | |||
500 | /* check if phys_is is already covered */ | ||
501 | for_each_cpu(i, &rapl_cpu_mask) { | ||
502 | if (phys_id == topology_physical_package_id(i)) | ||
503 | return; | ||
504 | } | ||
505 | /* was not found, so add it */ | ||
506 | cpumask_set_cpu(cpu, &rapl_cpu_mask); | ||
507 | } | ||
508 | |||
509 | static int rapl_cpu_prepare(int cpu) | ||
510 | { | ||
511 | struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu); | ||
512 | int phys_id = topology_physical_package_id(cpu); | ||
513 | u64 ms; | ||
514 | |||
515 | if (pmu) | ||
516 | return 0; | ||
517 | |||
518 | if (phys_id < 0) | ||
519 | return -1; | ||
520 | |||
521 | pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu)); | ||
522 | if (!pmu) | ||
523 | return -1; | ||
524 | |||
525 | spin_lock_init(&pmu->lock); | ||
526 | |||
527 | INIT_LIST_HEAD(&pmu->active_list); | ||
528 | |||
529 | /* | ||
530 | * grab power unit as: 1/2^unit Joules | ||
531 | * | ||
532 | * we cache in local PMU instance | ||
533 | */ | ||
534 | rdmsrl(MSR_RAPL_POWER_UNIT, pmu->hw_unit); | ||
535 | pmu->hw_unit = (pmu->hw_unit >> 8) & 0x1FULL; | ||
536 | pmu->pmu = &rapl_pmu_class; | ||
537 | |||
538 | /* | ||
539 | * use reference of 200W for scaling the timeout | ||
540 | * to avoid missing counter overflows. | ||
541 | * 200W = 200 Joules/sec | ||
542 | * divide interval by 2 to avoid lockstep (2 * 100) | ||
543 | * if hw unit is 32, then we use 2 ms 1/200/2 | ||
544 | */ | ||
545 | if (pmu->hw_unit < 32) | ||
546 | ms = (1000 / (2 * 100)) * (1ULL << (32 - pmu->hw_unit - 1)); | ||
547 | else | ||
548 | ms = 2; | ||
549 | |||
550 | pmu->timer_interval = ms_to_ktime(ms); | ||
551 | |||
552 | rapl_hrtimer_init(pmu); | ||
553 | |||
554 | /* set RAPL pmu for this cpu for now */ | ||
555 | per_cpu(rapl_pmu, cpu) = pmu; | ||
556 | per_cpu(rapl_pmu_to_free, cpu) = NULL; | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static void rapl_cpu_kfree(int cpu) | ||
562 | { | ||
563 | struct rapl_pmu *pmu = per_cpu(rapl_pmu_to_free, cpu); | ||
564 | |||
565 | kfree(pmu); | ||
566 | |||
567 | per_cpu(rapl_pmu_to_free, cpu) = NULL; | ||
568 | } | ||
569 | |||
570 | static int rapl_cpu_dying(int cpu) | ||
571 | { | ||
572 | struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu); | ||
573 | |||
574 | if (!pmu) | ||
575 | return 0; | ||
576 | |||
577 | per_cpu(rapl_pmu, cpu) = NULL; | ||
578 | |||
579 | per_cpu(rapl_pmu_to_free, cpu) = pmu; | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static int rapl_cpu_notifier(struct notifier_block *self, | ||
585 | unsigned long action, void *hcpu) | ||
586 | { | ||
587 | unsigned int cpu = (long)hcpu; | ||
588 | |||
589 | switch (action & ~CPU_TASKS_FROZEN) { | ||
590 | case CPU_UP_PREPARE: | ||
591 | rapl_cpu_prepare(cpu); | ||
592 | break; | ||
593 | case CPU_STARTING: | ||
594 | rapl_cpu_init(cpu); | ||
595 | break; | ||
596 | case CPU_UP_CANCELED: | ||
597 | case CPU_DYING: | ||
598 | rapl_cpu_dying(cpu); | ||
599 | break; | ||
600 | case CPU_ONLINE: | ||
601 | case CPU_DEAD: | ||
602 | rapl_cpu_kfree(cpu); | ||
603 | break; | ||
604 | case CPU_DOWN_PREPARE: | ||
605 | rapl_cpu_exit(cpu); | ||
606 | break; | ||
607 | default: | ||
608 | break; | ||
609 | } | ||
610 | |||
611 | return NOTIFY_OK; | ||
612 | } | ||
613 | |||
614 | static const struct x86_cpu_id rapl_cpu_match[] = { | ||
615 | [0] = { .vendor = X86_VENDOR_INTEL, .family = 6 }, | ||
616 | [1] = {}, | ||
617 | }; | ||
618 | |||
619 | static int __init rapl_pmu_init(void) | ||
620 | { | ||
621 | struct rapl_pmu *pmu; | ||
622 | int cpu, ret; | ||
623 | |||
624 | /* | ||
625 | * check for Intel processor family 6 | ||
626 | */ | ||
627 | if (!x86_match_cpu(rapl_cpu_match)) | ||
628 | return 0; | ||
629 | |||
630 | /* check supported CPU */ | ||
631 | switch (boot_cpu_data.x86_model) { | ||
632 | case 42: /* Sandy Bridge */ | ||
633 | case 58: /* Ivy Bridge */ | ||
634 | case 60: /* Haswell */ | ||
635 | case 69: /* Haswell-Celeron */ | ||
636 | rapl_cntr_mask = RAPL_IDX_CLN; | ||
637 | rapl_pmu_events_group.attrs = rapl_events_cln_attr; | ||
638 | break; | ||
639 | case 45: /* Sandy Bridge-EP */ | ||
640 | case 62: /* IvyTown */ | ||
641 | rapl_cntr_mask = RAPL_IDX_SRV; | ||
642 | rapl_pmu_events_group.attrs = rapl_events_srv_attr; | ||
643 | break; | ||
644 | |||
645 | default: | ||
646 | /* unsupported */ | ||
647 | return 0; | ||
648 | } | ||
649 | get_online_cpus(); | ||
650 | |||
651 | for_each_online_cpu(cpu) { | ||
652 | rapl_cpu_prepare(cpu); | ||
653 | rapl_cpu_init(cpu); | ||
654 | } | ||
655 | |||
656 | perf_cpu_notifier(rapl_cpu_notifier); | ||
657 | |||
658 | ret = perf_pmu_register(&rapl_pmu_class, "power", -1); | ||
659 | if (WARN_ON(ret)) { | ||
660 | pr_info("RAPL PMU detected, registration failed (%d), RAPL PMU disabled\n", ret); | ||
661 | put_online_cpus(); | ||
662 | return -1; | ||
663 | } | ||
664 | |||
665 | pmu = __get_cpu_var(rapl_pmu); | ||
666 | |||
667 | pr_info("RAPL PMU detected, hw unit 2^-%d Joules," | ||
668 | " API unit is 2^-32 Joules," | ||
669 | " %d fixed counters" | ||
670 | " %llu ms ovfl timer\n", | ||
671 | pmu->hw_unit, | ||
672 | hweight32(rapl_cntr_mask), | ||
673 | ktime_to_ms(pmu->timer_interval)); | ||
674 | |||
675 | put_online_cpus(); | ||
676 | |||
677 | return 0; | ||
678 | } | ||
679 | device_initcall(rapl_pmu_init); | ||
diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c index 88db010845cb..384df5105fbc 100644 --- a/arch/x86/kernel/cpu/rdrand.c +++ b/arch/x86/kernel/cpu/rdrand.c | |||
@@ -31,20 +31,6 @@ static int __init x86_rdrand_setup(char *s) | |||
31 | } | 31 | } |
32 | __setup("nordrand", x86_rdrand_setup); | 32 | __setup("nordrand", x86_rdrand_setup); |
33 | 33 | ||
34 | /* We can't use arch_get_random_long() here since alternatives haven't run */ | ||
35 | static inline int rdrand_long(unsigned long *v) | ||
36 | { | ||
37 | int ok; | ||
38 | asm volatile("1: " RDRAND_LONG "\n\t" | ||
39 | "jc 2f\n\t" | ||
40 | "decl %0\n\t" | ||
41 | "jnz 1b\n\t" | ||
42 | "2:" | ||
43 | : "=r" (ok), "=a" (*v) | ||
44 | : "0" (RDRAND_RETRY_LOOPS)); | ||
45 | return ok; | ||
46 | } | ||
47 | |||
48 | /* | 34 | /* |
49 | * Force a reseed cycle; we are architecturally guaranteed a reseed | 35 | * Force a reseed cycle; we are architecturally guaranteed a reseed |
50 | * after no more than 512 128-bit chunks of random data. This also | 36 | * after no more than 512 128-bit chunks of random data. This also |
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index aa0430d69b90..3fa0e5ad86b4 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/mm.h> | 2 | #include <linux/mm.h> |
3 | #include <linux/init.h> | ||
4 | #include <asm/processor.h> | 3 | #include <asm/processor.h> |
5 | #include <asm/msr.h> | 4 | #include <asm/msr.h> |
6 | #include "cpu.h" | 5 | #include "cpu.h" |
diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c index 75c5ad5d35cc..ef9c2a0078bd 100644 --- a/arch/x86/kernel/cpu/umc.c +++ b/arch/x86/kernel/cpu/umc.c | |||
@@ -1,5 +1,4 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/init.h> | ||
3 | #include <asm/processor.h> | 2 | #include <asm/processor.h> |
4 | #include "cpu.h" | 3 | #include "cpu.h" |
5 | 4 | ||
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 18677a90d6a3..a57902efe2d5 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/types.h> | 10 | #include <linux/types.h> |
12 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
13 | #include <linux/smp.h> | 12 | #include <linux/smp.h> |
diff --git a/arch/x86/kernel/doublefault.c b/arch/x86/kernel/doublefault.c index 5d3fe8d36e4a..f6dfd9334b67 100644 --- a/arch/x86/kernel/doublefault.c +++ b/arch/x86/kernel/doublefault.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #include <linux/mm.h> | 1 | #include <linux/mm.h> |
2 | #include <linux/sched.h> | 2 | #include <linux/sched.h> |
3 | #include <linux/init.h> | ||
4 | #include <linux/init_task.h> | 3 | #include <linux/init_task.h> |
5 | #include <linux/fs.h> | 4 | #include <linux/fs.h> |
6 | 5 | ||
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index f66ff162dce8..a67b47c31314 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/sched.h> | 40 | #include <linux/sched.h> |
41 | #include <linux/init.h> | ||
42 | #include <linux/smp.h> | 41 | #include <linux/smp.h> |
43 | 42 | ||
44 | #include <asm/hw_breakpoint.h> | 43 | #include <asm/hw_breakpoint.h> |
diff --git a/arch/x86/kernel/iosf_mbi.c b/arch/x86/kernel/iosf_mbi.c new file mode 100644 index 000000000000..c3aae6672843 --- /dev/null +++ b/arch/x86/kernel/iosf_mbi.c | |||
@@ -0,0 +1,226 @@ | |||
1 | /* | ||
2 | * IOSF-SB MailBox Interface Driver | ||
3 | * Copyright (c) 2013, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * | ||
15 | * The IOSF-SB is a fabric bus available on Atom based SOC's that uses a | ||
16 | * mailbox interface (MBI) to communicate with mutiple devices. This | ||
17 | * driver implements access to this interface for those platforms that can | ||
18 | * enumerate the device using PCI. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/pci.h> | ||
25 | |||
26 | #include <asm/iosf_mbi.h> | ||
27 | |||
28 | static DEFINE_SPINLOCK(iosf_mbi_lock); | ||
29 | |||
30 | static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset) | ||
31 | { | ||
32 | return (op << 24) | (port << 16) | (offset << 8) | MBI_ENABLE; | ||
33 | } | ||
34 | |||
35 | static struct pci_dev *mbi_pdev; /* one mbi device */ | ||
36 | |||
37 | static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr) | ||
38 | { | ||
39 | int result; | ||
40 | |||
41 | if (!mbi_pdev) | ||
42 | return -ENODEV; | ||
43 | |||
44 | if (mcrx) { | ||
45 | result = pci_write_config_dword(mbi_pdev, MBI_MCRX_OFFSET, | ||
46 | mcrx); | ||
47 | if (result < 0) | ||
48 | goto fail_read; | ||
49 | } | ||
50 | |||
51 | result = pci_write_config_dword(mbi_pdev, MBI_MCR_OFFSET, mcr); | ||
52 | if (result < 0) | ||
53 | goto fail_read; | ||
54 | |||
55 | result = pci_read_config_dword(mbi_pdev, MBI_MDR_OFFSET, mdr); | ||
56 | if (result < 0) | ||
57 | goto fail_read; | ||
58 | |||
59 | return 0; | ||
60 | |||
61 | fail_read: | ||
62 | dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result); | ||
63 | return result; | ||
64 | } | ||
65 | |||
66 | static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr) | ||
67 | { | ||
68 | int result; | ||
69 | |||
70 | if (!mbi_pdev) | ||
71 | return -ENODEV; | ||
72 | |||
73 | result = pci_write_config_dword(mbi_pdev, MBI_MDR_OFFSET, mdr); | ||
74 | if (result < 0) | ||
75 | goto fail_write; | ||
76 | |||
77 | if (mcrx) { | ||
78 | result = pci_write_config_dword(mbi_pdev, MBI_MCRX_OFFSET, | ||
79 | mcrx); | ||
80 | if (result < 0) | ||
81 | goto fail_write; | ||
82 | } | ||
83 | |||
84 | result = pci_write_config_dword(mbi_pdev, MBI_MCR_OFFSET, mcr); | ||
85 | if (result < 0) | ||
86 | goto fail_write; | ||
87 | |||
88 | return 0; | ||
89 | |||
90 | fail_write: | ||
91 | dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result); | ||
92 | return result; | ||
93 | } | ||
94 | |||
95 | int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr) | ||
96 | { | ||
97 | u32 mcr, mcrx; | ||
98 | unsigned long flags; | ||
99 | int ret; | ||
100 | |||
101 | /*Access to the GFX unit is handled by GPU code */ | ||
102 | if (port == BT_MBI_UNIT_GFX) { | ||
103 | WARN_ON(1); | ||
104 | return -EPERM; | ||
105 | } | ||
106 | |||
107 | mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO); | ||
108 | mcrx = offset & MBI_MASK_HI; | ||
109 | |||
110 | spin_lock_irqsave(&iosf_mbi_lock, flags); | ||
111 | ret = iosf_mbi_pci_read_mdr(mcrx, mcr, mdr); | ||
112 | spin_unlock_irqrestore(&iosf_mbi_lock, flags); | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | EXPORT_SYMBOL(iosf_mbi_read); | ||
117 | |||
118 | int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr) | ||
119 | { | ||
120 | u32 mcr, mcrx; | ||
121 | unsigned long flags; | ||
122 | int ret; | ||
123 | |||
124 | /*Access to the GFX unit is handled by GPU code */ | ||
125 | if (port == BT_MBI_UNIT_GFX) { | ||
126 | WARN_ON(1); | ||
127 | return -EPERM; | ||
128 | } | ||
129 | |||
130 | mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO); | ||
131 | mcrx = offset & MBI_MASK_HI; | ||
132 | |||
133 | spin_lock_irqsave(&iosf_mbi_lock, flags); | ||
134 | ret = iosf_mbi_pci_write_mdr(mcrx, mcr, mdr); | ||
135 | spin_unlock_irqrestore(&iosf_mbi_lock, flags); | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | EXPORT_SYMBOL(iosf_mbi_write); | ||
140 | |||
141 | int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask) | ||
142 | { | ||
143 | u32 mcr, mcrx; | ||
144 | u32 value; | ||
145 | unsigned long flags; | ||
146 | int ret; | ||
147 | |||
148 | /*Access to the GFX unit is handled by GPU code */ | ||
149 | if (port == BT_MBI_UNIT_GFX) { | ||
150 | WARN_ON(1); | ||
151 | return -EPERM; | ||
152 | } | ||
153 | |||
154 | mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO); | ||
155 | mcrx = offset & MBI_MASK_HI; | ||
156 | |||
157 | spin_lock_irqsave(&iosf_mbi_lock, flags); | ||
158 | |||
159 | /* Read current mdr value */ | ||
160 | ret = iosf_mbi_pci_read_mdr(mcrx, mcr & MBI_RD_MASK, &value); | ||
161 | if (ret < 0) { | ||
162 | spin_unlock_irqrestore(&iosf_mbi_lock, flags); | ||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | /* Apply mask */ | ||
167 | value &= ~mask; | ||
168 | mdr &= mask; | ||
169 | value |= mdr; | ||
170 | |||
171 | /* Write back */ | ||
172 | ret = iosf_mbi_pci_write_mdr(mcrx, mcr | MBI_WR_MASK, value); | ||
173 | |||
174 | spin_unlock_irqrestore(&iosf_mbi_lock, flags); | ||
175 | |||
176 | return ret; | ||
177 | } | ||
178 | EXPORT_SYMBOL(iosf_mbi_modify); | ||
179 | |||
180 | static int iosf_mbi_probe(struct pci_dev *pdev, | ||
181 | const struct pci_device_id *unused) | ||
182 | { | ||
183 | int ret; | ||
184 | |||
185 | ret = pci_enable_device(pdev); | ||
186 | if (ret < 0) { | ||
187 | dev_err(&pdev->dev, "error: could not enable device\n"); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | mbi_pdev = pci_dev_get(pdev); | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = { | ||
196 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F00) }, | ||
197 | { 0, }, | ||
198 | }; | ||
199 | MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids); | ||
200 | |||
201 | static struct pci_driver iosf_mbi_pci_driver = { | ||
202 | .name = "iosf_mbi_pci", | ||
203 | .probe = iosf_mbi_probe, | ||
204 | .id_table = iosf_mbi_pci_ids, | ||
205 | }; | ||
206 | |||
207 | static int __init iosf_mbi_init(void) | ||
208 | { | ||
209 | return pci_register_driver(&iosf_mbi_pci_driver); | ||
210 | } | ||
211 | |||
212 | static void __exit iosf_mbi_exit(void) | ||
213 | { | ||
214 | pci_unregister_driver(&iosf_mbi_pci_driver); | ||
215 | if (mbi_pdev) { | ||
216 | pci_dev_put(mbi_pdev); | ||
217 | mbi_pdev = NULL; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | module_init(iosf_mbi_init); | ||
222 | module_exit(iosf_mbi_exit); | ||
223 | |||
224 | MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>"); | ||
225 | MODULE_DESCRIPTION("IOSF Mailbox Interface accessor"); | ||
226 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 4207e8d1a094..dbb60878b744 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -193,9 +193,13 @@ __visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs) | |||
193 | if (!handle_irq(irq, regs)) { | 193 | if (!handle_irq(irq, regs)) { |
194 | ack_APIC_irq(); | 194 | ack_APIC_irq(); |
195 | 195 | ||
196 | if (printk_ratelimit()) | 196 | if (irq != VECTOR_RETRIGGERED) { |
197 | pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n", | 197 | pr_emerg_ratelimited("%s: %d.%d No irq handler for vector (irq %d)\n", |
198 | __func__, smp_processor_id(), vector, irq); | 198 | __func__, smp_processor_id(), |
199 | vector, irq); | ||
200 | } else { | ||
201 | __this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED); | ||
202 | } | ||
199 | } | 203 | } |
200 | 204 | ||
201 | irq_exit(); | 205 | irq_exit(); |
@@ -414,7 +418,7 @@ void fixup_irqs(void) | |||
414 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { | 418 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { |
415 | unsigned int irr; | 419 | unsigned int irr; |
416 | 420 | ||
417 | if (__this_cpu_read(vector_irq[vector]) < 0) | 421 | if (__this_cpu_read(vector_irq[vector]) <= VECTOR_UNDEFINED) |
418 | continue; | 422 | continue; |
419 | 423 | ||
420 | irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); | 424 | irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); |
@@ -425,11 +429,14 @@ void fixup_irqs(void) | |||
425 | data = irq_desc_get_irq_data(desc); | 429 | data = irq_desc_get_irq_data(desc); |
426 | chip = irq_data_get_irq_chip(data); | 430 | chip = irq_data_get_irq_chip(data); |
427 | raw_spin_lock(&desc->lock); | 431 | raw_spin_lock(&desc->lock); |
428 | if (chip->irq_retrigger) | 432 | if (chip->irq_retrigger) { |
429 | chip->irq_retrigger(data); | 433 | chip->irq_retrigger(data); |
434 | __this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED); | ||
435 | } | ||
430 | raw_spin_unlock(&desc->lock); | 436 | raw_spin_unlock(&desc->lock); |
431 | } | 437 | } |
432 | __this_cpu_write(vector_irq[vector], -1); | 438 | if (__this_cpu_read(vector_irq[vector]) != VECTOR_RETRIGGERED) |
439 | __this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED); | ||
433 | } | 440 | } |
434 | } | 441 | } |
435 | #endif | 442 | #endif |
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index a2a1fbc594ff..7f50156542fb 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -52,7 +52,7 @@ static struct irqaction irq2 = { | |||
52 | }; | 52 | }; |
53 | 53 | ||
54 | DEFINE_PER_CPU(vector_irq_t, vector_irq) = { | 54 | DEFINE_PER_CPU(vector_irq_t, vector_irq) = { |
55 | [0 ... NR_VECTORS - 1] = -1, | 55 | [0 ... NR_VECTORS - 1] = VECTOR_UNDEFINED, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | int vector_used_by_percpu_irq(unsigned int vector) | 58 | int vector_used_by_percpu_irq(unsigned int vector) |
@@ -60,7 +60,7 @@ int vector_used_by_percpu_irq(unsigned int vector) | |||
60 | int cpu; | 60 | int cpu; |
61 | 61 | ||
62 | for_each_online_cpu(cpu) { | 62 | for_each_online_cpu(cpu) { |
63 | if (per_cpu(vector_irq, cpu)[vector] != -1) | 63 | if (per_cpu(vector_irq, cpu)[vector] > VECTOR_UNDEFINED) |
64 | return 1; | 64 | return 1; |
65 | } | 65 | } |
66 | 66 | ||
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 836f8322960e..7ec1d5f8d283 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
40 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
41 | #include <linux/kgdb.h> | 41 | #include <linux/kgdb.h> |
42 | #include <linux/init.h> | ||
43 | #include <linux/smp.h> | 42 | #include <linux/smp.h> |
44 | #include <linux/nmi.h> | 43 | #include <linux/nmi.h> |
45 | #include <linux/hw_breakpoint.h> | 44 | #include <linux/hw_breakpoint.h> |
diff --git a/arch/x86/kernel/ksysfs.c b/arch/x86/kernel/ksysfs.c new file mode 100644 index 000000000000..c2bedaea11f7 --- /dev/null +++ b/arch/x86/kernel/ksysfs.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* | ||
2 | * Architecture specific sysfs attributes in /sys/kernel | ||
3 | * | ||
4 | * Copyright (C) 2007, Intel Corp. | ||
5 | * Huang Ying <ying.huang@intel.com> | ||
6 | * Copyright (C) 2013, 2013 Red Hat, Inc. | ||
7 | * Dave Young <dyoung@redhat.com> | ||
8 | * | ||
9 | * This file is released under the GPLv2 | ||
10 | */ | ||
11 | |||
12 | #include <linux/kobject.h> | ||
13 | #include <linux/string.h> | ||
14 | #include <linux/sysfs.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/stat.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/mm.h> | ||
19 | |||
20 | #include <asm/io.h> | ||
21 | #include <asm/setup.h> | ||
22 | |||
23 | static ssize_t version_show(struct kobject *kobj, | ||
24 | struct kobj_attribute *attr, char *buf) | ||
25 | { | ||
26 | return sprintf(buf, "0x%04x\n", boot_params.hdr.version); | ||
27 | } | ||
28 | |||
29 | static struct kobj_attribute boot_params_version_attr = __ATTR_RO(version); | ||
30 | |||
31 | static ssize_t boot_params_data_read(struct file *fp, struct kobject *kobj, | ||
32 | struct bin_attribute *bin_attr, | ||
33 | char *buf, loff_t off, size_t count) | ||
34 | { | ||
35 | memcpy(buf, (void *)&boot_params + off, count); | ||
36 | return count; | ||
37 | } | ||
38 | |||
39 | static struct bin_attribute boot_params_data_attr = { | ||
40 | .attr = { | ||
41 | .name = "data", | ||
42 | .mode = S_IRUGO, | ||
43 | }, | ||
44 | .read = boot_params_data_read, | ||
45 | .size = sizeof(boot_params), | ||
46 | }; | ||
47 | |||
48 | static struct attribute *boot_params_version_attrs[] = { | ||
49 | &boot_params_version_attr.attr, | ||
50 | NULL, | ||
51 | }; | ||
52 | |||
53 | static struct bin_attribute *boot_params_data_attrs[] = { | ||
54 | &boot_params_data_attr, | ||
55 | NULL, | ||
56 | }; | ||
57 | |||
58 | static struct attribute_group boot_params_attr_group = { | ||
59 | .attrs = boot_params_version_attrs, | ||
60 | .bin_attrs = boot_params_data_attrs, | ||
61 | }; | ||
62 | |||
63 | static int kobj_to_setup_data_nr(struct kobject *kobj, int *nr) | ||
64 | { | ||
65 | const char *name; | ||
66 | |||
67 | name = kobject_name(kobj); | ||
68 | return kstrtoint(name, 10, nr); | ||
69 | } | ||
70 | |||
71 | static int get_setup_data_paddr(int nr, u64 *paddr) | ||
72 | { | ||
73 | int i = 0; | ||
74 | struct setup_data *data; | ||
75 | u64 pa_data = boot_params.hdr.setup_data; | ||
76 | |||
77 | while (pa_data) { | ||
78 | if (nr == i) { | ||
79 | *paddr = pa_data; | ||
80 | return 0; | ||
81 | } | ||
82 | data = ioremap_cache(pa_data, sizeof(*data)); | ||
83 | if (!data) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | pa_data = data->next; | ||
87 | iounmap(data); | ||
88 | i++; | ||
89 | } | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | static int __init get_setup_data_size(int nr, size_t *size) | ||
94 | { | ||
95 | int i = 0; | ||
96 | struct setup_data *data; | ||
97 | u64 pa_data = boot_params.hdr.setup_data; | ||
98 | |||
99 | while (pa_data) { | ||
100 | data = ioremap_cache(pa_data, sizeof(*data)); | ||
101 | if (!data) | ||
102 | return -ENOMEM; | ||
103 | if (nr == i) { | ||
104 | *size = data->len; | ||
105 | iounmap(data); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | pa_data = data->next; | ||
110 | iounmap(data); | ||
111 | i++; | ||
112 | } | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | |||
116 | static ssize_t type_show(struct kobject *kobj, | ||
117 | struct kobj_attribute *attr, char *buf) | ||
118 | { | ||
119 | int nr, ret; | ||
120 | u64 paddr; | ||
121 | struct setup_data *data; | ||
122 | |||
123 | ret = kobj_to_setup_data_nr(kobj, &nr); | ||
124 | if (ret) | ||
125 | return ret; | ||
126 | |||
127 | ret = get_setup_data_paddr(nr, &paddr); | ||
128 | if (ret) | ||
129 | return ret; | ||
130 | data = ioremap_cache(paddr, sizeof(*data)); | ||
131 | if (!data) | ||
132 | return -ENOMEM; | ||
133 | |||
134 | ret = sprintf(buf, "0x%x\n", data->type); | ||
135 | iounmap(data); | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static ssize_t setup_data_data_read(struct file *fp, | ||
140 | struct kobject *kobj, | ||
141 | struct bin_attribute *bin_attr, | ||
142 | char *buf, | ||
143 | loff_t off, size_t count) | ||
144 | { | ||
145 | int nr, ret = 0; | ||
146 | u64 paddr; | ||
147 | struct setup_data *data; | ||
148 | void *p; | ||
149 | |||
150 | ret = kobj_to_setup_data_nr(kobj, &nr); | ||
151 | if (ret) | ||
152 | return ret; | ||
153 | |||
154 | ret = get_setup_data_paddr(nr, &paddr); | ||
155 | if (ret) | ||
156 | return ret; | ||
157 | data = ioremap_cache(paddr, sizeof(*data)); | ||
158 | if (!data) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | if (off > data->len) { | ||
162 | ret = -EINVAL; | ||
163 | goto out; | ||
164 | } | ||
165 | |||
166 | if (count > data->len - off) | ||
167 | count = data->len - off; | ||
168 | |||
169 | if (!count) | ||
170 | goto out; | ||
171 | |||
172 | ret = count; | ||
173 | p = ioremap_cache(paddr + sizeof(*data), data->len); | ||
174 | if (!p) { | ||
175 | ret = -ENOMEM; | ||
176 | goto out; | ||
177 | } | ||
178 | memcpy(buf, p + off, count); | ||
179 | iounmap(p); | ||
180 | out: | ||
181 | iounmap(data); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | static struct kobj_attribute type_attr = __ATTR_RO(type); | ||
186 | |||
187 | static struct bin_attribute data_attr = { | ||
188 | .attr = { | ||
189 | .name = "data", | ||
190 | .mode = S_IRUGO, | ||
191 | }, | ||
192 | .read = setup_data_data_read, | ||
193 | }; | ||
194 | |||
195 | static struct attribute *setup_data_type_attrs[] = { | ||
196 | &type_attr.attr, | ||
197 | NULL, | ||
198 | }; | ||
199 | |||
200 | static struct bin_attribute *setup_data_data_attrs[] = { | ||
201 | &data_attr, | ||
202 | NULL, | ||
203 | }; | ||
204 | |||
205 | static struct attribute_group setup_data_attr_group = { | ||
206 | .attrs = setup_data_type_attrs, | ||
207 | .bin_attrs = setup_data_data_attrs, | ||
208 | }; | ||
209 | |||
210 | static int __init create_setup_data_node(struct kobject *parent, | ||
211 | struct kobject **kobjp, int nr) | ||
212 | { | ||
213 | int ret = 0; | ||
214 | size_t size; | ||
215 | struct kobject *kobj; | ||
216 | char name[16]; /* should be enough for setup_data nodes numbers */ | ||
217 | snprintf(name, 16, "%d", nr); | ||
218 | |||
219 | kobj = kobject_create_and_add(name, parent); | ||
220 | if (!kobj) | ||
221 | return -ENOMEM; | ||
222 | |||
223 | ret = get_setup_data_size(nr, &size); | ||
224 | if (ret) | ||
225 | goto out_kobj; | ||
226 | |||
227 | data_attr.size = size; | ||
228 | ret = sysfs_create_group(kobj, &setup_data_attr_group); | ||
229 | if (ret) | ||
230 | goto out_kobj; | ||
231 | *kobjp = kobj; | ||
232 | |||
233 | return 0; | ||
234 | out_kobj: | ||
235 | kobject_put(kobj); | ||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static void __init cleanup_setup_data_node(struct kobject *kobj) | ||
240 | { | ||
241 | sysfs_remove_group(kobj, &setup_data_attr_group); | ||
242 | kobject_put(kobj); | ||
243 | } | ||
244 | |||
245 | static int __init get_setup_data_total_num(u64 pa_data, int *nr) | ||
246 | { | ||
247 | int ret = 0; | ||
248 | struct setup_data *data; | ||
249 | |||
250 | *nr = 0; | ||
251 | while (pa_data) { | ||
252 | *nr += 1; | ||
253 | data = ioremap_cache(pa_data, sizeof(*data)); | ||
254 | if (!data) { | ||
255 | ret = -ENOMEM; | ||
256 | goto out; | ||
257 | } | ||
258 | pa_data = data->next; | ||
259 | iounmap(data); | ||
260 | } | ||
261 | |||
262 | out: | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | static int __init create_setup_data_nodes(struct kobject *parent) | ||
267 | { | ||
268 | struct kobject *setup_data_kobj, **kobjp; | ||
269 | u64 pa_data; | ||
270 | int i, j, nr, ret = 0; | ||
271 | |||
272 | pa_data = boot_params.hdr.setup_data; | ||
273 | if (!pa_data) | ||
274 | return 0; | ||
275 | |||
276 | setup_data_kobj = kobject_create_and_add("setup_data", parent); | ||
277 | if (!setup_data_kobj) { | ||
278 | ret = -ENOMEM; | ||
279 | goto out; | ||
280 | } | ||
281 | |||
282 | ret = get_setup_data_total_num(pa_data, &nr); | ||
283 | if (ret) | ||
284 | goto out_setup_data_kobj; | ||
285 | |||
286 | kobjp = kmalloc(sizeof(*kobjp) * nr, GFP_KERNEL); | ||
287 | if (!kobjp) { | ||
288 | ret = -ENOMEM; | ||
289 | goto out_setup_data_kobj; | ||
290 | } | ||
291 | |||
292 | for (i = 0; i < nr; i++) { | ||
293 | ret = create_setup_data_node(setup_data_kobj, kobjp + i, i); | ||
294 | if (ret) | ||
295 | goto out_clean_nodes; | ||
296 | } | ||
297 | |||
298 | kfree(kobjp); | ||
299 | return 0; | ||
300 | |||
301 | out_clean_nodes: | ||
302 | for (j = i - 1; j > 0; j--) | ||
303 | cleanup_setup_data_node(*(kobjp + j)); | ||
304 | kfree(kobjp); | ||
305 | out_setup_data_kobj: | ||
306 | kobject_put(setup_data_kobj); | ||
307 | out: | ||
308 | return ret; | ||
309 | } | ||
310 | |||
311 | static int __init boot_params_ksysfs_init(void) | ||
312 | { | ||
313 | int ret; | ||
314 | struct kobject *boot_params_kobj; | ||
315 | |||
316 | boot_params_kobj = kobject_create_and_add("boot_params", | ||
317 | kernel_kobj); | ||
318 | if (!boot_params_kobj) { | ||
319 | ret = -ENOMEM; | ||
320 | goto out; | ||
321 | } | ||
322 | |||
323 | ret = sysfs_create_group(boot_params_kobj, &boot_params_attr_group); | ||
324 | if (ret) | ||
325 | goto out_boot_params_kobj; | ||
326 | |||
327 | ret = create_setup_data_nodes(boot_params_kobj); | ||
328 | if (ret) | ||
329 | goto out_create_group; | ||
330 | |||
331 | return 0; | ||
332 | out_create_group: | ||
333 | sysfs_remove_group(boot_params_kobj, &boot_params_attr_group); | ||
334 | out_boot_params_kobj: | ||
335 | kobject_put(boot_params_kobj); | ||
336 | out: | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | arch_initcall(boot_params_ksysfs_init); | ||
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index 5b19e4d78b00..1667b1de8d5d 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
10 | #include <linux/kexec.h> | 10 | #include <linux/kexec.h> |
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/init.h> | ||
13 | #include <linux/numa.h> | 12 | #include <linux/numa.h> |
14 | #include <linux/ftrace.h> | 13 | #include <linux/ftrace.h> |
15 | #include <linux/suspend.h> | 14 | #include <linux/suspend.h> |
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 871be4a84c7d..da15918d1c81 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c | |||
@@ -3,7 +3,6 @@ | |||
3 | #include <linux/dma-mapping.h> | 3 | #include <linux/dma-mapping.h> |
4 | #include <linux/scatterlist.h> | 4 | #include <linux/scatterlist.h> |
5 | #include <linux/string.h> | 5 | #include <linux/string.h> |
6 | #include <linux/init.h> | ||
7 | #include <linux/gfp.h> | 6 | #include <linux/gfp.h> |
8 | #include <linux/pci.h> | 7 | #include <linux/pci.h> |
9 | #include <linux/mm.h> | 8 | #include <linux/mm.h> |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 6f1236c29c4b..0de43e98ce08 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/reboot.h> | 26 | #include <linux/reboot.h> |
27 | #include <linux/init.h> | ||
28 | #include <linux/mc146818rtc.h> | 27 | #include <linux/mc146818rtc.h> |
29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
30 | #include <linux/kallsyms.h> | 29 | #include <linux/kallsyms.h> |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index cb233bc9dee3..06853e670354 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -295,6 +295,8 @@ static void __init reserve_brk(void) | |||
295 | _brk_start = 0; | 295 | _brk_start = 0; |
296 | } | 296 | } |
297 | 297 | ||
298 | u64 relocated_ramdisk; | ||
299 | |||
298 | #ifdef CONFIG_BLK_DEV_INITRD | 300 | #ifdef CONFIG_BLK_DEV_INITRD |
299 | 301 | ||
300 | static u64 __init get_ramdisk_image(void) | 302 | static u64 __init get_ramdisk_image(void) |
@@ -321,25 +323,24 @@ static void __init relocate_initrd(void) | |||
321 | u64 ramdisk_image = get_ramdisk_image(); | 323 | u64 ramdisk_image = get_ramdisk_image(); |
322 | u64 ramdisk_size = get_ramdisk_size(); | 324 | u64 ramdisk_size = get_ramdisk_size(); |
323 | u64 area_size = PAGE_ALIGN(ramdisk_size); | 325 | u64 area_size = PAGE_ALIGN(ramdisk_size); |
324 | u64 ramdisk_here; | ||
325 | unsigned long slop, clen, mapaddr; | 326 | unsigned long slop, clen, mapaddr; |
326 | char *p, *q; | 327 | char *p, *q; |
327 | 328 | ||
328 | /* We need to move the initrd down into directly mapped mem */ | 329 | /* We need to move the initrd down into directly mapped mem */ |
329 | ramdisk_here = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), | 330 | relocated_ramdisk = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), |
330 | area_size, PAGE_SIZE); | 331 | area_size, PAGE_SIZE); |
331 | 332 | ||
332 | if (!ramdisk_here) | 333 | if (!relocated_ramdisk) |
333 | panic("Cannot find place for new RAMDISK of size %lld\n", | 334 | panic("Cannot find place for new RAMDISK of size %lld\n", |
334 | ramdisk_size); | 335 | ramdisk_size); |
335 | 336 | ||
336 | /* Note: this includes all the mem currently occupied by | 337 | /* Note: this includes all the mem currently occupied by |
337 | the initrd, we rely on that fact to keep the data intact. */ | 338 | the initrd, we rely on that fact to keep the data intact. */ |
338 | memblock_reserve(ramdisk_here, area_size); | 339 | memblock_reserve(relocated_ramdisk, area_size); |
339 | initrd_start = ramdisk_here + PAGE_OFFSET; | 340 | initrd_start = relocated_ramdisk + PAGE_OFFSET; |
340 | initrd_end = initrd_start + ramdisk_size; | 341 | initrd_end = initrd_start + ramdisk_size; |
341 | printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n", | 342 | printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n", |
342 | ramdisk_here, ramdisk_here + ramdisk_size - 1); | 343 | relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1); |
343 | 344 | ||
344 | q = (char *)initrd_start; | 345 | q = (char *)initrd_start; |
345 | 346 | ||
@@ -363,7 +364,7 @@ static void __init relocate_initrd(void) | |||
363 | printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to" | 364 | printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to" |
364 | " [mem %#010llx-%#010llx]\n", | 365 | " [mem %#010llx-%#010llx]\n", |
365 | ramdisk_image, ramdisk_image + ramdisk_size - 1, | 366 | ramdisk_image, ramdisk_image + ramdisk_size - 1, |
366 | ramdisk_here, ramdisk_here + ramdisk_size - 1); | 367 | relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1); |
367 | } | 368 | } |
368 | 369 | ||
369 | static void __init early_reserve_initrd(void) | 370 | static void __init early_reserve_initrd(void) |
@@ -447,6 +448,9 @@ static void __init parse_setup_data(void) | |||
447 | case SETUP_DTB: | 448 | case SETUP_DTB: |
448 | add_dtb(pa_data); | 449 | add_dtb(pa_data); |
449 | break; | 450 | break; |
451 | case SETUP_EFI: | ||
452 | parse_efi_setup(pa_data, data_len); | ||
453 | break; | ||
450 | default: | 454 | default: |
451 | break; | 455 | break; |
452 | } | 456 | } |
@@ -824,6 +828,20 @@ static void __init trim_low_memory_range(void) | |||
824 | } | 828 | } |
825 | 829 | ||
826 | /* | 830 | /* |
831 | * Dump out kernel offset information on panic. | ||
832 | */ | ||
833 | static int | ||
834 | dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) | ||
835 | { | ||
836 | pr_emerg("Kernel Offset: 0x%lx from 0x%lx " | ||
837 | "(relocation range: 0x%lx-0x%lx)\n", | ||
838 | (unsigned long)&_text - __START_KERNEL, __START_KERNEL, | ||
839 | __START_KERNEL_map, MODULES_VADDR-1); | ||
840 | |||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | /* | ||
827 | * Determine if we were loaded by an EFI loader. If so, then we have also been | 845 | * Determine if we were loaded by an EFI loader. If so, then we have also been |
828 | * passed the efi memmap, systab, etc., so we should use these data structures | 846 | * passed the efi memmap, systab, etc., so we should use these data structures |
829 | * for initialization. Note, the efi init code path is determined by the | 847 | * for initialization. Note, the efi init code path is determined by the |
@@ -924,8 +942,6 @@ void __init setup_arch(char **cmdline_p) | |||
924 | iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1; | 942 | iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1; |
925 | setup_memory_map(); | 943 | setup_memory_map(); |
926 | parse_setup_data(); | 944 | parse_setup_data(); |
927 | /* update the e820_saved too */ | ||
928 | e820_reserve_setup_data(); | ||
929 | 945 | ||
930 | copy_edd(); | 946 | copy_edd(); |
931 | 947 | ||
@@ -987,6 +1003,8 @@ void __init setup_arch(char **cmdline_p) | |||
987 | early_dump_pci_devices(); | 1003 | early_dump_pci_devices(); |
988 | #endif | 1004 | #endif |
989 | 1005 | ||
1006 | /* update the e820_saved too */ | ||
1007 | e820_reserve_setup_data(); | ||
990 | finish_e820_parsing(); | 1008 | finish_e820_parsing(); |
991 | 1009 | ||
992 | if (efi_enabled(EFI_BOOT)) | 1010 | if (efi_enabled(EFI_BOOT)) |
@@ -1248,3 +1266,15 @@ void __init i386_reserve_resources(void) | |||
1248 | } | 1266 | } |
1249 | 1267 | ||
1250 | #endif /* CONFIG_X86_32 */ | 1268 | #endif /* CONFIG_X86_32 */ |
1269 | |||
1270 | static struct notifier_block kernel_offset_notifier = { | ||
1271 | .notifier_call = dump_kernel_offset | ||
1272 | }; | ||
1273 | |||
1274 | static int __init register_kernel_offset_dumper(void) | ||
1275 | { | ||
1276 | atomic_notifier_chain_register(&panic_notifier_list, | ||
1277 | &kernel_offset_notifier); | ||
1278 | return 0; | ||
1279 | } | ||
1280 | __initcall(register_kernel_offset_dumper); | ||
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 391ea529dc26..a32da804252e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -1423,7 +1423,9 @@ static inline void mwait_play_dead(void) | |||
1423 | * The WBINVD is insufficient due to the spurious-wakeup | 1423 | * The WBINVD is insufficient due to the spurious-wakeup |
1424 | * case where we return around the loop. | 1424 | * case where we return around the loop. |
1425 | */ | 1425 | */ |
1426 | mb(); | ||
1426 | clflush(mwait_ptr); | 1427 | clflush(mwait_ptr); |
1428 | mb(); | ||
1427 | __monitor(mwait_ptr, 0, 0); | 1429 | __monitor(mwait_ptr, 0, 0); |
1428 | mb(); | 1430 | mb(); |
1429 | __mwait(eax, 0); | 1431 | __mwait(eax, 0); |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index b857ed890b4c..57409f6b8c62 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -211,21 +211,17 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ | |||
211 | exception_exit(prev_state); \ | 211 | exception_exit(prev_state); \ |
212 | } | 212 | } |
213 | 213 | ||
214 | DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, | 214 | DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip ) |
215 | regs->ip) | 215 | DO_ERROR (X86_TRAP_OF, SIGSEGV, "overflow", overflow ) |
216 | DO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow) | 216 | DO_ERROR (X86_TRAP_BR, SIGSEGV, "bounds", bounds ) |
217 | DO_ERROR(X86_TRAP_BR, SIGSEGV, "bounds", bounds) | 217 | DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip ) |
218 | DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, | 218 | DO_ERROR (X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun ) |
219 | regs->ip) | 219 | DO_ERROR (X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS ) |
220 | DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", | 220 | DO_ERROR (X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present ) |
221 | coprocessor_segment_overrun) | ||
222 | DO_ERROR(X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS) | ||
223 | DO_ERROR(X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present) | ||
224 | #ifdef CONFIG_X86_32 | 221 | #ifdef CONFIG_X86_32 |
225 | DO_ERROR(X86_TRAP_SS, SIGBUS, "stack segment", stack_segment) | 222 | DO_ERROR (X86_TRAP_SS, SIGBUS, "stack segment", stack_segment ) |
226 | #endif | 223 | #endif |
227 | DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, | 224 | DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0 ) |
228 | BUS_ADRALN, 0) | ||
229 | 225 | ||
230 | #ifdef CONFIG_X86_64 | 226 | #ifdef CONFIG_X86_64 |
231 | /* Runs on IST stack */ | 227 | /* Runs on IST stack */ |
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 930e5d48f560..a3acbac2ee72 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/clocksource.h> | 11 | #include <linux/clocksource.h> |
12 | #include <linux/percpu.h> | 12 | #include <linux/percpu.h> |
13 | #include <linux/timex.h> | 13 | #include <linux/timex.h> |
14 | #include <linux/static_key.h> | ||
14 | 15 | ||
15 | #include <asm/hpet.h> | 16 | #include <asm/hpet.h> |
16 | #include <asm/timer.h> | 17 | #include <asm/timer.h> |
@@ -37,13 +38,244 @@ static int __read_mostly tsc_unstable; | |||
37 | erroneous rdtsc usage on !cpu_has_tsc processors */ | 38 | erroneous rdtsc usage on !cpu_has_tsc processors */ |
38 | static int __read_mostly tsc_disabled = -1; | 39 | static int __read_mostly tsc_disabled = -1; |
39 | 40 | ||
41 | static struct static_key __use_tsc = STATIC_KEY_INIT; | ||
42 | |||
40 | int tsc_clocksource_reliable; | 43 | int tsc_clocksource_reliable; |
44 | |||
45 | /* | ||
46 | * Use a ring-buffer like data structure, where a writer advances the head by | ||
47 | * writing a new data entry and a reader advances the tail when it observes a | ||
48 | * new entry. | ||
49 | * | ||
50 | * Writers are made to wait on readers until there's space to write a new | ||
51 | * entry. | ||
52 | * | ||
53 | * This means that we can always use an {offset, mul} pair to compute a ns | ||
54 | * value that is 'roughly' in the right direction, even if we're writing a new | ||
55 | * {offset, mul} pair during the clock read. | ||
56 | * | ||
57 | * The down-side is that we can no longer guarantee strict monotonicity anymore | ||
58 | * (assuming the TSC was that to begin with), because while we compute the | ||
59 | * intersection point of the two clock slopes and make sure the time is | ||
60 | * continuous at the point of switching; we can no longer guarantee a reader is | ||
61 | * strictly before or after the switch point. | ||
62 | * | ||
63 | * It does mean a reader no longer needs to disable IRQs in order to avoid | ||
64 | * CPU-Freq updates messing with his times, and similarly an NMI reader will | ||
65 | * no longer run the risk of hitting half-written state. | ||
66 | */ | ||
67 | |||
68 | struct cyc2ns { | ||
69 | struct cyc2ns_data data[2]; /* 0 + 2*24 = 48 */ | ||
70 | struct cyc2ns_data *head; /* 48 + 8 = 56 */ | ||
71 | struct cyc2ns_data *tail; /* 56 + 8 = 64 */ | ||
72 | }; /* exactly fits one cacheline */ | ||
73 | |||
74 | static DEFINE_PER_CPU_ALIGNED(struct cyc2ns, cyc2ns); | ||
75 | |||
76 | struct cyc2ns_data *cyc2ns_read_begin(void) | ||
77 | { | ||
78 | struct cyc2ns_data *head; | ||
79 | |||
80 | preempt_disable(); | ||
81 | |||
82 | head = this_cpu_read(cyc2ns.head); | ||
83 | /* | ||
84 | * Ensure we observe the entry when we observe the pointer to it. | ||
85 | * matches the wmb from cyc2ns_write_end(). | ||
86 | */ | ||
87 | smp_read_barrier_depends(); | ||
88 | head->__count++; | ||
89 | barrier(); | ||
90 | |||
91 | return head; | ||
92 | } | ||
93 | |||
94 | void cyc2ns_read_end(struct cyc2ns_data *head) | ||
95 | { | ||
96 | barrier(); | ||
97 | /* | ||
98 | * If we're the outer most nested read; update the tail pointer | ||
99 | * when we're done. This notifies possible pending writers | ||
100 | * that we've observed the head pointer and that the other | ||
101 | * entry is now free. | ||
102 | */ | ||
103 | if (!--head->__count) { | ||
104 | /* | ||
105 | * x86-TSO does not reorder writes with older reads; | ||
106 | * therefore once this write becomes visible to another | ||
107 | * cpu, we must be finished reading the cyc2ns_data. | ||
108 | * | ||
109 | * matches with cyc2ns_write_begin(). | ||
110 | */ | ||
111 | this_cpu_write(cyc2ns.tail, head); | ||
112 | } | ||
113 | preempt_enable(); | ||
114 | } | ||
115 | |||
116 | /* | ||
117 | * Begin writing a new @data entry for @cpu. | ||
118 | * | ||
119 | * Assumes some sort of write side lock; currently 'provided' by the assumption | ||
120 | * that cpufreq will call its notifiers sequentially. | ||
121 | */ | ||
122 | static struct cyc2ns_data *cyc2ns_write_begin(int cpu) | ||
123 | { | ||
124 | struct cyc2ns *c2n = &per_cpu(cyc2ns, cpu); | ||
125 | struct cyc2ns_data *data = c2n->data; | ||
126 | |||
127 | if (data == c2n->head) | ||
128 | data++; | ||
129 | |||
130 | /* XXX send an IPI to @cpu in order to guarantee a read? */ | ||
131 | |||
132 | /* | ||
133 | * When we observe the tail write from cyc2ns_read_end(), | ||
134 | * the cpu must be done with that entry and its safe | ||
135 | * to start writing to it. | ||
136 | */ | ||
137 | while (c2n->tail == data) | ||
138 | cpu_relax(); | ||
139 | |||
140 | return data; | ||
141 | } | ||
142 | |||
143 | static void cyc2ns_write_end(int cpu, struct cyc2ns_data *data) | ||
144 | { | ||
145 | struct cyc2ns *c2n = &per_cpu(cyc2ns, cpu); | ||
146 | |||
147 | /* | ||
148 | * Ensure the @data writes are visible before we publish the | ||
149 | * entry. Matches the data-depencency in cyc2ns_read_begin(). | ||
150 | */ | ||
151 | smp_wmb(); | ||
152 | |||
153 | ACCESS_ONCE(c2n->head) = data; | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * Accelerators for sched_clock() | ||
158 | * convert from cycles(64bits) => nanoseconds (64bits) | ||
159 | * basic equation: | ||
160 | * ns = cycles / (freq / ns_per_sec) | ||
161 | * ns = cycles * (ns_per_sec / freq) | ||
162 | * ns = cycles * (10^9 / (cpu_khz * 10^3)) | ||
163 | * ns = cycles * (10^6 / cpu_khz) | ||
164 | * | ||
165 | * Then we use scaling math (suggested by george@mvista.com) to get: | ||
166 | * ns = cycles * (10^6 * SC / cpu_khz) / SC | ||
167 | * ns = cycles * cyc2ns_scale / SC | ||
168 | * | ||
169 | * And since SC is a constant power of two, we can convert the div | ||
170 | * into a shift. | ||
171 | * | ||
172 | * We can use khz divisor instead of mhz to keep a better precision, since | ||
173 | * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. | ||
174 | * (mathieu.desnoyers@polymtl.ca) | ||
175 | * | ||
176 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" | ||
177 | */ | ||
178 | |||
179 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ | ||
180 | |||
181 | static void cyc2ns_data_init(struct cyc2ns_data *data) | ||
182 | { | ||
183 | data->cyc2ns_mul = 1U << CYC2NS_SCALE_FACTOR; | ||
184 | data->cyc2ns_shift = CYC2NS_SCALE_FACTOR; | ||
185 | data->cyc2ns_offset = 0; | ||
186 | data->__count = 0; | ||
187 | } | ||
188 | |||
189 | static void cyc2ns_init(int cpu) | ||
190 | { | ||
191 | struct cyc2ns *c2n = &per_cpu(cyc2ns, cpu); | ||
192 | |||
193 | cyc2ns_data_init(&c2n->data[0]); | ||
194 | cyc2ns_data_init(&c2n->data[1]); | ||
195 | |||
196 | c2n->head = c2n->data; | ||
197 | c2n->tail = c2n->data; | ||
198 | } | ||
199 | |||
200 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) | ||
201 | { | ||
202 | struct cyc2ns_data *data, *tail; | ||
203 | unsigned long long ns; | ||
204 | |||
205 | /* | ||
206 | * See cyc2ns_read_*() for details; replicated in order to avoid | ||
207 | * an extra few instructions that came with the abstraction. | ||
208 | * Notable, it allows us to only do the __count and tail update | ||
209 | * dance when its actually needed. | ||
210 | */ | ||
211 | |||
212 | preempt_disable(); | ||
213 | data = this_cpu_read(cyc2ns.head); | ||
214 | tail = this_cpu_read(cyc2ns.tail); | ||
215 | |||
216 | if (likely(data == tail)) { | ||
217 | ns = data->cyc2ns_offset; | ||
218 | ns += mul_u64_u32_shr(cyc, data->cyc2ns_mul, CYC2NS_SCALE_FACTOR); | ||
219 | } else { | ||
220 | data->__count++; | ||
221 | |||
222 | barrier(); | ||
223 | |||
224 | ns = data->cyc2ns_offset; | ||
225 | ns += mul_u64_u32_shr(cyc, data->cyc2ns_mul, CYC2NS_SCALE_FACTOR); | ||
226 | |||
227 | barrier(); | ||
228 | |||
229 | if (!--data->__count) | ||
230 | this_cpu_write(cyc2ns.tail, data); | ||
231 | } | ||
232 | preempt_enable(); | ||
233 | |||
234 | return ns; | ||
235 | } | ||
236 | |||
237 | /* XXX surely we already have this someplace in the kernel?! */ | ||
238 | #define DIV_ROUND(n, d) (((n) + ((d) / 2)) / (d)) | ||
239 | |||
240 | static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) | ||
241 | { | ||
242 | unsigned long long tsc_now, ns_now; | ||
243 | struct cyc2ns_data *data; | ||
244 | unsigned long flags; | ||
245 | |||
246 | local_irq_save(flags); | ||
247 | sched_clock_idle_sleep_event(); | ||
248 | |||
249 | if (!cpu_khz) | ||
250 | goto done; | ||
251 | |||
252 | data = cyc2ns_write_begin(cpu); | ||
253 | |||
254 | rdtscll(tsc_now); | ||
255 | ns_now = cycles_2_ns(tsc_now); | ||
256 | |||
257 | /* | ||
258 | * Compute a new multiplier as per the above comment and ensure our | ||
259 | * time function is continuous; see the comment near struct | ||
260 | * cyc2ns_data. | ||
261 | */ | ||
262 | data->cyc2ns_mul = DIV_ROUND(NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR, cpu_khz); | ||
263 | data->cyc2ns_shift = CYC2NS_SCALE_FACTOR; | ||
264 | data->cyc2ns_offset = ns_now - | ||
265 | mul_u64_u32_shr(tsc_now, data->cyc2ns_mul, CYC2NS_SCALE_FACTOR); | ||
266 | |||
267 | cyc2ns_write_end(cpu, data); | ||
268 | |||
269 | done: | ||
270 | sched_clock_idle_wakeup_event(0); | ||
271 | local_irq_restore(flags); | ||
272 | } | ||
41 | /* | 273 | /* |
42 | * Scheduler clock - returns current time in nanosec units. | 274 | * Scheduler clock - returns current time in nanosec units. |
43 | */ | 275 | */ |
44 | u64 native_sched_clock(void) | 276 | u64 native_sched_clock(void) |
45 | { | 277 | { |
46 | u64 this_offset; | 278 | u64 tsc_now; |
47 | 279 | ||
48 | /* | 280 | /* |
49 | * Fall back to jiffies if there's no TSC available: | 281 | * Fall back to jiffies if there's no TSC available: |
@@ -53,16 +285,16 @@ u64 native_sched_clock(void) | |||
53 | * very important for it to be as fast as the platform | 285 | * very important for it to be as fast as the platform |
54 | * can achieve it. ) | 286 | * can achieve it. ) |
55 | */ | 287 | */ |
56 | if (unlikely(tsc_disabled)) { | 288 | if (!static_key_false(&__use_tsc)) { |
57 | /* No locking but a rare wrong value is not a big deal: */ | 289 | /* No locking but a rare wrong value is not a big deal: */ |
58 | return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); | 290 | return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); |
59 | } | 291 | } |
60 | 292 | ||
61 | /* read the Time Stamp Counter: */ | 293 | /* read the Time Stamp Counter: */ |
62 | rdtscll(this_offset); | 294 | rdtscll(tsc_now); |
63 | 295 | ||
64 | /* return the value in ns */ | 296 | /* return the value in ns */ |
65 | return __cycles_2_ns(this_offset); | 297 | return cycles_2_ns(tsc_now); |
66 | } | 298 | } |
67 | 299 | ||
68 | /* We need to define a real function for sched_clock, to override the | 300 | /* We need to define a real function for sched_clock, to override the |
@@ -419,6 +651,16 @@ unsigned long native_calibrate_tsc(void) | |||
419 | unsigned long flags, latch, ms, fast_calibrate; | 651 | unsigned long flags, latch, ms, fast_calibrate; |
420 | int hpet = is_hpet_enabled(), i, loopmin; | 652 | int hpet = is_hpet_enabled(), i, loopmin; |
421 | 653 | ||
654 | /* Calibrate TSC using MSR for Intel Atom SoCs */ | ||
655 | local_irq_save(flags); | ||
656 | i = try_msr_calibrate_tsc(&fast_calibrate); | ||
657 | local_irq_restore(flags); | ||
658 | if (i >= 0) { | ||
659 | if (i == 0) | ||
660 | pr_warn("Fast TSC calibration using MSR failed\n"); | ||
661 | return fast_calibrate; | ||
662 | } | ||
663 | |||
422 | local_irq_save(flags); | 664 | local_irq_save(flags); |
423 | fast_calibrate = quick_pit_calibrate(); | 665 | fast_calibrate = quick_pit_calibrate(); |
424 | local_irq_restore(flags); | 666 | local_irq_restore(flags); |
@@ -589,61 +831,11 @@ int recalibrate_cpu_khz(void) | |||
589 | EXPORT_SYMBOL(recalibrate_cpu_khz); | 831 | EXPORT_SYMBOL(recalibrate_cpu_khz); |
590 | 832 | ||
591 | 833 | ||
592 | /* Accelerators for sched_clock() | ||
593 | * convert from cycles(64bits) => nanoseconds (64bits) | ||
594 | * basic equation: | ||
595 | * ns = cycles / (freq / ns_per_sec) | ||
596 | * ns = cycles * (ns_per_sec / freq) | ||
597 | * ns = cycles * (10^9 / (cpu_khz * 10^3)) | ||
598 | * ns = cycles * (10^6 / cpu_khz) | ||
599 | * | ||
600 | * Then we use scaling math (suggested by george@mvista.com) to get: | ||
601 | * ns = cycles * (10^6 * SC / cpu_khz) / SC | ||
602 | * ns = cycles * cyc2ns_scale / SC | ||
603 | * | ||
604 | * And since SC is a constant power of two, we can convert the div | ||
605 | * into a shift. | ||
606 | * | ||
607 | * We can use khz divisor instead of mhz to keep a better precision, since | ||
608 | * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. | ||
609 | * (mathieu.desnoyers@polymtl.ca) | ||
610 | * | ||
611 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" | ||
612 | */ | ||
613 | |||
614 | DEFINE_PER_CPU(unsigned long, cyc2ns); | ||
615 | DEFINE_PER_CPU(unsigned long long, cyc2ns_offset); | ||
616 | |||
617 | static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) | ||
618 | { | ||
619 | unsigned long long tsc_now, ns_now, *offset; | ||
620 | unsigned long flags, *scale; | ||
621 | |||
622 | local_irq_save(flags); | ||
623 | sched_clock_idle_sleep_event(); | ||
624 | |||
625 | scale = &per_cpu(cyc2ns, cpu); | ||
626 | offset = &per_cpu(cyc2ns_offset, cpu); | ||
627 | |||
628 | rdtscll(tsc_now); | ||
629 | ns_now = __cycles_2_ns(tsc_now); | ||
630 | |||
631 | if (cpu_khz) { | ||
632 | *scale = ((NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR) + | ||
633 | cpu_khz / 2) / cpu_khz; | ||
634 | *offset = ns_now - mult_frac(tsc_now, *scale, | ||
635 | (1UL << CYC2NS_SCALE_FACTOR)); | ||
636 | } | ||
637 | |||
638 | sched_clock_idle_wakeup_event(0); | ||
639 | local_irq_restore(flags); | ||
640 | } | ||
641 | |||
642 | static unsigned long long cyc2ns_suspend; | 834 | static unsigned long long cyc2ns_suspend; |
643 | 835 | ||
644 | void tsc_save_sched_clock_state(void) | 836 | void tsc_save_sched_clock_state(void) |
645 | { | 837 | { |
646 | if (!sched_clock_stable) | 838 | if (!sched_clock_stable()) |
647 | return; | 839 | return; |
648 | 840 | ||
649 | cyc2ns_suspend = sched_clock(); | 841 | cyc2ns_suspend = sched_clock(); |
@@ -663,16 +855,26 @@ void tsc_restore_sched_clock_state(void) | |||
663 | unsigned long flags; | 855 | unsigned long flags; |
664 | int cpu; | 856 | int cpu; |
665 | 857 | ||
666 | if (!sched_clock_stable) | 858 | if (!sched_clock_stable()) |
667 | return; | 859 | return; |
668 | 860 | ||
669 | local_irq_save(flags); | 861 | local_irq_save(flags); |
670 | 862 | ||
671 | __this_cpu_write(cyc2ns_offset, 0); | 863 | /* |
864 | * We're comming out of suspend, there's no concurrency yet; don't | ||
865 | * bother being nice about the RCU stuff, just write to both | ||
866 | * data fields. | ||
867 | */ | ||
868 | |||
869 | this_cpu_write(cyc2ns.data[0].cyc2ns_offset, 0); | ||
870 | this_cpu_write(cyc2ns.data[1].cyc2ns_offset, 0); | ||
871 | |||
672 | offset = cyc2ns_suspend - sched_clock(); | 872 | offset = cyc2ns_suspend - sched_clock(); |
673 | 873 | ||
674 | for_each_possible_cpu(cpu) | 874 | for_each_possible_cpu(cpu) { |
675 | per_cpu(cyc2ns_offset, cpu) = offset; | 875 | per_cpu(cyc2ns.data[0].cyc2ns_offset, cpu) = offset; |
876 | per_cpu(cyc2ns.data[1].cyc2ns_offset, cpu) = offset; | ||
877 | } | ||
676 | 878 | ||
677 | local_irq_restore(flags); | 879 | local_irq_restore(flags); |
678 | } | 880 | } |
@@ -795,7 +997,7 @@ void mark_tsc_unstable(char *reason) | |||
795 | { | 997 | { |
796 | if (!tsc_unstable) { | 998 | if (!tsc_unstable) { |
797 | tsc_unstable = 1; | 999 | tsc_unstable = 1; |
798 | sched_clock_stable = 0; | 1000 | clear_sched_clock_stable(); |
799 | disable_sched_clock_irqtime(); | 1001 | disable_sched_clock_irqtime(); |
800 | pr_info("Marking TSC unstable due to %s\n", reason); | 1002 | pr_info("Marking TSC unstable due to %s\n", reason); |
801 | /* Change only the rating, when not registered */ | 1003 | /* Change only the rating, when not registered */ |
@@ -995,14 +1197,18 @@ void __init tsc_init(void) | |||
995 | * speed as the bootup CPU. (cpufreq notifiers will fix this | 1197 | * speed as the bootup CPU. (cpufreq notifiers will fix this |
996 | * up if their speed diverges) | 1198 | * up if their speed diverges) |
997 | */ | 1199 | */ |
998 | for_each_possible_cpu(cpu) | 1200 | for_each_possible_cpu(cpu) { |
1201 | cyc2ns_init(cpu); | ||
999 | set_cyc2ns_scale(cpu_khz, cpu); | 1202 | set_cyc2ns_scale(cpu_khz, cpu); |
1203 | } | ||
1000 | 1204 | ||
1001 | if (tsc_disabled > 0) | 1205 | if (tsc_disabled > 0) |
1002 | return; | 1206 | return; |
1003 | 1207 | ||
1004 | /* now allow native_sched_clock() to use rdtsc */ | 1208 | /* now allow native_sched_clock() to use rdtsc */ |
1209 | |||
1005 | tsc_disabled = 0; | 1210 | tsc_disabled = 0; |
1211 | static_key_slow_inc(&__use_tsc); | ||
1006 | 1212 | ||
1007 | if (!no_sched_irq_time) | 1213 | if (!no_sched_irq_time) |
1008 | enable_sched_clock_irqtime(); | 1214 | enable_sched_clock_irqtime(); |
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c new file mode 100644 index 000000000000..8b5434f4389f --- /dev/null +++ b/arch/x86/kernel/tsc_msr.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * tsc_msr.c - MSR based TSC calibration on Intel Atom SoC platforms. | ||
3 | * | ||
4 | * TSC in Intel Atom SoC runs at a constant rate which can be figured | ||
5 | * by this formula: | ||
6 | * <maximum core-clock to bus-clock ratio> * <maximum resolved frequency> | ||
7 | * See Intel 64 and IA-32 System Programming Guid section 16.12 and 30.11.5 | ||
8 | * for details. | ||
9 | * Especially some Intel Atom SoCs don't have PIT(i8254) or HPET, so MSR | ||
10 | * based calibration is the only option. | ||
11 | * | ||
12 | * | ||
13 | * Copyright (C) 2013 Intel Corporation | ||
14 | * Author: Bin Gao <bin.gao@intel.com> | ||
15 | * | ||
16 | * This file is released under the GPLv2. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <asm/processor.h> | ||
21 | #include <asm/setup.h> | ||
22 | #include <asm/apic.h> | ||
23 | #include <asm/param.h> | ||
24 | |||
25 | /* CPU reference clock frequency: in KHz */ | ||
26 | #define FREQ_83 83200 | ||
27 | #define FREQ_100 99840 | ||
28 | #define FREQ_133 133200 | ||
29 | #define FREQ_166 166400 | ||
30 | |||
31 | #define MAX_NUM_FREQS 8 | ||
32 | |||
33 | /* | ||
34 | * According to Intel 64 and IA-32 System Programming Guide, | ||
35 | * if MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be | ||
36 | * read in MSR_PLATFORM_ID[12:8], otherwise in MSR_PERF_STAT[44:40]. | ||
37 | * Unfortunately some Intel Atom SoCs aren't quite compliant to this, | ||
38 | * so we need manually differentiate SoC families. This is what the | ||
39 | * field msr_plat does. | ||
40 | */ | ||
41 | struct freq_desc { | ||
42 | u8 x86_family; /* CPU family */ | ||
43 | u8 x86_model; /* model */ | ||
44 | u8 msr_plat; /* 1: use MSR_PLATFORM_INFO, 0: MSR_IA32_PERF_STATUS */ | ||
45 | u32 freqs[MAX_NUM_FREQS]; | ||
46 | }; | ||
47 | |||
48 | static struct freq_desc freq_desc_tables[] = { | ||
49 | /* PNW */ | ||
50 | { 6, 0x27, 0, { 0, 0, 0, 0, 0, FREQ_100, 0, FREQ_83 } }, | ||
51 | /* CLV+ */ | ||
52 | { 6, 0x35, 0, { 0, FREQ_133, 0, 0, 0, FREQ_100, 0, FREQ_83 } }, | ||
53 | /* TNG */ | ||
54 | { 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } }, | ||
55 | /* VLV2 */ | ||
56 | { 6, 0x37, 1, { 0, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } }, | ||
57 | /* ANN */ | ||
58 | { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } }, | ||
59 | }; | ||
60 | |||
61 | static int match_cpu(u8 family, u8 model) | ||
62 | { | ||
63 | int i; | ||
64 | |||
65 | for (i = 0; i < ARRAY_SIZE(freq_desc_tables); i++) { | ||
66 | if ((family == freq_desc_tables[i].x86_family) && | ||
67 | (model == freq_desc_tables[i].x86_model)) | ||
68 | return i; | ||
69 | } | ||
70 | |||
71 | return -1; | ||
72 | } | ||
73 | |||
74 | /* Map CPU reference clock freq ID(0-7) to CPU reference clock freq(KHz) */ | ||
75 | #define id_to_freq(cpu_index, freq_id) \ | ||
76 | (freq_desc_tables[cpu_index].freqs[freq_id]) | ||
77 | |||
78 | /* | ||
79 | * Do MSR calibration only for known/supported CPUs. | ||
80 | * Return values: | ||
81 | * -1: CPU is unknown/unsupported for MSR based calibration | ||
82 | * 0: CPU is known/supported, but calibration failed | ||
83 | * 1: CPU is known/supported, and calibration succeeded | ||
84 | */ | ||
85 | int try_msr_calibrate_tsc(unsigned long *fast_calibrate) | ||
86 | { | ||
87 | int cpu_index; | ||
88 | u32 lo, hi, ratio, freq_id, freq; | ||
89 | |||
90 | cpu_index = match_cpu(boot_cpu_data.x86, boot_cpu_data.x86_model); | ||
91 | if (cpu_index < 0) | ||
92 | return -1; | ||
93 | |||
94 | *fast_calibrate = 0; | ||
95 | |||
96 | if (freq_desc_tables[cpu_index].msr_plat) { | ||
97 | rdmsr(MSR_PLATFORM_INFO, lo, hi); | ||
98 | ratio = (lo >> 8) & 0x1f; | ||
99 | } else { | ||
100 | rdmsr(MSR_IA32_PERF_STATUS, lo, hi); | ||
101 | ratio = (hi >> 8) & 0x1f; | ||
102 | } | ||
103 | pr_info("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio); | ||
104 | |||
105 | if (!ratio) | ||
106 | return 0; | ||
107 | |||
108 | /* Get FSB FREQ ID */ | ||
109 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
110 | freq_id = lo & 0x7; | ||
111 | freq = id_to_freq(cpu_index, freq_id); | ||
112 | pr_info("Resolved frequency ID: %u, frequency: %u KHz\n", | ||
113 | freq_id, freq); | ||
114 | if (!freq) | ||
115 | return 0; | ||
116 | |||
117 | /* TSC frequency = maximum resolved freq * maximum resolved bus ratio */ | ||
118 | *fast_calibrate = freq * ratio; | ||
119 | pr_info("TSC runs at %lu KHz\n", *fast_calibrate); | ||
120 | |||
121 | #ifdef CONFIG_X86_LOCAL_APIC | ||
122 | lapic_timer_frequency = (freq * 1000) / HZ; | ||
123 | pr_info("lapic_timer_frequency = %d\n", lapic_timer_frequency); | ||
124 | #endif | ||
125 | |||
126 | return 1; | ||
127 | } | ||
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index adfdf56a3714..26488487bc61 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c | |||
@@ -16,7 +16,6 @@ | |||
16 | */ | 16 | */ |
17 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/init.h> | ||
20 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
21 | #include <linux/nmi.h> | 20 | #include <linux/nmi.h> |
22 | #include <asm/tsc.h> | 21 | #include <asm/tsc.h> |
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 422fd8223470..a4b451c6addf 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
@@ -562,6 +562,16 @@ static void __init xstate_enable_boot_cpu(void) | |||
562 | if (cpu_has_xsaveopt && eagerfpu != DISABLE) | 562 | if (cpu_has_xsaveopt && eagerfpu != DISABLE) |
563 | eagerfpu = ENABLE; | 563 | eagerfpu = ENABLE; |
564 | 564 | ||
565 | if (pcntxt_mask & XSTATE_EAGER) { | ||
566 | if (eagerfpu == DISABLE) { | ||
567 | pr_err("eagerfpu not present, disabling some xstate features: 0x%llx\n", | ||
568 | pcntxt_mask & XSTATE_EAGER); | ||
569 | pcntxt_mask &= ~XSTATE_EAGER; | ||
570 | } else { | ||
571 | eagerfpu = ENABLE; | ||
572 | } | ||
573 | } | ||
574 | |||
565 | pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n", | 575 | pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n", |
566 | pcntxt_mask, xstate_size); | 576 | pcntxt_mask, xstate_size); |
567 | } | 577 | } |
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 1673940cf9c3..775702f649ca 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -1355,7 +1355,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value) | |||
1355 | vcpu->arch.apic_base = value; | 1355 | vcpu->arch.apic_base = value; |
1356 | 1356 | ||
1357 | /* update jump label if enable bit changes */ | 1357 | /* update jump label if enable bit changes */ |
1358 | if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) { | 1358 | if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) { |
1359 | if (value & MSR_IA32_APICBASE_ENABLE) | 1359 | if (value & MSR_IA32_APICBASE_ENABLE) |
1360 | static_key_slow_dec_deferred(&apic_hw_disabled); | 1360 | static_key_slow_dec_deferred(&apic_hw_disabled); |
1361 | else | 1361 | else |
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index a30ca15be21c..dee945d55594 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S | |||
@@ -186,7 +186,7 @@ ENTRY(copy_user_generic_unrolled) | |||
186 | 30: shll $6,%ecx | 186 | 30: shll $6,%ecx |
187 | addl %ecx,%edx | 187 | addl %ecx,%edx |
188 | jmp 60f | 188 | jmp 60f |
189 | 40: lea (%rdx,%rcx,8),%rdx | 189 | 40: leal (%rdx,%rcx,8),%edx |
190 | jmp 60f | 190 | jmp 60f |
191 | 50: movl %ecx,%edx | 191 | 50: movl %ecx,%edx |
192 | 60: jmp copy_user_handle_tail /* ecx is zerorest also */ | 192 | 60: jmp copy_user_handle_tail /* ecx is zerorest also */ |
@@ -236,8 +236,6 @@ ENDPROC(copy_user_generic_unrolled) | |||
236 | ENTRY(copy_user_generic_string) | 236 | ENTRY(copy_user_generic_string) |
237 | CFI_STARTPROC | 237 | CFI_STARTPROC |
238 | ASM_STAC | 238 | ASM_STAC |
239 | andl %edx,%edx | ||
240 | jz 4f | ||
241 | cmpl $8,%edx | 239 | cmpl $8,%edx |
242 | jb 2f /* less than 8 bytes, go to byte copy loop */ | 240 | jb 2f /* less than 8 bytes, go to byte copy loop */ |
243 | ALIGN_DESTINATION | 241 | ALIGN_DESTINATION |
@@ -249,12 +247,12 @@ ENTRY(copy_user_generic_string) | |||
249 | 2: movl %edx,%ecx | 247 | 2: movl %edx,%ecx |
250 | 3: rep | 248 | 3: rep |
251 | movsb | 249 | movsb |
252 | 4: xorl %eax,%eax | 250 | xorl %eax,%eax |
253 | ASM_CLAC | 251 | ASM_CLAC |
254 | ret | 252 | ret |
255 | 253 | ||
256 | .section .fixup,"ax" | 254 | .section .fixup,"ax" |
257 | 11: lea (%rdx,%rcx,8),%rcx | 255 | 11: leal (%rdx,%rcx,8),%ecx |
258 | 12: movl %ecx,%edx /* ecx is zerorest also */ | 256 | 12: movl %ecx,%edx /* ecx is zerorest also */ |
259 | jmp copy_user_handle_tail | 257 | jmp copy_user_handle_tail |
260 | .previous | 258 | .previous |
@@ -279,12 +277,10 @@ ENDPROC(copy_user_generic_string) | |||
279 | ENTRY(copy_user_enhanced_fast_string) | 277 | ENTRY(copy_user_enhanced_fast_string) |
280 | CFI_STARTPROC | 278 | CFI_STARTPROC |
281 | ASM_STAC | 279 | ASM_STAC |
282 | andl %edx,%edx | ||
283 | jz 2f | ||
284 | movl %edx,%ecx | 280 | movl %edx,%ecx |
285 | 1: rep | 281 | 1: rep |
286 | movsb | 282 | movsb |
287 | 2: xorl %eax,%eax | 283 | xorl %eax,%eax |
288 | ASM_CLAC | 284 | ASM_CLAC |
289 | ret | 285 | ret |
290 | 286 | ||
diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index 7c3bee636e2f..39d6a3db0b96 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/timex.h> | 16 | #include <linux/timex.h> |
17 | #include <linux/preempt.h> | 17 | #include <linux/preempt.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/init.h> | ||
20 | 19 | ||
21 | #include <asm/processor.h> | 20 | #include <asm/processor.h> |
22 | #include <asm/delay.h> | 21 | #include <asm/delay.h> |
diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt index 533a85e3a07e..1a2be7c6895d 100644 --- a/arch/x86/lib/x86-opcode-map.txt +++ b/arch/x86/lib/x86-opcode-map.txt | |||
@@ -346,8 +346,8 @@ AVXcode: 1 | |||
346 | 17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1) | 346 | 17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1) |
347 | 18: Grp16 (1A) | 347 | 18: Grp16 (1A) |
348 | 19: | 348 | 19: |
349 | 1a: | 349 | 1a: BNDCL Ev,Gv | BNDCU Ev,Gv | BNDMOV Gv,Ev | BNDLDX Gv,Ev,Gv |
350 | 1b: | 350 | 1b: BNDCN Ev,Gv | BNDMOV Ev,Gv | BNDMK Gv,Ev | BNDSTX Ev,GV,Gv |
351 | 1c: | 351 | 1c: |
352 | 1d: | 352 | 1d: |
353 | 1e: | 353 | 1e: |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 9ff85bb8dd69..9d591c895803 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -641,6 +641,20 @@ no_context(struct pt_regs *regs, unsigned long error_code, | |||
641 | 641 | ||
642 | /* Are we prepared to handle this kernel fault? */ | 642 | /* Are we prepared to handle this kernel fault? */ |
643 | if (fixup_exception(regs)) { | 643 | if (fixup_exception(regs)) { |
644 | /* | ||
645 | * Any interrupt that takes a fault gets the fixup. This makes | ||
646 | * the below recursive fault logic only apply to a faults from | ||
647 | * task context. | ||
648 | */ | ||
649 | if (in_interrupt()) | ||
650 | return; | ||
651 | |||
652 | /* | ||
653 | * Per the above we're !in_interrupt(), aka. task context. | ||
654 | * | ||
655 | * In this case we need to make sure we're not recursively | ||
656 | * faulting through the emulate_vsyscall() logic. | ||
657 | */ | ||
644 | if (current_thread_info()->sig_on_uaccess_error && signal) { | 658 | if (current_thread_info()->sig_on_uaccess_error && signal) { |
645 | tsk->thread.trap_nr = X86_TRAP_PF; | 659 | tsk->thread.trap_nr = X86_TRAP_PF; |
646 | tsk->thread.error_code = error_code | PF_USER; | 660 | tsk->thread.error_code = error_code | PF_USER; |
@@ -649,6 +663,10 @@ no_context(struct pt_regs *regs, unsigned long error_code, | |||
649 | /* XXX: hwpoison faults will set the wrong code. */ | 663 | /* XXX: hwpoison faults will set the wrong code. */ |
650 | force_sig_info_fault(signal, si_code, address, tsk, 0); | 664 | force_sig_info_fault(signal, si_code, address, tsk, 0); |
651 | } | 665 | } |
666 | |||
667 | /* | ||
668 | * Barring that, we can do the fixup and be happy. | ||
669 | */ | ||
652 | return; | 670 | return; |
653 | } | 671 | } |
654 | 672 | ||
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index 9d980d88b747..8c9f647ff9e1 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c | |||
@@ -87,9 +87,7 @@ int pmd_huge_support(void) | |||
87 | } | 87 | } |
88 | #endif | 88 | #endif |
89 | 89 | ||
90 | /* x86_64 also uses this file */ | 90 | #ifdef CONFIG_HUGETLB_PAGE |
91 | |||
92 | #ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA | ||
93 | static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, | 91 | static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, |
94 | unsigned long addr, unsigned long len, | 92 | unsigned long addr, unsigned long len, |
95 | unsigned long pgoff, unsigned long flags) | 93 | unsigned long pgoff, unsigned long flags) |
@@ -99,7 +97,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, | |||
99 | 97 | ||
100 | info.flags = 0; | 98 | info.flags = 0; |
101 | info.length = len; | 99 | info.length = len; |
102 | info.low_limit = TASK_UNMAPPED_BASE; | 100 | info.low_limit = current->mm->mmap_legacy_base; |
103 | info.high_limit = TASK_SIZE; | 101 | info.high_limit = TASK_SIZE; |
104 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); | 102 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); |
105 | info.align_offset = 0; | 103 | info.align_offset = 0; |
@@ -172,8 +170,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
172 | return hugetlb_get_unmapped_area_topdown(file, addr, len, | 170 | return hugetlb_get_unmapped_area_topdown(file, addr, len, |
173 | pgoff, flags); | 171 | pgoff, flags); |
174 | } | 172 | } |
175 | 173 | #endif /* CONFIG_HUGETLB_PAGE */ | |
176 | #endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/ | ||
177 | 174 | ||
178 | #ifdef CONFIG_X86_64 | 175 | #ifdef CONFIG_X86_64 |
179 | static __init int setup_hugepagesz(char *opt) | 176 | static __init int setup_hugepagesz(char *opt) |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 4287f1ffba7e..5bdc5430597c 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -806,6 +806,9 @@ void __init mem_init(void) | |||
806 | BUILD_BUG_ON(VMALLOC_START >= VMALLOC_END); | 806 | BUILD_BUG_ON(VMALLOC_START >= VMALLOC_END); |
807 | #undef high_memory | 807 | #undef high_memory |
808 | #undef __FIXADDR_TOP | 808 | #undef __FIXADDR_TOP |
809 | #ifdef CONFIG_RANDOMIZE_BASE | ||
810 | BUILD_BUG_ON(CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE); | ||
811 | #endif | ||
809 | 812 | ||
810 | #ifdef CONFIG_HIGHMEM | 813 | #ifdef CONFIG_HIGHMEM |
811 | BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE > FIXADDR_START); | 814 | BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE > FIXADDR_START); |
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index e5d5e2ce9f77..637ab34ed632 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/rculist.h> | 11 | #include <linux/rculist.h> |
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/hash.h> | 13 | #include <linux/hash.h> |
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
17 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 24aec58d6afd..c85da7bb6b60 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c | |||
@@ -211,9 +211,13 @@ static void __init setup_node_data(int nid, u64 start, u64 end) | |||
211 | */ | 211 | */ |
212 | nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); | 212 | nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); |
213 | if (!nd_pa) { | 213 | if (!nd_pa) { |
214 | pr_err("Cannot find %zu bytes in node %d\n", | 214 | nd_pa = __memblock_alloc_base(nd_size, SMP_CACHE_BYTES, |
215 | nd_size, nid); | 215 | MEMBLOCK_ALLOC_ACCESSIBLE); |
216 | return; | 216 | if (!nd_pa) { |
217 | pr_err("Cannot find %zu bytes in node %d\n", | ||
218 | nd_size, nid); | ||
219 | return; | ||
220 | } | ||
217 | } | 221 | } |
218 | nd = __va(nd_pa); | 222 | nd = __va(nd_pa); |
219 | 223 | ||
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c index d0b1773d9d2e..461bc8289024 100644 --- a/arch/x86/mm/pageattr-test.c +++ b/arch/x86/mm/pageattr-test.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/kthread.h> | 8 | #include <linux/kthread.h> |
9 | #include <linux/random.h> | 9 | #include <linux/random.h> |
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/init.h> | ||
12 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
13 | 12 | ||
14 | #include <asm/cacheflush.h> | 13 | #include <asm/cacheflush.h> |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index bb32480c2d71..b3b19f46c016 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -30,6 +30,7 @@ | |||
30 | */ | 30 | */ |
31 | struct cpa_data { | 31 | struct cpa_data { |
32 | unsigned long *vaddr; | 32 | unsigned long *vaddr; |
33 | pgd_t *pgd; | ||
33 | pgprot_t mask_set; | 34 | pgprot_t mask_set; |
34 | pgprot_t mask_clr; | 35 | pgprot_t mask_clr; |
35 | int numpages; | 36 | int numpages; |
@@ -322,17 +323,9 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, | |||
322 | return prot; | 323 | return prot; |
323 | } | 324 | } |
324 | 325 | ||
325 | /* | 326 | static pte_t *__lookup_address_in_pgd(pgd_t *pgd, unsigned long address, |
326 | * Lookup the page table entry for a virtual address. Return a pointer | 327 | unsigned int *level) |
327 | * to the entry and the level of the mapping. | ||
328 | * | ||
329 | * Note: We return pud and pmd either when the entry is marked large | ||
330 | * or when the present bit is not set. Otherwise we would return a | ||
331 | * pointer to a nonexisting mapping. | ||
332 | */ | ||
333 | pte_t *lookup_address(unsigned long address, unsigned int *level) | ||
334 | { | 328 | { |
335 | pgd_t *pgd = pgd_offset_k(address); | ||
336 | pud_t *pud; | 329 | pud_t *pud; |
337 | pmd_t *pmd; | 330 | pmd_t *pmd; |
338 | 331 | ||
@@ -361,8 +354,31 @@ pte_t *lookup_address(unsigned long address, unsigned int *level) | |||
361 | 354 | ||
362 | return pte_offset_kernel(pmd, address); | 355 | return pte_offset_kernel(pmd, address); |
363 | } | 356 | } |
357 | |||
358 | /* | ||
359 | * Lookup the page table entry for a virtual address. Return a pointer | ||
360 | * to the entry and the level of the mapping. | ||
361 | * | ||
362 | * Note: We return pud and pmd either when the entry is marked large | ||
363 | * or when the present bit is not set. Otherwise we would return a | ||
364 | * pointer to a nonexisting mapping. | ||
365 | */ | ||
366 | pte_t *lookup_address(unsigned long address, unsigned int *level) | ||
367 | { | ||
368 | return __lookup_address_in_pgd(pgd_offset_k(address), address, level); | ||
369 | } | ||
364 | EXPORT_SYMBOL_GPL(lookup_address); | 370 | EXPORT_SYMBOL_GPL(lookup_address); |
365 | 371 | ||
372 | static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address, | ||
373 | unsigned int *level) | ||
374 | { | ||
375 | if (cpa->pgd) | ||
376 | return __lookup_address_in_pgd(cpa->pgd + pgd_index(address), | ||
377 | address, level); | ||
378 | |||
379 | return lookup_address(address, level); | ||
380 | } | ||
381 | |||
366 | /* | 382 | /* |
367 | * This is necessary because __pa() does not work on some | 383 | * This is necessary because __pa() does not work on some |
368 | * kinds of memory, like vmalloc() or the alloc_remap() | 384 | * kinds of memory, like vmalloc() or the alloc_remap() |
@@ -437,7 +453,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
437 | * Check for races, another CPU might have split this page | 453 | * Check for races, another CPU might have split this page |
438 | * up already: | 454 | * up already: |
439 | */ | 455 | */ |
440 | tmp = lookup_address(address, &level); | 456 | tmp = _lookup_address_cpa(cpa, address, &level); |
441 | if (tmp != kpte) | 457 | if (tmp != kpte) |
442 | goto out_unlock; | 458 | goto out_unlock; |
443 | 459 | ||
@@ -543,7 +559,8 @@ out_unlock: | |||
543 | } | 559 | } |
544 | 560 | ||
545 | static int | 561 | static int |
546 | __split_large_page(pte_t *kpte, unsigned long address, struct page *base) | 562 | __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address, |
563 | struct page *base) | ||
547 | { | 564 | { |
548 | pte_t *pbase = (pte_t *)page_address(base); | 565 | pte_t *pbase = (pte_t *)page_address(base); |
549 | unsigned long pfn, pfninc = 1; | 566 | unsigned long pfn, pfninc = 1; |
@@ -556,7 +573,7 @@ __split_large_page(pte_t *kpte, unsigned long address, struct page *base) | |||
556 | * Check for races, another CPU might have split this page | 573 | * Check for races, another CPU might have split this page |
557 | * up for us already: | 574 | * up for us already: |
558 | */ | 575 | */ |
559 | tmp = lookup_address(address, &level); | 576 | tmp = _lookup_address_cpa(cpa, address, &level); |
560 | if (tmp != kpte) { | 577 | if (tmp != kpte) { |
561 | spin_unlock(&pgd_lock); | 578 | spin_unlock(&pgd_lock); |
562 | return 1; | 579 | return 1; |
@@ -632,7 +649,8 @@ __split_large_page(pte_t *kpte, unsigned long address, struct page *base) | |||
632 | return 0; | 649 | return 0; |
633 | } | 650 | } |
634 | 651 | ||
635 | static int split_large_page(pte_t *kpte, unsigned long address) | 652 | static int split_large_page(struct cpa_data *cpa, pte_t *kpte, |
653 | unsigned long address) | ||
636 | { | 654 | { |
637 | struct page *base; | 655 | struct page *base; |
638 | 656 | ||
@@ -644,15 +662,390 @@ static int split_large_page(pte_t *kpte, unsigned long address) | |||
644 | if (!base) | 662 | if (!base) |
645 | return -ENOMEM; | 663 | return -ENOMEM; |
646 | 664 | ||
647 | if (__split_large_page(kpte, address, base)) | 665 | if (__split_large_page(cpa, kpte, address, base)) |
648 | __free_page(base); | 666 | __free_page(base); |
649 | 667 | ||
650 | return 0; | 668 | return 0; |
651 | } | 669 | } |
652 | 670 | ||
671 | static bool try_to_free_pte_page(pte_t *pte) | ||
672 | { | ||
673 | int i; | ||
674 | |||
675 | for (i = 0; i < PTRS_PER_PTE; i++) | ||
676 | if (!pte_none(pte[i])) | ||
677 | return false; | ||
678 | |||
679 | free_page((unsigned long)pte); | ||
680 | return true; | ||
681 | } | ||
682 | |||
683 | static bool try_to_free_pmd_page(pmd_t *pmd) | ||
684 | { | ||
685 | int i; | ||
686 | |||
687 | for (i = 0; i < PTRS_PER_PMD; i++) | ||
688 | if (!pmd_none(pmd[i])) | ||
689 | return false; | ||
690 | |||
691 | free_page((unsigned long)pmd); | ||
692 | return true; | ||
693 | } | ||
694 | |||
695 | static bool unmap_pte_range(pmd_t *pmd, unsigned long start, unsigned long end) | ||
696 | { | ||
697 | pte_t *pte = pte_offset_kernel(pmd, start); | ||
698 | |||
699 | while (start < end) { | ||
700 | set_pte(pte, __pte(0)); | ||
701 | |||
702 | start += PAGE_SIZE; | ||
703 | pte++; | ||
704 | } | ||
705 | |||
706 | if (try_to_free_pte_page((pte_t *)pmd_page_vaddr(*pmd))) { | ||
707 | pmd_clear(pmd); | ||
708 | return true; | ||
709 | } | ||
710 | return false; | ||
711 | } | ||
712 | |||
713 | static void __unmap_pmd_range(pud_t *pud, pmd_t *pmd, | ||
714 | unsigned long start, unsigned long end) | ||
715 | { | ||
716 | if (unmap_pte_range(pmd, start, end)) | ||
717 | if (try_to_free_pmd_page((pmd_t *)pud_page_vaddr(*pud))) | ||
718 | pud_clear(pud); | ||
719 | } | ||
720 | |||
721 | static void unmap_pmd_range(pud_t *pud, unsigned long start, unsigned long end) | ||
722 | { | ||
723 | pmd_t *pmd = pmd_offset(pud, start); | ||
724 | |||
725 | /* | ||
726 | * Not on a 2MB page boundary? | ||
727 | */ | ||
728 | if (start & (PMD_SIZE - 1)) { | ||
729 | unsigned long next_page = (start + PMD_SIZE) & PMD_MASK; | ||
730 | unsigned long pre_end = min_t(unsigned long, end, next_page); | ||
731 | |||
732 | __unmap_pmd_range(pud, pmd, start, pre_end); | ||
733 | |||
734 | start = pre_end; | ||
735 | pmd++; | ||
736 | } | ||
737 | |||
738 | /* | ||
739 | * Try to unmap in 2M chunks. | ||
740 | */ | ||
741 | while (end - start >= PMD_SIZE) { | ||
742 | if (pmd_large(*pmd)) | ||
743 | pmd_clear(pmd); | ||
744 | else | ||
745 | __unmap_pmd_range(pud, pmd, start, start + PMD_SIZE); | ||
746 | |||
747 | start += PMD_SIZE; | ||
748 | pmd++; | ||
749 | } | ||
750 | |||
751 | /* | ||
752 | * 4K leftovers? | ||
753 | */ | ||
754 | if (start < end) | ||
755 | return __unmap_pmd_range(pud, pmd, start, end); | ||
756 | |||
757 | /* | ||
758 | * Try again to free the PMD page if haven't succeeded above. | ||
759 | */ | ||
760 | if (!pud_none(*pud)) | ||
761 | if (try_to_free_pmd_page((pmd_t *)pud_page_vaddr(*pud))) | ||
762 | pud_clear(pud); | ||
763 | } | ||
764 | |||
765 | static void unmap_pud_range(pgd_t *pgd, unsigned long start, unsigned long end) | ||
766 | { | ||
767 | pud_t *pud = pud_offset(pgd, start); | ||
768 | |||
769 | /* | ||
770 | * Not on a GB page boundary? | ||
771 | */ | ||
772 | if (start & (PUD_SIZE - 1)) { | ||
773 | unsigned long next_page = (start + PUD_SIZE) & PUD_MASK; | ||
774 | unsigned long pre_end = min_t(unsigned long, end, next_page); | ||
775 | |||
776 | unmap_pmd_range(pud, start, pre_end); | ||
777 | |||
778 | start = pre_end; | ||
779 | pud++; | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * Try to unmap in 1G chunks? | ||
784 | */ | ||
785 | while (end - start >= PUD_SIZE) { | ||
786 | |||
787 | if (pud_large(*pud)) | ||
788 | pud_clear(pud); | ||
789 | else | ||
790 | unmap_pmd_range(pud, start, start + PUD_SIZE); | ||
791 | |||
792 | start += PUD_SIZE; | ||
793 | pud++; | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * 2M leftovers? | ||
798 | */ | ||
799 | if (start < end) | ||
800 | unmap_pmd_range(pud, start, end); | ||
801 | |||
802 | /* | ||
803 | * No need to try to free the PUD page because we'll free it in | ||
804 | * populate_pgd's error path | ||
805 | */ | ||
806 | } | ||
807 | |||
808 | static int alloc_pte_page(pmd_t *pmd) | ||
809 | { | ||
810 | pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK); | ||
811 | if (!pte) | ||
812 | return -1; | ||
813 | |||
814 | set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE)); | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | static int alloc_pmd_page(pud_t *pud) | ||
819 | { | ||
820 | pmd_t *pmd = (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK); | ||
821 | if (!pmd) | ||
822 | return -1; | ||
823 | |||
824 | set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE)); | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | static void populate_pte(struct cpa_data *cpa, | ||
829 | unsigned long start, unsigned long end, | ||
830 | unsigned num_pages, pmd_t *pmd, pgprot_t pgprot) | ||
831 | { | ||
832 | pte_t *pte; | ||
833 | |||
834 | pte = pte_offset_kernel(pmd, start); | ||
835 | |||
836 | while (num_pages-- && start < end) { | ||
837 | |||
838 | /* deal with the NX bit */ | ||
839 | if (!(pgprot_val(pgprot) & _PAGE_NX)) | ||
840 | cpa->pfn &= ~_PAGE_NX; | ||
841 | |||
842 | set_pte(pte, pfn_pte(cpa->pfn >> PAGE_SHIFT, pgprot)); | ||
843 | |||
844 | start += PAGE_SIZE; | ||
845 | cpa->pfn += PAGE_SIZE; | ||
846 | pte++; | ||
847 | } | ||
848 | } | ||
849 | |||
850 | static int populate_pmd(struct cpa_data *cpa, | ||
851 | unsigned long start, unsigned long end, | ||
852 | unsigned num_pages, pud_t *pud, pgprot_t pgprot) | ||
853 | { | ||
854 | unsigned int cur_pages = 0; | ||
855 | pmd_t *pmd; | ||
856 | |||
857 | /* | ||
858 | * Not on a 2M boundary? | ||
859 | */ | ||
860 | if (start & (PMD_SIZE - 1)) { | ||
861 | unsigned long pre_end = start + (num_pages << PAGE_SHIFT); | ||
862 | unsigned long next_page = (start + PMD_SIZE) & PMD_MASK; | ||
863 | |||
864 | pre_end = min_t(unsigned long, pre_end, next_page); | ||
865 | cur_pages = (pre_end - start) >> PAGE_SHIFT; | ||
866 | cur_pages = min_t(unsigned int, num_pages, cur_pages); | ||
867 | |||
868 | /* | ||
869 | * Need a PTE page? | ||
870 | */ | ||
871 | pmd = pmd_offset(pud, start); | ||
872 | if (pmd_none(*pmd)) | ||
873 | if (alloc_pte_page(pmd)) | ||
874 | return -1; | ||
875 | |||
876 | populate_pte(cpa, start, pre_end, cur_pages, pmd, pgprot); | ||
877 | |||
878 | start = pre_end; | ||
879 | } | ||
880 | |||
881 | /* | ||
882 | * We mapped them all? | ||
883 | */ | ||
884 | if (num_pages == cur_pages) | ||
885 | return cur_pages; | ||
886 | |||
887 | while (end - start >= PMD_SIZE) { | ||
888 | |||
889 | /* | ||
890 | * We cannot use a 1G page so allocate a PMD page if needed. | ||
891 | */ | ||
892 | if (pud_none(*pud)) | ||
893 | if (alloc_pmd_page(pud)) | ||
894 | return -1; | ||
895 | |||
896 | pmd = pmd_offset(pud, start); | ||
897 | |||
898 | set_pmd(pmd, __pmd(cpa->pfn | _PAGE_PSE | massage_pgprot(pgprot))); | ||
899 | |||
900 | start += PMD_SIZE; | ||
901 | cpa->pfn += PMD_SIZE; | ||
902 | cur_pages += PMD_SIZE >> PAGE_SHIFT; | ||
903 | } | ||
904 | |||
905 | /* | ||
906 | * Map trailing 4K pages. | ||
907 | */ | ||
908 | if (start < end) { | ||
909 | pmd = pmd_offset(pud, start); | ||
910 | if (pmd_none(*pmd)) | ||
911 | if (alloc_pte_page(pmd)) | ||
912 | return -1; | ||
913 | |||
914 | populate_pte(cpa, start, end, num_pages - cur_pages, | ||
915 | pmd, pgprot); | ||
916 | } | ||
917 | return num_pages; | ||
918 | } | ||
919 | |||
920 | static int populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd, | ||
921 | pgprot_t pgprot) | ||
922 | { | ||
923 | pud_t *pud; | ||
924 | unsigned long end; | ||
925 | int cur_pages = 0; | ||
926 | |||
927 | end = start + (cpa->numpages << PAGE_SHIFT); | ||
928 | |||
929 | /* | ||
930 | * Not on a Gb page boundary? => map everything up to it with | ||
931 | * smaller pages. | ||
932 | */ | ||
933 | if (start & (PUD_SIZE - 1)) { | ||
934 | unsigned long pre_end; | ||
935 | unsigned long next_page = (start + PUD_SIZE) & PUD_MASK; | ||
936 | |||
937 | pre_end = min_t(unsigned long, end, next_page); | ||
938 | cur_pages = (pre_end - start) >> PAGE_SHIFT; | ||
939 | cur_pages = min_t(int, (int)cpa->numpages, cur_pages); | ||
940 | |||
941 | pud = pud_offset(pgd, start); | ||
942 | |||
943 | /* | ||
944 | * Need a PMD page? | ||
945 | */ | ||
946 | if (pud_none(*pud)) | ||
947 | if (alloc_pmd_page(pud)) | ||
948 | return -1; | ||
949 | |||
950 | cur_pages = populate_pmd(cpa, start, pre_end, cur_pages, | ||
951 | pud, pgprot); | ||
952 | if (cur_pages < 0) | ||
953 | return cur_pages; | ||
954 | |||
955 | start = pre_end; | ||
956 | } | ||
957 | |||
958 | /* We mapped them all? */ | ||
959 | if (cpa->numpages == cur_pages) | ||
960 | return cur_pages; | ||
961 | |||
962 | pud = pud_offset(pgd, start); | ||
963 | |||
964 | /* | ||
965 | * Map everything starting from the Gb boundary, possibly with 1G pages | ||
966 | */ | ||
967 | while (end - start >= PUD_SIZE) { | ||
968 | set_pud(pud, __pud(cpa->pfn | _PAGE_PSE | massage_pgprot(pgprot))); | ||
969 | |||
970 | start += PUD_SIZE; | ||
971 | cpa->pfn += PUD_SIZE; | ||
972 | cur_pages += PUD_SIZE >> PAGE_SHIFT; | ||
973 | pud++; | ||
974 | } | ||
975 | |||
976 | /* Map trailing leftover */ | ||
977 | if (start < end) { | ||
978 | int tmp; | ||
979 | |||
980 | pud = pud_offset(pgd, start); | ||
981 | if (pud_none(*pud)) | ||
982 | if (alloc_pmd_page(pud)) | ||
983 | return -1; | ||
984 | |||
985 | tmp = populate_pmd(cpa, start, end, cpa->numpages - cur_pages, | ||
986 | pud, pgprot); | ||
987 | if (tmp < 0) | ||
988 | return cur_pages; | ||
989 | |||
990 | cur_pages += tmp; | ||
991 | } | ||
992 | return cur_pages; | ||
993 | } | ||
994 | |||
995 | /* | ||
996 | * Restrictions for kernel page table do not necessarily apply when mapping in | ||
997 | * an alternate PGD. | ||
998 | */ | ||
999 | static int populate_pgd(struct cpa_data *cpa, unsigned long addr) | ||
1000 | { | ||
1001 | pgprot_t pgprot = __pgprot(_KERNPG_TABLE); | ||
1002 | bool allocd_pgd = false; | ||
1003 | pgd_t *pgd_entry; | ||
1004 | pud_t *pud = NULL; /* shut up gcc */ | ||
1005 | int ret; | ||
1006 | |||
1007 | pgd_entry = cpa->pgd + pgd_index(addr); | ||
1008 | |||
1009 | /* | ||
1010 | * Allocate a PUD page and hand it down for mapping. | ||
1011 | */ | ||
1012 | if (pgd_none(*pgd_entry)) { | ||
1013 | pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK); | ||
1014 | if (!pud) | ||
1015 | return -1; | ||
1016 | |||
1017 | set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE)); | ||
1018 | allocd_pgd = true; | ||
1019 | } | ||
1020 | |||
1021 | pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr); | ||
1022 | pgprot_val(pgprot) |= pgprot_val(cpa->mask_set); | ||
1023 | |||
1024 | ret = populate_pud(cpa, addr, pgd_entry, pgprot); | ||
1025 | if (ret < 0) { | ||
1026 | unmap_pud_range(pgd_entry, addr, | ||
1027 | addr + (cpa->numpages << PAGE_SHIFT)); | ||
1028 | |||
1029 | if (allocd_pgd) { | ||
1030 | /* | ||
1031 | * If I allocated this PUD page, I can just as well | ||
1032 | * free it in this error path. | ||
1033 | */ | ||
1034 | pgd_clear(pgd_entry); | ||
1035 | free_page((unsigned long)pud); | ||
1036 | } | ||
1037 | return ret; | ||
1038 | } | ||
1039 | cpa->numpages = ret; | ||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
653 | static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr, | 1043 | static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr, |
654 | int primary) | 1044 | int primary) |
655 | { | 1045 | { |
1046 | if (cpa->pgd) | ||
1047 | return populate_pgd(cpa, vaddr); | ||
1048 | |||
656 | /* | 1049 | /* |
657 | * Ignore all non primary paths. | 1050 | * Ignore all non primary paths. |
658 | */ | 1051 | */ |
@@ -697,7 +1090,7 @@ static int __change_page_attr(struct cpa_data *cpa, int primary) | |||
697 | else | 1090 | else |
698 | address = *cpa->vaddr; | 1091 | address = *cpa->vaddr; |
699 | repeat: | 1092 | repeat: |
700 | kpte = lookup_address(address, &level); | 1093 | kpte = _lookup_address_cpa(cpa, address, &level); |
701 | if (!kpte) | 1094 | if (!kpte) |
702 | return __cpa_process_fault(cpa, address, primary); | 1095 | return __cpa_process_fault(cpa, address, primary); |
703 | 1096 | ||
@@ -761,7 +1154,7 @@ repeat: | |||
761 | /* | 1154 | /* |
762 | * We have to split the large page: | 1155 | * We have to split the large page: |
763 | */ | 1156 | */ |
764 | err = split_large_page(kpte, address); | 1157 | err = split_large_page(cpa, kpte, address); |
765 | if (!err) { | 1158 | if (!err) { |
766 | /* | 1159 | /* |
767 | * Do a global flush tlb after splitting the large page | 1160 | * Do a global flush tlb after splitting the large page |
@@ -910,6 +1303,8 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, | |||
910 | int ret, cache, checkalias; | 1303 | int ret, cache, checkalias; |
911 | unsigned long baddr = 0; | 1304 | unsigned long baddr = 0; |
912 | 1305 | ||
1306 | memset(&cpa, 0, sizeof(cpa)); | ||
1307 | |||
913 | /* | 1308 | /* |
914 | * Check, if we are requested to change a not supported | 1309 | * Check, if we are requested to change a not supported |
915 | * feature: | 1310 | * feature: |
@@ -1356,6 +1751,7 @@ static int __set_pages_p(struct page *page, int numpages) | |||
1356 | { | 1751 | { |
1357 | unsigned long tempaddr = (unsigned long) page_address(page); | 1752 | unsigned long tempaddr = (unsigned long) page_address(page); |
1358 | struct cpa_data cpa = { .vaddr = &tempaddr, | 1753 | struct cpa_data cpa = { .vaddr = &tempaddr, |
1754 | .pgd = NULL, | ||
1359 | .numpages = numpages, | 1755 | .numpages = numpages, |
1360 | .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), | 1756 | .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), |
1361 | .mask_clr = __pgprot(0), | 1757 | .mask_clr = __pgprot(0), |
@@ -1374,6 +1770,7 @@ static int __set_pages_np(struct page *page, int numpages) | |||
1374 | { | 1770 | { |
1375 | unsigned long tempaddr = (unsigned long) page_address(page); | 1771 | unsigned long tempaddr = (unsigned long) page_address(page); |
1376 | struct cpa_data cpa = { .vaddr = &tempaddr, | 1772 | struct cpa_data cpa = { .vaddr = &tempaddr, |
1773 | .pgd = NULL, | ||
1377 | .numpages = numpages, | 1774 | .numpages = numpages, |
1378 | .mask_set = __pgprot(0), | 1775 | .mask_set = __pgprot(0), |
1379 | .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), | 1776 | .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), |
@@ -1434,6 +1831,36 @@ bool kernel_page_present(struct page *page) | |||
1434 | 1831 | ||
1435 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | 1832 | #endif /* CONFIG_DEBUG_PAGEALLOC */ |
1436 | 1833 | ||
1834 | int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address, | ||
1835 | unsigned numpages, unsigned long page_flags) | ||
1836 | { | ||
1837 | int retval = -EINVAL; | ||
1838 | |||
1839 | struct cpa_data cpa = { | ||
1840 | .vaddr = &address, | ||
1841 | .pfn = pfn, | ||
1842 | .pgd = pgd, | ||
1843 | .numpages = numpages, | ||
1844 | .mask_set = __pgprot(0), | ||
1845 | .mask_clr = __pgprot(0), | ||
1846 | .flags = 0, | ||
1847 | }; | ||
1848 | |||
1849 | if (!(__supported_pte_mask & _PAGE_NX)) | ||
1850 | goto out; | ||
1851 | |||
1852 | if (!(page_flags & _PAGE_NX)) | ||
1853 | cpa.mask_clr = __pgprot(_PAGE_NX); | ||
1854 | |||
1855 | cpa.mask_set = __pgprot(_PAGE_PRESENT | page_flags); | ||
1856 | |||
1857 | retval = __change_page_attr_set_clr(&cpa, 0); | ||
1858 | __flush_tlb_all(); | ||
1859 | |||
1860 | out: | ||
1861 | return retval; | ||
1862 | } | ||
1863 | |||
1437 | /* | 1864 | /* |
1438 | * The testcases use internal knowledge of the implementation that shouldn't | 1865 | * The testcases use internal knowledge of the implementation that shouldn't |
1439 | * be exposed to the rest of the kernel. Include these directly here. | 1866 | * be exposed to the rest of the kernel. Include these directly here. |
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 26328e800869..4ed75dd81d05 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -359,15 +359,21 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
359 | EMIT2(0x89, 0xd0); /* mov %edx,%eax */ | 359 | EMIT2(0x89, 0xd0); /* mov %edx,%eax */ |
360 | break; | 360 | break; |
361 | case BPF_S_ALU_MOD_K: /* A %= K; */ | 361 | case BPF_S_ALU_MOD_K: /* A %= K; */ |
362 | if (K == 1) { | ||
363 | CLEAR_A(); | ||
364 | break; | ||
365 | } | ||
362 | EMIT2(0x31, 0xd2); /* xor %edx,%edx */ | 366 | EMIT2(0x31, 0xd2); /* xor %edx,%edx */ |
363 | EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */ | 367 | EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */ |
364 | EMIT2(0xf7, 0xf1); /* div %ecx */ | 368 | EMIT2(0xf7, 0xf1); /* div %ecx */ |
365 | EMIT2(0x89, 0xd0); /* mov %edx,%eax */ | 369 | EMIT2(0x89, 0xd0); /* mov %edx,%eax */ |
366 | break; | 370 | break; |
367 | case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ | 371 | case BPF_S_ALU_DIV_K: /* A /= K */ |
368 | EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */ | 372 | if (K == 1) |
369 | EMIT(K, 4); | 373 | break; |
370 | EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ | 374 | EMIT2(0x31, 0xd2); /* xor %edx,%edx */ |
375 | EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */ | ||
376 | EMIT2(0xf7, 0xf1); /* div %ecx */ | ||
371 | break; | 377 | break; |
372 | case BPF_S_ALU_AND_X: | 378 | case BPF_S_ALU_AND_X: |
373 | seen |= SEEN_XREG; | 379 | seen |= SEEN_XREG; |
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index b046e070e088..bca9e85daaa5 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <linux/delay.h> | 5 | #include <linux/delay.h> |
6 | #include <linux/dmi.h> | 6 | #include <linux/dmi.h> |
7 | #include <linux/pci.h> | 7 | #include <linux/pci.h> |
8 | #include <linux/init.h> | ||
9 | #include <linux/vgaarb.h> | 8 | #include <linux/vgaarb.h> |
10 | #include <asm/pci_x86.h> | 9 | #include <asm/pci_x86.h> |
11 | 10 | ||
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c index 51384ca727ad..84b9d672843d 100644 --- a/arch/x86/pci/intel_mid_pci.c +++ b/arch/x86/pci/intel_mid_pci.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/pci_x86.h> | 31 | #include <asm/pci_x86.h> |
32 | #include <asm/hw_irq.h> | 32 | #include <asm/hw_irq.h> |
33 | #include <asm/io_apic.h> | 33 | #include <asm/io_apic.h> |
34 | #include <asm/intel-mid.h> | ||
34 | 35 | ||
35 | #define PCIE_CAP_OFFSET 0x100 | 36 | #define PCIE_CAP_OFFSET 0x100 |
36 | 37 | ||
@@ -219,7 +220,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) | |||
219 | irq_attr.ioapic = mp_find_ioapic(dev->irq); | 220 | irq_attr.ioapic = mp_find_ioapic(dev->irq); |
220 | irq_attr.ioapic_pin = dev->irq; | 221 | irq_attr.ioapic_pin = dev->irq; |
221 | irq_attr.trigger = 1; /* level */ | 222 | irq_attr.trigger = 1; /* level */ |
222 | irq_attr.polarity = 1; /* active low */ | 223 | if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER) |
224 | irq_attr.polarity = 0; /* active high */ | ||
225 | else | ||
226 | irq_attr.polarity = 1; /* active low */ | ||
223 | io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr); | 227 | io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr); |
224 | 228 | ||
225 | return 0; | 229 | return 0; |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index cceb813044ef..d62ec87a2b26 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -12,6 +12,8 @@ | |||
12 | * Bibo Mao <bibo.mao@intel.com> | 12 | * Bibo Mao <bibo.mao@intel.com> |
13 | * Chandramouli Narayanan <mouli@linux.intel.com> | 13 | * Chandramouli Narayanan <mouli@linux.intel.com> |
14 | * Huang Ying <ying.huang@intel.com> | 14 | * Huang Ying <ying.huang@intel.com> |
15 | * Copyright (C) 2013 SuSE Labs | ||
16 | * Borislav Petkov <bp@suse.de> - runtime services VA mapping | ||
15 | * | 17 | * |
16 | * Copied from efi_32.c to eliminate the duplicated code between EFI | 18 | * Copied from efi_32.c to eliminate the duplicated code between EFI |
17 | * 32/64 support code. --ying 2007-10-26 | 19 | * 32/64 support code. --ying 2007-10-26 |
@@ -51,7 +53,7 @@ | |||
51 | #include <asm/x86_init.h> | 53 | #include <asm/x86_init.h> |
52 | #include <asm/rtc.h> | 54 | #include <asm/rtc.h> |
53 | 55 | ||
54 | #define EFI_DEBUG 1 | 56 | #define EFI_DEBUG |
55 | 57 | ||
56 | #define EFI_MIN_RESERVE 5120 | 58 | #define EFI_MIN_RESERVE 5120 |
57 | 59 | ||
@@ -74,6 +76,8 @@ static __initdata efi_config_table_type_t arch_tables[] = { | |||
74 | {NULL_GUID, NULL, NULL}, | 76 | {NULL_GUID, NULL, NULL}, |
75 | }; | 77 | }; |
76 | 78 | ||
79 | u64 efi_setup; /* efi setup_data physical address */ | ||
80 | |||
77 | /* | 81 | /* |
78 | * Returns 1 if 'facility' is enabled, 0 otherwise. | 82 | * Returns 1 if 'facility' is enabled, 0 otherwise. |
79 | */ | 83 | */ |
@@ -110,7 +114,6 @@ static int __init setup_storage_paranoia(char *arg) | |||
110 | } | 114 | } |
111 | early_param("efi_no_storage_paranoia", setup_storage_paranoia); | 115 | early_param("efi_no_storage_paranoia", setup_storage_paranoia); |
112 | 116 | ||
113 | |||
114 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | 117 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) |
115 | { | 118 | { |
116 | unsigned long flags; | 119 | unsigned long flags; |
@@ -398,9 +401,9 @@ int __init efi_memblock_x86_reserve_range(void) | |||
398 | return 0; | 401 | return 0; |
399 | } | 402 | } |
400 | 403 | ||
401 | #if EFI_DEBUG | ||
402 | static void __init print_efi_memmap(void) | 404 | static void __init print_efi_memmap(void) |
403 | { | 405 | { |
406 | #ifdef EFI_DEBUG | ||
404 | efi_memory_desc_t *md; | 407 | efi_memory_desc_t *md; |
405 | void *p; | 408 | void *p; |
406 | int i; | 409 | int i; |
@@ -415,8 +418,8 @@ static void __init print_efi_memmap(void) | |||
415 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), | 418 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), |
416 | (md->num_pages >> (20 - EFI_PAGE_SHIFT))); | 419 | (md->num_pages >> (20 - EFI_PAGE_SHIFT))); |
417 | } | 420 | } |
418 | } | ||
419 | #endif /* EFI_DEBUG */ | 421 | #endif /* EFI_DEBUG */ |
422 | } | ||
420 | 423 | ||
421 | void __init efi_reserve_boot_services(void) | 424 | void __init efi_reserve_boot_services(void) |
422 | { | 425 | { |
@@ -436,7 +439,7 @@ void __init efi_reserve_boot_services(void) | |||
436 | * - Not within any part of the kernel | 439 | * - Not within any part of the kernel |
437 | * - Not the bios reserved area | 440 | * - Not the bios reserved area |
438 | */ | 441 | */ |
439 | if ((start+size >= __pa_symbol(_text) | 442 | if ((start + size > __pa_symbol(_text) |
440 | && start <= __pa_symbol(_end)) || | 443 | && start <= __pa_symbol(_end)) || |
441 | !e820_all_mapped(start, start+size, E820_RAM) || | 444 | !e820_all_mapped(start, start+size, E820_RAM) || |
442 | memblock_is_region_reserved(start, size)) { | 445 | memblock_is_region_reserved(start, size)) { |
@@ -489,18 +492,27 @@ static int __init efi_systab_init(void *phys) | |||
489 | { | 492 | { |
490 | if (efi_enabled(EFI_64BIT)) { | 493 | if (efi_enabled(EFI_64BIT)) { |
491 | efi_system_table_64_t *systab64; | 494 | efi_system_table_64_t *systab64; |
495 | struct efi_setup_data *data = NULL; | ||
492 | u64 tmp = 0; | 496 | u64 tmp = 0; |
493 | 497 | ||
498 | if (efi_setup) { | ||
499 | data = early_memremap(efi_setup, sizeof(*data)); | ||
500 | if (!data) | ||
501 | return -ENOMEM; | ||
502 | } | ||
494 | systab64 = early_ioremap((unsigned long)phys, | 503 | systab64 = early_ioremap((unsigned long)phys, |
495 | sizeof(*systab64)); | 504 | sizeof(*systab64)); |
496 | if (systab64 == NULL) { | 505 | if (systab64 == NULL) { |
497 | pr_err("Couldn't map the system table!\n"); | 506 | pr_err("Couldn't map the system table!\n"); |
507 | if (data) | ||
508 | early_iounmap(data, sizeof(*data)); | ||
498 | return -ENOMEM; | 509 | return -ENOMEM; |
499 | } | 510 | } |
500 | 511 | ||
501 | efi_systab.hdr = systab64->hdr; | 512 | efi_systab.hdr = systab64->hdr; |
502 | efi_systab.fw_vendor = systab64->fw_vendor; | 513 | efi_systab.fw_vendor = data ? (unsigned long)data->fw_vendor : |
503 | tmp |= systab64->fw_vendor; | 514 | systab64->fw_vendor; |
515 | tmp |= data ? data->fw_vendor : systab64->fw_vendor; | ||
504 | efi_systab.fw_revision = systab64->fw_revision; | 516 | efi_systab.fw_revision = systab64->fw_revision; |
505 | efi_systab.con_in_handle = systab64->con_in_handle; | 517 | efi_systab.con_in_handle = systab64->con_in_handle; |
506 | tmp |= systab64->con_in_handle; | 518 | tmp |= systab64->con_in_handle; |
@@ -514,15 +526,20 @@ static int __init efi_systab_init(void *phys) | |||
514 | tmp |= systab64->stderr_handle; | 526 | tmp |= systab64->stderr_handle; |
515 | efi_systab.stderr = systab64->stderr; | 527 | efi_systab.stderr = systab64->stderr; |
516 | tmp |= systab64->stderr; | 528 | tmp |= systab64->stderr; |
517 | efi_systab.runtime = (void *)(unsigned long)systab64->runtime; | 529 | efi_systab.runtime = data ? |
518 | tmp |= systab64->runtime; | 530 | (void *)(unsigned long)data->runtime : |
531 | (void *)(unsigned long)systab64->runtime; | ||
532 | tmp |= data ? data->runtime : systab64->runtime; | ||
519 | efi_systab.boottime = (void *)(unsigned long)systab64->boottime; | 533 | efi_systab.boottime = (void *)(unsigned long)systab64->boottime; |
520 | tmp |= systab64->boottime; | 534 | tmp |= systab64->boottime; |
521 | efi_systab.nr_tables = systab64->nr_tables; | 535 | efi_systab.nr_tables = systab64->nr_tables; |
522 | efi_systab.tables = systab64->tables; | 536 | efi_systab.tables = data ? (unsigned long)data->tables : |
523 | tmp |= systab64->tables; | 537 | systab64->tables; |
538 | tmp |= data ? data->tables : systab64->tables; | ||
524 | 539 | ||
525 | early_iounmap(systab64, sizeof(*systab64)); | 540 | early_iounmap(systab64, sizeof(*systab64)); |
541 | if (data) | ||
542 | early_iounmap(data, sizeof(*data)); | ||
526 | #ifdef CONFIG_X86_32 | 543 | #ifdef CONFIG_X86_32 |
527 | if (tmp >> 32) { | 544 | if (tmp >> 32) { |
528 | pr_err("EFI data located above 4GB, disabling EFI.\n"); | 545 | pr_err("EFI data located above 4GB, disabling EFI.\n"); |
@@ -626,6 +643,62 @@ static int __init efi_memmap_init(void) | |||
626 | return 0; | 643 | return 0; |
627 | } | 644 | } |
628 | 645 | ||
646 | /* | ||
647 | * A number of config table entries get remapped to virtual addresses | ||
648 | * after entering EFI virtual mode. However, the kexec kernel requires | ||
649 | * their physical addresses therefore we pass them via setup_data and | ||
650 | * correct those entries to their respective physical addresses here. | ||
651 | * | ||
652 | * Currently only handles smbios which is necessary for some firmware | ||
653 | * implementation. | ||
654 | */ | ||
655 | static int __init efi_reuse_config(u64 tables, int nr_tables) | ||
656 | { | ||
657 | int i, sz, ret = 0; | ||
658 | void *p, *tablep; | ||
659 | struct efi_setup_data *data; | ||
660 | |||
661 | if (!efi_setup) | ||
662 | return 0; | ||
663 | |||
664 | if (!efi_enabled(EFI_64BIT)) | ||
665 | return 0; | ||
666 | |||
667 | data = early_memremap(efi_setup, sizeof(*data)); | ||
668 | if (!data) { | ||
669 | ret = -ENOMEM; | ||
670 | goto out; | ||
671 | } | ||
672 | |||
673 | if (!data->smbios) | ||
674 | goto out_memremap; | ||
675 | |||
676 | sz = sizeof(efi_config_table_64_t); | ||
677 | |||
678 | p = tablep = early_memremap(tables, nr_tables * sz); | ||
679 | if (!p) { | ||
680 | pr_err("Could not map Configuration table!\n"); | ||
681 | ret = -ENOMEM; | ||
682 | goto out_memremap; | ||
683 | } | ||
684 | |||
685 | for (i = 0; i < efi.systab->nr_tables; i++) { | ||
686 | efi_guid_t guid; | ||
687 | |||
688 | guid = ((efi_config_table_64_t *)p)->guid; | ||
689 | |||
690 | if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) | ||
691 | ((efi_config_table_64_t *)p)->table = data->smbios; | ||
692 | p += sz; | ||
693 | } | ||
694 | early_iounmap(tablep, nr_tables * sz); | ||
695 | |||
696 | out_memremap: | ||
697 | early_iounmap(data, sizeof(*data)); | ||
698 | out: | ||
699 | return ret; | ||
700 | } | ||
701 | |||
629 | void __init efi_init(void) | 702 | void __init efi_init(void) |
630 | { | 703 | { |
631 | efi_char16_t *c16; | 704 | efi_char16_t *c16; |
@@ -651,6 +724,10 @@ void __init efi_init(void) | |||
651 | 724 | ||
652 | set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); | 725 | set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); |
653 | 726 | ||
727 | efi.config_table = (unsigned long)efi.systab->tables; | ||
728 | efi.fw_vendor = (unsigned long)efi.systab->fw_vendor; | ||
729 | efi.runtime = (unsigned long)efi.systab->runtime; | ||
730 | |||
654 | /* | 731 | /* |
655 | * Show what we know for posterity | 732 | * Show what we know for posterity |
656 | */ | 733 | */ |
@@ -667,6 +744,9 @@ void __init efi_init(void) | |||
667 | efi.systab->hdr.revision >> 16, | 744 | efi.systab->hdr.revision >> 16, |
668 | efi.systab->hdr.revision & 0xffff, vendor); | 745 | efi.systab->hdr.revision & 0xffff, vendor); |
669 | 746 | ||
747 | if (efi_reuse_config(efi.systab->tables, efi.systab->nr_tables)) | ||
748 | return; | ||
749 | |||
670 | if (efi_config_init(arch_tables)) | 750 | if (efi_config_init(arch_tables)) |
671 | return; | 751 | return; |
672 | 752 | ||
@@ -684,15 +764,12 @@ void __init efi_init(void) | |||
684 | return; | 764 | return; |
685 | set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); | 765 | set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); |
686 | } | 766 | } |
687 | |||
688 | if (efi_memmap_init()) | 767 | if (efi_memmap_init()) |
689 | return; | 768 | return; |
690 | 769 | ||
691 | set_bit(EFI_MEMMAP, &x86_efi_facility); | 770 | set_bit(EFI_MEMMAP, &x86_efi_facility); |
692 | 771 | ||
693 | #if EFI_DEBUG | ||
694 | print_efi_memmap(); | 772 | print_efi_memmap(); |
695 | #endif | ||
696 | } | 773 | } |
697 | 774 | ||
698 | void __init efi_late_init(void) | 775 | void __init efi_late_init(void) |
@@ -741,36 +818,38 @@ void efi_memory_uc(u64 addr, unsigned long size) | |||
741 | set_memory_uc(addr, npages); | 818 | set_memory_uc(addr, npages); |
742 | } | 819 | } |
743 | 820 | ||
744 | /* | 821 | void __init old_map_region(efi_memory_desc_t *md) |
745 | * This function will switch the EFI runtime services to virtual mode. | ||
746 | * Essentially, look through the EFI memmap and map every region that | ||
747 | * has the runtime attribute bit set in its memory descriptor and update | ||
748 | * that memory descriptor with the virtual address obtained from ioremap(). | ||
749 | * This enables the runtime services to be called without having to | ||
750 | * thunk back into physical mode for every invocation. | ||
751 | */ | ||
752 | void __init efi_enter_virtual_mode(void) | ||
753 | { | 822 | { |
754 | efi_memory_desc_t *md, *prev_md = NULL; | 823 | u64 start_pfn, end_pfn, end; |
755 | efi_status_t status; | ||
756 | unsigned long size; | 824 | unsigned long size; |
757 | u64 end, systab, start_pfn, end_pfn; | 825 | void *va; |
758 | void *p, *va, *new_memmap = NULL; | ||
759 | int count = 0; | ||
760 | 826 | ||
761 | efi.systab = NULL; | 827 | start_pfn = PFN_DOWN(md->phys_addr); |
828 | size = md->num_pages << PAGE_SHIFT; | ||
829 | end = md->phys_addr + size; | ||
830 | end_pfn = PFN_UP(end); | ||
762 | 831 | ||
763 | /* | 832 | if (pfn_range_is_mapped(start_pfn, end_pfn)) { |
764 | * We don't do virtual mode, since we don't do runtime services, on | 833 | va = __va(md->phys_addr); |
765 | * non-native EFI | ||
766 | */ | ||
767 | 834 | ||
768 | if (!efi_is_native()) { | 835 | if (!(md->attribute & EFI_MEMORY_WB)) |
769 | efi_unmap_memmap(); | 836 | efi_memory_uc((u64)(unsigned long)va, size); |
770 | return; | 837 | } else |
771 | } | 838 | va = efi_ioremap(md->phys_addr, size, |
839 | md->type, md->attribute); | ||
840 | |||
841 | md->virt_addr = (u64) (unsigned long) va; | ||
842 | if (!va) | ||
843 | pr_err("ioremap of 0x%llX failed!\n", | ||
844 | (unsigned long long)md->phys_addr); | ||
845 | } | ||
846 | |||
847 | /* Merge contiguous regions of the same type and attribute */ | ||
848 | static void __init efi_merge_regions(void) | ||
849 | { | ||
850 | void *p; | ||
851 | efi_memory_desc_t *md, *prev_md = NULL; | ||
772 | 852 | ||
773 | /* Merge contiguous regions of the same type and attribute */ | ||
774 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 853 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
775 | u64 prev_size; | 854 | u64 prev_size; |
776 | md = p; | 855 | md = p; |
@@ -796,6 +875,77 @@ void __init efi_enter_virtual_mode(void) | |||
796 | } | 875 | } |
797 | prev_md = md; | 876 | prev_md = md; |
798 | } | 877 | } |
878 | } | ||
879 | |||
880 | static void __init get_systab_virt_addr(efi_memory_desc_t *md) | ||
881 | { | ||
882 | unsigned long size; | ||
883 | u64 end, systab; | ||
884 | |||
885 | size = md->num_pages << EFI_PAGE_SHIFT; | ||
886 | end = md->phys_addr + size; | ||
887 | systab = (u64)(unsigned long)efi_phys.systab; | ||
888 | if (md->phys_addr <= systab && systab < end) { | ||
889 | systab += md->virt_addr - md->phys_addr; | ||
890 | efi.systab = (efi_system_table_t *)(unsigned long)systab; | ||
891 | } | ||
892 | } | ||
893 | |||
894 | static int __init save_runtime_map(void) | ||
895 | { | ||
896 | efi_memory_desc_t *md; | ||
897 | void *tmp, *p, *q = NULL; | ||
898 | int count = 0; | ||
899 | |||
900 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
901 | md = p; | ||
902 | |||
903 | if (!(md->attribute & EFI_MEMORY_RUNTIME) || | ||
904 | (md->type == EFI_BOOT_SERVICES_CODE) || | ||
905 | (md->type == EFI_BOOT_SERVICES_DATA)) | ||
906 | continue; | ||
907 | tmp = krealloc(q, (count + 1) * memmap.desc_size, GFP_KERNEL); | ||
908 | if (!tmp) | ||
909 | goto out; | ||
910 | q = tmp; | ||
911 | |||
912 | memcpy(q + count * memmap.desc_size, md, memmap.desc_size); | ||
913 | count++; | ||
914 | } | ||
915 | |||
916 | efi_runtime_map_setup(q, count, memmap.desc_size); | ||
917 | |||
918 | return 0; | ||
919 | out: | ||
920 | kfree(q); | ||
921 | return -ENOMEM; | ||
922 | } | ||
923 | |||
924 | /* | ||
925 | * Map efi regions which were passed via setup_data. The virt_addr is a fixed | ||
926 | * addr which was used in first kernel of a kexec boot. | ||
927 | */ | ||
928 | static void __init efi_map_regions_fixed(void) | ||
929 | { | ||
930 | void *p; | ||
931 | efi_memory_desc_t *md; | ||
932 | |||
933 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
934 | md = p; | ||
935 | efi_map_region_fixed(md); /* FIXME: add error handling */ | ||
936 | get_systab_virt_addr(md); | ||
937 | } | ||
938 | |||
939 | } | ||
940 | |||
941 | /* | ||
942 | * Map efi memory ranges for runtime serivce and update new_memmap with virtual | ||
943 | * addresses. | ||
944 | */ | ||
945 | static void * __init efi_map_regions(int *count) | ||
946 | { | ||
947 | efi_memory_desc_t *md; | ||
948 | void *p, *tmp, *new_memmap = NULL; | ||
799 | 949 | ||
800 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 950 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
801 | md = p; | 951 | md = p; |
@@ -807,53 +957,95 @@ void __init efi_enter_virtual_mode(void) | |||
807 | continue; | 957 | continue; |
808 | } | 958 | } |
809 | 959 | ||
810 | size = md->num_pages << EFI_PAGE_SHIFT; | 960 | efi_map_region(md); |
811 | end = md->phys_addr + size; | 961 | get_systab_virt_addr(md); |
812 | 962 | ||
813 | start_pfn = PFN_DOWN(md->phys_addr); | 963 | tmp = krealloc(new_memmap, (*count + 1) * memmap.desc_size, |
814 | end_pfn = PFN_UP(end); | 964 | GFP_KERNEL); |
815 | if (pfn_range_is_mapped(start_pfn, end_pfn)) { | 965 | if (!tmp) |
816 | va = __va(md->phys_addr); | 966 | goto out; |
967 | new_memmap = tmp; | ||
968 | memcpy(new_memmap + (*count * memmap.desc_size), md, | ||
969 | memmap.desc_size); | ||
970 | (*count)++; | ||
971 | } | ||
817 | 972 | ||
818 | if (!(md->attribute & EFI_MEMORY_WB)) | 973 | return new_memmap; |
819 | efi_memory_uc((u64)(unsigned long)va, size); | 974 | out: |
820 | } else | 975 | kfree(new_memmap); |
821 | va = efi_ioremap(md->phys_addr, size, | 976 | return NULL; |
822 | md->type, md->attribute); | 977 | } |
978 | |||
979 | /* | ||
980 | * This function will switch the EFI runtime services to virtual mode. | ||
981 | * Essentially, we look through the EFI memmap and map every region that | ||
982 | * has the runtime attribute bit set in its memory descriptor into the | ||
983 | * ->trampoline_pgd page table using a top-down VA allocation scheme. | ||
984 | * | ||
985 | * The old method which used to update that memory descriptor with the | ||
986 | * virtual address obtained from ioremap() is still supported when the | ||
987 | * kernel is booted with efi=old_map on its command line. Same old | ||
988 | * method enabled the runtime services to be called without having to | ||
989 | * thunk back into physical mode for every invocation. | ||
990 | * | ||
991 | * The new method does a pagetable switch in a preemption-safe manner | ||
992 | * so that we're in a different address space when calling a runtime | ||
993 | * function. For function arguments passing we do copy the PGDs of the | ||
994 | * kernel page table into ->trampoline_pgd prior to each call. | ||
995 | * | ||
996 | * Specially for kexec boot, efi runtime maps in previous kernel should | ||
997 | * be passed in via setup_data. In that case runtime ranges will be mapped | ||
998 | * to the same virtual addresses as the first kernel. | ||
999 | */ | ||
1000 | void __init efi_enter_virtual_mode(void) | ||
1001 | { | ||
1002 | efi_status_t status; | ||
1003 | void *new_memmap = NULL; | ||
1004 | int err, count = 0; | ||
823 | 1005 | ||
824 | md->virt_addr = (u64) (unsigned long) va; | 1006 | efi.systab = NULL; |
825 | 1007 | ||
826 | if (!va) { | 1008 | /* |
827 | pr_err("ioremap of 0x%llX failed!\n", | 1009 | * We don't do virtual mode, since we don't do runtime services, on |
828 | (unsigned long long)md->phys_addr); | 1010 | * non-native EFI |
829 | continue; | 1011 | */ |
830 | } | 1012 | if (!efi_is_native()) { |
1013 | efi_unmap_memmap(); | ||
1014 | return; | ||
1015 | } | ||
831 | 1016 | ||
832 | systab = (u64) (unsigned long) efi_phys.systab; | 1017 | if (efi_setup) { |
833 | if (md->phys_addr <= systab && systab < end) { | 1018 | efi_map_regions_fixed(); |
834 | systab += md->virt_addr - md->phys_addr; | 1019 | } else { |
835 | efi.systab = (efi_system_table_t *) (unsigned long) systab; | 1020 | efi_merge_regions(); |
1021 | new_memmap = efi_map_regions(&count); | ||
1022 | if (!new_memmap) { | ||
1023 | pr_err("Error reallocating memory, EFI runtime non-functional!\n"); | ||
1024 | return; | ||
836 | } | 1025 | } |
837 | new_memmap = krealloc(new_memmap, | ||
838 | (count + 1) * memmap.desc_size, | ||
839 | GFP_KERNEL); | ||
840 | memcpy(new_memmap + (count * memmap.desc_size), md, | ||
841 | memmap.desc_size); | ||
842 | count++; | ||
843 | } | 1026 | } |
844 | 1027 | ||
1028 | err = save_runtime_map(); | ||
1029 | if (err) | ||
1030 | pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n"); | ||
1031 | |||
845 | BUG_ON(!efi.systab); | 1032 | BUG_ON(!efi.systab); |
846 | 1033 | ||
847 | status = phys_efi_set_virtual_address_map( | 1034 | efi_setup_page_tables(); |
848 | memmap.desc_size * count, | 1035 | efi_sync_low_kernel_mappings(); |
849 | memmap.desc_size, | ||
850 | memmap.desc_version, | ||
851 | (efi_memory_desc_t *)__pa(new_memmap)); | ||
852 | 1036 | ||
853 | if (status != EFI_SUCCESS) { | 1037 | if (!efi_setup) { |
854 | pr_alert("Unable to switch EFI into virtual mode " | 1038 | status = phys_efi_set_virtual_address_map( |
855 | "(status=%lx)!\n", status); | 1039 | memmap.desc_size * count, |
856 | panic("EFI call to SetVirtualAddressMap() failed!"); | 1040 | memmap.desc_size, |
1041 | memmap.desc_version, | ||
1042 | (efi_memory_desc_t *)__pa(new_memmap)); | ||
1043 | |||
1044 | if (status != EFI_SUCCESS) { | ||
1045 | pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n", | ||
1046 | status); | ||
1047 | panic("EFI call to SetVirtualAddressMap() failed!"); | ||
1048 | } | ||
857 | } | 1049 | } |
858 | 1050 | ||
859 | /* | 1051 | /* |
@@ -876,7 +1068,8 @@ void __init efi_enter_virtual_mode(void) | |||
876 | efi.query_variable_info = virt_efi_query_variable_info; | 1068 | efi.query_variable_info = virt_efi_query_variable_info; |
877 | efi.update_capsule = virt_efi_update_capsule; | 1069 | efi.update_capsule = virt_efi_update_capsule; |
878 | efi.query_capsule_caps = virt_efi_query_capsule_caps; | 1070 | efi.query_capsule_caps = virt_efi_query_capsule_caps; |
879 | if (__supported_pte_mask & _PAGE_NX) | 1071 | |
1072 | if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX)) | ||
880 | runtime_code_page_mkexec(); | 1073 | runtime_code_page_mkexec(); |
881 | 1074 | ||
882 | kfree(new_memmap); | 1075 | kfree(new_memmap); |
@@ -1006,3 +1199,15 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) | |||
1006 | return EFI_SUCCESS; | 1199 | return EFI_SUCCESS; |
1007 | } | 1200 | } |
1008 | EXPORT_SYMBOL_GPL(efi_query_variable_store); | 1201 | EXPORT_SYMBOL_GPL(efi_query_variable_store); |
1202 | |||
1203 | static int __init parse_efi_cmdline(char *str) | ||
1204 | { | ||
1205 | if (*str == '=') | ||
1206 | str++; | ||
1207 | |||
1208 | if (!strncmp(str, "old_map", 7)) | ||
1209 | set_bit(EFI_OLD_MEMMAP, &x86_efi_facility); | ||
1210 | |||
1211 | return 0; | ||
1212 | } | ||
1213 | early_param("efi", parse_efi_cmdline); | ||
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index 40e446941dd7..249b183cf417 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c | |||
@@ -37,9 +37,19 @@ | |||
37 | * claim EFI runtime service handler exclusively and to duplicate a memory in | 37 | * claim EFI runtime service handler exclusively and to duplicate a memory in |
38 | * low memory space say 0 - 3G. | 38 | * low memory space say 0 - 3G. |
39 | */ | 39 | */ |
40 | |||
41 | static unsigned long efi_rt_eflags; | 40 | static unsigned long efi_rt_eflags; |
42 | 41 | ||
42 | void efi_sync_low_kernel_mappings(void) {} | ||
43 | void efi_setup_page_tables(void) {} | ||
44 | |||
45 | void __init efi_map_region(efi_memory_desc_t *md) | ||
46 | { | ||
47 | old_map_region(md); | ||
48 | } | ||
49 | |||
50 | void __init efi_map_region_fixed(efi_memory_desc_t *md) {} | ||
51 | void __init parse_efi_setup(u64 phys_addr, u32 data_len) {} | ||
52 | |||
43 | void efi_call_phys_prelog(void) | 53 | void efi_call_phys_prelog(void) |
44 | { | 54 | { |
45 | struct desc_ptr gdt_descr; | 55 | struct desc_ptr gdt_descr; |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 39a0e7f1f0a3..6284f158a47d 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
@@ -38,10 +38,28 @@ | |||
38 | #include <asm/efi.h> | 38 | #include <asm/efi.h> |
39 | #include <asm/cacheflush.h> | 39 | #include <asm/cacheflush.h> |
40 | #include <asm/fixmap.h> | 40 | #include <asm/fixmap.h> |
41 | #include <asm/realmode.h> | ||
41 | 42 | ||
42 | static pgd_t *save_pgd __initdata; | 43 | static pgd_t *save_pgd __initdata; |
43 | static unsigned long efi_flags __initdata; | 44 | static unsigned long efi_flags __initdata; |
44 | 45 | ||
46 | /* | ||
47 | * We allocate runtime services regions bottom-up, starting from -4G, i.e. | ||
48 | * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G. | ||
49 | */ | ||
50 | static u64 efi_va = -4 * (1UL << 30); | ||
51 | #define EFI_VA_END (-68 * (1UL << 30)) | ||
52 | |||
53 | /* | ||
54 | * Scratch space used for switching the pagetable in the EFI stub | ||
55 | */ | ||
56 | struct efi_scratch { | ||
57 | u64 r15; | ||
58 | u64 prev_cr3; | ||
59 | pgd_t *efi_pgt; | ||
60 | bool use_pgd; | ||
61 | }; | ||
62 | |||
45 | static void __init early_code_mapping_set_exec(int executable) | 63 | static void __init early_code_mapping_set_exec(int executable) |
46 | { | 64 | { |
47 | efi_memory_desc_t *md; | 65 | efi_memory_desc_t *md; |
@@ -65,6 +83,9 @@ void __init efi_call_phys_prelog(void) | |||
65 | int pgd; | 83 | int pgd; |
66 | int n_pgds; | 84 | int n_pgds; |
67 | 85 | ||
86 | if (!efi_enabled(EFI_OLD_MEMMAP)) | ||
87 | return; | ||
88 | |||
68 | early_code_mapping_set_exec(1); | 89 | early_code_mapping_set_exec(1); |
69 | local_irq_save(efi_flags); | 90 | local_irq_save(efi_flags); |
70 | 91 | ||
@@ -86,6 +107,10 @@ void __init efi_call_phys_epilog(void) | |||
86 | */ | 107 | */ |
87 | int pgd; | 108 | int pgd; |
88 | int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); | 109 | int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); |
110 | |||
111 | if (!efi_enabled(EFI_OLD_MEMMAP)) | ||
112 | return; | ||
113 | |||
89 | for (pgd = 0; pgd < n_pgds; pgd++) | 114 | for (pgd = 0; pgd < n_pgds; pgd++) |
90 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); | 115 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); |
91 | kfree(save_pgd); | 116 | kfree(save_pgd); |
@@ -94,6 +119,96 @@ void __init efi_call_phys_epilog(void) | |||
94 | early_code_mapping_set_exec(0); | 119 | early_code_mapping_set_exec(0); |
95 | } | 120 | } |
96 | 121 | ||
122 | /* | ||
123 | * Add low kernel mappings for passing arguments to EFI functions. | ||
124 | */ | ||
125 | void efi_sync_low_kernel_mappings(void) | ||
126 | { | ||
127 | unsigned num_pgds; | ||
128 | pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd); | ||
129 | |||
130 | if (efi_enabled(EFI_OLD_MEMMAP)) | ||
131 | return; | ||
132 | |||
133 | num_pgds = pgd_index(MODULES_END - 1) - pgd_index(PAGE_OFFSET); | ||
134 | |||
135 | memcpy(pgd + pgd_index(PAGE_OFFSET), | ||
136 | init_mm.pgd + pgd_index(PAGE_OFFSET), | ||
137 | sizeof(pgd_t) * num_pgds); | ||
138 | } | ||
139 | |||
140 | void efi_setup_page_tables(void) | ||
141 | { | ||
142 | efi_scratch.efi_pgt = (pgd_t *)(unsigned long)real_mode_header->trampoline_pgd; | ||
143 | |||
144 | if (!efi_enabled(EFI_OLD_MEMMAP)) | ||
145 | efi_scratch.use_pgd = true; | ||
146 | } | ||
147 | |||
148 | static void __init __map_region(efi_memory_desc_t *md, u64 va) | ||
149 | { | ||
150 | pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd); | ||
151 | unsigned long pf = 0; | ||
152 | |||
153 | if (!(md->attribute & EFI_MEMORY_WB)) | ||
154 | pf |= _PAGE_PCD; | ||
155 | |||
156 | if (kernel_map_pages_in_pgd(pgd, md->phys_addr, va, md->num_pages, pf)) | ||
157 | pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n", | ||
158 | md->phys_addr, va); | ||
159 | } | ||
160 | |||
161 | void __init efi_map_region(efi_memory_desc_t *md) | ||
162 | { | ||
163 | unsigned long size = md->num_pages << PAGE_SHIFT; | ||
164 | u64 pa = md->phys_addr; | ||
165 | |||
166 | if (efi_enabled(EFI_OLD_MEMMAP)) | ||
167 | return old_map_region(md); | ||
168 | |||
169 | /* | ||
170 | * Make sure the 1:1 mappings are present as a catch-all for b0rked | ||
171 | * firmware which doesn't update all internal pointers after switching | ||
172 | * to virtual mode and would otherwise crap on us. | ||
173 | */ | ||
174 | __map_region(md, md->phys_addr); | ||
175 | |||
176 | efi_va -= size; | ||
177 | |||
178 | /* Is PA 2M-aligned? */ | ||
179 | if (!(pa & (PMD_SIZE - 1))) { | ||
180 | efi_va &= PMD_MASK; | ||
181 | } else { | ||
182 | u64 pa_offset = pa & (PMD_SIZE - 1); | ||
183 | u64 prev_va = efi_va; | ||
184 | |||
185 | /* get us the same offset within this 2M page */ | ||
186 | efi_va = (efi_va & PMD_MASK) + pa_offset; | ||
187 | |||
188 | if (efi_va > prev_va) | ||
189 | efi_va -= PMD_SIZE; | ||
190 | } | ||
191 | |||
192 | if (efi_va < EFI_VA_END) { | ||
193 | pr_warn(FW_WARN "VA address range overflow!\n"); | ||
194 | return; | ||
195 | } | ||
196 | |||
197 | /* Do the VA map */ | ||
198 | __map_region(md, efi_va); | ||
199 | md->virt_addr = efi_va; | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * kexec kernel will use efi_map_region_fixed to map efi runtime memory ranges. | ||
204 | * md->virt_addr is the original virtual address which had been mapped in kexec | ||
205 | * 1st kernel. | ||
206 | */ | ||
207 | void __init efi_map_region_fixed(efi_memory_desc_t *md) | ||
208 | { | ||
209 | __map_region(md, md->virt_addr); | ||
210 | } | ||
211 | |||
97 | void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, | 212 | void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, |
98 | u32 type, u64 attribute) | 213 | u32 type, u64 attribute) |
99 | { | 214 | { |
@@ -113,3 +228,8 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, | |||
113 | 228 | ||
114 | return (void __iomem *)__va(phys_addr); | 229 | return (void __iomem *)__va(phys_addr); |
115 | } | 230 | } |
231 | |||
232 | void __init parse_efi_setup(u64 phys_addr, u32 data_len) | ||
233 | { | ||
234 | efi_setup = phys_addr + sizeof(struct setup_data); | ||
235 | } | ||
diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S index 4c07ccab8146..88073b140298 100644 --- a/arch/x86/platform/efi/efi_stub_64.S +++ b/arch/x86/platform/efi/efi_stub_64.S | |||
@@ -34,10 +34,47 @@ | |||
34 | mov %rsi, %cr0; \ | 34 | mov %rsi, %cr0; \ |
35 | mov (%rsp), %rsp | 35 | mov (%rsp), %rsp |
36 | 36 | ||
37 | /* stolen from gcc */ | ||
38 | .macro FLUSH_TLB_ALL | ||
39 | movq %r15, efi_scratch(%rip) | ||
40 | movq %r14, efi_scratch+8(%rip) | ||
41 | movq %cr4, %r15 | ||
42 | movq %r15, %r14 | ||
43 | andb $0x7f, %r14b | ||
44 | movq %r14, %cr4 | ||
45 | movq %r15, %cr4 | ||
46 | movq efi_scratch+8(%rip), %r14 | ||
47 | movq efi_scratch(%rip), %r15 | ||
48 | .endm | ||
49 | |||
50 | .macro SWITCH_PGT | ||
51 | cmpb $0, efi_scratch+24(%rip) | ||
52 | je 1f | ||
53 | movq %r15, efi_scratch(%rip) # r15 | ||
54 | # save previous CR3 | ||
55 | movq %cr3, %r15 | ||
56 | movq %r15, efi_scratch+8(%rip) # prev_cr3 | ||
57 | movq efi_scratch+16(%rip), %r15 # EFI pgt | ||
58 | movq %r15, %cr3 | ||
59 | 1: | ||
60 | .endm | ||
61 | |||
62 | .macro RESTORE_PGT | ||
63 | cmpb $0, efi_scratch+24(%rip) | ||
64 | je 2f | ||
65 | movq efi_scratch+8(%rip), %r15 | ||
66 | movq %r15, %cr3 | ||
67 | movq efi_scratch(%rip), %r15 | ||
68 | FLUSH_TLB_ALL | ||
69 | 2: | ||
70 | .endm | ||
71 | |||
37 | ENTRY(efi_call0) | 72 | ENTRY(efi_call0) |
38 | SAVE_XMM | 73 | SAVE_XMM |
39 | subq $32, %rsp | 74 | subq $32, %rsp |
75 | SWITCH_PGT | ||
40 | call *%rdi | 76 | call *%rdi |
77 | RESTORE_PGT | ||
41 | addq $32, %rsp | 78 | addq $32, %rsp |
42 | RESTORE_XMM | 79 | RESTORE_XMM |
43 | ret | 80 | ret |
@@ -47,7 +84,9 @@ ENTRY(efi_call1) | |||
47 | SAVE_XMM | 84 | SAVE_XMM |
48 | subq $32, %rsp | 85 | subq $32, %rsp |
49 | mov %rsi, %rcx | 86 | mov %rsi, %rcx |
87 | SWITCH_PGT | ||
50 | call *%rdi | 88 | call *%rdi |
89 | RESTORE_PGT | ||
51 | addq $32, %rsp | 90 | addq $32, %rsp |
52 | RESTORE_XMM | 91 | RESTORE_XMM |
53 | ret | 92 | ret |
@@ -57,7 +96,9 @@ ENTRY(efi_call2) | |||
57 | SAVE_XMM | 96 | SAVE_XMM |
58 | subq $32, %rsp | 97 | subq $32, %rsp |
59 | mov %rsi, %rcx | 98 | mov %rsi, %rcx |
99 | SWITCH_PGT | ||
60 | call *%rdi | 100 | call *%rdi |
101 | RESTORE_PGT | ||
61 | addq $32, %rsp | 102 | addq $32, %rsp |
62 | RESTORE_XMM | 103 | RESTORE_XMM |
63 | ret | 104 | ret |
@@ -68,7 +109,9 @@ ENTRY(efi_call3) | |||
68 | subq $32, %rsp | 109 | subq $32, %rsp |
69 | mov %rcx, %r8 | 110 | mov %rcx, %r8 |
70 | mov %rsi, %rcx | 111 | mov %rsi, %rcx |
112 | SWITCH_PGT | ||
71 | call *%rdi | 113 | call *%rdi |
114 | RESTORE_PGT | ||
72 | addq $32, %rsp | 115 | addq $32, %rsp |
73 | RESTORE_XMM | 116 | RESTORE_XMM |
74 | ret | 117 | ret |
@@ -80,7 +123,9 @@ ENTRY(efi_call4) | |||
80 | mov %r8, %r9 | 123 | mov %r8, %r9 |
81 | mov %rcx, %r8 | 124 | mov %rcx, %r8 |
82 | mov %rsi, %rcx | 125 | mov %rsi, %rcx |
126 | SWITCH_PGT | ||
83 | call *%rdi | 127 | call *%rdi |
128 | RESTORE_PGT | ||
84 | addq $32, %rsp | 129 | addq $32, %rsp |
85 | RESTORE_XMM | 130 | RESTORE_XMM |
86 | ret | 131 | ret |
@@ -93,7 +138,9 @@ ENTRY(efi_call5) | |||
93 | mov %r8, %r9 | 138 | mov %r8, %r9 |
94 | mov %rcx, %r8 | 139 | mov %rcx, %r8 |
95 | mov %rsi, %rcx | 140 | mov %rsi, %rcx |
141 | SWITCH_PGT | ||
96 | call *%rdi | 142 | call *%rdi |
143 | RESTORE_PGT | ||
97 | addq $48, %rsp | 144 | addq $48, %rsp |
98 | RESTORE_XMM | 145 | RESTORE_XMM |
99 | ret | 146 | ret |
@@ -109,8 +156,15 @@ ENTRY(efi_call6) | |||
109 | mov %r8, %r9 | 156 | mov %r8, %r9 |
110 | mov %rcx, %r8 | 157 | mov %rcx, %r8 |
111 | mov %rsi, %rcx | 158 | mov %rsi, %rcx |
159 | SWITCH_PGT | ||
112 | call *%rdi | 160 | call *%rdi |
161 | RESTORE_PGT | ||
113 | addq $48, %rsp | 162 | addq $48, %rsp |
114 | RESTORE_XMM | 163 | RESTORE_XMM |
115 | ret | 164 | ret |
116 | ENDPROC(efi_call6) | 165 | ENDPROC(efi_call6) |
166 | |||
167 | .data | ||
168 | ENTRY(efi_scratch) | ||
169 | .fill 3,8,0 | ||
170 | .byte 0 | ||
diff --git a/arch/x86/platform/intel-mid/Makefile b/arch/x86/platform/intel-mid/Makefile index 01cc29ea5ff7..0a8ee703b9fa 100644 --- a/arch/x86/platform/intel-mid/Makefile +++ b/arch/x86/platform/intel-mid/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o | 1 | obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o mfld.o mrfl.o |
2 | obj-$(CONFIG_X86_INTEL_MID) += intel_mid_vrtc.o | ||
3 | obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o | 2 | obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o |
3 | |||
4 | # SFI specific code | 4 | # SFI specific code |
5 | ifdef CONFIG_X86_INTEL_MID | 5 | ifdef CONFIG_X86_INTEL_MID |
6 | obj-$(CONFIG_SFI) += sfi.o device_libs/ | 6 | obj-$(CONFIG_SFI) += sfi.o device_libs/ |
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c index 0d942c1d26d5..69a783689d21 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c | |||
@@ -22,7 +22,9 @@ static void __init *emc1403_platform_data(void *info) | |||
22 | int intr = get_gpio_by_name("thermal_int"); | 22 | int intr = get_gpio_by_name("thermal_int"); |
23 | int intr2nd = get_gpio_by_name("thermal_alert"); | 23 | int intr2nd = get_gpio_by_name("thermal_alert"); |
24 | 24 | ||
25 | if (intr == -1 || intr2nd == -1) | 25 | if (intr < 0) |
26 | return NULL; | ||
27 | if (intr2nd < 0) | ||
26 | return NULL; | 28 | return NULL; |
27 | 29 | ||
28 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | 30 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; |
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c index a013a4834bbe..dccae6b0413f 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c | |||
@@ -66,7 +66,7 @@ static int __init pb_keys_init(void) | |||
66 | gb[i].gpio = get_gpio_by_name(gb[i].desc); | 66 | gb[i].gpio = get_gpio_by_name(gb[i].desc); |
67 | pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc, | 67 | pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc, |
68 | gb[i].gpio); | 68 | gb[i].gpio); |
69 | if (gb[i].gpio == -1) | 69 | if (gb[i].gpio < 0) |
70 | continue; | 70 | continue; |
71 | 71 | ||
72 | if (i != good) | 72 | if (i != good) |
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_lis331.c b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c index 15278c11f714..54226de7541a 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_lis331.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c | |||
@@ -21,7 +21,9 @@ static void __init *lis331dl_platform_data(void *info) | |||
21 | int intr = get_gpio_by_name("accel_int"); | 21 | int intr = get_gpio_by_name("accel_int"); |
22 | int intr2nd = get_gpio_by_name("accel_2"); | 22 | int intr2nd = get_gpio_by_name("accel_2"); |
23 | 23 | ||
24 | if (intr == -1 || intr2nd == -1) | 24 | if (intr < 0) |
25 | return NULL; | ||
26 | if (intr2nd < 0) | ||
25 | return NULL; | 27 | return NULL; |
26 | 28 | ||
27 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | 29 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; |
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_max7315.c b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c index 94ade10024ae..2c8acbc1e9ad 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_max7315.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c | |||
@@ -48,7 +48,7 @@ static void __init *max7315_platform_data(void *info) | |||
48 | gpio_base = get_gpio_by_name(base_pin_name); | 48 | gpio_base = get_gpio_by_name(base_pin_name); |
49 | intr = get_gpio_by_name(intr_pin_name); | 49 | intr = get_gpio_by_name(intr_pin_name); |
50 | 50 | ||
51 | if (gpio_base == -1) | 51 | if (gpio_base < 0) |
52 | return NULL; | 52 | return NULL; |
53 | max7315->gpio_base = gpio_base; | 53 | max7315->gpio_base = gpio_base; |
54 | if (intr != -1) { | 54 | if (intr != -1) { |
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c index dd28d63c84fb..cfe9a47a1e87 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c | |||
@@ -19,7 +19,7 @@ static void *mpu3050_platform_data(void *info) | |||
19 | struct i2c_board_info *i2c_info = info; | 19 | struct i2c_board_info *i2c_info = info; |
20 | int intr = get_gpio_by_name("mpu3050_int"); | 20 | int intr = get_gpio_by_name("mpu3050_int"); |
21 | 21 | ||
22 | if (intr == -1) | 22 | if (intr < 0) |
23 | return NULL; | 23 | return NULL; |
24 | 24 | ||
25 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | 25 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; |
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c b/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c index d87182a09263..65c2a9a19db4 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c | |||
@@ -26,7 +26,7 @@ static void __init *pmic_gpio_platform_data(void *info) | |||
26 | static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; | 26 | static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; |
27 | int gpio_base = get_gpio_by_name("pmic_gpio_base"); | 27 | int gpio_base = get_gpio_by_name("pmic_gpio_base"); |
28 | 28 | ||
29 | if (gpio_base == -1) | 29 | if (gpio_base < 0) |
30 | gpio_base = 64; | 30 | gpio_base = 64; |
31 | pmic_gpio_pdata.gpio_base = gpio_base; | 31 | pmic_gpio_pdata.gpio_base = gpio_base; |
32 | pmic_gpio_pdata.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; | 32 | pmic_gpio_pdata.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; |
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c index 22881c9a6737..33be0b3be6e1 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c | |||
@@ -34,10 +34,10 @@ static void *tca6416_platform_data(void *info) | |||
34 | gpio_base = get_gpio_by_name(base_pin_name); | 34 | gpio_base = get_gpio_by_name(base_pin_name); |
35 | intr = get_gpio_by_name(intr_pin_name); | 35 | intr = get_gpio_by_name(intr_pin_name); |
36 | 36 | ||
37 | if (gpio_base == -1) | 37 | if (gpio_base < 0) |
38 | return NULL; | 38 | return NULL; |
39 | tca6416.gpio_base = gpio_base; | 39 | tca6416.gpio_base = gpio_base; |
40 | if (intr != -1) { | 40 | if (intr >= 0) { |
41 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | 41 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; |
42 | tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; | 42 | tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; |
43 | } else { | 43 | } else { |
diff --git a/arch/x86/platform/intel-mid/early_printk_intel_mid.c b/arch/x86/platform/intel-mid/early_printk_intel_mid.c index 4f702f554f6e..e0bd082a80e0 100644 --- a/arch/x86/platform/intel-mid/early_printk_intel_mid.c +++ b/arch/x86/platform/intel-mid/early_printk_intel_mid.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/console.h> | 22 | #include <linux/console.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/init.h> | ||
26 | #include <linux/io.h> | 25 | #include <linux/io.h> |
27 | 26 | ||
28 | #include <asm/fixmap.h> | 27 | #include <asm/fixmap.h> |
diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c index f90e290f689f..1bbedc4b0f88 100644 --- a/arch/x86/platform/intel-mid/intel-mid.c +++ b/arch/x86/platform/intel-mid/intel-mid.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include <asm/apb_timer.h> | 35 | #include <asm/apb_timer.h> |
36 | #include <asm/reboot.h> | 36 | #include <asm/reboot.h> |
37 | 37 | ||
38 | #include "intel_mid_weak_decls.h" | ||
39 | |||
38 | /* | 40 | /* |
39 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, | 41 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, |
40 | * cmdline option x86_intel_mid_timer can be used to override the configuration | 42 | * cmdline option x86_intel_mid_timer can be used to override the configuration |
@@ -58,12 +60,16 @@ | |||
58 | 60 | ||
59 | enum intel_mid_timer_options intel_mid_timer_options; | 61 | enum intel_mid_timer_options intel_mid_timer_options; |
60 | 62 | ||
63 | /* intel_mid_ops to store sub arch ops */ | ||
64 | struct intel_mid_ops *intel_mid_ops; | ||
65 | /* getter function for sub arch ops*/ | ||
66 | static void *(*get_intel_mid_ops[])(void) = INTEL_MID_OPS_INIT; | ||
61 | enum intel_mid_cpu_type __intel_mid_cpu_chip; | 67 | enum intel_mid_cpu_type __intel_mid_cpu_chip; |
62 | EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip); | 68 | EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip); |
63 | 69 | ||
64 | static void intel_mid_power_off(void) | 70 | static void intel_mid_power_off(void) |
65 | { | 71 | { |
66 | } | 72 | }; |
67 | 73 | ||
68 | static void intel_mid_reboot(void) | 74 | static void intel_mid_reboot(void) |
69 | { | 75 | { |
@@ -72,32 +78,6 @@ static void intel_mid_reboot(void) | |||
72 | 78 | ||
73 | static unsigned long __init intel_mid_calibrate_tsc(void) | 79 | static unsigned long __init intel_mid_calibrate_tsc(void) |
74 | { | 80 | { |
75 | unsigned long fast_calibrate; | ||
76 | u32 lo, hi, ratio, fsb; | ||
77 | |||
78 | rdmsr(MSR_IA32_PERF_STATUS, lo, hi); | ||
79 | pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi); | ||
80 | ratio = (hi >> 8) & 0x1f; | ||
81 | pr_debug("ratio is %d\n", ratio); | ||
82 | if (!ratio) { | ||
83 | pr_err("read a zero ratio, should be incorrect!\n"); | ||
84 | pr_err("force tsc ratio to 16 ...\n"); | ||
85 | ratio = 16; | ||
86 | } | ||
87 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
88 | if ((lo & 0x7) == 0x7) | ||
89 | fsb = PENWELL_FSB_FREQ_83SKU; | ||
90 | else | ||
91 | fsb = PENWELL_FSB_FREQ_100SKU; | ||
92 | fast_calibrate = ratio * fsb; | ||
93 | pr_debug("read penwell tsc %lu khz\n", fast_calibrate); | ||
94 | lapic_timer_frequency = fsb * 1000 / HZ; | ||
95 | /* mark tsc clocksource as reliable */ | ||
96 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); | ||
97 | |||
98 | if (fast_calibrate) | ||
99 | return fast_calibrate; | ||
100 | |||
101 | return 0; | 81 | return 0; |
102 | } | 82 | } |
103 | 83 | ||
@@ -125,13 +105,37 @@ static void __init intel_mid_time_init(void) | |||
125 | 105 | ||
126 | static void intel_mid_arch_setup(void) | 106 | static void intel_mid_arch_setup(void) |
127 | { | 107 | { |
128 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) | 108 | if (boot_cpu_data.x86 != 6) { |
129 | __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL; | ||
130 | else { | ||
131 | pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n", | 109 | pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n", |
132 | boot_cpu_data.x86, boot_cpu_data.x86_model); | 110 | boot_cpu_data.x86, boot_cpu_data.x86_model); |
133 | __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL; | 111 | __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL; |
112 | goto out; | ||
134 | } | 113 | } |
114 | |||
115 | switch (boot_cpu_data.x86_model) { | ||
116 | case 0x35: | ||
117 | __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_CLOVERVIEW; | ||
118 | break; | ||
119 | case 0x3C: | ||
120 | case 0x4A: | ||
121 | __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_TANGIER; | ||
122 | break; | ||
123 | case 0x27: | ||
124 | default: | ||
125 | __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL; | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | if (__intel_mid_cpu_chip < MAX_CPU_OPS(get_intel_mid_ops)) | ||
130 | intel_mid_ops = get_intel_mid_ops[__intel_mid_cpu_chip](); | ||
131 | else { | ||
132 | intel_mid_ops = get_intel_mid_ops[INTEL_MID_CPU_CHIP_PENWELL](); | ||
133 | pr_info("ARCH: Uknown SoC, assuming PENWELL!\n"); | ||
134 | } | ||
135 | |||
136 | out: | ||
137 | if (intel_mid_ops->arch_setup) | ||
138 | intel_mid_ops->arch_setup(); | ||
135 | } | 139 | } |
136 | 140 | ||
137 | /* MID systems don't have i8042 controller */ | 141 | /* MID systems don't have i8042 controller */ |
diff --git a/arch/x86/platform/intel-mid/intel_mid_weak_decls.h b/arch/x86/platform/intel-mid/intel_mid_weak_decls.h new file mode 100644 index 000000000000..a537ffc16299 --- /dev/null +++ b/arch/x86/platform/intel-mid/intel_mid_weak_decls.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * intel_mid_weak_decls.h: Weak declarations of intel-mid.c | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | */ | ||
11 | |||
12 | |||
13 | /* __attribute__((weak)) makes these declarations overridable */ | ||
14 | /* For every CPU addition a new get_<cpuname>_ops interface needs | ||
15 | * to be added. | ||
16 | */ | ||
17 | extern void * __cpuinit get_penwell_ops(void) __attribute__((weak)); | ||
18 | extern void * __cpuinit get_cloverview_ops(void) __attribute__((weak)); | ||
19 | extern void * __init get_tangier_ops(void) __attribute__((weak)); | ||
diff --git a/arch/x86/platform/intel-mid/mfld.c b/arch/x86/platform/intel-mid/mfld.c new file mode 100644 index 000000000000..4f7884eebc14 --- /dev/null +++ b/arch/x86/platform/intel-mid/mfld.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * mfld.c: Intel Medfield platform setup code | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | |||
14 | #include <asm/apic.h> | ||
15 | #include <asm/intel-mid.h> | ||
16 | #include <asm/intel_mid_vrtc.h> | ||
17 | |||
18 | #include "intel_mid_weak_decls.h" | ||
19 | |||
20 | static void penwell_arch_setup(void); | ||
21 | /* penwell arch ops */ | ||
22 | static struct intel_mid_ops penwell_ops = { | ||
23 | .arch_setup = penwell_arch_setup, | ||
24 | }; | ||
25 | |||
26 | static void mfld_power_off(void) | ||
27 | { | ||
28 | } | ||
29 | |||
30 | static unsigned long __init mfld_calibrate_tsc(void) | ||
31 | { | ||
32 | unsigned long fast_calibrate; | ||
33 | u32 lo, hi, ratio, fsb; | ||
34 | |||
35 | rdmsr(MSR_IA32_PERF_STATUS, lo, hi); | ||
36 | pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi); | ||
37 | ratio = (hi >> 8) & 0x1f; | ||
38 | pr_debug("ratio is %d\n", ratio); | ||
39 | if (!ratio) { | ||
40 | pr_err("read a zero ratio, should be incorrect!\n"); | ||
41 | pr_err("force tsc ratio to 16 ...\n"); | ||
42 | ratio = 16; | ||
43 | } | ||
44 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
45 | if ((lo & 0x7) == 0x7) | ||
46 | fsb = FSB_FREQ_83SKU; | ||
47 | else | ||
48 | fsb = FSB_FREQ_100SKU; | ||
49 | fast_calibrate = ratio * fsb; | ||
50 | pr_debug("read penwell tsc %lu khz\n", fast_calibrate); | ||
51 | lapic_timer_frequency = fsb * 1000 / HZ; | ||
52 | /* mark tsc clocksource as reliable */ | ||
53 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); | ||
54 | |||
55 | if (fast_calibrate) | ||
56 | return fast_calibrate; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static void __init penwell_arch_setup() | ||
62 | { | ||
63 | x86_platform.calibrate_tsc = mfld_calibrate_tsc; | ||
64 | pm_power_off = mfld_power_off; | ||
65 | } | ||
66 | |||
67 | void * __cpuinit get_penwell_ops() | ||
68 | { | ||
69 | return &penwell_ops; | ||
70 | } | ||
71 | |||
72 | void * __cpuinit get_cloverview_ops() | ||
73 | { | ||
74 | return &penwell_ops; | ||
75 | } | ||
diff --git a/arch/x86/platform/intel-mid/mrfl.c b/arch/x86/platform/intel-mid/mrfl.c new file mode 100644 index 000000000000..09d10159e7b7 --- /dev/null +++ b/arch/x86/platform/intel-mid/mrfl.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * mrfl.c: Intel Merrifield platform specific setup code | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | |||
14 | #include <asm/apic.h> | ||
15 | #include <asm/intel-mid.h> | ||
16 | |||
17 | #include "intel_mid_weak_decls.h" | ||
18 | |||
19 | static unsigned long __init tangier_calibrate_tsc(void) | ||
20 | { | ||
21 | unsigned long fast_calibrate; | ||
22 | u32 lo, hi, ratio, fsb, bus_freq; | ||
23 | |||
24 | /* *********************** */ | ||
25 | /* Compute TSC:Ratio * FSB */ | ||
26 | /* *********************** */ | ||
27 | |||
28 | /* Compute Ratio */ | ||
29 | rdmsr(MSR_PLATFORM_INFO, lo, hi); | ||
30 | pr_debug("IA32 PLATFORM_INFO is 0x%x : %x\n", hi, lo); | ||
31 | |||
32 | ratio = (lo >> 8) & 0xFF; | ||
33 | pr_debug("ratio is %d\n", ratio); | ||
34 | if (!ratio) { | ||
35 | pr_err("Read a zero ratio, force tsc ratio to 4 ...\n"); | ||
36 | ratio = 4; | ||
37 | } | ||
38 | |||
39 | /* Compute FSB */ | ||
40 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
41 | pr_debug("Actual FSB frequency detected by SOC 0x%x : %x\n", | ||
42 | hi, lo); | ||
43 | |||
44 | bus_freq = lo & 0x7; | ||
45 | pr_debug("bus_freq = 0x%x\n", bus_freq); | ||
46 | |||
47 | if (bus_freq == 0) | ||
48 | fsb = FSB_FREQ_100SKU; | ||
49 | else if (bus_freq == 1) | ||
50 | fsb = FSB_FREQ_100SKU; | ||
51 | else if (bus_freq == 2) | ||
52 | fsb = FSB_FREQ_133SKU; | ||
53 | else if (bus_freq == 3) | ||
54 | fsb = FSB_FREQ_167SKU; | ||
55 | else if (bus_freq == 4) | ||
56 | fsb = FSB_FREQ_83SKU; | ||
57 | else if (bus_freq == 5) | ||
58 | fsb = FSB_FREQ_400SKU; | ||
59 | else if (bus_freq == 6) | ||
60 | fsb = FSB_FREQ_267SKU; | ||
61 | else if (bus_freq == 7) | ||
62 | fsb = FSB_FREQ_333SKU; | ||
63 | else { | ||
64 | BUG(); | ||
65 | pr_err("Invalid bus_freq! Setting to minimal value!\n"); | ||
66 | fsb = FSB_FREQ_100SKU; | ||
67 | } | ||
68 | |||
69 | /* TSC = FSB Freq * Resolved HFM Ratio */ | ||
70 | fast_calibrate = ratio * fsb; | ||
71 | pr_debug("calculate tangier tsc %lu KHz\n", fast_calibrate); | ||
72 | |||
73 | /* ************************************ */ | ||
74 | /* Calculate Local APIC Timer Frequency */ | ||
75 | /* ************************************ */ | ||
76 | lapic_timer_frequency = (fsb * 1000) / HZ; | ||
77 | |||
78 | pr_debug("Setting lapic_timer_frequency = %d\n", | ||
79 | lapic_timer_frequency); | ||
80 | |||
81 | /* mark tsc clocksource as reliable */ | ||
82 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); | ||
83 | |||
84 | if (fast_calibrate) | ||
85 | return fast_calibrate; | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static void __init tangier_arch_setup(void) | ||
91 | { | ||
92 | x86_platform.calibrate_tsc = tangier_calibrate_tsc; | ||
93 | } | ||
94 | |||
95 | /* tangier arch ops */ | ||
96 | static struct intel_mid_ops tangier_ops = { | ||
97 | .arch_setup = tangier_arch_setup, | ||
98 | }; | ||
99 | |||
100 | void * __cpuinit get_tangier_ops() | ||
101 | { | ||
102 | return &tangier_ops; | ||
103 | } | ||
diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c index c84c1ca396bf..994c40bd7cb7 100644 --- a/arch/x86/platform/intel-mid/sfi.c +++ b/arch/x86/platform/intel-mid/sfi.c | |||
@@ -224,7 +224,7 @@ int get_gpio_by_name(const char *name) | |||
224 | if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) | 224 | if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) |
225 | return pentry->pin_no; | 225 | return pentry->pin_no; |
226 | } | 226 | } |
227 | return -1; | 227 | return -EINVAL; |
228 | } | 228 | } |
229 | 229 | ||
230 | void __init intel_scu_device_register(struct platform_device *pdev) | 230 | void __init intel_scu_device_register(struct platform_device *pdev) |
@@ -250,7 +250,7 @@ static void __init intel_scu_spi_device_register(struct spi_board_info *sdev) | |||
250 | sdev->modalias); | 250 | sdev->modalias); |
251 | return; | 251 | return; |
252 | } | 252 | } |
253 | memcpy(new_dev, sdev, sizeof(*sdev)); | 253 | *new_dev = *sdev; |
254 | 254 | ||
255 | spi_devs[spi_next_dev++] = new_dev; | 255 | spi_devs[spi_next_dev++] = new_dev; |
256 | } | 256 | } |
@@ -271,7 +271,7 @@ static void __init intel_scu_i2c_device_register(int bus, | |||
271 | idev->type); | 271 | idev->type); |
272 | return; | 272 | return; |
273 | } | 273 | } |
274 | memcpy(new_dev, idev, sizeof(*idev)); | 274 | *new_dev = *idev; |
275 | 275 | ||
276 | i2c_bus[i2c_next_dev] = bus; | 276 | i2c_bus[i2c_next_dev] = bus; |
277 | i2c_devs[i2c_next_dev++] = new_dev; | 277 | i2c_devs[i2c_next_dev++] = new_dev; |
@@ -337,6 +337,8 @@ static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *pentry, | |||
337 | pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n", | 337 | pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n", |
338 | pentry->name, pentry->irq); | 338 | pentry->name, pentry->irq); |
339 | pdata = intel_mid_sfi_get_pdata(dev, pentry); | 339 | pdata = intel_mid_sfi_get_pdata(dev, pentry); |
340 | if (IS_ERR(pdata)) | ||
341 | return; | ||
340 | 342 | ||
341 | pdev = platform_device_alloc(pentry->name, 0); | 343 | pdev = platform_device_alloc(pentry->name, 0); |
342 | if (pdev == NULL) { | 344 | if (pdev == NULL) { |
@@ -370,6 +372,8 @@ static void __init sfi_handle_spi_dev(struct sfi_device_table_entry *pentry, | |||
370 | spi_info.chip_select); | 372 | spi_info.chip_select); |
371 | 373 | ||
372 | pdata = intel_mid_sfi_get_pdata(dev, &spi_info); | 374 | pdata = intel_mid_sfi_get_pdata(dev, &spi_info); |
375 | if (IS_ERR(pdata)) | ||
376 | return; | ||
373 | 377 | ||
374 | spi_info.platform_data = pdata; | 378 | spi_info.platform_data = pdata; |
375 | if (dev->delay) | 379 | if (dev->delay) |
@@ -395,6 +399,8 @@ static void __init sfi_handle_i2c_dev(struct sfi_device_table_entry *pentry, | |||
395 | i2c_info.addr); | 399 | i2c_info.addr); |
396 | pdata = intel_mid_sfi_get_pdata(dev, &i2c_info); | 400 | pdata = intel_mid_sfi_get_pdata(dev, &i2c_info); |
397 | i2c_info.platform_data = pdata; | 401 | i2c_info.platform_data = pdata; |
402 | if (IS_ERR(pdata)) | ||
403 | return; | ||
398 | 404 | ||
399 | if (dev->delay) | 405 | if (dev->delay) |
400 | intel_scu_i2c_device_register(pentry->host_num, &i2c_info); | 406 | intel_scu_i2c_device_register(pentry->host_num, &i2c_info); |
@@ -443,13 +449,35 @@ static int __init sfi_parse_devs(struct sfi_table_header *table) | |||
443 | * so we have to enable them one by one here | 449 | * so we have to enable them one by one here |
444 | */ | 450 | */ |
445 | ioapic = mp_find_ioapic(irq); | 451 | ioapic = mp_find_ioapic(irq); |
446 | irq_attr.ioapic = ioapic; | 452 | if (ioapic >= 0) { |
447 | irq_attr.ioapic_pin = irq; | 453 | irq_attr.ioapic = ioapic; |
448 | irq_attr.trigger = 1; | 454 | irq_attr.ioapic_pin = irq; |
449 | irq_attr.polarity = 1; | 455 | irq_attr.trigger = 1; |
450 | io_apic_set_pci_routing(NULL, irq, &irq_attr); | 456 | if (intel_mid_identify_cpu() == |
451 | } else | 457 | INTEL_MID_CPU_CHIP_TANGIER) { |
458 | if (!strncmp(pentry->name, | ||
459 | "r69001-ts-i2c", 13)) | ||
460 | /* active low */ | ||
461 | irq_attr.polarity = 1; | ||
462 | else if (!strncmp(pentry->name, | ||
463 | "synaptics_3202", 14)) | ||
464 | /* active low */ | ||
465 | irq_attr.polarity = 1; | ||
466 | else if (irq == 41) | ||
467 | /* fast_int_1 */ | ||
468 | irq_attr.polarity = 1; | ||
469 | else | ||
470 | /* active high */ | ||
471 | irq_attr.polarity = 0; | ||
472 | } else { | ||
473 | /* PNW and CLV go with active low */ | ||
474 | irq_attr.polarity = 1; | ||
475 | } | ||
476 | io_apic_set_pci_routing(NULL, irq, &irq_attr); | ||
477 | } | ||
478 | } else { | ||
452 | irq = 0; /* No irq */ | 479 | irq = 0; /* No irq */ |
480 | } | ||
453 | 481 | ||
454 | dev = get_device_id(pentry->type, pentry->name); | 482 | dev = get_device_id(pentry->type, pentry->name); |
455 | 483 | ||
diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c index e6cb80f620af..4d171e8640ef 100644 --- a/arch/x86/platform/iris/iris.c +++ b/arch/x86/platform/iris/iris.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/init.h> | ||
31 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
32 | #include <asm/io.h> | 31 | #include <asm/io.h> |
33 | 32 | ||
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index efe4d7220397..dfe605ac1bcd 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c | |||
@@ -433,15 +433,49 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp) | |||
433 | return; | 433 | return; |
434 | } | 434 | } |
435 | 435 | ||
436 | static inline unsigned long cycles_2_us(unsigned long long cyc) | 436 | /* |
437 | * Not to be confused with cycles_2_ns() from tsc.c; this gives a relative | ||
438 | * number, not an absolute. It converts a duration in cycles to a duration in | ||
439 | * ns. | ||
440 | */ | ||
441 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) | ||
437 | { | 442 | { |
443 | struct cyc2ns_data *data = cyc2ns_read_begin(); | ||
438 | unsigned long long ns; | 444 | unsigned long long ns; |
439 | unsigned long us; | ||
440 | int cpu = smp_processor_id(); | ||
441 | 445 | ||
442 | ns = (cyc * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR; | 446 | ns = mul_u64_u32_shr(cyc, data->cyc2ns_mul, data->cyc2ns_shift); |
443 | us = ns / 1000; | 447 | |
444 | return us; | 448 | cyc2ns_read_end(data); |
449 | return ns; | ||
450 | } | ||
451 | |||
452 | /* | ||
453 | * The reverse of the above; converts a duration in ns to a duration in cycles. | ||
454 | */ | ||
455 | static inline unsigned long long ns_2_cycles(unsigned long long ns) | ||
456 | { | ||
457 | struct cyc2ns_data *data = cyc2ns_read_begin(); | ||
458 | unsigned long long cyc; | ||
459 | |||
460 | cyc = (ns << data->cyc2ns_shift) / data->cyc2ns_mul; | ||
461 | |||
462 | cyc2ns_read_end(data); | ||
463 | return cyc; | ||
464 | } | ||
465 | |||
466 | static inline unsigned long cycles_2_us(unsigned long long cyc) | ||
467 | { | ||
468 | return cycles_2_ns(cyc) / NSEC_PER_USEC; | ||
469 | } | ||
470 | |||
471 | static inline cycles_t sec_2_cycles(unsigned long sec) | ||
472 | { | ||
473 | return ns_2_cycles(sec * NSEC_PER_SEC); | ||
474 | } | ||
475 | |||
476 | static inline unsigned long long usec_2_cycles(unsigned long usec) | ||
477 | { | ||
478 | return ns_2_cycles(usec * NSEC_PER_USEC); | ||
445 | } | 479 | } |
446 | 480 | ||
447 | /* | 481 | /* |
@@ -668,16 +702,6 @@ static int wait_completion(struct bau_desc *bau_desc, | |||
668 | bcp, try); | 702 | bcp, try); |
669 | } | 703 | } |
670 | 704 | ||
671 | static inline cycles_t sec_2_cycles(unsigned long sec) | ||
672 | { | ||
673 | unsigned long ns; | ||
674 | cycles_t cyc; | ||
675 | |||
676 | ns = sec * 1000000000; | ||
677 | cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id())); | ||
678 | return cyc; | ||
679 | } | ||
680 | |||
681 | /* | 705 | /* |
682 | * Our retries are blocked by all destination sw ack resources being | 706 | * Our retries are blocked by all destination sw ack resources being |
683 | * in use, and a timeout is pending. In that case hardware immediately | 707 | * in use, and a timeout is pending. In that case hardware immediately |
@@ -1327,16 +1351,6 @@ static void ptc_seq_stop(struct seq_file *file, void *data) | |||
1327 | { | 1351 | { |
1328 | } | 1352 | } |
1329 | 1353 | ||
1330 | static inline unsigned long long usec_2_cycles(unsigned long microsec) | ||
1331 | { | ||
1332 | unsigned long ns; | ||
1333 | unsigned long long cyc; | ||
1334 | |||
1335 | ns = microsec * 1000; | ||
1336 | cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id())); | ||
1337 | return cyc; | ||
1338 | } | ||
1339 | |||
1340 | /* | 1354 | /* |
1341 | * Display the statistics thru /proc/sgi_uv/ptc_statistics | 1355 | * Display the statistics thru /proc/sgi_uv/ptc_statistics |
1342 | * 'data' points to the cpu number | 1356 | * 'data' points to the cpu number |
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c index a44f457e70a1..bad628a620c4 100644 --- a/arch/x86/realmode/init.c +++ b/arch/x86/realmode/init.c | |||
@@ -29,12 +29,10 @@ void __init reserve_real_mode(void) | |||
29 | void __init setup_real_mode(void) | 29 | void __init setup_real_mode(void) |
30 | { | 30 | { |
31 | u16 real_mode_seg; | 31 | u16 real_mode_seg; |
32 | u32 *rel; | 32 | const u32 *rel; |
33 | u32 count; | 33 | u32 count; |
34 | u32 *ptr; | ||
35 | u16 *seg; | ||
36 | int i; | ||
37 | unsigned char *base; | 34 | unsigned char *base; |
35 | unsigned long phys_base; | ||
38 | struct trampoline_header *trampoline_header; | 36 | struct trampoline_header *trampoline_header; |
39 | size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); | 37 | size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); |
40 | #ifdef CONFIG_X86_64 | 38 | #ifdef CONFIG_X86_64 |
@@ -46,23 +44,23 @@ void __init setup_real_mode(void) | |||
46 | 44 | ||
47 | memcpy(base, real_mode_blob, size); | 45 | memcpy(base, real_mode_blob, size); |
48 | 46 | ||
49 | real_mode_seg = __pa(base) >> 4; | 47 | phys_base = __pa(base); |
48 | real_mode_seg = phys_base >> 4; | ||
49 | |||
50 | rel = (u32 *) real_mode_relocs; | 50 | rel = (u32 *) real_mode_relocs; |
51 | 51 | ||
52 | /* 16-bit segment relocations. */ | 52 | /* 16-bit segment relocations. */ |
53 | count = rel[0]; | 53 | count = *rel++; |
54 | rel = &rel[1]; | 54 | while (count--) { |
55 | for (i = 0; i < count; i++) { | 55 | u16 *seg = (u16 *) (base + *rel++); |
56 | seg = (u16 *) (base + rel[i]); | ||
57 | *seg = real_mode_seg; | 56 | *seg = real_mode_seg; |
58 | } | 57 | } |
59 | 58 | ||
60 | /* 32-bit linear relocations. */ | 59 | /* 32-bit linear relocations. */ |
61 | count = rel[i]; | 60 | count = *rel++; |
62 | rel = &rel[i + 1]; | 61 | while (count--) { |
63 | for (i = 0; i < count; i++) { | 62 | u32 *ptr = (u32 *) (base + *rel++); |
64 | ptr = (u32 *) (base + rel[i]); | 63 | *ptr += phys_base; |
65 | *ptr += __pa(base); | ||
66 | } | 64 | } |
67 | 65 | ||
68 | /* Must be perfomed *after* relocation. */ | 66 | /* Must be perfomed *after* relocation. */ |
diff --git a/arch/x86/realmode/rm/reboot.S b/arch/x86/realmode/rm/reboot.S index f932ea61d1c8..d66c607bdc58 100644 --- a/arch/x86/realmode/rm/reboot.S +++ b/arch/x86/realmode/rm/reboot.S | |||
@@ -1,5 +1,4 @@ | |||
1 | #include <linux/linkage.h> | 1 | #include <linux/linkage.h> |
2 | #include <linux/init.h> | ||
3 | #include <asm/segment.h> | 2 | #include <asm/segment.h> |
4 | #include <asm/page_types.h> | 3 | #include <asm/page_types.h> |
5 | #include <asm/processor-flags.h> | 4 | #include <asm/processor-flags.h> |
diff --git a/arch/x86/realmode/rm/trampoline_32.S b/arch/x86/realmode/rm/trampoline_32.S index c1b2791183e7..48ddd76bc4c3 100644 --- a/arch/x86/realmode/rm/trampoline_32.S +++ b/arch/x86/realmode/rm/trampoline_32.S | |||
@@ -20,7 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/linkage.h> | 22 | #include <linux/linkage.h> |
23 | #include <linux/init.h> | ||
24 | #include <asm/segment.h> | 23 | #include <asm/segment.h> |
25 | #include <asm/page_types.h> | 24 | #include <asm/page_types.h> |
26 | #include "realmode.h" | 25 | #include "realmode.h" |
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S index bb360dc39d21..dac7b20d2f9d 100644 --- a/arch/x86/realmode/rm/trampoline_64.S +++ b/arch/x86/realmode/rm/trampoline_64.S | |||
@@ -25,7 +25,6 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/linkage.h> | 27 | #include <linux/linkage.h> |
28 | #include <linux/init.h> | ||
29 | #include <asm/pgtable_types.h> | 28 | #include <asm/pgtable_types.h> |
30 | #include <asm/page_types.h> | 29 | #include <asm/page_types.h> |
31 | #include <asm/msr.h> | 30 | #include <asm/msr.h> |
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index aabfb8380a1c..96bc506ac6de 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl | |||
@@ -357,3 +357,5 @@ | |||
357 | 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev | 357 | 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev |
358 | 349 i386 kcmp sys_kcmp | 358 | 349 i386 kcmp sys_kcmp |
359 | 350 i386 finit_module sys_finit_module | 359 | 350 i386 finit_module sys_finit_module |
360 | 351 i386 sched_setattr sys_sched_setattr | ||
361 | 352 i386 sched_getattr sys_sched_getattr | ||
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index 38ae65dfd14f..a12bddc7ccea 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl | |||
@@ -320,6 +320,8 @@ | |||
320 | 311 64 process_vm_writev sys_process_vm_writev | 320 | 311 64 process_vm_writev sys_process_vm_writev |
321 | 312 common kcmp sys_kcmp | 321 | 312 common kcmp sys_kcmp |
322 | 313 common finit_module sys_finit_module | 322 | 313 common finit_module sys_finit_module |
323 | 314 common sched_setattr sys_sched_setattr | ||
324 | 315 common sched_getattr sys_sched_getattr | ||
323 | 325 | ||
324 | # | 326 | # |
325 | # x32-specific system call numbers start at 512 to avoid cache impact | 327 | # x32-specific system call numbers start at 512 to avoid cache impact |
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index f7bab68a4b83..11f9285a2ff6 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c | |||
@@ -722,15 +722,25 @@ static void percpu_init(void) | |||
722 | 722 | ||
723 | /* | 723 | /* |
724 | * Check to see if a symbol lies in the .data..percpu section. | 724 | * Check to see if a symbol lies in the .data..percpu section. |
725 | * For some as yet not understood reason the "__init_begin" | 725 | * |
726 | * symbol which immediately preceeds the .data..percpu section | 726 | * The linker incorrectly associates some symbols with the |
727 | * also shows up as it it were part of it so we do an explict | 727 | * .data..percpu section so we also need to check the symbol |
728 | * check for that symbol name and ignore it. | 728 | * name to make sure that we classify the symbol correctly. |
729 | * | ||
730 | * The GNU linker incorrectly associates: | ||
731 | * __init_begin | ||
732 | * __per_cpu_load | ||
733 | * | ||
734 | * The "gold" linker incorrectly associates: | ||
735 | * init_per_cpu__irq_stack_union | ||
736 | * init_per_cpu__gdt_page | ||
729 | */ | 737 | */ |
730 | static int is_percpu_sym(ElfW(Sym) *sym, const char *symname) | 738 | static int is_percpu_sym(ElfW(Sym) *sym, const char *symname) |
731 | { | 739 | { |
732 | return (sym->st_shndx == per_cpu_shndx) && | 740 | return (sym->st_shndx == per_cpu_shndx) && |
733 | strcmp(symname, "__init_begin"); | 741 | strcmp(symname, "__init_begin") && |
742 | strcmp(symname, "__per_cpu_load") && | ||
743 | strncmp(symname, "init_per_cpu_", 13); | ||
734 | } | 744 | } |
735 | 745 | ||
736 | 746 | ||
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index 2ada505067cc..eb5d7a56f8d4 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c | |||
@@ -178,7 +178,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts) | |||
178 | 178 | ||
179 | ts->tv_nsec = 0; | 179 | ts->tv_nsec = 0; |
180 | do { | 180 | do { |
181 | seq = read_seqcount_begin_no_lockdep(>od->seq); | 181 | seq = raw_read_seqcount_begin(>od->seq); |
182 | mode = gtod->clock.vclock_mode; | 182 | mode = gtod->clock.vclock_mode; |
183 | ts->tv_sec = gtod->wall_time_sec; | 183 | ts->tv_sec = gtod->wall_time_sec; |
184 | ns = gtod->wall_time_snsec; | 184 | ns = gtod->wall_time_snsec; |
@@ -198,7 +198,7 @@ notrace static int do_monotonic(struct timespec *ts) | |||
198 | 198 | ||
199 | ts->tv_nsec = 0; | 199 | ts->tv_nsec = 0; |
200 | do { | 200 | do { |
201 | seq = read_seqcount_begin_no_lockdep(>od->seq); | 201 | seq = raw_read_seqcount_begin(>od->seq); |
202 | mode = gtod->clock.vclock_mode; | 202 | mode = gtod->clock.vclock_mode; |
203 | ts->tv_sec = gtod->monotonic_time_sec; | 203 | ts->tv_sec = gtod->monotonic_time_sec; |
204 | ns = gtod->monotonic_time_snsec; | 204 | ns = gtod->monotonic_time_snsec; |
@@ -214,7 +214,7 @@ notrace static int do_realtime_coarse(struct timespec *ts) | |||
214 | { | 214 | { |
215 | unsigned long seq; | 215 | unsigned long seq; |
216 | do { | 216 | do { |
217 | seq = read_seqcount_begin_no_lockdep(>od->seq); | 217 | seq = raw_read_seqcount_begin(>od->seq); |
218 | ts->tv_sec = gtod->wall_time_coarse.tv_sec; | 218 | ts->tv_sec = gtod->wall_time_coarse.tv_sec; |
219 | ts->tv_nsec = gtod->wall_time_coarse.tv_nsec; | 219 | ts->tv_nsec = gtod->wall_time_coarse.tv_nsec; |
220 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); | 220 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); |
@@ -225,7 +225,7 @@ notrace static int do_monotonic_coarse(struct timespec *ts) | |||
225 | { | 225 | { |
226 | unsigned long seq; | 226 | unsigned long seq; |
227 | do { | 227 | do { |
228 | seq = read_seqcount_begin_no_lockdep(>od->seq); | 228 | seq = raw_read_seqcount_begin(>od->seq); |
229 | ts->tv_sec = gtod->monotonic_time_coarse.tv_sec; | 229 | ts->tv_sec = gtod->monotonic_time_coarse.tv_sec; |
230 | ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec; | 230 | ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec; |
231 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); | 231 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); |
diff --git a/arch/x86/vdso/vdso.S b/arch/x86/vdso/vdso.S index 01f5e3b4613c..1e13eb8c9656 100644 --- a/arch/x86/vdso/vdso.S +++ b/arch/x86/vdso/vdso.S | |||
@@ -1,6 +1,5 @@ | |||
1 | #include <asm/page_types.h> | 1 | #include <asm/page_types.h> |
2 | #include <linux/linkage.h> | 2 | #include <linux/linkage.h> |
3 | #include <linux/init.h> | ||
4 | 3 | ||
5 | __PAGE_ALIGNED_DATA | 4 | __PAGE_ALIGNED_DATA |
6 | 5 | ||
diff --git a/arch/x86/vdso/vdsox32.S b/arch/x86/vdso/vdsox32.S index d6b9a7f42a8a..295f1c7543d8 100644 --- a/arch/x86/vdso/vdsox32.S +++ b/arch/x86/vdso/vdsox32.S | |||
@@ -1,6 +1,5 @@ | |||
1 | #include <asm/page_types.h> | 1 | #include <asm/page_types.h> |
2 | #include <linux/linkage.h> | 2 | #include <linux/linkage.h> |
3 | #include <linux/init.h> | ||
4 | 3 | ||
5 | __PAGE_ALIGNED_DATA | 4 | __PAGE_ALIGNED_DATA |
6 | 5 | ||
diff --git a/arch/xtensa/include/asm/barrier.h b/arch/xtensa/include/asm/barrier.h index ef021677d536..e1ee6b51dfc5 100644 --- a/arch/xtensa/include/asm/barrier.h +++ b/arch/xtensa/include/asm/barrier.h | |||
@@ -9,21 +9,14 @@ | |||
9 | #ifndef _XTENSA_SYSTEM_H | 9 | #ifndef _XTENSA_SYSTEM_H |
10 | #define _XTENSA_SYSTEM_H | 10 | #define _XTENSA_SYSTEM_H |
11 | 11 | ||
12 | #define smp_read_barrier_depends() do { } while(0) | ||
13 | #define read_barrier_depends() do { } while(0) | ||
14 | |||
15 | #define mb() ({ __asm__ __volatile__("memw" : : : "memory"); }) | 12 | #define mb() ({ __asm__ __volatile__("memw" : : : "memory"); }) |
16 | #define rmb() barrier() | 13 | #define rmb() barrier() |
17 | #define wmb() mb() | 14 | #define wmb() mb() |
18 | 15 | ||
19 | #ifdef CONFIG_SMP | 16 | #ifdef CONFIG_SMP |
20 | #error smp_* not defined | 17 | #error smp_* not defined |
21 | #else | ||
22 | #define smp_mb() barrier() | ||
23 | #define smp_rmb() barrier() | ||
24 | #define smp_wmb() barrier() | ||
25 | #endif | 18 | #endif |
26 | 19 | ||
27 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 20 | #include <asm-generic/barrier.h> |
28 | 21 | ||
29 | #endif /* _XTENSA_SYSTEM_H */ | 22 | #endif /* _XTENSA_SYSTEM_H */ |
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index a6869e110ce5..5d33c5415405 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <acpi/acpi_bus.h> | 12 | #include <acpi/acpi_bus.h> |
13 | #include <linux/cper.h> | 13 | #include <linux/cper.h> |
14 | #include <linux/ratelimit.h> | 14 | #include <linux/ratelimit.h> |
15 | #include <linux/edac.h> | ||
15 | #include <asm/cpu.h> | 16 | #include <asm/cpu.h> |
16 | #include <asm/mce.h> | 17 | #include <asm/mce.h> |
17 | 18 | ||
@@ -43,6 +44,8 @@ struct extlog_l1_head { | |||
43 | u8 rev1[12]; | 44 | u8 rev1[12]; |
44 | }; | 45 | }; |
45 | 46 | ||
47 | static int old_edac_report_status; | ||
48 | |||
46 | static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295"; | 49 | static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295"; |
47 | 50 | ||
48 | /* L1 table related physical address */ | 51 | /* L1 table related physical address */ |
@@ -150,7 +153,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, | |||
150 | 153 | ||
151 | rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu); | 154 | rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu); |
152 | 155 | ||
153 | return NOTIFY_DONE; | 156 | return NOTIFY_STOP; |
154 | } | 157 | } |
155 | 158 | ||
156 | static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret) | 159 | static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret) |
@@ -231,8 +234,12 @@ static int __init extlog_init(void) | |||
231 | u64 cap; | 234 | u64 cap; |
232 | int rc; | 235 | int rc; |
233 | 236 | ||
234 | rc = -ENODEV; | 237 | if (get_edac_report_status() == EDAC_REPORTING_FORCE) { |
238 | pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n"); | ||
239 | return -EPERM; | ||
240 | } | ||
235 | 241 | ||
242 | rc = -ENODEV; | ||
236 | rdmsrl(MSR_IA32_MCG_CAP, cap); | 243 | rdmsrl(MSR_IA32_MCG_CAP, cap); |
237 | if (!(cap & MCG_ELOG_P)) | 244 | if (!(cap & MCG_ELOG_P)) |
238 | return rc; | 245 | return rc; |
@@ -287,6 +294,12 @@ static int __init extlog_init(void) | |||
287 | if (elog_buf == NULL) | 294 | if (elog_buf == NULL) |
288 | goto err_release_elog; | 295 | goto err_release_elog; |
289 | 296 | ||
297 | /* | ||
298 | * eMCA event report method has higher priority than EDAC method, | ||
299 | * unless EDAC event report method is mandatory. | ||
300 | */ | ||
301 | old_edac_report_status = get_edac_report_status(); | ||
302 | set_edac_report_status(EDAC_REPORTING_DISABLED); | ||
290 | mce_register_decode_chain(&extlog_mce_dec); | 303 | mce_register_decode_chain(&extlog_mce_dec); |
291 | /* enable OS to be involved to take over management from BIOS */ | 304 | /* enable OS to be involved to take over management from BIOS */ |
292 | ((struct extlog_l1_head *)extlog_l1_addr)->flags |= FLAG_OS_OPTIN; | 305 | ((struct extlog_l1_head *)extlog_l1_addr)->flags |= FLAG_OS_OPTIN; |
@@ -308,6 +321,7 @@ err: | |||
308 | 321 | ||
309 | static void __exit extlog_exit(void) | 322 | static void __exit extlog_exit(void) |
310 | { | 323 | { |
324 | set_edac_report_status(old_edac_report_status); | ||
311 | mce_unregister_decode_chain(&extlog_mce_dec); | 325 | mce_unregister_decode_chain(&extlog_mce_dec); |
312 | ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN; | 326 | ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN; |
313 | if (extlog_l1_addr) | 327 | if (extlog_l1_addr) |
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index e60390597372..6745fe137b9e 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -162,7 +162,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { | |||
162 | { "80860F14", (unsigned long)&byt_sdio_dev_desc }, | 162 | { "80860F14", (unsigned long)&byt_sdio_dev_desc }, |
163 | { "80860F41", (unsigned long)&byt_i2c_dev_desc }, | 163 | { "80860F41", (unsigned long)&byt_i2c_dev_desc }, |
164 | { "INT33B2", }, | 164 | { "INT33B2", }, |
165 | { "INT33FC", }, | ||
166 | 165 | ||
167 | { "INT3430", (unsigned long)&lpt_dev_desc }, | 166 | { "INT3430", (unsigned long)&lpt_dev_desc }, |
168 | { "INT3431", (unsigned long)&lpt_dev_desc }, | 167 | { "INT3431", (unsigned long)&lpt_dev_desc }, |
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index fc6008fbce35..509452a62f96 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c | |||
@@ -193,10 +193,7 @@ static int power_saving_thread(void *data) | |||
193 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); | 193 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); |
194 | stop_critical_timings(); | 194 | stop_critical_timings(); |
195 | 195 | ||
196 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | 196 | mwait_idle_with_hints(power_saving_mwait_eax, 1); |
197 | smp_mb(); | ||
198 | if (!need_resched()) | ||
199 | __mwait(power_saving_mwait_eax, 1); | ||
200 | 197 | ||
201 | start_critical_timings(); | 198 | start_critical_timings(); |
202 | if (lapic_marked_unstable) | 199 | if (lapic_marked_unstable) |
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 6d2c49b86b7f..e55584a072c6 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/rculist.h> | 41 | #include <linux/rculist.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/debugfs.h> | 43 | #include <linux/debugfs.h> |
44 | #include <asm/unaligned.h> | ||
44 | 45 | ||
45 | #include "apei-internal.h" | 46 | #include "apei-internal.h" |
46 | 47 | ||
@@ -567,8 +568,7 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, | |||
567 | bit_offset = reg->bit_offset; | 568 | bit_offset = reg->bit_offset; |
568 | access_size_code = reg->access_width; | 569 | access_size_code = reg->access_width; |
569 | space_id = reg->space_id; | 570 | space_id = reg->space_id; |
570 | /* Handle possible alignment issues */ | 571 | *paddr = get_unaligned(®->address); |
571 | memcpy(paddr, ®->address, sizeof(*paddr)); | ||
572 | if (!*paddr) { | 572 | if (!*paddr) { |
573 | pr_warning(FW_BUG APEI_PFX | 573 | pr_warning(FW_BUG APEI_PFX |
574 | "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n", | 574 | "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n", |
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index fb57d03e698b..7dcc8a824aae 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
36 | #include <acpi/acpi.h> | 36 | #include <acpi/acpi.h> |
37 | #include <asm/unaligned.h> | ||
37 | 38 | ||
38 | #include "apei-internal.h" | 39 | #include "apei-internal.h" |
39 | 40 | ||
@@ -216,7 +217,7 @@ static void check_vendor_extension(u64 paddr, | |||
216 | static void *einj_get_parameter_address(void) | 217 | static void *einj_get_parameter_address(void) |
217 | { | 218 | { |
218 | int i; | 219 | int i; |
219 | u64 paddrv4 = 0, paddrv5 = 0; | 220 | u64 pa_v4 = 0, pa_v5 = 0; |
220 | struct acpi_whea_header *entry; | 221 | struct acpi_whea_header *entry; |
221 | 222 | ||
222 | entry = EINJ_TAB_ENTRY(einj_tab); | 223 | entry = EINJ_TAB_ENTRY(einj_tab); |
@@ -225,30 +226,28 @@ static void *einj_get_parameter_address(void) | |||
225 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && | 226 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && |
226 | entry->register_region.space_id == | 227 | entry->register_region.space_id == |
227 | ACPI_ADR_SPACE_SYSTEM_MEMORY) | 228 | ACPI_ADR_SPACE_SYSTEM_MEMORY) |
228 | memcpy(&paddrv4, &entry->register_region.address, | 229 | pa_v4 = get_unaligned(&entry->register_region.address); |
229 | sizeof(paddrv4)); | ||
230 | if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS && | 230 | if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS && |
231 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && | 231 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && |
232 | entry->register_region.space_id == | 232 | entry->register_region.space_id == |
233 | ACPI_ADR_SPACE_SYSTEM_MEMORY) | 233 | ACPI_ADR_SPACE_SYSTEM_MEMORY) |
234 | memcpy(&paddrv5, &entry->register_region.address, | 234 | pa_v5 = get_unaligned(&entry->register_region.address); |
235 | sizeof(paddrv5)); | ||
236 | entry++; | 235 | entry++; |
237 | } | 236 | } |
238 | if (paddrv5) { | 237 | if (pa_v5) { |
239 | struct set_error_type_with_address *v5param; | 238 | struct set_error_type_with_address *v5param; |
240 | 239 | ||
241 | v5param = acpi_os_map_memory(paddrv5, sizeof(*v5param)); | 240 | v5param = acpi_os_map_memory(pa_v5, sizeof(*v5param)); |
242 | if (v5param) { | 241 | if (v5param) { |
243 | acpi5 = 1; | 242 | acpi5 = 1; |
244 | check_vendor_extension(paddrv5, v5param); | 243 | check_vendor_extension(pa_v5, v5param); |
245 | return v5param; | 244 | return v5param; |
246 | } | 245 | } |
247 | } | 246 | } |
248 | if (param_extension && paddrv4) { | 247 | if (param_extension && pa_v4) { |
249 | struct einj_parameter *v4param; | 248 | struct einj_parameter *v4param; |
250 | 249 | ||
251 | v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param)); | 250 | v4param = acpi_os_map_memory(pa_v4, sizeof(*v4param)); |
252 | if (!v4param) | 251 | if (!v4param) |
253 | return NULL; | 252 | return NULL; |
254 | if (v4param->reserved1 || v4param->reserved2) { | 253 | if (v4param->reserved1 || v4param->reserved2) { |
@@ -416,7 +415,8 @@ out: | |||
416 | return rc; | 415 | return rc; |
417 | } | 416 | } |
418 | 417 | ||
419 | static int __einj_error_inject(u32 type, u64 param1, u64 param2) | 418 | static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, |
419 | u64 param3, u64 param4) | ||
420 | { | 420 | { |
421 | struct apei_exec_context ctx; | 421 | struct apei_exec_context ctx; |
422 | u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; | 422 | u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; |
@@ -446,6 +446,12 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) | |||
446 | break; | 446 | break; |
447 | } | 447 | } |
448 | v5param->flags = vendor_flags; | 448 | v5param->flags = vendor_flags; |
449 | } else if (flags) { | ||
450 | v5param->flags = flags; | ||
451 | v5param->memory_address = param1; | ||
452 | v5param->memory_address_range = param2; | ||
453 | v5param->apicid = param3; | ||
454 | v5param->pcie_sbdf = param4; | ||
449 | } else { | 455 | } else { |
450 | switch (type) { | 456 | switch (type) { |
451 | case ACPI_EINJ_PROCESSOR_CORRECTABLE: | 457 | case ACPI_EINJ_PROCESSOR_CORRECTABLE: |
@@ -514,11 +520,17 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) | |||
514 | } | 520 | } |
515 | 521 | ||
516 | /* Inject the specified hardware error */ | 522 | /* Inject the specified hardware error */ |
517 | static int einj_error_inject(u32 type, u64 param1, u64 param2) | 523 | static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, |
524 | u64 param3, u64 param4) | ||
518 | { | 525 | { |
519 | int rc; | 526 | int rc; |
520 | unsigned long pfn; | 527 | unsigned long pfn; |
521 | 528 | ||
529 | /* If user manually set "flags", make sure it is legal */ | ||
530 | if (flags && (flags & | ||
531 | ~(SETWA_FLAGS_APICID|SETWA_FLAGS_MEM|SETWA_FLAGS_PCIE_SBDF))) | ||
532 | return -EINVAL; | ||
533 | |||
522 | /* | 534 | /* |
523 | * We need extra sanity checks for memory errors. | 535 | * We need extra sanity checks for memory errors. |
524 | * Other types leap directly to injection. | 536 | * Other types leap directly to injection. |
@@ -532,7 +544,7 @@ static int einj_error_inject(u32 type, u64 param1, u64 param2) | |||
532 | if (type & ACPI5_VENDOR_BIT) { | 544 | if (type & ACPI5_VENDOR_BIT) { |
533 | if (vendor_flags != SETWA_FLAGS_MEM) | 545 | if (vendor_flags != SETWA_FLAGS_MEM) |
534 | goto inject; | 546 | goto inject; |
535 | } else if (!(type & MEM_ERROR_MASK)) | 547 | } else if (!(type & MEM_ERROR_MASK) && !(flags & SETWA_FLAGS_MEM)) |
536 | goto inject; | 548 | goto inject; |
537 | 549 | ||
538 | /* | 550 | /* |
@@ -546,15 +558,18 @@ static int einj_error_inject(u32 type, u64 param1, u64 param2) | |||
546 | 558 | ||
547 | inject: | 559 | inject: |
548 | mutex_lock(&einj_mutex); | 560 | mutex_lock(&einj_mutex); |
549 | rc = __einj_error_inject(type, param1, param2); | 561 | rc = __einj_error_inject(type, flags, param1, param2, param3, param4); |
550 | mutex_unlock(&einj_mutex); | 562 | mutex_unlock(&einj_mutex); |
551 | 563 | ||
552 | return rc; | 564 | return rc; |
553 | } | 565 | } |
554 | 566 | ||
555 | static u32 error_type; | 567 | static u32 error_type; |
568 | static u32 error_flags; | ||
556 | static u64 error_param1; | 569 | static u64 error_param1; |
557 | static u64 error_param2; | 570 | static u64 error_param2; |
571 | static u64 error_param3; | ||
572 | static u64 error_param4; | ||
558 | static struct dentry *einj_debug_dir; | 573 | static struct dentry *einj_debug_dir; |
559 | 574 | ||
560 | static int available_error_type_show(struct seq_file *m, void *v) | 575 | static int available_error_type_show(struct seq_file *m, void *v) |
@@ -648,7 +663,8 @@ static int error_inject_set(void *data, u64 val) | |||
648 | if (!error_type) | 663 | if (!error_type) |
649 | return -EINVAL; | 664 | return -EINVAL; |
650 | 665 | ||
651 | return einj_error_inject(error_type, error_param1, error_param2); | 666 | return einj_error_inject(error_type, error_flags, error_param1, error_param2, |
667 | error_param3, error_param4); | ||
652 | } | 668 | } |
653 | 669 | ||
654 | DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, | 670 | DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, |
@@ -729,6 +745,10 @@ static int __init einj_init(void) | |||
729 | rc = -ENOMEM; | 745 | rc = -ENOMEM; |
730 | einj_param = einj_get_parameter_address(); | 746 | einj_param = einj_get_parameter_address(); |
731 | if ((param_extension || acpi5) && einj_param) { | 747 | if ((param_extension || acpi5) && einj_param) { |
748 | fentry = debugfs_create_x32("flags", S_IRUSR | S_IWUSR, | ||
749 | einj_debug_dir, &error_flags); | ||
750 | if (!fentry) | ||
751 | goto err_unmap; | ||
732 | fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, | 752 | fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, |
733 | einj_debug_dir, &error_param1); | 753 | einj_debug_dir, &error_param1); |
734 | if (!fentry) | 754 | if (!fentry) |
@@ -737,6 +757,14 @@ static int __init einj_init(void) | |||
737 | einj_debug_dir, &error_param2); | 757 | einj_debug_dir, &error_param2); |
738 | if (!fentry) | 758 | if (!fentry) |
739 | goto err_unmap; | 759 | goto err_unmap; |
760 | fentry = debugfs_create_x64("param3", S_IRUSR | S_IWUSR, | ||
761 | einj_debug_dir, &error_param3); | ||
762 | if (!fentry) | ||
763 | goto err_unmap; | ||
764 | fentry = debugfs_create_x64("param4", S_IRUSR | S_IWUSR, | ||
765 | einj_debug_dir, &error_param4); | ||
766 | if (!fentry) | ||
767 | goto err_unmap; | ||
740 | 768 | ||
741 | fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR, | 769 | fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR, |
742 | einj_debug_dir, ¬rigger); | 770 | einj_debug_dir, ¬rigger); |
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index cb1d557fc22c..ed65e9c4b5b0 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -611,7 +611,7 @@ static void __erst_record_id_cache_compact(void) | |||
611 | if (entries[i] == APEI_ERST_INVALID_RECORD_ID) | 611 | if (entries[i] == APEI_ERST_INVALID_RECORD_ID) |
612 | continue; | 612 | continue; |
613 | if (wpos != i) | 613 | if (wpos != i) |
614 | memcpy(&entries[wpos], &entries[i], sizeof(entries[i])); | 614 | entries[wpos] = entries[i]; |
615 | wpos++; | 615 | wpos++; |
616 | } | 616 | } |
617 | erst_record_id_cache.len = wpos; | 617 | erst_record_id_cache.len = wpos; |
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index a30bc313787b..46766ef7ef5d 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -413,27 +413,31 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) | |||
413 | { | 413 | { |
414 | #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE | 414 | #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE |
415 | unsigned long pfn; | 415 | unsigned long pfn; |
416 | int flags = -1; | ||
416 | int sec_sev = ghes_severity(gdata->error_severity); | 417 | int sec_sev = ghes_severity(gdata->error_severity); |
417 | struct cper_sec_mem_err *mem_err; | 418 | struct cper_sec_mem_err *mem_err; |
418 | mem_err = (struct cper_sec_mem_err *)(gdata + 1); | 419 | mem_err = (struct cper_sec_mem_err *)(gdata + 1); |
419 | 420 | ||
420 | if (sec_sev == GHES_SEV_CORRECTED && | 421 | if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) |
421 | (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED) && | 422 | return; |
422 | (mem_err->validation_bits & CPER_MEM_VALID_PA)) { | 423 | |
423 | pfn = mem_err->physical_addr >> PAGE_SHIFT; | 424 | pfn = mem_err->physical_addr >> PAGE_SHIFT; |
424 | if (pfn_valid(pfn)) | 425 | if (!pfn_valid(pfn)) { |
425 | memory_failure_queue(pfn, 0, MF_SOFT_OFFLINE); | 426 | pr_warn_ratelimited(FW_WARN GHES_PFX |
426 | else if (printk_ratelimit()) | 427 | "Invalid address in generic error data: %#llx\n", |
427 | pr_warn(FW_WARN GHES_PFX | 428 | mem_err->physical_addr); |
428 | "Invalid address in generic error data: %#llx\n", | 429 | return; |
429 | mem_err->physical_addr); | ||
430 | } | ||
431 | if (sev == GHES_SEV_RECOVERABLE && | ||
432 | sec_sev == GHES_SEV_RECOVERABLE && | ||
433 | mem_err->validation_bits & CPER_MEM_VALID_PA) { | ||
434 | pfn = mem_err->physical_addr >> PAGE_SHIFT; | ||
435 | memory_failure_queue(pfn, 0, 0); | ||
436 | } | 430 | } |
431 | |||
432 | /* iff following two events can be handled properly by now */ | ||
433 | if (sec_sev == GHES_SEV_CORRECTED && | ||
434 | (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED)) | ||
435 | flags = MF_SOFT_OFFLINE; | ||
436 | if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE) | ||
437 | flags = 0; | ||
438 | |||
439 | if (flags != -1) | ||
440 | memory_failure_queue(pfn, 0, flags); | ||
437 | #endif | 441 | #endif |
438 | } | 442 | } |
439 | 443 | ||
@@ -453,8 +457,7 @@ static void ghes_do_proc(struct ghes *ghes, | |||
453 | ghes_edac_report_mem_error(ghes, sev, mem_err); | 457 | ghes_edac_report_mem_error(ghes, sev, mem_err); |
454 | 458 | ||
455 | #ifdef CONFIG_X86_MCE | 459 | #ifdef CONFIG_X86_MCE |
456 | apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED, | 460 | apei_mce_report_mem_error(sev, mem_err); |
457 | mem_err); | ||
458 | #endif | 461 | #endif |
459 | ghes_handle_memory_failure(gdata, sev); | 462 | ghes_handle_memory_failure(gdata, sev); |
460 | } | 463 | } |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 644516d9bde6..f90c56c8379e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -727,11 +727,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
727 | if (unlikely(!pr)) | 727 | if (unlikely(!pr)) |
728 | return -EINVAL; | 728 | return -EINVAL; |
729 | 729 | ||
730 | if (cx->entry_method == ACPI_CSTATE_FFH) { | ||
731 | if (current_set_polling_and_test()) | ||
732 | return -EINVAL; | ||
733 | } | ||
734 | |||
735 | lapic_timer_state_broadcast(pr, cx, 1); | 730 | lapic_timer_state_broadcast(pr, cx, 1); |
736 | acpi_idle_do_entry(cx); | 731 | acpi_idle_do_entry(cx); |
737 | 732 | ||
@@ -785,11 +780,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
785 | if (unlikely(!pr)) | 780 | if (unlikely(!pr)) |
786 | return -EINVAL; | 781 | return -EINVAL; |
787 | 782 | ||
788 | if (cx->entry_method == ACPI_CSTATE_FFH) { | ||
789 | if (current_set_polling_and_test()) | ||
790 | return -EINVAL; | ||
791 | } | ||
792 | |||
793 | /* | 783 | /* |
794 | * Must be done before busmaster disable as we might need to | 784 | * Must be done before busmaster disable as we might need to |
795 | * access HPET ! | 785 | * access HPET ! |
@@ -841,11 +831,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
841 | } | 831 | } |
842 | } | 832 | } |
843 | 833 | ||
844 | if (cx->entry_method == ACPI_CSTATE_FFH) { | ||
845 | if (current_set_polling_and_test()) | ||
846 | return -EINVAL; | ||
847 | } | ||
848 | |||
849 | acpi_unlazy_tlb(smp_processor_id()); | 834 | acpi_unlazy_tlb(smp_processor_id()); |
850 | 835 | ||
851 | /* Tell the scheduler that we are going deep-idle: */ | 836 | /* Tell the scheduler that we are going deep-idle: */ |
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 5a95baf4b104..27de5046708a 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c | |||
@@ -43,9 +43,6 @@ | |||
43 | #include <linux/zorro.h> | 43 | #include <linux/zorro.h> |
44 | 44 | ||
45 | 45 | ||
46 | extern int m68k_realnum_memory; | ||
47 | extern struct mem_info m68k_memory[NUM_MEMINFO]; | ||
48 | |||
49 | #define Z2MINOR_COMBINED (0) | 46 | #define Z2MINOR_COMBINED (0) |
50 | #define Z2MINOR_Z2ONLY (1) | 47 | #define Z2MINOR_Z2ONLY (1) |
51 | #define Z2MINOR_CHIPONLY (2) | 48 | #define Z2MINOR_CHIPONLY (2) |
@@ -116,8 +113,8 @@ get_z2ram( void ) | |||
116 | if ( test_bit( i, zorro_unused_z2ram ) ) | 113 | if ( test_bit( i, zorro_unused_z2ram ) ) |
117 | { | 114 | { |
118 | z2_count++; | 115 | z2_count++; |
119 | z2ram_map[ z2ram_size++ ] = | 116 | z2ram_map[z2ram_size++] = (unsigned long)ZTWO_VADDR(Z2RAM_START) + |
120 | ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT ); | 117 | (i << Z2RAM_CHUNKSHIFT); |
121 | clear_bit( i, zorro_unused_z2ram ); | 118 | clear_bit( i, zorro_unused_z2ram ); |
122 | } | 119 | } |
123 | } | 120 | } |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 634c4d6dd45a..cd6950fd8caf 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -37,6 +37,10 @@ config SUN4I_TIMER | |||
37 | select CLKSRC_MMIO | 37 | select CLKSRC_MMIO |
38 | bool | 38 | bool |
39 | 39 | ||
40 | config SUN5I_HSTIMER | ||
41 | select CLKSRC_MMIO | ||
42 | bool | ||
43 | |||
40 | config VT8500_TIMER | 44 | config VT8500_TIMER |
41 | bool | 45 | bool |
42 | 46 | ||
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 33621efb9148..358358d87b6d 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o | |||
22 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o | 22 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o |
23 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o | 23 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o |
24 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o | 24 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o |
25 | obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o | ||
25 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o | 26 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o |
26 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o | 27 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o |
27 | obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o | 28 | obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o |
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index c639b1a9e996..0fc31d029e52 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c | |||
@@ -202,7 +202,7 @@ static struct clocksource gt_clocksource = { | |||
202 | }; | 202 | }; |
203 | 203 | ||
204 | #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK | 204 | #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK |
205 | static u32 notrace gt_sched_clock_read(void) | 205 | static u64 notrace gt_sched_clock_read(void) |
206 | { | 206 | { |
207 | return gt_counter_read(); | 207 | return gt_counter_read(); |
208 | } | 208 | } |
@@ -217,7 +217,7 @@ static void __init gt_clocksource_init(void) | |||
217 | writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); | 217 | writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); |
218 | 218 | ||
219 | #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK | 219 | #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK |
220 | setup_sched_clock(gt_sched_clock_read, 32, gt_clk_rate); | 220 | sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate); |
221 | #endif | 221 | #endif |
222 | clocksource_register_hz(>_clocksource, gt_clk_rate); | 222 | clocksource_register_hz(>_clocksource, gt_clk_rate); |
223 | } | 223 | } |
diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index 0d7d8c3ed6b2..5176e761166b 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c | |||
@@ -98,12 +98,6 @@ kona_timer_get_counter(void *timer_base, uint32_t *msw, uint32_t *lsw) | |||
98 | return; | 98 | return; |
99 | } | 99 | } |
100 | 100 | ||
101 | static const struct of_device_id bcm_timer_ids[] __initconst = { | ||
102 | {.compatible = "brcm,kona-timer"}, | ||
103 | {.compatible = "bcm,kona-timer"}, /* deprecated name */ | ||
104 | {}, | ||
105 | }; | ||
106 | |||
107 | static void __init kona_timers_init(struct device_node *node) | 101 | static void __init kona_timers_init(struct device_node *node) |
108 | { | 102 | { |
109 | u32 freq; | 103 | u32 freq; |
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index b2bb3a4bc205..63f176de0d02 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c | |||
@@ -67,11 +67,13 @@ | |||
67 | * struct ttc_timer - This definition defines local timer structure | 67 | * struct ttc_timer - This definition defines local timer structure |
68 | * | 68 | * |
69 | * @base_addr: Base address of timer | 69 | * @base_addr: Base address of timer |
70 | * @freq: Timer input clock frequency | ||
70 | * @clk: Associated clock source | 71 | * @clk: Associated clock source |
71 | * @clk_rate_change_nb Notifier block for clock rate changes | 72 | * @clk_rate_change_nb Notifier block for clock rate changes |
72 | */ | 73 | */ |
73 | struct ttc_timer { | 74 | struct ttc_timer { |
74 | void __iomem *base_addr; | 75 | void __iomem *base_addr; |
76 | unsigned long freq; | ||
75 | struct clk *clk; | 77 | struct clk *clk; |
76 | struct notifier_block clk_rate_change_nb; | 78 | struct notifier_block clk_rate_change_nb; |
77 | }; | 79 | }; |
@@ -158,7 +160,7 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs) | |||
158 | TTC_COUNT_VAL_OFFSET); | 160 | TTC_COUNT_VAL_OFFSET); |
159 | } | 161 | } |
160 | 162 | ||
161 | static u32 notrace ttc_sched_clock_read(void) | 163 | static u64 notrace ttc_sched_clock_read(void) |
162 | { | 164 | { |
163 | return __raw_readl(ttc_sched_clock_val_reg); | 165 | return __raw_readl(ttc_sched_clock_val_reg); |
164 | } | 166 | } |
@@ -196,9 +198,8 @@ static void ttc_set_mode(enum clock_event_mode mode, | |||
196 | 198 | ||
197 | switch (mode) { | 199 | switch (mode) { |
198 | case CLOCK_EVT_MODE_PERIODIC: | 200 | case CLOCK_EVT_MODE_PERIODIC: |
199 | ttc_set_interval(timer, | 201 | ttc_set_interval(timer, DIV_ROUND_CLOSEST(ttce->ttc.freq, |
200 | DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk), | 202 | PRESCALE * HZ)); |
201 | PRESCALE * HZ)); | ||
202 | break; | 203 | break; |
203 | case CLOCK_EVT_MODE_ONESHOT: | 204 | case CLOCK_EVT_MODE_ONESHOT: |
204 | case CLOCK_EVT_MODE_UNUSED: | 205 | case CLOCK_EVT_MODE_UNUSED: |
@@ -273,6 +274,8 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) | |||
273 | return; | 274 | return; |
274 | } | 275 | } |
275 | 276 | ||
277 | ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk); | ||
278 | |||
276 | ttccs->ttc.clk_rate_change_nb.notifier_call = | 279 | ttccs->ttc.clk_rate_change_nb.notifier_call = |
277 | ttc_rate_change_clocksource_cb; | 280 | ttc_rate_change_clocksource_cb; |
278 | ttccs->ttc.clk_rate_change_nb.next = NULL; | 281 | ttccs->ttc.clk_rate_change_nb.next = NULL; |
@@ -298,16 +301,14 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) | |||
298 | __raw_writel(CNT_CNTRL_RESET, | 301 | __raw_writel(CNT_CNTRL_RESET, |
299 | ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); | 302 | ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); |
300 | 303 | ||
301 | err = clocksource_register_hz(&ttccs->cs, | 304 | err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE); |
302 | clk_get_rate(ttccs->ttc.clk) / PRESCALE); | ||
303 | if (WARN_ON(err)) { | 305 | if (WARN_ON(err)) { |
304 | kfree(ttccs); | 306 | kfree(ttccs); |
305 | return; | 307 | return; |
306 | } | 308 | } |
307 | 309 | ||
308 | ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; | 310 | ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; |
309 | setup_sched_clock(ttc_sched_clock_read, 16, | 311 | sched_clock_register(ttc_sched_clock_read, 16, ttccs->ttc.freq / PRESCALE); |
310 | clk_get_rate(ttccs->ttc.clk) / PRESCALE); | ||
311 | } | 312 | } |
312 | 313 | ||
313 | static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, | 314 | static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, |
@@ -334,6 +335,9 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, | |||
334 | ndata->new_rate / PRESCALE); | 335 | ndata->new_rate / PRESCALE); |
335 | local_irq_restore(flags); | 336 | local_irq_restore(flags); |
336 | 337 | ||
338 | /* update cached frequency */ | ||
339 | ttc->freq = ndata->new_rate; | ||
340 | |||
337 | /* fall through */ | 341 | /* fall through */ |
338 | } | 342 | } |
339 | case PRE_RATE_CHANGE: | 343 | case PRE_RATE_CHANGE: |
@@ -367,6 +371,7 @@ static void __init ttc_setup_clockevent(struct clk *clk, | |||
367 | if (clk_notifier_register(ttcce->ttc.clk, | 371 | if (clk_notifier_register(ttcce->ttc.clk, |
368 | &ttcce->ttc.clk_rate_change_nb)) | 372 | &ttcce->ttc.clk_rate_change_nb)) |
369 | pr_warn("Unable to register clock notifier.\n"); | 373 | pr_warn("Unable to register clock notifier.\n"); |
374 | ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk); | ||
370 | 375 | ||
371 | ttcce->ttc.base_addr = base; | 376 | ttcce->ttc.base_addr = base; |
372 | ttcce->ce.name = "ttc_clockevent"; | 377 | ttcce->ce.name = "ttc_clockevent"; |
@@ -388,15 +393,14 @@ static void __init ttc_setup_clockevent(struct clk *clk, | |||
388 | __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); | 393 | __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); |
389 | 394 | ||
390 | err = request_irq(irq, ttc_clock_event_interrupt, | 395 | err = request_irq(irq, ttc_clock_event_interrupt, |
391 | IRQF_DISABLED | IRQF_TIMER, | 396 | IRQF_TIMER, ttcce->ce.name, ttcce); |
392 | ttcce->ce.name, ttcce); | ||
393 | if (WARN_ON(err)) { | 397 | if (WARN_ON(err)) { |
394 | kfree(ttcce); | 398 | kfree(ttcce); |
395 | return; | 399 | return; |
396 | } | 400 | } |
397 | 401 | ||
398 | clockevents_config_and_register(&ttcce->ce, | 402 | clockevents_config_and_register(&ttcce->ce, |
399 | clk_get_rate(ttcce->ttc.clk) / PRESCALE, 1, 0xfffe); | 403 | ttcce->ttc.freq / PRESCALE, 1, 0xfffe); |
400 | } | 404 | } |
401 | 405 | ||
402 | /** | 406 | /** |
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c index b9ddd9e3a2f5..ae2e4278c42a 100644 --- a/drivers/clocksource/clksrc-of.c +++ b/drivers/clocksource/clksrc-of.c | |||
@@ -28,6 +28,7 @@ void __init clocksource_of_init(void) | |||
28 | struct device_node *np; | 28 | struct device_node *np; |
29 | const struct of_device_id *match; | 29 | const struct of_device_id *match; |
30 | clocksource_of_init_fn init_func; | 30 | clocksource_of_init_fn init_func; |
31 | unsigned clocksources = 0; | ||
31 | 32 | ||
32 | for_each_matching_node_and_match(np, __clksrc_of_table, &match) { | 33 | for_each_matching_node_and_match(np, __clksrc_of_table, &match) { |
33 | if (!of_device_is_available(np)) | 34 | if (!of_device_is_available(np)) |
@@ -35,5 +36,8 @@ void __init clocksource_of_init(void) | |||
35 | 36 | ||
36 | init_func = match->data; | 37 | init_func = match->data; |
37 | init_func(np); | 38 | init_func(np); |
39 | clocksources++; | ||
38 | } | 40 | } |
41 | if (!clocksources) | ||
42 | pr_crit("%s: no matching clocksources found\n", __func__); | ||
39 | } | 43 | } |
diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index ea210482dd20..db2105290898 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c | |||
@@ -131,7 +131,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id) | |||
131 | 131 | ||
132 | static struct irqaction mfgptirq = { | 132 | static struct irqaction mfgptirq = { |
133 | .handler = mfgpt_tick, | 133 | .handler = mfgpt_tick, |
134 | .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED, | 134 | .flags = IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED, |
135 | .name = DRV_NAME, | 135 | .name = DRV_NAME, |
136 | }; | 136 | }; |
137 | 137 | ||
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index e54ca1062d8e..f3656a6b0382 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c | |||
@@ -243,8 +243,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, | |||
243 | dw_ced->irqaction.dev_id = &dw_ced->ced; | 243 | dw_ced->irqaction.dev_id = &dw_ced->ced; |
244 | dw_ced->irqaction.irq = irq; | 244 | dw_ced->irqaction.irq = irq; |
245 | dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | | 245 | dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | |
246 | IRQF_NOBALANCING | | 246 | IRQF_NOBALANCING; |
247 | IRQF_DISABLED; | ||
248 | 247 | ||
249 | dw_ced->eoi = apbt_eoi; | 248 | dw_ced->eoi = apbt_eoi; |
250 | err = setup_irq(irq, &dw_ced->irqaction); | 249 | err = setup_irq(irq, &dw_ced->irqaction); |
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index ed7b73b508e0..152a3f3875ee 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c | |||
@@ -187,7 +187,7 @@ static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id) | |||
187 | 187 | ||
188 | static struct irqaction nmdk_timer_irq = { | 188 | static struct irqaction nmdk_timer_irq = { |
189 | .name = "Nomadik Timer Tick", | 189 | .name = "Nomadik Timer Tick", |
190 | .flags = IRQF_DISABLED | IRQF_TIMER, | 190 | .flags = IRQF_TIMER, |
191 | .handler = nmdk_timer_interrupt, | 191 | .handler = nmdk_timer_interrupt, |
192 | .dev_id = &nmdk_clkevt, | 192 | .dev_id = &nmdk_clkevt, |
193 | }; | 193 | }; |
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index 85082e8d3052..5645cfc90c41 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c | |||
@@ -264,7 +264,7 @@ static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id) | |||
264 | 264 | ||
265 | static struct irqaction samsung_clock_event_irq = { | 265 | static struct irqaction samsung_clock_event_irq = { |
266 | .name = "samsung_time_irq", | 266 | .name = "samsung_time_irq", |
267 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 267 | .flags = IRQF_TIMER | IRQF_IRQPOLL, |
268 | .handler = samsung_clock_event_isr, | 268 | .handler = samsung_clock_event_isr, |
269 | .dev_id = &time_event_device, | 269 | .dev_id = &time_event_device, |
270 | }; | 270 | }; |
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 0965e9848b3d..0b1836a6c539 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
@@ -634,12 +634,18 @@ static int sh_cmt_clock_event_next(unsigned long delta, | |||
634 | 634 | ||
635 | static void sh_cmt_clock_event_suspend(struct clock_event_device *ced) | 635 | static void sh_cmt_clock_event_suspend(struct clock_event_device *ced) |
636 | { | 636 | { |
637 | pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev); | 637 | struct sh_cmt_priv *p = ced_to_sh_cmt(ced); |
638 | |||
639 | pm_genpd_syscore_poweroff(&p->pdev->dev); | ||
640 | clk_unprepare(p->clk); | ||
638 | } | 641 | } |
639 | 642 | ||
640 | static void sh_cmt_clock_event_resume(struct clock_event_device *ced) | 643 | static void sh_cmt_clock_event_resume(struct clock_event_device *ced) |
641 | { | 644 | { |
642 | pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev); | 645 | struct sh_cmt_priv *p = ced_to_sh_cmt(ced); |
646 | |||
647 | clk_prepare(p->clk); | ||
648 | pm_genpd_syscore_poweron(&p->pdev->dev); | ||
643 | } | 649 | } |
644 | 650 | ||
645 | static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, | 651 | static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, |
@@ -726,8 +732,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
726 | p->irqaction.name = dev_name(&p->pdev->dev); | 732 | p->irqaction.name = dev_name(&p->pdev->dev); |
727 | p->irqaction.handler = sh_cmt_interrupt; | 733 | p->irqaction.handler = sh_cmt_interrupt; |
728 | p->irqaction.dev_id = p; | 734 | p->irqaction.dev_id = p; |
729 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ | 735 | p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; |
730 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
731 | 736 | ||
732 | /* get hold of clock */ | 737 | /* get hold of clock */ |
733 | p->clk = clk_get(&p->pdev->dev, "cmt_fck"); | 738 | p->clk = clk_get(&p->pdev->dev, "cmt_fck"); |
@@ -737,6 +742,10 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
737 | goto err2; | 742 | goto err2; |
738 | } | 743 | } |
739 | 744 | ||
745 | ret = clk_prepare(p->clk); | ||
746 | if (ret < 0) | ||
747 | goto err3; | ||
748 | |||
740 | if (res2 && (resource_size(res2) == 4)) { | 749 | if (res2 && (resource_size(res2) == 4)) { |
741 | /* assume both CMSTR and CMCSR to be 32-bit */ | 750 | /* assume both CMSTR and CMCSR to be 32-bit */ |
742 | p->read_control = sh_cmt_read32; | 751 | p->read_control = sh_cmt_read32; |
@@ -773,19 +782,21 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
773 | cfg->clocksource_rating); | 782 | cfg->clocksource_rating); |
774 | if (ret) { | 783 | if (ret) { |
775 | dev_err(&p->pdev->dev, "registration failed\n"); | 784 | dev_err(&p->pdev->dev, "registration failed\n"); |
776 | goto err3; | 785 | goto err4; |
777 | } | 786 | } |
778 | p->cs_enabled = false; | 787 | p->cs_enabled = false; |
779 | 788 | ||
780 | ret = setup_irq(irq, &p->irqaction); | 789 | ret = setup_irq(irq, &p->irqaction); |
781 | if (ret) { | 790 | if (ret) { |
782 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); | 791 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); |
783 | goto err3; | 792 | goto err4; |
784 | } | 793 | } |
785 | 794 | ||
786 | platform_set_drvdata(pdev, p); | 795 | platform_set_drvdata(pdev, p); |
787 | 796 | ||
788 | return 0; | 797 | return 0; |
798 | err4: | ||
799 | clk_unprepare(p->clk); | ||
789 | err3: | 800 | err3: |
790 | clk_put(p->clk); | 801 | clk_put(p->clk); |
791 | err2: | 802 | err2: |
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 3cf12834681e..e30d76e0a6fa 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c | |||
@@ -302,8 +302,7 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) | |||
302 | p->irqaction.handler = sh_mtu2_interrupt; | 302 | p->irqaction.handler = sh_mtu2_interrupt; |
303 | p->irqaction.dev_id = p; | 303 | p->irqaction.dev_id = p; |
304 | p->irqaction.irq = irq; | 304 | p->irqaction.irq = irq; |
305 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ | 305 | p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; |
306 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
307 | 306 | ||
308 | /* get hold of clock */ | 307 | /* get hold of clock */ |
309 | p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); | 308 | p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); |
@@ -358,7 +357,6 @@ static int sh_mtu2_probe(struct platform_device *pdev) | |||
358 | ret = sh_mtu2_setup(p, pdev); | 357 | ret = sh_mtu2_setup(p, pdev); |
359 | if (ret) { | 358 | if (ret) { |
360 | kfree(p); | 359 | kfree(p); |
361 | platform_set_drvdata(pdev, NULL); | ||
362 | pm_runtime_idle(&pdev->dev); | 360 | pm_runtime_idle(&pdev->dev); |
363 | return ret; | 361 | return ret; |
364 | } | 362 | } |
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 63557cda0a7d..ecd7b60bfdfa 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
@@ -462,8 +462,7 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) | |||
462 | p->irqaction.handler = sh_tmu_interrupt; | 462 | p->irqaction.handler = sh_tmu_interrupt; |
463 | p->irqaction.dev_id = p; | 463 | p->irqaction.dev_id = p; |
464 | p->irqaction.irq = irq; | 464 | p->irqaction.irq = irq; |
465 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ | 465 | p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; |
466 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
467 | 466 | ||
468 | /* get hold of clock */ | 467 | /* get hold of clock */ |
469 | p->clk = clk_get(&p->pdev->dev, "tmu_fck"); | 468 | p->clk = clk_get(&p->pdev->dev, "tmu_fck"); |
@@ -523,7 +522,6 @@ static int sh_tmu_probe(struct platform_device *pdev) | |||
523 | ret = sh_tmu_setup(p, pdev); | 522 | ret = sh_tmu_setup(p, pdev); |
524 | if (ret) { | 523 | if (ret) { |
525 | kfree(p); | 524 | kfree(p); |
526 | platform_set_drvdata(pdev, NULL); | ||
527 | pm_runtime_idle(&pdev->dev); | 525 | pm_runtime_idle(&pdev->dev); |
528 | return ret; | 526 | return ret; |
529 | } | 527 | } |
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index a4f6119aafd8..bf497afba9ad 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c | |||
@@ -114,7 +114,7 @@ static int sun4i_clkevt_next_event(unsigned long evt, | |||
114 | 114 | ||
115 | static struct clock_event_device sun4i_clockevent = { | 115 | static struct clock_event_device sun4i_clockevent = { |
116 | .name = "sun4i_tick", | 116 | .name = "sun4i_tick", |
117 | .rating = 300, | 117 | .rating = 350, |
118 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 118 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
119 | .set_mode = sun4i_clkevt_mode, | 119 | .set_mode = sun4i_clkevt_mode, |
120 | .set_next_event = sun4i_clkevt_next_event, | 120 | .set_next_event = sun4i_clkevt_next_event, |
@@ -138,7 +138,7 @@ static struct irqaction sun4i_timer_irq = { | |||
138 | .dev_id = &sun4i_clockevent, | 138 | .dev_id = &sun4i_clockevent, |
139 | }; | 139 | }; |
140 | 140 | ||
141 | static u32 sun4i_timer_sched_read(void) | 141 | static u64 notrace sun4i_timer_sched_read(void) |
142 | { | 142 | { |
143 | return ~readl(timer_base + TIMER_CNTVAL_REG(1)); | 143 | return ~readl(timer_base + TIMER_CNTVAL_REG(1)); |
144 | } | 144 | } |
@@ -170,9 +170,9 @@ static void __init sun4i_timer_init(struct device_node *node) | |||
170 | TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), | 170 | TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), |
171 | timer_base + TIMER_CTL_REG(1)); | 171 | timer_base + TIMER_CTL_REG(1)); |
172 | 172 | ||
173 | setup_sched_clock(sun4i_timer_sched_read, 32, rate); | 173 | sched_clock_register(sun4i_timer_sched_read, 32, rate); |
174 | clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, | 174 | clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, |
175 | rate, 300, 32, clocksource_mmio_readl_down); | 175 | rate, 350, 32, clocksource_mmio_readl_down); |
176 | 176 | ||
177 | ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); | 177 | ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); |
178 | 178 | ||
@@ -190,7 +190,8 @@ static void __init sun4i_timer_init(struct device_node *node) | |||
190 | val = readl(timer_base + TIMER_IRQ_EN_REG); | 190 | val = readl(timer_base + TIMER_IRQ_EN_REG); |
191 | writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); | 191 | writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); |
192 | 192 | ||
193 | sun4i_clockevent.cpumask = cpumask_of(0); | 193 | sun4i_clockevent.cpumask = cpu_possible_mask; |
194 | sun4i_clockevent.irq = irq; | ||
194 | 195 | ||
195 | clockevents_config_and_register(&sun4i_clockevent, rate, | 196 | clockevents_config_and_register(&sun4i_clockevent, rate, |
196 | TIMER_SYNC_TICKS, 0xffffffff); | 197 | TIMER_SYNC_TICKS, 0xffffffff); |
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index 642849256d82..d1869f02051c 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c | |||
@@ -149,7 +149,7 @@ static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) | |||
149 | 149 | ||
150 | static struct irqaction tegra_timer_irq = { | 150 | static struct irqaction tegra_timer_irq = { |
151 | .name = "timer0", | 151 | .name = "timer0", |
152 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH, | 152 | .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH, |
153 | .handler = tegra_timer_interrupt, | 153 | .handler = tegra_timer_interrupt, |
154 | .dev_id = &tegra_clockevent, | 154 | .dev_id = &tegra_clockevent, |
155 | }; | 155 | }; |
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 4e7f6802e840..ee8691b89944 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c | |||
@@ -76,6 +76,7 @@ | |||
76 | static void __iomem *timer_base, *local_base; | 76 | static void __iomem *timer_base, *local_base; |
77 | static unsigned int timer_clk; | 77 | static unsigned int timer_clk; |
78 | static bool timer25Mhz = true; | 78 | static bool timer25Mhz = true; |
79 | static u32 enable_mask; | ||
79 | 80 | ||
80 | /* | 81 | /* |
81 | * Number of timer ticks per jiffy. | 82 | * Number of timer ticks per jiffy. |
@@ -121,8 +122,7 @@ armada_370_xp_clkevt_next_event(unsigned long delta, | |||
121 | /* | 122 | /* |
122 | * Enable the timer. | 123 | * Enable the timer. |
123 | */ | 124 | */ |
124 | local_timer_ctrl_clrset(TIMER0_RELOAD_EN, | 125 | local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask); |
125 | TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT)); | ||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
@@ -141,9 +141,7 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode, | |||
141 | /* | 141 | /* |
142 | * Enable timer. | 142 | * Enable timer. |
143 | */ | 143 | */ |
144 | local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | | 144 | local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); |
145 | TIMER0_EN | | ||
146 | TIMER0_DIV(TIMER_DIVIDER_SHIFT)); | ||
147 | } else { | 145 | } else { |
148 | /* | 146 | /* |
149 | * Disable timer. | 147 | * Disable timer. |
@@ -240,10 +238,13 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) | |||
240 | WARN_ON(!timer_base); | 238 | WARN_ON(!timer_base); |
241 | local_base = of_iomap(np, 1); | 239 | local_base = of_iomap(np, 1); |
242 | 240 | ||
243 | if (timer25Mhz) | 241 | if (timer25Mhz) { |
244 | set = TIMER0_25MHZ; | 242 | set = TIMER0_25MHZ; |
245 | else | 243 | enable_mask = TIMER0_EN; |
244 | } else { | ||
246 | clr = TIMER0_25MHZ; | 245 | clr = TIMER0_25MHZ; |
246 | enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); | ||
247 | } | ||
247 | timer_ctrl_clrset(clr, set); | 248 | timer_ctrl_clrset(clr, set); |
248 | local_timer_ctrl_clrset(clr, set); | 249 | local_timer_ctrl_clrset(clr, set); |
249 | 250 | ||
@@ -262,8 +263,7 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) | |||
262 | writel(0xffffffff, timer_base + TIMER0_VAL_OFF); | 263 | writel(0xffffffff, timer_base + TIMER0_VAL_OFF); |
263 | writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); | 264 | writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); |
264 | 265 | ||
265 | timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN | | 266 | timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); |
266 | TIMER0_DIV(TIMER_DIVIDER_SHIFT)); | ||
267 | 267 | ||
268 | /* | 268 | /* |
269 | * Set scale and timer for sched_clock. | 269 | * Set scale and timer for sched_clock. |
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index 9c7f018a67ca..20066222f3f2 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c | |||
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(orion_timer_ctrl_clrset); | |||
53 | /* | 53 | /* |
54 | * Free-running clocksource handling. | 54 | * Free-running clocksource handling. |
55 | */ | 55 | */ |
56 | static u32 notrace orion_read_sched_clock(void) | 56 | static u64 notrace orion_read_sched_clock(void) |
57 | { | 57 | { |
58 | return ~readl(timer_base + TIMER0_VAL); | 58 | return ~readl(timer_base + TIMER0_VAL); |
59 | } | 59 | } |
@@ -135,7 +135,7 @@ static void __init orion_timer_init(struct device_node *np) | |||
135 | clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", | 135 | clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", |
136 | clk_get_rate(clk), 300, 32, | 136 | clk_get_rate(clk), 300, 32, |
137 | clocksource_mmio_readl_down); | 137 | clocksource_mmio_readl_down); |
138 | setup_sched_clock(orion_read_sched_clock, 32, clk_get_rate(clk)); | 138 | sched_clock_register(orion_read_sched_clock, 32, clk_get_rate(clk)); |
139 | 139 | ||
140 | /* setup timer1 as clockevent timer */ | 140 | /* setup timer1 as clockevent timer */ |
141 | if (setup_irq(irq, &orion_clkevt_irq)) | 141 | if (setup_irq(irq, &orion_clkevt_irq)) |
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c new file mode 100644 index 000000000000..deebcd6469fc --- /dev/null +++ b/drivers/clocksource/timer-sun5i.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * Allwinner SoCs hstimer driver. | ||
3 | * | ||
4 | * Copyright (C) 2013 Maxime Ripard | ||
5 | * | ||
6 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/clockchips.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/irqreturn.h> | ||
19 | #include <linux/sched_clock.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include <linux/of_irq.h> | ||
23 | |||
24 | #define TIMER_IRQ_EN_REG 0x00 | ||
25 | #define TIMER_IRQ_EN(val) BIT(val) | ||
26 | #define TIMER_IRQ_ST_REG 0x04 | ||
27 | #define TIMER_CTL_REG(val) (0x20 * (val) + 0x10) | ||
28 | #define TIMER_CTL_ENABLE BIT(0) | ||
29 | #define TIMER_CTL_RELOAD BIT(1) | ||
30 | #define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4) | ||
31 | #define TIMER_CTL_ONESHOT BIT(7) | ||
32 | #define TIMER_INTVAL_LO_REG(val) (0x20 * (val) + 0x14) | ||
33 | #define TIMER_INTVAL_HI_REG(val) (0x20 * (val) + 0x18) | ||
34 | #define TIMER_CNTVAL_LO_REG(val) (0x20 * (val) + 0x1c) | ||
35 | #define TIMER_CNTVAL_HI_REG(val) (0x20 * (val) + 0x20) | ||
36 | |||
37 | #define TIMER_SYNC_TICKS 3 | ||
38 | |||
39 | static void __iomem *timer_base; | ||
40 | static u32 ticks_per_jiffy; | ||
41 | |||
42 | /* | ||
43 | * When we disable a timer, we need to wait at least for 2 cycles of | ||
44 | * the timer source clock. We will use for that the clocksource timer | ||
45 | * that is already setup and runs at the same frequency than the other | ||
46 | * timers, and we never will be disabled. | ||
47 | */ | ||
48 | static void sun5i_clkevt_sync(void) | ||
49 | { | ||
50 | u32 old = readl(timer_base + TIMER_CNTVAL_LO_REG(1)); | ||
51 | |||
52 | while ((old - readl(timer_base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS) | ||
53 | cpu_relax(); | ||
54 | } | ||
55 | |||
56 | static void sun5i_clkevt_time_stop(u8 timer) | ||
57 | { | ||
58 | u32 val = readl(timer_base + TIMER_CTL_REG(timer)); | ||
59 | writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); | ||
60 | |||
61 | sun5i_clkevt_sync(); | ||
62 | } | ||
63 | |||
64 | static void sun5i_clkevt_time_setup(u8 timer, u32 delay) | ||
65 | { | ||
66 | writel(delay, timer_base + TIMER_INTVAL_LO_REG(timer)); | ||
67 | } | ||
68 | |||
69 | static void sun5i_clkevt_time_start(u8 timer, bool periodic) | ||
70 | { | ||
71 | u32 val = readl(timer_base + TIMER_CTL_REG(timer)); | ||
72 | |||
73 | if (periodic) | ||
74 | val &= ~TIMER_CTL_ONESHOT; | ||
75 | else | ||
76 | val |= TIMER_CTL_ONESHOT; | ||
77 | |||
78 | writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, | ||
79 | timer_base + TIMER_CTL_REG(timer)); | ||
80 | } | ||
81 | |||
82 | static void sun5i_clkevt_mode(enum clock_event_mode mode, | ||
83 | struct clock_event_device *clk) | ||
84 | { | ||
85 | switch (mode) { | ||
86 | case CLOCK_EVT_MODE_PERIODIC: | ||
87 | sun5i_clkevt_time_stop(0); | ||
88 | sun5i_clkevt_time_setup(0, ticks_per_jiffy); | ||
89 | sun5i_clkevt_time_start(0, true); | ||
90 | break; | ||
91 | case CLOCK_EVT_MODE_ONESHOT: | ||
92 | sun5i_clkevt_time_stop(0); | ||
93 | sun5i_clkevt_time_start(0, false); | ||
94 | break; | ||
95 | case CLOCK_EVT_MODE_UNUSED: | ||
96 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
97 | default: | ||
98 | sun5i_clkevt_time_stop(0); | ||
99 | break; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static int sun5i_clkevt_next_event(unsigned long evt, | ||
104 | struct clock_event_device *unused) | ||
105 | { | ||
106 | sun5i_clkevt_time_stop(0); | ||
107 | sun5i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS); | ||
108 | sun5i_clkevt_time_start(0, false); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static struct clock_event_device sun5i_clockevent = { | ||
114 | .name = "sun5i_tick", | ||
115 | .rating = 340, | ||
116 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
117 | .set_mode = sun5i_clkevt_mode, | ||
118 | .set_next_event = sun5i_clkevt_next_event, | ||
119 | }; | ||
120 | |||
121 | |||
122 | static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) | ||
123 | { | ||
124 | struct clock_event_device *evt = (struct clock_event_device *)dev_id; | ||
125 | |||
126 | writel(0x1, timer_base + TIMER_IRQ_ST_REG); | ||
127 | evt->event_handler(evt); | ||
128 | |||
129 | return IRQ_HANDLED; | ||
130 | } | ||
131 | |||
132 | static struct irqaction sun5i_timer_irq = { | ||
133 | .name = "sun5i_timer0", | ||
134 | .flags = IRQF_TIMER | IRQF_IRQPOLL, | ||
135 | .handler = sun5i_timer_interrupt, | ||
136 | .dev_id = &sun5i_clockevent, | ||
137 | }; | ||
138 | |||
139 | static u64 sun5i_timer_sched_read(void) | ||
140 | { | ||
141 | return ~readl(timer_base + TIMER_CNTVAL_LO_REG(1)); | ||
142 | } | ||
143 | |||
144 | static void __init sun5i_timer_init(struct device_node *node) | ||
145 | { | ||
146 | unsigned long rate; | ||
147 | struct clk *clk; | ||
148 | int ret, irq; | ||
149 | u32 val; | ||
150 | |||
151 | timer_base = of_iomap(node, 0); | ||
152 | if (!timer_base) | ||
153 | panic("Can't map registers"); | ||
154 | |||
155 | irq = irq_of_parse_and_map(node, 0); | ||
156 | if (irq <= 0) | ||
157 | panic("Can't parse IRQ"); | ||
158 | |||
159 | clk = of_clk_get(node, 0); | ||
160 | if (IS_ERR(clk)) | ||
161 | panic("Can't get timer clock"); | ||
162 | clk_prepare_enable(clk); | ||
163 | rate = clk_get_rate(clk); | ||
164 | |||
165 | writel(~0, timer_base + TIMER_INTVAL_LO_REG(1)); | ||
166 | writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, | ||
167 | timer_base + TIMER_CTL_REG(1)); | ||
168 | |||
169 | sched_clock_register(sun5i_timer_sched_read, 32, rate); | ||
170 | clocksource_mmio_init(timer_base + TIMER_CNTVAL_LO_REG(1), node->name, | ||
171 | rate, 340, 32, clocksource_mmio_readl_down); | ||
172 | |||
173 | ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); | ||
174 | |||
175 | ret = setup_irq(irq, &sun5i_timer_irq); | ||
176 | if (ret) | ||
177 | pr_warn("failed to setup irq %d\n", irq); | ||
178 | |||
179 | /* Enable timer0 interrupt */ | ||
180 | val = readl(timer_base + TIMER_IRQ_EN_REG); | ||
181 | writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); | ||
182 | |||
183 | sun5i_clockevent.cpumask = cpu_possible_mask; | ||
184 | sun5i_clockevent.irq = irq; | ||
185 | |||
186 | clockevents_config_and_register(&sun5i_clockevent, rate, | ||
187 | TIMER_SYNC_TICKS, 0xffffffff); | ||
188 | } | ||
189 | CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", | ||
190 | sun5i_timer_init); | ||
191 | CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer", | ||
192 | sun5i_timer_init); | ||
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index ad3c0e83a779..1098ed3b9b89 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c | |||
@@ -124,7 +124,7 @@ static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) | |||
124 | 124 | ||
125 | static struct irqaction irq = { | 125 | static struct irqaction irq = { |
126 | .name = "vt8500_timer", | 126 | .name = "vt8500_timer", |
127 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 127 | .flags = IRQF_TIMER | IRQF_IRQPOLL, |
128 | .handler = vt8500_timer_interrupt, | 128 | .handler = vt8500_timer_interrupt, |
129 | .dev_id = &clockevent, | 129 | .dev_id = &clockevent, |
130 | }; | 130 | }; |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index b53d0de17e15..98e14ee4833c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -1,7 +1,7 @@ | |||
1 | #include "amd64_edac.h" | 1 | #include "amd64_edac.h" |
2 | #include <asm/amd_nb.h> | 2 | #include <asm/amd_nb.h> |
3 | 3 | ||
4 | static struct edac_pci_ctl_info *amd64_ctl_pci; | 4 | static struct edac_pci_ctl_info *pci_ctl; |
5 | 5 | ||
6 | static int report_gart_errors; | 6 | static int report_gart_errors; |
7 | module_param(report_gart_errors, int, 0644); | 7 | module_param(report_gart_errors, int, 0644); |
@@ -162,7 +162,7 @@ static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, | |||
162 | * scan the scrub rate mapping table for a close or matching bandwidth value to | 162 | * scan the scrub rate mapping table for a close or matching bandwidth value to |
163 | * issue. If requested is too big, then use last maximum value found. | 163 | * issue. If requested is too big, then use last maximum value found. |
164 | */ | 164 | */ |
165 | static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) | 165 | static int __set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) |
166 | { | 166 | { |
167 | u32 scrubval; | 167 | u32 scrubval; |
168 | int i; | 168 | int i; |
@@ -198,7 +198,7 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) | |||
198 | return 0; | 198 | return 0; |
199 | } | 199 | } |
200 | 200 | ||
201 | static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) | 201 | static int set_scrub_rate(struct mem_ctl_info *mci, u32 bw) |
202 | { | 202 | { |
203 | struct amd64_pvt *pvt = mci->pvt_info; | 203 | struct amd64_pvt *pvt = mci->pvt_info; |
204 | u32 min_scrubrate = 0x5; | 204 | u32 min_scrubrate = 0x5; |
@@ -210,10 +210,10 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) | |||
210 | if (pvt->fam == 0x15 && pvt->model < 0x10) | 210 | if (pvt->fam == 0x15 && pvt->model < 0x10) |
211 | f15h_select_dct(pvt, 0); | 211 | f15h_select_dct(pvt, 0); |
212 | 212 | ||
213 | return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate); | 213 | return __set_scrub_rate(pvt->F3, bw, min_scrubrate); |
214 | } | 214 | } |
215 | 215 | ||
216 | static int amd64_get_scrub_rate(struct mem_ctl_info *mci) | 216 | static int get_scrub_rate(struct mem_ctl_info *mci) |
217 | { | 217 | { |
218 | struct amd64_pvt *pvt = mci->pvt_info; | 218 | struct amd64_pvt *pvt = mci->pvt_info; |
219 | u32 scrubval = 0; | 219 | u32 scrubval = 0; |
@@ -240,8 +240,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci) | |||
240 | * returns true if the SysAddr given by sys_addr matches the | 240 | * returns true if the SysAddr given by sys_addr matches the |
241 | * DRAM base/limit associated with node_id | 241 | * DRAM base/limit associated with node_id |
242 | */ | 242 | */ |
243 | static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, | 243 | static bool base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, u8 nid) |
244 | u8 nid) | ||
245 | { | 244 | { |
246 | u64 addr; | 245 | u64 addr; |
247 | 246 | ||
@@ -285,7 +284,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
285 | 284 | ||
286 | if (intlv_en == 0) { | 285 | if (intlv_en == 0) { |
287 | for (node_id = 0; node_id < DRAM_RANGES; node_id++) { | 286 | for (node_id = 0; node_id < DRAM_RANGES; node_id++) { |
288 | if (amd64_base_limit_match(pvt, sys_addr, node_id)) | 287 | if (base_limit_match(pvt, sys_addr, node_id)) |
289 | goto found; | 288 | goto found; |
290 | } | 289 | } |
291 | goto err_no_match; | 290 | goto err_no_match; |
@@ -309,7 +308,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
309 | } | 308 | } |
310 | 309 | ||
311 | /* sanity test for sys_addr */ | 310 | /* sanity test for sys_addr */ |
312 | if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { | 311 | if (unlikely(!base_limit_match(pvt, sys_addr, node_id))) { |
313 | amd64_warn("%s: sys_addr 0x%llx falls outside base/limit address" | 312 | amd64_warn("%s: sys_addr 0x%llx falls outside base/limit address" |
314 | "range for node %d with node interleaving enabled.\n", | 313 | "range for node %d with node interleaving enabled.\n", |
315 | __func__, sys_addr, node_id); | 314 | __func__, sys_addr, node_id); |
@@ -660,7 +659,7 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); | |||
660 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs | 659 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs |
661 | * are ECC capable. | 660 | * are ECC capable. |
662 | */ | 661 | */ |
663 | static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt) | 662 | static unsigned long determine_edac_cap(struct amd64_pvt *pvt) |
664 | { | 663 | { |
665 | u8 bit; | 664 | u8 bit; |
666 | unsigned long edac_cap = EDAC_FLAG_NONE; | 665 | unsigned long edac_cap = EDAC_FLAG_NONE; |
@@ -675,9 +674,9 @@ static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt) | |||
675 | return edac_cap; | 674 | return edac_cap; |
676 | } | 675 | } |
677 | 676 | ||
678 | static void amd64_debug_display_dimm_sizes(struct amd64_pvt *, u8); | 677 | static void debug_display_dimm_sizes(struct amd64_pvt *, u8); |
679 | 678 | ||
680 | static void amd64_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) | 679 | static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) |
681 | { | 680 | { |
682 | edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); | 681 | edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); |
683 | 682 | ||
@@ -711,7 +710,7 @@ static void dump_misc_regs(struct amd64_pvt *pvt) | |||
711 | (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no", | 710 | (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no", |
712 | (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no"); | 711 | (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no"); |
713 | 712 | ||
714 | amd64_dump_dramcfg_low(pvt, pvt->dclr0, 0); | 713 | debug_dump_dramcfg_low(pvt, pvt->dclr0, 0); |
715 | 714 | ||
716 | edac_dbg(1, "F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare); | 715 | edac_dbg(1, "F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare); |
717 | 716 | ||
@@ -722,19 +721,19 @@ static void dump_misc_regs(struct amd64_pvt *pvt) | |||
722 | 721 | ||
723 | edac_dbg(1, " DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); | 722 | edac_dbg(1, " DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); |
724 | 723 | ||
725 | amd64_debug_display_dimm_sizes(pvt, 0); | 724 | debug_display_dimm_sizes(pvt, 0); |
726 | 725 | ||
727 | /* everything below this point is Fam10h and above */ | 726 | /* everything below this point is Fam10h and above */ |
728 | if (pvt->fam == 0xf) | 727 | if (pvt->fam == 0xf) |
729 | return; | 728 | return; |
730 | 729 | ||
731 | amd64_debug_display_dimm_sizes(pvt, 1); | 730 | debug_display_dimm_sizes(pvt, 1); |
732 | 731 | ||
733 | amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4")); | 732 | amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4")); |
734 | 733 | ||
735 | /* Only if NOT ganged does dclr1 have valid info */ | 734 | /* Only if NOT ganged does dclr1 have valid info */ |
736 | if (!dct_ganging_enabled(pvt)) | 735 | if (!dct_ganging_enabled(pvt)) |
737 | amd64_dump_dramcfg_low(pvt, pvt->dclr1, 1); | 736 | debug_dump_dramcfg_low(pvt, pvt->dclr1, 1); |
738 | } | 737 | } |
739 | 738 | ||
740 | /* | 739 | /* |
@@ -800,7 +799,7 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) | |||
800 | } | 799 | } |
801 | } | 800 | } |
802 | 801 | ||
803 | static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs) | 802 | static enum mem_type determine_memory_type(struct amd64_pvt *pvt, int cs) |
804 | { | 803 | { |
805 | enum mem_type type; | 804 | enum mem_type type; |
806 | 805 | ||
@@ -1578,7 +1577,7 @@ static int f15_m30h_match_to_this_node(struct amd64_pvt *pvt, unsigned range, | |||
1578 | num_dcts_intlv, dct_sel); | 1577 | num_dcts_intlv, dct_sel); |
1579 | 1578 | ||
1580 | /* Verify we stay within the MAX number of channels allowed */ | 1579 | /* Verify we stay within the MAX number of channels allowed */ |
1581 | if (channel > 4 || channel < 0) | 1580 | if (channel > 3) |
1582 | return -EINVAL; | 1581 | return -EINVAL; |
1583 | 1582 | ||
1584 | leg_mmio_hole = (u8) (dct_cont_base_reg >> 1 & BIT(0)); | 1583 | leg_mmio_hole = (u8) (dct_cont_base_reg >> 1 & BIT(0)); |
@@ -1702,7 +1701,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, | |||
1702 | * debug routine to display the memory sizes of all logical DIMMs and its | 1701 | * debug routine to display the memory sizes of all logical DIMMs and its |
1703 | * CSROWs | 1702 | * CSROWs |
1704 | */ | 1703 | */ |
1705 | static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) | 1704 | static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) |
1706 | { | 1705 | { |
1707 | int dimm, size0, size1; | 1706 | int dimm, size0, size1; |
1708 | u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases; | 1707 | u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases; |
@@ -1744,7 +1743,7 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) | |||
1744 | } | 1743 | } |
1745 | } | 1744 | } |
1746 | 1745 | ||
1747 | static struct amd64_family_type amd64_family_types[] = { | 1746 | static struct amd64_family_type family_types[] = { |
1748 | [K8_CPUS] = { | 1747 | [K8_CPUS] = { |
1749 | .ctl_name = "K8", | 1748 | .ctl_name = "K8", |
1750 | .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, | 1749 | .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, |
@@ -2005,9 +2004,9 @@ static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err, | |||
2005 | string, ""); | 2004 | string, ""); |
2006 | } | 2005 | } |
2007 | 2006 | ||
2008 | static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | 2007 | static inline void decode_bus_error(int node_id, struct mce *m) |
2009 | struct mce *m) | ||
2010 | { | 2008 | { |
2009 | struct mem_ctl_info *mci = mcis[node_id]; | ||
2011 | struct amd64_pvt *pvt = mci->pvt_info; | 2010 | struct amd64_pvt *pvt = mci->pvt_info; |
2012 | u8 ecc_type = (m->status >> 45) & 0x3; | 2011 | u8 ecc_type = (m->status >> 45) & 0x3; |
2013 | u8 xec = XEC(m->status, 0x1f); | 2012 | u8 xec = XEC(m->status, 0x1f); |
@@ -2035,11 +2034,6 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | |||
2035 | __log_bus_error(mci, &err, ecc_type); | 2034 | __log_bus_error(mci, &err, ecc_type); |
2036 | } | 2035 | } |
2037 | 2036 | ||
2038 | void amd64_decode_bus_error(int node_id, struct mce *m) | ||
2039 | { | ||
2040 | __amd64_decode_bus_error(mcis[node_id], m); | ||
2041 | } | ||
2042 | |||
2043 | /* | 2037 | /* |
2044 | * Use pvt->F2 which contains the F2 CPU PCI device to get the related | 2038 | * Use pvt->F2 which contains the F2 CPU PCI device to get the related |
2045 | * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error. | 2039 | * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error. |
@@ -2196,7 +2190,7 @@ static void read_mc_regs(struct amd64_pvt *pvt) | |||
2196 | * encompasses | 2190 | * encompasses |
2197 | * | 2191 | * |
2198 | */ | 2192 | */ |
2199 | static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) | 2193 | static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) |
2200 | { | 2194 | { |
2201 | u32 cs_mode, nr_pages; | 2195 | u32 cs_mode, nr_pages; |
2202 | u32 dbam = dct ? pvt->dbam1 : pvt->dbam0; | 2196 | u32 dbam = dct ? pvt->dbam1 : pvt->dbam0; |
@@ -2263,19 +2257,19 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
2263 | pvt->mc_node_id, i); | 2257 | pvt->mc_node_id, i); |
2264 | 2258 | ||
2265 | if (row_dct0) { | 2259 | if (row_dct0) { |
2266 | nr_pages = amd64_csrow_nr_pages(pvt, 0, i); | 2260 | nr_pages = get_csrow_nr_pages(pvt, 0, i); |
2267 | csrow->channels[0]->dimm->nr_pages = nr_pages; | 2261 | csrow->channels[0]->dimm->nr_pages = nr_pages; |
2268 | } | 2262 | } |
2269 | 2263 | ||
2270 | /* K8 has only one DCT */ | 2264 | /* K8 has only one DCT */ |
2271 | if (pvt->fam != 0xf && row_dct1) { | 2265 | if (pvt->fam != 0xf && row_dct1) { |
2272 | int row_dct1_pages = amd64_csrow_nr_pages(pvt, 1, i); | 2266 | int row_dct1_pages = get_csrow_nr_pages(pvt, 1, i); |
2273 | 2267 | ||
2274 | csrow->channels[1]->dimm->nr_pages = row_dct1_pages; | 2268 | csrow->channels[1]->dimm->nr_pages = row_dct1_pages; |
2275 | nr_pages += row_dct1_pages; | 2269 | nr_pages += row_dct1_pages; |
2276 | } | 2270 | } |
2277 | 2271 | ||
2278 | mtype = amd64_determine_memory_type(pvt, i); | 2272 | mtype = determine_memory_type(pvt, i); |
2279 | 2273 | ||
2280 | edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages); | 2274 | edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages); |
2281 | 2275 | ||
@@ -2309,7 +2303,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, u16 nid) | |||
2309 | } | 2303 | } |
2310 | 2304 | ||
2311 | /* check MCG_CTL on all the cpus on this node */ | 2305 | /* check MCG_CTL on all the cpus on this node */ |
2312 | static bool amd64_nb_mce_bank_enabled_on_node(u16 nid) | 2306 | static bool nb_mce_bank_enabled_on_node(u16 nid) |
2313 | { | 2307 | { |
2314 | cpumask_var_t mask; | 2308 | cpumask_var_t mask; |
2315 | int cpu, nbe; | 2309 | int cpu, nbe; |
@@ -2482,7 +2476,7 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid) | |||
2482 | ecc_en = !!(value & NBCFG_ECC_ENABLE); | 2476 | ecc_en = !!(value & NBCFG_ECC_ENABLE); |
2483 | amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled")); | 2477 | amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled")); |
2484 | 2478 | ||
2485 | nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid); | 2479 | nb_mce_en = nb_mce_bank_enabled_on_node(nid); |
2486 | if (!nb_mce_en) | 2480 | if (!nb_mce_en) |
2487 | amd64_notice("NB MCE bank disabled, set MSR " | 2481 | amd64_notice("NB MCE bank disabled, set MSR " |
2488 | "0x%08x[4] on node %d to enable.\n", | 2482 | "0x%08x[4] on node %d to enable.\n", |
@@ -2537,7 +2531,7 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci, | |||
2537 | if (pvt->nbcap & NBCAP_CHIPKILL) | 2531 | if (pvt->nbcap & NBCAP_CHIPKILL) |
2538 | mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED; | 2532 | mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED; |
2539 | 2533 | ||
2540 | mci->edac_cap = amd64_determine_edac_cap(pvt); | 2534 | mci->edac_cap = determine_edac_cap(pvt); |
2541 | mci->mod_name = EDAC_MOD_STR; | 2535 | mci->mod_name = EDAC_MOD_STR; |
2542 | mci->mod_ver = EDAC_AMD64_VERSION; | 2536 | mci->mod_ver = EDAC_AMD64_VERSION; |
2543 | mci->ctl_name = fam->ctl_name; | 2537 | mci->ctl_name = fam->ctl_name; |
@@ -2545,14 +2539,14 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci, | |||
2545 | mci->ctl_page_to_phys = NULL; | 2539 | mci->ctl_page_to_phys = NULL; |
2546 | 2540 | ||
2547 | /* memory scrubber interface */ | 2541 | /* memory scrubber interface */ |
2548 | mci->set_sdram_scrub_rate = amd64_set_scrub_rate; | 2542 | mci->set_sdram_scrub_rate = set_scrub_rate; |
2549 | mci->get_sdram_scrub_rate = amd64_get_scrub_rate; | 2543 | mci->get_sdram_scrub_rate = get_scrub_rate; |
2550 | } | 2544 | } |
2551 | 2545 | ||
2552 | /* | 2546 | /* |
2553 | * returns a pointer to the family descriptor on success, NULL otherwise. | 2547 | * returns a pointer to the family descriptor on success, NULL otherwise. |
2554 | */ | 2548 | */ |
2555 | static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) | 2549 | static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) |
2556 | { | 2550 | { |
2557 | struct amd64_family_type *fam_type = NULL; | 2551 | struct amd64_family_type *fam_type = NULL; |
2558 | 2552 | ||
@@ -2563,29 +2557,29 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) | |||
2563 | 2557 | ||
2564 | switch (pvt->fam) { | 2558 | switch (pvt->fam) { |
2565 | case 0xf: | 2559 | case 0xf: |
2566 | fam_type = &amd64_family_types[K8_CPUS]; | 2560 | fam_type = &family_types[K8_CPUS]; |
2567 | pvt->ops = &amd64_family_types[K8_CPUS].ops; | 2561 | pvt->ops = &family_types[K8_CPUS].ops; |
2568 | break; | 2562 | break; |
2569 | 2563 | ||
2570 | case 0x10: | 2564 | case 0x10: |
2571 | fam_type = &amd64_family_types[F10_CPUS]; | 2565 | fam_type = &family_types[F10_CPUS]; |
2572 | pvt->ops = &amd64_family_types[F10_CPUS].ops; | 2566 | pvt->ops = &family_types[F10_CPUS].ops; |
2573 | break; | 2567 | break; |
2574 | 2568 | ||
2575 | case 0x15: | 2569 | case 0x15: |
2576 | if (pvt->model == 0x30) { | 2570 | if (pvt->model == 0x30) { |
2577 | fam_type = &amd64_family_types[F15_M30H_CPUS]; | 2571 | fam_type = &family_types[F15_M30H_CPUS]; |
2578 | pvt->ops = &amd64_family_types[F15_M30H_CPUS].ops; | 2572 | pvt->ops = &family_types[F15_M30H_CPUS].ops; |
2579 | break; | 2573 | break; |
2580 | } | 2574 | } |
2581 | 2575 | ||
2582 | fam_type = &amd64_family_types[F15_CPUS]; | 2576 | fam_type = &family_types[F15_CPUS]; |
2583 | pvt->ops = &amd64_family_types[F15_CPUS].ops; | 2577 | pvt->ops = &family_types[F15_CPUS].ops; |
2584 | break; | 2578 | break; |
2585 | 2579 | ||
2586 | case 0x16: | 2580 | case 0x16: |
2587 | fam_type = &amd64_family_types[F16_CPUS]; | 2581 | fam_type = &family_types[F16_CPUS]; |
2588 | pvt->ops = &amd64_family_types[F16_CPUS].ops; | 2582 | pvt->ops = &family_types[F16_CPUS].ops; |
2589 | break; | 2583 | break; |
2590 | 2584 | ||
2591 | default: | 2585 | default: |
@@ -2601,7 +2595,7 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) | |||
2601 | return fam_type; | 2595 | return fam_type; |
2602 | } | 2596 | } |
2603 | 2597 | ||
2604 | static int amd64_init_one_instance(struct pci_dev *F2) | 2598 | static int init_one_instance(struct pci_dev *F2) |
2605 | { | 2599 | { |
2606 | struct amd64_pvt *pvt = NULL; | 2600 | struct amd64_pvt *pvt = NULL; |
2607 | struct amd64_family_type *fam_type = NULL; | 2601 | struct amd64_family_type *fam_type = NULL; |
@@ -2619,7 +2613,7 @@ static int amd64_init_one_instance(struct pci_dev *F2) | |||
2619 | pvt->F2 = F2; | 2613 | pvt->F2 = F2; |
2620 | 2614 | ||
2621 | ret = -EINVAL; | 2615 | ret = -EINVAL; |
2622 | fam_type = amd64_per_family_init(pvt); | 2616 | fam_type = per_family_init(pvt); |
2623 | if (!fam_type) | 2617 | if (!fam_type) |
2624 | goto err_free; | 2618 | goto err_free; |
2625 | 2619 | ||
@@ -2680,7 +2674,7 @@ static int amd64_init_one_instance(struct pci_dev *F2) | |||
2680 | if (report_gart_errors) | 2674 | if (report_gart_errors) |
2681 | amd_report_gart_errors(true); | 2675 | amd_report_gart_errors(true); |
2682 | 2676 | ||
2683 | amd_register_ecc_decoder(amd64_decode_bus_error); | 2677 | amd_register_ecc_decoder(decode_bus_error); |
2684 | 2678 | ||
2685 | mcis[nid] = mci; | 2679 | mcis[nid] = mci; |
2686 | 2680 | ||
@@ -2703,8 +2697,8 @@ err_ret: | |||
2703 | return ret; | 2697 | return ret; |
2704 | } | 2698 | } |
2705 | 2699 | ||
2706 | static int amd64_probe_one_instance(struct pci_dev *pdev, | 2700 | static int probe_one_instance(struct pci_dev *pdev, |
2707 | const struct pci_device_id *mc_type) | 2701 | const struct pci_device_id *mc_type) |
2708 | { | 2702 | { |
2709 | u16 nid = amd_get_node_id(pdev); | 2703 | u16 nid = amd_get_node_id(pdev); |
2710 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | 2704 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; |
@@ -2736,7 +2730,7 @@ static int amd64_probe_one_instance(struct pci_dev *pdev, | |||
2736 | goto err_enable; | 2730 | goto err_enable; |
2737 | } | 2731 | } |
2738 | 2732 | ||
2739 | ret = amd64_init_one_instance(pdev); | 2733 | ret = init_one_instance(pdev); |
2740 | if (ret < 0) { | 2734 | if (ret < 0) { |
2741 | amd64_err("Error probing instance: %d\n", nid); | 2735 | amd64_err("Error probing instance: %d\n", nid); |
2742 | restore_ecc_error_reporting(s, nid, F3); | 2736 | restore_ecc_error_reporting(s, nid, F3); |
@@ -2752,7 +2746,7 @@ err_out: | |||
2752 | return ret; | 2746 | return ret; |
2753 | } | 2747 | } |
2754 | 2748 | ||
2755 | static void amd64_remove_one_instance(struct pci_dev *pdev) | 2749 | static void remove_one_instance(struct pci_dev *pdev) |
2756 | { | 2750 | { |
2757 | struct mem_ctl_info *mci; | 2751 | struct mem_ctl_info *mci; |
2758 | struct amd64_pvt *pvt; | 2752 | struct amd64_pvt *pvt; |
@@ -2777,7 +2771,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev) | |||
2777 | 2771 | ||
2778 | /* unregister from EDAC MCE */ | 2772 | /* unregister from EDAC MCE */ |
2779 | amd_report_gart_errors(false); | 2773 | amd_report_gart_errors(false); |
2780 | amd_unregister_ecc_decoder(amd64_decode_bus_error); | 2774 | amd_unregister_ecc_decoder(decode_bus_error); |
2781 | 2775 | ||
2782 | kfree(ecc_stngs[nid]); | 2776 | kfree(ecc_stngs[nid]); |
2783 | ecc_stngs[nid] = NULL; | 2777 | ecc_stngs[nid] = NULL; |
@@ -2795,7 +2789,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev) | |||
2795 | * PCI core identifies what devices are on a system during boot, and then | 2789 | * PCI core identifies what devices are on a system during boot, and then |
2796 | * inquiry this table to see if this driver is for a given device found. | 2790 | * inquiry this table to see if this driver is for a given device found. |
2797 | */ | 2791 | */ |
2798 | static DEFINE_PCI_DEVICE_TABLE(amd64_pci_table) = { | 2792 | static const struct pci_device_id amd64_pci_table[] = { |
2799 | { | 2793 | { |
2800 | .vendor = PCI_VENDOR_ID_AMD, | 2794 | .vendor = PCI_VENDOR_ID_AMD, |
2801 | .device = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, | 2795 | .device = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, |
@@ -2843,8 +2837,8 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table); | |||
2843 | 2837 | ||
2844 | static struct pci_driver amd64_pci_driver = { | 2838 | static struct pci_driver amd64_pci_driver = { |
2845 | .name = EDAC_MOD_STR, | 2839 | .name = EDAC_MOD_STR, |
2846 | .probe = amd64_probe_one_instance, | 2840 | .probe = probe_one_instance, |
2847 | .remove = amd64_remove_one_instance, | 2841 | .remove = remove_one_instance, |
2848 | .id_table = amd64_pci_table, | 2842 | .id_table = amd64_pci_table, |
2849 | }; | 2843 | }; |
2850 | 2844 | ||
@@ -2853,23 +2847,18 @@ static void setup_pci_device(void) | |||
2853 | struct mem_ctl_info *mci; | 2847 | struct mem_ctl_info *mci; |
2854 | struct amd64_pvt *pvt; | 2848 | struct amd64_pvt *pvt; |
2855 | 2849 | ||
2856 | if (amd64_ctl_pci) | 2850 | if (pci_ctl) |
2857 | return; | 2851 | return; |
2858 | 2852 | ||
2859 | mci = mcis[0]; | 2853 | mci = mcis[0]; |
2860 | if (mci) { | 2854 | if (!mci) |
2861 | 2855 | return; | |
2862 | pvt = mci->pvt_info; | ||
2863 | amd64_ctl_pci = | ||
2864 | edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR); | ||
2865 | |||
2866 | if (!amd64_ctl_pci) { | ||
2867 | pr_warning("%s(): Unable to create PCI control\n", | ||
2868 | __func__); | ||
2869 | 2856 | ||
2870 | pr_warning("%s(): PCI error report via EDAC not set\n", | 2857 | pvt = mci->pvt_info; |
2871 | __func__); | 2858 | pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR); |
2872 | } | 2859 | if (!pci_ctl) { |
2860 | pr_warn("%s(): Unable to create PCI control\n", __func__); | ||
2861 | pr_warn("%s(): PCI error report via EDAC not set\n", __func__); | ||
2873 | } | 2862 | } |
2874 | } | 2863 | } |
2875 | 2864 | ||
@@ -2925,8 +2914,8 @@ err_ret: | |||
2925 | 2914 | ||
2926 | static void __exit amd64_edac_exit(void) | 2915 | static void __exit amd64_edac_exit(void) |
2927 | { | 2916 | { |
2928 | if (amd64_ctl_pci) | 2917 | if (pci_ctl) |
2929 | edac_pci_release_generic_ctl(amd64_ctl_pci); | 2918 | edac_pci_release_generic_ctl(pci_ctl); |
2930 | 2919 | ||
2931 | pci_unregister_driver(&amd64_pci_driver); | 2920 | pci_unregister_driver(&amd64_pci_driver); |
2932 | 2921 | ||
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 96e3ee3460a5..3a501b530e11 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c | |||
@@ -333,7 +333,7 @@ static void amd76x_remove_one(struct pci_dev *pdev) | |||
333 | edac_mc_free(mci); | 333 | edac_mc_free(mci); |
334 | } | 334 | } |
335 | 335 | ||
336 | static DEFINE_PCI_DEVICE_TABLE(amd76x_pci_tbl) = { | 336 | static const struct pci_device_id amd76x_pci_tbl[] = { |
337 | { | 337 | { |
338 | PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 338 | PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
339 | AMD762}, | 339 | AMD762}, |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 644fec54681f..92d54fa65f93 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
@@ -1182,9 +1182,11 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx, | |||
1182 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, | 1182 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, |
1183 | pvt->dev_info->err_dev, pvt->bridge_ck); | 1183 | pvt->dev_info->err_dev, pvt->bridge_ck); |
1184 | 1184 | ||
1185 | if (pvt->bridge_ck == NULL) | 1185 | if (pvt->bridge_ck == NULL) { |
1186 | pvt->bridge_ck = pci_scan_single_device(pdev->bus, | 1186 | pvt->bridge_ck = pci_scan_single_device(pdev->bus, |
1187 | PCI_DEVFN(0, 1)); | 1187 | PCI_DEVFN(0, 1)); |
1188 | pci_dev_get(pvt->bridge_ck); | ||
1189 | } | ||
1188 | 1190 | ||
1189 | if (pvt->bridge_ck == NULL) { | 1191 | if (pvt->bridge_ck == NULL) { |
1190 | e752x_printk(KERN_ERR, "error reporting device not found:" | 1192 | e752x_printk(KERN_ERR, "error reporting device not found:" |
@@ -1421,7 +1423,7 @@ static void e752x_remove_one(struct pci_dev *pdev) | |||
1421 | edac_mc_free(mci); | 1423 | edac_mc_free(mci); |
1422 | } | 1424 | } |
1423 | 1425 | ||
1424 | static DEFINE_PCI_DEVICE_TABLE(e752x_pci_tbl) = { | 1426 | static const struct pci_device_id e752x_pci_tbl[] = { |
1425 | { | 1427 | { |
1426 | PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 1428 | PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
1427 | E7520}, | 1429 | E7520}, |
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 1c4056a50383..3cda79bc8b00 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c | |||
@@ -555,7 +555,7 @@ static void e7xxx_remove_one(struct pci_dev *pdev) | |||
555 | edac_mc_free(mci); | 555 | edac_mc_free(mci); |
556 | } | 556 | } |
557 | 557 | ||
558 | static DEFINE_PCI_DEVICE_TABLE(e7xxx_pci_tbl) = { | 558 | static const struct pci_device_id e7xxx_pci_tbl[] = { |
559 | { | 559 | { |
560 | PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 560 | PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
561 | E7205}, | 561 | E7205}, |
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index 102674346035..592af5f0cf39 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c | |||
@@ -437,6 +437,9 @@ void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev) | |||
437 | { | 437 | { |
438 | int status; | 438 | int status; |
439 | 439 | ||
440 | if (!edac_dev->edac_check) | ||
441 | return; | ||
442 | |||
440 | status = cancel_delayed_work(&edac_dev->work); | 443 | status = cancel_delayed_work(&edac_dev->work); |
441 | if (status == 0) { | 444 | if (status == 0) { |
442 | /* workq instance might be running, wait for it */ | 445 | /* workq instance might be running, wait for it */ |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 9f7e0e609516..51c0362acf5c 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -914,7 +914,7 @@ void __exit edac_debugfs_exit(void) | |||
914 | debugfs_remove(edac_debugfs); | 914 | debugfs_remove(edac_debugfs); |
915 | } | 915 | } |
916 | 916 | ||
917 | int edac_create_debug_nodes(struct mem_ctl_info *mci) | 917 | static int edac_create_debug_nodes(struct mem_ctl_info *mci) |
918 | { | 918 | { |
919 | struct dentry *d, *parent; | 919 | struct dentry *d, *parent; |
920 | char name[80]; | 920 | char name[80]; |
diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c index 351945fa2ecd..9d9e18aefaaa 100644 --- a/drivers/edac/edac_stub.c +++ b/drivers/edac/edac_stub.c | |||
@@ -29,6 +29,25 @@ EXPORT_SYMBOL_GPL(edac_err_assert); | |||
29 | 29 | ||
30 | static atomic_t edac_subsys_valid = ATOMIC_INIT(0); | 30 | static atomic_t edac_subsys_valid = ATOMIC_INIT(0); |
31 | 31 | ||
32 | int edac_report_status = EDAC_REPORTING_ENABLED; | ||
33 | EXPORT_SYMBOL_GPL(edac_report_status); | ||
34 | |||
35 | static int __init edac_report_setup(char *str) | ||
36 | { | ||
37 | if (!str) | ||
38 | return -EINVAL; | ||
39 | |||
40 | if (!strncmp(str, "on", 2)) | ||
41 | set_edac_report_status(EDAC_REPORTING_ENABLED); | ||
42 | else if (!strncmp(str, "off", 3)) | ||
43 | set_edac_report_status(EDAC_REPORTING_DISABLED); | ||
44 | else if (!strncmp(str, "force", 5)) | ||
45 | set_edac_report_status(EDAC_REPORTING_FORCE); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | __setup("edac_report=", edac_report_setup); | ||
50 | |||
32 | /* | 51 | /* |
33 | * called to determine if there is an EDAC driver interested in | 52 | * called to determine if there is an EDAC driver interested in |
34 | * knowing an event (such as NMI) occurred | 53 | * knowing an event (such as NMI) occurred |
diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 694efcbf19c0..cd28b968e5c7 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c | |||
@@ -487,7 +487,7 @@ static void i3000_remove_one(struct pci_dev *pdev) | |||
487 | edac_mc_free(mci); | 487 | edac_mc_free(mci); |
488 | } | 488 | } |
489 | 489 | ||
490 | static DEFINE_PCI_DEVICE_TABLE(i3000_pci_tbl) = { | 490 | static const struct pci_device_id i3000_pci_tbl[] = { |
491 | { | 491 | { |
492 | PCI_VEND_DEV(INTEL, 3000_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 492 | PCI_VEND_DEV(INTEL, 3000_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
493 | I3000}, | 493 | I3000}, |
diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index be10a74b16ea..fa1326e5a4b0 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c | |||
@@ -466,7 +466,7 @@ static void i3200_remove_one(struct pci_dev *pdev) | |||
466 | edac_mc_free(mci); | 466 | edac_mc_free(mci); |
467 | } | 467 | } |
468 | 468 | ||
469 | static DEFINE_PCI_DEVICE_TABLE(i3200_pci_tbl) = { | 469 | static const struct pci_device_id i3200_pci_tbl[] = { |
470 | { | 470 | { |
471 | PCI_VEND_DEV(INTEL, 3200_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 471 | PCI_VEND_DEV(INTEL, 3200_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
472 | I3200}, | 472 | I3200}, |
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 63b2194e8c20..72e07e3cf718 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c | |||
@@ -1530,7 +1530,7 @@ static void i5000_remove_one(struct pci_dev *pdev) | |||
1530 | * | 1530 | * |
1531 | * The "E500P" device is the first device supported. | 1531 | * The "E500P" device is the first device supported. |
1532 | */ | 1532 | */ |
1533 | static DEFINE_PCI_DEVICE_TABLE(i5000_pci_tbl) = { | 1533 | static const struct pci_device_id i5000_pci_tbl[] = { |
1534 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I5000_DEV16), | 1534 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I5000_DEV16), |
1535 | .driver_data = I5000P}, | 1535 | .driver_data = I5000P}, |
1536 | 1536 | ||
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 157b934e8ce3..36a38ee94fa8 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c | |||
@@ -1213,7 +1213,7 @@ static void i5100_remove_one(struct pci_dev *pdev) | |||
1213 | edac_mc_free(mci); | 1213 | edac_mc_free(mci); |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | static DEFINE_PCI_DEVICE_TABLE(i5100_pci_tbl) = { | 1216 | static const struct pci_device_id i5100_pci_tbl[] = { |
1217 | /* Device 16, Function 0, Channel 0 Memory Map, Error Flag/Mask, ... */ | 1217 | /* Device 16, Function 0, Channel 0 Memory Map, Error Flag/Mask, ... */ |
1218 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_16) }, | 1218 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_16) }, |
1219 | { 0, } | 1219 | { 0, } |
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 0a05bbceb08f..e080cbfa8fc9 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c | |||
@@ -1416,7 +1416,7 @@ static void i5400_remove_one(struct pci_dev *pdev) | |||
1416 | * | 1416 | * |
1417 | * The "E500P" device is the first device supported. | 1417 | * The "E500P" device is the first device supported. |
1418 | */ | 1418 | */ |
1419 | static DEFINE_PCI_DEVICE_TABLE(i5400_pci_tbl) = { | 1419 | static const struct pci_device_id i5400_pci_tbl[] = { |
1420 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR)}, | 1420 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR)}, |
1421 | {0,} /* 0 terminated list. */ | 1421 | {0,} /* 0 terminated list. */ |
1422 | }; | 1422 | }; |
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 9004c64b169e..d63f4798f7d0 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c | |||
@@ -1160,7 +1160,7 @@ static void i7300_remove_one(struct pci_dev *pdev) | |||
1160 | * | 1160 | * |
1161 | * Has only 8086:360c PCI ID | 1161 | * Has only 8086:360c PCI ID |
1162 | */ | 1162 | */ |
1163 | static DEFINE_PCI_DEVICE_TABLE(i7300_pci_tbl) = { | 1163 | static const struct pci_device_id i7300_pci_tbl[] = { |
1164 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)}, | 1164 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)}, |
1165 | {0,} /* 0 terminated list. */ | 1165 | {0,} /* 0 terminated list. */ |
1166 | }; | 1166 | }; |
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 80a963d64e58..87533ca7752e 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -394,7 +394,7 @@ static const struct pci_id_table pci_dev_table[] = { | |||
394 | /* | 394 | /* |
395 | * pci_device_id table for which devices we are looking for | 395 | * pci_device_id table for which devices we are looking for |
396 | */ | 396 | */ |
397 | static DEFINE_PCI_DEVICE_TABLE(i7core_pci_tbl) = { | 397 | static const struct pci_device_id i7core_pci_tbl[] = { |
398 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)}, | 398 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)}, |
399 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)}, | 399 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)}, |
400 | {0,} /* 0 terminated list. */ | 400 | {0,} /* 0 terminated list. */ |
diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 57fdb77903ba..d730e276d1a8 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c | |||
@@ -386,7 +386,7 @@ static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) | |||
386 | 386 | ||
387 | EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_remove_one); | 387 | EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_remove_one); |
388 | 388 | ||
389 | static DEFINE_PCI_DEVICE_TABLE(i82443bxgx_pci_tbl) = { | 389 | static const struct pci_device_id i82443bxgx_pci_tbl[] = { |
390 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0)}, | 390 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0)}, |
391 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2)}, | 391 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2)}, |
392 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0)}, | 392 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0)}, |
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 3e3e431c8301..3382f6344e42 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c | |||
@@ -288,7 +288,7 @@ static void i82860_remove_one(struct pci_dev *pdev) | |||
288 | edac_mc_free(mci); | 288 | edac_mc_free(mci); |
289 | } | 289 | } |
290 | 290 | ||
291 | static DEFINE_PCI_DEVICE_TABLE(i82860_pci_tbl) = { | 291 | static const struct pci_device_id i82860_pci_tbl[] = { |
292 | { | 292 | { |
293 | PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 293 | PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
294 | I82860}, | 294 | I82860}, |
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 2f8535fc451e..80573df0a4d7 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c | |||
@@ -527,7 +527,7 @@ static void i82875p_remove_one(struct pci_dev *pdev) | |||
527 | edac_mc_free(mci); | 527 | edac_mc_free(mci); |
528 | } | 528 | } |
529 | 529 | ||
530 | static DEFINE_PCI_DEVICE_TABLE(i82875p_pci_tbl) = { | 530 | static const struct pci_device_id i82875p_pci_tbl[] = { |
531 | { | 531 | { |
532 | PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 532 | PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
533 | I82875P}, | 533 | I82875P}, |
diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 0c8d4b0eaa32..10b10521f62e 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c | |||
@@ -628,7 +628,7 @@ static void i82975x_remove_one(struct pci_dev *pdev) | |||
628 | edac_mc_free(mci); | 628 | edac_mc_free(mci); |
629 | } | 629 | } |
630 | 630 | ||
631 | static DEFINE_PCI_DEVICE_TABLE(i82975x_pci_tbl) = { | 631 | static const struct pci_device_id i82975x_pci_tbl[] = { |
632 | { | 632 | { |
633 | PCI_VEND_DEV(INTEL, 82975_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 633 | PCI_VEND_DEV(INTEL, 82975_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
634 | I82975X | 634 | I82975X |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index fd46b0bd5f2a..8f9182179a7c 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Freescale MPC85xx Memory Controller kenel module | 2 | * Freescale MPC85xx Memory Controller kenel module |
3 | * | 3 | * |
4 | * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc. | ||
5 | * | ||
4 | * Author: Dave Jiang <djiang@mvista.com> | 6 | * Author: Dave Jiang <djiang@mvista.com> |
5 | * | 7 | * |
6 | * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under | 8 | * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under |
@@ -196,6 +198,42 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci) | |||
196 | edac_pci_handle_npe(pci, pci->ctl_name); | 198 | edac_pci_handle_npe(pci, pci->ctl_name); |
197 | } | 199 | } |
198 | 200 | ||
201 | static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci) | ||
202 | { | ||
203 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; | ||
204 | u32 err_detect; | ||
205 | |||
206 | err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR); | ||
207 | |||
208 | pr_err("PCIe error(s) detected\n"); | ||
209 | pr_err("PCIe ERR_DR register: 0x%08x\n", err_detect); | ||
210 | pr_err("PCIe ERR_CAP_STAT register: 0x%08x\n", | ||
211 | in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR)); | ||
212 | pr_err("PCIe ERR_CAP_R0 register: 0x%08x\n", | ||
213 | in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0)); | ||
214 | pr_err("PCIe ERR_CAP_R1 register: 0x%08x\n", | ||
215 | in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1)); | ||
216 | pr_err("PCIe ERR_CAP_R2 register: 0x%08x\n", | ||
217 | in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2)); | ||
218 | pr_err("PCIe ERR_CAP_R3 register: 0x%08x\n", | ||
219 | in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3)); | ||
220 | |||
221 | /* clear error bits */ | ||
222 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect); | ||
223 | } | ||
224 | |||
225 | static int mpc85xx_pcie_find_capability(struct device_node *np) | ||
226 | { | ||
227 | struct pci_controller *hose; | ||
228 | |||
229 | if (!np) | ||
230 | return -EINVAL; | ||
231 | |||
232 | hose = pci_find_hose_for_OF_device(np); | ||
233 | |||
234 | return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); | ||
235 | } | ||
236 | |||
199 | static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) | 237 | static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) |
200 | { | 238 | { |
201 | struct edac_pci_ctl_info *pci = dev_id; | 239 | struct edac_pci_ctl_info *pci = dev_id; |
@@ -207,7 +245,10 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) | |||
207 | if (!err_detect) | 245 | if (!err_detect) |
208 | return IRQ_NONE; | 246 | return IRQ_NONE; |
209 | 247 | ||
210 | mpc85xx_pci_check(pci); | 248 | if (pdata->is_pcie) |
249 | mpc85xx_pcie_check(pci); | ||
250 | else | ||
251 | mpc85xx_pci_check(pci); | ||
211 | 252 | ||
212 | return IRQ_HANDLED; | 253 | return IRQ_HANDLED; |
213 | } | 254 | } |
@@ -239,14 +280,22 @@ int mpc85xx_pci_err_probe(struct platform_device *op) | |||
239 | pdata = pci->pvt_info; | 280 | pdata = pci->pvt_info; |
240 | pdata->name = "mpc85xx_pci_err"; | 281 | pdata->name = "mpc85xx_pci_err"; |
241 | pdata->irq = NO_IRQ; | 282 | pdata->irq = NO_IRQ; |
283 | |||
284 | if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0) | ||
285 | pdata->is_pcie = true; | ||
286 | |||
242 | dev_set_drvdata(&op->dev, pci); | 287 | dev_set_drvdata(&op->dev, pci); |
243 | pci->dev = &op->dev; | 288 | pci->dev = &op->dev; |
244 | pci->mod_name = EDAC_MOD_STR; | 289 | pci->mod_name = EDAC_MOD_STR; |
245 | pci->ctl_name = pdata->name; | 290 | pci->ctl_name = pdata->name; |
246 | pci->dev_name = dev_name(&op->dev); | 291 | pci->dev_name = dev_name(&op->dev); |
247 | 292 | ||
248 | if (edac_op_state == EDAC_OPSTATE_POLL) | 293 | if (edac_op_state == EDAC_OPSTATE_POLL) { |
249 | pci->edac_check = mpc85xx_pci_check; | 294 | if (pdata->is_pcie) |
295 | pci->edac_check = mpc85xx_pcie_check; | ||
296 | else | ||
297 | pci->edac_check = mpc85xx_pci_check; | ||
298 | } | ||
250 | 299 | ||
251 | pdata->edac_idx = edac_pci_idx++; | 300 | pdata->edac_idx = edac_pci_idx++; |
252 | 301 | ||
@@ -275,16 +324,26 @@ int mpc85xx_pci_err_probe(struct platform_device *op) | |||
275 | goto err; | 324 | goto err; |
276 | } | 325 | } |
277 | 326 | ||
278 | orig_pci_err_cap_dr = | 327 | if (pdata->is_pcie) { |
279 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR); | 328 | orig_pci_err_cap_dr = |
329 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR); | ||
330 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0); | ||
331 | orig_pci_err_en = | ||
332 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN); | ||
333 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0); | ||
334 | } else { | ||
335 | orig_pci_err_cap_dr = | ||
336 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR); | ||
280 | 337 | ||
281 | /* PCI master abort is expected during config cycles */ | 338 | /* PCI master abort is expected during config cycles */ |
282 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40); | 339 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40); |
283 | 340 | ||
284 | orig_pci_err_en = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN); | 341 | orig_pci_err_en = |
342 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN); | ||
285 | 343 | ||
286 | /* disable master abort reporting */ | 344 | /* disable master abort reporting */ |
287 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40); | 345 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40); |
346 | } | ||
288 | 347 | ||
289 | /* clear error bits */ | 348 | /* clear error bits */ |
290 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0); | 349 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0); |
@@ -297,7 +356,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op) | |||
297 | if (edac_op_state == EDAC_OPSTATE_INT) { | 356 | if (edac_op_state == EDAC_OPSTATE_INT) { |
298 | pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0); | 357 | pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0); |
299 | res = devm_request_irq(&op->dev, pdata->irq, | 358 | res = devm_request_irq(&op->dev, pdata->irq, |
300 | mpc85xx_pci_isr, IRQF_DISABLED, | 359 | mpc85xx_pci_isr, |
360 | IRQF_DISABLED | IRQF_SHARED, | ||
301 | "[EDAC] PCI err", pci); | 361 | "[EDAC] PCI err", pci); |
302 | if (res < 0) { | 362 | if (res < 0) { |
303 | printk(KERN_ERR | 363 | printk(KERN_ERR |
@@ -312,6 +372,22 @@ int mpc85xx_pci_err_probe(struct platform_device *op) | |||
312 | pdata->irq); | 372 | pdata->irq); |
313 | } | 373 | } |
314 | 374 | ||
375 | if (pdata->is_pcie) { | ||
376 | /* | ||
377 | * Enable all PCIe error interrupt & error detect except invalid | ||
378 | * PEX_CONFIG_ADDR/PEX_CONFIG_DATA access interrupt generation | ||
379 | * enable bit and invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA access | ||
380 | * detection enable bit. Because PCIe bus code to initialize and | ||
381 | * configure these PCIe devices on booting will use some invalid | ||
382 | * PEX_CONFIG_ADDR/PEX_CONFIG_DATA, edac driver prints the much | ||
383 | * notice information. So disable this detect to fix ugly print. | ||
384 | */ | ||
385 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0 | ||
386 | & ~PEX_ERR_ICCAIE_EN_BIT); | ||
387 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0 | ||
388 | | PEX_ERR_ICCAD_DISR_BIT); | ||
389 | } | ||
390 | |||
315 | devres_remove_group(&op->dev, mpc85xx_pci_err_probe); | 391 | devres_remove_group(&op->dev, mpc85xx_pci_err_probe); |
316 | edac_dbg(3, "success\n"); | 392 | edac_dbg(3, "success\n"); |
317 | printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); | 393 | printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); |
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index 932016f2cf06..8c6256436227 100644 --- a/drivers/edac/mpc85xx_edac.h +++ b/drivers/edac/mpc85xx_edac.h | |||
@@ -134,13 +134,19 @@ | |||
134 | #define MPC85XX_PCI_ERR_DR 0x0000 | 134 | #define MPC85XX_PCI_ERR_DR 0x0000 |
135 | #define MPC85XX_PCI_ERR_CAP_DR 0x0004 | 135 | #define MPC85XX_PCI_ERR_CAP_DR 0x0004 |
136 | #define MPC85XX_PCI_ERR_EN 0x0008 | 136 | #define MPC85XX_PCI_ERR_EN 0x0008 |
137 | #define PEX_ERR_ICCAIE_EN_BIT 0x00020000 | ||
137 | #define MPC85XX_PCI_ERR_ATTRIB 0x000c | 138 | #define MPC85XX_PCI_ERR_ATTRIB 0x000c |
138 | #define MPC85XX_PCI_ERR_ADDR 0x0010 | 139 | #define MPC85XX_PCI_ERR_ADDR 0x0010 |
140 | #define PEX_ERR_ICCAD_DISR_BIT 0x00020000 | ||
139 | #define MPC85XX_PCI_ERR_EXT_ADDR 0x0014 | 141 | #define MPC85XX_PCI_ERR_EXT_ADDR 0x0014 |
140 | #define MPC85XX_PCI_ERR_DL 0x0018 | 142 | #define MPC85XX_PCI_ERR_DL 0x0018 |
141 | #define MPC85XX_PCI_ERR_DH 0x001c | 143 | #define MPC85XX_PCI_ERR_DH 0x001c |
142 | #define MPC85XX_PCI_GAS_TIMR 0x0020 | 144 | #define MPC85XX_PCI_GAS_TIMR 0x0020 |
143 | #define MPC85XX_PCI_PCIX_TIMR 0x0024 | 145 | #define MPC85XX_PCI_PCIX_TIMR 0x0024 |
146 | #define MPC85XX_PCIE_ERR_CAP_R0 0x0028 | ||
147 | #define MPC85XX_PCIE_ERR_CAP_R1 0x002c | ||
148 | #define MPC85XX_PCIE_ERR_CAP_R2 0x0030 | ||
149 | #define MPC85XX_PCIE_ERR_CAP_R3 0x0034 | ||
144 | 150 | ||
145 | struct mpc85xx_mc_pdata { | 151 | struct mpc85xx_mc_pdata { |
146 | char *name; | 152 | char *name; |
@@ -158,6 +164,7 @@ struct mpc85xx_l2_pdata { | |||
158 | 164 | ||
159 | struct mpc85xx_pci_pdata { | 165 | struct mpc85xx_pci_pdata { |
160 | char *name; | 166 | char *name; |
167 | bool is_pcie; | ||
161 | int edac_idx; | 168 | int edac_idx; |
162 | void __iomem *pci_vbase; | 169 | void __iomem *pci_vbase; |
163 | int irq; | 170 | int irq; |
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 2fd6a5490905..8f936bc7a010 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c | |||
@@ -383,7 +383,7 @@ static void r82600_remove_one(struct pci_dev *pdev) | |||
383 | edac_mc_free(mci); | 383 | edac_mc_free(mci); |
384 | } | 384 | } |
385 | 385 | ||
386 | static DEFINE_PCI_DEVICE_TABLE(r82600_pci_tbl) = { | 386 | static const struct pci_device_id r82600_pci_tbl[] = { |
387 | { | 387 | { |
388 | PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID) | 388 | PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID) |
389 | }, | 389 | }, |
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index d7f1b57bd3be..54e2abe671f7 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c | |||
@@ -461,7 +461,7 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { | |||
461 | /* | 461 | /* |
462 | * pci_device_id table for which devices we are looking for | 462 | * pci_device_id table for which devices we are looking for |
463 | */ | 463 | */ |
464 | static DEFINE_PCI_DEVICE_TABLE(sbridge_pci_tbl) = { | 464 | static const struct pci_device_id sbridge_pci_tbl[] = { |
465 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, | 465 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, |
466 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, | 466 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, |
467 | {0,} /* 0 terminated list. */ | 467 | {0,} /* 0 terminated list. */ |
@@ -915,7 +915,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) | |||
915 | } | 915 | } |
916 | } | 916 | } |
917 | 917 | ||
918 | struct mem_ctl_info *get_mci_for_node_id(u8 node_id) | 918 | static struct mem_ctl_info *get_mci_for_node_id(u8 node_id) |
919 | { | 919 | { |
920 | struct sbridge_dev *sbridge_dev; | 920 | struct sbridge_dev *sbridge_dev; |
921 | 921 | ||
@@ -1829,6 +1829,9 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, | |||
1829 | struct mem_ctl_info *mci; | 1829 | struct mem_ctl_info *mci; |
1830 | struct sbridge_pvt *pvt; | 1830 | struct sbridge_pvt *pvt; |
1831 | 1831 | ||
1832 | if (get_edac_report_status() == EDAC_REPORTING_DISABLED) | ||
1833 | return NOTIFY_DONE; | ||
1834 | |||
1832 | mci = get_mci_for_node_id(mce->socketid); | 1835 | mci = get_mci_for_node_id(mce->socketid); |
1833 | if (!mci) | 1836 | if (!mci) |
1834 | return NOTIFY_BAD; | 1837 | return NOTIFY_BAD; |
@@ -2142,9 +2145,10 @@ static int __init sbridge_init(void) | |||
2142 | opstate_init(); | 2145 | opstate_init(); |
2143 | 2146 | ||
2144 | pci_rc = pci_register_driver(&sbridge_driver); | 2147 | pci_rc = pci_register_driver(&sbridge_driver); |
2145 | |||
2146 | if (pci_rc >= 0) { | 2148 | if (pci_rc >= 0) { |
2147 | mce_register_decode_chain(&sbridge_mce_dec); | 2149 | mce_register_decode_chain(&sbridge_mce_dec); |
2150 | if (get_edac_report_status() == EDAC_REPORTING_DISABLED) | ||
2151 | sbridge_printk(KERN_WARNING, "Loading driver, error reporting disabled.\n"); | ||
2148 | return 0; | 2152 | return 0; |
2149 | } | 2153 | } |
2150 | 2154 | ||
diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 1a4df82376ba..4891b450830b 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c | |||
@@ -448,7 +448,7 @@ static void x38_remove_one(struct pci_dev *pdev) | |||
448 | edac_mc_free(mci); | 448 | edac_mc_free(mci); |
449 | } | 449 | } |
450 | 450 | ||
451 | static DEFINE_PCI_DEVICE_TABLE(x38_pci_tbl) = { | 451 | static const struct pci_device_id x38_pci_tbl[] = { |
452 | { | 452 | { |
453 | PCI_VEND_DEV(INTEL, X38_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 453 | PCI_VEND_DEV(INTEL, X38_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
454 | X38}, | 454 | X38}, |
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 6aecbc86ec94..1e75f48b61f8 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig | |||
@@ -36,6 +36,17 @@ config EFI_VARS_PSTORE_DEFAULT_DISABLE | |||
36 | backend for pstore by default. This setting can be overridden | 36 | backend for pstore by default. This setting can be overridden |
37 | using the efivars module's pstore_disable parameter. | 37 | using the efivars module's pstore_disable parameter. |
38 | 38 | ||
39 | config EFI_RUNTIME_MAP | ||
40 | bool "Export efi runtime maps to sysfs" | ||
41 | depends on X86 && EFI && KEXEC | ||
42 | default y | ||
43 | help | ||
44 | Export efi runtime memory maps to /sys/firmware/efi/runtime-map. | ||
45 | That memory map is used for example by kexec to set up efi virtual | ||
46 | mapping the 2nd kernel, but can also be used for debugging purposes. | ||
47 | |||
48 | See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map. | ||
49 | |||
39 | endmenu | 50 | endmenu |
40 | 51 | ||
41 | config UEFI_CPER | 52 | config UEFI_CPER |
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 6c2a41ec21ba..9553496b0f43 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
@@ -5,3 +5,4 @@ obj-$(CONFIG_EFI) += efi.o vars.o | |||
5 | obj-$(CONFIG_EFI_VARS) += efivars.o | 5 | obj-$(CONFIG_EFI_VARS) += efivars.o |
6 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o | 6 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o |
7 | obj-$(CONFIG_UEFI_CPER) += cper.o | 7 | obj-$(CONFIG_UEFI_CPER) += cper.o |
8 | obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o | ||
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 2e2fbdec0845..4753bac65279 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -32,6 +32,9 @@ struct efi __read_mostly efi = { | |||
32 | .hcdp = EFI_INVALID_TABLE_ADDR, | 32 | .hcdp = EFI_INVALID_TABLE_ADDR, |
33 | .uga = EFI_INVALID_TABLE_ADDR, | 33 | .uga = EFI_INVALID_TABLE_ADDR, |
34 | .uv_systab = EFI_INVALID_TABLE_ADDR, | 34 | .uv_systab = EFI_INVALID_TABLE_ADDR, |
35 | .fw_vendor = EFI_INVALID_TABLE_ADDR, | ||
36 | .runtime = EFI_INVALID_TABLE_ADDR, | ||
37 | .config_table = EFI_INVALID_TABLE_ADDR, | ||
35 | }; | 38 | }; |
36 | EXPORT_SYMBOL(efi); | 39 | EXPORT_SYMBOL(efi); |
37 | 40 | ||
@@ -71,13 +74,49 @@ static ssize_t systab_show(struct kobject *kobj, | |||
71 | static struct kobj_attribute efi_attr_systab = | 74 | static struct kobj_attribute efi_attr_systab = |
72 | __ATTR(systab, 0400, systab_show, NULL); | 75 | __ATTR(systab, 0400, systab_show, NULL); |
73 | 76 | ||
77 | #define EFI_FIELD(var) efi.var | ||
78 | |||
79 | #define EFI_ATTR_SHOW(name) \ | ||
80 | static ssize_t name##_show(struct kobject *kobj, \ | ||
81 | struct kobj_attribute *attr, char *buf) \ | ||
82 | { \ | ||
83 | return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \ | ||
84 | } | ||
85 | |||
86 | EFI_ATTR_SHOW(fw_vendor); | ||
87 | EFI_ATTR_SHOW(runtime); | ||
88 | EFI_ATTR_SHOW(config_table); | ||
89 | |||
90 | static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor); | ||
91 | static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime); | ||
92 | static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table); | ||
93 | |||
74 | static struct attribute *efi_subsys_attrs[] = { | 94 | static struct attribute *efi_subsys_attrs[] = { |
75 | &efi_attr_systab.attr, | 95 | &efi_attr_systab.attr, |
76 | NULL, /* maybe more in the future? */ | 96 | &efi_attr_fw_vendor.attr, |
97 | &efi_attr_runtime.attr, | ||
98 | &efi_attr_config_table.attr, | ||
99 | NULL, | ||
77 | }; | 100 | }; |
78 | 101 | ||
102 | static umode_t efi_attr_is_visible(struct kobject *kobj, | ||
103 | struct attribute *attr, int n) | ||
104 | { | ||
105 | umode_t mode = attr->mode; | ||
106 | |||
107 | if (attr == &efi_attr_fw_vendor.attr) | ||
108 | return (efi.fw_vendor == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | ||
109 | else if (attr == &efi_attr_runtime.attr) | ||
110 | return (efi.runtime == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | ||
111 | else if (attr == &efi_attr_config_table.attr) | ||
112 | return (efi.config_table == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | ||
113 | |||
114 | return mode; | ||
115 | } | ||
116 | |||
79 | static struct attribute_group efi_subsys_attr_group = { | 117 | static struct attribute_group efi_subsys_attr_group = { |
80 | .attrs = efi_subsys_attrs, | 118 | .attrs = efi_subsys_attrs, |
119 | .is_visible = efi_attr_is_visible, | ||
81 | }; | 120 | }; |
82 | 121 | ||
83 | static struct efivars generic_efivars; | 122 | static struct efivars generic_efivars; |
@@ -128,6 +167,10 @@ static int __init efisubsys_init(void) | |||
128 | goto err_unregister; | 167 | goto err_unregister; |
129 | } | 168 | } |
130 | 169 | ||
170 | error = efi_runtime_map_init(efi_kobj); | ||
171 | if (error) | ||
172 | goto err_remove_group; | ||
173 | |||
131 | /* and the standard mountpoint for efivarfs */ | 174 | /* and the standard mountpoint for efivarfs */ |
132 | efivars_kobj = kobject_create_and_add("efivars", efi_kobj); | 175 | efivars_kobj = kobject_create_and_add("efivars", efi_kobj); |
133 | if (!efivars_kobj) { | 176 | if (!efivars_kobj) { |
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c new file mode 100644 index 000000000000..97cdd16a2169 --- /dev/null +++ b/drivers/firmware/efi/runtime-map.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * linux/drivers/efi/runtime-map.c | ||
3 | * Copyright (C) 2013 Red Hat, Inc., Dave Young <dyoung@redhat.com> | ||
4 | * | ||
5 | * This file is released under the GPLv2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/string.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/efi.h> | ||
13 | #include <linux/slab.h> | ||
14 | |||
15 | #include <asm/setup.h> | ||
16 | |||
17 | static void *efi_runtime_map; | ||
18 | static int nr_efi_runtime_map; | ||
19 | static u32 efi_memdesc_size; | ||
20 | |||
21 | struct efi_runtime_map_entry { | ||
22 | efi_memory_desc_t md; | ||
23 | struct kobject kobj; /* kobject for each entry */ | ||
24 | }; | ||
25 | |||
26 | static struct efi_runtime_map_entry **map_entries; | ||
27 | |||
28 | struct map_attribute { | ||
29 | struct attribute attr; | ||
30 | ssize_t (*show)(struct efi_runtime_map_entry *entry, char *buf); | ||
31 | }; | ||
32 | |||
33 | static inline struct map_attribute *to_map_attr(struct attribute *attr) | ||
34 | { | ||
35 | return container_of(attr, struct map_attribute, attr); | ||
36 | } | ||
37 | |||
38 | static ssize_t type_show(struct efi_runtime_map_entry *entry, char *buf) | ||
39 | { | ||
40 | return snprintf(buf, PAGE_SIZE, "0x%x\n", entry->md.type); | ||
41 | } | ||
42 | |||
43 | #define EFI_RUNTIME_FIELD(var) entry->md.var | ||
44 | |||
45 | #define EFI_RUNTIME_U64_ATTR_SHOW(name) \ | ||
46 | static ssize_t name##_show(struct efi_runtime_map_entry *entry, char *buf) \ | ||
47 | { \ | ||
48 | return snprintf(buf, PAGE_SIZE, "0x%llx\n", EFI_RUNTIME_FIELD(name)); \ | ||
49 | } | ||
50 | |||
51 | EFI_RUNTIME_U64_ATTR_SHOW(phys_addr); | ||
52 | EFI_RUNTIME_U64_ATTR_SHOW(virt_addr); | ||
53 | EFI_RUNTIME_U64_ATTR_SHOW(num_pages); | ||
54 | EFI_RUNTIME_U64_ATTR_SHOW(attribute); | ||
55 | |||
56 | static inline struct efi_runtime_map_entry *to_map_entry(struct kobject *kobj) | ||
57 | { | ||
58 | return container_of(kobj, struct efi_runtime_map_entry, kobj); | ||
59 | } | ||
60 | |||
61 | static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr, | ||
62 | char *buf) | ||
63 | { | ||
64 | struct efi_runtime_map_entry *entry = to_map_entry(kobj); | ||
65 | struct map_attribute *map_attr = to_map_attr(attr); | ||
66 | |||
67 | return map_attr->show(entry, buf); | ||
68 | } | ||
69 | |||
70 | static struct map_attribute map_type_attr = __ATTR_RO(type); | ||
71 | static struct map_attribute map_phys_addr_attr = __ATTR_RO(phys_addr); | ||
72 | static struct map_attribute map_virt_addr_attr = __ATTR_RO(virt_addr); | ||
73 | static struct map_attribute map_num_pages_attr = __ATTR_RO(num_pages); | ||
74 | static struct map_attribute map_attribute_attr = __ATTR_RO(attribute); | ||
75 | |||
76 | /* | ||
77 | * These are default attributes that are added for every memmap entry. | ||
78 | */ | ||
79 | static struct attribute *def_attrs[] = { | ||
80 | &map_type_attr.attr, | ||
81 | &map_phys_addr_attr.attr, | ||
82 | &map_virt_addr_attr.attr, | ||
83 | &map_num_pages_attr.attr, | ||
84 | &map_attribute_attr.attr, | ||
85 | NULL | ||
86 | }; | ||
87 | |||
88 | static const struct sysfs_ops map_attr_ops = { | ||
89 | .show = map_attr_show, | ||
90 | }; | ||
91 | |||
92 | static void map_release(struct kobject *kobj) | ||
93 | { | ||
94 | struct efi_runtime_map_entry *entry; | ||
95 | |||
96 | entry = to_map_entry(kobj); | ||
97 | kfree(entry); | ||
98 | } | ||
99 | |||
100 | static struct kobj_type __refdata map_ktype = { | ||
101 | .sysfs_ops = &map_attr_ops, | ||
102 | .default_attrs = def_attrs, | ||
103 | .release = map_release, | ||
104 | }; | ||
105 | |||
106 | static struct kset *map_kset; | ||
107 | |||
108 | static struct efi_runtime_map_entry * | ||
109 | add_sysfs_runtime_map_entry(struct kobject *kobj, int nr) | ||
110 | { | ||
111 | int ret; | ||
112 | struct efi_runtime_map_entry *entry; | ||
113 | |||
114 | if (!map_kset) { | ||
115 | map_kset = kset_create_and_add("runtime-map", NULL, kobj); | ||
116 | if (!map_kset) | ||
117 | return ERR_PTR(-ENOMEM); | ||
118 | } | ||
119 | |||
120 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | ||
121 | if (!entry) { | ||
122 | kset_unregister(map_kset); | ||
123 | return entry; | ||
124 | } | ||
125 | |||
126 | memcpy(&entry->md, efi_runtime_map + nr * efi_memdesc_size, | ||
127 | sizeof(efi_memory_desc_t)); | ||
128 | |||
129 | kobject_init(&entry->kobj, &map_ktype); | ||
130 | entry->kobj.kset = map_kset; | ||
131 | ret = kobject_add(&entry->kobj, NULL, "%d", nr); | ||
132 | if (ret) { | ||
133 | kobject_put(&entry->kobj); | ||
134 | kset_unregister(map_kset); | ||
135 | return ERR_PTR(ret); | ||
136 | } | ||
137 | |||
138 | return entry; | ||
139 | } | ||
140 | |||
141 | void efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) | ||
142 | { | ||
143 | efi_runtime_map = map; | ||
144 | nr_efi_runtime_map = nr_entries; | ||
145 | efi_memdesc_size = desc_size; | ||
146 | } | ||
147 | |||
148 | int __init efi_runtime_map_init(struct kobject *efi_kobj) | ||
149 | { | ||
150 | int i, j, ret = 0; | ||
151 | struct efi_runtime_map_entry *entry; | ||
152 | |||
153 | if (!efi_runtime_map) | ||
154 | return 0; | ||
155 | |||
156 | map_entries = kzalloc(nr_efi_runtime_map * sizeof(entry), GFP_KERNEL); | ||
157 | if (!map_entries) { | ||
158 | ret = -ENOMEM; | ||
159 | goto out; | ||
160 | } | ||
161 | |||
162 | for (i = 0; i < nr_efi_runtime_map; i++) { | ||
163 | entry = add_sysfs_runtime_map_entry(efi_kobj, i); | ||
164 | if (IS_ERR(entry)) { | ||
165 | ret = PTR_ERR(entry); | ||
166 | goto out_add_entry; | ||
167 | } | ||
168 | *(map_entries + i) = entry; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | out_add_entry: | ||
173 | for (j = i - 1; j > 0; j--) { | ||
174 | entry = *(map_entries + j); | ||
175 | kobject_put(&entry->kobj); | ||
176 | } | ||
177 | if (map_kset) | ||
178 | kset_unregister(map_kset); | ||
179 | out: | ||
180 | return ret; | ||
181 | } | ||
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 85071a1c4547..b0733153dfd2 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -1041,7 +1041,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector) | |||
1041 | /* if equal delete the probed mode */ | 1041 | /* if equal delete the probed mode */ |
1042 | mode->status = pmode->status; | 1042 | mode->status = pmode->status; |
1043 | /* Merge type bits together */ | 1043 | /* Merge type bits together */ |
1044 | mode->type = pmode->type; | 1044 | mode->type |= pmode->type; |
1045 | list_del(&pmode->head); | 1045 | list_del(&pmode->head); |
1046 | drm_mode_destroy(connector->dev, pmode); | 1046 | drm_mode_destroy(connector->dev, pmode); |
1047 | break; | 1047 | break; |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5d1dedc02f15..f13d5edc39d5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -2713,6 +2713,8 @@ static void gen8_irq_preinstall(struct drm_device *dev) | |||
2713 | #undef GEN8_IRQ_INIT_NDX | 2713 | #undef GEN8_IRQ_INIT_NDX |
2714 | 2714 | ||
2715 | POSTING_READ(GEN8_PCU_IIR); | 2715 | POSTING_READ(GEN8_PCU_IIR); |
2716 | |||
2717 | ibx_irq_preinstall(dev); | ||
2716 | } | 2718 | } |
2717 | 2719 | ||
2718 | static void ibx_hpd_irq_setup(struct drm_device *dev) | 2720 | static void ibx_hpd_irq_setup(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 526c8ded16b0..b69dc3e66c16 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -1057,12 +1057,18 @@ void intel_ddi_setup_hw_pll_state(struct drm_device *dev) | |||
1057 | enum pipe pipe; | 1057 | enum pipe pipe; |
1058 | struct intel_crtc *intel_crtc; | 1058 | struct intel_crtc *intel_crtc; |
1059 | 1059 | ||
1060 | dev_priv->ddi_plls.spll_refcount = 0; | ||
1061 | dev_priv->ddi_plls.wrpll1_refcount = 0; | ||
1062 | dev_priv->ddi_plls.wrpll2_refcount = 0; | ||
1063 | |||
1060 | for_each_pipe(pipe) { | 1064 | for_each_pipe(pipe) { |
1061 | intel_crtc = | 1065 | intel_crtc = |
1062 | to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); | 1066 | to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
1063 | 1067 | ||
1064 | if (!intel_crtc->active) | 1068 | if (!intel_crtc->active) { |
1069 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE; | ||
1065 | continue; | 1070 | continue; |
1071 | } | ||
1066 | 1072 | ||
1067 | intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, | 1073 | intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, |
1068 | pipe); | 1074 | pipe); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 769b864465a9..2bde35d34eb9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -11053,10 +11053,10 @@ void intel_modeset_gem_init(struct drm_device *dev) | |||
11053 | 11053 | ||
11054 | intel_setup_overlay(dev); | 11054 | intel_setup_overlay(dev); |
11055 | 11055 | ||
11056 | drm_modeset_lock_all(dev); | 11056 | mutex_lock(&dev->mode_config.mutex); |
11057 | drm_mode_config_reset(dev); | 11057 | drm_mode_config_reset(dev); |
11058 | intel_modeset_setup_hw_state(dev, false); | 11058 | intel_modeset_setup_hw_state(dev, false); |
11059 | drm_modeset_unlock_all(dev); | 11059 | mutex_unlock(&dev->mode_config.mutex); |
11060 | } | 11060 | } |
11061 | 11061 | ||
11062 | void intel_modeset_cleanup(struct drm_device *dev) | 11062 | void intel_modeset_cleanup(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 9fa5da723871..7f50a858b16f 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h | |||
@@ -73,7 +73,7 @@ struct nouveau_i2c { | |||
73 | int (*identify)(struct nouveau_i2c *, int index, | 73 | int (*identify)(struct nouveau_i2c *, int index, |
74 | const char *what, struct nouveau_i2c_board_info *, | 74 | const char *what, struct nouveau_i2c_board_info *, |
75 | bool (*match)(struct nouveau_i2c_port *, | 75 | bool (*match)(struct nouveau_i2c_port *, |
76 | struct i2c_board_info *)); | 76 | struct i2c_board_info *, void *), void *); |
77 | struct list_head ports; | 77 | struct list_head ports; |
78 | }; | 78 | }; |
79 | 79 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h index ec7a54e91a08..4aca33887aaa 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h | |||
@@ -50,6 +50,13 @@ struct nouveau_instmem { | |||
50 | static inline struct nouveau_instmem * | 50 | static inline struct nouveau_instmem * |
51 | nouveau_instmem(void *obj) | 51 | nouveau_instmem(void *obj) |
52 | { | 52 | { |
53 | /* nv04/nv40 impls need to create objects in their constructor, | ||
54 | * which is before the subdev pointer is valid | ||
55 | */ | ||
56 | if (nv_iclass(obj, NV_SUBDEV_CLASS) && | ||
57 | nv_subidx(obj) == NVDEV_SUBDEV_INSTMEM) | ||
58 | return obj; | ||
59 | |||
53 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM]; | 60 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM]; |
54 | } | 61 | } |
55 | 62 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 041fd5edaebf..c33c03d2f4af 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | |||
@@ -197,7 +197,7 @@ static int | |||
197 | nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, | 197 | nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, |
198 | struct nouveau_i2c_board_info *info, | 198 | struct nouveau_i2c_board_info *info, |
199 | bool (*match)(struct nouveau_i2c_port *, | 199 | bool (*match)(struct nouveau_i2c_port *, |
200 | struct i2c_board_info *)) | 200 | struct i2c_board_info *, void *), void *data) |
201 | { | 201 | { |
202 | struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); | 202 | struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); |
203 | int i; | 203 | int i; |
@@ -221,7 +221,7 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, | |||
221 | } | 221 | } |
222 | 222 | ||
223 | if (nv_probe_i2c(port, info[i].dev.addr) && | 223 | if (nv_probe_i2c(port, info[i].dev.addr) && |
224 | (!match || match(port, &info[i].dev))) { | 224 | (!match || match(port, &info[i].dev, data))) { |
225 | nv_info(i2c, "detected %s: %s\n", what, | 225 | nv_info(i2c, "detected %s: %s\n", what, |
226 | info[i].dev.type); | 226 | info[i].dev.type); |
227 | return i; | 227 | return i; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c index af129c2e8113..64f8b4702bf7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c | |||
@@ -100,7 +100,7 @@ mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info) | |||
100 | static int | 100 | static int |
101 | mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb) | 101 | mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb) |
102 | { | 102 | { |
103 | struct nouveau_mxm *mxm = nouveau_mxm(bios); | 103 | struct nouveau_mxm *mxm = data; |
104 | struct context ctx = { .outp = (u32 *)(bios->data + pdcb) }; | 104 | struct context ctx = { .outp = (u32 *)(bios->data + pdcb) }; |
105 | u8 type, i2cidx, link, ver, len; | 105 | u8 type, i2cidx, link, ver, len; |
106 | u8 *conn; | 106 | u8 *conn; |
@@ -199,7 +199,7 @@ mxm_dcb_sanitise(struct nouveau_mxm *mxm) | |||
199 | return; | 199 | return; |
200 | } | 200 | } |
201 | 201 | ||
202 | dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry); | 202 | dcb_outp_foreach(bios, mxm, mxm_dcb_sanitise_entry); |
203 | mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL); | 203 | mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL); |
204 | } | 204 | } |
205 | 205 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index e44ed7b93c6d..7610fc5f8fa2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c | |||
@@ -29,9 +29,9 @@ | |||
29 | 29 | ||
30 | static bool | 30 | static bool |
31 | probe_monitoring_device(struct nouveau_i2c_port *i2c, | 31 | probe_monitoring_device(struct nouveau_i2c_port *i2c, |
32 | struct i2c_board_info *info) | 32 | struct i2c_board_info *info, void *data) |
33 | { | 33 | { |
34 | struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); | 34 | struct nouveau_therm_priv *priv = data; |
35 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; | 35 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; |
36 | struct i2c_client *client; | 36 | struct i2c_client *client; |
37 | 37 | ||
@@ -96,7 +96,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) | |||
96 | }; | 96 | }; |
97 | 97 | ||
98 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | 98 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", |
99 | board, probe_monitoring_device); | 99 | board, probe_monitoring_device, therm); |
100 | if (priv->ic) | 100 | if (priv->ic) |
101 | return; | 101 | return; |
102 | } | 102 | } |
@@ -108,7 +108,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) | |||
108 | }; | 108 | }; |
109 | 109 | ||
110 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | 110 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", |
111 | board, probe_monitoring_device); | 111 | board, probe_monitoring_device, therm); |
112 | if (priv->ic) | 112 | if (priv->ic) |
113 | return; | 113 | return; |
114 | } | 114 | } |
@@ -117,5 +117,5 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) | |||
117 | device. Let's try our static list. | 117 | device. Let's try our static list. |
118 | */ | 118 | */ |
119 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | 119 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", |
120 | nv_board_infos, probe_monitoring_device); | 120 | nv_board_infos, probe_monitoring_device, therm); |
121 | } | 121 | } |
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 936a71c59080..7fdc51e2a571 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c | |||
@@ -643,7 +643,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) | |||
643 | get_tmds_slave(encoder)) | 643 | get_tmds_slave(encoder)) |
644 | return; | 644 | return; |
645 | 645 | ||
646 | type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL); | 646 | type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL, NULL); |
647 | if (type < 0) | 647 | if (type < 0) |
648 | return; | 648 | return; |
649 | 649 | ||
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index cc4b208ce546..244822df8ffc 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | |||
@@ -59,7 +59,7 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index) | |||
59 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | 59 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); |
60 | 60 | ||
61 | return i2c->identify(i2c, i2c_index, "TV encoder", | 61 | return i2c->identify(i2c, i2c_index, "TV encoder", |
62 | nv04_tv_encoder_info, NULL); | 62 | nv04_tv_encoder_info, NULL, NULL); |
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | ||
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 78be66176840..bbb0b0d463f7 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/cpu.h> | 36 | #include <linux/cpu.h> |
37 | #include <linux/smp.h> | 37 | #include <linux/smp.h> |
38 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
39 | #include <linux/pci.h> | ||
39 | #include <asm/msr.h> | 40 | #include <asm/msr.h> |
40 | #include <asm/processor.h> | 41 | #include <asm/processor.h> |
41 | #include <asm/cpu_device_id.h> | 42 | #include <asm/cpu_device_id.h> |
@@ -52,7 +53,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); | |||
52 | 53 | ||
53 | #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ | 54 | #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ |
54 | #define NUM_REAL_CORES 32 /* Number of Real cores per cpu */ | 55 | #define NUM_REAL_CORES 32 /* Number of Real cores per cpu */ |
55 | #define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ | 56 | #define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */ |
56 | #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ | 57 | #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ |
57 | #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) | 58 | #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) |
58 | #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) | 59 | #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) |
@@ -176,20 +177,33 @@ static ssize_t show_temp(struct device *dev, | |||
176 | /* Check whether the time interval has elapsed */ | 177 | /* Check whether the time interval has elapsed */ |
177 | if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) { | 178 | if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) { |
178 | rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); | 179 | rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); |
179 | tdata->valid = 0; | 180 | /* |
180 | /* Check whether the data is valid */ | 181 | * Ignore the valid bit. In all observed cases the register |
181 | if (eax & 0x80000000) { | 182 | * value is either low or zero if the valid bit is 0. |
182 | tdata->temp = tdata->tjmax - | 183 | * Return it instead of reporting an error which doesn't |
183 | ((eax >> 16) & 0x7f) * 1000; | 184 | * really help at all. |
184 | tdata->valid = 1; | 185 | */ |
185 | } | 186 | tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; |
187 | tdata->valid = 1; | ||
186 | tdata->last_updated = jiffies; | 188 | tdata->last_updated = jiffies; |
187 | } | 189 | } |
188 | 190 | ||
189 | mutex_unlock(&tdata->update_lock); | 191 | mutex_unlock(&tdata->update_lock); |
190 | return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN; | 192 | return sprintf(buf, "%d\n", tdata->temp); |
191 | } | 193 | } |
192 | 194 | ||
195 | struct tjmax_pci { | ||
196 | unsigned int device; | ||
197 | int tjmax; | ||
198 | }; | ||
199 | |||
200 | static const struct tjmax_pci tjmax_pci_table[] = { | ||
201 | { 0x0708, 110000 }, /* CE41x0 (Sodaville ) */ | ||
202 | { 0x0c72, 102000 }, /* Atom S1240 (Centerton) */ | ||
203 | { 0x0c73, 95000 }, /* Atom S1220 (Centerton) */ | ||
204 | { 0x0c75, 95000 }, /* Atom S1260 (Centerton) */ | ||
205 | }; | ||
206 | |||
193 | struct tjmax { | 207 | struct tjmax { |
194 | char const *id; | 208 | char const *id; |
195 | int tjmax; | 209 | int tjmax; |
@@ -198,9 +212,6 @@ struct tjmax { | |||
198 | static const struct tjmax tjmax_table[] = { | 212 | static const struct tjmax tjmax_table[] = { |
199 | { "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */ | 213 | { "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */ |
200 | { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */ | 214 | { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */ |
201 | { "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 Sodaville */ | ||
202 | { "CPU CE4150", 110000 }, /* Model 0x1c, stepping 10 */ | ||
203 | { "CPU CE4170", 110000 }, /* Model 0x1c, stepping 10 */ | ||
204 | }; | 215 | }; |
205 | 216 | ||
206 | struct tjmax_model { | 217 | struct tjmax_model { |
@@ -222,8 +233,11 @@ static const struct tjmax_model tjmax_model_table[] = { | |||
222 | * is undetectable by software | 233 | * is undetectable by software |
223 | */ | 234 | */ |
224 | { 0x27, ANY, 90000 }, /* Atom Medfield (Z2460) */ | 235 | { 0x27, ANY, 90000 }, /* Atom Medfield (Z2460) */ |
225 | { 0x35, ANY, 90000 }, /* Atom Clover Trail/Cloverview (Z2760) */ | 236 | { 0x35, ANY, 90000 }, /* Atom Clover Trail/Cloverview (Z27x0) */ |
226 | { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */ | 237 | { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) |
238 | * Also matches S12x0 (stepping 9), covered by | ||
239 | * PCI table | ||
240 | */ | ||
227 | }; | 241 | }; |
228 | 242 | ||
229 | static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) | 243 | static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) |
@@ -236,8 +250,20 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) | |||
236 | int err; | 250 | int err; |
237 | u32 eax, edx; | 251 | u32 eax, edx; |
238 | int i; | 252 | int i; |
253 | struct pci_dev *host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); | ||
254 | |||
255 | /* | ||
256 | * Explicit tjmax table entries override heuristics. | ||
257 | * First try PCI host bridge IDs, followed by model ID strings | ||
258 | * and model/stepping information. | ||
259 | */ | ||
260 | if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) { | ||
261 | for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) { | ||
262 | if (host_bridge->device == tjmax_pci_table[i].device) | ||
263 | return tjmax_pci_table[i].tjmax; | ||
264 | } | ||
265 | } | ||
239 | 266 | ||
240 | /* explicit tjmax table entries override heuristics */ | ||
241 | for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) { | 267 | for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) { |
242 | if (strstr(c->x86_model_id, tjmax_table[i].id)) | 268 | if (strstr(c->x86_model_id, tjmax_table[i].id)) |
243 | return tjmax_table[i].tjmax; | 269 | return tjmax_table[i].tjmax; |
@@ -343,12 +369,12 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) | |||
343 | if (cpu_has_tjmax(c)) | 369 | if (cpu_has_tjmax(c)) |
344 | dev_warn(dev, "Unable to read TjMax from CPU %u\n", id); | 370 | dev_warn(dev, "Unable to read TjMax from CPU %u\n", id); |
345 | } else { | 371 | } else { |
346 | val = (eax >> 16) & 0xff; | 372 | val = (eax >> 16) & 0x7f; |
347 | /* | 373 | /* |
348 | * If the TjMax is not plausible, an assumption | 374 | * If the TjMax is not plausible, an assumption |
349 | * will be used | 375 | * will be used |
350 | */ | 376 | */ |
351 | if (val) { | 377 | if (val >= 85) { |
352 | dev_dbg(dev, "TjMax is %d degrees C\n", val); | 378 | dev_dbg(dev, "TjMax is %d degrees C\n", val); |
353 | return val * 1000; | 379 | return val * 1000; |
354 | } | 380 | } |
diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c index 960fac3fb166..afd31042b452 100644 --- a/drivers/hwmon/da9052-hwmon.c +++ b/drivers/hwmon/da9052-hwmon.c | |||
@@ -45,7 +45,7 @@ static const char * const input_names[] = { | |||
45 | /* Conversion function for VDDOUT and VBAT */ | 45 | /* Conversion function for VDDOUT and VBAT */ |
46 | static inline int volt_reg_to_mv(int value) | 46 | static inline int volt_reg_to_mv(int value) |
47 | { | 47 | { |
48 | return DIV_ROUND_CLOSEST(value * 1000, 512) + 2500; | 48 | return DIV_ROUND_CLOSEST(value * 2000, 1023) + 2500; |
49 | } | 49 | } |
50 | 50 | ||
51 | /* Conversion function for ADC channels 4, 5 and 6 */ | 51 | /* Conversion function for ADC channels 4, 5 and 6 */ |
@@ -57,7 +57,7 @@ static inline int input_reg_to_mv(int value) | |||
57 | /* Conversion function for VBBAT */ | 57 | /* Conversion function for VBBAT */ |
58 | static inline int vbbat_reg_to_mv(int value) | 58 | static inline int vbbat_reg_to_mv(int value) |
59 | { | 59 | { |
60 | return DIV_ROUND_CLOSEST(value * 2500, 512); | 60 | return DIV_ROUND_CLOSEST(value * 5000, 1023); |
61 | } | 61 | } |
62 | 62 | ||
63 | static inline int da9052_enable_vddout_channel(struct da9052 *da9052) | 63 | static inline int da9052_enable_vddout_channel(struct da9052 *da9052) |
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index dff841085baf..6040121a405a 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c | |||
@@ -249,7 +249,7 @@ static void fam15h_power_remove(struct pci_dev *pdev) | |||
249 | sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); | 249 | sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); |
250 | } | 250 | } |
251 | 251 | ||
252 | static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = { | 252 | static const struct pci_device_id fam15h_power_id_table[] = { |
253 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, | 253 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, |
254 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) }, | 254 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) }, |
255 | {} | 255 | {} |
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index d65f3fd895dd..baf375b5ab0d 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c | |||
@@ -204,12 +204,13 @@ static void k10temp_remove(struct pci_dev *pdev) | |||
204 | &sensor_dev_attr_temp1_crit_hyst.dev_attr); | 204 | &sensor_dev_attr_temp1_crit_hyst.dev_attr); |
205 | } | 205 | } |
206 | 206 | ||
207 | static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = { | 207 | static const struct pci_device_id k10temp_id_table[] = { |
208 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, | 208 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, |
209 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, | 209 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, |
210 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, | 210 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, |
211 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, | 211 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, |
212 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) }, | 212 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) }, |
213 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) }, | ||
213 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, | 214 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, |
214 | {} | 215 | {} |
215 | }; | 216 | }; |
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 5b50e9e4f96b..734d55d48cc8 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c | |||
@@ -135,7 +135,7 @@ static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0); | |||
135 | static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1); | 135 | static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1); |
136 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 136 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
137 | 137 | ||
138 | static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = { | 138 | static const struct pci_device_id k8temp_ids[] = { |
139 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, | 139 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, |
140 | { 0 }, | 140 | { 0 }, |
141 | }; | 141 | }; |
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index cf811c1a1475..8686e966fa28 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c | |||
@@ -3936,6 +3936,18 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3936 | return PTR_ERR_OR_ZERO(hwmon_dev); | 3936 | return PTR_ERR_OR_ZERO(hwmon_dev); |
3937 | } | 3937 | } |
3938 | 3938 | ||
3939 | static void nct6791_enable_io_mapping(int sioaddr) | ||
3940 | { | ||
3941 | int val; | ||
3942 | |||
3943 | val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE); | ||
3944 | if (val & 0x10) { | ||
3945 | pr_info("Enabling hardware monitor logical device mappings.\n"); | ||
3946 | superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE, | ||
3947 | val & ~0x10); | ||
3948 | } | ||
3949 | } | ||
3950 | |||
3939 | #ifdef CONFIG_PM | 3951 | #ifdef CONFIG_PM |
3940 | static int nct6775_suspend(struct device *dev) | 3952 | static int nct6775_suspend(struct device *dev) |
3941 | { | 3953 | { |
@@ -3955,11 +3967,20 @@ static int nct6775_suspend(struct device *dev) | |||
3955 | static int nct6775_resume(struct device *dev) | 3967 | static int nct6775_resume(struct device *dev) |
3956 | { | 3968 | { |
3957 | struct nct6775_data *data = dev_get_drvdata(dev); | 3969 | struct nct6775_data *data = dev_get_drvdata(dev); |
3958 | int i, j; | 3970 | int i, j, err = 0; |
3959 | 3971 | ||
3960 | mutex_lock(&data->update_lock); | 3972 | mutex_lock(&data->update_lock); |
3961 | data->bank = 0xff; /* Force initial bank selection */ | 3973 | data->bank = 0xff; /* Force initial bank selection */ |
3962 | 3974 | ||
3975 | if (data->kind == nct6791) { | ||
3976 | err = superio_enter(data->sioreg); | ||
3977 | if (err) | ||
3978 | goto abort; | ||
3979 | |||
3980 | nct6791_enable_io_mapping(data->sioreg); | ||
3981 | superio_exit(data->sioreg); | ||
3982 | } | ||
3983 | |||
3963 | /* Restore limits */ | 3984 | /* Restore limits */ |
3964 | for (i = 0; i < data->in_num; i++) { | 3985 | for (i = 0; i < data->in_num; i++) { |
3965 | if (!(data->have_in & (1 << i))) | 3986 | if (!(data->have_in & (1 << i))) |
@@ -3996,11 +4017,12 @@ static int nct6775_resume(struct device *dev) | |||
3996 | nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2); | 4017 | nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2); |
3997 | } | 4018 | } |
3998 | 4019 | ||
4020 | abort: | ||
3999 | /* Force re-reading all values */ | 4021 | /* Force re-reading all values */ |
4000 | data->valid = false; | 4022 | data->valid = false; |
4001 | mutex_unlock(&data->update_lock); | 4023 | mutex_unlock(&data->update_lock); |
4002 | 4024 | ||
4003 | return 0; | 4025 | return err; |
4004 | } | 4026 | } |
4005 | 4027 | ||
4006 | static const struct dev_pm_ops nct6775_dev_pm_ops = { | 4028 | static const struct dev_pm_ops nct6775_dev_pm_ops = { |
@@ -4088,15 +4110,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) | |||
4088 | pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n"); | 4110 | pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n"); |
4089 | superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); | 4111 | superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); |
4090 | } | 4112 | } |
4091 | if (sio_data->kind == nct6791) { | 4113 | |
4092 | val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE); | 4114 | if (sio_data->kind == nct6791) |
4093 | if (val & 0x10) { | 4115 | nct6791_enable_io_mapping(sioaddr); |
4094 | pr_info("Enabling hardware monitor logical device mappings.\n"); | ||
4095 | superio_outb(sioaddr, | ||
4096 | NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE, | ||
4097 | val & ~0x10); | ||
4098 | } | ||
4099 | } | ||
4100 | 4116 | ||
4101 | superio_exit(sioaddr); | 4117 | superio_exit(sioaddr); |
4102 | pr_info("Found %s or compatible chip at %#x:%#x\n", | 4118 | pr_info("Found %s or compatible chip at %#x:%#x\n", |
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 72a889702f0d..e74bd7e620e8 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c | |||
@@ -754,7 +754,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) | |||
754 | return data; | 754 | return data; |
755 | } | 755 | } |
756 | 756 | ||
757 | static DEFINE_PCI_DEVICE_TABLE(sis5595_pci_ids) = { | 757 | static const struct pci_device_id sis5595_pci_ids[] = { |
758 | { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, | 758 | { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, |
759 | { 0, } | 759 | { 0, } |
760 | }; | 760 | }; |
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index c9dcce8c3dc3..babd732b4e18 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c | |||
@@ -824,7 +824,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) | |||
824 | return data; | 824 | return data; |
825 | } | 825 | } |
826 | 826 | ||
827 | static DEFINE_PCI_DEVICE_TABLE(via686a_pci_ids) = { | 827 | static const struct pci_device_id via686a_pci_ids[] = { |
828 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) }, | 828 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) }, |
829 | { } | 829 | { } |
830 | }; | 830 | }; |
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index aee14e2192f8..b3babe3326fb 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c | |||
@@ -766,7 +766,7 @@ static struct platform_driver vt8231_driver = { | |||
766 | .remove = vt8231_remove, | 766 | .remove = vt8231_remove, |
767 | }; | 767 | }; |
768 | 768 | ||
769 | static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = { | 769 | static const struct pci_device_id vt8231_pci_ids[] = { |
770 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) }, | 770 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) }, |
771 | { 0, } | 771 | { 0, } |
772 | }; | 772 | }; |
diff --git a/drivers/ide/buddha.c b/drivers/ide/buddha.c index b1d38590ac01..46eaf58d881b 100644 --- a/drivers/ide/buddha.c +++ b/drivers/ide/buddha.c | |||
@@ -198,7 +198,7 @@ fail_base2: | |||
198 | continue; | 198 | continue; |
199 | } | 199 | } |
200 | } | 200 | } |
201 | buddha_board = ZTWO_VADDR(board); | 201 | buddha_board = (unsigned long)ZTWO_VADDR(board); |
202 | 202 | ||
203 | /* write to BUDDHA_IRQ_MR to enable the board IRQ */ | 203 | /* write to BUDDHA_IRQ_MR to enable the board IRQ */ |
204 | /* X-Surf doesn't have this. IRQs are always on */ | 204 | /* X-Surf doesn't have this. IRQs are always on */ |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 797ed29a36ea..6c0e0452dd9b 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -377,16 +377,7 @@ static int intel_idle(struct cpuidle_device *dev, | |||
377 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) | 377 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) |
378 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); | 378 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); |
379 | 379 | ||
380 | if (!current_set_polling_and_test()) { | 380 | mwait_idle_with_hints(eax, ecx); |
381 | |||
382 | if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) | ||
383 | clflush((void *)¤t_thread_info()->flags); | ||
384 | |||
385 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
386 | smp_mb(); | ||
387 | if (!need_resched()) | ||
388 | __mwait(eax, ecx); | ||
389 | } | ||
390 | 381 | ||
391 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) | 382 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) |
392 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); | 383 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index d26a312f117a..3067d56b11a6 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -32,7 +32,7 @@ config ADB_MACII | |||
32 | 32 | ||
33 | config ADB_MACIISI | 33 | config ADB_MACIISI |
34 | bool "Include Mac IIsi ADB driver" | 34 | bool "Include Mac IIsi ADB driver" |
35 | depends on ADB && MAC | 35 | depends on ADB && MAC && BROKEN |
36 | help | 36 | help |
37 | Say Y here if want your kernel to support Macintosh systems that use | 37 | Say Y here if want your kernel to support Macintosh systems that use |
38 | the Mac IIsi style ADB. This includes the IIsi, IIvi, IIvx, Classic | 38 | the Mac IIsi style ADB. This includes the IIsi, IIvi, IIvx, Classic |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 21f4d7ff0da2..369d919bdafe 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1077,6 +1077,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1077 | rdev->raid_disk = -1; | 1077 | rdev->raid_disk = -1; |
1078 | clear_bit(Faulty, &rdev->flags); | 1078 | clear_bit(Faulty, &rdev->flags); |
1079 | clear_bit(In_sync, &rdev->flags); | 1079 | clear_bit(In_sync, &rdev->flags); |
1080 | clear_bit(Bitmap_sync, &rdev->flags); | ||
1080 | clear_bit(WriteMostly, &rdev->flags); | 1081 | clear_bit(WriteMostly, &rdev->flags); |
1081 | 1082 | ||
1082 | if (mddev->raid_disks == 0) { | 1083 | if (mddev->raid_disks == 0) { |
@@ -1155,6 +1156,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1155 | */ | 1156 | */ |
1156 | if (ev1 < mddev->bitmap->events_cleared) | 1157 | if (ev1 < mddev->bitmap->events_cleared) |
1157 | return 0; | 1158 | return 0; |
1159 | if (ev1 < mddev->events) | ||
1160 | set_bit(Bitmap_sync, &rdev->flags); | ||
1158 | } else { | 1161 | } else { |
1159 | if (ev1 < mddev->events) | 1162 | if (ev1 < mddev->events) |
1160 | /* just a hot-add of a new device, leave raid_disk at -1 */ | 1163 | /* just a hot-add of a new device, leave raid_disk at -1 */ |
@@ -1563,6 +1566,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1563 | rdev->raid_disk = -1; | 1566 | rdev->raid_disk = -1; |
1564 | clear_bit(Faulty, &rdev->flags); | 1567 | clear_bit(Faulty, &rdev->flags); |
1565 | clear_bit(In_sync, &rdev->flags); | 1568 | clear_bit(In_sync, &rdev->flags); |
1569 | clear_bit(Bitmap_sync, &rdev->flags); | ||
1566 | clear_bit(WriteMostly, &rdev->flags); | 1570 | clear_bit(WriteMostly, &rdev->flags); |
1567 | 1571 | ||
1568 | if (mddev->raid_disks == 0) { | 1572 | if (mddev->raid_disks == 0) { |
@@ -1645,6 +1649,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1645 | */ | 1649 | */ |
1646 | if (ev1 < mddev->bitmap->events_cleared) | 1650 | if (ev1 < mddev->bitmap->events_cleared) |
1647 | return 0; | 1651 | return 0; |
1652 | if (ev1 < mddev->events) | ||
1653 | set_bit(Bitmap_sync, &rdev->flags); | ||
1648 | } else { | 1654 | } else { |
1649 | if (ev1 < mddev->events) | 1655 | if (ev1 < mddev->events) |
1650 | /* just a hot-add of a new device, leave raid_disk at -1 */ | 1656 | /* just a hot-add of a new device, leave raid_disk at -1 */ |
@@ -2788,6 +2794,7 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2788 | else | 2794 | else |
2789 | rdev->saved_raid_disk = -1; | 2795 | rdev->saved_raid_disk = -1; |
2790 | clear_bit(In_sync, &rdev->flags); | 2796 | clear_bit(In_sync, &rdev->flags); |
2797 | clear_bit(Bitmap_sync, &rdev->flags); | ||
2791 | err = rdev->mddev->pers-> | 2798 | err = rdev->mddev->pers-> |
2792 | hot_add_disk(rdev->mddev, rdev); | 2799 | hot_add_disk(rdev->mddev, rdev); |
2793 | if (err) { | 2800 | if (err) { |
@@ -5760,6 +5767,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) | |||
5760 | info->raid_disk < mddev->raid_disks) { | 5767 | info->raid_disk < mddev->raid_disks) { |
5761 | rdev->raid_disk = info->raid_disk; | 5768 | rdev->raid_disk = info->raid_disk; |
5762 | set_bit(In_sync, &rdev->flags); | 5769 | set_bit(In_sync, &rdev->flags); |
5770 | clear_bit(Bitmap_sync, &rdev->flags); | ||
5763 | } else | 5771 | } else |
5764 | rdev->raid_disk = -1; | 5772 | rdev->raid_disk = -1; |
5765 | } else | 5773 | } else |
@@ -7706,7 +7714,8 @@ static int remove_and_add_spares(struct mddev *mddev, | |||
7706 | if (test_bit(Faulty, &rdev->flags)) | 7714 | if (test_bit(Faulty, &rdev->flags)) |
7707 | continue; | 7715 | continue; |
7708 | if (mddev->ro && | 7716 | if (mddev->ro && |
7709 | rdev->saved_raid_disk < 0) | 7717 | ! (rdev->saved_raid_disk >= 0 && |
7718 | !test_bit(Bitmap_sync, &rdev->flags))) | ||
7710 | continue; | 7719 | continue; |
7711 | 7720 | ||
7712 | rdev->recovery_offset = 0; | 7721 | rdev->recovery_offset = 0; |
@@ -7787,9 +7796,12 @@ void md_check_recovery(struct mddev *mddev) | |||
7787 | * As we only add devices that are already in-sync, | 7796 | * As we only add devices that are already in-sync, |
7788 | * we can activate the spares immediately. | 7797 | * we can activate the spares immediately. |
7789 | */ | 7798 | */ |
7790 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
7791 | remove_and_add_spares(mddev, NULL); | 7799 | remove_and_add_spares(mddev, NULL); |
7792 | mddev->pers->spare_active(mddev); | 7800 | /* There is no thread, but we need to call |
7801 | * ->spare_active and clear saved_raid_disk | ||
7802 | */ | ||
7803 | md_reap_sync_thread(mddev); | ||
7804 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
7793 | goto unlock; | 7805 | goto unlock; |
7794 | } | 7806 | } |
7795 | 7807 | ||
diff --git a/drivers/md/md.h b/drivers/md/md.h index 2f5cc8a7ef3e..0095ec84ffc7 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
@@ -129,6 +129,9 @@ struct md_rdev { | |||
129 | enum flag_bits { | 129 | enum flag_bits { |
130 | Faulty, /* device is known to have a fault */ | 130 | Faulty, /* device is known to have a fault */ |
131 | In_sync, /* device is in_sync with rest of array */ | 131 | In_sync, /* device is in_sync with rest of array */ |
132 | Bitmap_sync, /* ..actually, not quite In_sync. Need a | ||
133 | * bitmap-based recovery to get fully in sync | ||
134 | */ | ||
132 | Unmerged, /* device is being added to array and should | 135 | Unmerged, /* device is being added to array and should |
133 | * be considerred for bvec_merge_fn but not | 136 | * be considerred for bvec_merge_fn but not |
134 | * yet for actual IO | 137 | * yet for actual IO |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1e5a540995e9..a49cfcc7a343 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -924,9 +924,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio) | |||
924 | conf->next_window_requests++; | 924 | conf->next_window_requests++; |
925 | else | 925 | else |
926 | conf->current_window_requests++; | 926 | conf->current_window_requests++; |
927 | } | ||
928 | if (bio->bi_sector >= conf->start_next_window) | ||
929 | sector = conf->start_next_window; | 927 | sector = conf->start_next_window; |
928 | } | ||
930 | } | 929 | } |
931 | 930 | ||
932 | conf->nr_pending++; | 931 | conf->nr_pending++; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c504e8389e69..06eeb99ea6fc 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1319,7 +1319,7 @@ read_again: | |||
1319 | /* Could not read all from this device, so we will | 1319 | /* Could not read all from this device, so we will |
1320 | * need another r10_bio. | 1320 | * need another r10_bio. |
1321 | */ | 1321 | */ |
1322 | sectors_handled = (r10_bio->sectors + max_sectors | 1322 | sectors_handled = (r10_bio->sector + max_sectors |
1323 | - bio->bi_sector); | 1323 | - bio->bi_sector); |
1324 | r10_bio->sectors = max_sectors; | 1324 | r10_bio->sectors = max_sectors; |
1325 | spin_lock_irq(&conf->device_lock); | 1325 | spin_lock_irq(&conf->device_lock); |
@@ -1327,7 +1327,7 @@ read_again: | |||
1327 | bio->bi_phys_segments = 2; | 1327 | bio->bi_phys_segments = 2; |
1328 | else | 1328 | else |
1329 | bio->bi_phys_segments++; | 1329 | bio->bi_phys_segments++; |
1330 | spin_unlock(&conf->device_lock); | 1330 | spin_unlock_irq(&conf->device_lock); |
1331 | /* Cannot call generic_make_request directly | 1331 | /* Cannot call generic_make_request directly |
1332 | * as that will be queued in __generic_make_request | 1332 | * as that will be queued in __generic_make_request |
1333 | * and subsequent mempool_alloc might block | 1333 | * and subsequent mempool_alloc might block |
@@ -3218,10 +3218,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
3218 | if (j == conf->copies) { | 3218 | if (j == conf->copies) { |
3219 | /* Cannot recover, so abort the recovery or | 3219 | /* Cannot recover, so abort the recovery or |
3220 | * record a bad block */ | 3220 | * record a bad block */ |
3221 | put_buf(r10_bio); | ||
3222 | if (rb2) | ||
3223 | atomic_dec(&rb2->remaining); | ||
3224 | r10_bio = rb2; | ||
3225 | if (any_working) { | 3221 | if (any_working) { |
3226 | /* problem is that there are bad blocks | 3222 | /* problem is that there are bad blocks |
3227 | * on other device(s) | 3223 | * on other device(s) |
@@ -3253,6 +3249,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
3253 | mirror->recovery_disabled | 3249 | mirror->recovery_disabled |
3254 | = mddev->recovery_disabled; | 3250 | = mddev->recovery_disabled; |
3255 | } | 3251 | } |
3252 | put_buf(r10_bio); | ||
3253 | if (rb2) | ||
3254 | atomic_dec(&rb2->remaining); | ||
3255 | r10_bio = rb2; | ||
3256 | break; | 3256 | break; |
3257 | } | 3257 | } |
3258 | } | 3258 | } |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index cc055da02e2a..cbb15716a5db 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -687,7 +687,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector, | |||
687 | } else { | 687 | } else { |
688 | if (!test_bit(STRIPE_HANDLE, &sh->state)) | 688 | if (!test_bit(STRIPE_HANDLE, &sh->state)) |
689 | atomic_inc(&conf->active_stripes); | 689 | atomic_inc(&conf->active_stripes); |
690 | BUG_ON(list_empty(&sh->lru)); | 690 | BUG_ON(list_empty(&sh->lru) && |
691 | !test_bit(STRIPE_EXPANDING, &sh->state)); | ||
691 | list_del_init(&sh->lru); | 692 | list_del_init(&sh->lru); |
692 | if (sh->group) { | 693 | if (sh->group) { |
693 | sh->group->stripes_cnt--; | 694 | sh->group->stripes_cnt--; |
@@ -3608,7 +3609,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
3608 | */ | 3609 | */ |
3609 | set_bit(R5_Insync, &dev->flags); | 3610 | set_bit(R5_Insync, &dev->flags); |
3610 | 3611 | ||
3611 | if (rdev && test_bit(R5_WriteError, &dev->flags)) { | 3612 | if (test_bit(R5_WriteError, &dev->flags)) { |
3612 | /* This flag does not apply to '.replacement' | 3613 | /* This flag does not apply to '.replacement' |
3613 | * only to .rdev, so make sure to check that*/ | 3614 | * only to .rdev, so make sure to check that*/ |
3614 | struct md_rdev *rdev2 = rcu_dereference( | 3615 | struct md_rdev *rdev2 = rcu_dereference( |
@@ -3621,7 +3622,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
3621 | } else | 3622 | } else |
3622 | clear_bit(R5_WriteError, &dev->flags); | 3623 | clear_bit(R5_WriteError, &dev->flags); |
3623 | } | 3624 | } |
3624 | if (rdev && test_bit(R5_MadeGood, &dev->flags)) { | 3625 | if (test_bit(R5_MadeGood, &dev->flags)) { |
3625 | /* This flag does not apply to '.replacement' | 3626 | /* This flag does not apply to '.replacement' |
3626 | * only to .rdev, so make sure to check that*/ | 3627 | * only to .rdev, so make sure to check that*/ |
3627 | struct md_rdev *rdev2 = rcu_dereference( | 3628 | struct md_rdev *rdev2 = rcu_dereference( |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4b8c58b0ec24..6191b551a0e8 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1763,7 +1763,7 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
1763 | } | 1763 | } |
1764 | 1764 | ||
1765 | if (all) { | 1765 | if (all) { |
1766 | rcu_assign_pointer(bond->curr_active_slave, NULL); | 1766 | RCU_INIT_POINTER(bond->curr_active_slave, NULL); |
1767 | } else if (oldcurrent == slave) { | 1767 | } else if (oldcurrent == slave) { |
1768 | /* | 1768 | /* |
1769 | * Note that we hold RTNL over this sequence, so there | 1769 | * Note that we hold RTNL over this sequence, so there |
diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c index fb3dd4399cf3..f615fdec0f1b 100644 --- a/drivers/net/ethernet/8390/hydra.c +++ b/drivers/net/ethernet/8390/hydra.c | |||
@@ -113,7 +113,7 @@ static const struct net_device_ops hydra_netdev_ops = { | |||
113 | static int hydra_init(struct zorro_dev *z) | 113 | static int hydra_init(struct zorro_dev *z) |
114 | { | 114 | { |
115 | struct net_device *dev; | 115 | struct net_device *dev; |
116 | unsigned long board = ZTWO_VADDR(z->resource.start); | 116 | unsigned long board = (unsigned long)ZTWO_VADDR(z->resource.start); |
117 | unsigned long ioaddr = board+HYDRA_NIC_BASE; | 117 | unsigned long ioaddr = board+HYDRA_NIC_BASE; |
118 | const char name[] = "NE2000"; | 118 | const char name[] = "NE2000"; |
119 | int start_page, stop_page; | 119 | int start_page, stop_page; |
diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c index 85ec4c2d2645..ae2a12b7db62 100644 --- a/drivers/net/ethernet/8390/zorro8390.c +++ b/drivers/net/ethernet/8390/zorro8390.c | |||
@@ -287,7 +287,7 @@ static const struct net_device_ops zorro8390_netdev_ops = { | |||
287 | }; | 287 | }; |
288 | 288 | ||
289 | static int zorro8390_init(struct net_device *dev, unsigned long board, | 289 | static int zorro8390_init(struct net_device *dev, unsigned long board, |
290 | const char *name, unsigned long ioaddr) | 290 | const char *name, void __iomem *ioaddr) |
291 | { | 291 | { |
292 | int i; | 292 | int i; |
293 | int err; | 293 | int err; |
@@ -354,7 +354,7 @@ static int zorro8390_init(struct net_device *dev, unsigned long board, | |||
354 | start_page = NESM_START_PG; | 354 | start_page = NESM_START_PG; |
355 | stop_page = NESM_STOP_PG; | 355 | stop_page = NESM_STOP_PG; |
356 | 356 | ||
357 | dev->base_addr = ioaddr; | 357 | dev->base_addr = (unsigned long)ioaddr; |
358 | dev->irq = IRQ_AMIGA_PORTS; | 358 | dev->irq = IRQ_AMIGA_PORTS; |
359 | 359 | ||
360 | /* Install the Interrupt handler */ | 360 | /* Install the Interrupt handler */ |
diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index 0866e7627433..56139184b801 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/zorro.h> | 57 | #include <linux/zorro.h> |
58 | #include <linux/bitops.h> | 58 | #include <linux/bitops.h> |
59 | 59 | ||
60 | #include <asm/byteorder.h> | ||
60 | #include <asm/irq.h> | 61 | #include <asm/irq.h> |
61 | #include <asm/amigaints.h> | 62 | #include <asm/amigaints.h> |
62 | #include <asm/amigahw.h> | 63 | #include <asm/amigahw.h> |
@@ -678,6 +679,7 @@ static int a2065_init_one(struct zorro_dev *z, | |||
678 | unsigned long base_addr = board + A2065_LANCE; | 679 | unsigned long base_addr = board + A2065_LANCE; |
679 | unsigned long mem_start = board + A2065_RAM; | 680 | unsigned long mem_start = board + A2065_RAM; |
680 | struct resource *r1, *r2; | 681 | struct resource *r1, *r2; |
682 | u32 serial; | ||
681 | int err; | 683 | int err; |
682 | 684 | ||
683 | r1 = request_mem_region(base_addr, sizeof(struct lance_regs), | 685 | r1 = request_mem_region(base_addr, sizeof(struct lance_regs), |
@@ -702,6 +704,7 @@ static int a2065_init_one(struct zorro_dev *z, | |||
702 | r1->name = dev->name; | 704 | r1->name = dev->name; |
703 | r2->name = dev->name; | 705 | r2->name = dev->name; |
704 | 706 | ||
707 | serial = be32_to_cpu(z->rom.er_SerialNumber); | ||
705 | dev->dev_addr[0] = 0x00; | 708 | dev->dev_addr[0] = 0x00; |
706 | if (z->id != ZORRO_PROD_AMERISTAR_A2065) { /* Commodore */ | 709 | if (z->id != ZORRO_PROD_AMERISTAR_A2065) { /* Commodore */ |
707 | dev->dev_addr[1] = 0x80; | 710 | dev->dev_addr[1] = 0x80; |
@@ -710,11 +713,11 @@ static int a2065_init_one(struct zorro_dev *z, | |||
710 | dev->dev_addr[1] = 0x00; | 713 | dev->dev_addr[1] = 0x00; |
711 | dev->dev_addr[2] = 0x9f; | 714 | dev->dev_addr[2] = 0x9f; |
712 | } | 715 | } |
713 | dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff; | 716 | dev->dev_addr[3] = (serial >> 16) & 0xff; |
714 | dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff; | 717 | dev->dev_addr[4] = (serial >> 8) & 0xff; |
715 | dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; | 718 | dev->dev_addr[5] = serial & 0xff; |
716 | dev->base_addr = ZTWO_VADDR(base_addr); | 719 | dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr); |
717 | dev->mem_start = ZTWO_VADDR(mem_start); | 720 | dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start); |
718 | dev->mem_end = dev->mem_start + A2065_RAM_SIZE; | 721 | dev->mem_end = dev->mem_start + A2065_RAM_SIZE; |
719 | 722 | ||
720 | priv->ll = (volatile struct lance_regs *)dev->base_addr; | 723 | priv->ll = (volatile struct lance_regs *)dev->base_addr; |
diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c index c178eb4c8166..b08101b31b8b 100644 --- a/drivers/net/ethernet/amd/ariadne.c +++ b/drivers/net/ethernet/amd/ariadne.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/zorro.h> | 51 | #include <linux/zorro.h> |
52 | #include <linux/bitops.h> | 52 | #include <linux/bitops.h> |
53 | 53 | ||
54 | #include <asm/byteorder.h> | ||
54 | #include <asm/amigaints.h> | 55 | #include <asm/amigaints.h> |
55 | #include <asm/amigahw.h> | 56 | #include <asm/amigahw.h> |
56 | #include <asm/irq.h> | 57 | #include <asm/irq.h> |
@@ -718,6 +719,7 @@ static int ariadne_init_one(struct zorro_dev *z, | |||
718 | struct resource *r1, *r2; | 719 | struct resource *r1, *r2; |
719 | struct net_device *dev; | 720 | struct net_device *dev; |
720 | struct ariadne_private *priv; | 721 | struct ariadne_private *priv; |
722 | u32 serial; | ||
721 | int err; | 723 | int err; |
722 | 724 | ||
723 | r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960"); | 725 | r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960"); |
@@ -741,14 +743,15 @@ static int ariadne_init_one(struct zorro_dev *z, | |||
741 | r1->name = dev->name; | 743 | r1->name = dev->name; |
742 | r2->name = dev->name; | 744 | r2->name = dev->name; |
743 | 745 | ||
746 | serial = be32_to_cpu(z->rom.er_SerialNumber); | ||
744 | dev->dev_addr[0] = 0x00; | 747 | dev->dev_addr[0] = 0x00; |
745 | dev->dev_addr[1] = 0x60; | 748 | dev->dev_addr[1] = 0x60; |
746 | dev->dev_addr[2] = 0x30; | 749 | dev->dev_addr[2] = 0x30; |
747 | dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff; | 750 | dev->dev_addr[3] = (serial >> 16) & 0xff; |
748 | dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff; | 751 | dev->dev_addr[4] = (serial >> 8) & 0xff; |
749 | dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; | 752 | dev->dev_addr[5] = serial & 0xff; |
750 | dev->base_addr = ZTWO_VADDR(base_addr); | 753 | dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr); |
751 | dev->mem_start = ZTWO_VADDR(mem_start); | 754 | dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start); |
752 | dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE; | 755 | dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE; |
753 | 756 | ||
754 | dev->netdev_ops = &ariadne_netdev_ops; | 757 | dev->netdev_ops = &ariadne_netdev_ops; |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 8b3107b2fcc1..0067b975873f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -12942,25 +12942,26 @@ static void __bnx2x_remove(struct pci_dev *pdev, | |||
12942 | pci_set_power_state(pdev, PCI_D3hot); | 12942 | pci_set_power_state(pdev, PCI_D3hot); |
12943 | } | 12943 | } |
12944 | 12944 | ||
12945 | if (bp->regview) | 12945 | if (remove_netdev) { |
12946 | iounmap(bp->regview); | 12946 | if (bp->regview) |
12947 | iounmap(bp->regview); | ||
12947 | 12948 | ||
12948 | /* for vf doorbells are part of the regview and were unmapped along with | 12949 | /* For vfs, doorbells are part of the regview and were unmapped |
12949 | * it. FW is only loaded by PF. | 12950 | * along with it. FW is only loaded by PF. |
12950 | */ | 12951 | */ |
12951 | if (IS_PF(bp)) { | 12952 | if (IS_PF(bp)) { |
12952 | if (bp->doorbells) | 12953 | if (bp->doorbells) |
12953 | iounmap(bp->doorbells); | 12954 | iounmap(bp->doorbells); |
12954 | 12955 | ||
12955 | bnx2x_release_firmware(bp); | 12956 | bnx2x_release_firmware(bp); |
12956 | } | 12957 | } |
12957 | bnx2x_free_mem_bp(bp); | 12958 | bnx2x_free_mem_bp(bp); |
12958 | 12959 | ||
12959 | if (remove_netdev) | ||
12960 | free_netdev(dev); | 12960 | free_netdev(dev); |
12961 | 12961 | ||
12962 | if (atomic_read(&pdev->enable_cnt) == 1) | 12962 | if (atomic_read(&pdev->enable_cnt) == 1) |
12963 | pci_release_regions(pdev); | 12963 | pci_release_regions(pdev); |
12964 | } | ||
12964 | 12965 | ||
12965 | pci_disable_device(pdev); | 12966 | pci_disable_device(pdev); |
12966 | } | 12967 | } |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c index cb05be905def..81e8402a74b4 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c | |||
@@ -423,7 +423,7 @@ u64 cxgb4_select_ntuple(struct net_device *dev, | |||
423 | * in the Compressed Filter Tuple. | 423 | * in the Compressed Filter Tuple. |
424 | */ | 424 | */ |
425 | if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE) | 425 | if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE) |
426 | ntuple |= (F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift; | 426 | ntuple |= (u64)(F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift; |
427 | 427 | ||
428 | if (tp->port_shift >= 0) | 428 | if (tp->port_shift >= 0) |
429 | ntuple |= (u64)l2t->lport << tp->port_shift; | 429 | ntuple |= (u64)l2t->lport << tp->port_shift; |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index bf40fdaecfa3..a37039d353c5 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -1776,6 +1776,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) | |||
1776 | struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; | 1776 | struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; |
1777 | struct be_queue_info *rxq = &rxo->q; | 1777 | struct be_queue_info *rxq = &rxo->q; |
1778 | struct page *pagep = NULL; | 1778 | struct page *pagep = NULL; |
1779 | struct device *dev = &adapter->pdev->dev; | ||
1779 | struct be_eth_rx_d *rxd; | 1780 | struct be_eth_rx_d *rxd; |
1780 | u64 page_dmaaddr = 0, frag_dmaaddr; | 1781 | u64 page_dmaaddr = 0, frag_dmaaddr; |
1781 | u32 posted, page_offset = 0; | 1782 | u32 posted, page_offset = 0; |
@@ -1788,9 +1789,15 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) | |||
1788 | rx_stats(rxo)->rx_post_fail++; | 1789 | rx_stats(rxo)->rx_post_fail++; |
1789 | break; | 1790 | break; |
1790 | } | 1791 | } |
1791 | page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep, | 1792 | page_dmaaddr = dma_map_page(dev, pagep, 0, |
1792 | 0, adapter->big_page_size, | 1793 | adapter->big_page_size, |
1793 | DMA_FROM_DEVICE); | 1794 | DMA_FROM_DEVICE); |
1795 | if (dma_mapping_error(dev, page_dmaaddr)) { | ||
1796 | put_page(pagep); | ||
1797 | pagep = NULL; | ||
1798 | rx_stats(rxo)->rx_post_fail++; | ||
1799 | break; | ||
1800 | } | ||
1794 | page_info->page_offset = 0; | 1801 | page_info->page_offset = 0; |
1795 | } else { | 1802 | } else { |
1796 | get_page(pagep); | 1803 | get_page(pagep); |
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index c30d41d6e426..6d14eea17918 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c | |||
@@ -6174,7 +6174,7 @@ static int __e1000_resume(struct pci_dev *pdev) | |||
6174 | return 0; | 6174 | return 0; |
6175 | } | 6175 | } |
6176 | 6176 | ||
6177 | #ifdef CONFIG_PM | 6177 | #ifdef CONFIG_PM_SLEEP |
6178 | static int e1000_suspend(struct device *dev) | 6178 | static int e1000_suspend(struct device *dev) |
6179 | { | 6179 | { |
6180 | struct pci_dev *pdev = to_pci_dev(dev); | 6180 | struct pci_dev *pdev = to_pci_dev(dev); |
@@ -6193,7 +6193,7 @@ static int e1000_resume(struct device *dev) | |||
6193 | 6193 | ||
6194 | return __e1000_resume(pdev); | 6194 | return __e1000_resume(pdev); |
6195 | } | 6195 | } |
6196 | #endif /* CONFIG_PM */ | 6196 | #endif /* CONFIG_PM_SLEEP */ |
6197 | 6197 | ||
6198 | #ifdef CONFIG_PM_RUNTIME | 6198 | #ifdef CONFIG_PM_RUNTIME |
6199 | static int e1000_runtime_suspend(struct device *dev) | 6199 | static int e1000_runtime_suspend(struct device *dev) |
@@ -7015,13 +7015,11 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { | |||
7015 | }; | 7015 | }; |
7016 | MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); | 7016 | MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); |
7017 | 7017 | ||
7018 | #ifdef CONFIG_PM | ||
7019 | static const struct dev_pm_ops e1000_pm_ops = { | 7018 | static const struct dev_pm_ops e1000_pm_ops = { |
7020 | SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume) | 7019 | SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume) |
7021 | SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume, | 7020 | SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume, |
7022 | e1000_idle) | 7021 | e1000_idle) |
7023 | }; | 7022 | }; |
7024 | #endif | ||
7025 | 7023 | ||
7026 | /* PCI Device API Driver */ | 7024 | /* PCI Device API Driver */ |
7027 | static struct pci_driver e1000_driver = { | 7025 | static struct pci_driver e1000_driver = { |
@@ -7029,11 +7027,9 @@ static struct pci_driver e1000_driver = { | |||
7029 | .id_table = e1000_pci_tbl, | 7027 | .id_table = e1000_pci_tbl, |
7030 | .probe = e1000_probe, | 7028 | .probe = e1000_probe, |
7031 | .remove = e1000_remove, | 7029 | .remove = e1000_remove, |
7032 | #ifdef CONFIG_PM | ||
7033 | .driver = { | 7030 | .driver = { |
7034 | .pm = &e1000_pm_ops, | 7031 | .pm = &e1000_pm_ops, |
7035 | }, | 7032 | }, |
7036 | #endif | ||
7037 | .shutdown = e1000_shutdown, | 7033 | .shutdown = e1000_shutdown, |
7038 | .err_handler = &e1000_err_handler | 7034 | .err_handler = &e1000_err_handler |
7039 | }; | 7035 | }; |
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index 346a4e025c34..04b3ec1352f1 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/bitrev.h> | 52 | #include <linux/bitrev.h> |
53 | #include <linux/slab.h> | 53 | #include <linux/slab.h> |
54 | 54 | ||
55 | #include <asm/bootinfo.h> | ||
56 | #include <asm/pgtable.h> | 55 | #include <asm/pgtable.h> |
57 | #include <asm/io.h> | 56 | #include <asm/io.h> |
58 | #include <asm/hwtest.h> | 57 | #include <asm/hwtest.h> |
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 449f506d2e8f..f705aeeba767 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c | |||
@@ -4765,6 +4765,8 @@ static int qlge_probe(struct pci_dev *pdev, | |||
4765 | NETIF_F_RXCSUM; | 4765 | NETIF_F_RXCSUM; |
4766 | ndev->features = ndev->hw_features; | 4766 | ndev->features = ndev->hw_features; |
4767 | ndev->vlan_features = ndev->hw_features; | 4767 | ndev->vlan_features = ndev->hw_features; |
4768 | /* vlan gets same features (except vlan filter) */ | ||
4769 | ndev->vlan_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; | ||
4768 | 4770 | ||
4769 | if (test_bit(QL_DMA64, &qdev->flags)) | 4771 | if (test_bit(QL_DMA64, &qdev->flags)) |
4770 | ndev->features |= NETIF_F_HIGHDMA; | 4772 | ndev->features |= NETIF_F_HIGHDMA; |
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index cce6c4bc556a..ef312bc6b865 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c | |||
@@ -1618,6 +1618,7 @@ static void rhine_reset_task(struct work_struct *work) | |||
1618 | goto out_unlock; | 1618 | goto out_unlock; |
1619 | 1619 | ||
1620 | napi_disable(&rp->napi); | 1620 | napi_disable(&rp->napi); |
1621 | netif_tx_disable(dev); | ||
1621 | spin_lock_bh(&rp->lock); | 1622 | spin_lock_bh(&rp->lock); |
1622 | 1623 | ||
1623 | /* clear all descriptors */ | 1624 | /* clear all descriptors */ |
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 14aa48fa8d7e..e80219877730 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c | |||
@@ -614,6 +614,18 @@ static const struct usb_device_id products[] = { | |||
614 | USB_DEVICE(0x0a46, 0x9621), /* DM9621A USB to Fast Ethernet Adapter */ | 614 | USB_DEVICE(0x0a46, 0x9621), /* DM9621A USB to Fast Ethernet Adapter */ |
615 | .driver_info = (unsigned long)&dm9601_info, | 615 | .driver_info = (unsigned long)&dm9601_info, |
616 | }, | 616 | }, |
617 | { | ||
618 | USB_DEVICE(0x0a46, 0x9622), /* DM9622 USB to Fast Ethernet Adapter */ | ||
619 | .driver_info = (unsigned long)&dm9601_info, | ||
620 | }, | ||
621 | { | ||
622 | USB_DEVICE(0x0a46, 0x0269), /* DM962OA USB to Fast Ethernet Adapter */ | ||
623 | .driver_info = (unsigned long)&dm9601_info, | ||
624 | }, | ||
625 | { | ||
626 | USB_DEVICE(0x0a46, 0x1269), /* DM9621A USB to Fast Ethernet Adapter */ | ||
627 | .driver_info = (unsigned long)&dm9601_info, | ||
628 | }, | ||
617 | {}, // END | 629 | {}, // END |
618 | }; | 630 | }; |
619 | 631 | ||
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 8494bb53ebdc..aba04f561760 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -1245,7 +1245,7 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb) | |||
1245 | return -ENOMEM; | 1245 | return -ENOMEM; |
1246 | 1246 | ||
1247 | urb->num_sgs = num_sgs; | 1247 | urb->num_sgs = num_sgs; |
1248 | sg_init_table(urb->sg, urb->num_sgs); | 1248 | sg_init_table(urb->sg, urb->num_sgs + 1); |
1249 | 1249 | ||
1250 | sg_set_buf(&urb->sg[s++], skb->data, skb_headlen(skb)); | 1250 | sg_set_buf(&urb->sg[s++], skb->data, skb_headlen(skb)); |
1251 | total_len += skb_headlen(skb); | 1251 | total_len += skb_headlen(skb); |
diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c index 7578d79b3688..2f650f68af14 100644 --- a/drivers/parport/parport_mfc3.c +++ b/drivers/parport/parport_mfc3.c | |||
@@ -300,7 +300,7 @@ static int __init parport_mfc3_init(void) | |||
300 | if (!request_mem_region(piabase, sizeof(struct pia), "PIA")) | 300 | if (!request_mem_region(piabase, sizeof(struct pia), "PIA")) |
301 | continue; | 301 | continue; |
302 | 302 | ||
303 | pp = (struct pia *)ZTWO_VADDR(piabase); | 303 | pp = ZTWO_VADDR(piabase); |
304 | pp->crb = 0; | 304 | pp->crb = 0; |
305 | pp->pddrb = 255; /* all data pins output */ | 305 | pp->pddrb = 255; /* all data pins output */ |
306 | pp->crb = PIA_DDR|32|8; | 306 | pp->crb = PIA_DDR|32|8; |
diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c index 114f5ef4b73a..2832576d8b12 100644 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ b/drivers/pinctrl/pinctrl-baytrail.c | |||
@@ -512,7 +512,6 @@ static const struct dev_pm_ops byt_gpio_pm_ops = { | |||
512 | 512 | ||
513 | static const struct acpi_device_id byt_gpio_acpi_match[] = { | 513 | static const struct acpi_device_id byt_gpio_acpi_match[] = { |
514 | { "INT33B2", 0 }, | 514 | { "INT33B2", 0 }, |
515 | { "INT33FC", 0 }, | ||
516 | { } | 515 | { } |
517 | }; | 516 | }; |
518 | MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match); | 517 | MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match); |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f14876256a4a..a2325bc5e497 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -34,11 +34,11 @@ | |||
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | ||
38 | #include <linux/log2.h> | 37 | #include <linux/log2.h> |
39 | #include <linux/pm.h> | 38 | #include <linux/pm.h> |
40 | #include <linux/of.h> | 39 | #include <linux/of.h> |
41 | #include <linux/of_platform.h> | 40 | #include <linux/of_platform.h> |
41 | #include <linux/dmi.h> | ||
42 | 42 | ||
43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
44 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
@@ -377,6 +377,51 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
377 | return 0; | 377 | return 0; |
378 | } | 378 | } |
379 | 379 | ||
380 | /* | ||
381 | * Do not disable RTC alarm on shutdown - workaround for b0rked BIOSes. | ||
382 | */ | ||
383 | static bool alarm_disable_quirk; | ||
384 | |||
385 | static int __init set_alarm_disable_quirk(const struct dmi_system_id *id) | ||
386 | { | ||
387 | alarm_disable_quirk = true; | ||
388 | pr_info("rtc-cmos: BIOS has alarm-disable quirk. "); | ||
389 | pr_info("RTC alarms disabled\n"); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static const struct dmi_system_id rtc_quirks[] __initconst = { | ||
394 | /* https://bugzilla.novell.com/show_bug.cgi?id=805740 */ | ||
395 | { | ||
396 | .callback = set_alarm_disable_quirk, | ||
397 | .ident = "IBM Truman", | ||
398 | .matches = { | ||
399 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
400 | DMI_MATCH(DMI_PRODUCT_NAME, "4852570"), | ||
401 | }, | ||
402 | }, | ||
403 | /* https://bugzilla.novell.com/show_bug.cgi?id=812592 */ | ||
404 | { | ||
405 | .callback = set_alarm_disable_quirk, | ||
406 | .ident = "Gigabyte GA-990XA-UD3", | ||
407 | .matches = { | ||
408 | DMI_MATCH(DMI_SYS_VENDOR, | ||
409 | "Gigabyte Technology Co., Ltd."), | ||
410 | DMI_MATCH(DMI_PRODUCT_NAME, "GA-990XA-UD3"), | ||
411 | }, | ||
412 | }, | ||
413 | /* http://permalink.gmane.org/gmane.linux.kernel/1604474 */ | ||
414 | { | ||
415 | .callback = set_alarm_disable_quirk, | ||
416 | .ident = "Toshiba Satellite L300", | ||
417 | .matches = { | ||
418 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
419 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), | ||
420 | }, | ||
421 | }, | ||
422 | {} | ||
423 | }; | ||
424 | |||
380 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | 425 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) |
381 | { | 426 | { |
382 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 427 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
@@ -385,6 +430,9 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
385 | if (!is_valid_irq(cmos->irq)) | 430 | if (!is_valid_irq(cmos->irq)) |
386 | return -EINVAL; | 431 | return -EINVAL; |
387 | 432 | ||
433 | if (alarm_disable_quirk) | ||
434 | return 0; | ||
435 | |||
388 | spin_lock_irqsave(&rtc_lock, flags); | 436 | spin_lock_irqsave(&rtc_lock, flags); |
389 | 437 | ||
390 | if (enabled) | 438 | if (enabled) |
@@ -1157,6 +1205,8 @@ static int __init cmos_init(void) | |||
1157 | platform_driver_registered = true; | 1205 | platform_driver_registered = true; |
1158 | } | 1206 | } |
1159 | 1207 | ||
1208 | dmi_check_system(rtc_quirks); | ||
1209 | |||
1160 | if (retval == 0) | 1210 | if (retval == 0) |
1161 | return 0; | 1211 | return 0; |
1162 | 1212 | ||
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index f302efa937ef..1eef0f586950 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -3386,7 +3386,7 @@ int dasd_generic_set_offline(struct ccw_device *cdev) | |||
3386 | 3386 | ||
3387 | if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) { | 3387 | if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) { |
3388 | /* | 3388 | /* |
3389 | * safe offline allready running | 3389 | * safe offline already running |
3390 | * could only be called by normal offline so safe_offline flag | 3390 | * could only be called by normal offline so safe_offline flag |
3391 | * needs to be removed to run normal offline and kill all I/O | 3391 | * needs to be removed to run normal offline and kill all I/O |
3392 | */ | 3392 | */ |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 6fbe09686d18..fea76aed9eea 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -183,7 +183,6 @@ extern unsigned long sclp_console_full; | |||
183 | extern u8 sclp_fac84; | 183 | extern u8 sclp_fac84; |
184 | extern unsigned long long sclp_rzm; | 184 | extern unsigned long long sclp_rzm; |
185 | extern unsigned long long sclp_rnmax; | 185 | extern unsigned long long sclp_rnmax; |
186 | extern __initdata int sclp_early_read_info_sccb_valid; | ||
187 | 186 | ||
188 | /* useful inlines */ | 187 | /* useful inlines */ |
189 | 188 | ||
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index eaa21d542c5c..cb3c4e05a385 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
@@ -455,8 +455,6 @@ static int __init sclp_detect_standby_memory(void) | |||
455 | 455 | ||
456 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ | 456 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ |
457 | return 0; | 457 | return 0; |
458 | if (!sclp_early_read_info_sccb_valid) | ||
459 | return 0; | ||
460 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) | 458 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) |
461 | return 0; | 459 | return 0; |
462 | rc = -ENOMEM; | 460 | rc = -ENOMEM; |
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 1465e9563101..82f2c389b4d1 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c | |||
@@ -35,11 +35,12 @@ struct read_info_sccb { | |||
35 | u8 _reserved5[4096 - 112]; /* 112-4095 */ | 35 | u8 _reserved5[4096 - 112]; /* 112-4095 */ |
36 | } __packed __aligned(PAGE_SIZE); | 36 | } __packed __aligned(PAGE_SIZE); |
37 | 37 | ||
38 | static __initdata struct read_info_sccb early_read_info_sccb; | 38 | static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata; |
39 | static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); | 39 | static unsigned int sclp_con_has_vt220 __initdata; |
40 | static unsigned int sclp_con_has_linemode __initdata; | ||
40 | static unsigned long sclp_hsa_size; | 41 | static unsigned long sclp_hsa_size; |
42 | static struct sclp_ipl_info sclp_ipl_info; | ||
41 | 43 | ||
42 | __initdata int sclp_early_read_info_sccb_valid; | ||
43 | u64 sclp_facilities; | 44 | u64 sclp_facilities; |
44 | u8 sclp_fac84; | 45 | u8 sclp_fac84; |
45 | unsigned long long sclp_rzm; | 46 | unsigned long long sclp_rzm; |
@@ -63,15 +64,12 @@ out: | |||
63 | return rc; | 64 | return rc; |
64 | } | 65 | } |
65 | 66 | ||
66 | static void __init sclp_read_info_early(void) | 67 | static int __init sclp_read_info_early(struct read_info_sccb *sccb) |
67 | { | 68 | { |
68 | int rc; | 69 | int rc, i; |
69 | int i; | ||
70 | struct read_info_sccb *sccb; | ||
71 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, | 70 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, |
72 | SCLP_CMDW_READ_SCP_INFO}; | 71 | SCLP_CMDW_READ_SCP_INFO}; |
73 | 72 | ||
74 | sccb = &early_read_info_sccb; | ||
75 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | 73 | for (i = 0; i < ARRAY_SIZE(commands); i++) { |
76 | do { | 74 | do { |
77 | memset(sccb, 0, sizeof(*sccb)); | 75 | memset(sccb, 0, sizeof(*sccb)); |
@@ -83,24 +81,19 @@ static void __init sclp_read_info_early(void) | |||
83 | 81 | ||
84 | if (rc) | 82 | if (rc) |
85 | break; | 83 | break; |
86 | if (sccb->header.response_code == 0x10) { | 84 | if (sccb->header.response_code == 0x10) |
87 | sclp_early_read_info_sccb_valid = 1; | 85 | return 0; |
88 | break; | ||
89 | } | ||
90 | if (sccb->header.response_code != 0x1f0) | 86 | if (sccb->header.response_code != 0x1f0) |
91 | break; | 87 | break; |
92 | } | 88 | } |
89 | return -EIO; | ||
93 | } | 90 | } |
94 | 91 | ||
95 | static void __init sclp_facilities_detect(void) | 92 | static void __init sclp_facilities_detect(struct read_info_sccb *sccb) |
96 | { | 93 | { |
97 | struct read_info_sccb *sccb; | 94 | if (sclp_read_info_early(sccb)) |
98 | |||
99 | sclp_read_info_early(); | ||
100 | if (!sclp_early_read_info_sccb_valid) | ||
101 | return; | 95 | return; |
102 | 96 | ||
103 | sccb = &early_read_info_sccb; | ||
104 | sclp_facilities = sccb->facilities; | 97 | sclp_facilities = sccb->facilities; |
105 | sclp_fac84 = sccb->fac84; | 98 | sclp_fac84 = sccb->fac84; |
106 | if (sccb->fac85 & 0x02) | 99 | if (sccb->fac85 & 0x02) |
@@ -108,30 +101,22 @@ static void __init sclp_facilities_detect(void) | |||
108 | sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; | 101 | sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; |
109 | sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; | 102 | sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; |
110 | sclp_rzm <<= 20; | 103 | sclp_rzm <<= 20; |
104 | |||
105 | /* Save IPL information */ | ||
106 | sclp_ipl_info.is_valid = 1; | ||
107 | if (sccb->flags & 0x2) | ||
108 | sclp_ipl_info.has_dump = 1; | ||
109 | memcpy(&sclp_ipl_info.loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
111 | } | 110 | } |
112 | 111 | ||
113 | bool __init sclp_has_linemode(void) | 112 | bool __init sclp_has_linemode(void) |
114 | { | 113 | { |
115 | struct init_sccb *sccb = (void *) &sccb_early; | 114 | return !!sclp_con_has_linemode; |
116 | |||
117 | if (sccb->header.response_code != 0x20) | ||
118 | return 0; | ||
119 | if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) | ||
120 | return 0; | ||
121 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
122 | return 0; | ||
123 | return 1; | ||
124 | } | 115 | } |
125 | 116 | ||
126 | bool __init sclp_has_vt220(void) | 117 | bool __init sclp_has_vt220(void) |
127 | { | 118 | { |
128 | struct init_sccb *sccb = (void *) &sccb_early; | 119 | return !!sclp_con_has_vt220; |
129 | |||
130 | if (sccb->header.response_code != 0x20) | ||
131 | return 0; | ||
132 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | ||
133 | return 1; | ||
134 | return 0; | ||
135 | } | 120 | } |
136 | 121 | ||
137 | unsigned long long sclp_get_rnmax(void) | 122 | unsigned long long sclp_get_rnmax(void) |
@@ -146,19 +131,12 @@ unsigned long long sclp_get_rzm(void) | |||
146 | 131 | ||
147 | /* | 132 | /* |
148 | * This function will be called after sclp_facilities_detect(), which gets | 133 | * This function will be called after sclp_facilities_detect(), which gets |
149 | * called from early.c code. Therefore the sccb should have valid contents. | 134 | * called from early.c code. The sclp_facilities_detect() function retrieves |
135 | * and saves the IPL information. | ||
150 | */ | 136 | */ |
151 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) | 137 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) |
152 | { | 138 | { |
153 | struct read_info_sccb *sccb; | 139 | *info = sclp_ipl_info; |
154 | |||
155 | if (!sclp_early_read_info_sccb_valid) | ||
156 | return; | ||
157 | sccb = &early_read_info_sccb; | ||
158 | info->is_valid = 1; | ||
159 | if (sccb->flags & 0x2) | ||
160 | info->has_dump = 1; | ||
161 | memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
162 | } | 140 | } |
163 | 141 | ||
164 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) | 142 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) |
@@ -189,11 +167,10 @@ static void __init sccb_init_eq_size(struct sdias_sccb *sccb) | |||
189 | sccb->evbuf.dbs = 1; | 167 | sccb->evbuf.dbs = 1; |
190 | } | 168 | } |
191 | 169 | ||
192 | static int __init sclp_set_event_mask(unsigned long receive_mask, | 170 | static int __init sclp_set_event_mask(struct init_sccb *sccb, |
171 | unsigned long receive_mask, | ||
193 | unsigned long send_mask) | 172 | unsigned long send_mask) |
194 | { | 173 | { |
195 | struct init_sccb *sccb = (void *) &sccb_early; | ||
196 | |||
197 | memset(sccb, 0, sizeof(*sccb)); | 174 | memset(sccb, 0, sizeof(*sccb)); |
198 | sccb->header.length = sizeof(*sccb); | 175 | sccb->header.length = sizeof(*sccb); |
199 | sccb->mask_length = sizeof(sccb_mask_t); | 176 | sccb->mask_length = sizeof(sccb_mask_t); |
@@ -202,10 +179,8 @@ static int __init sclp_set_event_mask(unsigned long receive_mask, | |||
202 | return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); | 179 | return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); |
203 | } | 180 | } |
204 | 181 | ||
205 | static long __init sclp_hsa_size_init(void) | 182 | static long __init sclp_hsa_size_init(struct sdias_sccb *sccb) |
206 | { | 183 | { |
207 | struct sdias_sccb *sccb = (void *) &sccb_early; | ||
208 | |||
209 | sccb_init_eq_size(sccb); | 184 | sccb_init_eq_size(sccb); |
210 | if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) | 185 | if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) |
211 | return -EIO; | 186 | return -EIO; |
@@ -214,10 +189,8 @@ static long __init sclp_hsa_size_init(void) | |||
214 | return 0; | 189 | return 0; |
215 | } | 190 | } |
216 | 191 | ||
217 | static long __init sclp_hsa_copy_wait(void) | 192 | static long __init sclp_hsa_copy_wait(struct sccb_header *sccb) |
218 | { | 193 | { |
219 | struct sccb_header *sccb = (void *) &sccb_early; | ||
220 | |||
221 | memset(sccb, 0, PAGE_SIZE); | 194 | memset(sccb, 0, PAGE_SIZE); |
222 | sccb->length = PAGE_SIZE; | 195 | sccb->length = PAGE_SIZE; |
223 | if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb)) | 196 | if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb)) |
@@ -230,34 +203,62 @@ unsigned long sclp_get_hsa_size(void) | |||
230 | return sclp_hsa_size; | 203 | return sclp_hsa_size; |
231 | } | 204 | } |
232 | 205 | ||
233 | static void __init sclp_hsa_size_detect(void) | 206 | static void __init sclp_hsa_size_detect(void *sccb) |
234 | { | 207 | { |
235 | long size; | 208 | long size; |
236 | 209 | ||
237 | /* First try synchronous interface (LPAR) */ | 210 | /* First try synchronous interface (LPAR) */ |
238 | if (sclp_set_event_mask(0, 0x40000010)) | 211 | if (sclp_set_event_mask(sccb, 0, 0x40000010)) |
239 | return; | 212 | return; |
240 | size = sclp_hsa_size_init(); | 213 | size = sclp_hsa_size_init(sccb); |
241 | if (size < 0) | 214 | if (size < 0) |
242 | return; | 215 | return; |
243 | if (size != 0) | 216 | if (size != 0) |
244 | goto out; | 217 | goto out; |
245 | /* Then try asynchronous interface (z/VM) */ | 218 | /* Then try asynchronous interface (z/VM) */ |
246 | if (sclp_set_event_mask(0x00000010, 0x40000010)) | 219 | if (sclp_set_event_mask(sccb, 0x00000010, 0x40000010)) |
247 | return; | 220 | return; |
248 | size = sclp_hsa_size_init(); | 221 | size = sclp_hsa_size_init(sccb); |
249 | if (size < 0) | 222 | if (size < 0) |
250 | return; | 223 | return; |
251 | size = sclp_hsa_copy_wait(); | 224 | size = sclp_hsa_copy_wait(sccb); |
252 | if (size < 0) | 225 | if (size < 0) |
253 | return; | 226 | return; |
254 | out: | 227 | out: |
255 | sclp_hsa_size = size; | 228 | sclp_hsa_size = size; |
256 | } | 229 | } |
257 | 230 | ||
231 | static unsigned int __init sclp_con_check_linemode(struct init_sccb *sccb) | ||
232 | { | ||
233 | if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) | ||
234 | return 0; | ||
235 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
236 | return 0; | ||
237 | return 1; | ||
238 | } | ||
239 | |||
240 | static void __init sclp_console_detect(struct init_sccb *sccb) | ||
241 | { | ||
242 | if (sccb->header.response_code != 0x20) | ||
243 | return; | ||
244 | |||
245 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | ||
246 | sclp_con_has_vt220 = 1; | ||
247 | |||
248 | if (sclp_con_check_linemode(sccb)) | ||
249 | sclp_con_has_linemode = 1; | ||
250 | } | ||
251 | |||
258 | void __init sclp_early_detect(void) | 252 | void __init sclp_early_detect(void) |
259 | { | 253 | { |
260 | sclp_facilities_detect(); | 254 | void *sccb = &sccb_early; |
261 | sclp_hsa_size_detect(); | 255 | |
262 | sclp_set_event_mask(0, 0); | 256 | sclp_facilities_detect(sccb); |
257 | sclp_hsa_size_detect(sccb); | ||
258 | |||
259 | /* Turn off SCLP event notifications. Also save remote masks in the | ||
260 | * sccb. These are sufficient to detect sclp console capabilities. | ||
261 | */ | ||
262 | sclp_set_event_mask(sccb, 0, 0); | ||
263 | sclp_console_detect(sccb); | ||
263 | } | 264 | } |
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 34629ea913d4..e91b89dc6d1f 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c | |||
@@ -125,10 +125,7 @@ static void tty3270_resize_work(struct work_struct *work); | |||
125 | */ | 125 | */ |
126 | static void tty3270_set_timer(struct tty3270 *tp, int expires) | 126 | static void tty3270_set_timer(struct tty3270 *tp, int expires) |
127 | { | 127 | { |
128 | if (expires == 0) | 128 | mod_timer(&tp->timer, jiffies + expires); |
129 | del_timer(&tp->timer); | ||
130 | else | ||
131 | mod_timer(&tp->timer, jiffies + expires); | ||
132 | } | 129 | } |
133 | 130 | ||
134 | /* | 131 | /* |
@@ -744,7 +741,6 @@ tty3270_free_view(struct tty3270 *tp) | |||
744 | { | 741 | { |
745 | int pages; | 742 | int pages; |
746 | 743 | ||
747 | del_timer_sync(&tp->timer); | ||
748 | kbd_free(tp->kbd); | 744 | kbd_free(tp->kbd); |
749 | raw3270_request_free(tp->kreset); | 745 | raw3270_request_free(tp->kreset); |
750 | raw3270_request_free(tp->read); | 746 | raw3270_request_free(tp->read); |
@@ -877,6 +873,7 @@ tty3270_free(struct raw3270_view *view) | |||
877 | { | 873 | { |
878 | struct tty3270 *tp = container_of(view, struct tty3270, view); | 874 | struct tty3270 *tp = container_of(view, struct tty3270, view); |
879 | 875 | ||
876 | del_timer_sync(&tp->timer); | ||
880 | tty3270_free_screen(tp->screen, tp->view.rows); | 877 | tty3270_free_screen(tp->screen, tp->view.rows); |
881 | tty3270_free_view(tp); | 878 | tty3270_free_view(tp); |
882 | } | 879 | } |
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index a9fe3de2dec1..b3f791b2c1f8 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c | |||
@@ -260,16 +260,16 @@ static int blacklist_parse_proc_parameters(char *buf) | |||
260 | 260 | ||
261 | parm = strsep(&buf, " "); | 261 | parm = strsep(&buf, " "); |
262 | 262 | ||
263 | if (strcmp("free", parm) == 0) | 263 | if (strcmp("free", parm) == 0) { |
264 | rc = blacklist_parse_parameters(buf, free, 0); | 264 | rc = blacklist_parse_parameters(buf, free, 0); |
265 | else if (strcmp("add", parm) == 0) | 265 | css_schedule_eval_all_unreg(0); |
266 | } else if (strcmp("add", parm) == 0) | ||
266 | rc = blacklist_parse_parameters(buf, add, 0); | 267 | rc = blacklist_parse_parameters(buf, add, 0); |
267 | else if (strcmp("purge", parm) == 0) | 268 | else if (strcmp("purge", parm) == 0) |
268 | return ccw_purge_blacklisted(); | 269 | return ccw_purge_blacklisted(); |
269 | else | 270 | else |
270 | return -EINVAL; | 271 | return -EINVAL; |
271 | 272 | ||
272 | css_schedule_reprobe(); | ||
273 | 273 | ||
274 | return rc; | 274 | return rc; |
275 | } | 275 | } |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 959135a01847..fd3367a1dc7a 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -128,14 +128,14 @@ static ssize_t ccwgroup_online_store(struct device *dev, | |||
128 | const char *buf, size_t count) | 128 | const char *buf, size_t count) |
129 | { | 129 | { |
130 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | 130 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
131 | struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); | ||
132 | unsigned long value; | 131 | unsigned long value; |
133 | int ret; | 132 | int ret; |
134 | 133 | ||
135 | if (!dev->driver) | 134 | device_lock(dev); |
136 | return -EINVAL; | 135 | if (!dev->driver) { |
137 | if (!try_module_get(gdrv->driver.owner)) | 136 | ret = -EINVAL; |
138 | return -EINVAL; | 137 | goto out; |
138 | } | ||
139 | 139 | ||
140 | ret = kstrtoul(buf, 0, &value); | 140 | ret = kstrtoul(buf, 0, &value); |
141 | if (ret) | 141 | if (ret) |
@@ -148,7 +148,7 @@ static ssize_t ccwgroup_online_store(struct device *dev, | |||
148 | else | 148 | else |
149 | ret = -EINVAL; | 149 | ret = -EINVAL; |
150 | out: | 150 | out: |
151 | module_put(gdrv->driver.owner); | 151 | device_unlock(dev); |
152 | return (ret == 0) ? count : ret; | 152 | return (ret == 0) ? count : ret; |
153 | } | 153 | } |
154 | 154 | ||
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 13299f902676..f6b9188c5af5 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -55,6 +55,7 @@ int chsc_error_from_response(int response) | |||
55 | case 0x0004: | 55 | case 0x0004: |
56 | return -EOPNOTSUPP; | 56 | return -EOPNOTSUPP; |
57 | case 0x000b: | 57 | case 0x000b: |
58 | case 0x0107: /* "Channel busy" for the op 0x003d */ | ||
58 | return -EBUSY; | 59 | return -EBUSY; |
59 | case 0x0100: | 60 | case 0x0100: |
60 | case 0x0102: | 61 | case 0x0102: |
@@ -237,26 +238,6 @@ void chsc_chp_offline(struct chp_id chpid) | |||
237 | for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); | 238 | for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); |
238 | } | 239 | } |
239 | 240 | ||
240 | static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data) | ||
241 | { | ||
242 | struct schib schib; | ||
243 | /* | ||
244 | * We don't know the device yet, but since a path | ||
245 | * may be available now to the device we'll have | ||
246 | * to do recognition again. | ||
247 | * Since we don't have any idea about which chpid | ||
248 | * that beast may be on we'll have to do a stsch | ||
249 | * on all devices, grr... | ||
250 | */ | ||
251 | if (stsch_err(schid, &schib)) | ||
252 | /* We're through */ | ||
253 | return -ENXIO; | ||
254 | |||
255 | /* Put it on the slow path. */ | ||
256 | css_schedule_eval(schid); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int __s390_process_res_acc(struct subchannel *sch, void *data) | 241 | static int __s390_process_res_acc(struct subchannel *sch, void *data) |
261 | { | 242 | { |
262 | spin_lock_irq(sch->lock); | 243 | spin_lock_irq(sch->lock); |
@@ -287,8 +268,8 @@ static void s390_process_res_acc(struct chp_link *link) | |||
287 | * The more information we have (info), the less scanning | 268 | * The more information we have (info), the less scanning |
288 | * will we have to do. | 269 | * will we have to do. |
289 | */ | 270 | */ |
290 | for_each_subchannel_staged(__s390_process_res_acc, | 271 | for_each_subchannel_staged(__s390_process_res_acc, NULL, link); |
291 | s390_process_res_acc_new_sch, link); | 272 | css_schedule_reprobe(); |
292 | } | 273 | } |
293 | 274 | ||
294 | static int | 275 | static int |
@@ -663,19 +644,6 @@ static int s390_subchannel_vary_chpid_on(struct subchannel *sch, void *data) | |||
663 | return 0; | 644 | return 0; |
664 | } | 645 | } |
665 | 646 | ||
666 | static int | ||
667 | __s390_vary_chpid_on(struct subchannel_id schid, void *data) | ||
668 | { | ||
669 | struct schib schib; | ||
670 | |||
671 | if (stsch_err(schid, &schib)) | ||
672 | /* We're through */ | ||
673 | return -ENXIO; | ||
674 | /* Put it on the slow path. */ | ||
675 | css_schedule_eval(schid); | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | /** | 647 | /** |
680 | * chsc_chp_vary - propagate channel-path vary operation to subchannels | 648 | * chsc_chp_vary - propagate channel-path vary operation to subchannels |
681 | * @chpid: channl-path ID | 649 | * @chpid: channl-path ID |
@@ -694,7 +662,8 @@ int chsc_chp_vary(struct chp_id chpid, int on) | |||
694 | /* Try to update the channel path description. */ | 662 | /* Try to update the channel path description. */ |
695 | chp_update_desc(chp); | 663 | chp_update_desc(chp); |
696 | for_each_subchannel_staged(s390_subchannel_vary_chpid_on, | 664 | for_each_subchannel_staged(s390_subchannel_vary_chpid_on, |
697 | __s390_vary_chpid_on, &chpid); | 665 | NULL, &chpid); |
666 | css_schedule_reprobe(); | ||
698 | } else | 667 | } else |
699 | for_each_subchannel_staged(s390_subchannel_vary_chpid_off, | 668 | for_each_subchannel_staged(s390_subchannel_vary_chpid_off, |
700 | NULL, &chpid); | 669 | NULL, &chpid); |
@@ -1234,3 +1203,35 @@ out: | |||
1234 | return ret; | 1203 | return ret; |
1235 | } | 1204 | } |
1236 | EXPORT_SYMBOL_GPL(chsc_scm_info); | 1205 | EXPORT_SYMBOL_GPL(chsc_scm_info); |
1206 | |||
1207 | /** | ||
1208 | * chsc_pnso_brinfo() - Perform Network-Subchannel Operation, Bridge Info. | ||
1209 | * @schid: id of the subchannel on which PNSO is performed | ||
1210 | * @brinfo_area: request and response block for the operation | ||
1211 | * @resume_token: resume token for multiblock response | ||
1212 | * @cnc: Boolean change-notification control | ||
1213 | * | ||
1214 | * brinfo_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL) | ||
1215 | * | ||
1216 | * Returns 0 on success. | ||
1217 | */ | ||
1218 | int chsc_pnso_brinfo(struct subchannel_id schid, | ||
1219 | struct chsc_pnso_area *brinfo_area, | ||
1220 | struct chsc_brinfo_resume_token resume_token, | ||
1221 | int cnc) | ||
1222 | { | ||
1223 | memset(brinfo_area, 0, sizeof(*brinfo_area)); | ||
1224 | brinfo_area->request.length = 0x0030; | ||
1225 | brinfo_area->request.code = 0x003d; /* network-subchannel operation */ | ||
1226 | brinfo_area->m = schid.m; | ||
1227 | brinfo_area->ssid = schid.ssid; | ||
1228 | brinfo_area->sch = schid.sch_no; | ||
1229 | brinfo_area->cssid = schid.cssid; | ||
1230 | brinfo_area->oc = 0; /* Store-network-bridging-information list */ | ||
1231 | brinfo_area->resume_token = resume_token; | ||
1232 | brinfo_area->n = (cnc != 0); | ||
1233 | if (chsc(brinfo_area)) | ||
1234 | return -EIO; | ||
1235 | return chsc_error_from_response(brinfo_area->response.code); | ||
1236 | } | ||
1237 | EXPORT_SYMBOL_GPL(chsc_pnso_brinfo); | ||
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 23d072e70eb2..7e53a9c8b0b9 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -61,7 +61,9 @@ struct css_chsc_char { | |||
61 | u32 : 20; | 61 | u32 : 20; |
62 | u32 scssc : 1; /* bit 107 */ | 62 | u32 scssc : 1; /* bit 107 */ |
63 | u32 scsscf : 1; /* bit 108 */ | 63 | u32 scsscf : 1; /* bit 108 */ |
64 | u32 : 19; | 64 | u32:7; |
65 | u32 pnso:1; /* bit 116 */ | ||
66 | u32:11; | ||
65 | }__attribute__((packed)); | 67 | }__attribute__((packed)); |
66 | 68 | ||
67 | extern struct css_chsc_char css_chsc_characteristics; | 69 | extern struct css_chsc_char css_chsc_characteristics; |
@@ -188,6 +190,53 @@ struct chsc_scm_info { | |||
188 | 190 | ||
189 | int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token); | 191 | int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token); |
190 | 192 | ||
193 | struct chsc_brinfo_resume_token { | ||
194 | u64 t1; | ||
195 | u64 t2; | ||
196 | } __packed; | ||
197 | |||
198 | struct chsc_brinfo_naihdr { | ||
199 | struct chsc_brinfo_resume_token resume_token; | ||
200 | u32:32; | ||
201 | u32 instance; | ||
202 | u32:24; | ||
203 | u8 naids; | ||
204 | u32 reserved[3]; | ||
205 | } __packed; | ||
206 | |||
207 | struct chsc_pnso_area { | ||
208 | struct chsc_header request; | ||
209 | u8:2; | ||
210 | u8 m:1; | ||
211 | u8:5; | ||
212 | u8:2; | ||
213 | u8 ssid:2; | ||
214 | u8 fmt:4; | ||
215 | u16 sch; | ||
216 | u8:8; | ||
217 | u8 cssid; | ||
218 | u16:16; | ||
219 | u8 oc; | ||
220 | u32:24; | ||
221 | struct chsc_brinfo_resume_token resume_token; | ||
222 | u32 n:1; | ||
223 | u32:31; | ||
224 | u32 reserved[3]; | ||
225 | struct chsc_header response; | ||
226 | u32:32; | ||
227 | struct chsc_brinfo_naihdr naihdr; | ||
228 | union { | ||
229 | struct qdio_brinfo_entry_l3_ipv6 l3_ipv6[0]; | ||
230 | struct qdio_brinfo_entry_l3_ipv4 l3_ipv4[0]; | ||
231 | struct qdio_brinfo_entry_l2 l2[0]; | ||
232 | } entries; | ||
233 | } __packed; | ||
234 | |||
235 | int chsc_pnso_brinfo(struct subchannel_id schid, | ||
236 | struct chsc_pnso_area *brinfo_area, | ||
237 | struct chsc_brinfo_resume_token resume_token, | ||
238 | int cnc); | ||
239 | |||
191 | #ifdef CONFIG_SCM_BUS | 240 | #ifdef CONFIG_SCM_BUS |
192 | int scm_update_information(void); | 241 | int scm_update_information(void); |
193 | int scm_process_availability_information(void); | 242 | int scm_process_availability_information(void); |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 8c2cb87bccc5..0268e5fd59b5 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -69,7 +69,8 @@ static int call_fn_known_sch(struct device *dev, void *data) | |||
69 | struct cb_data *cb = data; | 69 | struct cb_data *cb = data; |
70 | int rc = 0; | 70 | int rc = 0; |
71 | 71 | ||
72 | idset_sch_del(cb->set, sch->schid); | 72 | if (cb->set) |
73 | idset_sch_del(cb->set, sch->schid); | ||
73 | if (cb->fn_known_sch) | 74 | if (cb->fn_known_sch) |
74 | rc = cb->fn_known_sch(sch, cb->data); | 75 | rc = cb->fn_known_sch(sch, cb->data); |
75 | return rc; | 76 | return rc; |
@@ -115,6 +116,13 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), | |||
115 | cb.fn_known_sch = fn_known; | 116 | cb.fn_known_sch = fn_known; |
116 | cb.fn_unknown_sch = fn_unknown; | 117 | cb.fn_unknown_sch = fn_unknown; |
117 | 118 | ||
119 | if (fn_known && !fn_unknown) { | ||
120 | /* Skip idset allocation in case of known-only loop. */ | ||
121 | cb.set = NULL; | ||
122 | return bus_for_each_dev(&css_bus_type, NULL, &cb, | ||
123 | call_fn_known_sch); | ||
124 | } | ||
125 | |||
118 | cb.set = idset_sch_new(); | 126 | cb.set = idset_sch_new(); |
119 | if (!cb.set) | 127 | if (!cb.set) |
120 | /* fall back to brute force scanning in case of oom */ | 128 | /* fall back to brute force scanning in case of oom */ |
@@ -553,6 +561,9 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) | |||
553 | default: | 561 | default: |
554 | rc = 0; | 562 | rc = 0; |
555 | } | 563 | } |
564 | /* Allow scheduling here since the containing loop might | ||
565 | * take a while. */ | ||
566 | cond_resched(); | ||
556 | } | 567 | } |
557 | return rc; | 568 | return rc; |
558 | } | 569 | } |
@@ -572,7 +583,7 @@ static void css_slow_path_func(struct work_struct *unused) | |||
572 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 583 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
573 | } | 584 | } |
574 | 585 | ||
575 | static DECLARE_WORK(slow_path_work, css_slow_path_func); | 586 | static DECLARE_DELAYED_WORK(slow_path_work, css_slow_path_func); |
576 | struct workqueue_struct *cio_work_q; | 587 | struct workqueue_struct *cio_work_q; |
577 | 588 | ||
578 | void css_schedule_eval(struct subchannel_id schid) | 589 | void css_schedule_eval(struct subchannel_id schid) |
@@ -582,7 +593,7 @@ void css_schedule_eval(struct subchannel_id schid) | |||
582 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 593 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
583 | idset_sch_add(slow_subchannel_set, schid); | 594 | idset_sch_add(slow_subchannel_set, schid); |
584 | atomic_set(&css_eval_scheduled, 1); | 595 | atomic_set(&css_eval_scheduled, 1); |
585 | queue_work(cio_work_q, &slow_path_work); | 596 | queue_delayed_work(cio_work_q, &slow_path_work, 0); |
586 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 597 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
587 | } | 598 | } |
588 | 599 | ||
@@ -593,7 +604,7 @@ void css_schedule_eval_all(void) | |||
593 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 604 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
594 | idset_fill(slow_subchannel_set); | 605 | idset_fill(slow_subchannel_set); |
595 | atomic_set(&css_eval_scheduled, 1); | 606 | atomic_set(&css_eval_scheduled, 1); |
596 | queue_work(cio_work_q, &slow_path_work); | 607 | queue_delayed_work(cio_work_q, &slow_path_work, 0); |
597 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 608 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
598 | } | 609 | } |
599 | 610 | ||
@@ -606,7 +617,7 @@ static int __unset_registered(struct device *dev, void *data) | |||
606 | return 0; | 617 | return 0; |
607 | } | 618 | } |
608 | 619 | ||
609 | static void css_schedule_eval_all_unreg(void) | 620 | void css_schedule_eval_all_unreg(unsigned long delay) |
610 | { | 621 | { |
611 | unsigned long flags; | 622 | unsigned long flags; |
612 | struct idset *unreg_set; | 623 | struct idset *unreg_set; |
@@ -624,7 +635,7 @@ static void css_schedule_eval_all_unreg(void) | |||
624 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 635 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
625 | idset_add_set(slow_subchannel_set, unreg_set); | 636 | idset_add_set(slow_subchannel_set, unreg_set); |
626 | atomic_set(&css_eval_scheduled, 1); | 637 | atomic_set(&css_eval_scheduled, 1); |
627 | queue_work(cio_work_q, &slow_path_work); | 638 | queue_delayed_work(cio_work_q, &slow_path_work, delay); |
628 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 639 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
629 | idset_free(unreg_set); | 640 | idset_free(unreg_set); |
630 | } | 641 | } |
@@ -637,7 +648,8 @@ void css_wait_for_slow_path(void) | |||
637 | /* Schedule reprobing of all unregistered subchannels. */ | 648 | /* Schedule reprobing of all unregistered subchannels. */ |
638 | void css_schedule_reprobe(void) | 649 | void css_schedule_reprobe(void) |
639 | { | 650 | { |
640 | css_schedule_eval_all_unreg(); | 651 | /* Schedule with a delay to allow merging of subsequent calls. */ |
652 | css_schedule_eval_all_unreg(1 * HZ); | ||
641 | } | 653 | } |
642 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); | 654 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); |
643 | 655 | ||
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 29351321bad6..2c9107e20251 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -133,6 +133,7 @@ extern struct channel_subsystem *channel_subsystems[]; | |||
133 | /* Helper functions to build lists for the slow path. */ | 133 | /* Helper functions to build lists for the slow path. */ |
134 | void css_schedule_eval(struct subchannel_id schid); | 134 | void css_schedule_eval(struct subchannel_id schid); |
135 | void css_schedule_eval_all(void); | 135 | void css_schedule_eval_all(void); |
136 | void css_schedule_eval_all_unreg(unsigned long delay); | ||
136 | int css_complete_work(void); | 137 | int css_complete_work(void); |
137 | 138 | ||
138 | int sch_is_pseudo_sch(struct subchannel *); | 139 | int sch_is_pseudo_sch(struct subchannel *); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e4a7ab2bb629..e9d783563cbb 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -333,9 +333,9 @@ int ccw_device_set_offline(struct ccw_device *cdev) | |||
333 | if (ret != 0) | 333 | if (ret != 0) |
334 | return ret; | 334 | return ret; |
335 | } | 335 | } |
336 | cdev->online = 0; | ||
337 | spin_lock_irq(cdev->ccwlock); | 336 | spin_lock_irq(cdev->ccwlock); |
338 | sch = to_subchannel(cdev->dev.parent); | 337 | sch = to_subchannel(cdev->dev.parent); |
338 | cdev->online = 0; | ||
339 | /* Wait until a final state or DISCONNECTED is reached */ | 339 | /* Wait until a final state or DISCONNECTED is reached */ |
340 | while (!dev_fsm_final_state(cdev) && | 340 | while (!dev_fsm_final_state(cdev) && |
341 | cdev->private->state != DEV_STATE_DISCONNECTED) { | 341 | cdev->private->state != DEV_STATE_DISCONNECTED) { |
@@ -446,7 +446,10 @@ int ccw_device_set_online(struct ccw_device *cdev) | |||
446 | ret = cdev->drv->set_online(cdev); | 446 | ret = cdev->drv->set_online(cdev); |
447 | if (ret) | 447 | if (ret) |
448 | goto rollback; | 448 | goto rollback; |
449 | |||
450 | spin_lock_irq(cdev->ccwlock); | ||
449 | cdev->online = 1; | 451 | cdev->online = 1; |
452 | spin_unlock_irq(cdev->ccwlock); | ||
450 | return 0; | 453 | return 0; |
451 | 454 | ||
452 | rollback: | 455 | rollback: |
@@ -546,17 +549,12 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, | |||
546 | if (!dev_fsm_final_state(cdev) && | 549 | if (!dev_fsm_final_state(cdev) && |
547 | cdev->private->state != DEV_STATE_DISCONNECTED) { | 550 | cdev->private->state != DEV_STATE_DISCONNECTED) { |
548 | ret = -EAGAIN; | 551 | ret = -EAGAIN; |
549 | goto out_onoff; | 552 | goto out; |
550 | } | 553 | } |
551 | /* Prevent conflict between pending work and on-/offline processing.*/ | 554 | /* Prevent conflict between pending work and on-/offline processing.*/ |
552 | if (work_pending(&cdev->private->todo_work)) { | 555 | if (work_pending(&cdev->private->todo_work)) { |
553 | ret = -EAGAIN; | 556 | ret = -EAGAIN; |
554 | goto out_onoff; | 557 | goto out; |
555 | } | ||
556 | |||
557 | if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) { | ||
558 | ret = -EINVAL; | ||
559 | goto out_onoff; | ||
560 | } | 558 | } |
561 | if (!strncmp(buf, "force\n", count)) { | 559 | if (!strncmp(buf, "force\n", count)) { |
562 | force = 1; | 560 | force = 1; |
@@ -568,6 +566,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, | |||
568 | } | 566 | } |
569 | if (ret) | 567 | if (ret) |
570 | goto out; | 568 | goto out; |
569 | |||
570 | device_lock(dev); | ||
571 | switch (i) { | 571 | switch (i) { |
572 | case 0: | 572 | case 0: |
573 | ret = online_store_handle_offline(cdev); | 573 | ret = online_store_handle_offline(cdev); |
@@ -578,10 +578,9 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, | |||
578 | default: | 578 | default: |
579 | ret = -EINVAL; | 579 | ret = -EINVAL; |
580 | } | 580 | } |
581 | device_unlock(dev); | ||
582 | |||
581 | out: | 583 | out: |
582 | if (cdev->drv) | ||
583 | module_put(cdev->drv->driver.owner); | ||
584 | out_onoff: | ||
585 | atomic_set(&cdev->private->onoff, 0); | 584 | atomic_set(&cdev->private->onoff, 0); |
586 | return (ret < 0) ? ret : count; | 585 | return (ret < 0) ? ret : count; |
587 | } | 586 | } |
@@ -1745,8 +1744,7 @@ ccw_device_probe (struct device *dev) | |||
1745 | return 0; | 1744 | return 0; |
1746 | } | 1745 | } |
1747 | 1746 | ||
1748 | static int | 1747 | static int ccw_device_remove(struct device *dev) |
1749 | ccw_device_remove (struct device *dev) | ||
1750 | { | 1748 | { |
1751 | struct ccw_device *cdev = to_ccwdev(dev); | 1749 | struct ccw_device *cdev = to_ccwdev(dev); |
1752 | struct ccw_driver *cdrv = cdev->drv; | 1750 | struct ccw_driver *cdrv = cdev->drv; |
@@ -1754,9 +1752,10 @@ ccw_device_remove (struct device *dev) | |||
1754 | 1752 | ||
1755 | if (cdrv->remove) | 1753 | if (cdrv->remove) |
1756 | cdrv->remove(cdev); | 1754 | cdrv->remove(cdev); |
1755 | |||
1756 | spin_lock_irq(cdev->ccwlock); | ||
1757 | if (cdev->online) { | 1757 | if (cdev->online) { |
1758 | cdev->online = 0; | 1758 | cdev->online = 0; |
1759 | spin_lock_irq(cdev->ccwlock); | ||
1760 | ret = ccw_device_offline(cdev); | 1759 | ret = ccw_device_offline(cdev); |
1761 | spin_unlock_irq(cdev->ccwlock); | 1760 | spin_unlock_irq(cdev->ccwlock); |
1762 | if (ret == 0) | 1761 | if (ret == 0) |
@@ -1769,10 +1768,12 @@ ccw_device_remove (struct device *dev) | |||
1769 | cdev->private->dev_id.devno); | 1768 | cdev->private->dev_id.devno); |
1770 | /* Give up reference obtained in ccw_device_set_online(). */ | 1769 | /* Give up reference obtained in ccw_device_set_online(). */ |
1771 | put_device(&cdev->dev); | 1770 | put_device(&cdev->dev); |
1771 | spin_lock_irq(cdev->ccwlock); | ||
1772 | } | 1772 | } |
1773 | ccw_device_set_timeout(cdev, 0); | 1773 | ccw_device_set_timeout(cdev, 0); |
1774 | cdev->drv = NULL; | 1774 | cdev->drv = NULL; |
1775 | cdev->private->int_class = IRQIO_CIO; | 1775 | cdev->private->int_class = IRQIO_CIO; |
1776 | spin_unlock_irq(cdev->ccwlock); | ||
1776 | return 0; | 1777 | return 0; |
1777 | } | 1778 | } |
1778 | 1779 | ||
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 3e602e8affa7..c883a085c059 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -1752,6 +1752,97 @@ int qdio_stop_irq(struct ccw_device *cdev, int nr) | |||
1752 | } | 1752 | } |
1753 | EXPORT_SYMBOL(qdio_stop_irq); | 1753 | EXPORT_SYMBOL(qdio_stop_irq); |
1754 | 1754 | ||
1755 | /** | ||
1756 | * qdio_pnso_brinfo() - perform network subchannel op #0 - bridge info. | ||
1757 | * @schid: Subchannel ID. | ||
1758 | * @cnc: Boolean Change-Notification Control | ||
1759 | * @response: Response code will be stored at this address | ||
1760 | * @cb: Callback function will be executed for each element | ||
1761 | * of the address list | ||
1762 | * @priv: Pointer passed from the caller to qdio_pnso_brinfo() | ||
1763 | * @type: Type of the address entry passed to the callback | ||
1764 | * @entry: Entry containg the address of the specified type | ||
1765 | * @priv: Pointer to pass to the callback function. | ||
1766 | * | ||
1767 | * Performs "Store-network-bridging-information list" operation and calls | ||
1768 | * the callback function for every entry in the list. If "change- | ||
1769 | * notification-control" is set, further changes in the address list | ||
1770 | * will be reported via the IPA command. | ||
1771 | */ | ||
1772 | int qdio_pnso_brinfo(struct subchannel_id schid, | ||
1773 | int cnc, u16 *response, | ||
1774 | void (*cb)(void *priv, enum qdio_brinfo_entry_type type, | ||
1775 | void *entry), | ||
1776 | void *priv) | ||
1777 | { | ||
1778 | struct chsc_pnso_area *rr; | ||
1779 | int rc; | ||
1780 | u32 prev_instance = 0; | ||
1781 | int isfirstblock = 1; | ||
1782 | int i, size, elems; | ||
1783 | |||
1784 | rr = (struct chsc_pnso_area *)get_zeroed_page(GFP_KERNEL); | ||
1785 | if (rr == NULL) | ||
1786 | return -ENOMEM; | ||
1787 | do { | ||
1788 | /* on the first iteration, naihdr.resume_token will be zero */ | ||
1789 | rc = chsc_pnso_brinfo(schid, rr, rr->naihdr.resume_token, cnc); | ||
1790 | if (rc != 0 && rc != -EBUSY) | ||
1791 | goto out; | ||
1792 | if (rr->response.code != 1) { | ||
1793 | rc = -EIO; | ||
1794 | continue; | ||
1795 | } else | ||
1796 | rc = 0; | ||
1797 | |||
1798 | if (cb == NULL) | ||
1799 | continue; | ||
1800 | |||
1801 | size = rr->naihdr.naids; | ||
1802 | elems = (rr->response.length - | ||
1803 | sizeof(struct chsc_header) - | ||
1804 | sizeof(struct chsc_brinfo_naihdr)) / | ||
1805 | size; | ||
1806 | |||
1807 | if (!isfirstblock && (rr->naihdr.instance != prev_instance)) { | ||
1808 | /* Inform the caller that they need to scrap */ | ||
1809 | /* the data that was already reported via cb */ | ||
1810 | rc = -EAGAIN; | ||
1811 | break; | ||
1812 | } | ||
1813 | isfirstblock = 0; | ||
1814 | prev_instance = rr->naihdr.instance; | ||
1815 | for (i = 0; i < elems; i++) | ||
1816 | switch (size) { | ||
1817 | case sizeof(struct qdio_brinfo_entry_l3_ipv6): | ||
1818 | (*cb)(priv, l3_ipv6_addr, | ||
1819 | &rr->entries.l3_ipv6[i]); | ||
1820 | break; | ||
1821 | case sizeof(struct qdio_brinfo_entry_l3_ipv4): | ||
1822 | (*cb)(priv, l3_ipv4_addr, | ||
1823 | &rr->entries.l3_ipv4[i]); | ||
1824 | break; | ||
1825 | case sizeof(struct qdio_brinfo_entry_l2): | ||
1826 | (*cb)(priv, l2_addr_lnid, | ||
1827 | &rr->entries.l2[i]); | ||
1828 | break; | ||
1829 | default: | ||
1830 | WARN_ON_ONCE(1); | ||
1831 | rc = -EIO; | ||
1832 | goto out; | ||
1833 | } | ||
1834 | } while (rr->response.code == 0x0107 || /* channel busy */ | ||
1835 | (rr->response.code == 1 && /* list stored */ | ||
1836 | /* resume token is non-zero => list incomplete */ | ||
1837 | (rr->naihdr.resume_token.t1 || rr->naihdr.resume_token.t2))); | ||
1838 | (*response) = rr->response.code; | ||
1839 | |||
1840 | out: | ||
1841 | free_page((unsigned long)rr); | ||
1842 | return rc; | ||
1843 | } | ||
1844 | EXPORT_SYMBOL_GPL(qdio_pnso_brinfo); | ||
1845 | |||
1755 | static int __init init_QDIO(void) | 1846 | static int __init init_QDIO(void) |
1756 | { | 1847 | { |
1757 | int rc; | 1848 | int rc; |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 02300dcfac91..ab3baa7f9508 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -591,7 +591,13 @@ static int ap_init_queue(ap_qid_t qid) | |||
591 | if (rc != -ENODEV && rc != -EBUSY) | 591 | if (rc != -ENODEV && rc != -EBUSY) |
592 | break; | 592 | break; |
593 | if (i < AP_MAX_RESET - 1) { | 593 | if (i < AP_MAX_RESET - 1) { |
594 | udelay(5); | 594 | /* Time we are waiting until we give up (0.7sec * 90). |
595 | * Since the actual request (in progress) will not | ||
596 | * interrupted immediately for the reset command, | ||
597 | * we have to be patient. In worst case we have to | ||
598 | * wait 60sec + reset time (some msec). | ||
599 | */ | ||
600 | schedule_timeout(AP_RESET_TIMEOUT); | ||
595 | status = ap_test_queue(qid, &dummy, &dummy); | 601 | status = ap_test_queue(qid, &dummy, &dummy); |
596 | } | 602 | } |
597 | } | 603 | } |
@@ -992,6 +998,28 @@ static ssize_t ap_domain_show(struct bus_type *bus, char *buf) | |||
992 | 998 | ||
993 | static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL); | 999 | static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL); |
994 | 1000 | ||
1001 | static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf) | ||
1002 | { | ||
1003 | if (ap_configuration != NULL) { /* QCI not supported */ | ||
1004 | if (test_facility(76)) { /* format 1 - 256 bit domain field */ | ||
1005 | return snprintf(buf, PAGE_SIZE, | ||
1006 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", | ||
1007 | ap_configuration->adm[0], ap_configuration->adm[1], | ||
1008 | ap_configuration->adm[2], ap_configuration->adm[3], | ||
1009 | ap_configuration->adm[4], ap_configuration->adm[5], | ||
1010 | ap_configuration->adm[6], ap_configuration->adm[7]); | ||
1011 | } else { /* format 0 - 16 bit domain field */ | ||
1012 | return snprintf(buf, PAGE_SIZE, "%08x%08x\n", | ||
1013 | ap_configuration->adm[0], ap_configuration->adm[1]); | ||
1014 | } | ||
1015 | } else { | ||
1016 | return snprintf(buf, PAGE_SIZE, "not supported\n"); | ||
1017 | } | ||
1018 | } | ||
1019 | |||
1020 | static BUS_ATTR(ap_control_domain_mask, 0444, | ||
1021 | ap_control_domain_mask_show, NULL); | ||
1022 | |||
995 | static ssize_t ap_config_time_show(struct bus_type *bus, char *buf) | 1023 | static ssize_t ap_config_time_show(struct bus_type *bus, char *buf) |
996 | { | 1024 | { |
997 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); | 1025 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); |
@@ -1077,6 +1105,7 @@ static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store); | |||
1077 | 1105 | ||
1078 | static struct bus_attribute *const ap_bus_attrs[] = { | 1106 | static struct bus_attribute *const ap_bus_attrs[] = { |
1079 | &bus_attr_ap_domain, | 1107 | &bus_attr_ap_domain, |
1108 | &bus_attr_ap_control_domain_mask, | ||
1080 | &bus_attr_config_time, | 1109 | &bus_attr_config_time, |
1081 | &bus_attr_poll_thread, | 1110 | &bus_attr_poll_thread, |
1082 | &bus_attr_ap_interrupts, | 1111 | &bus_attr_ap_interrupts, |
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 685f6cc022f9..6405ae24a7a6 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h | |||
@@ -33,7 +33,7 @@ | |||
33 | #define AP_DEVICES 64 /* Number of AP devices. */ | 33 | #define AP_DEVICES 64 /* Number of AP devices. */ |
34 | #define AP_DOMAINS 16 /* Number of AP domains. */ | 34 | #define AP_DOMAINS 16 /* Number of AP domains. */ |
35 | #define AP_MAX_RESET 90 /* Maximum number of resets. */ | 35 | #define AP_MAX_RESET 90 /* Maximum number of resets. */ |
36 | #define AP_RESET_TIMEOUT (HZ/2) /* Time in ticks for reset timeouts. */ | 36 | #define AP_RESET_TIMEOUT (HZ*0.7) /* Time in ticks for reset timeouts. */ |
37 | #define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ | 37 | #define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ |
38 | #define AP_POLL_TIME 1 /* Time in ticks between receive polls. */ | 38 | #define AP_POLL_TIME 1 /* Time in ticks between receive polls. */ |
39 | 39 | ||
@@ -125,6 +125,8 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) | |||
125 | #define AP_FUNC_CRT4K 2 | 125 | #define AP_FUNC_CRT4K 2 |
126 | #define AP_FUNC_COPRO 3 | 126 | #define AP_FUNC_COPRO 3 |
127 | #define AP_FUNC_ACCEL 4 | 127 | #define AP_FUNC_ACCEL 4 |
128 | #define AP_FUNC_EP11 5 | ||
129 | #define AP_FUNC_APXA 6 | ||
128 | 130 | ||
129 | /* | 131 | /* |
130 | * AP reset flag states | 132 | * AP reset flag states |
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 31cfaa556072..4b824b15194f 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include "zcrypt_debug.h" | 44 | #include "zcrypt_debug.h" |
45 | #include "zcrypt_api.h" | 45 | #include "zcrypt_api.h" |
46 | 46 | ||
47 | #include "zcrypt_msgtype6.h" | ||
48 | |||
47 | /* | 49 | /* |
48 | * Module description. | 50 | * Module description. |
49 | */ | 51 | */ |
@@ -554,9 +556,9 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) | |||
554 | spin_lock_bh(&zcrypt_device_lock); | 556 | spin_lock_bh(&zcrypt_device_lock); |
555 | list_for_each_entry(zdev, &zcrypt_device_list, list) { | 557 | list_for_each_entry(zdev, &zcrypt_device_list, list) { |
556 | if (!zdev->online || !zdev->ops->send_cprb || | 558 | if (!zdev->online || !zdev->ops->send_cprb || |
557 | (xcRB->user_defined != AUTOSELECT && | 559 | (zdev->ops->variant == MSGTYPE06_VARIANT_EP11) || |
558 | AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined) | 560 | (xcRB->user_defined != AUTOSELECT && |
559 | ) | 561 | AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined)) |
560 | continue; | 562 | continue; |
561 | zcrypt_device_get(zdev); | 563 | zcrypt_device_get(zdev); |
562 | get_device(&zdev->ap_dev->device); | 564 | get_device(&zdev->ap_dev->device); |
@@ -581,6 +583,90 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) | |||
581 | return -ENODEV; | 583 | return -ENODEV; |
582 | } | 584 | } |
583 | 585 | ||
586 | struct ep11_target_dev_list { | ||
587 | unsigned short targets_num; | ||
588 | struct ep11_target_dev *targets; | ||
589 | }; | ||
590 | |||
591 | static bool is_desired_ep11dev(unsigned int dev_qid, | ||
592 | struct ep11_target_dev_list dev_list) | ||
593 | { | ||
594 | int n; | ||
595 | |||
596 | for (n = 0; n < dev_list.targets_num; n++, dev_list.targets++) { | ||
597 | if ((AP_QID_DEVICE(dev_qid) == dev_list.targets->ap_id) && | ||
598 | (AP_QID_QUEUE(dev_qid) == dev_list.targets->dom_id)) { | ||
599 | return true; | ||
600 | } | ||
601 | } | ||
602 | return false; | ||
603 | } | ||
604 | |||
605 | static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) | ||
606 | { | ||
607 | struct zcrypt_device *zdev; | ||
608 | bool autoselect = false; | ||
609 | int rc; | ||
610 | struct ep11_target_dev_list ep11_dev_list = { | ||
611 | .targets_num = 0x00, | ||
612 | .targets = NULL, | ||
613 | }; | ||
614 | |||
615 | ep11_dev_list.targets_num = (unsigned short) xcrb->targets_num; | ||
616 | |||
617 | /* empty list indicates autoselect (all available targets) */ | ||
618 | if (ep11_dev_list.targets_num == 0) | ||
619 | autoselect = true; | ||
620 | else { | ||
621 | ep11_dev_list.targets = kcalloc((unsigned short) | ||
622 | xcrb->targets_num, | ||
623 | sizeof(struct ep11_target_dev), | ||
624 | GFP_KERNEL); | ||
625 | if (!ep11_dev_list.targets) | ||
626 | return -ENOMEM; | ||
627 | |||
628 | if (copy_from_user(ep11_dev_list.targets, | ||
629 | (struct ep11_target_dev *)xcrb->targets, | ||
630 | xcrb->targets_num * | ||
631 | sizeof(struct ep11_target_dev))) | ||
632 | return -EFAULT; | ||
633 | } | ||
634 | |||
635 | spin_lock_bh(&zcrypt_device_lock); | ||
636 | list_for_each_entry(zdev, &zcrypt_device_list, list) { | ||
637 | /* check if device is eligible */ | ||
638 | if (!zdev->online || | ||
639 | zdev->ops->variant != MSGTYPE06_VARIANT_EP11) | ||
640 | continue; | ||
641 | |||
642 | /* check if device is selected as valid target */ | ||
643 | if (!is_desired_ep11dev(zdev->ap_dev->qid, ep11_dev_list) && | ||
644 | !autoselect) | ||
645 | continue; | ||
646 | |||
647 | zcrypt_device_get(zdev); | ||
648 | get_device(&zdev->ap_dev->device); | ||
649 | zdev->request_count++; | ||
650 | __zcrypt_decrease_preference(zdev); | ||
651 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { | ||
652 | spin_unlock_bh(&zcrypt_device_lock); | ||
653 | rc = zdev->ops->send_ep11_cprb(zdev, xcrb); | ||
654 | spin_lock_bh(&zcrypt_device_lock); | ||
655 | module_put(zdev->ap_dev->drv->driver.owner); | ||
656 | } else { | ||
657 | rc = -EAGAIN; | ||
658 | } | ||
659 | zdev->request_count--; | ||
660 | __zcrypt_increase_preference(zdev); | ||
661 | put_device(&zdev->ap_dev->device); | ||
662 | zcrypt_device_put(zdev); | ||
663 | spin_unlock_bh(&zcrypt_device_lock); | ||
664 | return rc; | ||
665 | } | ||
666 | spin_unlock_bh(&zcrypt_device_lock); | ||
667 | return -ENODEV; | ||
668 | } | ||
669 | |||
584 | static long zcrypt_rng(char *buffer) | 670 | static long zcrypt_rng(char *buffer) |
585 | { | 671 | { |
586 | struct zcrypt_device *zdev; | 672 | struct zcrypt_device *zdev; |
@@ -784,6 +870,23 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, | |||
784 | return -EFAULT; | 870 | return -EFAULT; |
785 | return rc; | 871 | return rc; |
786 | } | 872 | } |
873 | case ZSENDEP11CPRB: { | ||
874 | struct ep11_urb __user *uxcrb = (void __user *)arg; | ||
875 | struct ep11_urb xcrb; | ||
876 | if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb))) | ||
877 | return -EFAULT; | ||
878 | do { | ||
879 | rc = zcrypt_send_ep11_cprb(&xcrb); | ||
880 | } while (rc == -EAGAIN); | ||
881 | /* on failure: retry once again after a requested rescan */ | ||
882 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
883 | do { | ||
884 | rc = zcrypt_send_ep11_cprb(&xcrb); | ||
885 | } while (rc == -EAGAIN); | ||
886 | if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb))) | ||
887 | return -EFAULT; | ||
888 | return rc; | ||
889 | } | ||
787 | case Z90STAT_STATUS_MASK: { | 890 | case Z90STAT_STATUS_MASK: { |
788 | char status[AP_DEVICES]; | 891 | char status[AP_DEVICES]; |
789 | zcrypt_status_mask(status); | 892 | zcrypt_status_mask(status); |
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 89632919c993..b3d496bfaa7e 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h | |||
@@ -74,6 +74,7 @@ struct ica_z90_status { | |||
74 | #define ZCRYPT_CEX2A 6 | 74 | #define ZCRYPT_CEX2A 6 |
75 | #define ZCRYPT_CEX3C 7 | 75 | #define ZCRYPT_CEX3C 7 |
76 | #define ZCRYPT_CEX3A 8 | 76 | #define ZCRYPT_CEX3A 8 |
77 | #define ZCRYPT_CEX4 10 | ||
77 | 78 | ||
78 | /** | 79 | /** |
79 | * Large random numbers are pulled in 4096 byte chunks from the crypto cards | 80 | * Large random numbers are pulled in 4096 byte chunks from the crypto cards |
@@ -89,6 +90,7 @@ struct zcrypt_ops { | |||
89 | long (*rsa_modexpo_crt)(struct zcrypt_device *, | 90 | long (*rsa_modexpo_crt)(struct zcrypt_device *, |
90 | struct ica_rsa_modexpo_crt *); | 91 | struct ica_rsa_modexpo_crt *); |
91 | long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); | 92 | long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); |
93 | long (*send_ep11_cprb)(struct zcrypt_device *, struct ep11_urb *); | ||
92 | long (*rng)(struct zcrypt_device *, char *); | 94 | long (*rng)(struct zcrypt_device *, char *); |
93 | struct list_head list; /* zcrypt ops list. */ | 95 | struct list_head list; /* zcrypt ops list. */ |
94 | struct module *owner; | 96 | struct module *owner; |
diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index ce1226398ac9..569f8b1d86c0 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c | |||
@@ -30,7 +30,12 @@ | |||
30 | #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE | 30 | #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE |
31 | #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE | 31 | #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE |
32 | 32 | ||
33 | #define CEX4_CLEANUP_TIME (15*HZ) | 33 | /* Waiting time for requests to be processed. |
34 | * Currently there are some types of request which are not deterministic. | ||
35 | * But the maximum time limit managed by the stomper code is set to 60sec. | ||
36 | * Hence we have to wait at least that time period. | ||
37 | */ | ||
38 | #define CEX4_CLEANUP_TIME (61*HZ) | ||
34 | 39 | ||
35 | static struct ap_device_id zcrypt_cex4_ids[] = { | 40 | static struct ap_device_id zcrypt_cex4_ids[] = { |
36 | { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, | 41 | { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, |
@@ -101,6 +106,19 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev) | |||
101 | zdev->speed_rating = CEX4C_SPEED_RATING; | 106 | zdev->speed_rating = CEX4C_SPEED_RATING; |
102 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, | 107 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, |
103 | MSGTYPE06_VARIANT_DEFAULT); | 108 | MSGTYPE06_VARIANT_DEFAULT); |
109 | } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_EP11)) { | ||
110 | zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); | ||
111 | if (!zdev) | ||
112 | return -ENOMEM; | ||
113 | zdev->type_string = "CEX4P"; | ||
114 | zdev->user_space_type = ZCRYPT_CEX4; | ||
115 | zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; | ||
116 | zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; | ||
117 | zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; | ||
118 | zdev->short_crt = 0; | ||
119 | zdev->speed_rating = CEX4C_SPEED_RATING; | ||
120 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, | ||
121 | MSGTYPE06_VARIANT_EP11); | ||
104 | } | 122 | } |
105 | break; | 123 | break; |
106 | } | 124 | } |
diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h index 0079b6617211..7b23f43c7b08 100644 --- a/drivers/s390/crypto/zcrypt_error.h +++ b/drivers/s390/crypto/zcrypt_error.h | |||
@@ -106,15 +106,15 @@ static inline int convert_error(struct zcrypt_device *zdev, | |||
106 | // REP88_ERROR_MESSAGE_TYPE // '20' CEX2A | 106 | // REP88_ERROR_MESSAGE_TYPE // '20' CEX2A |
107 | /* | 107 | /* |
108 | * To sent a message of the wrong type is a bug in the | 108 | * To sent a message of the wrong type is a bug in the |
109 | * device driver. Warn about it, disable the device | 109 | * device driver. Send error msg, disable the device |
110 | * and then repeat the request. | 110 | * and then repeat the request. |
111 | */ | 111 | */ |
112 | WARN_ON(1); | ||
113 | atomic_set(&zcrypt_rescan_req, 1); | 112 | atomic_set(&zcrypt_rescan_req, 1); |
114 | zdev->online = 0; | 113 | zdev->online = 0; |
114 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
115 | zdev->ap_dev->qid); | ||
115 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | 116 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", |
116 | zdev->ap_dev->qid, | 117 | zdev->ap_dev->qid, zdev->online, ehdr->reply_code); |
117 | zdev->online, ehdr->reply_code); | ||
118 | return -EAGAIN; | 118 | return -EAGAIN; |
119 | case REP82_ERROR_TRANSPORT_FAIL: | 119 | case REP82_ERROR_TRANSPORT_FAIL: |
120 | case REP82_ERROR_MACHINE_FAILURE: | 120 | case REP82_ERROR_MACHINE_FAILURE: |
@@ -122,15 +122,17 @@ static inline int convert_error(struct zcrypt_device *zdev, | |||
122 | /* If a card fails disable it and repeat the request. */ | 122 | /* If a card fails disable it and repeat the request. */ |
123 | atomic_set(&zcrypt_rescan_req, 1); | 123 | atomic_set(&zcrypt_rescan_req, 1); |
124 | zdev->online = 0; | 124 | zdev->online = 0; |
125 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
126 | zdev->ap_dev->qid); | ||
125 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | 127 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", |
126 | zdev->ap_dev->qid, | 128 | zdev->ap_dev->qid, zdev->online, ehdr->reply_code); |
127 | zdev->online, ehdr->reply_code); | ||
128 | return -EAGAIN; | 129 | return -EAGAIN; |
129 | default: | 130 | default: |
130 | zdev->online = 0; | 131 | zdev->online = 0; |
132 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
133 | zdev->ap_dev->qid); | ||
131 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | 134 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", |
132 | zdev->ap_dev->qid, | 135 | zdev->ap_dev->qid, zdev->online, ehdr->reply_code); |
133 | zdev->online, ehdr->reply_code); | ||
134 | return -EAGAIN; /* repeat the request on a different device. */ | 136 | return -EAGAIN; /* repeat the request on a different device. */ |
135 | } | 137 | } |
136 | } | 138 | } |
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c index 7c522f338bda..334e282f255b 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ b/drivers/s390/crypto/zcrypt_msgtype50.c | |||
@@ -25,6 +25,9 @@ | |||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define KMSG_COMPONENT "zcrypt" | ||
29 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
30 | |||
28 | #include <linux/module.h> | 31 | #include <linux/module.h> |
29 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
30 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -332,6 +335,11 @@ static int convert_type80(struct zcrypt_device *zdev, | |||
332 | if (t80h->len < sizeof(*t80h) + outputdatalength) { | 335 | if (t80h->len < sizeof(*t80h) + outputdatalength) { |
333 | /* The result is too short, the CEX2A card may not do that.. */ | 336 | /* The result is too short, the CEX2A card may not do that.. */ |
334 | zdev->online = 0; | 337 | zdev->online = 0; |
338 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
339 | zdev->ap_dev->qid); | ||
340 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
341 | zdev->ap_dev->qid, zdev->online, t80h->code); | ||
342 | |||
335 | return -EAGAIN; /* repeat the request on a different device. */ | 343 | return -EAGAIN; /* repeat the request on a different device. */ |
336 | } | 344 | } |
337 | if (zdev->user_space_type == ZCRYPT_CEX2A) | 345 | if (zdev->user_space_type == ZCRYPT_CEX2A) |
@@ -359,6 +367,10 @@ static int convert_response(struct zcrypt_device *zdev, | |||
359 | outputdata, outputdatalength); | 367 | outputdata, outputdatalength); |
360 | default: /* Unknown response type, this should NEVER EVER happen */ | 368 | default: /* Unknown response type, this should NEVER EVER happen */ |
361 | zdev->online = 0; | 369 | zdev->online = 0; |
370 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
371 | zdev->ap_dev->qid); | ||
372 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
373 | zdev->ap_dev->qid, zdev->online); | ||
362 | return -EAGAIN; /* repeat the request on a different device. */ | 374 | return -EAGAIN; /* repeat the request on a different device. */ |
363 | } | 375 | } |
364 | } | 376 | } |
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index 7d97fa5a26d0..dc542e0a3055 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c | |||
@@ -25,6 +25,9 @@ | |||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define KMSG_COMPONENT "zcrypt" | ||
29 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
30 | |||
28 | #include <linux/module.h> | 31 | #include <linux/module.h> |
29 | #include <linux/init.h> | 32 | #include <linux/init.h> |
30 | #include <linux/err.h> | 33 | #include <linux/err.h> |
@@ -50,6 +53,7 @@ struct response_type { | |||
50 | }; | 53 | }; |
51 | #define PCIXCC_RESPONSE_TYPE_ICA 0 | 54 | #define PCIXCC_RESPONSE_TYPE_ICA 0 |
52 | #define PCIXCC_RESPONSE_TYPE_XCRB 1 | 55 | #define PCIXCC_RESPONSE_TYPE_XCRB 1 |
56 | #define PCIXCC_RESPONSE_TYPE_EP11 2 | ||
53 | 57 | ||
54 | MODULE_AUTHOR("IBM Corporation"); | 58 | MODULE_AUTHOR("IBM Corporation"); |
55 | MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \ | 59 | MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \ |
@@ -358,6 +362,91 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, | |||
358 | return 0; | 362 | return 0; |
359 | } | 363 | } |
360 | 364 | ||
365 | static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev, | ||
366 | struct ap_message *ap_msg, | ||
367 | struct ep11_urb *xcRB) | ||
368 | { | ||
369 | unsigned int lfmt; | ||
370 | |||
371 | static struct type6_hdr static_type6_ep11_hdr = { | ||
372 | .type = 0x06, | ||
373 | .rqid = {0x00, 0x01}, | ||
374 | .function_code = {0x00, 0x00}, | ||
375 | .agent_id[0] = 0x58, /* {'X'} */ | ||
376 | .agent_id[1] = 0x43, /* {'C'} */ | ||
377 | .offset1 = 0x00000058, | ||
378 | }; | ||
379 | |||
380 | struct { | ||
381 | struct type6_hdr hdr; | ||
382 | struct ep11_cprb cprbx; | ||
383 | unsigned char pld_tag; /* fixed value 0x30 */ | ||
384 | unsigned char pld_lenfmt; /* payload length format */ | ||
385 | } __packed * msg = ap_msg->message; | ||
386 | |||
387 | struct pld_hdr { | ||
388 | unsigned char func_tag; /* fixed value 0x4 */ | ||
389 | unsigned char func_len; /* fixed value 0x4 */ | ||
390 | unsigned int func_val; /* function ID */ | ||
391 | unsigned char dom_tag; /* fixed value 0x4 */ | ||
392 | unsigned char dom_len; /* fixed value 0x4 */ | ||
393 | unsigned int dom_val; /* domain id */ | ||
394 | } __packed * payload_hdr; | ||
395 | |||
396 | /* length checks */ | ||
397 | ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len; | ||
398 | if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE - | ||
399 | (sizeof(struct type6_hdr))) | ||
400 | return -EINVAL; | ||
401 | |||
402 | if (CEIL4(xcRB->resp_len) > MSGTYPE06_MAX_MSG_SIZE - | ||
403 | (sizeof(struct type86_fmt2_msg))) | ||
404 | return -EINVAL; | ||
405 | |||
406 | /* prepare type6 header */ | ||
407 | msg->hdr = static_type6_ep11_hdr; | ||
408 | msg->hdr.ToCardLen1 = xcRB->req_len; | ||
409 | msg->hdr.FromCardLen1 = xcRB->resp_len; | ||
410 | |||
411 | /* Import CPRB data from the ioctl input parameter */ | ||
412 | if (copy_from_user(&(msg->cprbx.cprb_len), | ||
413 | (char *)xcRB->req, xcRB->req_len)) { | ||
414 | return -EFAULT; | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | The target domain field within the cprb body/payload block will be | ||
419 | replaced by the usage domain for non-management commands only. | ||
420 | Therefore we check the first bit of the 'flags' parameter for | ||
421 | management command indication. | ||
422 | 0 - non management command | ||
423 | 1 - management command | ||
424 | */ | ||
425 | if (!((msg->cprbx.flags & 0x80) == 0x80)) { | ||
426 | msg->cprbx.target_id = (unsigned int) | ||
427 | AP_QID_QUEUE(zdev->ap_dev->qid); | ||
428 | |||
429 | if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/ | ||
430 | switch (msg->pld_lenfmt & 0x03) { | ||
431 | case 1: | ||
432 | lfmt = 2; | ||
433 | break; | ||
434 | case 2: | ||
435 | lfmt = 3; | ||
436 | break; | ||
437 | default: | ||
438 | return -EINVAL; | ||
439 | } | ||
440 | } else { | ||
441 | lfmt = 1; /* length format #1 */ | ||
442 | } | ||
443 | payload_hdr = (struct pld_hdr *)((&(msg->pld_lenfmt))+lfmt); | ||
444 | payload_hdr->dom_val = (unsigned int) | ||
445 | AP_QID_QUEUE(zdev->ap_dev->qid); | ||
446 | } | ||
447 | return 0; | ||
448 | } | ||
449 | |||
361 | /** | 450 | /** |
362 | * Copy results from a type 86 ICA reply message back to user space. | 451 | * Copy results from a type 86 ICA reply message back to user space. |
363 | * | 452 | * |
@@ -377,6 +466,12 @@ struct type86x_reply { | |||
377 | char text[0]; | 466 | char text[0]; |
378 | } __packed; | 467 | } __packed; |
379 | 468 | ||
469 | struct type86_ep11_reply { | ||
470 | struct type86_hdr hdr; | ||
471 | struct type86_fmt2_ext fmt2; | ||
472 | struct ep11_cprb cprbx; | ||
473 | } __packed; | ||
474 | |||
380 | static int convert_type86_ica(struct zcrypt_device *zdev, | 475 | static int convert_type86_ica(struct zcrypt_device *zdev, |
381 | struct ap_message *reply, | 476 | struct ap_message *reply, |
382 | char __user *outputdata, | 477 | char __user *outputdata, |
@@ -440,6 +535,11 @@ static int convert_type86_ica(struct zcrypt_device *zdev, | |||
440 | if (service_rc == 8 && service_rs == 72) | 535 | if (service_rc == 8 && service_rs == 72) |
441 | return -EINVAL; | 536 | return -EINVAL; |
442 | zdev->online = 0; | 537 | zdev->online = 0; |
538 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
539 | zdev->ap_dev->qid); | ||
540 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
541 | zdev->ap_dev->qid, zdev->online, | ||
542 | msg->hdr.reply_code); | ||
443 | return -EAGAIN; /* repeat the request on a different device. */ | 543 | return -EAGAIN; /* repeat the request on a different device. */ |
444 | } | 544 | } |
445 | data = msg->text; | 545 | data = msg->text; |
@@ -503,6 +603,33 @@ static int convert_type86_xcrb(struct zcrypt_device *zdev, | |||
503 | return 0; | 603 | return 0; |
504 | } | 604 | } |
505 | 605 | ||
606 | /** | ||
607 | * Copy results from a type 86 EP11 XCRB reply message back to user space. | ||
608 | * | ||
609 | * @zdev: crypto device pointer | ||
610 | * @reply: reply AP message. | ||
611 | * @xcRB: pointer to EP11 user request block | ||
612 | * | ||
613 | * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. | ||
614 | */ | ||
615 | static int convert_type86_ep11_xcrb(struct zcrypt_device *zdev, | ||
616 | struct ap_message *reply, | ||
617 | struct ep11_urb *xcRB) | ||
618 | { | ||
619 | struct type86_fmt2_msg *msg = reply->message; | ||
620 | char *data = reply->message; | ||
621 | |||
622 | if (xcRB->resp_len < msg->fmt2.count1) | ||
623 | return -EINVAL; | ||
624 | |||
625 | /* Copy response CPRB to user */ | ||
626 | if (copy_to_user((char *)xcRB->resp, | ||
627 | data + msg->fmt2.offset1, msg->fmt2.count1)) | ||
628 | return -EFAULT; | ||
629 | xcRB->resp_len = msg->fmt2.count1; | ||
630 | return 0; | ||
631 | } | ||
632 | |||
506 | static int convert_type86_rng(struct zcrypt_device *zdev, | 633 | static int convert_type86_rng(struct zcrypt_device *zdev, |
507 | struct ap_message *reply, | 634 | struct ap_message *reply, |
508 | char *buffer) | 635 | char *buffer) |
@@ -551,6 +678,10 @@ static int convert_response_ica(struct zcrypt_device *zdev, | |||
551 | * response */ | 678 | * response */ |
552 | default: /* Unknown response type, this should NEVER EVER happen */ | 679 | default: /* Unknown response type, this should NEVER EVER happen */ |
553 | zdev->online = 0; | 680 | zdev->online = 0; |
681 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
682 | zdev->ap_dev->qid); | ||
683 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
684 | zdev->ap_dev->qid, zdev->online); | ||
554 | return -EAGAIN; /* repeat the request on a different device. */ | 685 | return -EAGAIN; /* repeat the request on a different device. */ |
555 | } | 686 | } |
556 | } | 687 | } |
@@ -579,10 +710,40 @@ static int convert_response_xcrb(struct zcrypt_device *zdev, | |||
579 | default: /* Unknown response type, this should NEVER EVER happen */ | 710 | default: /* Unknown response type, this should NEVER EVER happen */ |
580 | xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ | 711 | xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ |
581 | zdev->online = 0; | 712 | zdev->online = 0; |
713 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
714 | zdev->ap_dev->qid); | ||
715 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
716 | zdev->ap_dev->qid, zdev->online); | ||
582 | return -EAGAIN; /* repeat the request on a different device. */ | 717 | return -EAGAIN; /* repeat the request on a different device. */ |
583 | } | 718 | } |
584 | } | 719 | } |
585 | 720 | ||
721 | static int convert_response_ep11_xcrb(struct zcrypt_device *zdev, | ||
722 | struct ap_message *reply, struct ep11_urb *xcRB) | ||
723 | { | ||
724 | struct type86_ep11_reply *msg = reply->message; | ||
725 | |||
726 | /* Response type byte is the second byte in the response. */ | ||
727 | switch (((unsigned char *)reply->message)[1]) { | ||
728 | case TYPE82_RSP_CODE: | ||
729 | case TYPE87_RSP_CODE: | ||
730 | return convert_error(zdev, reply); | ||
731 | case TYPE86_RSP_CODE: | ||
732 | if (msg->hdr.reply_code) | ||
733 | return convert_error(zdev, reply); | ||
734 | if (msg->cprbx.cprb_ver_id == 0x04) | ||
735 | return convert_type86_ep11_xcrb(zdev, reply, xcRB); | ||
736 | /* Fall through, no break, incorrect cprb version is an unknown resp.*/ | ||
737 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
738 | zdev->online = 0; | ||
739 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
740 | zdev->ap_dev->qid); | ||
741 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
742 | zdev->ap_dev->qid, zdev->online); | ||
743 | return -EAGAIN; /* repeat the request on a different device. */ | ||
744 | } | ||
745 | } | ||
746 | |||
586 | static int convert_response_rng(struct zcrypt_device *zdev, | 747 | static int convert_response_rng(struct zcrypt_device *zdev, |
587 | struct ap_message *reply, | 748 | struct ap_message *reply, |
588 | char *data) | 749 | char *data) |
@@ -602,6 +763,10 @@ static int convert_response_rng(struct zcrypt_device *zdev, | |||
602 | * response */ | 763 | * response */ |
603 | default: /* Unknown response type, this should NEVER EVER happen */ | 764 | default: /* Unknown response type, this should NEVER EVER happen */ |
604 | zdev->online = 0; | 765 | zdev->online = 0; |
766 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
767 | zdev->ap_dev->qid); | ||
768 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
769 | zdev->ap_dev->qid, zdev->online); | ||
605 | return -EAGAIN; /* repeat the request on a different device. */ | 770 | return -EAGAIN; /* repeat the request on a different device. */ |
606 | } | 771 | } |
607 | } | 772 | } |
@@ -657,6 +822,51 @@ out: | |||
657 | complete(&(resp_type->work)); | 822 | complete(&(resp_type->work)); |
658 | } | 823 | } |
659 | 824 | ||
825 | /** | ||
826 | * This function is called from the AP bus code after a crypto request | ||
827 | * "msg" has finished with the reply message "reply". | ||
828 | * It is called from tasklet context. | ||
829 | * @ap_dev: pointer to the AP device | ||
830 | * @msg: pointer to the AP message | ||
831 | * @reply: pointer to the AP reply message | ||
832 | */ | ||
833 | static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev, | ||
834 | struct ap_message *msg, | ||
835 | struct ap_message *reply) | ||
836 | { | ||
837 | static struct error_hdr error_reply = { | ||
838 | .type = TYPE82_RSP_CODE, | ||
839 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | ||
840 | }; | ||
841 | struct response_type *resp_type = | ||
842 | (struct response_type *)msg->private; | ||
843 | struct type86_ep11_reply *t86r; | ||
844 | int length; | ||
845 | |||
846 | /* Copy the reply message to the request message buffer. */ | ||
847 | if (IS_ERR(reply)) { | ||
848 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | ||
849 | goto out; | ||
850 | } | ||
851 | t86r = reply->message; | ||
852 | if (t86r->hdr.type == TYPE86_RSP_CODE && | ||
853 | t86r->cprbx.cprb_ver_id == 0x04) { | ||
854 | switch (resp_type->type) { | ||
855 | case PCIXCC_RESPONSE_TYPE_EP11: | ||
856 | length = t86r->fmt2.offset1 + t86r->fmt2.count1; | ||
857 | length = min(MSGTYPE06_MAX_MSG_SIZE, length); | ||
858 | memcpy(msg->message, reply->message, length); | ||
859 | break; | ||
860 | default: | ||
861 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | ||
862 | } | ||
863 | } else { | ||
864 | memcpy(msg->message, reply->message, sizeof(error_reply)); | ||
865 | } | ||
866 | out: | ||
867 | complete(&(resp_type->work)); | ||
868 | } | ||
869 | |||
660 | static atomic_t zcrypt_step = ATOMIC_INIT(0); | 870 | static atomic_t zcrypt_step = ATOMIC_INIT(0); |
661 | 871 | ||
662 | /** | 872 | /** |
@@ -782,6 +992,46 @@ out_free: | |||
782 | } | 992 | } |
783 | 993 | ||
784 | /** | 994 | /** |
995 | * The request distributor calls this function if it picked the CEX4P | ||
996 | * device to handle a send_ep11_cprb request. | ||
997 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
998 | * CEX4P device to the request distributor | ||
999 | * @xcRB: pointer to the ep11 user request block | ||
1000 | */ | ||
1001 | static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev, | ||
1002 | struct ep11_urb *xcrb) | ||
1003 | { | ||
1004 | struct ap_message ap_msg; | ||
1005 | struct response_type resp_type = { | ||
1006 | .type = PCIXCC_RESPONSE_TYPE_EP11, | ||
1007 | }; | ||
1008 | int rc; | ||
1009 | |||
1010 | ap_init_message(&ap_msg); | ||
1011 | ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | ||
1012 | if (!ap_msg.message) | ||
1013 | return -ENOMEM; | ||
1014 | ap_msg.receive = zcrypt_msgtype6_receive_ep11; | ||
1015 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
1016 | atomic_inc_return(&zcrypt_step); | ||
1017 | ap_msg.private = &resp_type; | ||
1018 | rc = xcrb_msg_to_type6_ep11cprb_msgx(zdev, &ap_msg, xcrb); | ||
1019 | if (rc) | ||
1020 | goto out_free; | ||
1021 | init_completion(&resp_type.work); | ||
1022 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
1023 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
1024 | if (rc == 0) | ||
1025 | rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb); | ||
1026 | else /* Signal pending. */ | ||
1027 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
1028 | |||
1029 | out_free: | ||
1030 | kzfree(ap_msg.message); | ||
1031 | return rc; | ||
1032 | } | ||
1033 | |||
1034 | /** | ||
785 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | 1035 | * The request distributor calls this function if it picked the PCIXCC/CEX2C |
786 | * device to generate random data. | 1036 | * device to generate random data. |
787 | * @zdev: pointer to zcrypt_device structure that identifies the | 1037 | * @zdev: pointer to zcrypt_device structure that identifies the |
@@ -839,10 +1089,19 @@ static struct zcrypt_ops zcrypt_msgtype6_ops = { | |||
839 | .rng = zcrypt_msgtype6_rng, | 1089 | .rng = zcrypt_msgtype6_rng, |
840 | }; | 1090 | }; |
841 | 1091 | ||
1092 | static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = { | ||
1093 | .owner = THIS_MODULE, | ||
1094 | .variant = MSGTYPE06_VARIANT_EP11, | ||
1095 | .rsa_modexpo = NULL, | ||
1096 | .rsa_modexpo_crt = NULL, | ||
1097 | .send_ep11_cprb = zcrypt_msgtype6_send_ep11_cprb, | ||
1098 | }; | ||
1099 | |||
842 | int __init zcrypt_msgtype6_init(void) | 1100 | int __init zcrypt_msgtype6_init(void) |
843 | { | 1101 | { |
844 | zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops); | 1102 | zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops); |
845 | zcrypt_msgtype_register(&zcrypt_msgtype6_ops); | 1103 | zcrypt_msgtype_register(&zcrypt_msgtype6_ops); |
1104 | zcrypt_msgtype_register(&zcrypt_msgtype6_ep11_ops); | ||
846 | return 0; | 1105 | return 0; |
847 | } | 1106 | } |
848 | 1107 | ||
@@ -850,6 +1109,7 @@ void __exit zcrypt_msgtype6_exit(void) | |||
850 | { | 1109 | { |
851 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops); | 1110 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops); |
852 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops); | 1111 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops); |
1112 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_ep11_ops); | ||
853 | } | 1113 | } |
854 | 1114 | ||
855 | module_init(zcrypt_msgtype6_init); | 1115 | module_init(zcrypt_msgtype6_init); |
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.h b/drivers/s390/crypto/zcrypt_msgtype6.h index 1e500d3c0735..207247570623 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.h +++ b/drivers/s390/crypto/zcrypt_msgtype6.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define MSGTYPE06_NAME "zcrypt_msgtype6" | 32 | #define MSGTYPE06_NAME "zcrypt_msgtype6" |
33 | #define MSGTYPE06_VARIANT_DEFAULT 0 | 33 | #define MSGTYPE06_VARIANT_DEFAULT 0 |
34 | #define MSGTYPE06_VARIANT_NORNG 1 | 34 | #define MSGTYPE06_VARIANT_NORNG 1 |
35 | #define MSGTYPE06_VARIANT_EP11 2 | ||
35 | 36 | ||
36 | #define MSGTYPE06_MAX_MSG_SIZE (12*1024) | 37 | #define MSGTYPE06_MAX_MSG_SIZE (12*1024) |
37 | 38 | ||
@@ -99,6 +100,7 @@ struct type86_hdr { | |||
99 | } __packed; | 100 | } __packed; |
100 | 101 | ||
101 | #define TYPE86_RSP_CODE 0x86 | 102 | #define TYPE86_RSP_CODE 0x86 |
103 | #define TYPE87_RSP_CODE 0x87 | ||
102 | #define TYPE86_FMT2 0x02 | 104 | #define TYPE86_FMT2 0x02 |
103 | 105 | ||
104 | struct type86_fmt2_ext { | 106 | struct type86_fmt2_ext { |
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c index f2b71d8df01f..7a743f4c646c 100644 --- a/drivers/s390/crypto/zcrypt_pcica.c +++ b/drivers/s390/crypto/zcrypt_pcica.c | |||
@@ -24,6 +24,9 @@ | |||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define KMSG_COMPONENT "zcrypt" | ||
28 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
29 | |||
27 | #include <linux/module.h> | 30 | #include <linux/module.h> |
28 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
29 | #include <linux/init.h> | 32 | #include <linux/init.h> |
@@ -199,6 +202,10 @@ static int convert_type84(struct zcrypt_device *zdev, | |||
199 | if (t84h->len < sizeof(*t84h) + outputdatalength) { | 202 | if (t84h->len < sizeof(*t84h) + outputdatalength) { |
200 | /* The result is too short, the PCICA card may not do that.. */ | 203 | /* The result is too short, the PCICA card may not do that.. */ |
201 | zdev->online = 0; | 204 | zdev->online = 0; |
205 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
206 | zdev->ap_dev->qid); | ||
207 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
208 | zdev->ap_dev->qid, zdev->online, t84h->code); | ||
202 | return -EAGAIN; /* repeat the request on a different device. */ | 209 | return -EAGAIN; /* repeat the request on a different device. */ |
203 | } | 210 | } |
204 | BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE); | 211 | BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE); |
@@ -223,6 +230,10 @@ static int convert_response(struct zcrypt_device *zdev, | |||
223 | outputdata, outputdatalength); | 230 | outputdata, outputdatalength); |
224 | default: /* Unknown response type, this should NEVER EVER happen */ | 231 | default: /* Unknown response type, this should NEVER EVER happen */ |
225 | zdev->online = 0; | 232 | zdev->online = 0; |
233 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
234 | zdev->ap_dev->qid); | ||
235 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
236 | zdev->ap_dev->qid, zdev->online); | ||
226 | return -EAGAIN; /* repeat the request on a different device. */ | 237 | return -EAGAIN; /* repeat the request on a different device. */ |
227 | } | 238 | } |
228 | } | 239 | } |
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c index 0d90a4334055..4d14c04b746e 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.c +++ b/drivers/s390/crypto/zcrypt_pcicc.c | |||
@@ -24,6 +24,9 @@ | |||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define KMSG_COMPONENT "zcrypt" | ||
28 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
29 | |||
27 | #include <linux/module.h> | 30 | #include <linux/module.h> |
28 | #include <linux/init.h> | 31 | #include <linux/init.h> |
29 | #include <linux/gfp.h> | 32 | #include <linux/gfp.h> |
@@ -372,6 +375,11 @@ static int convert_type86(struct zcrypt_device *zdev, | |||
372 | if (service_rc == 8 && service_rs == 72) | 375 | if (service_rc == 8 && service_rs == 72) |
373 | return -EINVAL; | 376 | return -EINVAL; |
374 | zdev->online = 0; | 377 | zdev->online = 0; |
378 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
379 | zdev->ap_dev->qid); | ||
380 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
381 | zdev->ap_dev->qid, zdev->online, | ||
382 | msg->hdr.reply_code); | ||
375 | return -EAGAIN; /* repeat the request on a different device. */ | 383 | return -EAGAIN; /* repeat the request on a different device. */ |
376 | } | 384 | } |
377 | data = msg->text; | 385 | data = msg->text; |
@@ -425,6 +433,10 @@ static int convert_response(struct zcrypt_device *zdev, | |||
425 | /* no break, incorrect cprb version is an unknown response */ | 433 | /* no break, incorrect cprb version is an unknown response */ |
426 | default: /* Unknown response type, this should NEVER EVER happen */ | 434 | default: /* Unknown response type, this should NEVER EVER happen */ |
427 | zdev->online = 0; | 435 | zdev->online = 0; |
436 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
437 | zdev->ap_dev->qid); | ||
438 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
439 | zdev->ap_dev->qid, zdev->online); | ||
428 | return -EAGAIN; /* repeat the request on a different device. */ | 440 | return -EAGAIN; /* repeat the request on a different device. */ |
429 | } | 441 | } |
430 | } | 442 | } |
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 30fa38a0ad39..9176bfbd5745 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c | |||
@@ -201,7 +201,7 @@ static int a2091_probe(struct zorro_dev *z, const struct zorro_device_id *ent) | |||
201 | instance->irq = IRQ_AMIGA_PORTS; | 201 | instance->irq = IRQ_AMIGA_PORTS; |
202 | instance->unique_id = z->slotaddr; | 202 | instance->unique_id = z->slotaddr; |
203 | 203 | ||
204 | regs = (struct a2091_scsiregs *)ZTWO_VADDR(z->resource.start); | 204 | regs = ZTWO_VADDR(z->resource.start); |
205 | regs->DAWR = DAWR_A2091; | 205 | regs->DAWR = DAWR_A2091; |
206 | 206 | ||
207 | wdregs.SASR = ®s->SASR; | 207 | wdregs.SASR = ®s->SASR; |
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index c0f4f4290dd6..dd5b64726ddc 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c | |||
@@ -220,7 +220,7 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) | |||
220 | 220 | ||
221 | instance->irq = IRQ_AMIGA_PORTS; | 221 | instance->irq = IRQ_AMIGA_PORTS; |
222 | 222 | ||
223 | regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start); | 223 | regs = ZTWO_VADDR(res->start); |
224 | regs->DAWR = DAWR_A3000; | 224 | regs->DAWR = DAWR_A3000; |
225 | 225 | ||
226 | wdregs.SASR = ®s->SASR; | 226 | wdregs.SASR = ®s->SASR; |
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 70c521f79f7c..f5a2ab41543b 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c | |||
@@ -56,7 +56,7 @@ static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev) | |||
56 | scsi_addr = res->start + A4000T_SCSI_OFFSET; | 56 | scsi_addr = res->start + A4000T_SCSI_OFFSET; |
57 | 57 | ||
58 | /* Fill in the required pieces of hostdata */ | 58 | /* Fill in the required pieces of hostdata */ |
59 | hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr); | 59 | hostdata->base = ZTWO_VADDR(scsi_addr); |
60 | hostdata->clock = 50; | 60 | hostdata->clock = 50; |
61 | hostdata->chip710 = 1; | 61 | hostdata->chip710 = 1; |
62 | hostdata->dmode_extra = DMODE_FC2; | 62 | hostdata->dmode_extra = DMODE_FC2; |
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 2203ac281103..3b6f83ffddc4 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c | |||
@@ -310,7 +310,7 @@ static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent) | |||
310 | if (!request_mem_region(address, 256, "wd33c93")) | 310 | if (!request_mem_region(address, 256, "wd33c93")) |
311 | return -EBUSY; | 311 | return -EBUSY; |
312 | 312 | ||
313 | regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address)); | 313 | regs = ZTWO_VADDR(address); |
314 | 314 | ||
315 | error = check_wd33c93(regs); | 315 | error = check_wd33c93(regs); |
316 | if (error) | 316 | if (error) |
diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index cbf3476c68cd..aff31991aea9 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c | |||
@@ -104,7 +104,7 @@ static int zorro7xx_init_one(struct zorro_dev *z, | |||
104 | if (ioaddr > 0x01000000) | 104 | if (ioaddr > 0x01000000) |
105 | hostdata->base = ioremap(ioaddr, zorro_resource_len(z)); | 105 | hostdata->base = ioremap(ioaddr, zorro_resource_len(z)); |
106 | else | 106 | else |
107 | hostdata->base = (void __iomem *)ZTWO_VADDR(ioaddr); | 107 | hostdata->base = ZTWO_VADDR(ioaddr); |
108 | 108 | ||
109 | hostdata->clock = 50; | 109 | hostdata->clock = 50; |
110 | hostdata->chip710 = 1; | 110 | hostdata->chip710 = 1; |
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index 8f181b3f842b..d833c8f5b465 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c | |||
@@ -438,14 +438,12 @@ static int clamp_thread(void *arg) | |||
438 | */ | 438 | */ |
439 | local_touch_nmi(); | 439 | local_touch_nmi(); |
440 | stop_critical_timings(); | 440 | stop_critical_timings(); |
441 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | 441 | mwait_idle_with_hints(eax, ecx); |
442 | cpu_relax(); /* allow HT sibling to run */ | ||
443 | __mwait(eax, ecx); | ||
444 | start_critical_timings(); | 442 | start_critical_timings(); |
445 | atomic_inc(&idle_wakeup_counter); | 443 | atomic_inc(&idle_wakeup_counter); |
446 | } | 444 | } |
447 | tick_nohz_idle_exit(); | 445 | tick_nohz_idle_exit(); |
448 | preempt_enable_no_resched(); | 446 | preempt_enable(); |
449 | } | 447 | } |
450 | del_timer_sync(&wakeup_timer); | 448 | del_timer_sync(&wakeup_timer); |
451 | clear_bit(cpunr, cpu_clamping_mask); | 449 | clear_bit(cpunr, cpu_clamping_mask); |
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 0dac36ce09d6..518f790ef88a 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
@@ -3710,7 +3710,7 @@ default_chipset: | |||
3710 | if (!videomemory) { | 3710 | if (!videomemory) { |
3711 | dev_warn(&pdev->dev, | 3711 | dev_warn(&pdev->dev, |
3712 | "Unable to map videomem cached writethrough\n"); | 3712 | "Unable to map videomem cached writethrough\n"); |
3713 | info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start); | 3713 | info->screen_base = ZTWO_VADDR(info->fix.smem_start); |
3714 | } else | 3714 | } else |
3715 | info->screen_base = (char *)videomemory; | 3715 | info->screen_base = (char *)videomemory; |
3716 | 3716 | ||
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 5aab9b9dc210..d992aa5eb3f0 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
@@ -2256,7 +2256,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, | |||
2256 | 2256 | ||
2257 | info->fix.mmio_start = regbase; | 2257 | info->fix.mmio_start = regbase; |
2258 | cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024) | 2258 | cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024) |
2259 | : (caddr_t)ZTWO_VADDR(regbase); | 2259 | : ZTWO_VADDR(regbase); |
2260 | if (!cinfo->regbase) { | 2260 | if (!cinfo->regbase) { |
2261 | dev_err(info->device, "Cannot map registers\n"); | 2261 | dev_err(info->device, "Cannot map registers\n"); |
2262 | error = -EIO; | 2262 | error = -EIO; |
@@ -2266,7 +2266,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, | |||
2266 | info->fix.smem_start = rambase; | 2266 | info->fix.smem_start = rambase; |
2267 | info->screen_size = ramsize; | 2267 | info->screen_size = ramsize; |
2268 | info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize) | 2268 | info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize) |
2269 | : (caddr_t)ZTWO_VADDR(rambase); | 2269 | : ZTWO_VADDR(rambase); |
2270 | if (!info->screen_base) { | 2270 | if (!info->screen_base) { |
2271 | dev_err(info->device, "Cannot map video RAM\n"); | 2271 | dev_err(info->device, "Cannot map video RAM\n"); |
2272 | error = -EIO; | 2272 | error = -EIO; |
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 5bd2eb8d4f39..cda7587cbc86 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/fb.h> | 34 | #include <linux/fb.h> |
35 | 35 | ||
36 | #include <asm/setup.h> | 36 | #include <asm/setup.h> |
37 | #include <asm/bootinfo.h> | ||
38 | #include <asm/macintosh.h> | 37 | #include <asm/macintosh.h> |
39 | #include <asm/io.h> | 38 | #include <asm/io.h> |
40 | 39 | ||
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index e287ebc47817..97cb9bd1d1dd 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c | |||
@@ -56,7 +56,6 @@ | |||
56 | #include <linux/cuda.h> | 56 | #include <linux/cuda.h> |
57 | #include <asm/io.h> | 57 | #include <asm/io.h> |
58 | #ifdef CONFIG_MAC | 58 | #ifdef CONFIG_MAC |
59 | #include <asm/bootinfo.h> | ||
60 | #include <asm/macintosh.h> | 59 | #include <asm/macintosh.h> |
61 | #else | 60 | #else |
62 | #include <asm/prom.h> | 61 | #include <asm/prom.h> |
diff --git a/drivers/zorro/Makefile b/drivers/zorro/Makefile index f62172603215..7dc5332ff984 100644 --- a/drivers/zorro/Makefile +++ b/drivers/zorro/Makefile | |||
@@ -2,8 +2,9 @@ | |||
2 | # Makefile for the Zorro bus specific drivers. | 2 | # Makefile for the Zorro bus specific drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_ZORRO) += zorro.o zorro-driver.o zorro-sysfs.o names.o | 5 | obj-$(CONFIG_ZORRO) += zorro.o zorro-driver.o zorro-sysfs.o |
6 | obj-$(CONFIG_PROC_FS) += proc.o | 6 | obj-$(CONFIG_PROC_FS) += proc.o |
7 | obj-$(CONFIG_ZORRO_NAMES) += names.o | ||
7 | 8 | ||
8 | hostprogs-y := gen-devlist | 9 | hostprogs-y := gen-devlist |
9 | 10 | ||
diff --git a/drivers/zorro/names.c b/drivers/zorro/names.c index e8517c3d8e82..6f3fd9903ac3 100644 --- a/drivers/zorro/names.c +++ b/drivers/zorro/names.c | |||
@@ -15,8 +15,6 @@ | |||
15 | #include <linux/zorro.h> | 15 | #include <linux/zorro.h> |
16 | 16 | ||
17 | 17 | ||
18 | #ifdef CONFIG_ZORRO_NAMES | ||
19 | |||
20 | struct zorro_prod_info { | 18 | struct zorro_prod_info { |
21 | __u16 prod; | 19 | __u16 prod; |
22 | unsigned short seen; | 20 | unsigned short seen; |
@@ -69,7 +67,6 @@ void __init zorro_name_device(struct zorro_dev *dev) | |||
69 | } while (--i); | 67 | } while (--i); |
70 | 68 | ||
71 | /* Couldn't find either the manufacturer nor the product */ | 69 | /* Couldn't find either the manufacturer nor the product */ |
72 | sprintf(name, "Zorro device %08x", dev->id); | ||
73 | return; | 70 | return; |
74 | 71 | ||
75 | match_manuf: { | 72 | match_manuf: { |
@@ -98,11 +95,3 @@ void __init zorro_name_device(struct zorro_dev *dev) | |||
98 | } | 95 | } |
99 | } | 96 | } |
100 | } | 97 | } |
101 | |||
102 | #else | ||
103 | |||
104 | void __init zorro_name_device(struct zorro_dev *dev) | ||
105 | { | ||
106 | } | ||
107 | |||
108 | #endif | ||
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index ea1ce822a8e0..6ac2579da0eb 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/export.h> | 16 | #include <linux/export.h> |
17 | |||
18 | #include <asm/byteorder.h> | ||
17 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
18 | #include <asm/amigahw.h> | 20 | #include <asm/amigahw.h> |
19 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
@@ -41,10 +43,10 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t * | |||
41 | /* Construct a ConfigDev */ | 43 | /* Construct a ConfigDev */ |
42 | memset(&cd, 0, sizeof(cd)); | 44 | memset(&cd, 0, sizeof(cd)); |
43 | cd.cd_Rom = z->rom; | 45 | cd.cd_Rom = z->rom; |
44 | cd.cd_SlotAddr = z->slotaddr; | 46 | cd.cd_SlotAddr = cpu_to_be16(z->slotaddr); |
45 | cd.cd_SlotSize = z->slotsize; | 47 | cd.cd_SlotSize = cpu_to_be16(z->slotsize); |
46 | cd.cd_BoardAddr = (void *)zorro_resource_start(z); | 48 | cd.cd_BoardAddr = cpu_to_be32(zorro_resource_start(z)); |
47 | cd.cd_BoardSize = zorro_resource_len(z); | 49 | cd.cd_BoardSize = cpu_to_be32(zorro_resource_len(z)); |
48 | 50 | ||
49 | if (copy_to_user(buf, (void *)&cd + pos, nbytes)) | 51 | if (copy_to_user(buf, (void *)&cd + pos, nbytes)) |
50 | return -EFAULT; | 52 | return -EFAULT; |
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index ac1db7f1bcab..eacae1434b73 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c | |||
@@ -161,11 +161,12 @@ static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
161 | } | 161 | } |
162 | 162 | ||
163 | struct bus_type zorro_bus_type = { | 163 | struct bus_type zorro_bus_type = { |
164 | .name = "zorro", | 164 | .name = "zorro", |
165 | .match = zorro_bus_match, | 165 | .dev_name = "zorro", |
166 | .uevent = zorro_uevent, | 166 | .match = zorro_bus_match, |
167 | .probe = zorro_device_probe, | 167 | .uevent = zorro_uevent, |
168 | .remove = zorro_device_remove, | 168 | .probe = zorro_device_probe, |
169 | .remove = zorro_device_remove, | ||
169 | }; | 170 | }; |
170 | EXPORT_SYMBOL(zorro_bus_type); | 171 | EXPORT_SYMBOL(zorro_bus_type); |
171 | 172 | ||
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 26f7184ef9e1..36b210f9b6b2 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/stat.h> | 16 | #include <linux/stat.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | 18 | ||
19 | #include <asm/byteorder.h> | ||
20 | |||
19 | #include "zorro.h" | 21 | #include "zorro.h" |
20 | 22 | ||
21 | 23 | ||
@@ -33,10 +35,20 @@ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); | |||
33 | 35 | ||
34 | zorro_config_attr(id, id, "0x%08x\n"); | 36 | zorro_config_attr(id, id, "0x%08x\n"); |
35 | zorro_config_attr(type, rom.er_Type, "0x%02x\n"); | 37 | zorro_config_attr(type, rom.er_Type, "0x%02x\n"); |
36 | zorro_config_attr(serial, rom.er_SerialNumber, "0x%08x\n"); | ||
37 | zorro_config_attr(slotaddr, slotaddr, "0x%04x\n"); | 38 | zorro_config_attr(slotaddr, slotaddr, "0x%04x\n"); |
38 | zorro_config_attr(slotsize, slotsize, "0x%04x\n"); | 39 | zorro_config_attr(slotsize, slotsize, "0x%04x\n"); |
39 | 40 | ||
41 | static ssize_t | ||
42 | show_serial(struct device *dev, struct device_attribute *attr, char *buf) | ||
43 | { | ||
44 | struct zorro_dev *z; | ||
45 | |||
46 | z = to_zorro_dev(dev); | ||
47 | return sprintf(buf, "0x%08x\n", be32_to_cpu(z->rom.er_SerialNumber)); | ||
48 | } | ||
49 | |||
50 | static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); | ||
51 | |||
40 | static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *attr, char *buf) | 52 | static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *attr, char *buf) |
41 | { | 53 | { |
42 | struct zorro_dev *z = to_zorro_dev(dev); | 54 | struct zorro_dev *z = to_zorro_dev(dev); |
@@ -60,10 +72,10 @@ static ssize_t zorro_read_config(struct file *filp, struct kobject *kobj, | |||
60 | /* Construct a ConfigDev */ | 72 | /* Construct a ConfigDev */ |
61 | memset(&cd, 0, sizeof(cd)); | 73 | memset(&cd, 0, sizeof(cd)); |
62 | cd.cd_Rom = z->rom; | 74 | cd.cd_Rom = z->rom; |
63 | cd.cd_SlotAddr = z->slotaddr; | 75 | cd.cd_SlotAddr = cpu_to_be16(z->slotaddr); |
64 | cd.cd_SlotSize = z->slotsize; | 76 | cd.cd_SlotSize = cpu_to_be16(z->slotsize); |
65 | cd.cd_BoardAddr = (void *)zorro_resource_start(z); | 77 | cd.cd_BoardAddr = cpu_to_be32(zorro_resource_start(z)); |
66 | cd.cd_BoardSize = zorro_resource_len(z); | 78 | cd.cd_BoardSize = cpu_to_be32(zorro_resource_len(z)); |
67 | 79 | ||
68 | return memory_read_from_buffer(buf, count, &off, &cd, sizeof(cd)); | 80 | return memory_read_from_buffer(buf, count, &off, &cd, sizeof(cd)); |
69 | } | 81 | } |
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index 858c9714b2f3..707c1a5a0317 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | 20 | ||
21 | #include <asm/byteorder.h> | ||
21 | #include <asm/setup.h> | 22 | #include <asm/setup.h> |
22 | #include <asm/amigahw.h> | 23 | #include <asm/amigahw.h> |
23 | 24 | ||
@@ -29,7 +30,8 @@ | |||
29 | */ | 30 | */ |
30 | 31 | ||
31 | unsigned int zorro_num_autocon; | 32 | unsigned int zorro_num_autocon; |
32 | struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; | 33 | struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata; |
34 | struct zorro_dev *zorro_autocon; | ||
33 | 35 | ||
34 | 36 | ||
35 | /* | 37 | /* |
@@ -38,6 +40,7 @@ struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; | |||
38 | 40 | ||
39 | struct zorro_bus { | 41 | struct zorro_bus { |
40 | struct device dev; | 42 | struct device dev; |
43 | struct zorro_dev devices[0]; | ||
41 | }; | 44 | }; |
42 | 45 | ||
43 | 46 | ||
@@ -125,18 +128,22 @@ static struct resource __init *zorro_find_parent_resource( | |||
125 | static int __init amiga_zorro_probe(struct platform_device *pdev) | 128 | static int __init amiga_zorro_probe(struct platform_device *pdev) |
126 | { | 129 | { |
127 | struct zorro_bus *bus; | 130 | struct zorro_bus *bus; |
131 | struct zorro_dev_init *zi; | ||
128 | struct zorro_dev *z; | 132 | struct zorro_dev *z; |
129 | struct resource *r; | 133 | struct resource *r; |
130 | unsigned int i; | 134 | unsigned int i; |
131 | int error; | 135 | int error; |
132 | 136 | ||
133 | /* Initialize the Zorro bus */ | 137 | /* Initialize the Zorro bus */ |
134 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); | 138 | bus = kzalloc(sizeof(*bus) + |
139 | zorro_num_autocon * sizeof(bus->devices[0]), | ||
140 | GFP_KERNEL); | ||
135 | if (!bus) | 141 | if (!bus) |
136 | return -ENOMEM; | 142 | return -ENOMEM; |
137 | 143 | ||
144 | zorro_autocon = bus->devices; | ||
138 | bus->dev.parent = &pdev->dev; | 145 | bus->dev.parent = &pdev->dev; |
139 | dev_set_name(&bus->dev, "zorro"); | 146 | dev_set_name(&bus->dev, zorro_bus_type.name); |
140 | error = device_register(&bus->dev); | 147 | error = device_register(&bus->dev); |
141 | if (error) { | 148 | if (error) { |
142 | pr_err("Zorro: Error registering zorro_bus\n"); | 149 | pr_err("Zorro: Error registering zorro_bus\n"); |
@@ -151,15 +158,23 @@ static int __init amiga_zorro_probe(struct platform_device *pdev) | |||
151 | 158 | ||
152 | /* First identify all devices ... */ | 159 | /* First identify all devices ... */ |
153 | for (i = 0; i < zorro_num_autocon; i++) { | 160 | for (i = 0; i < zorro_num_autocon; i++) { |
161 | zi = &zorro_autocon_init[i]; | ||
154 | z = &zorro_autocon[i]; | 162 | z = &zorro_autocon[i]; |
155 | z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); | 163 | |
164 | z->rom = zi->rom; | ||
165 | z->id = (be16_to_cpu(z->rom.er_Manufacturer) << 16) | | ||
166 | (z->rom.er_Product << 8); | ||
156 | if (z->id == ZORRO_PROD_GVP_EPC_BASE) { | 167 | if (z->id == ZORRO_PROD_GVP_EPC_BASE) { |
157 | /* GVP quirk */ | 168 | /* GVP quirk */ |
158 | unsigned long magic = zorro_resource_start(z)+0x8000; | 169 | unsigned long magic = zi->boardaddr + 0x8000; |
159 | z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; | 170 | z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; |
160 | } | 171 | } |
172 | z->slotaddr = zi->slotaddr; | ||
173 | z->slotsize = zi->slotsize; | ||
161 | sprintf(z->name, "Zorro device %08x", z->id); | 174 | sprintf(z->name, "Zorro device %08x", z->id); |
162 | zorro_name_device(z); | 175 | zorro_name_device(z); |
176 | z->resource.start = zi->boardaddr; | ||
177 | z->resource.end = zi->boardaddr + zi->boardsize - 1; | ||
163 | z->resource.name = z->name; | 178 | z->resource.name = z->name; |
164 | r = zorro_find_parent_resource(pdev, z); | 179 | r = zorro_find_parent_resource(pdev, z); |
165 | error = request_resource(r, &z->resource); | 180 | error = request_resource(r, &z->resource); |
@@ -167,9 +182,9 @@ static int __init amiga_zorro_probe(struct platform_device *pdev) | |||
167 | dev_err(&bus->dev, | 182 | dev_err(&bus->dev, |
168 | "Address space collision on device %s %pR\n", | 183 | "Address space collision on device %s %pR\n", |
169 | z->name, &z->resource); | 184 | z->name, &z->resource); |
170 | dev_set_name(&z->dev, "%02x", i); | ||
171 | z->dev.parent = &bus->dev; | 185 | z->dev.parent = &bus->dev; |
172 | z->dev.bus = &zorro_bus_type; | 186 | z->dev.bus = &zorro_bus_type; |
187 | z->dev.id = i; | ||
173 | } | 188 | } |
174 | 189 | ||
175 | /* ... then register them */ | 190 | /* ... then register them */ |
diff --git a/drivers/zorro/zorro.h b/drivers/zorro/zorro.h index b682d5ccd63f..34119fb4e560 100644 --- a/drivers/zorro/zorro.h +++ b/drivers/zorro/zorro.h | |||
@@ -1,4 +1,9 @@ | |||
1 | 1 | ||
2 | #ifdef CONFIG_ZORRO_NAMES | ||
2 | extern void zorro_name_device(struct zorro_dev *z); | 3 | extern void zorro_name_device(struct zorro_dev *z); |
4 | #else | ||
5 | static inline void zorro_name_device(struct zorro_dev *dev) { } | ||
6 | #endif | ||
7 | |||
3 | extern int zorro_create_sysfs_dev_files(struct zorro_dev *z); | 8 | extern int zorro_create_sysfs_dev_files(struct zorro_dev *z); |
4 | 9 | ||
diff --git a/fs/dcache.c b/fs/dcache.c index 6055d61811d3..cb4a10690868 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -3061,8 +3061,13 @@ char *d_path(const struct path *path, char *buf, int buflen) | |||
3061 | * thus don't need to be hashed. They also don't need a name until a | 3061 | * thus don't need to be hashed. They also don't need a name until a |
3062 | * user wants to identify the object in /proc/pid/fd/. The little hack | 3062 | * user wants to identify the object in /proc/pid/fd/. The little hack |
3063 | * below allows us to generate a name for these objects on demand: | 3063 | * below allows us to generate a name for these objects on demand: |
3064 | * | ||
3065 | * Some pseudo inodes are mountable. When they are mounted | ||
3066 | * path->dentry == path->mnt->mnt_root. In that case don't call d_dname | ||
3067 | * and instead have d_path return the mounted path. | ||
3064 | */ | 3068 | */ |
3065 | if (path->dentry->d_op && path->dentry->d_op->d_dname) | 3069 | if (path->dentry->d_op && path->dentry->d_op->d_dname && |
3070 | (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root)) | ||
3066 | return path->dentry->d_op->d_dname(path->dentry, buf, buflen); | 3071 | return path->dentry->d_op->d_dname(path->dentry, buf, buflen); |
3067 | 3072 | ||
3068 | rcu_read_lock(); | 3073 | rcu_read_lock(); |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1f4a10ece2f1..e0259a163f98 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -516,13 +516,16 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb, | |||
516 | } | 516 | } |
517 | WARN_ON(inode->i_state & I_SYNC); | 517 | WARN_ON(inode->i_state & I_SYNC); |
518 | /* | 518 | /* |
519 | * Skip inode if it is clean. We don't want to mess with writeback | 519 | * Skip inode if it is clean and we have no outstanding writeback in |
520 | * lists in this function since flusher thread may be doing for example | 520 | * WB_SYNC_ALL mode. We don't want to mess with writeback lists in this |
521 | * sync in parallel and if we move the inode, it could get skipped. So | 521 | * function since flusher thread may be doing for example sync in |
522 | * here we make sure inode is on some writeback list and leave it there | 522 | * parallel and if we move the inode, it could get skipped. So here we |
523 | * unless we have completely cleaned the inode. | 523 | * make sure inode is on some writeback list and leave it there unless |
524 | * we have completely cleaned the inode. | ||
524 | */ | 525 | */ |
525 | if (!(inode->i_state & I_DIRTY)) | 526 | if (!(inode->i_state & I_DIRTY) && |
527 | (wbc->sync_mode != WB_SYNC_ALL || | ||
528 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK))) | ||
526 | goto out; | 529 | goto out; |
527 | inode->i_state |= I_SYNC; | 530 | inode->i_state |= I_SYNC; |
528 | spin_unlock(&inode->i_lock); | 531 | spin_unlock(&inode->i_lock); |
diff --git a/fs/namespace.c b/fs/namespace.c index ac2ce8a766e1..be32ebccdeb1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -2886,7 +2886,7 @@ bool fs_fully_visible(struct file_system_type *type) | |||
2886 | struct inode *inode = child->mnt_mountpoint->d_inode; | 2886 | struct inode *inode = child->mnt_mountpoint->d_inode; |
2887 | if (!S_ISDIR(inode->i_mode)) | 2887 | if (!S_ISDIR(inode->i_mode)) |
2888 | goto next; | 2888 | goto next; |
2889 | if (inode->i_nlink != 2) | 2889 | if (inode->i_nlink > 2) |
2890 | goto next; | 2890 | goto next; |
2891 | } | 2891 | } |
2892 | visible = true; | 2892 | visible = true; |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 9f6b486b6c01..a1a191634abc 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -1440,17 +1440,19 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, | |||
1440 | 1440 | ||
1441 | nilfs_clear_logs(&sci->sc_segbufs); | 1441 | nilfs_clear_logs(&sci->sc_segbufs); |
1442 | 1442 | ||
1443 | err = nilfs_segctor_extend_segments(sci, nilfs, nadd); | ||
1444 | if (unlikely(err)) | ||
1445 | return err; | ||
1446 | |||
1447 | if (sci->sc_stage.flags & NILFS_CF_SUFREED) { | 1443 | if (sci->sc_stage.flags & NILFS_CF_SUFREED) { |
1448 | err = nilfs_sufile_cancel_freev(nilfs->ns_sufile, | 1444 | err = nilfs_sufile_cancel_freev(nilfs->ns_sufile, |
1449 | sci->sc_freesegs, | 1445 | sci->sc_freesegs, |
1450 | sci->sc_nfreesegs, | 1446 | sci->sc_nfreesegs, |
1451 | NULL); | 1447 | NULL); |
1452 | WARN_ON(err); /* do not happen */ | 1448 | WARN_ON(err); /* do not happen */ |
1449 | sci->sc_stage.flags &= ~NILFS_CF_SUFREED; | ||
1453 | } | 1450 | } |
1451 | |||
1452 | err = nilfs_segctor_extend_segments(sci, nilfs, nadd); | ||
1453 | if (unlikely(err)) | ||
1454 | return err; | ||
1455 | |||
1454 | nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA); | 1456 | nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA); |
1455 | sci->sc_stage = prev_stage; | 1457 | sci->sc_stage = prev_stage; |
1456 | } | 1458 | } |
diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h index 639d7a4d033b..6f692f8ac664 100644 --- a/include/asm-generic/barrier.h +++ b/include/asm-generic/barrier.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* Generic barrier definitions, based on MN10300 definitions. | 1 | /* |
2 | * Generic barrier definitions, originally based on MN10300 definitions. | ||
2 | * | 3 | * |
3 | * It should be possible to use these on really simple architectures, | 4 | * It should be possible to use these on really simple architectures, |
4 | * but it serves more as a starting point for new ports. | 5 | * but it serves more as a starting point for new ports. |
@@ -16,35 +17,65 @@ | |||
16 | 17 | ||
17 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ |
18 | 19 | ||
19 | #define nop() asm volatile ("nop") | 20 | #include <linux/compiler.h> |
21 | |||
22 | #ifndef nop | ||
23 | #define nop() asm volatile ("nop") | ||
24 | #endif | ||
20 | 25 | ||
21 | /* | 26 | /* |
22 | * Force strict CPU ordering. | 27 | * Force strict CPU ordering. And yes, this is required on UP too when we're |
23 | * And yes, this is required on UP too when we're talking | 28 | * talking to devices. |
24 | * to devices. | ||
25 | * | 29 | * |
26 | * This implementation only contains a compiler barrier. | 30 | * Fall back to compiler barriers if nothing better is provided. |
27 | */ | 31 | */ |
28 | 32 | ||
29 | #define mb() asm volatile ("": : :"memory") | 33 | #ifndef mb |
34 | #define mb() barrier() | ||
35 | #endif | ||
36 | |||
37 | #ifndef rmb | ||
30 | #define rmb() mb() | 38 | #define rmb() mb() |
31 | #define wmb() asm volatile ("": : :"memory") | 39 | #endif |
40 | |||
41 | #ifndef wmb | ||
42 | #define wmb() mb() | ||
43 | #endif | ||
44 | |||
45 | #ifndef read_barrier_depends | ||
46 | #define read_barrier_depends() do { } while (0) | ||
47 | #endif | ||
32 | 48 | ||
33 | #ifdef CONFIG_SMP | 49 | #ifdef CONFIG_SMP |
34 | #define smp_mb() mb() | 50 | #define smp_mb() mb() |
35 | #define smp_rmb() rmb() | 51 | #define smp_rmb() rmb() |
36 | #define smp_wmb() wmb() | 52 | #define smp_wmb() wmb() |
53 | #define smp_read_barrier_depends() read_barrier_depends() | ||
37 | #else | 54 | #else |
38 | #define smp_mb() barrier() | 55 | #define smp_mb() barrier() |
39 | #define smp_rmb() barrier() | 56 | #define smp_rmb() barrier() |
40 | #define smp_wmb() barrier() | 57 | #define smp_wmb() barrier() |
58 | #define smp_read_barrier_depends() do { } while (0) | ||
59 | #endif | ||
60 | |||
61 | #ifndef set_mb | ||
62 | #define set_mb(var, value) do { (var) = (value); mb(); } while (0) | ||
41 | #endif | 63 | #endif |
42 | 64 | ||
43 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 65 | #define smp_store_release(p, v) \ |
44 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | 66 | do { \ |
67 | compiletime_assert_atomic_type(*p); \ | ||
68 | smp_mb(); \ | ||
69 | ACCESS_ONCE(*p) = (v); \ | ||
70 | } while (0) | ||
45 | 71 | ||
46 | #define read_barrier_depends() do {} while (0) | 72 | #define smp_load_acquire(p) \ |
47 | #define smp_read_barrier_depends() do {} while (0) | 73 | ({ \ |
74 | typeof(*p) ___p1 = ACCESS_ONCE(*p); \ | ||
75 | compiletime_assert_atomic_type(*p); \ | ||
76 | smp_mb(); \ | ||
77 | ___p1; \ | ||
78 | }) | ||
48 | 79 | ||
49 | #endif /* !__ASSEMBLY__ */ | 80 | #endif /* !__ASSEMBLY__ */ |
50 | #endif /* __ASM_GENERIC_BARRIER_H */ | 81 | #endif /* __ASM_GENERIC_BARRIER_H */ |
diff --git a/include/linux/bottom_half.h b/include/linux/bottom_half.h index 27b1bcffe408..86c12c93e3cf 100644 --- a/include/linux/bottom_half.h +++ b/include/linux/bottom_half.h | |||
@@ -1,9 +1,35 @@ | |||
1 | #ifndef _LINUX_BH_H | 1 | #ifndef _LINUX_BH_H |
2 | #define _LINUX_BH_H | 2 | #define _LINUX_BH_H |
3 | 3 | ||
4 | extern void local_bh_disable(void); | 4 | #include <linux/preempt.h> |
5 | #include <linux/preempt_mask.h> | ||
6 | |||
7 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
8 | extern void __local_bh_disable_ip(unsigned long ip, unsigned int cnt); | ||
9 | #else | ||
10 | static __always_inline void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) | ||
11 | { | ||
12 | preempt_count_add(cnt); | ||
13 | barrier(); | ||
14 | } | ||
15 | #endif | ||
16 | |||
17 | static inline void local_bh_disable(void) | ||
18 | { | ||
19 | __local_bh_disable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET); | ||
20 | } | ||
21 | |||
5 | extern void _local_bh_enable(void); | 22 | extern void _local_bh_enable(void); |
6 | extern void local_bh_enable(void); | 23 | extern void __local_bh_enable_ip(unsigned long ip, unsigned int cnt); |
7 | extern void local_bh_enable_ip(unsigned long ip); | 24 | |
25 | static inline void local_bh_enable_ip(unsigned long ip) | ||
26 | { | ||
27 | __local_bh_enable_ip(ip, SOFTIRQ_DISABLE_OFFSET); | ||
28 | } | ||
29 | |||
30 | static inline void local_bh_enable(void) | ||
31 | { | ||
32 | __local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET); | ||
33 | } | ||
8 | 34 | ||
9 | #endif /* _LINUX_BH_H */ | 35 | #endif /* _LINUX_BH_H */ |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 92669cd182a6..fe7a686dfd8d 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -298,6 +298,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); | |||
298 | # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) | 298 | # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) |
299 | #endif | 299 | #endif |
300 | 300 | ||
301 | /* Is this type a native word size -- useful for atomic operations */ | ||
302 | #ifndef __native_word | ||
303 | # define __native_word(t) (sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long)) | ||
304 | #endif | ||
305 | |||
301 | /* Compile time object size, -1 for unknown */ | 306 | /* Compile time object size, -1 for unknown */ |
302 | #ifndef __compiletime_object_size | 307 | #ifndef __compiletime_object_size |
303 | # define __compiletime_object_size(obj) -1 | 308 | # define __compiletime_object_size(obj) -1 |
@@ -337,6 +342,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); | |||
337 | #define compiletime_assert(condition, msg) \ | 342 | #define compiletime_assert(condition, msg) \ |
338 | _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) | 343 | _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) |
339 | 344 | ||
345 | #define compiletime_assert_atomic_type(t) \ | ||
346 | compiletime_assert(__native_word(t), \ | ||
347 | "Need native word sized stores/loads for atomicity.") | ||
348 | |||
340 | /* | 349 | /* |
341 | * Prevent the compiler from merging or refetching accesses. The compiler | 350 | * Prevent the compiler from merging or refetching accesses. The compiler |
342 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), | 351 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), |
diff --git a/include/linux/context_tracking.h b/include/linux/context_tracking.h index 158158704c30..37b81bd51ec0 100644 --- a/include/linux/context_tracking.h +++ b/include/linux/context_tracking.h | |||
@@ -17,13 +17,13 @@ extern void __context_tracking_task_switch(struct task_struct *prev, | |||
17 | 17 | ||
18 | static inline void user_enter(void) | 18 | static inline void user_enter(void) |
19 | { | 19 | { |
20 | if (static_key_false(&context_tracking_enabled)) | 20 | if (context_tracking_is_enabled()) |
21 | context_tracking_user_enter(); | 21 | context_tracking_user_enter(); |
22 | 22 | ||
23 | } | 23 | } |
24 | static inline void user_exit(void) | 24 | static inline void user_exit(void) |
25 | { | 25 | { |
26 | if (static_key_false(&context_tracking_enabled)) | 26 | if (context_tracking_is_enabled()) |
27 | context_tracking_user_exit(); | 27 | context_tracking_user_exit(); |
28 | } | 28 | } |
29 | 29 | ||
@@ -31,7 +31,7 @@ static inline enum ctx_state exception_enter(void) | |||
31 | { | 31 | { |
32 | enum ctx_state prev_ctx; | 32 | enum ctx_state prev_ctx; |
33 | 33 | ||
34 | if (!static_key_false(&context_tracking_enabled)) | 34 | if (!context_tracking_is_enabled()) |
35 | return 0; | 35 | return 0; |
36 | 36 | ||
37 | prev_ctx = this_cpu_read(context_tracking.state); | 37 | prev_ctx = this_cpu_read(context_tracking.state); |
@@ -42,7 +42,7 @@ static inline enum ctx_state exception_enter(void) | |||
42 | 42 | ||
43 | static inline void exception_exit(enum ctx_state prev_ctx) | 43 | static inline void exception_exit(enum ctx_state prev_ctx) |
44 | { | 44 | { |
45 | if (static_key_false(&context_tracking_enabled)) { | 45 | if (context_tracking_is_enabled()) { |
46 | if (prev_ctx == IN_USER) | 46 | if (prev_ctx == IN_USER) |
47 | context_tracking_user_enter(); | 47 | context_tracking_user_enter(); |
48 | } | 48 | } |
@@ -51,7 +51,7 @@ static inline void exception_exit(enum ctx_state prev_ctx) | |||
51 | static inline void context_tracking_task_switch(struct task_struct *prev, | 51 | static inline void context_tracking_task_switch(struct task_struct *prev, |
52 | struct task_struct *next) | 52 | struct task_struct *next) |
53 | { | 53 | { |
54 | if (static_key_false(&context_tracking_enabled)) | 54 | if (context_tracking_is_enabled()) |
55 | __context_tracking_task_switch(prev, next); | 55 | __context_tracking_task_switch(prev, next); |
56 | } | 56 | } |
57 | #else | 57 | #else |
diff --git a/include/linux/context_tracking_state.h b/include/linux/context_tracking_state.h index 0f1979d0674f..97a81225d037 100644 --- a/include/linux/context_tracking_state.h +++ b/include/linux/context_tracking_state.h | |||
@@ -22,15 +22,20 @@ struct context_tracking { | |||
22 | extern struct static_key context_tracking_enabled; | 22 | extern struct static_key context_tracking_enabled; |
23 | DECLARE_PER_CPU(struct context_tracking, context_tracking); | 23 | DECLARE_PER_CPU(struct context_tracking, context_tracking); |
24 | 24 | ||
25 | static inline bool context_tracking_in_user(void) | 25 | static inline bool context_tracking_is_enabled(void) |
26 | { | 26 | { |
27 | return __this_cpu_read(context_tracking.state) == IN_USER; | 27 | return static_key_false(&context_tracking_enabled); |
28 | } | 28 | } |
29 | 29 | ||
30 | static inline bool context_tracking_active(void) | 30 | static inline bool context_tracking_cpu_is_enabled(void) |
31 | { | 31 | { |
32 | return __this_cpu_read(context_tracking.active); | 32 | return __this_cpu_read(context_tracking.active); |
33 | } | 33 | } |
34 | |||
35 | static inline bool context_tracking_in_user(void) | ||
36 | { | ||
37 | return __this_cpu_read(context_tracking.state) == IN_USER; | ||
38 | } | ||
34 | #else | 39 | #else |
35 | static inline bool context_tracking_in_user(void) { return false; } | 40 | static inline bool context_tracking_in_user(void) { return false; } |
36 | static inline bool context_tracking_active(void) { return false; } | 41 | static inline bool context_tracking_active(void) { return false; } |
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h index fe68a5a98583..7032518f8542 100644 --- a/include/linux/crash_dump.h +++ b/include/linux/crash_dump.h | |||
@@ -6,6 +6,8 @@ | |||
6 | #include <linux/proc_fs.h> | 6 | #include <linux/proc_fs.h> |
7 | #include <linux/elf.h> | 7 | #include <linux/elf.h> |
8 | 8 | ||
9 | #include <asm/pgtable.h> /* for pgprot_t */ | ||
10 | |||
9 | #define ELFCORE_ADDR_MAX (-1ULL) | 11 | #define ELFCORE_ADDR_MAX (-1ULL) |
10 | #define ELFCORE_ADDR_ERR (-2ULL) | 12 | #define ELFCORE_ADDR_ERR (-2ULL) |
11 | 13 | ||
diff --git a/include/linux/edac.h b/include/linux/edac.h index dbdffe8d4469..8e6c20af11a2 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h | |||
@@ -35,6 +35,34 @@ extern void edac_atomic_assert_error(void); | |||
35 | extern struct bus_type *edac_get_sysfs_subsys(void); | 35 | extern struct bus_type *edac_get_sysfs_subsys(void); |
36 | extern void edac_put_sysfs_subsys(void); | 36 | extern void edac_put_sysfs_subsys(void); |
37 | 37 | ||
38 | enum { | ||
39 | EDAC_REPORTING_ENABLED, | ||
40 | EDAC_REPORTING_DISABLED, | ||
41 | EDAC_REPORTING_FORCE | ||
42 | }; | ||
43 | |||
44 | extern int edac_report_status; | ||
45 | #ifdef CONFIG_EDAC | ||
46 | static inline int get_edac_report_status(void) | ||
47 | { | ||
48 | return edac_report_status; | ||
49 | } | ||
50 | |||
51 | static inline void set_edac_report_status(int new) | ||
52 | { | ||
53 | edac_report_status = new; | ||
54 | } | ||
55 | #else | ||
56 | static inline int get_edac_report_status(void) | ||
57 | { | ||
58 | return EDAC_REPORTING_DISABLED; | ||
59 | } | ||
60 | |||
61 | static inline void set_edac_report_status(int new) | ||
62 | { | ||
63 | } | ||
64 | #endif | ||
65 | |||
38 | static inline void opstate_init(void) | 66 | static inline void opstate_init(void) |
39 | { | 67 | { |
40 | switch (edac_op_state) { | 68 | switch (edac_op_state) { |
diff --git a/include/linux/efi.h b/include/linux/efi.h index 11ce6784a196..0a819e7a60c9 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -556,6 +556,9 @@ extern struct efi { | |||
556 | unsigned long hcdp; /* HCDP table */ | 556 | unsigned long hcdp; /* HCDP table */ |
557 | unsigned long uga; /* UGA table */ | 557 | unsigned long uga; /* UGA table */ |
558 | unsigned long uv_systab; /* UV system table */ | 558 | unsigned long uv_systab; /* UV system table */ |
559 | unsigned long fw_vendor; /* fw_vendor */ | ||
560 | unsigned long runtime; /* runtime table */ | ||
561 | unsigned long config_table; /* config tables */ | ||
559 | efi_get_time_t *get_time; | 562 | efi_get_time_t *get_time; |
560 | efi_set_time_t *set_time; | 563 | efi_set_time_t *set_time; |
561 | efi_get_wakeup_time_t *get_wakeup_time; | 564 | efi_get_wakeup_time_t *get_wakeup_time; |
@@ -653,6 +656,7 @@ extern int __init efi_setup_pcdp_console(char *); | |||
653 | #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ | 656 | #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ |
654 | #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ | 657 | #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ |
655 | #define EFI_64BIT 5 /* Is the firmware 64-bit? */ | 658 | #define EFI_64BIT 5 /* Is the firmware 64-bit? */ |
659 | #define EFI_ARCH_1 6 /* First arch-specific bit */ | ||
656 | 660 | ||
657 | #ifdef CONFIG_EFI | 661 | #ifdef CONFIG_EFI |
658 | # ifdef CONFIG_X86 | 662 | # ifdef CONFIG_X86 |
@@ -872,4 +876,17 @@ int efivars_sysfs_init(void); | |||
872 | 876 | ||
873 | #endif /* CONFIG_EFI_VARS */ | 877 | #endif /* CONFIG_EFI_VARS */ |
874 | 878 | ||
879 | #ifdef CONFIG_EFI_RUNTIME_MAP | ||
880 | int efi_runtime_map_init(struct kobject *); | ||
881 | void efi_runtime_map_setup(void *, int, u32); | ||
882 | #else | ||
883 | static inline int efi_runtime_map_init(struct kobject *kobj) | ||
884 | { | ||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | static inline void | ||
889 | efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) {} | ||
890 | #endif | ||
891 | |||
875 | #endif /* _LINUX_EFI_H */ | 892 | #endif /* _LINUX_EFI_H */ |
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index d9cf963ac832..12d5f972f23f 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/lockdep.h> | 5 | #include <linux/lockdep.h> |
6 | #include <linux/ftrace_irq.h> | 6 | #include <linux/ftrace_irq.h> |
7 | #include <linux/vtime.h> | 7 | #include <linux/vtime.h> |
8 | #include <asm/hardirq.h> | ||
8 | 9 | ||
9 | 10 | ||
10 | extern void synchronize_irq(unsigned int irq); | 11 | extern void synchronize_irq(unsigned int irq); |
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index eff50e062be8..d9c8dbd3373f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
@@ -445,7 +445,7 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data) | |||
445 | static inline struct i2c_adapter * | 445 | static inline struct i2c_adapter * |
446 | i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) | 446 | i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) |
447 | { | 447 | { |
448 | #if IS_ENABLED(I2C_MUX) | 448 | #if IS_ENABLED(CONFIG_I2C_MUX) |
449 | struct device *parent = adapter->dev.parent; | 449 | struct device *parent = adapter->dev.parent; |
450 | 450 | ||
451 | if (parent != NULL && parent->type == &i2c_adapter_type) | 451 | if (parent != NULL && parent->type == &i2c_adapter_type) |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index b0ed422e4e4a..f0e52383a001 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/user_namespace.h> | 11 | #include <linux/user_namespace.h> |
12 | #include <linux/securebits.h> | 12 | #include <linux/securebits.h> |
13 | #include <linux/seqlock.h> | 13 | #include <linux/seqlock.h> |
14 | #include <linux/rbtree.h> | ||
14 | #include <net/net_namespace.h> | 15 | #include <net/net_namespace.h> |
15 | #include <linux/sched/rt.h> | 16 | #include <linux/sched/rt.h> |
16 | 17 | ||
@@ -154,6 +155,14 @@ extern struct task_group root_task_group; | |||
154 | 155 | ||
155 | #define INIT_TASK_COMM "swapper" | 156 | #define INIT_TASK_COMM "swapper" |
156 | 157 | ||
158 | #ifdef CONFIG_RT_MUTEXES | ||
159 | # define INIT_RT_MUTEXES(tsk) \ | ||
160 | .pi_waiters = RB_ROOT, \ | ||
161 | .pi_waiters_leftmost = NULL, | ||
162 | #else | ||
163 | # define INIT_RT_MUTEXES(tsk) | ||
164 | #endif | ||
165 | |||
157 | /* | 166 | /* |
158 | * INIT_TASK is used to set up the first task table, touch at | 167 | * INIT_TASK is used to set up the first task table, touch at |
159 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 168 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
@@ -221,6 +230,7 @@ extern struct task_group root_task_group; | |||
221 | INIT_TRACE_RECURSION \ | 230 | INIT_TRACE_RECURSION \ |
222 | INIT_TASK_RCU_PREEMPT(tsk) \ | 231 | INIT_TASK_RCU_PREEMPT(tsk) \ |
223 | INIT_CPUSET_SEQ(tsk) \ | 232 | INIT_CPUSET_SEQ(tsk) \ |
233 | INIT_RT_MUTEXES(tsk) \ | ||
224 | INIT_VTIME(tsk) \ | 234 | INIT_VTIME(tsk) \ |
225 | } | 235 | } |
226 | 236 | ||
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index ecb87544cc5d..2aa3d4b000e6 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -394,6 +394,15 @@ extern int panic_on_oops; | |||
394 | extern int panic_on_unrecovered_nmi; | 394 | extern int panic_on_unrecovered_nmi; |
395 | extern int panic_on_io_nmi; | 395 | extern int panic_on_io_nmi; |
396 | extern int sysctl_panic_on_stackoverflow; | 396 | extern int sysctl_panic_on_stackoverflow; |
397 | /* | ||
398 | * Only to be used by arch init code. If the user over-wrote the default | ||
399 | * CONFIG_PANIC_TIMEOUT, honor it. | ||
400 | */ | ||
401 | static inline void set_arch_panic_timeout(int timeout, int arch_default_timeout) | ||
402 | { | ||
403 | if (panic_timeout == arch_default_timeout) | ||
404 | panic_timeout = timeout; | ||
405 | } | ||
397 | extern const char *print_tainted(void); | 406 | extern const char *print_tainted(void); |
398 | enum lockdep_ok { | 407 | enum lockdep_ok { |
399 | LOCKDEP_STILL_OK, | 408 | LOCKDEP_STILL_OK, |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 2e069d1288df..e56b07f5c9b6 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -320,6 +320,7 @@ struct perf_event { | |||
320 | struct list_head migrate_entry; | 320 | struct list_head migrate_entry; |
321 | 321 | ||
322 | struct hlist_node hlist_entry; | 322 | struct hlist_node hlist_entry; |
323 | struct list_head active_entry; | ||
323 | int nr_siblings; | 324 | int nr_siblings; |
324 | int group_flags; | 325 | int group_flags; |
325 | struct perf_event *group_leader; | 326 | struct perf_event *group_leader; |
diff --git a/include/linux/platform_data/hwmon-s3c.h b/include/linux/platform_data/hwmon-s3c.h index c167e4429bc7..0e3cce130fe2 100644 --- a/include/linux/platform_data/hwmon-s3c.h +++ b/include/linux/platform_data/hwmon-s3c.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/arch/arm/plat-s3c/include/plat/hwmon.h | 1 | /* |
2 | * | ||
3 | * Copyright 2005 Simtec Electronics | 2 | * Copyright 2005 Simtec Electronics |
4 | * Ben Dooks <ben@simtec.co.uk> | 3 | * Ben Dooks <ben@simtec.co.uk> |
5 | * http://armlinux.simtec.co.uk/ | 4 | * http://armlinux.simtec.co.uk/ |
@@ -11,8 +10,8 @@ | |||
11 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
12 | */ | 11 | */ |
13 | 12 | ||
14 | #ifndef __ASM_ARCH_ADC_HWMON_H | 13 | #ifndef __HWMON_S3C_H__ |
15 | #define __ASM_ARCH_ADC_HWMON_H __FILE__ | 14 | #define __HWMON_S3C_H__ |
16 | 15 | ||
17 | /** | 16 | /** |
18 | * s3c_hwmon_chcfg - channel configuration | 17 | * s3c_hwmon_chcfg - channel configuration |
@@ -47,5 +46,4 @@ struct s3c_hwmon_pdata { | |||
47 | */ | 46 | */ |
48 | extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd); | 47 | extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd); |
49 | 48 | ||
50 | #endif /* __ASM_ARCH_ADC_HWMON_H */ | 49 | #endif /* __HWMON_S3C_H__ */ |
51 | |||
diff --git a/include/linux/platform_data/max197.h b/include/linux/platform_data/max197.h index e2a41dd7690c..8da8f94ee15c 100644 --- a/include/linux/platform_data/max197.h +++ b/include/linux/platform_data/max197.h | |||
@@ -11,6 +11,9 @@ | |||
11 | * For further information, see the Documentation/hwmon/max197 file. | 11 | * For further information, see the Documentation/hwmon/max197 file. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifndef _PDATA_MAX197_H | ||
15 | #define _PDATA_MAX197_H | ||
16 | |||
14 | /** | 17 | /** |
15 | * struct max197_platform_data - MAX197 connectivity info | 18 | * struct max197_platform_data - MAX197 connectivity info |
16 | * @convert: Function used to start a conversion with control byte ctrl. | 19 | * @convert: Function used to start a conversion with control byte ctrl. |
@@ -19,3 +22,5 @@ | |||
19 | struct max197_platform_data { | 22 | struct max197_platform_data { |
20 | int (*convert)(u8 ctrl); | 23 | int (*convert)(u8 ctrl); |
21 | }; | 24 | }; |
25 | |||
26 | #endif /* _PDATA_MAX197_H */ | ||
diff --git a/include/linux/platform_data/sht15.h b/include/linux/platform_data/sht15.h index 33e0fd27225e..12289c1e9413 100644 --- a/include/linux/platform_data/sht15.h +++ b/include/linux/platform_data/sht15.h | |||
@@ -12,6 +12,9 @@ | |||
12 | * For further information, see the Documentation/hwmon/sht15 file. | 12 | * For further information, see the Documentation/hwmon/sht15 file. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #ifndef _PDATA_SHT15_H | ||
16 | #define _PDATA_SHT15_H | ||
17 | |||
15 | /** | 18 | /** |
16 | * struct sht15_platform_data - sht15 connectivity info | 19 | * struct sht15_platform_data - sht15 connectivity info |
17 | * @gpio_data: no. of gpio to which bidirectional data line is | 20 | * @gpio_data: no. of gpio to which bidirectional data line is |
@@ -31,3 +34,5 @@ struct sht15_platform_data { | |||
31 | bool no_otp_reload; | 34 | bool no_otp_reload; |
32 | bool low_resolution; | 35 | bool low_resolution; |
33 | }; | 36 | }; |
37 | |||
38 | #endif /* _PDATA_SHT15_H */ | ||
diff --git a/include/linux/preempt.h b/include/linux/preempt.h index a3d9dc8c2c00..59749fc48328 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h | |||
@@ -64,7 +64,11 @@ do { \ | |||
64 | } while (0) | 64 | } while (0) |
65 | 65 | ||
66 | #else | 66 | #else |
67 | #define preempt_enable() preempt_enable_no_resched() | 67 | #define preempt_enable() \ |
68 | do { \ | ||
69 | barrier(); \ | ||
70 | preempt_count_dec(); \ | ||
71 | } while (0) | ||
68 | #define preempt_check_resched() do { } while (0) | 72 | #define preempt_check_resched() do { } while (0) |
69 | #endif | 73 | #endif |
70 | 74 | ||
@@ -93,7 +97,11 @@ do { \ | |||
93 | __preempt_schedule_context(); \ | 97 | __preempt_schedule_context(); \ |
94 | } while (0) | 98 | } while (0) |
95 | #else | 99 | #else |
96 | #define preempt_enable_notrace() preempt_enable_no_resched_notrace() | 100 | #define preempt_enable_notrace() \ |
101 | do { \ | ||
102 | barrier(); \ | ||
103 | __preempt_count_dec(); \ | ||
104 | } while (0) | ||
97 | #endif | 105 | #endif |
98 | 106 | ||
99 | #else /* !CONFIG_PREEMPT_COUNT */ | 107 | #else /* !CONFIG_PREEMPT_COUNT */ |
@@ -116,6 +124,31 @@ do { \ | |||
116 | 124 | ||
117 | #endif /* CONFIG_PREEMPT_COUNT */ | 125 | #endif /* CONFIG_PREEMPT_COUNT */ |
118 | 126 | ||
127 | #ifdef MODULE | ||
128 | /* | ||
129 | * Modules have no business playing preemption tricks. | ||
130 | */ | ||
131 | #undef sched_preempt_enable_no_resched | ||
132 | #undef preempt_enable_no_resched | ||
133 | #undef preempt_enable_no_resched_notrace | ||
134 | #undef preempt_check_resched | ||
135 | #endif | ||
136 | |||
137 | #ifdef CONFIG_PREEMPT | ||
138 | #define preempt_set_need_resched() \ | ||
139 | do { \ | ||
140 | set_preempt_need_resched(); \ | ||
141 | } while (0) | ||
142 | #define preempt_fold_need_resched() \ | ||
143 | do { \ | ||
144 | if (tif_need_resched()) \ | ||
145 | set_preempt_need_resched(); \ | ||
146 | } while (0) | ||
147 | #else | ||
148 | #define preempt_set_need_resched() do { } while (0) | ||
149 | #define preempt_fold_need_resched() do { } while (0) | ||
150 | #endif | ||
151 | |||
119 | #ifdef CONFIG_PREEMPT_NOTIFIERS | 152 | #ifdef CONFIG_PREEMPT_NOTIFIERS |
120 | 153 | ||
121 | struct preempt_notifier; | 154 | struct preempt_notifier; |
diff --git a/include/linux/preempt_mask.h b/include/linux/preempt_mask.h index d169820203dd..dbeec4d4a3be 100644 --- a/include/linux/preempt_mask.h +++ b/include/linux/preempt_mask.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #define LINUX_PREEMPT_MASK_H | 2 | #define LINUX_PREEMPT_MASK_H |
3 | 3 | ||
4 | #include <linux/preempt.h> | 4 | #include <linux/preempt.h> |
5 | #include <asm/hardirq.h> | ||
6 | 5 | ||
7 | /* | 6 | /* |
8 | * We put the hardirq and softirq counter into the preemption | 7 | * We put the hardirq and softirq counter into the preemption |
@@ -79,6 +78,21 @@ | |||
79 | #endif | 78 | #endif |
80 | 79 | ||
81 | /* | 80 | /* |
81 | * The preempt_count offset needed for things like: | ||
82 | * | ||
83 | * spin_lock_bh() | ||
84 | * | ||
85 | * Which need to disable both preemption (CONFIG_PREEMPT_COUNT) and | ||
86 | * softirqs, such that unlock sequences of: | ||
87 | * | ||
88 | * spin_unlock(); | ||
89 | * local_bh_enable(); | ||
90 | * | ||
91 | * Work as expected. | ||
92 | */ | ||
93 | #define SOFTIRQ_LOCK_OFFSET (SOFTIRQ_DISABLE_OFFSET + PREEMPT_CHECK_OFFSET) | ||
94 | |||
95 | /* | ||
82 | * Are we running in atomic context? WARNING: this macro cannot | 96 | * Are we running in atomic context? WARNING: this macro cannot |
83 | * always detect atomic context; in particular, it cannot know about | 97 | * always detect atomic context; in particular, it cannot know about |
84 | * held spinlocks in non-preemptible kernels. Thus it should not be | 98 | * held spinlocks in non-preemptible kernels. Thus it should not be |
diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 45a0a9e81478..dbaf99084112 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h | |||
@@ -55,8 +55,8 @@ static inline void __list_add_rcu(struct list_head *new, | |||
55 | next->prev = new; | 55 | next->prev = new; |
56 | } | 56 | } |
57 | #else | 57 | #else |
58 | extern void __list_add_rcu(struct list_head *new, | 58 | void __list_add_rcu(struct list_head *new, |
59 | struct list_head *prev, struct list_head *next); | 59 | struct list_head *prev, struct list_head *next); |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | /** | 62 | /** |
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 39cbb889e20d..3e355c688618 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -50,13 +50,13 @@ extern int rcutorture_runnable; /* for sysctl */ | |||
50 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ | 50 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ |
51 | 51 | ||
52 | #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) | 52 | #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) |
53 | extern void rcutorture_record_test_transition(void); | 53 | void rcutorture_record_test_transition(void); |
54 | extern void rcutorture_record_progress(unsigned long vernum); | 54 | void rcutorture_record_progress(unsigned long vernum); |
55 | extern void do_trace_rcu_torture_read(const char *rcutorturename, | 55 | void do_trace_rcu_torture_read(const char *rcutorturename, |
56 | struct rcu_head *rhp, | 56 | struct rcu_head *rhp, |
57 | unsigned long secs, | 57 | unsigned long secs, |
58 | unsigned long c_old, | 58 | unsigned long c_old, |
59 | unsigned long c); | 59 | unsigned long c); |
60 | #else | 60 | #else |
61 | static inline void rcutorture_record_test_transition(void) | 61 | static inline void rcutorture_record_test_transition(void) |
62 | { | 62 | { |
@@ -65,11 +65,11 @@ static inline void rcutorture_record_progress(unsigned long vernum) | |||
65 | { | 65 | { |
66 | } | 66 | } |
67 | #ifdef CONFIG_RCU_TRACE | 67 | #ifdef CONFIG_RCU_TRACE |
68 | extern void do_trace_rcu_torture_read(const char *rcutorturename, | 68 | void do_trace_rcu_torture_read(const char *rcutorturename, |
69 | struct rcu_head *rhp, | 69 | struct rcu_head *rhp, |
70 | unsigned long secs, | 70 | unsigned long secs, |
71 | unsigned long c_old, | 71 | unsigned long c_old, |
72 | unsigned long c); | 72 | unsigned long c); |
73 | #else | 73 | #else |
74 | #define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \ | 74 | #define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \ |
75 | do { } while (0) | 75 | do { } while (0) |
@@ -118,8 +118,8 @@ extern void do_trace_rcu_torture_read(const char *rcutorturename, | |||
118 | * if CPU A and CPU B are the same CPU (but again only if the system has | 118 | * if CPU A and CPU B are the same CPU (but again only if the system has |
119 | * more than one CPU). | 119 | * more than one CPU). |
120 | */ | 120 | */ |
121 | extern void call_rcu(struct rcu_head *head, | 121 | void call_rcu(struct rcu_head *head, |
122 | void (*func)(struct rcu_head *head)); | 122 | void (*func)(struct rcu_head *head)); |
123 | 123 | ||
124 | #else /* #ifdef CONFIG_PREEMPT_RCU */ | 124 | #else /* #ifdef CONFIG_PREEMPT_RCU */ |
125 | 125 | ||
@@ -149,8 +149,8 @@ extern void call_rcu(struct rcu_head *head, | |||
149 | * See the description of call_rcu() for more detailed information on | 149 | * See the description of call_rcu() for more detailed information on |
150 | * memory ordering guarantees. | 150 | * memory ordering guarantees. |
151 | */ | 151 | */ |
152 | extern void call_rcu_bh(struct rcu_head *head, | 152 | void call_rcu_bh(struct rcu_head *head, |
153 | void (*func)(struct rcu_head *head)); | 153 | void (*func)(struct rcu_head *head)); |
154 | 154 | ||
155 | /** | 155 | /** |
156 | * call_rcu_sched() - Queue an RCU for invocation after sched grace period. | 156 | * call_rcu_sched() - Queue an RCU for invocation after sched grace period. |
@@ -171,16 +171,16 @@ extern void call_rcu_bh(struct rcu_head *head, | |||
171 | * See the description of call_rcu() for more detailed information on | 171 | * See the description of call_rcu() for more detailed information on |
172 | * memory ordering guarantees. | 172 | * memory ordering guarantees. |
173 | */ | 173 | */ |
174 | extern void call_rcu_sched(struct rcu_head *head, | 174 | void call_rcu_sched(struct rcu_head *head, |
175 | void (*func)(struct rcu_head *rcu)); | 175 | void (*func)(struct rcu_head *rcu)); |
176 | 176 | ||
177 | extern void synchronize_sched(void); | 177 | void synchronize_sched(void); |
178 | 178 | ||
179 | #ifdef CONFIG_PREEMPT_RCU | 179 | #ifdef CONFIG_PREEMPT_RCU |
180 | 180 | ||
181 | extern void __rcu_read_lock(void); | 181 | void __rcu_read_lock(void); |
182 | extern void __rcu_read_unlock(void); | 182 | void __rcu_read_unlock(void); |
183 | extern void rcu_read_unlock_special(struct task_struct *t); | 183 | void rcu_read_unlock_special(struct task_struct *t); |
184 | void synchronize_rcu(void); | 184 | void synchronize_rcu(void); |
185 | 185 | ||
186 | /* | 186 | /* |
@@ -216,19 +216,19 @@ static inline int rcu_preempt_depth(void) | |||
216 | #endif /* #else #ifdef CONFIG_PREEMPT_RCU */ | 216 | #endif /* #else #ifdef CONFIG_PREEMPT_RCU */ |
217 | 217 | ||
218 | /* Internal to kernel */ | 218 | /* Internal to kernel */ |
219 | extern void rcu_init(void); | 219 | void rcu_init(void); |
220 | extern void rcu_sched_qs(int cpu); | 220 | void rcu_sched_qs(int cpu); |
221 | extern void rcu_bh_qs(int cpu); | 221 | void rcu_bh_qs(int cpu); |
222 | extern void rcu_check_callbacks(int cpu, int user); | 222 | void rcu_check_callbacks(int cpu, int user); |
223 | struct notifier_block; | 223 | struct notifier_block; |
224 | extern void rcu_idle_enter(void); | 224 | void rcu_idle_enter(void); |
225 | extern void rcu_idle_exit(void); | 225 | void rcu_idle_exit(void); |
226 | extern void rcu_irq_enter(void); | 226 | void rcu_irq_enter(void); |
227 | extern void rcu_irq_exit(void); | 227 | void rcu_irq_exit(void); |
228 | 228 | ||
229 | #ifdef CONFIG_RCU_USER_QS | 229 | #ifdef CONFIG_RCU_USER_QS |
230 | extern void rcu_user_enter(void); | 230 | void rcu_user_enter(void); |
231 | extern void rcu_user_exit(void); | 231 | void rcu_user_exit(void); |
232 | #else | 232 | #else |
233 | static inline void rcu_user_enter(void) { } | 233 | static inline void rcu_user_enter(void) { } |
234 | static inline void rcu_user_exit(void) { } | 234 | static inline void rcu_user_exit(void) { } |
@@ -262,7 +262,7 @@ static inline void rcu_user_hooks_switch(struct task_struct *prev, | |||
262 | } while (0) | 262 | } while (0) |
263 | 263 | ||
264 | #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) | 264 | #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) |
265 | extern bool __rcu_is_watching(void); | 265 | bool __rcu_is_watching(void); |
266 | #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ | 266 | #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ |
267 | 267 | ||
268 | /* | 268 | /* |
@@ -289,8 +289,8 @@ void wait_rcu_gp(call_rcu_func_t crf); | |||
289 | * initialization. | 289 | * initialization. |
290 | */ | 290 | */ |
291 | #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD | 291 | #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD |
292 | extern void init_rcu_head_on_stack(struct rcu_head *head); | 292 | void init_rcu_head_on_stack(struct rcu_head *head); |
293 | extern void destroy_rcu_head_on_stack(struct rcu_head *head); | 293 | void destroy_rcu_head_on_stack(struct rcu_head *head); |
294 | #else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ | 294 | #else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ |
295 | static inline void init_rcu_head_on_stack(struct rcu_head *head) | 295 | static inline void init_rcu_head_on_stack(struct rcu_head *head) |
296 | { | 296 | { |
@@ -325,6 +325,7 @@ static inline void rcu_lock_release(struct lockdep_map *map) | |||
325 | extern struct lockdep_map rcu_lock_map; | 325 | extern struct lockdep_map rcu_lock_map; |
326 | extern struct lockdep_map rcu_bh_lock_map; | 326 | extern struct lockdep_map rcu_bh_lock_map; |
327 | extern struct lockdep_map rcu_sched_lock_map; | 327 | extern struct lockdep_map rcu_sched_lock_map; |
328 | extern struct lockdep_map rcu_callback_map; | ||
328 | extern int debug_lockdep_rcu_enabled(void); | 329 | extern int debug_lockdep_rcu_enabled(void); |
329 | 330 | ||
330 | /** | 331 | /** |
@@ -362,7 +363,7 @@ static inline int rcu_read_lock_held(void) | |||
362 | * rcu_read_lock_bh_held() is defined out of line to avoid #include-file | 363 | * rcu_read_lock_bh_held() is defined out of line to avoid #include-file |
363 | * hell. | 364 | * hell. |
364 | */ | 365 | */ |
365 | extern int rcu_read_lock_bh_held(void); | 366 | int rcu_read_lock_bh_held(void); |
366 | 367 | ||
367 | /** | 368 | /** |
368 | * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? | 369 | * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? |
@@ -448,7 +449,7 @@ static inline int rcu_read_lock_sched_held(void) | |||
448 | 449 | ||
449 | #ifdef CONFIG_PROVE_RCU | 450 | #ifdef CONFIG_PROVE_RCU |
450 | 451 | ||
451 | extern int rcu_my_thread_group_empty(void); | 452 | int rcu_my_thread_group_empty(void); |
452 | 453 | ||
453 | /** | 454 | /** |
454 | * rcu_lockdep_assert - emit lockdep splat if specified condition not met | 455 | * rcu_lockdep_assert - emit lockdep splat if specified condition not met |
@@ -548,10 +549,48 @@ static inline void rcu_preempt_sleep_check(void) | |||
548 | smp_read_barrier_depends(); \ | 549 | smp_read_barrier_depends(); \ |
549 | (_________p1); \ | 550 | (_________p1); \ |
550 | }) | 551 | }) |
551 | #define __rcu_assign_pointer(p, v, space) \ | 552 | |
553 | /** | ||
554 | * RCU_INITIALIZER() - statically initialize an RCU-protected global variable | ||
555 | * @v: The value to statically initialize with. | ||
556 | */ | ||
557 | #define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v) | ||
558 | |||
559 | /** | ||
560 | * rcu_assign_pointer() - assign to RCU-protected pointer | ||
561 | * @p: pointer to assign to | ||
562 | * @v: value to assign (publish) | ||
563 | * | ||
564 | * Assigns the specified value to the specified RCU-protected | ||
565 | * pointer, ensuring that any concurrent RCU readers will see | ||
566 | * any prior initialization. | ||
567 | * | ||
568 | * Inserts memory barriers on architectures that require them | ||
569 | * (which is most of them), and also prevents the compiler from | ||
570 | * reordering the code that initializes the structure after the pointer | ||
571 | * assignment. More importantly, this call documents which pointers | ||
572 | * will be dereferenced by RCU read-side code. | ||
573 | * | ||
574 | * In some special cases, you may use RCU_INIT_POINTER() instead | ||
575 | * of rcu_assign_pointer(). RCU_INIT_POINTER() is a bit faster due | ||
576 | * to the fact that it does not constrain either the CPU or the compiler. | ||
577 | * That said, using RCU_INIT_POINTER() when you should have used | ||
578 | * rcu_assign_pointer() is a very bad thing that results in | ||
579 | * impossible-to-diagnose memory corruption. So please be careful. | ||
580 | * See the RCU_INIT_POINTER() comment header for details. | ||
581 | * | ||
582 | * Note that rcu_assign_pointer() evaluates each of its arguments only | ||
583 | * once, appearances notwithstanding. One of the "extra" evaluations | ||
584 | * is in typeof() and the other visible only to sparse (__CHECKER__), | ||
585 | * neither of which actually execute the argument. As with most cpp | ||
586 | * macros, this execute-arguments-only-once property is important, so | ||
587 | * please be careful when making changes to rcu_assign_pointer() and the | ||
588 | * other macros that it invokes. | ||
589 | */ | ||
590 | #define rcu_assign_pointer(p, v) \ | ||
552 | do { \ | 591 | do { \ |
553 | smp_wmb(); \ | 592 | smp_wmb(); \ |
554 | (p) = (typeof(*v) __force space *)(v); \ | 593 | ACCESS_ONCE(p) = RCU_INITIALIZER(v); \ |
555 | } while (0) | 594 | } while (0) |
556 | 595 | ||
557 | 596 | ||
@@ -890,32 +929,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) | |||
890 | } | 929 | } |
891 | 930 | ||
892 | /** | 931 | /** |
893 | * rcu_assign_pointer() - assign to RCU-protected pointer | ||
894 | * @p: pointer to assign to | ||
895 | * @v: value to assign (publish) | ||
896 | * | ||
897 | * Assigns the specified value to the specified RCU-protected | ||
898 | * pointer, ensuring that any concurrent RCU readers will see | ||
899 | * any prior initialization. | ||
900 | * | ||
901 | * Inserts memory barriers on architectures that require them | ||
902 | * (which is most of them), and also prevents the compiler from | ||
903 | * reordering the code that initializes the structure after the pointer | ||
904 | * assignment. More importantly, this call documents which pointers | ||
905 | * will be dereferenced by RCU read-side code. | ||
906 | * | ||
907 | * In some special cases, you may use RCU_INIT_POINTER() instead | ||
908 | * of rcu_assign_pointer(). RCU_INIT_POINTER() is a bit faster due | ||
909 | * to the fact that it does not constrain either the CPU or the compiler. | ||
910 | * That said, using RCU_INIT_POINTER() when you should have used | ||
911 | * rcu_assign_pointer() is a very bad thing that results in | ||
912 | * impossible-to-diagnose memory corruption. So please be careful. | ||
913 | * See the RCU_INIT_POINTER() comment header for details. | ||
914 | */ | ||
915 | #define rcu_assign_pointer(p, v) \ | ||
916 | __rcu_assign_pointer((p), (v), __rcu) | ||
917 | |||
918 | /** | ||
919 | * RCU_INIT_POINTER() - initialize an RCU protected pointer | 932 | * RCU_INIT_POINTER() - initialize an RCU protected pointer |
920 | * | 933 | * |
921 | * Initialize an RCU-protected pointer in special cases where readers | 934 | * Initialize an RCU-protected pointer in special cases where readers |
@@ -949,7 +962,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) | |||
949 | */ | 962 | */ |
950 | #define RCU_INIT_POINTER(p, v) \ | 963 | #define RCU_INIT_POINTER(p, v) \ |
951 | do { \ | 964 | do { \ |
952 | p = (typeof(*v) __force __rcu *)(v); \ | 965 | p = RCU_INITIALIZER(v); \ |
953 | } while (0) | 966 | } while (0) |
954 | 967 | ||
955 | /** | 968 | /** |
@@ -958,7 +971,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) | |||
958 | * GCC-style initialization for an RCU-protected pointer in a structure field. | 971 | * GCC-style initialization for an RCU-protected pointer in a structure field. |
959 | */ | 972 | */ |
960 | #define RCU_POINTER_INITIALIZER(p, v) \ | 973 | #define RCU_POINTER_INITIALIZER(p, v) \ |
961 | .p = (typeof(*v) __force __rcu *)(v) | 974 | .p = RCU_INITIALIZER(v) |
962 | 975 | ||
963 | /* | 976 | /* |
964 | * Does the specified offset indicate that the corresponding rcu_head | 977 | * Does the specified offset indicate that the corresponding rcu_head |
@@ -1005,7 +1018,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) | |||
1005 | __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) | 1018 | __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) |
1006 | 1019 | ||
1007 | #ifdef CONFIG_RCU_NOCB_CPU | 1020 | #ifdef CONFIG_RCU_NOCB_CPU |
1008 | extern bool rcu_is_nocb_cpu(int cpu); | 1021 | bool rcu_is_nocb_cpu(int cpu); |
1009 | #else | 1022 | #else |
1010 | static inline bool rcu_is_nocb_cpu(int cpu) { return false; } | 1023 | static inline bool rcu_is_nocb_cpu(int cpu) { return false; } |
1011 | #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */ | 1024 | #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */ |
@@ -1013,8 +1026,8 @@ static inline bool rcu_is_nocb_cpu(int cpu) { return false; } | |||
1013 | 1026 | ||
1014 | /* Only for use by adaptive-ticks code. */ | 1027 | /* Only for use by adaptive-ticks code. */ |
1015 | #ifdef CONFIG_NO_HZ_FULL_SYSIDLE | 1028 | #ifdef CONFIG_NO_HZ_FULL_SYSIDLE |
1016 | extern bool rcu_sys_is_idle(void); | 1029 | bool rcu_sys_is_idle(void); |
1017 | extern void rcu_sysidle_force_exit(void); | 1030 | void rcu_sysidle_force_exit(void); |
1018 | #else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ | 1031 | #else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ |
1019 | 1032 | ||
1020 | static inline bool rcu_sys_is_idle(void) | 1033 | static inline bool rcu_sys_is_idle(void) |
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index 09ebcbe9fd78..6f01771b571c 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h | |||
@@ -125,7 +125,7 @@ static inline void exit_rcu(void) | |||
125 | 125 | ||
126 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 126 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
127 | extern int rcu_scheduler_active __read_mostly; | 127 | extern int rcu_scheduler_active __read_mostly; |
128 | extern void rcu_scheduler_starting(void); | 128 | void rcu_scheduler_starting(void); |
129 | #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ | 129 | #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ |
130 | static inline void rcu_scheduler_starting(void) | 130 | static inline void rcu_scheduler_starting(void) |
131 | { | 131 | { |
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 4b9c81548742..72137ee8c603 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h | |||
@@ -30,9 +30,9 @@ | |||
30 | #ifndef __LINUX_RCUTREE_H | 30 | #ifndef __LINUX_RCUTREE_H |
31 | #define __LINUX_RCUTREE_H | 31 | #define __LINUX_RCUTREE_H |
32 | 32 | ||
33 | extern void rcu_note_context_switch(int cpu); | 33 | void rcu_note_context_switch(int cpu); |
34 | extern int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies); | 34 | int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies); |
35 | extern void rcu_cpu_stall_reset(void); | 35 | void rcu_cpu_stall_reset(void); |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Note a virtualization-based context switch. This is simply a | 38 | * Note a virtualization-based context switch. This is simply a |
@@ -44,9 +44,9 @@ static inline void rcu_virt_note_context_switch(int cpu) | |||
44 | rcu_note_context_switch(cpu); | 44 | rcu_note_context_switch(cpu); |
45 | } | 45 | } |
46 | 46 | ||
47 | extern void synchronize_rcu_bh(void); | 47 | void synchronize_rcu_bh(void); |
48 | extern void synchronize_sched_expedited(void); | 48 | void synchronize_sched_expedited(void); |
49 | extern void synchronize_rcu_expedited(void); | 49 | void synchronize_rcu_expedited(void); |
50 | 50 | ||
51 | void kfree_call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); | 51 | void kfree_call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); |
52 | 52 | ||
@@ -71,25 +71,25 @@ static inline void synchronize_rcu_bh_expedited(void) | |||
71 | synchronize_sched_expedited(); | 71 | synchronize_sched_expedited(); |
72 | } | 72 | } |
73 | 73 | ||
74 | extern void rcu_barrier(void); | 74 | void rcu_barrier(void); |
75 | extern void rcu_barrier_bh(void); | 75 | void rcu_barrier_bh(void); |
76 | extern void rcu_barrier_sched(void); | 76 | void rcu_barrier_sched(void); |
77 | 77 | ||
78 | extern unsigned long rcutorture_testseq; | 78 | extern unsigned long rcutorture_testseq; |
79 | extern unsigned long rcutorture_vernum; | 79 | extern unsigned long rcutorture_vernum; |
80 | extern long rcu_batches_completed(void); | 80 | long rcu_batches_completed(void); |
81 | extern long rcu_batches_completed_bh(void); | 81 | long rcu_batches_completed_bh(void); |
82 | extern long rcu_batches_completed_sched(void); | 82 | long rcu_batches_completed_sched(void); |
83 | 83 | ||
84 | extern void rcu_force_quiescent_state(void); | 84 | void rcu_force_quiescent_state(void); |
85 | extern void rcu_bh_force_quiescent_state(void); | 85 | void rcu_bh_force_quiescent_state(void); |
86 | extern void rcu_sched_force_quiescent_state(void); | 86 | void rcu_sched_force_quiescent_state(void); |
87 | 87 | ||
88 | extern void exit_rcu(void); | 88 | void exit_rcu(void); |
89 | 89 | ||
90 | extern void rcu_scheduler_starting(void); | 90 | void rcu_scheduler_starting(void); |
91 | extern int rcu_scheduler_active __read_mostly; | 91 | extern int rcu_scheduler_active __read_mostly; |
92 | 92 | ||
93 | extern bool rcu_is_watching(void); | 93 | bool rcu_is_watching(void); |
94 | 94 | ||
95 | #endif /* __LINUX_RCUTREE_H */ | 95 | #endif /* __LINUX_RCUTREE_H */ |
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h index de17134244f3..3aed8d737e1a 100644 --- a/include/linux/rtmutex.h +++ b/include/linux/rtmutex.h | |||
@@ -13,7 +13,7 @@ | |||
13 | #define __LINUX_RT_MUTEX_H | 13 | #define __LINUX_RT_MUTEX_H |
14 | 14 | ||
15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
16 | #include <linux/plist.h> | 16 | #include <linux/rbtree.h> |
17 | #include <linux/spinlock_types.h> | 17 | #include <linux/spinlock_types.h> |
18 | 18 | ||
19 | extern int max_lock_depth; /* for sysctl */ | 19 | extern int max_lock_depth; /* for sysctl */ |
@@ -22,12 +22,14 @@ extern int max_lock_depth; /* for sysctl */ | |||
22 | * The rt_mutex structure | 22 | * The rt_mutex structure |
23 | * | 23 | * |
24 | * @wait_lock: spinlock to protect the structure | 24 | * @wait_lock: spinlock to protect the structure |
25 | * @wait_list: pilist head to enqueue waiters in priority order | 25 | * @waiters: rbtree root to enqueue waiters in priority order |
26 | * @waiters_leftmost: top waiter | ||
26 | * @owner: the mutex owner | 27 | * @owner: the mutex owner |
27 | */ | 28 | */ |
28 | struct rt_mutex { | 29 | struct rt_mutex { |
29 | raw_spinlock_t wait_lock; | 30 | raw_spinlock_t wait_lock; |
30 | struct plist_head wait_list; | 31 | struct rb_root waiters; |
32 | struct rb_node *waiters_leftmost; | ||
31 | struct task_struct *owner; | 33 | struct task_struct *owner; |
32 | #ifdef CONFIG_DEBUG_RT_MUTEXES | 34 | #ifdef CONFIG_DEBUG_RT_MUTEXES |
33 | int save_state; | 35 | int save_state; |
@@ -66,7 +68,7 @@ struct hrtimer_sleeper; | |||
66 | 68 | ||
67 | #define __RT_MUTEX_INITIALIZER(mutexname) \ | 69 | #define __RT_MUTEX_INITIALIZER(mutexname) \ |
68 | { .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \ | 70 | { .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \ |
69 | , .wait_list = PLIST_HEAD_INIT(mutexname.wait_list) \ | 71 | , .waiters = RB_ROOT \ |
70 | , .owner = NULL \ | 72 | , .owner = NULL \ |
71 | __DEBUG_RT_MUTEX_INITIALIZER(mutexname)} | 73 | __DEBUG_RT_MUTEX_INITIALIZER(mutexname)} |
72 | 74 | ||
@@ -98,12 +100,4 @@ extern int rt_mutex_trylock(struct rt_mutex *lock); | |||
98 | 100 | ||
99 | extern void rt_mutex_unlock(struct rt_mutex *lock); | 101 | extern void rt_mutex_unlock(struct rt_mutex *lock); |
100 | 102 | ||
101 | #ifdef CONFIG_RT_MUTEXES | ||
102 | # define INIT_RT_MUTEXES(tsk) \ | ||
103 | .pi_waiters = PLIST_HEAD_INIT(tsk.pi_waiters), \ | ||
104 | INIT_RT_MUTEX_DEBUG(tsk) | ||
105 | #else | ||
106 | # define INIT_RT_MUTEXES(tsk) | ||
107 | #endif | ||
108 | |||
109 | #endif | 103 | #endif |
diff --git a/include/linux/rwlock_api_smp.h b/include/linux/rwlock_api_smp.h index 9c9f0495d37c..5b9b84b20407 100644 --- a/include/linux/rwlock_api_smp.h +++ b/include/linux/rwlock_api_smp.h | |||
@@ -172,8 +172,7 @@ static inline void __raw_read_lock_irq(rwlock_t *lock) | |||
172 | 172 | ||
173 | static inline void __raw_read_lock_bh(rwlock_t *lock) | 173 | static inline void __raw_read_lock_bh(rwlock_t *lock) |
174 | { | 174 | { |
175 | local_bh_disable(); | 175 | __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); |
176 | preempt_disable(); | ||
177 | rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); | 176 | rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); |
178 | LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock); | 177 | LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock); |
179 | } | 178 | } |
@@ -200,8 +199,7 @@ static inline void __raw_write_lock_irq(rwlock_t *lock) | |||
200 | 199 | ||
201 | static inline void __raw_write_lock_bh(rwlock_t *lock) | 200 | static inline void __raw_write_lock_bh(rwlock_t *lock) |
202 | { | 201 | { |
203 | local_bh_disable(); | 202 | __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); |
204 | preempt_disable(); | ||
205 | rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); | 203 | rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); |
206 | LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock); | 204 | LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock); |
207 | } | 205 | } |
@@ -250,8 +248,7 @@ static inline void __raw_read_unlock_bh(rwlock_t *lock) | |||
250 | { | 248 | { |
251 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | 249 | rwlock_release(&lock->dep_map, 1, _RET_IP_); |
252 | do_raw_read_unlock(lock); | 250 | do_raw_read_unlock(lock); |
253 | preempt_enable_no_resched(); | 251 | __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); |
254 | local_bh_enable_ip((unsigned long)__builtin_return_address(0)); | ||
255 | } | 252 | } |
256 | 253 | ||
257 | static inline void __raw_write_unlock_irqrestore(rwlock_t *lock, | 254 | static inline void __raw_write_unlock_irqrestore(rwlock_t *lock, |
@@ -275,8 +272,7 @@ static inline void __raw_write_unlock_bh(rwlock_t *lock) | |||
275 | { | 272 | { |
276 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | 273 | rwlock_release(&lock->dep_map, 1, _RET_IP_); |
277 | do_raw_write_unlock(lock); | 274 | do_raw_write_unlock(lock); |
278 | preempt_enable_no_resched(); | 275 | __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); |
279 | local_bh_enable_ip((unsigned long)__builtin_return_address(0)); | ||
280 | } | 276 | } |
281 | 277 | ||
282 | #endif /* __LINUX_RWLOCK_API_SMP_H */ | 278 | #endif /* __LINUX_RWLOCK_API_SMP_H */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 53f97eb8dbc7..ffccdad050b5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -16,6 +16,7 @@ struct sched_param { | |||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/timex.h> | 17 | #include <linux/timex.h> |
18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
19 | #include <linux/plist.h> | ||
19 | #include <linux/rbtree.h> | 20 | #include <linux/rbtree.h> |
20 | #include <linux/thread_info.h> | 21 | #include <linux/thread_info.h> |
21 | #include <linux/cpumask.h> | 22 | #include <linux/cpumask.h> |
@@ -56,6 +57,70 @@ struct sched_param { | |||
56 | 57 | ||
57 | #include <asm/processor.h> | 58 | #include <asm/processor.h> |
58 | 59 | ||
60 | #define SCHED_ATTR_SIZE_VER0 48 /* sizeof first published struct */ | ||
61 | |||
62 | /* | ||
63 | * Extended scheduling parameters data structure. | ||
64 | * | ||
65 | * This is needed because the original struct sched_param can not be | ||
66 | * altered without introducing ABI issues with legacy applications | ||
67 | * (e.g., in sched_getparam()). | ||
68 | * | ||
69 | * However, the possibility of specifying more than just a priority for | ||
70 | * the tasks may be useful for a wide variety of application fields, e.g., | ||
71 | * multimedia, streaming, automation and control, and many others. | ||
72 | * | ||
73 | * This variant (sched_attr) is meant at describing a so-called | ||
74 | * sporadic time-constrained task. In such model a task is specified by: | ||
75 | * - the activation period or minimum instance inter-arrival time; | ||
76 | * - the maximum (or average, depending on the actual scheduling | ||
77 | * discipline) computation time of all instances, a.k.a. runtime; | ||
78 | * - the deadline (relative to the actual activation time) of each | ||
79 | * instance. | ||
80 | * Very briefly, a periodic (sporadic) task asks for the execution of | ||
81 | * some specific computation --which is typically called an instance-- | ||
82 | * (at most) every period. Moreover, each instance typically lasts no more | ||
83 | * than the runtime and must be completed by time instant t equal to | ||
84 | * the instance activation time + the deadline. | ||
85 | * | ||
86 | * This is reflected by the actual fields of the sched_attr structure: | ||
87 | * | ||
88 | * @size size of the structure, for fwd/bwd compat. | ||
89 | * | ||
90 | * @sched_policy task's scheduling policy | ||
91 | * @sched_flags for customizing the scheduler behaviour | ||
92 | * @sched_nice task's nice value (SCHED_NORMAL/BATCH) | ||
93 | * @sched_priority task's static priority (SCHED_FIFO/RR) | ||
94 | * @sched_deadline representative of the task's deadline | ||
95 | * @sched_runtime representative of the task's runtime | ||
96 | * @sched_period representative of the task's period | ||
97 | * | ||
98 | * Given this task model, there are a multiplicity of scheduling algorithms | ||
99 | * and policies, that can be used to ensure all the tasks will make their | ||
100 | * timing constraints. | ||
101 | * | ||
102 | * As of now, the SCHED_DEADLINE policy (sched_dl scheduling class) is the | ||
103 | * only user of this new interface. More information about the algorithm | ||
104 | * available in the scheduling class file or in Documentation/. | ||
105 | */ | ||
106 | struct sched_attr { | ||
107 | u32 size; | ||
108 | |||
109 | u32 sched_policy; | ||
110 | u64 sched_flags; | ||
111 | |||
112 | /* SCHED_NORMAL, SCHED_BATCH */ | ||
113 | s32 sched_nice; | ||
114 | |||
115 | /* SCHED_FIFO, SCHED_RR */ | ||
116 | u32 sched_priority; | ||
117 | |||
118 | /* SCHED_DEADLINE */ | ||
119 | u64 sched_runtime; | ||
120 | u64 sched_deadline; | ||
121 | u64 sched_period; | ||
122 | }; | ||
123 | |||
59 | struct exec_domain; | 124 | struct exec_domain; |
60 | struct futex_pi_state; | 125 | struct futex_pi_state; |
61 | struct robust_list_head; | 126 | struct robust_list_head; |
@@ -168,7 +233,6 @@ extern char ___assert_task_state[1 - 2*!!( | |||
168 | 233 | ||
169 | #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) | 234 | #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) |
170 | #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) | 235 | #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) |
171 | #define task_is_dead(task) ((task)->exit_state != 0) | ||
172 | #define task_is_stopped_or_traced(task) \ | 236 | #define task_is_stopped_or_traced(task) \ |
173 | ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0) | 237 | ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0) |
174 | #define task_contributes_to_load(task) \ | 238 | #define task_contributes_to_load(task) \ |
@@ -1029,6 +1093,51 @@ struct sched_rt_entity { | |||
1029 | #endif | 1093 | #endif |
1030 | }; | 1094 | }; |
1031 | 1095 | ||
1096 | struct sched_dl_entity { | ||
1097 | struct rb_node rb_node; | ||
1098 | |||
1099 | /* | ||
1100 | * Original scheduling parameters. Copied here from sched_attr | ||
1101 | * during sched_setscheduler2(), they will remain the same until | ||
1102 | * the next sched_setscheduler2(). | ||
1103 | */ | ||
1104 | u64 dl_runtime; /* maximum runtime for each instance */ | ||
1105 | u64 dl_deadline; /* relative deadline of each instance */ | ||
1106 | u64 dl_period; /* separation of two instances (period) */ | ||
1107 | u64 dl_bw; /* dl_runtime / dl_deadline */ | ||
1108 | |||
1109 | /* | ||
1110 | * Actual scheduling parameters. Initialized with the values above, | ||
1111 | * they are continously updated during task execution. Note that | ||
1112 | * the remaining runtime could be < 0 in case we are in overrun. | ||
1113 | */ | ||
1114 | s64 runtime; /* remaining runtime for this instance */ | ||
1115 | u64 deadline; /* absolute deadline for this instance */ | ||
1116 | unsigned int flags; /* specifying the scheduler behaviour */ | ||
1117 | |||
1118 | /* | ||
1119 | * Some bool flags: | ||
1120 | * | ||
1121 | * @dl_throttled tells if we exhausted the runtime. If so, the | ||
1122 | * task has to wait for a replenishment to be performed at the | ||
1123 | * next firing of dl_timer. | ||
1124 | * | ||
1125 | * @dl_new tells if a new instance arrived. If so we must | ||
1126 | * start executing it with full runtime and reset its absolute | ||
1127 | * deadline; | ||
1128 | * | ||
1129 | * @dl_boosted tells if we are boosted due to DI. If so we are | ||
1130 | * outside bandwidth enforcement mechanism (but only until we | ||
1131 | * exit the critical section). | ||
1132 | */ | ||
1133 | int dl_throttled, dl_new, dl_boosted; | ||
1134 | |||
1135 | /* | ||
1136 | * Bandwidth enforcement timer. Each -deadline task has its | ||
1137 | * own bandwidth to be enforced, thus we need one timer per task. | ||
1138 | */ | ||
1139 | struct hrtimer dl_timer; | ||
1140 | }; | ||
1032 | 1141 | ||
1033 | struct rcu_node; | 1142 | struct rcu_node; |
1034 | 1143 | ||
@@ -1065,6 +1174,7 @@ struct task_struct { | |||
1065 | #ifdef CONFIG_CGROUP_SCHED | 1174 | #ifdef CONFIG_CGROUP_SCHED |
1066 | struct task_group *sched_task_group; | 1175 | struct task_group *sched_task_group; |
1067 | #endif | 1176 | #endif |
1177 | struct sched_dl_entity dl; | ||
1068 | 1178 | ||
1069 | #ifdef CONFIG_PREEMPT_NOTIFIERS | 1179 | #ifdef CONFIG_PREEMPT_NOTIFIERS |
1070 | /* list of struct preempt_notifier: */ | 1180 | /* list of struct preempt_notifier: */ |
@@ -1098,6 +1208,7 @@ struct task_struct { | |||
1098 | struct list_head tasks; | 1208 | struct list_head tasks; |
1099 | #ifdef CONFIG_SMP | 1209 | #ifdef CONFIG_SMP |
1100 | struct plist_node pushable_tasks; | 1210 | struct plist_node pushable_tasks; |
1211 | struct rb_node pushable_dl_tasks; | ||
1101 | #endif | 1212 | #endif |
1102 | 1213 | ||
1103 | struct mm_struct *mm, *active_mm; | 1214 | struct mm_struct *mm, *active_mm; |
@@ -1249,9 +1360,12 @@ struct task_struct { | |||
1249 | 1360 | ||
1250 | #ifdef CONFIG_RT_MUTEXES | 1361 | #ifdef CONFIG_RT_MUTEXES |
1251 | /* PI waiters blocked on a rt_mutex held by this task */ | 1362 | /* PI waiters blocked on a rt_mutex held by this task */ |
1252 | struct plist_head pi_waiters; | 1363 | struct rb_root pi_waiters; |
1364 | struct rb_node *pi_waiters_leftmost; | ||
1253 | /* Deadlock detection and priority inheritance handling */ | 1365 | /* Deadlock detection and priority inheritance handling */ |
1254 | struct rt_mutex_waiter *pi_blocked_on; | 1366 | struct rt_mutex_waiter *pi_blocked_on; |
1367 | /* Top pi_waiters task */ | ||
1368 | struct task_struct *pi_top_task; | ||
1255 | #endif | 1369 | #endif |
1256 | 1370 | ||
1257 | #ifdef CONFIG_DEBUG_MUTEXES | 1371 | #ifdef CONFIG_DEBUG_MUTEXES |
@@ -1880,7 +1994,9 @@ static inline void sched_clock_idle_wakeup_event(u64 delta_ns) | |||
1880 | * but then during bootup it turns out that sched_clock() | 1994 | * but then during bootup it turns out that sched_clock() |
1881 | * is reliable after all: | 1995 | * is reliable after all: |
1882 | */ | 1996 | */ |
1883 | extern int sched_clock_stable; | 1997 | extern int sched_clock_stable(void); |
1998 | extern void set_sched_clock_stable(void); | ||
1999 | extern void clear_sched_clock_stable(void); | ||
1884 | 2000 | ||
1885 | extern void sched_clock_tick(void); | 2001 | extern void sched_clock_tick(void); |
1886 | extern void sched_clock_idle_sleep_event(void); | 2002 | extern void sched_clock_idle_sleep_event(void); |
@@ -1959,6 +2075,8 @@ extern int sched_setscheduler(struct task_struct *, int, | |||
1959 | const struct sched_param *); | 2075 | const struct sched_param *); |
1960 | extern int sched_setscheduler_nocheck(struct task_struct *, int, | 2076 | extern int sched_setscheduler_nocheck(struct task_struct *, int, |
1961 | const struct sched_param *); | 2077 | const struct sched_param *); |
2078 | extern int sched_setattr(struct task_struct *, | ||
2079 | const struct sched_attr *); | ||
1962 | extern struct task_struct *idle_task(int cpu); | 2080 | extern struct task_struct *idle_task(int cpu); |
1963 | /** | 2081 | /** |
1964 | * is_idle_task - is the specified task an idle task? | 2082 | * is_idle_task - is the specified task an idle task? |
@@ -2038,7 +2156,7 @@ extern void wake_up_new_task(struct task_struct *tsk); | |||
2038 | #else | 2156 | #else |
2039 | static inline void kick_process(struct task_struct *tsk) { } | 2157 | static inline void kick_process(struct task_struct *tsk) { } |
2040 | #endif | 2158 | #endif |
2041 | extern void sched_fork(unsigned long clone_flags, struct task_struct *p); | 2159 | extern int sched_fork(unsigned long clone_flags, struct task_struct *p); |
2042 | extern void sched_dead(struct task_struct *p); | 2160 | extern void sched_dead(struct task_struct *p); |
2043 | 2161 | ||
2044 | extern void proc_caches_init(void); | 2162 | extern void proc_caches_init(void); |
@@ -2627,6 +2745,21 @@ static inline bool __must_check current_clr_polling_and_test(void) | |||
2627 | } | 2745 | } |
2628 | #endif | 2746 | #endif |
2629 | 2747 | ||
2748 | static inline void current_clr_polling(void) | ||
2749 | { | ||
2750 | __current_clr_polling(); | ||
2751 | |||
2752 | /* | ||
2753 | * Ensure we check TIF_NEED_RESCHED after we clear the polling bit. | ||
2754 | * Once the bit is cleared, we'll get IPIs with every new | ||
2755 | * TIF_NEED_RESCHED and the IPI handler, scheduler_ipi(), will also | ||
2756 | * fold. | ||
2757 | */ | ||
2758 | smp_mb(); /* paired with resched_task() */ | ||
2759 | |||
2760 | preempt_fold_need_resched(); | ||
2761 | } | ||
2762 | |||
2630 | static __always_inline bool need_resched(void) | 2763 | static __always_inline bool need_resched(void) |
2631 | { | 2764 | { |
2632 | return unlikely(tif_need_resched()); | 2765 | return unlikely(tif_need_resched()); |
diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h new file mode 100644 index 000000000000..9d303b8847df --- /dev/null +++ b/include/linux/sched/deadline.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef _SCHED_DEADLINE_H | ||
2 | #define _SCHED_DEADLINE_H | ||
3 | |||
4 | /* | ||
5 | * SCHED_DEADLINE tasks has negative priorities, reflecting | ||
6 | * the fact that any of them has higher prio than RT and | ||
7 | * NORMAL/BATCH tasks. | ||
8 | */ | ||
9 | |||
10 | #define MAX_DL_PRIO 0 | ||
11 | |||
12 | static inline int dl_prio(int prio) | ||
13 | { | ||
14 | if (unlikely(prio < MAX_DL_PRIO)) | ||
15 | return 1; | ||
16 | return 0; | ||
17 | } | ||
18 | |||
19 | static inline int dl_task(struct task_struct *p) | ||
20 | { | ||
21 | return dl_prio(p->prio); | ||
22 | } | ||
23 | |||
24 | #endif /* _SCHED_DEADLINE_H */ | ||
diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h index 440434df3627..34e4ebea8fce 100644 --- a/include/linux/sched/rt.h +++ b/include/linux/sched/rt.h | |||
@@ -35,6 +35,7 @@ static inline int rt_task(struct task_struct *p) | |||
35 | #ifdef CONFIG_RT_MUTEXES | 35 | #ifdef CONFIG_RT_MUTEXES |
36 | extern int rt_mutex_getprio(struct task_struct *p); | 36 | extern int rt_mutex_getprio(struct task_struct *p); |
37 | extern void rt_mutex_setprio(struct task_struct *p, int prio); | 37 | extern void rt_mutex_setprio(struct task_struct *p, int prio); |
38 | extern struct task_struct *rt_mutex_get_top_task(struct task_struct *task); | ||
38 | extern void rt_mutex_adjust_pi(struct task_struct *p); | 39 | extern void rt_mutex_adjust_pi(struct task_struct *p); |
39 | static inline bool tsk_is_pi_blocked(struct task_struct *tsk) | 40 | static inline bool tsk_is_pi_blocked(struct task_struct *tsk) |
40 | { | 41 | { |
@@ -45,6 +46,10 @@ static inline int rt_mutex_getprio(struct task_struct *p) | |||
45 | { | 46 | { |
46 | return p->normal_prio; | 47 | return p->normal_prio; |
47 | } | 48 | } |
49 | static inline struct task_struct *rt_mutex_get_top_task(struct task_struct *task) | ||
50 | { | ||
51 | return NULL; | ||
52 | } | ||
48 | # define rt_mutex_adjust_pi(p) do { } while (0) | 53 | # define rt_mutex_adjust_pi(p) do { } while (0) |
49 | static inline bool tsk_is_pi_blocked(struct task_struct *tsk) | 54 | static inline bool tsk_is_pi_blocked(struct task_struct *tsk) |
50 | { | 55 | { |
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index 41467f8ff8ec..31e0193cb0c5 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h | |||
@@ -48,7 +48,6 @@ extern unsigned int sysctl_numa_balancing_scan_delay; | |||
48 | extern unsigned int sysctl_numa_balancing_scan_period_min; | 48 | extern unsigned int sysctl_numa_balancing_scan_period_min; |
49 | extern unsigned int sysctl_numa_balancing_scan_period_max; | 49 | extern unsigned int sysctl_numa_balancing_scan_period_max; |
50 | extern unsigned int sysctl_numa_balancing_scan_size; | 50 | extern unsigned int sysctl_numa_balancing_scan_size; |
51 | extern unsigned int sysctl_numa_balancing_settle_count; | ||
52 | 51 | ||
53 | #ifdef CONFIG_SCHED_DEBUG | 52 | #ifdef CONFIG_SCHED_DEBUG |
54 | extern unsigned int sysctl_sched_migration_cost; | 53 | extern unsigned int sysctl_sched_migration_cost; |
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h index cf87a24c0f92..535f158977b9 100644 --- a/include/linux/seqlock.h +++ b/include/linux/seqlock.h | |||
@@ -117,15 +117,15 @@ repeat: | |||
117 | } | 117 | } |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * read_seqcount_begin_no_lockdep - start seq-read critical section w/o lockdep | 120 | * raw_read_seqcount_begin - start seq-read critical section w/o lockdep |
121 | * @s: pointer to seqcount_t | 121 | * @s: pointer to seqcount_t |
122 | * Returns: count to be passed to read_seqcount_retry | 122 | * Returns: count to be passed to read_seqcount_retry |
123 | * | 123 | * |
124 | * read_seqcount_begin_no_lockdep opens a read critical section of the given | 124 | * raw_read_seqcount_begin opens a read critical section of the given |
125 | * seqcount, but without any lockdep checking. Validity of the critical | 125 | * seqcount, but without any lockdep checking. Validity of the critical |
126 | * section is tested by checking read_seqcount_retry function. | 126 | * section is tested by checking read_seqcount_retry function. |
127 | */ | 127 | */ |
128 | static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s) | 128 | static inline unsigned raw_read_seqcount_begin(const seqcount_t *s) |
129 | { | 129 | { |
130 | unsigned ret = __read_seqcount_begin(s); | 130 | unsigned ret = __read_seqcount_begin(s); |
131 | smp_rmb(); | 131 | smp_rmb(); |
@@ -144,7 +144,7 @@ static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s) | |||
144 | static inline unsigned read_seqcount_begin(const seqcount_t *s) | 144 | static inline unsigned read_seqcount_begin(const seqcount_t *s) |
145 | { | 145 | { |
146 | seqcount_lockdep_reader_access(s); | 146 | seqcount_lockdep_reader_access(s); |
147 | return read_seqcount_begin_no_lockdep(s); | 147 | return raw_read_seqcount_begin(s); |
148 | } | 148 | } |
149 | 149 | ||
150 | /** | 150 | /** |
@@ -206,14 +206,26 @@ static inline int read_seqcount_retry(const seqcount_t *s, unsigned start) | |||
206 | } | 206 | } |
207 | 207 | ||
208 | 208 | ||
209 | |||
210 | static inline void raw_write_seqcount_begin(seqcount_t *s) | ||
211 | { | ||
212 | s->sequence++; | ||
213 | smp_wmb(); | ||
214 | } | ||
215 | |||
216 | static inline void raw_write_seqcount_end(seqcount_t *s) | ||
217 | { | ||
218 | smp_wmb(); | ||
219 | s->sequence++; | ||
220 | } | ||
221 | |||
209 | /* | 222 | /* |
210 | * Sequence counter only version assumes that callers are using their | 223 | * Sequence counter only version assumes that callers are using their |
211 | * own mutexing. | 224 | * own mutexing. |
212 | */ | 225 | */ |
213 | static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass) | 226 | static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass) |
214 | { | 227 | { |
215 | s->sequence++; | 228 | raw_write_seqcount_begin(s); |
216 | smp_wmb(); | ||
217 | seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_); | 229 | seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_); |
218 | } | 230 | } |
219 | 231 | ||
@@ -225,8 +237,7 @@ static inline void write_seqcount_begin(seqcount_t *s) | |||
225 | static inline void write_seqcount_end(seqcount_t *s) | 237 | static inline void write_seqcount_end(seqcount_t *s) |
226 | { | 238 | { |
227 | seqcount_release(&s->dep_map, 1, _RET_IP_); | 239 | seqcount_release(&s->dep_map, 1, _RET_IP_); |
228 | smp_wmb(); | 240 | raw_write_seqcount_end(s); |
229 | s->sequence++; | ||
230 | } | 241 | } |
231 | 242 | ||
232 | /** | 243 | /** |
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 75f34949d9ab..3f2867ff0ced 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h | |||
@@ -130,6 +130,16 @@ do { \ | |||
130 | #define smp_mb__before_spinlock() smp_wmb() | 130 | #define smp_mb__before_spinlock() smp_wmb() |
131 | #endif | 131 | #endif |
132 | 132 | ||
133 | /* | ||
134 | * Place this after a lock-acquisition primitive to guarantee that | ||
135 | * an UNLOCK+LOCK pair act as a full barrier. This guarantee applies | ||
136 | * if the UNLOCK and LOCK are executed by the same CPU or if the | ||
137 | * UNLOCK and LOCK operate on the same lock variable. | ||
138 | */ | ||
139 | #ifndef smp_mb__after_unlock_lock | ||
140 | #define smp_mb__after_unlock_lock() do { } while (0) | ||
141 | #endif | ||
142 | |||
133 | /** | 143 | /** |
134 | * raw_spin_unlock_wait - wait until the spinlock gets unlocked | 144 | * raw_spin_unlock_wait - wait until the spinlock gets unlocked |
135 | * @lock: the spinlock in question. | 145 | * @lock: the spinlock in question. |
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h index bdb9993f0fda..42dfab89e740 100644 --- a/include/linux/spinlock_api_smp.h +++ b/include/linux/spinlock_api_smp.h | |||
@@ -131,8 +131,7 @@ static inline void __raw_spin_lock_irq(raw_spinlock_t *lock) | |||
131 | 131 | ||
132 | static inline void __raw_spin_lock_bh(raw_spinlock_t *lock) | 132 | static inline void __raw_spin_lock_bh(raw_spinlock_t *lock) |
133 | { | 133 | { |
134 | local_bh_disable(); | 134 | __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); |
135 | preempt_disable(); | ||
136 | spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); | 135 | spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); |
137 | LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); | 136 | LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); |
138 | } | 137 | } |
@@ -174,20 +173,17 @@ static inline void __raw_spin_unlock_bh(raw_spinlock_t *lock) | |||
174 | { | 173 | { |
175 | spin_release(&lock->dep_map, 1, _RET_IP_); | 174 | spin_release(&lock->dep_map, 1, _RET_IP_); |
176 | do_raw_spin_unlock(lock); | 175 | do_raw_spin_unlock(lock); |
177 | preempt_enable_no_resched(); | 176 | __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); |
178 | local_bh_enable_ip((unsigned long)__builtin_return_address(0)); | ||
179 | } | 177 | } |
180 | 178 | ||
181 | static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock) | 179 | static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock) |
182 | { | 180 | { |
183 | local_bh_disable(); | 181 | __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); |
184 | preempt_disable(); | ||
185 | if (do_raw_spin_trylock(lock)) { | 182 | if (do_raw_spin_trylock(lock)) { |
186 | spin_acquire(&lock->dep_map, 0, 1, _RET_IP_); | 183 | spin_acquire(&lock->dep_map, 0, 1, _RET_IP_); |
187 | return 1; | 184 | return 1; |
188 | } | 185 | } |
189 | preempt_enable_no_resched(); | 186 | __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); |
190 | local_bh_enable_ip((unsigned long)__builtin_return_address(0)); | ||
191 | return 0; | 187 | return 0; |
192 | } | 188 | } |
193 | 189 | ||
diff --git a/include/linux/spinlock_api_up.h b/include/linux/spinlock_api_up.h index af1f47229e70..d0d188861ad6 100644 --- a/include/linux/spinlock_api_up.h +++ b/include/linux/spinlock_api_up.h | |||
@@ -24,11 +24,14 @@ | |||
24 | * flags straight, to suppress compiler warnings of unused lock | 24 | * flags straight, to suppress compiler warnings of unused lock |
25 | * variables, and to add the proper checker annotations: | 25 | * variables, and to add the proper checker annotations: |
26 | */ | 26 | */ |
27 | #define ___LOCK(lock) \ | ||
28 | do { __acquire(lock); (void)(lock); } while (0) | ||
29 | |||
27 | #define __LOCK(lock) \ | 30 | #define __LOCK(lock) \ |
28 | do { preempt_disable(); __acquire(lock); (void)(lock); } while (0) | 31 | do { preempt_disable(); ___LOCK(lock); } while (0) |
29 | 32 | ||
30 | #define __LOCK_BH(lock) \ | 33 | #define __LOCK_BH(lock) \ |
31 | do { local_bh_disable(); __LOCK(lock); } while (0) | 34 | do { __local_bh_disable_ip(_THIS_IP_, SOFTIRQ_LOCK_OFFSET); ___LOCK(lock); } while (0) |
32 | 35 | ||
33 | #define __LOCK_IRQ(lock) \ | 36 | #define __LOCK_IRQ(lock) \ |
34 | do { local_irq_disable(); __LOCK(lock); } while (0) | 37 | do { local_irq_disable(); __LOCK(lock); } while (0) |
@@ -36,12 +39,15 @@ | |||
36 | #define __LOCK_IRQSAVE(lock, flags) \ | 39 | #define __LOCK_IRQSAVE(lock, flags) \ |
37 | do { local_irq_save(flags); __LOCK(lock); } while (0) | 40 | do { local_irq_save(flags); __LOCK(lock); } while (0) |
38 | 41 | ||
42 | #define ___UNLOCK(lock) \ | ||
43 | do { __release(lock); (void)(lock); } while (0) | ||
44 | |||
39 | #define __UNLOCK(lock) \ | 45 | #define __UNLOCK(lock) \ |
40 | do { preempt_enable(); __release(lock); (void)(lock); } while (0) | 46 | do { preempt_enable(); ___UNLOCK(lock); } while (0) |
41 | 47 | ||
42 | #define __UNLOCK_BH(lock) \ | 48 | #define __UNLOCK_BH(lock) \ |
43 | do { preempt_enable_no_resched(); local_bh_enable(); \ | 49 | do { __local_bh_enable_ip(_THIS_IP_, SOFTIRQ_LOCK_OFFSET); \ |
44 | __release(lock); (void)(lock); } while (0) | 50 | ___UNLOCK(lock); } while (0) |
45 | 51 | ||
46 | #define __UNLOCK_IRQ(lock) \ | 52 | #define __UNLOCK_IRQ(lock) \ |
47 | do { local_irq_enable(); __UNLOCK(lock); } while (0) | 53 | do { local_irq_enable(); __UNLOCK(lock); } while (0) |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 94273bbe6050..40ed9e9a77e5 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -38,6 +38,7 @@ struct rlimit; | |||
38 | struct rlimit64; | 38 | struct rlimit64; |
39 | struct rusage; | 39 | struct rusage; |
40 | struct sched_param; | 40 | struct sched_param; |
41 | struct sched_attr; | ||
41 | struct sel_arg_struct; | 42 | struct sel_arg_struct; |
42 | struct semaphore; | 43 | struct semaphore; |
43 | struct sembuf; | 44 | struct sembuf; |
@@ -279,9 +280,14 @@ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, | |||
279 | struct sched_param __user *param); | 280 | struct sched_param __user *param); |
280 | asmlinkage long sys_sched_setparam(pid_t pid, | 281 | asmlinkage long sys_sched_setparam(pid_t pid, |
281 | struct sched_param __user *param); | 282 | struct sched_param __user *param); |
283 | asmlinkage long sys_sched_setattr(pid_t pid, | ||
284 | struct sched_attr __user *attr); | ||
282 | asmlinkage long sys_sched_getscheduler(pid_t pid); | 285 | asmlinkage long sys_sched_getscheduler(pid_t pid); |
283 | asmlinkage long sys_sched_getparam(pid_t pid, | 286 | asmlinkage long sys_sched_getparam(pid_t pid, |
284 | struct sched_param __user *param); | 287 | struct sched_param __user *param); |
288 | asmlinkage long sys_sched_getattr(pid_t pid, | ||
289 | struct sched_attr __user *attr, | ||
290 | unsigned int size); | ||
285 | asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, | 291 | asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, |
286 | unsigned long __user *user_mask_ptr); | 292 | unsigned long __user *user_mask_ptr); |
287 | asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, | 293 | asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, |
diff --git a/include/linux/tick.h b/include/linux/tick.h index 5128d33bbb39..0175d8663b6c 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h | |||
@@ -104,7 +104,7 @@ extern struct cpumask *tick_get_broadcast_oneshot_mask(void); | |||
104 | extern void tick_clock_notify(void); | 104 | extern void tick_clock_notify(void); |
105 | extern int tick_check_oneshot_change(int allow_nohz); | 105 | extern int tick_check_oneshot_change(int allow_nohz); |
106 | extern struct tick_sched *tick_get_tick_sched(int cpu); | 106 | extern struct tick_sched *tick_get_tick_sched(int cpu); |
107 | extern void tick_check_idle(int cpu); | 107 | extern void tick_check_idle(void); |
108 | extern int tick_oneshot_mode_active(void); | 108 | extern int tick_oneshot_mode_active(void); |
109 | # ifndef arch_needs_cpu | 109 | # ifndef arch_needs_cpu |
110 | # define arch_needs_cpu(cpu) (0) | 110 | # define arch_needs_cpu(cpu) (0) |
@@ -112,7 +112,7 @@ extern int tick_oneshot_mode_active(void); | |||
112 | # else | 112 | # else |
113 | static inline void tick_clock_notify(void) { } | 113 | static inline void tick_clock_notify(void) { } |
114 | static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } | 114 | static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } |
115 | static inline void tick_check_idle(int cpu) { } | 115 | static inline void tick_check_idle(void) { } |
116 | static inline int tick_oneshot_mode_active(void) { return 0; } | 116 | static inline int tick_oneshot_mode_active(void) { return 0; } |
117 | # endif | 117 | # endif |
118 | 118 | ||
@@ -121,7 +121,7 @@ static inline void tick_init(void) { } | |||
121 | static inline void tick_cancel_sched_timer(int cpu) { } | 121 | static inline void tick_cancel_sched_timer(int cpu) { } |
122 | static inline void tick_clock_notify(void) { } | 122 | static inline void tick_clock_notify(void) { } |
123 | static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } | 123 | static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } |
124 | static inline void tick_check_idle(int cpu) { } | 124 | static inline void tick_check_idle(void) { } |
125 | static inline int tick_oneshot_mode_active(void) { return 0; } | 125 | static inline int tick_oneshot_mode_active(void) { return 0; } |
126 | #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ | 126 | #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ |
127 | 127 | ||
@@ -165,7 +165,7 @@ extern cpumask_var_t tick_nohz_full_mask; | |||
165 | 165 | ||
166 | static inline bool tick_nohz_full_enabled(void) | 166 | static inline bool tick_nohz_full_enabled(void) |
167 | { | 167 | { |
168 | if (!static_key_false(&context_tracking_enabled)) | 168 | if (!context_tracking_is_enabled()) |
169 | return false; | 169 | return false; |
170 | 170 | ||
171 | return tick_nohz_full_running; | 171 | return tick_nohz_full_running; |
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 9d8cf056e661..ecd3319dac33 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h | |||
@@ -25,13 +25,16 @@ static inline void pagefault_disable(void) | |||
25 | 25 | ||
26 | static inline void pagefault_enable(void) | 26 | static inline void pagefault_enable(void) |
27 | { | 27 | { |
28 | #ifndef CONFIG_PREEMPT | ||
28 | /* | 29 | /* |
29 | * make sure to issue those last loads/stores before enabling | 30 | * make sure to issue those last loads/stores before enabling |
30 | * the pagefault handler again. | 31 | * the pagefault handler again. |
31 | */ | 32 | */ |
32 | barrier(); | 33 | barrier(); |
33 | preempt_count_dec(); | 34 | preempt_count_dec(); |
34 | preempt_check_resched(); | 35 | #else |
36 | preempt_enable(); | ||
37 | #endif | ||
35 | } | 38 | } |
36 | 39 | ||
37 | #ifndef ARCH_HAS_NOCACHE_UACCESS | 40 | #ifndef ARCH_HAS_NOCACHE_UACCESS |
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h index 319eae70fe84..e32251e00e62 100644 --- a/include/linux/uprobes.h +++ b/include/linux/uprobes.h | |||
@@ -26,16 +26,13 @@ | |||
26 | 26 | ||
27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
28 | #include <linux/rbtree.h> | 28 | #include <linux/rbtree.h> |
29 | #include <linux/types.h> | ||
29 | 30 | ||
30 | struct vm_area_struct; | 31 | struct vm_area_struct; |
31 | struct mm_struct; | 32 | struct mm_struct; |
32 | struct inode; | 33 | struct inode; |
33 | struct notifier_block; | 34 | struct notifier_block; |
34 | 35 | ||
35 | #ifdef CONFIG_ARCH_SUPPORTS_UPROBES | ||
36 | # include <asm/uprobes.h> | ||
37 | #endif | ||
38 | |||
39 | #define UPROBE_HANDLER_REMOVE 1 | 36 | #define UPROBE_HANDLER_REMOVE 1 |
40 | #define UPROBE_HANDLER_MASK 1 | 37 | #define UPROBE_HANDLER_MASK 1 |
41 | 38 | ||
@@ -60,6 +57,8 @@ struct uprobe_consumer { | |||
60 | }; | 57 | }; |
61 | 58 | ||
62 | #ifdef CONFIG_UPROBES | 59 | #ifdef CONFIG_UPROBES |
60 | #include <asm/uprobes.h> | ||
61 | |||
63 | enum uprobe_task_state { | 62 | enum uprobe_task_state { |
64 | UTASK_RUNNING, | 63 | UTASK_RUNNING, |
65 | UTASK_SSTEP, | 64 | UTASK_SSTEP, |
@@ -72,35 +71,28 @@ enum uprobe_task_state { | |||
72 | */ | 71 | */ |
73 | struct uprobe_task { | 72 | struct uprobe_task { |
74 | enum uprobe_task_state state; | 73 | enum uprobe_task_state state; |
75 | struct arch_uprobe_task autask; | ||
76 | 74 | ||
77 | struct return_instance *return_instances; | 75 | union { |
78 | unsigned int depth; | 76 | struct { |
79 | struct uprobe *active_uprobe; | 77 | struct arch_uprobe_task autask; |
78 | unsigned long vaddr; | ||
79 | }; | ||
80 | 80 | ||
81 | struct { | ||
82 | struct callback_head dup_xol_work; | ||
83 | unsigned long dup_xol_addr; | ||
84 | }; | ||
85 | }; | ||
86 | |||
87 | struct uprobe *active_uprobe; | ||
81 | unsigned long xol_vaddr; | 88 | unsigned long xol_vaddr; |
82 | unsigned long vaddr; | ||
83 | }; | ||
84 | 89 | ||
85 | /* | 90 | struct return_instance *return_instances; |
86 | * On a breakpoint hit, thread contests for a slot. It frees the | 91 | unsigned int depth; |
87 | * slot after singlestep. Currently a fixed number of slots are | ||
88 | * allocated. | ||
89 | */ | ||
90 | struct xol_area { | ||
91 | wait_queue_head_t wq; /* if all slots are busy */ | ||
92 | atomic_t slot_count; /* number of in-use slots */ | ||
93 | unsigned long *bitmap; /* 0 = free slot */ | ||
94 | struct page *page; | ||
95 | |||
96 | /* | ||
97 | * We keep the vma's vm_start rather than a pointer to the vma | ||
98 | * itself. The probed process or a naughty kernel module could make | ||
99 | * the vma go away, and we must handle that reasonably gracefully. | ||
100 | */ | ||
101 | unsigned long vaddr; /* Page(s) of instruction slots */ | ||
102 | }; | 92 | }; |
103 | 93 | ||
94 | struct xol_area; | ||
95 | |||
104 | struct uprobes_state { | 96 | struct uprobes_state { |
105 | struct xol_area *xol_area; | 97 | struct xol_area *xol_area; |
106 | }; | 98 | }; |
@@ -109,6 +101,7 @@ extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsign | |||
109 | extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); | 101 | extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); |
110 | extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); | 102 | extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); |
111 | extern bool __weak is_trap_insn(uprobe_opcode_t *insn); | 103 | extern bool __weak is_trap_insn(uprobe_opcode_t *insn); |
104 | extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); | ||
112 | extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t); | 105 | extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t); |
113 | extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); | 106 | extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); |
114 | extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool); | 107 | extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool); |
@@ -120,7 +113,6 @@ extern void uprobe_end_dup_mmap(void); | |||
120 | extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); | 113 | extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); |
121 | extern void uprobe_free_utask(struct task_struct *t); | 114 | extern void uprobe_free_utask(struct task_struct *t); |
122 | extern void uprobe_copy_process(struct task_struct *t, unsigned long flags); | 115 | extern void uprobe_copy_process(struct task_struct *t, unsigned long flags); |
123 | extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); | ||
124 | extern int uprobe_post_sstep_notifier(struct pt_regs *regs); | 116 | extern int uprobe_post_sstep_notifier(struct pt_regs *regs); |
125 | extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); | 117 | extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); |
126 | extern void uprobe_notify_resume(struct pt_regs *regs); | 118 | extern void uprobe_notify_resume(struct pt_regs *regs); |
@@ -176,10 +168,6 @@ static inline bool uprobe_deny_signal(void) | |||
176 | { | 168 | { |
177 | return false; | 169 | return false; |
178 | } | 170 | } |
179 | static inline unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) | ||
180 | { | ||
181 | return 0; | ||
182 | } | ||
183 | static inline void uprobe_free_utask(struct task_struct *t) | 171 | static inline void uprobe_free_utask(struct task_struct *t) |
184 | { | 172 | { |
185 | } | 173 | } |
diff --git a/include/linux/vtime.h b/include/linux/vtime.h index f5b72b364bda..c5165fd256f9 100644 --- a/include/linux/vtime.h +++ b/include/linux/vtime.h | |||
@@ -19,8 +19,8 @@ static inline bool vtime_accounting_enabled(void) { return true; } | |||
19 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN | 19 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN |
20 | static inline bool vtime_accounting_enabled(void) | 20 | static inline bool vtime_accounting_enabled(void) |
21 | { | 21 | { |
22 | if (static_key_false(&context_tracking_enabled)) { | 22 | if (context_tracking_is_enabled()) { |
23 | if (context_tracking_active()) | 23 | if (context_tracking_cpu_is_enabled()) |
24 | return true; | 24 | return true; |
25 | } | 25 | } |
26 | 26 | ||
diff --git a/include/linux/zorro.h b/include/linux/zorro.h index dff42025649b..63fbba0740c2 100644 --- a/include/linux/zorro.h +++ b/include/linux/zorro.h | |||
@@ -11,107 +11,10 @@ | |||
11 | #ifndef _LINUX_ZORRO_H | 11 | #ifndef _LINUX_ZORRO_H |
12 | #define _LINUX_ZORRO_H | 12 | #define _LINUX_ZORRO_H |
13 | 13 | ||
14 | #include <linux/device.h> | ||
15 | |||
16 | |||
17 | /* | ||
18 | * Each Zorro board has a 32-bit ID of the form | ||
19 | * | ||
20 | * mmmmmmmmmmmmmmmmppppppppeeeeeeee | ||
21 | * | ||
22 | * with | ||
23 | * | ||
24 | * mmmmmmmmmmmmmmmm 16-bit Manufacturer ID (assigned by CBM (sigh)) | ||
25 | * pppppppp 8-bit Product ID (assigned by manufacturer) | ||
26 | * eeeeeeee 8-bit Extended Product ID (currently only used | ||
27 | * for some GVP boards) | ||
28 | */ | ||
29 | |||
30 | |||
31 | #define ZORRO_MANUF(id) ((id) >> 16) | ||
32 | #define ZORRO_PROD(id) (((id) >> 8) & 0xff) | ||
33 | #define ZORRO_EPC(id) ((id) & 0xff) | ||
34 | |||
35 | #define ZORRO_ID(manuf, prod, epc) \ | ||
36 | ((ZORRO_MANUF_##manuf << 16) | ((prod) << 8) | (epc)) | ||
37 | |||
38 | typedef __u32 zorro_id; | ||
39 | |||
40 | |||
41 | /* Include the ID list */ | ||
42 | #include <linux/zorro_ids.h> | ||
43 | |||
44 | 14 | ||
45 | /* | 15 | #include <uapi/linux/zorro.h> |
46 | * GVP identifies most of its products through the 'extended product code' | ||
47 | * (epc). The epc has to be ANDed with the GVP_PRODMASK before the | ||
48 | * identification. | ||
49 | */ | ||
50 | |||
51 | #define GVP_PRODMASK (0xf8) | ||
52 | #define GVP_SCSICLKMASK (0x01) | ||
53 | |||
54 | enum GVP_flags { | ||
55 | GVP_IO = 0x01, | ||
56 | GVP_ACCEL = 0x02, | ||
57 | GVP_SCSI = 0x04, | ||
58 | GVP_24BITDMA = 0x08, | ||
59 | GVP_25BITDMA = 0x10, | ||
60 | GVP_NOBANK = 0x20, | ||
61 | GVP_14MHZ = 0x40, | ||
62 | }; | ||
63 | |||
64 | |||
65 | struct Node { | ||
66 | struct Node *ln_Succ; /* Pointer to next (successor) */ | ||
67 | struct Node *ln_Pred; /* Pointer to previous (predecessor) */ | ||
68 | __u8 ln_Type; | ||
69 | __s8 ln_Pri; /* Priority, for sorting */ | ||
70 | __s8 *ln_Name; /* ID string, null terminated */ | ||
71 | } __attribute__ ((packed)); | ||
72 | |||
73 | struct ExpansionRom { | ||
74 | /* -First 16 bytes of the expansion ROM */ | ||
75 | __u8 er_Type; /* Board type, size and flags */ | ||
76 | __u8 er_Product; /* Product number, assigned by manufacturer */ | ||
77 | __u8 er_Flags; /* Flags */ | ||
78 | __u8 er_Reserved03; /* Must be zero ($ff inverted) */ | ||
79 | __u16 er_Manufacturer; /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */ | ||
80 | __u32 er_SerialNumber; /* Available for use by manufacturer */ | ||
81 | __u16 er_InitDiagVec; /* Offset to optional "DiagArea" structure */ | ||
82 | __u8 er_Reserved0c; | ||
83 | __u8 er_Reserved0d; | ||
84 | __u8 er_Reserved0e; | ||
85 | __u8 er_Reserved0f; | ||
86 | } __attribute__ ((packed)); | ||
87 | |||
88 | /* er_Type board type bits */ | ||
89 | #define ERT_TYPEMASK 0xc0 | ||
90 | #define ERT_ZORROII 0xc0 | ||
91 | #define ERT_ZORROIII 0x80 | ||
92 | |||
93 | /* other bits defined in er_Type */ | ||
94 | #define ERTB_MEMLIST 5 /* Link RAM into free memory list */ | ||
95 | #define ERTF_MEMLIST (1<<5) | ||
96 | |||
97 | struct ConfigDev { | ||
98 | struct Node cd_Node; | ||
99 | __u8 cd_Flags; /* (read/write) */ | ||
100 | __u8 cd_Pad; /* reserved */ | ||
101 | struct ExpansionRom cd_Rom; /* copy of board's expansion ROM */ | ||
102 | void *cd_BoardAddr; /* where in memory the board was placed */ | ||
103 | __u32 cd_BoardSize; /* size of board in bytes */ | ||
104 | __u16 cd_SlotAddr; /* which slot number (PRIVATE) */ | ||
105 | __u16 cd_SlotSize; /* number of slots (PRIVATE) */ | ||
106 | void *cd_Driver; /* pointer to node of driver */ | ||
107 | struct ConfigDev *cd_NextCD; /* linked list of drivers to config */ | ||
108 | __u32 cd_Unused[4]; /* for whatever the driver wants */ | ||
109 | } __attribute__ ((packed)); | ||
110 | |||
111 | #define ZORRO_NUM_AUTO 16 | ||
112 | |||
113 | #ifdef __KERNEL__ | ||
114 | 16 | ||
17 | #include <linux/device.h> | ||
115 | #include <linux/init.h> | 18 | #include <linux/init.h> |
116 | #include <linux/ioport.h> | 19 | #include <linux/ioport.h> |
117 | #include <linux/mod_devicetable.h> | 20 | #include <linux/mod_devicetable.h> |
@@ -175,7 +78,23 @@ static inline struct zorro_driver *zorro_dev_driver(const struct zorro_dev *z) | |||
175 | 78 | ||
176 | 79 | ||
177 | extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */ | 80 | extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */ |
178 | extern struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; | 81 | extern struct zorro_dev *zorro_autocon; |
82 | |||
83 | |||
84 | /* | ||
85 | * Minimal information about a Zorro device, passed from bootinfo | ||
86 | * Only available temporarily, i.e. until initmem has been freed! | ||
87 | */ | ||
88 | |||
89 | struct zorro_dev_init { | ||
90 | struct ExpansionRom rom; | ||
91 | u16 slotaddr; | ||
92 | u16 slotsize; | ||
93 | u32 boardaddr; | ||
94 | u32 boardsize; | ||
95 | }; | ||
96 | |||
97 | extern struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata; | ||
179 | 98 | ||
180 | 99 | ||
181 | /* | 100 | /* |
@@ -229,6 +148,4 @@ extern DECLARE_BITMAP(zorro_unused_z2ram, 128); | |||
229 | #define Z2RAM_CHUNKSHIFT (16) | 148 | #define Z2RAM_CHUNKSHIFT (16) |
230 | 149 | ||
231 | 150 | ||
232 | #endif /* __KERNEL__ */ | ||
233 | |||
234 | #endif /* _LINUX_ZORRO_H */ | 151 | #endif /* _LINUX_ZORRO_H */ |
diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h index 829627d7b846..1d67fb6b23a0 100644 --- a/include/net/busy_poll.h +++ b/include/net/busy_poll.h | |||
@@ -42,27 +42,10 @@ static inline bool net_busy_loop_on(void) | |||
42 | return sysctl_net_busy_poll; | 42 | return sysctl_net_busy_poll; |
43 | } | 43 | } |
44 | 44 | ||
45 | /* a wrapper to make debug_smp_processor_id() happy | ||
46 | * we can use sched_clock() because we don't care much about precision | ||
47 | * we only care that the average is bounded | ||
48 | */ | ||
49 | #ifdef CONFIG_DEBUG_PREEMPT | ||
50 | static inline u64 busy_loop_us_clock(void) | ||
51 | { | ||
52 | u64 rc; | ||
53 | |||
54 | preempt_disable_notrace(); | ||
55 | rc = sched_clock(); | ||
56 | preempt_enable_no_resched_notrace(); | ||
57 | |||
58 | return rc >> 10; | ||
59 | } | ||
60 | #else /* CONFIG_DEBUG_PREEMPT */ | ||
61 | static inline u64 busy_loop_us_clock(void) | 45 | static inline u64 busy_loop_us_clock(void) |
62 | { | 46 | { |
63 | return sched_clock() >> 10; | 47 | return local_clock() >> 10; |
64 | } | 48 | } |
65 | #endif /* CONFIG_DEBUG_PREEMPT */ | ||
66 | 49 | ||
67 | static inline unsigned long sk_busy_loop_end_time(struct sock *sk) | 50 | static inline unsigned long sk_busy_loop_end_time(struct sock *sk) |
68 | { | 51 | { |
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 76d54270f2e2..65bb13035598 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h | |||
@@ -165,7 +165,6 @@ struct inet6_dev { | |||
165 | struct net_device *dev; | 165 | struct net_device *dev; |
166 | 166 | ||
167 | struct list_head addr_list; | 167 | struct list_head addr_list; |
168 | int valid_ll_addr_cnt; | ||
169 | 168 | ||
170 | struct ifmcaddr6 *mc_list; | 169 | struct ifmcaddr6 *mc_list; |
171 | struct ifmcaddr6 *mc_tomb; | 170 | struct ifmcaddr6 *mc_tomb; |
diff --git a/include/trace/events/ras.h b/include/trace/events/ras.h index 88b878383797..1c875ad1ee5f 100644 --- a/include/trace/events/ras.h +++ b/include/trace/events/ras.h | |||
@@ -5,7 +5,7 @@ | |||
5 | #define _TRACE_AER_H | 5 | #define _TRACE_AER_H |
6 | 6 | ||
7 | #include <linux/tracepoint.h> | 7 | #include <linux/tracepoint.h> |
8 | #include <linux/edac.h> | 8 | #include <linux/aer.h> |
9 | 9 | ||
10 | 10 | ||
11 | /* | 11 | /* |
@@ -63,10 +63,10 @@ TRACE_EVENT(aer_event, | |||
63 | 63 | ||
64 | TP_printk("%s PCIe Bus Error: severity=%s, %s\n", | 64 | TP_printk("%s PCIe Bus Error: severity=%s, %s\n", |
65 | __get_str(dev_name), | 65 | __get_str(dev_name), |
66 | __entry->severity == HW_EVENT_ERR_CORRECTED ? "Corrected" : | 66 | __entry->severity == AER_CORRECTABLE ? "Corrected" : |
67 | __entry->severity == HW_EVENT_ERR_FATAL ? | 67 | __entry->severity == AER_FATAL ? |
68 | "Fatal" : "Uncorrected", | 68 | "Fatal" : "Uncorrected, non-fatal", |
69 | __entry->severity == HW_EVENT_ERR_CORRECTED ? | 69 | __entry->severity == AER_CORRECTABLE ? |
70 | __print_flags(__entry->status, "|", aer_correctable_errors) : | 70 | __print_flags(__entry->status, "|", aer_correctable_errors) : |
71 | __print_flags(__entry->status, "|", aer_uncorrectable_errors)) | 71 | __print_flags(__entry->status, "|", aer_uncorrectable_errors)) |
72 | ); | 72 | ); |
diff --git a/include/uapi/asm-generic/statfs.h b/include/uapi/asm-generic/statfs.h index 0999647fca13..cb89cc730f0b 100644 --- a/include/uapi/asm-generic/statfs.h +++ b/include/uapi/asm-generic/statfs.h | |||
@@ -13,7 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | #ifndef __statfs_word | 14 | #ifndef __statfs_word |
15 | #if __BITS_PER_LONG == 64 | 15 | #if __BITS_PER_LONG == 64 |
16 | #define __statfs_word long | 16 | #define __statfs_word __kernel_long_t |
17 | #else | 17 | #else |
18 | #define __statfs_word __u32 | 18 | #define __statfs_word __u32 |
19 | #endif | 19 | #endif |
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 33d2b8fe166d..3ce25b5d75a9 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild | |||
@@ -426,3 +426,5 @@ header-y += x25.h | |||
426 | header-y += xattr.h | 426 | header-y += xattr.h |
427 | header-y += xfrm.h | 427 | header-y += xfrm.h |
428 | header-y += hw_breakpoint.h | 428 | header-y += hw_breakpoint.h |
429 | header-y += zorro.h | ||
430 | header-y += zorro_ids.h | ||
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h index 104838f65bc1..d6629d49a243 100644 --- a/include/uapi/linux/kexec.h +++ b/include/uapi/linux/kexec.h | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | #define KEXEC_ARCH_DEFAULT ( 0 << 16) | 19 | #define KEXEC_ARCH_DEFAULT ( 0 << 16) |
20 | #define KEXEC_ARCH_386 ( 3 << 16) | 20 | #define KEXEC_ARCH_386 ( 3 << 16) |
21 | #define KEXEC_ARCH_68K ( 4 << 16) | ||
21 | #define KEXEC_ARCH_X86_64 (62 << 16) | 22 | #define KEXEC_ARCH_X86_64 (62 << 16) |
22 | #define KEXEC_ARCH_PPC (20 << 16) | 23 | #define KEXEC_ARCH_PPC (20 << 16) |
23 | #define KEXEC_ARCH_PPC64 (21 << 16) | 24 | #define KEXEC_ARCH_PPC64 (21 << 16) |
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 959d454f76a1..e244ed412745 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h | |||
@@ -725,6 +725,7 @@ enum perf_callchain_context { | |||
725 | #define PERF_FLAG_FD_NO_GROUP (1U << 0) | 725 | #define PERF_FLAG_FD_NO_GROUP (1U << 0) |
726 | #define PERF_FLAG_FD_OUTPUT (1U << 1) | 726 | #define PERF_FLAG_FD_OUTPUT (1U << 1) |
727 | #define PERF_FLAG_PID_CGROUP (1U << 2) /* pid=cgroup id, per-cpu mode only */ | 727 | #define PERF_FLAG_PID_CGROUP (1U << 2) /* pid=cgroup id, per-cpu mode only */ |
728 | #define PERF_FLAG_FD_CLOEXEC (1U << 3) /* O_CLOEXEC */ | ||
728 | 729 | ||
729 | union perf_mem_data_src { | 730 | union perf_mem_data_src { |
730 | __u64 val; | 731 | __u64 val; |
diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h index 5a0f945927ac..34f9d7387d13 100644 --- a/include/uapi/linux/sched.h +++ b/include/uapi/linux/sched.h | |||
@@ -39,8 +39,14 @@ | |||
39 | #define SCHED_BATCH 3 | 39 | #define SCHED_BATCH 3 |
40 | /* SCHED_ISO: reserved but not implemented yet */ | 40 | /* SCHED_ISO: reserved but not implemented yet */ |
41 | #define SCHED_IDLE 5 | 41 | #define SCHED_IDLE 5 |
42 | #define SCHED_DEADLINE 6 | ||
43 | |||
42 | /* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */ | 44 | /* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */ |
43 | #define SCHED_RESET_ON_FORK 0x40000000 | 45 | #define SCHED_RESET_ON_FORK 0x40000000 |
44 | 46 | ||
47 | /* | ||
48 | * For the sched_{set,get}attr() calls | ||
49 | */ | ||
50 | #define SCHED_FLAG_RESET_ON_FORK 0x01 | ||
45 | 51 | ||
46 | #endif /* _UAPI_LINUX_SCHED_H */ | 52 | #endif /* _UAPI_LINUX_SCHED_H */ |
diff --git a/include/uapi/linux/zorro.h b/include/uapi/linux/zorro.h new file mode 100644 index 000000000000..59d021b242ed --- /dev/null +++ b/include/uapi/linux/zorro.h | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * linux/zorro.h -- Amiga AutoConfig (Zorro) Bus Definitions | ||
3 | * | ||
4 | * Copyright (C) 1995--2003 Geert Uytterhoeven | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | #ifndef _UAPI_LINUX_ZORRO_H | ||
12 | #define _UAPI_LINUX_ZORRO_H | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | |||
16 | |||
17 | /* | ||
18 | * Each Zorro board has a 32-bit ID of the form | ||
19 | * | ||
20 | * mmmmmmmmmmmmmmmmppppppppeeeeeeee | ||
21 | * | ||
22 | * with | ||
23 | * | ||
24 | * mmmmmmmmmmmmmmmm 16-bit Manufacturer ID (assigned by CBM (sigh)) | ||
25 | * pppppppp 8-bit Product ID (assigned by manufacturer) | ||
26 | * eeeeeeee 8-bit Extended Product ID (currently only used | ||
27 | * for some GVP boards) | ||
28 | */ | ||
29 | |||
30 | |||
31 | #define ZORRO_MANUF(id) ((id) >> 16) | ||
32 | #define ZORRO_PROD(id) (((id) >> 8) & 0xff) | ||
33 | #define ZORRO_EPC(id) ((id) & 0xff) | ||
34 | |||
35 | #define ZORRO_ID(manuf, prod, epc) \ | ||
36 | ((ZORRO_MANUF_##manuf << 16) | ((prod) << 8) | (epc)) | ||
37 | |||
38 | typedef __u32 zorro_id; | ||
39 | |||
40 | |||
41 | /* Include the ID list */ | ||
42 | #include <linux/zorro_ids.h> | ||
43 | |||
44 | |||
45 | /* | ||
46 | * GVP identifies most of its products through the 'extended product code' | ||
47 | * (epc). The epc has to be ANDed with the GVP_PRODMASK before the | ||
48 | * identification. | ||
49 | */ | ||
50 | |||
51 | #define GVP_PRODMASK (0xf8) | ||
52 | #define GVP_SCSICLKMASK (0x01) | ||
53 | |||
54 | enum GVP_flags { | ||
55 | GVP_IO = 0x01, | ||
56 | GVP_ACCEL = 0x02, | ||
57 | GVP_SCSI = 0x04, | ||
58 | GVP_24BITDMA = 0x08, | ||
59 | GVP_25BITDMA = 0x10, | ||
60 | GVP_NOBANK = 0x20, | ||
61 | GVP_14MHZ = 0x40, | ||
62 | }; | ||
63 | |||
64 | |||
65 | struct Node { | ||
66 | __be32 ln_Succ; /* Pointer to next (successor) */ | ||
67 | __be32 ln_Pred; /* Pointer to previous (predecessor) */ | ||
68 | __u8 ln_Type; | ||
69 | __s8 ln_Pri; /* Priority, for sorting */ | ||
70 | __be32 ln_Name; /* ID string, null terminated */ | ||
71 | } __packed; | ||
72 | |||
73 | struct ExpansionRom { | ||
74 | /* -First 16 bytes of the expansion ROM */ | ||
75 | __u8 er_Type; /* Board type, size and flags */ | ||
76 | __u8 er_Product; /* Product number, assigned by manufacturer */ | ||
77 | __u8 er_Flags; /* Flags */ | ||
78 | __u8 er_Reserved03; /* Must be zero ($ff inverted) */ | ||
79 | __be16 er_Manufacturer; /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */ | ||
80 | __be32 er_SerialNumber; /* Available for use by manufacturer */ | ||
81 | __be16 er_InitDiagVec; /* Offset to optional "DiagArea" structure */ | ||
82 | __u8 er_Reserved0c; | ||
83 | __u8 er_Reserved0d; | ||
84 | __u8 er_Reserved0e; | ||
85 | __u8 er_Reserved0f; | ||
86 | } __packed; | ||
87 | |||
88 | /* er_Type board type bits */ | ||
89 | #define ERT_TYPEMASK 0xc0 | ||
90 | #define ERT_ZORROII 0xc0 | ||
91 | #define ERT_ZORROIII 0x80 | ||
92 | |||
93 | /* other bits defined in er_Type */ | ||
94 | #define ERTB_MEMLIST 5 /* Link RAM into free memory list */ | ||
95 | #define ERTF_MEMLIST (1<<5) | ||
96 | |||
97 | struct ConfigDev { | ||
98 | struct Node cd_Node; | ||
99 | __u8 cd_Flags; /* (read/write) */ | ||
100 | __u8 cd_Pad; /* reserved */ | ||
101 | struct ExpansionRom cd_Rom; /* copy of board's expansion ROM */ | ||
102 | __be32 cd_BoardAddr; /* where in memory the board was placed */ | ||
103 | __be32 cd_BoardSize; /* size of board in bytes */ | ||
104 | __be16 cd_SlotAddr; /* which slot number (PRIVATE) */ | ||
105 | __be16 cd_SlotSize; /* number of slots (PRIVATE) */ | ||
106 | __be32 cd_Driver; /* pointer to node of driver */ | ||
107 | __be32 cd_NextCD; /* linked list of drivers to config */ | ||
108 | __be32 cd_Unused[4]; /* for whatever the driver wants */ | ||
109 | } __packed; | ||
110 | |||
111 | #define ZORRO_NUM_AUTO 16 | ||
112 | |||
113 | #endif /* _UAPI_LINUX_ZORRO_H */ | ||
diff --git a/include/linux/zorro_ids.h b/include/uapi/linux/zorro_ids.h index 74bc53bcfdcf..74bc53bcfdcf 100644 --- a/include/linux/zorro_ids.h +++ b/include/uapi/linux/zorro_ids.h | |||
diff --git a/include/xen/interface/callback.h b/include/xen/interface/callback.h index 8c5fa0e20155..dc3193f4b581 100644 --- a/include/xen/interface/callback.h +++ b/include/xen/interface/callback.h | |||
@@ -36,7 +36,7 @@ | |||
36 | * @extra_args == Operation-specific extra arguments (NULL if none). | 36 | * @extra_args == Operation-specific extra arguments (NULL if none). |
37 | */ | 37 | */ |
38 | 38 | ||
39 | /* ia64, x86: Callback for event delivery. */ | 39 | /* x86: Callback for event delivery. */ |
40 | #define CALLBACKTYPE_event 0 | 40 | #define CALLBACKTYPE_event 0 |
41 | 41 | ||
42 | /* x86: Failsafe callback when guest state cannot be restored by Xen. */ | 42 | /* x86: Failsafe callback when guest state cannot be restored by Xen. */ |
diff --git a/include/xen/interface/io/protocols.h b/include/xen/interface/io/protocols.h index 056744b4b05e..545a14ba0bb3 100644 --- a/include/xen/interface/io/protocols.h +++ b/include/xen/interface/io/protocols.h | |||
@@ -3,7 +3,6 @@ | |||
3 | 3 | ||
4 | #define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi" | 4 | #define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi" |
5 | #define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi" | 5 | #define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi" |
6 | #define XEN_IO_PROTO_ABI_IA64 "ia64-abi" | ||
7 | #define XEN_IO_PROTO_ABI_POWERPC64 "powerpc64-abi" | 6 | #define XEN_IO_PROTO_ABI_POWERPC64 "powerpc64-abi" |
8 | #define XEN_IO_PROTO_ABI_ARM "arm-abi" | 7 | #define XEN_IO_PROTO_ABI_ARM "arm-abi" |
9 | 8 | ||
@@ -11,8 +10,6 @@ | |||
11 | # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32 | 10 | # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32 |
12 | #elif defined(__x86_64__) | 11 | #elif defined(__x86_64__) |
13 | # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64 | 12 | # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64 |
14 | #elif defined(__ia64__) | ||
15 | # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64 | ||
16 | #elif defined(__powerpc64__) | 13 | #elif defined(__powerpc64__) |
17 | # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64 | 14 | # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64 |
18 | #elif defined(__arm__) || defined(__aarch64__) | 15 | #elif defined(__arm__) || defined(__aarch64__) |
diff --git a/init/Kconfig b/init/Kconfig index 4e5d96ab2034..5236dc562a36 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -532,7 +532,7 @@ config CONTEXT_TRACKING_FORCE | |||
532 | dynticks subsystem by forcing the context tracking on all | 532 | dynticks subsystem by forcing the context tracking on all |
533 | CPUs in the system. | 533 | CPUs in the system. |
534 | 534 | ||
535 | Say Y only if you're working on the developpement of an | 535 | Say Y only if you're working on the development of an |
536 | architecture backend for the context tracking. | 536 | architecture backend for the context tracking. |
537 | 537 | ||
538 | Say N otherwise, this option brings an overhead that you | 538 | Say N otherwise, this option brings an overhead that you |
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c index e5f3917aa05b..6cb20d2e7ee0 100644 --- a/kernel/context_tracking.c +++ b/kernel/context_tracking.c | |||
@@ -53,10 +53,10 @@ void context_tracking_user_enter(void) | |||
53 | /* | 53 | /* |
54 | * Repeat the user_enter() check here because some archs may be calling | 54 | * Repeat the user_enter() check here because some archs may be calling |
55 | * this from asm and if no CPU needs context tracking, they shouldn't | 55 | * this from asm and if no CPU needs context tracking, they shouldn't |
56 | * go further. Repeat the check here until they support the static key | 56 | * go further. Repeat the check here until they support the inline static |
57 | * check. | 57 | * key check. |
58 | */ | 58 | */ |
59 | if (!static_key_false(&context_tracking_enabled)) | 59 | if (!context_tracking_is_enabled()) |
60 | return; | 60 | return; |
61 | 61 | ||
62 | /* | 62 | /* |
@@ -160,7 +160,7 @@ void context_tracking_user_exit(void) | |||
160 | { | 160 | { |
161 | unsigned long flags; | 161 | unsigned long flags; |
162 | 162 | ||
163 | if (!static_key_false(&context_tracking_enabled)) | 163 | if (!context_tracking_is_enabled()) |
164 | return; | 164 | return; |
165 | 165 | ||
166 | if (in_interrupt()) | 166 | if (in_interrupt()) |
diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c index 988573a9a387..277f494c2a9a 100644 --- a/kernel/cpu/idle.c +++ b/kernel/cpu/idle.c | |||
@@ -105,14 +105,17 @@ static void cpu_idle_loop(void) | |||
105 | __current_set_polling(); | 105 | __current_set_polling(); |
106 | } | 106 | } |
107 | arch_cpu_idle_exit(); | 107 | arch_cpu_idle_exit(); |
108 | /* | ||
109 | * We need to test and propagate the TIF_NEED_RESCHED | ||
110 | * bit here because we might not have send the | ||
111 | * reschedule IPI to idle tasks. | ||
112 | */ | ||
113 | if (tif_need_resched()) | ||
114 | set_preempt_need_resched(); | ||
115 | } | 108 | } |
109 | |||
110 | /* | ||
111 | * Since we fell out of the loop above, we know | ||
112 | * TIF_NEED_RESCHED must be set, propagate it into | ||
113 | * PREEMPT_NEED_RESCHED. | ||
114 | * | ||
115 | * This is required because for polling idle loops we will | ||
116 | * not have had an IPI to fold the state for us. | ||
117 | */ | ||
118 | preempt_set_need_resched(); | ||
116 | tick_nohz_idle_exit(); | 119 | tick_nohz_idle_exit(); |
117 | schedule_preempt_disabled(); | 120 | schedule_preempt_disabled(); |
118 | } | 121 | } |
diff --git a/kernel/events/core.c b/kernel/events/core.c index f5744010a8d2..56003c6edfd3 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -119,7 +119,8 @@ static int cpu_function_call(int cpu, int (*func) (void *info), void *info) | |||
119 | 119 | ||
120 | #define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\ | 120 | #define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\ |
121 | PERF_FLAG_FD_OUTPUT |\ | 121 | PERF_FLAG_FD_OUTPUT |\ |
122 | PERF_FLAG_PID_CGROUP) | 122 | PERF_FLAG_PID_CGROUP |\ |
123 | PERF_FLAG_FD_CLOEXEC) | ||
123 | 124 | ||
124 | /* | 125 | /* |
125 | * branch priv levels that need permission checks | 126 | * branch priv levels that need permission checks |
@@ -3542,7 +3543,7 @@ static void perf_event_for_each(struct perf_event *event, | |||
3542 | static int perf_event_period(struct perf_event *event, u64 __user *arg) | 3543 | static int perf_event_period(struct perf_event *event, u64 __user *arg) |
3543 | { | 3544 | { |
3544 | struct perf_event_context *ctx = event->ctx; | 3545 | struct perf_event_context *ctx = event->ctx; |
3545 | int ret = 0; | 3546 | int ret = 0, active; |
3546 | u64 value; | 3547 | u64 value; |
3547 | 3548 | ||
3548 | if (!is_sampling_event(event)) | 3549 | if (!is_sampling_event(event)) |
@@ -3566,6 +3567,20 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) | |||
3566 | event->attr.sample_period = value; | 3567 | event->attr.sample_period = value; |
3567 | event->hw.sample_period = value; | 3568 | event->hw.sample_period = value; |
3568 | } | 3569 | } |
3570 | |||
3571 | active = (event->state == PERF_EVENT_STATE_ACTIVE); | ||
3572 | if (active) { | ||
3573 | perf_pmu_disable(ctx->pmu); | ||
3574 | event->pmu->stop(event, PERF_EF_UPDATE); | ||
3575 | } | ||
3576 | |||
3577 | local64_set(&event->hw.period_left, 0); | ||
3578 | |||
3579 | if (active) { | ||
3580 | event->pmu->start(event, PERF_EF_RELOAD); | ||
3581 | perf_pmu_enable(ctx->pmu); | ||
3582 | } | ||
3583 | |||
3569 | unlock: | 3584 | unlock: |
3570 | raw_spin_unlock_irq(&ctx->lock); | 3585 | raw_spin_unlock_irq(&ctx->lock); |
3571 | 3586 | ||
@@ -6670,6 +6685,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, | |||
6670 | INIT_LIST_HEAD(&event->event_entry); | 6685 | INIT_LIST_HEAD(&event->event_entry); |
6671 | INIT_LIST_HEAD(&event->sibling_list); | 6686 | INIT_LIST_HEAD(&event->sibling_list); |
6672 | INIT_LIST_HEAD(&event->rb_entry); | 6687 | INIT_LIST_HEAD(&event->rb_entry); |
6688 | INIT_LIST_HEAD(&event->active_entry); | ||
6689 | INIT_HLIST_NODE(&event->hlist_entry); | ||
6690 | |||
6673 | 6691 | ||
6674 | init_waitqueue_head(&event->waitq); | 6692 | init_waitqueue_head(&event->waitq); |
6675 | init_irq_work(&event->pending, perf_pending_event); | 6693 | init_irq_work(&event->pending, perf_pending_event); |
@@ -6980,6 +6998,7 @@ SYSCALL_DEFINE5(perf_event_open, | |||
6980 | int event_fd; | 6998 | int event_fd; |
6981 | int move_group = 0; | 6999 | int move_group = 0; |
6982 | int err; | 7000 | int err; |
7001 | int f_flags = O_RDWR; | ||
6983 | 7002 | ||
6984 | /* for future expandability... */ | 7003 | /* for future expandability... */ |
6985 | if (flags & ~PERF_FLAG_ALL) | 7004 | if (flags & ~PERF_FLAG_ALL) |
@@ -7008,7 +7027,10 @@ SYSCALL_DEFINE5(perf_event_open, | |||
7008 | if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1)) | 7027 | if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1)) |
7009 | return -EINVAL; | 7028 | return -EINVAL; |
7010 | 7029 | ||
7011 | event_fd = get_unused_fd(); | 7030 | if (flags & PERF_FLAG_FD_CLOEXEC) |
7031 | f_flags |= O_CLOEXEC; | ||
7032 | |||
7033 | event_fd = get_unused_fd_flags(f_flags); | ||
7012 | if (event_fd < 0) | 7034 | if (event_fd < 0) |
7013 | return event_fd; | 7035 | return event_fd; |
7014 | 7036 | ||
@@ -7130,7 +7152,8 @@ SYSCALL_DEFINE5(perf_event_open, | |||
7130 | goto err_context; | 7152 | goto err_context; |
7131 | } | 7153 | } |
7132 | 7154 | ||
7133 | event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR); | 7155 | event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, |
7156 | f_flags); | ||
7134 | if (IS_ERR(event_file)) { | 7157 | if (IS_ERR(event_file)) { |
7135 | err = PTR_ERR(event_file); | 7158 | err = PTR_ERR(event_file); |
7136 | goto err_context; | 7159 | goto err_context; |
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index e8b168af135b..146a5792b1d2 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c | |||
@@ -61,19 +61,20 @@ again: | |||
61 | * | 61 | * |
62 | * kernel user | 62 | * kernel user |
63 | * | 63 | * |
64 | * READ ->data_tail READ ->data_head | 64 | * if (LOAD ->data_tail) { LOAD ->data_head |
65 | * smp_mb() (A) smp_rmb() (C) | 65 | * (A) smp_rmb() (C) |
66 | * WRITE $data READ $data | 66 | * STORE $data LOAD $data |
67 | * smp_wmb() (B) smp_mb() (D) | 67 | * smp_wmb() (B) smp_mb() (D) |
68 | * STORE ->data_head WRITE ->data_tail | 68 | * STORE ->data_head STORE ->data_tail |
69 | * } | ||
69 | * | 70 | * |
70 | * Where A pairs with D, and B pairs with C. | 71 | * Where A pairs with D, and B pairs with C. |
71 | * | 72 | * |
72 | * I don't think A needs to be a full barrier because we won't in fact | 73 | * In our case (A) is a control dependency that separates the load of |
73 | * write data until we see the store from userspace. So we simply don't | 74 | * the ->data_tail and the stores of $data. In case ->data_tail |
74 | * issue the data WRITE until we observe it. Be conservative for now. | 75 | * indicates there is no room in the buffer to store $data we do not. |
75 | * | 76 | * |
76 | * OTOH, D needs to be a full barrier since it separates the data READ | 77 | * D needs to be a full barrier since it separates the data READ |
77 | * from the tail WRITE. | 78 | * from the tail WRITE. |
78 | * | 79 | * |
79 | * For B a WMB is sufficient since it separates two WRITEs, and for C | 80 | * For B a WMB is sufficient since it separates two WRITEs, and for C |
@@ -81,7 +82,7 @@ again: | |||
81 | * | 82 | * |
82 | * See perf_output_begin(). | 83 | * See perf_output_begin(). |
83 | */ | 84 | */ |
84 | smp_wmb(); | 85 | smp_wmb(); /* B, matches C */ |
85 | rb->user_page->data_head = head; | 86 | rb->user_page->data_head = head; |
86 | 87 | ||
87 | /* | 88 | /* |
@@ -144,17 +145,26 @@ int perf_output_begin(struct perf_output_handle *handle, | |||
144 | if (!rb->overwrite && | 145 | if (!rb->overwrite && |
145 | unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size)) | 146 | unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size)) |
146 | goto fail; | 147 | goto fail; |
148 | |||
149 | /* | ||
150 | * The above forms a control dependency barrier separating the | ||
151 | * @tail load above from the data stores below. Since the @tail | ||
152 | * load is required to compute the branch to fail below. | ||
153 | * | ||
154 | * A, matches D; the full memory barrier userspace SHOULD issue | ||
155 | * after reading the data and before storing the new tail | ||
156 | * position. | ||
157 | * | ||
158 | * See perf_output_put_handle(). | ||
159 | */ | ||
160 | |||
147 | head += size; | 161 | head += size; |
148 | } while (local_cmpxchg(&rb->head, offset, head) != offset); | 162 | } while (local_cmpxchg(&rb->head, offset, head) != offset); |
149 | 163 | ||
150 | /* | 164 | /* |
151 | * Separate the userpage->tail read from the data stores below. | 165 | * We rely on the implied barrier() by local_cmpxchg() to ensure |
152 | * Matches the MB userspace SHOULD issue after reading the data | 166 | * none of the data stores below can be lifted up by the compiler. |
153 | * and before storing the new tail position. | ||
154 | * | ||
155 | * See perf_output_put_handle(). | ||
156 | */ | 167 | */ |
157 | smp_mb(); | ||
158 | 168 | ||
159 | if (unlikely(head - local_read(&rb->wakeup) > rb->watermark)) | 169 | if (unlikely(head - local_read(&rb->wakeup) > rb->watermark)) |
160 | local_add(rb->watermark, &rb->wakeup); | 170 | local_add(rb->watermark, &rb->wakeup); |
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 24b7d6ca871b..b886a5e7d4ff 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -73,6 +73,17 @@ struct uprobe { | |||
73 | struct inode *inode; /* Also hold a ref to inode */ | 73 | struct inode *inode; /* Also hold a ref to inode */ |
74 | loff_t offset; | 74 | loff_t offset; |
75 | unsigned long flags; | 75 | unsigned long flags; |
76 | |||
77 | /* | ||
78 | * The generic code assumes that it has two members of unknown type | ||
79 | * owned by the arch-specific code: | ||
80 | * | ||
81 | * insn - copy_insn() saves the original instruction here for | ||
82 | * arch_uprobe_analyze_insn(). | ||
83 | * | ||
84 | * ixol - potentially modified instruction to execute out of | ||
85 | * line, copied to xol_area by xol_get_insn_slot(). | ||
86 | */ | ||
76 | struct arch_uprobe arch; | 87 | struct arch_uprobe arch; |
77 | }; | 88 | }; |
78 | 89 | ||
@@ -86,6 +97,29 @@ struct return_instance { | |||
86 | }; | 97 | }; |
87 | 98 | ||
88 | /* | 99 | /* |
100 | * Execute out of line area: anonymous executable mapping installed | ||
101 | * by the probed task to execute the copy of the original instruction | ||
102 | * mangled by set_swbp(). | ||
103 | * | ||
104 | * On a breakpoint hit, thread contests for a slot. It frees the | ||
105 | * slot after singlestep. Currently a fixed number of slots are | ||
106 | * allocated. | ||
107 | */ | ||
108 | struct xol_area { | ||
109 | wait_queue_head_t wq; /* if all slots are busy */ | ||
110 | atomic_t slot_count; /* number of in-use slots */ | ||
111 | unsigned long *bitmap; /* 0 = free slot */ | ||
112 | struct page *page; | ||
113 | |||
114 | /* | ||
115 | * We keep the vma's vm_start rather than a pointer to the vma | ||
116 | * itself. The probed process or a naughty kernel module could make | ||
117 | * the vma go away, and we must handle that reasonably gracefully. | ||
118 | */ | ||
119 | unsigned long vaddr; /* Page(s) of instruction slots */ | ||
120 | }; | ||
121 | |||
122 | /* | ||
89 | * valid_vma: Verify if the specified vma is an executable vma | 123 | * valid_vma: Verify if the specified vma is an executable vma |
90 | * Relax restrictions while unregistering: vm_flags might have | 124 | * Relax restrictions while unregistering: vm_flags might have |
91 | * changed after breakpoint was inserted. | 125 | * changed after breakpoint was inserted. |
@@ -330,7 +364,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned | |||
330 | int __weak | 364 | int __weak |
331 | set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) | 365 | set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) |
332 | { | 366 | { |
333 | return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); | 367 | return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)&auprobe->insn); |
334 | } | 368 | } |
335 | 369 | ||
336 | static int match_uprobe(struct uprobe *l, struct uprobe *r) | 370 | static int match_uprobe(struct uprobe *l, struct uprobe *r) |
@@ -529,8 +563,8 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp) | |||
529 | { | 563 | { |
530 | struct address_space *mapping = uprobe->inode->i_mapping; | 564 | struct address_space *mapping = uprobe->inode->i_mapping; |
531 | loff_t offs = uprobe->offset; | 565 | loff_t offs = uprobe->offset; |
532 | void *insn = uprobe->arch.insn; | 566 | void *insn = &uprobe->arch.insn; |
533 | int size = MAX_UINSN_BYTES; | 567 | int size = sizeof(uprobe->arch.insn); |
534 | int len, err = -EIO; | 568 | int len, err = -EIO; |
535 | 569 | ||
536 | /* Copy only available bytes, -EIO if nothing was read */ | 570 | /* Copy only available bytes, -EIO if nothing was read */ |
@@ -569,7 +603,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file, | |||
569 | goto out; | 603 | goto out; |
570 | 604 | ||
571 | ret = -ENOTSUPP; | 605 | ret = -ENOTSUPP; |
572 | if (is_trap_insn((uprobe_opcode_t *)uprobe->arch.insn)) | 606 | if (is_trap_insn((uprobe_opcode_t *)&uprobe->arch.insn)) |
573 | goto out; | 607 | goto out; |
574 | 608 | ||
575 | ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); | 609 | ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); |
@@ -1264,7 +1298,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe) | |||
1264 | 1298 | ||
1265 | /* Initialize the slot */ | 1299 | /* Initialize the slot */ |
1266 | copy_to_page(area->page, xol_vaddr, | 1300 | copy_to_page(area->page, xol_vaddr, |
1267 | uprobe->arch.ixol, sizeof(uprobe->arch.ixol)); | 1301 | &uprobe->arch.ixol, sizeof(uprobe->arch.ixol)); |
1268 | /* | 1302 | /* |
1269 | * We probably need flush_icache_user_range() but it needs vma. | 1303 | * We probably need flush_icache_user_range() but it needs vma. |
1270 | * This should work on supported architectures too. | 1304 | * This should work on supported architectures too. |
@@ -1403,12 +1437,10 @@ static void uprobe_warn(struct task_struct *t, const char *msg) | |||
1403 | 1437 | ||
1404 | static void dup_xol_work(struct callback_head *work) | 1438 | static void dup_xol_work(struct callback_head *work) |
1405 | { | 1439 | { |
1406 | kfree(work); | ||
1407 | |||
1408 | if (current->flags & PF_EXITING) | 1440 | if (current->flags & PF_EXITING) |
1409 | return; | 1441 | return; |
1410 | 1442 | ||
1411 | if (!__create_xol_area(current->utask->vaddr)) | 1443 | if (!__create_xol_area(current->utask->dup_xol_addr)) |
1412 | uprobe_warn(current, "dup xol area"); | 1444 | uprobe_warn(current, "dup xol area"); |
1413 | } | 1445 | } |
1414 | 1446 | ||
@@ -1419,7 +1451,6 @@ void uprobe_copy_process(struct task_struct *t, unsigned long flags) | |||
1419 | { | 1451 | { |
1420 | struct uprobe_task *utask = current->utask; | 1452 | struct uprobe_task *utask = current->utask; |
1421 | struct mm_struct *mm = current->mm; | 1453 | struct mm_struct *mm = current->mm; |
1422 | struct callback_head *work; | ||
1423 | struct xol_area *area; | 1454 | struct xol_area *area; |
1424 | 1455 | ||
1425 | t->utask = NULL; | 1456 | t->utask = NULL; |
@@ -1441,14 +1472,9 @@ void uprobe_copy_process(struct task_struct *t, unsigned long flags) | |||
1441 | if (mm == t->mm) | 1472 | if (mm == t->mm) |
1442 | return; | 1473 | return; |
1443 | 1474 | ||
1444 | /* TODO: move it into the union in uprobe_task */ | 1475 | t->utask->dup_xol_addr = area->vaddr; |
1445 | work = kmalloc(sizeof(*work), GFP_KERNEL); | 1476 | init_task_work(&t->utask->dup_xol_work, dup_xol_work); |
1446 | if (!work) | 1477 | task_work_add(t, &t->utask->dup_xol_work, true); |
1447 | return uprobe_warn(t, "dup xol area"); | ||
1448 | |||
1449 | t->utask->vaddr = area->vaddr; | ||
1450 | init_task_work(work, dup_xol_work); | ||
1451 | task_work_add(t, work, true); | ||
1452 | } | 1478 | } |
1453 | 1479 | ||
1454 | /* | 1480 | /* |
diff --git a/kernel/fork.c b/kernel/fork.c index 5721f0e3f2da..294189fc7ac8 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1087,8 +1087,10 @@ static void rt_mutex_init_task(struct task_struct *p) | |||
1087 | { | 1087 | { |
1088 | raw_spin_lock_init(&p->pi_lock); | 1088 | raw_spin_lock_init(&p->pi_lock); |
1089 | #ifdef CONFIG_RT_MUTEXES | 1089 | #ifdef CONFIG_RT_MUTEXES |
1090 | plist_head_init(&p->pi_waiters); | 1090 | p->pi_waiters = RB_ROOT; |
1091 | p->pi_waiters_leftmost = NULL; | ||
1091 | p->pi_blocked_on = NULL; | 1092 | p->pi_blocked_on = NULL; |
1093 | p->pi_top_task = NULL; | ||
1092 | #endif | 1094 | #endif |
1093 | } | 1095 | } |
1094 | 1096 | ||
@@ -1172,7 +1174,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1172 | * do not allow it to share a thread group or signal handlers or | 1174 | * do not allow it to share a thread group or signal handlers or |
1173 | * parent with the forking task. | 1175 | * parent with the forking task. |
1174 | */ | 1176 | */ |
1175 | if (clone_flags & (CLONE_SIGHAND | CLONE_PARENT)) { | 1177 | if (clone_flags & CLONE_SIGHAND) { |
1176 | if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) || | 1178 | if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) || |
1177 | (task_active_pid_ns(current) != | 1179 | (task_active_pid_ns(current) != |
1178 | current->nsproxy->pid_ns_for_children)) | 1180 | current->nsproxy->pid_ns_for_children)) |
@@ -1311,7 +1313,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1311 | #endif | 1313 | #endif |
1312 | 1314 | ||
1313 | /* Perform scheduler related setup. Assign this task to a CPU. */ | 1315 | /* Perform scheduler related setup. Assign this task to a CPU. */ |
1314 | sched_fork(clone_flags, p); | 1316 | retval = sched_fork(clone_flags, p); |
1317 | if (retval) | ||
1318 | goto bad_fork_cleanup_policy; | ||
1315 | 1319 | ||
1316 | retval = perf_event_init_task(p); | 1320 | retval = perf_event_init_task(p); |
1317 | if (retval) | 1321 | if (retval) |
@@ -1403,13 +1407,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1403 | p->tgid = p->pid; | 1407 | p->tgid = p->pid; |
1404 | } | 1408 | } |
1405 | 1409 | ||
1406 | p->pdeath_signal = 0; | ||
1407 | p->exit_state = 0; | ||
1408 | |||
1409 | p->nr_dirtied = 0; | 1410 | p->nr_dirtied = 0; |
1410 | p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); | 1411 | p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); |
1411 | p->dirty_paused_when = 0; | 1412 | p->dirty_paused_when = 0; |
1412 | 1413 | ||
1414 | p->pdeath_signal = 0; | ||
1413 | INIT_LIST_HEAD(&p->thread_group); | 1415 | INIT_LIST_HEAD(&p->thread_group); |
1414 | p->task_works = NULL; | 1416 | p->task_works = NULL; |
1415 | 1417 | ||
diff --git a/kernel/futex.c b/kernel/futex.c index f6ff0191ecf7..44a1261cb9ff 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -63,14 +63,101 @@ | |||
63 | #include <linux/sched/rt.h> | 63 | #include <linux/sched/rt.h> |
64 | #include <linux/hugetlb.h> | 64 | #include <linux/hugetlb.h> |
65 | #include <linux/freezer.h> | 65 | #include <linux/freezer.h> |
66 | #include <linux/bootmem.h> | ||
66 | 67 | ||
67 | #include <asm/futex.h> | 68 | #include <asm/futex.h> |
68 | 69 | ||
69 | #include "locking/rtmutex_common.h" | 70 | #include "locking/rtmutex_common.h" |
70 | 71 | ||
71 | int __read_mostly futex_cmpxchg_enabled; | 72 | /* |
73 | * Basic futex operation and ordering guarantees: | ||
74 | * | ||
75 | * The waiter reads the futex value in user space and calls | ||
76 | * futex_wait(). This function computes the hash bucket and acquires | ||
77 | * the hash bucket lock. After that it reads the futex user space value | ||
78 | * again and verifies that the data has not changed. If it has not changed | ||
79 | * it enqueues itself into the hash bucket, releases the hash bucket lock | ||
80 | * and schedules. | ||
81 | * | ||
82 | * The waker side modifies the user space value of the futex and calls | ||
83 | * futex_wake(). This function computes the hash bucket and acquires the | ||
84 | * hash bucket lock. Then it looks for waiters on that futex in the hash | ||
85 | * bucket and wakes them. | ||
86 | * | ||
87 | * In futex wake up scenarios where no tasks are blocked on a futex, taking | ||
88 | * the hb spinlock can be avoided and simply return. In order for this | ||
89 | * optimization to work, ordering guarantees must exist so that the waiter | ||
90 | * being added to the list is acknowledged when the list is concurrently being | ||
91 | * checked by the waker, avoiding scenarios like the following: | ||
92 | * | ||
93 | * CPU 0 CPU 1 | ||
94 | * val = *futex; | ||
95 | * sys_futex(WAIT, futex, val); | ||
96 | * futex_wait(futex, val); | ||
97 | * uval = *futex; | ||
98 | * *futex = newval; | ||
99 | * sys_futex(WAKE, futex); | ||
100 | * futex_wake(futex); | ||
101 | * if (queue_empty()) | ||
102 | * return; | ||
103 | * if (uval == val) | ||
104 | * lock(hash_bucket(futex)); | ||
105 | * queue(); | ||
106 | * unlock(hash_bucket(futex)); | ||
107 | * schedule(); | ||
108 | * | ||
109 | * This would cause the waiter on CPU 0 to wait forever because it | ||
110 | * missed the transition of the user space value from val to newval | ||
111 | * and the waker did not find the waiter in the hash bucket queue. | ||
112 | * | ||
113 | * The correct serialization ensures that a waiter either observes | ||
114 | * the changed user space value before blocking or is woken by a | ||
115 | * concurrent waker: | ||
116 | * | ||
117 | * CPU 0 CPU 1 | ||
118 | * val = *futex; | ||
119 | * sys_futex(WAIT, futex, val); | ||
120 | * futex_wait(futex, val); | ||
121 | * | ||
122 | * waiters++; | ||
123 | * mb(); (A) <-- paired with -. | ||
124 | * | | ||
125 | * lock(hash_bucket(futex)); | | ||
126 | * | | ||
127 | * uval = *futex; | | ||
128 | * | *futex = newval; | ||
129 | * | sys_futex(WAKE, futex); | ||
130 | * | futex_wake(futex); | ||
131 | * | | ||
132 | * `-------> mb(); (B) | ||
133 | * if (uval == val) | ||
134 | * queue(); | ||
135 | * unlock(hash_bucket(futex)); | ||
136 | * schedule(); if (waiters) | ||
137 | * lock(hash_bucket(futex)); | ||
138 | * wake_waiters(futex); | ||
139 | * unlock(hash_bucket(futex)); | ||
140 | * | ||
141 | * Where (A) orders the waiters increment and the futex value read -- this | ||
142 | * is guaranteed by the head counter in the hb spinlock; and where (B) | ||
143 | * orders the write to futex and the waiters read -- this is done by the | ||
144 | * barriers in get_futex_key_refs(), through either ihold or atomic_inc, | ||
145 | * depending on the futex type. | ||
146 | * | ||
147 | * This yields the following case (where X:=waiters, Y:=futex): | ||
148 | * | ||
149 | * X = Y = 0 | ||
150 | * | ||
151 | * w[X]=1 w[Y]=1 | ||
152 | * MB MB | ||
153 | * r[Y]=y r[X]=x | ||
154 | * | ||
155 | * Which guarantees that x==0 && y==0 is impossible; which translates back into | ||
156 | * the guarantee that we cannot both miss the futex variable change and the | ||
157 | * enqueue. | ||
158 | */ | ||
72 | 159 | ||
73 | #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) | 160 | int __read_mostly futex_cmpxchg_enabled; |
74 | 161 | ||
75 | /* | 162 | /* |
76 | * Futex flags used to encode options to functions and preserve them across | 163 | * Futex flags used to encode options to functions and preserve them across |
@@ -149,9 +236,41 @@ static const struct futex_q futex_q_init = { | |||
149 | struct futex_hash_bucket { | 236 | struct futex_hash_bucket { |
150 | spinlock_t lock; | 237 | spinlock_t lock; |
151 | struct plist_head chain; | 238 | struct plist_head chain; |
152 | }; | 239 | } ____cacheline_aligned_in_smp; |
153 | 240 | ||
154 | static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS]; | 241 | static unsigned long __read_mostly futex_hashsize; |
242 | |||
243 | static struct futex_hash_bucket *futex_queues; | ||
244 | |||
245 | static inline void futex_get_mm(union futex_key *key) | ||
246 | { | ||
247 | atomic_inc(&key->private.mm->mm_count); | ||
248 | /* | ||
249 | * Ensure futex_get_mm() implies a full barrier such that | ||
250 | * get_futex_key() implies a full barrier. This is relied upon | ||
251 | * as full barrier (B), see the ordering comment above. | ||
252 | */ | ||
253 | smp_mb__after_atomic_inc(); | ||
254 | } | ||
255 | |||
256 | static inline bool hb_waiters_pending(struct futex_hash_bucket *hb) | ||
257 | { | ||
258 | #ifdef CONFIG_SMP | ||
259 | /* | ||
260 | * Tasks trying to enter the critical region are most likely | ||
261 | * potential waiters that will be added to the plist. Ensure | ||
262 | * that wakers won't miss to-be-slept tasks in the window between | ||
263 | * the wait call and the actual plist_add. | ||
264 | */ | ||
265 | if (spin_is_locked(&hb->lock)) | ||
266 | return true; | ||
267 | smp_rmb(); /* Make sure we check the lock state first */ | ||
268 | |||
269 | return !plist_head_empty(&hb->chain); | ||
270 | #else | ||
271 | return true; | ||
272 | #endif | ||
273 | } | ||
155 | 274 | ||
156 | /* | 275 | /* |
157 | * We hash on the keys returned from get_futex_key (see below). | 276 | * We hash on the keys returned from get_futex_key (see below). |
@@ -161,7 +280,7 @@ static struct futex_hash_bucket *hash_futex(union futex_key *key) | |||
161 | u32 hash = jhash2((u32*)&key->both.word, | 280 | u32 hash = jhash2((u32*)&key->both.word, |
162 | (sizeof(key->both.word)+sizeof(key->both.ptr))/4, | 281 | (sizeof(key->both.word)+sizeof(key->both.ptr))/4, |
163 | key->both.offset); | 282 | key->both.offset); |
164 | return &futex_queues[hash & ((1 << FUTEX_HASHBITS)-1)]; | 283 | return &futex_queues[hash & (futex_hashsize - 1)]; |
165 | } | 284 | } |
166 | 285 | ||
167 | /* | 286 | /* |
@@ -187,10 +306,10 @@ static void get_futex_key_refs(union futex_key *key) | |||
187 | 306 | ||
188 | switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { | 307 | switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { |
189 | case FUT_OFF_INODE: | 308 | case FUT_OFF_INODE: |
190 | ihold(key->shared.inode); | 309 | ihold(key->shared.inode); /* implies MB (B) */ |
191 | break; | 310 | break; |
192 | case FUT_OFF_MMSHARED: | 311 | case FUT_OFF_MMSHARED: |
193 | atomic_inc(&key->private.mm->mm_count); | 312 | futex_get_mm(key); /* implies MB (B) */ |
194 | break; | 313 | break; |
195 | } | 314 | } |
196 | } | 315 | } |
@@ -264,7 +383,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) | |||
264 | if (!fshared) { | 383 | if (!fshared) { |
265 | key->private.mm = mm; | 384 | key->private.mm = mm; |
266 | key->private.address = address; | 385 | key->private.address = address; |
267 | get_futex_key_refs(key); | 386 | get_futex_key_refs(key); /* implies MB (B) */ |
268 | return 0; | 387 | return 0; |
269 | } | 388 | } |
270 | 389 | ||
@@ -371,7 +490,7 @@ again: | |||
371 | key->shared.pgoff = basepage_index(page); | 490 | key->shared.pgoff = basepage_index(page); |
372 | } | 491 | } |
373 | 492 | ||
374 | get_futex_key_refs(key); | 493 | get_futex_key_refs(key); /* implies MB (B) */ |
375 | 494 | ||
376 | out: | 495 | out: |
377 | unlock_page(page_head); | 496 | unlock_page(page_head); |
@@ -598,13 +717,10 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, | |||
598 | { | 717 | { |
599 | struct futex_pi_state *pi_state = NULL; | 718 | struct futex_pi_state *pi_state = NULL; |
600 | struct futex_q *this, *next; | 719 | struct futex_q *this, *next; |
601 | struct plist_head *head; | ||
602 | struct task_struct *p; | 720 | struct task_struct *p; |
603 | pid_t pid = uval & FUTEX_TID_MASK; | 721 | pid_t pid = uval & FUTEX_TID_MASK; |
604 | 722 | ||
605 | head = &hb->chain; | 723 | plist_for_each_entry_safe(this, next, &hb->chain, list) { |
606 | |||
607 | plist_for_each_entry_safe(this, next, head, list) { | ||
608 | if (match_futex(&this->key, key)) { | 724 | if (match_futex(&this->key, key)) { |
609 | /* | 725 | /* |
610 | * Another waiter already exists - bump up | 726 | * Another waiter already exists - bump up |
@@ -986,7 +1102,6 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset) | |||
986 | { | 1102 | { |
987 | struct futex_hash_bucket *hb; | 1103 | struct futex_hash_bucket *hb; |
988 | struct futex_q *this, *next; | 1104 | struct futex_q *this, *next; |
989 | struct plist_head *head; | ||
990 | union futex_key key = FUTEX_KEY_INIT; | 1105 | union futex_key key = FUTEX_KEY_INIT; |
991 | int ret; | 1106 | int ret; |
992 | 1107 | ||
@@ -998,10 +1113,14 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset) | |||
998 | goto out; | 1113 | goto out; |
999 | 1114 | ||
1000 | hb = hash_futex(&key); | 1115 | hb = hash_futex(&key); |
1116 | |||
1117 | /* Make sure we really have tasks to wakeup */ | ||
1118 | if (!hb_waiters_pending(hb)) | ||
1119 | goto out_put_key; | ||
1120 | |||
1001 | spin_lock(&hb->lock); | 1121 | spin_lock(&hb->lock); |
1002 | head = &hb->chain; | ||
1003 | 1122 | ||
1004 | plist_for_each_entry_safe(this, next, head, list) { | 1123 | plist_for_each_entry_safe(this, next, &hb->chain, list) { |
1005 | if (match_futex (&this->key, &key)) { | 1124 | if (match_futex (&this->key, &key)) { |
1006 | if (this->pi_state || this->rt_waiter) { | 1125 | if (this->pi_state || this->rt_waiter) { |
1007 | ret = -EINVAL; | 1126 | ret = -EINVAL; |
@@ -1019,6 +1138,7 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset) | |||
1019 | } | 1138 | } |
1020 | 1139 | ||
1021 | spin_unlock(&hb->lock); | 1140 | spin_unlock(&hb->lock); |
1141 | out_put_key: | ||
1022 | put_futex_key(&key); | 1142 | put_futex_key(&key); |
1023 | out: | 1143 | out: |
1024 | return ret; | 1144 | return ret; |
@@ -1034,7 +1154,6 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, | |||
1034 | { | 1154 | { |
1035 | union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT; | 1155 | union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT; |
1036 | struct futex_hash_bucket *hb1, *hb2; | 1156 | struct futex_hash_bucket *hb1, *hb2; |
1037 | struct plist_head *head; | ||
1038 | struct futex_q *this, *next; | 1157 | struct futex_q *this, *next; |
1039 | int ret, op_ret; | 1158 | int ret, op_ret; |
1040 | 1159 | ||
@@ -1082,9 +1201,7 @@ retry_private: | |||
1082 | goto retry; | 1201 | goto retry; |
1083 | } | 1202 | } |
1084 | 1203 | ||
1085 | head = &hb1->chain; | 1204 | plist_for_each_entry_safe(this, next, &hb1->chain, list) { |
1086 | |||
1087 | plist_for_each_entry_safe(this, next, head, list) { | ||
1088 | if (match_futex (&this->key, &key1)) { | 1205 | if (match_futex (&this->key, &key1)) { |
1089 | if (this->pi_state || this->rt_waiter) { | 1206 | if (this->pi_state || this->rt_waiter) { |
1090 | ret = -EINVAL; | 1207 | ret = -EINVAL; |
@@ -1097,10 +1214,8 @@ retry_private: | |||
1097 | } | 1214 | } |
1098 | 1215 | ||
1099 | if (op_ret > 0) { | 1216 | if (op_ret > 0) { |
1100 | head = &hb2->chain; | ||
1101 | |||
1102 | op_ret = 0; | 1217 | op_ret = 0; |
1103 | plist_for_each_entry_safe(this, next, head, list) { | 1218 | plist_for_each_entry_safe(this, next, &hb2->chain, list) { |
1104 | if (match_futex (&this->key, &key2)) { | 1219 | if (match_futex (&this->key, &key2)) { |
1105 | if (this->pi_state || this->rt_waiter) { | 1220 | if (this->pi_state || this->rt_waiter) { |
1106 | ret = -EINVAL; | 1221 | ret = -EINVAL; |
@@ -1270,7 +1385,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, | |||
1270 | int drop_count = 0, task_count = 0, ret; | 1385 | int drop_count = 0, task_count = 0, ret; |
1271 | struct futex_pi_state *pi_state = NULL; | 1386 | struct futex_pi_state *pi_state = NULL; |
1272 | struct futex_hash_bucket *hb1, *hb2; | 1387 | struct futex_hash_bucket *hb1, *hb2; |
1273 | struct plist_head *head1; | ||
1274 | struct futex_q *this, *next; | 1388 | struct futex_q *this, *next; |
1275 | u32 curval2; | 1389 | u32 curval2; |
1276 | 1390 | ||
@@ -1393,8 +1507,7 @@ retry_private: | |||
1393 | } | 1507 | } |
1394 | } | 1508 | } |
1395 | 1509 | ||
1396 | head1 = &hb1->chain; | 1510 | plist_for_each_entry_safe(this, next, &hb1->chain, list) { |
1397 | plist_for_each_entry_safe(this, next, head1, list) { | ||
1398 | if (task_count - nr_wake >= nr_requeue) | 1511 | if (task_count - nr_wake >= nr_requeue) |
1399 | break; | 1512 | break; |
1400 | 1513 | ||
@@ -1489,12 +1602,12 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q) | |||
1489 | hb = hash_futex(&q->key); | 1602 | hb = hash_futex(&q->key); |
1490 | q->lock_ptr = &hb->lock; | 1603 | q->lock_ptr = &hb->lock; |
1491 | 1604 | ||
1492 | spin_lock(&hb->lock); | 1605 | spin_lock(&hb->lock); /* implies MB (A) */ |
1493 | return hb; | 1606 | return hb; |
1494 | } | 1607 | } |
1495 | 1608 | ||
1496 | static inline void | 1609 | static inline void |
1497 | queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb) | 1610 | queue_unlock(struct futex_hash_bucket *hb) |
1498 | __releases(&hb->lock) | 1611 | __releases(&hb->lock) |
1499 | { | 1612 | { |
1500 | spin_unlock(&hb->lock); | 1613 | spin_unlock(&hb->lock); |
@@ -1867,7 +1980,7 @@ retry_private: | |||
1867 | ret = get_futex_value_locked(&uval, uaddr); | 1980 | ret = get_futex_value_locked(&uval, uaddr); |
1868 | 1981 | ||
1869 | if (ret) { | 1982 | if (ret) { |
1870 | queue_unlock(q, *hb); | 1983 | queue_unlock(*hb); |
1871 | 1984 | ||
1872 | ret = get_user(uval, uaddr); | 1985 | ret = get_user(uval, uaddr); |
1873 | if (ret) | 1986 | if (ret) |
@@ -1881,7 +1994,7 @@ retry_private: | |||
1881 | } | 1994 | } |
1882 | 1995 | ||
1883 | if (uval != val) { | 1996 | if (uval != val) { |
1884 | queue_unlock(q, *hb); | 1997 | queue_unlock(*hb); |
1885 | ret = -EWOULDBLOCK; | 1998 | ret = -EWOULDBLOCK; |
1886 | } | 1999 | } |
1887 | 2000 | ||
@@ -2029,7 +2142,7 @@ retry_private: | |||
2029 | * Task is exiting and we just wait for the | 2142 | * Task is exiting and we just wait for the |
2030 | * exit to complete. | 2143 | * exit to complete. |
2031 | */ | 2144 | */ |
2032 | queue_unlock(&q, hb); | 2145 | queue_unlock(hb); |
2033 | put_futex_key(&q.key); | 2146 | put_futex_key(&q.key); |
2034 | cond_resched(); | 2147 | cond_resched(); |
2035 | goto retry; | 2148 | goto retry; |
@@ -2081,7 +2194,7 @@ retry_private: | |||
2081 | goto out_put_key; | 2194 | goto out_put_key; |
2082 | 2195 | ||
2083 | out_unlock_put_key: | 2196 | out_unlock_put_key: |
2084 | queue_unlock(&q, hb); | 2197 | queue_unlock(hb); |
2085 | 2198 | ||
2086 | out_put_key: | 2199 | out_put_key: |
2087 | put_futex_key(&q.key); | 2200 | put_futex_key(&q.key); |
@@ -2091,7 +2204,7 @@ out: | |||
2091 | return ret != -EINTR ? ret : -ERESTARTNOINTR; | 2204 | return ret != -EINTR ? ret : -ERESTARTNOINTR; |
2092 | 2205 | ||
2093 | uaddr_faulted: | 2206 | uaddr_faulted: |
2094 | queue_unlock(&q, hb); | 2207 | queue_unlock(hb); |
2095 | 2208 | ||
2096 | ret = fault_in_user_writeable(uaddr); | 2209 | ret = fault_in_user_writeable(uaddr); |
2097 | if (ret) | 2210 | if (ret) |
@@ -2113,7 +2226,6 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags) | |||
2113 | { | 2226 | { |
2114 | struct futex_hash_bucket *hb; | 2227 | struct futex_hash_bucket *hb; |
2115 | struct futex_q *this, *next; | 2228 | struct futex_q *this, *next; |
2116 | struct plist_head *head; | ||
2117 | union futex_key key = FUTEX_KEY_INIT; | 2229 | union futex_key key = FUTEX_KEY_INIT; |
2118 | u32 uval, vpid = task_pid_vnr(current); | 2230 | u32 uval, vpid = task_pid_vnr(current); |
2119 | int ret; | 2231 | int ret; |
@@ -2153,9 +2265,7 @@ retry: | |||
2153 | * Ok, other tasks may need to be woken up - check waiters | 2265 | * Ok, other tasks may need to be woken up - check waiters |
2154 | * and do the wakeup if necessary: | 2266 | * and do the wakeup if necessary: |
2155 | */ | 2267 | */ |
2156 | head = &hb->chain; | 2268 | plist_for_each_entry_safe(this, next, &hb->chain, list) { |
2157 | |||
2158 | plist_for_each_entry_safe(this, next, head, list) { | ||
2159 | if (!match_futex (&this->key, &key)) | 2269 | if (!match_futex (&this->key, &key)) |
2160 | continue; | 2270 | continue; |
2161 | ret = wake_futex_pi(uaddr, uval, this); | 2271 | ret = wake_futex_pi(uaddr, uval, this); |
@@ -2316,6 +2426,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, | |||
2316 | * code while we sleep on uaddr. | 2426 | * code while we sleep on uaddr. |
2317 | */ | 2427 | */ |
2318 | debug_rt_mutex_init_waiter(&rt_waiter); | 2428 | debug_rt_mutex_init_waiter(&rt_waiter); |
2429 | RB_CLEAR_NODE(&rt_waiter.pi_tree_entry); | ||
2430 | RB_CLEAR_NODE(&rt_waiter.tree_entry); | ||
2319 | rt_waiter.task = NULL; | 2431 | rt_waiter.task = NULL; |
2320 | 2432 | ||
2321 | ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, VERIFY_WRITE); | 2433 | ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, VERIFY_WRITE); |
@@ -2734,8 +2846,21 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, | |||
2734 | static int __init futex_init(void) | 2846 | static int __init futex_init(void) |
2735 | { | 2847 | { |
2736 | u32 curval; | 2848 | u32 curval; |
2737 | int i; | 2849 | unsigned int futex_shift; |
2850 | unsigned long i; | ||
2851 | |||
2852 | #if CONFIG_BASE_SMALL | ||
2853 | futex_hashsize = 16; | ||
2854 | #else | ||
2855 | futex_hashsize = roundup_pow_of_two(256 * num_possible_cpus()); | ||
2856 | #endif | ||
2738 | 2857 | ||
2858 | futex_queues = alloc_large_system_hash("futex", sizeof(*futex_queues), | ||
2859 | futex_hashsize, 0, | ||
2860 | futex_hashsize < 256 ? HASH_SMALL : 0, | ||
2861 | &futex_shift, NULL, | ||
2862 | futex_hashsize, futex_hashsize); | ||
2863 | futex_hashsize = 1UL << futex_shift; | ||
2739 | /* | 2864 | /* |
2740 | * This will fail and we want it. Some arch implementations do | 2865 | * This will fail and we want it. Some arch implementations do |
2741 | * runtime detection of the futex_atomic_cmpxchg_inatomic() | 2866 | * runtime detection of the futex_atomic_cmpxchg_inatomic() |
@@ -2749,7 +2874,7 @@ static int __init futex_init(void) | |||
2749 | if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT) | 2874 | if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT) |
2750 | futex_cmpxchg_enabled = 1; | 2875 | futex_cmpxchg_enabled = 1; |
2751 | 2876 | ||
2752 | for (i = 0; i < ARRAY_SIZE(futex_queues); i++) { | 2877 | for (i = 0; i < futex_hashsize; i++) { |
2753 | plist_head_init(&futex_queues[i].chain); | 2878 | plist_head_init(&futex_queues[i].chain); |
2754 | spin_lock_init(&futex_queues[i].lock); | 2879 | spin_lock_init(&futex_queues[i].lock); |
2755 | } | 2880 | } |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 383319bae3f7..09094361dce5 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/sched.h> | 46 | #include <linux/sched.h> |
47 | #include <linux/sched/sysctl.h> | 47 | #include <linux/sched/sysctl.h> |
48 | #include <linux/sched/rt.h> | 48 | #include <linux/sched/rt.h> |
49 | #include <linux/sched/deadline.h> | ||
49 | #include <linux/timer.h> | 50 | #include <linux/timer.h> |
50 | #include <linux/freezer.h> | 51 | #include <linux/freezer.h> |
51 | 52 | ||
@@ -1610,7 +1611,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
1610 | unsigned long slack; | 1611 | unsigned long slack; |
1611 | 1612 | ||
1612 | slack = current->timer_slack_ns; | 1613 | slack = current->timer_slack_ns; |
1613 | if (rt_task(current)) | 1614 | if (dl_task(current) || rt_task(current)) |
1614 | slack = 0; | 1615 | slack = 0; |
1615 | 1616 | ||
1616 | hrtimer_init_on_stack(&t.timer, clockid, mode); | 1617 | hrtimer_init_on_stack(&t.timer, clockid, mode); |
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 576ba756a32d..eb8a54783fa0 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c | |||
@@ -590,6 +590,7 @@ static int very_verbose(struct lock_class *class) | |||
590 | /* | 590 | /* |
591 | * Is this the address of a static object: | 591 | * Is this the address of a static object: |
592 | */ | 592 | */ |
593 | #ifdef __KERNEL__ | ||
593 | static int static_obj(void *obj) | 594 | static int static_obj(void *obj) |
594 | { | 595 | { |
595 | unsigned long start = (unsigned long) &_stext, | 596 | unsigned long start = (unsigned long) &_stext, |
@@ -616,6 +617,7 @@ static int static_obj(void *obj) | |||
616 | */ | 617 | */ |
617 | return is_module_address(addr) || is_module_percpu_address(addr); | 618 | return is_module_address(addr) || is_module_percpu_address(addr); |
618 | } | 619 | } |
620 | #endif | ||
619 | 621 | ||
620 | /* | 622 | /* |
621 | * To make lock name printouts unique, we calculate a unique | 623 | * To make lock name printouts unique, we calculate a unique |
@@ -4115,6 +4117,7 @@ void debug_check_no_locks_held(void) | |||
4115 | } | 4117 | } |
4116 | EXPORT_SYMBOL_GPL(debug_check_no_locks_held); | 4118 | EXPORT_SYMBOL_GPL(debug_check_no_locks_held); |
4117 | 4119 | ||
4120 | #ifdef __KERNEL__ | ||
4118 | void debug_show_all_locks(void) | 4121 | void debug_show_all_locks(void) |
4119 | { | 4122 | { |
4120 | struct task_struct *g, *p; | 4123 | struct task_struct *g, *p; |
@@ -4172,6 +4175,7 @@ retry: | |||
4172 | read_unlock(&tasklist_lock); | 4175 | read_unlock(&tasklist_lock); |
4173 | } | 4176 | } |
4174 | EXPORT_SYMBOL_GPL(debug_show_all_locks); | 4177 | EXPORT_SYMBOL_GPL(debug_show_all_locks); |
4178 | #endif | ||
4175 | 4179 | ||
4176 | /* | 4180 | /* |
4177 | * Careful: only use this function if you are sure that | 4181 | * Careful: only use this function if you are sure that |
diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c index 7e3443fe1f48..faf6f5b53e77 100644 --- a/kernel/locking/mutex-debug.c +++ b/kernel/locking/mutex-debug.c | |||
@@ -75,7 +75,12 @@ void debug_mutex_unlock(struct mutex *lock) | |||
75 | return; | 75 | return; |
76 | 76 | ||
77 | DEBUG_LOCKS_WARN_ON(lock->magic != lock); | 77 | DEBUG_LOCKS_WARN_ON(lock->magic != lock); |
78 | DEBUG_LOCKS_WARN_ON(lock->owner != current); | 78 | |
79 | if (!lock->owner) | ||
80 | DEBUG_LOCKS_WARN_ON(!lock->owner); | ||
81 | else | ||
82 | DEBUG_LOCKS_WARN_ON(lock->owner != current); | ||
83 | |||
79 | DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next); | 84 | DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next); |
80 | mutex_clear_owner(lock); | 85 | mutex_clear_owner(lock); |
81 | } | 86 | } |
diff --git a/kernel/locking/rtmutex-debug.c b/kernel/locking/rtmutex-debug.c index 13b243a323fa..49b2ed3dced8 100644 --- a/kernel/locking/rtmutex-debug.c +++ b/kernel/locking/rtmutex-debug.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/kallsyms.h> | 24 | #include <linux/kallsyms.h> |
25 | #include <linux/syscalls.h> | 25 | #include <linux/syscalls.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/plist.h> | 27 | #include <linux/rbtree.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/debug_locks.h> | 29 | #include <linux/debug_locks.h> |
30 | 30 | ||
@@ -57,7 +57,7 @@ static void printk_lock(struct rt_mutex *lock, int print_owner) | |||
57 | 57 | ||
58 | void rt_mutex_debug_task_free(struct task_struct *task) | 58 | void rt_mutex_debug_task_free(struct task_struct *task) |
59 | { | 59 | { |
60 | DEBUG_LOCKS_WARN_ON(!plist_head_empty(&task->pi_waiters)); | 60 | DEBUG_LOCKS_WARN_ON(!RB_EMPTY_ROOT(&task->pi_waiters)); |
61 | DEBUG_LOCKS_WARN_ON(task->pi_blocked_on); | 61 | DEBUG_LOCKS_WARN_ON(task->pi_blocked_on); |
62 | } | 62 | } |
63 | 63 | ||
@@ -154,16 +154,12 @@ void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock) | |||
154 | void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter) | 154 | void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter) |
155 | { | 155 | { |
156 | memset(waiter, 0x11, sizeof(*waiter)); | 156 | memset(waiter, 0x11, sizeof(*waiter)); |
157 | plist_node_init(&waiter->list_entry, MAX_PRIO); | ||
158 | plist_node_init(&waiter->pi_list_entry, MAX_PRIO); | ||
159 | waiter->deadlock_task_pid = NULL; | 157 | waiter->deadlock_task_pid = NULL; |
160 | } | 158 | } |
161 | 159 | ||
162 | void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter) | 160 | void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter) |
163 | { | 161 | { |
164 | put_pid(waiter->deadlock_task_pid); | 162 | put_pid(waiter->deadlock_task_pid); |
165 | DEBUG_LOCKS_WARN_ON(!plist_node_empty(&waiter->list_entry)); | ||
166 | DEBUG_LOCKS_WARN_ON(!plist_node_empty(&waiter->pi_list_entry)); | ||
167 | memset(waiter, 0x22, sizeof(*waiter)); | 163 | memset(waiter, 0x22, sizeof(*waiter)); |
168 | } | 164 | } |
169 | 165 | ||
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index 0dd6aec1cb6a..2e960a2bab81 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/export.h> | 14 | #include <linux/export.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/sched/rt.h> | 16 | #include <linux/sched/rt.h> |
17 | #include <linux/sched/deadline.h> | ||
17 | #include <linux/timer.h> | 18 | #include <linux/timer.h> |
18 | 19 | ||
19 | #include "rtmutex_common.h" | 20 | #include "rtmutex_common.h" |
@@ -91,10 +92,107 @@ static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) | |||
91 | } | 92 | } |
92 | #endif | 93 | #endif |
93 | 94 | ||
95 | static inline int | ||
96 | rt_mutex_waiter_less(struct rt_mutex_waiter *left, | ||
97 | struct rt_mutex_waiter *right) | ||
98 | { | ||
99 | if (left->prio < right->prio) | ||
100 | return 1; | ||
101 | |||
102 | /* | ||
103 | * If both waiters have dl_prio(), we check the deadlines of the | ||
104 | * associated tasks. | ||
105 | * If left waiter has a dl_prio(), and we didn't return 1 above, | ||
106 | * then right waiter has a dl_prio() too. | ||
107 | */ | ||
108 | if (dl_prio(left->prio)) | ||
109 | return (left->task->dl.deadline < right->task->dl.deadline); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static void | ||
115 | rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter) | ||
116 | { | ||
117 | struct rb_node **link = &lock->waiters.rb_node; | ||
118 | struct rb_node *parent = NULL; | ||
119 | struct rt_mutex_waiter *entry; | ||
120 | int leftmost = 1; | ||
121 | |||
122 | while (*link) { | ||
123 | parent = *link; | ||
124 | entry = rb_entry(parent, struct rt_mutex_waiter, tree_entry); | ||
125 | if (rt_mutex_waiter_less(waiter, entry)) { | ||
126 | link = &parent->rb_left; | ||
127 | } else { | ||
128 | link = &parent->rb_right; | ||
129 | leftmost = 0; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | if (leftmost) | ||
134 | lock->waiters_leftmost = &waiter->tree_entry; | ||
135 | |||
136 | rb_link_node(&waiter->tree_entry, parent, link); | ||
137 | rb_insert_color(&waiter->tree_entry, &lock->waiters); | ||
138 | } | ||
139 | |||
140 | static void | ||
141 | rt_mutex_dequeue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter) | ||
142 | { | ||
143 | if (RB_EMPTY_NODE(&waiter->tree_entry)) | ||
144 | return; | ||
145 | |||
146 | if (lock->waiters_leftmost == &waiter->tree_entry) | ||
147 | lock->waiters_leftmost = rb_next(&waiter->tree_entry); | ||
148 | |||
149 | rb_erase(&waiter->tree_entry, &lock->waiters); | ||
150 | RB_CLEAR_NODE(&waiter->tree_entry); | ||
151 | } | ||
152 | |||
153 | static void | ||
154 | rt_mutex_enqueue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter) | ||
155 | { | ||
156 | struct rb_node **link = &task->pi_waiters.rb_node; | ||
157 | struct rb_node *parent = NULL; | ||
158 | struct rt_mutex_waiter *entry; | ||
159 | int leftmost = 1; | ||
160 | |||
161 | while (*link) { | ||
162 | parent = *link; | ||
163 | entry = rb_entry(parent, struct rt_mutex_waiter, pi_tree_entry); | ||
164 | if (rt_mutex_waiter_less(waiter, entry)) { | ||
165 | link = &parent->rb_left; | ||
166 | } else { | ||
167 | link = &parent->rb_right; | ||
168 | leftmost = 0; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | if (leftmost) | ||
173 | task->pi_waiters_leftmost = &waiter->pi_tree_entry; | ||
174 | |||
175 | rb_link_node(&waiter->pi_tree_entry, parent, link); | ||
176 | rb_insert_color(&waiter->pi_tree_entry, &task->pi_waiters); | ||
177 | } | ||
178 | |||
179 | static void | ||
180 | rt_mutex_dequeue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter) | ||
181 | { | ||
182 | if (RB_EMPTY_NODE(&waiter->pi_tree_entry)) | ||
183 | return; | ||
184 | |||
185 | if (task->pi_waiters_leftmost == &waiter->pi_tree_entry) | ||
186 | task->pi_waiters_leftmost = rb_next(&waiter->pi_tree_entry); | ||
187 | |||
188 | rb_erase(&waiter->pi_tree_entry, &task->pi_waiters); | ||
189 | RB_CLEAR_NODE(&waiter->pi_tree_entry); | ||
190 | } | ||
191 | |||
94 | /* | 192 | /* |
95 | * Calculate task priority from the waiter list priority | 193 | * Calculate task priority from the waiter tree priority |
96 | * | 194 | * |
97 | * Return task->normal_prio when the waiter list is empty or when | 195 | * Return task->normal_prio when the waiter tree is empty or when |
98 | * the waiter is not allowed to do priority boosting | 196 | * the waiter is not allowed to do priority boosting |
99 | */ | 197 | */ |
100 | int rt_mutex_getprio(struct task_struct *task) | 198 | int rt_mutex_getprio(struct task_struct *task) |
@@ -102,10 +200,18 @@ int rt_mutex_getprio(struct task_struct *task) | |||
102 | if (likely(!task_has_pi_waiters(task))) | 200 | if (likely(!task_has_pi_waiters(task))) |
103 | return task->normal_prio; | 201 | return task->normal_prio; |
104 | 202 | ||
105 | return min(task_top_pi_waiter(task)->pi_list_entry.prio, | 203 | return min(task_top_pi_waiter(task)->prio, |
106 | task->normal_prio); | 204 | task->normal_prio); |
107 | } | 205 | } |
108 | 206 | ||
207 | struct task_struct *rt_mutex_get_top_task(struct task_struct *task) | ||
208 | { | ||
209 | if (likely(!task_has_pi_waiters(task))) | ||
210 | return NULL; | ||
211 | |||
212 | return task_top_pi_waiter(task)->task; | ||
213 | } | ||
214 | |||
109 | /* | 215 | /* |
110 | * Adjust the priority of a task, after its pi_waiters got modified. | 216 | * Adjust the priority of a task, after its pi_waiters got modified. |
111 | * | 217 | * |
@@ -115,7 +221,7 @@ static void __rt_mutex_adjust_prio(struct task_struct *task) | |||
115 | { | 221 | { |
116 | int prio = rt_mutex_getprio(task); | 222 | int prio = rt_mutex_getprio(task); |
117 | 223 | ||
118 | if (task->prio != prio) | 224 | if (task->prio != prio || dl_prio(prio)) |
119 | rt_mutex_setprio(task, prio); | 225 | rt_mutex_setprio(task, prio); |
120 | } | 226 | } |
121 | 227 | ||
@@ -233,7 +339,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
233 | * When deadlock detection is off then we check, if further | 339 | * When deadlock detection is off then we check, if further |
234 | * priority adjustment is necessary. | 340 | * priority adjustment is necessary. |
235 | */ | 341 | */ |
236 | if (!detect_deadlock && waiter->list_entry.prio == task->prio) | 342 | if (!detect_deadlock && waiter->prio == task->prio) |
237 | goto out_unlock_pi; | 343 | goto out_unlock_pi; |
238 | 344 | ||
239 | lock = waiter->lock; | 345 | lock = waiter->lock; |
@@ -254,9 +360,9 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
254 | top_waiter = rt_mutex_top_waiter(lock); | 360 | top_waiter = rt_mutex_top_waiter(lock); |
255 | 361 | ||
256 | /* Requeue the waiter */ | 362 | /* Requeue the waiter */ |
257 | plist_del(&waiter->list_entry, &lock->wait_list); | 363 | rt_mutex_dequeue(lock, waiter); |
258 | waiter->list_entry.prio = task->prio; | 364 | waiter->prio = task->prio; |
259 | plist_add(&waiter->list_entry, &lock->wait_list); | 365 | rt_mutex_enqueue(lock, waiter); |
260 | 366 | ||
261 | /* Release the task */ | 367 | /* Release the task */ |
262 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | 368 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
@@ -280,17 +386,15 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, | |||
280 | 386 | ||
281 | if (waiter == rt_mutex_top_waiter(lock)) { | 387 | if (waiter == rt_mutex_top_waiter(lock)) { |
282 | /* Boost the owner */ | 388 | /* Boost the owner */ |
283 | plist_del(&top_waiter->pi_list_entry, &task->pi_waiters); | 389 | rt_mutex_dequeue_pi(task, top_waiter); |
284 | waiter->pi_list_entry.prio = waiter->list_entry.prio; | 390 | rt_mutex_enqueue_pi(task, waiter); |
285 | plist_add(&waiter->pi_list_entry, &task->pi_waiters); | ||
286 | __rt_mutex_adjust_prio(task); | 391 | __rt_mutex_adjust_prio(task); |
287 | 392 | ||
288 | } else if (top_waiter == waiter) { | 393 | } else if (top_waiter == waiter) { |
289 | /* Deboost the owner */ | 394 | /* Deboost the owner */ |
290 | plist_del(&waiter->pi_list_entry, &task->pi_waiters); | 395 | rt_mutex_dequeue_pi(task, waiter); |
291 | waiter = rt_mutex_top_waiter(lock); | 396 | waiter = rt_mutex_top_waiter(lock); |
292 | waiter->pi_list_entry.prio = waiter->list_entry.prio; | 397 | rt_mutex_enqueue_pi(task, waiter); |
293 | plist_add(&waiter->pi_list_entry, &task->pi_waiters); | ||
294 | __rt_mutex_adjust_prio(task); | 398 | __rt_mutex_adjust_prio(task); |
295 | } | 399 | } |
296 | 400 | ||
@@ -355,7 +459,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task, | |||
355 | * 3) it is top waiter | 459 | * 3) it is top waiter |
356 | */ | 460 | */ |
357 | if (rt_mutex_has_waiters(lock)) { | 461 | if (rt_mutex_has_waiters(lock)) { |
358 | if (task->prio >= rt_mutex_top_waiter(lock)->list_entry.prio) { | 462 | if (task->prio >= rt_mutex_top_waiter(lock)->prio) { |
359 | if (!waiter || waiter != rt_mutex_top_waiter(lock)) | 463 | if (!waiter || waiter != rt_mutex_top_waiter(lock)) |
360 | return 0; | 464 | return 0; |
361 | } | 465 | } |
@@ -369,7 +473,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task, | |||
369 | 473 | ||
370 | /* remove the queued waiter. */ | 474 | /* remove the queued waiter. */ |
371 | if (waiter) { | 475 | if (waiter) { |
372 | plist_del(&waiter->list_entry, &lock->wait_list); | 476 | rt_mutex_dequeue(lock, waiter); |
373 | task->pi_blocked_on = NULL; | 477 | task->pi_blocked_on = NULL; |
374 | } | 478 | } |
375 | 479 | ||
@@ -379,8 +483,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task, | |||
379 | */ | 483 | */ |
380 | if (rt_mutex_has_waiters(lock)) { | 484 | if (rt_mutex_has_waiters(lock)) { |
381 | top = rt_mutex_top_waiter(lock); | 485 | top = rt_mutex_top_waiter(lock); |
382 | top->pi_list_entry.prio = top->list_entry.prio; | 486 | rt_mutex_enqueue_pi(task, top); |
383 | plist_add(&top->pi_list_entry, &task->pi_waiters); | ||
384 | } | 487 | } |
385 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | 488 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
386 | } | 489 | } |
@@ -416,13 +519,12 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, | |||
416 | __rt_mutex_adjust_prio(task); | 519 | __rt_mutex_adjust_prio(task); |
417 | waiter->task = task; | 520 | waiter->task = task; |
418 | waiter->lock = lock; | 521 | waiter->lock = lock; |
419 | plist_node_init(&waiter->list_entry, task->prio); | 522 | waiter->prio = task->prio; |
420 | plist_node_init(&waiter->pi_list_entry, task->prio); | ||
421 | 523 | ||
422 | /* Get the top priority waiter on the lock */ | 524 | /* Get the top priority waiter on the lock */ |
423 | if (rt_mutex_has_waiters(lock)) | 525 | if (rt_mutex_has_waiters(lock)) |
424 | top_waiter = rt_mutex_top_waiter(lock); | 526 | top_waiter = rt_mutex_top_waiter(lock); |
425 | plist_add(&waiter->list_entry, &lock->wait_list); | 527 | rt_mutex_enqueue(lock, waiter); |
426 | 528 | ||
427 | task->pi_blocked_on = waiter; | 529 | task->pi_blocked_on = waiter; |
428 | 530 | ||
@@ -433,8 +535,8 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, | |||
433 | 535 | ||
434 | if (waiter == rt_mutex_top_waiter(lock)) { | 536 | if (waiter == rt_mutex_top_waiter(lock)) { |
435 | raw_spin_lock_irqsave(&owner->pi_lock, flags); | 537 | raw_spin_lock_irqsave(&owner->pi_lock, flags); |
436 | plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters); | 538 | rt_mutex_dequeue_pi(owner, top_waiter); |
437 | plist_add(&waiter->pi_list_entry, &owner->pi_waiters); | 539 | rt_mutex_enqueue_pi(owner, waiter); |
438 | 540 | ||
439 | __rt_mutex_adjust_prio(owner); | 541 | __rt_mutex_adjust_prio(owner); |
440 | if (owner->pi_blocked_on) | 542 | if (owner->pi_blocked_on) |
@@ -486,7 +588,7 @@ static void wakeup_next_waiter(struct rt_mutex *lock) | |||
486 | * boosted mode and go back to normal after releasing | 588 | * boosted mode and go back to normal after releasing |
487 | * lock->wait_lock. | 589 | * lock->wait_lock. |
488 | */ | 590 | */ |
489 | plist_del(&waiter->pi_list_entry, ¤t->pi_waiters); | 591 | rt_mutex_dequeue_pi(current, waiter); |
490 | 592 | ||
491 | rt_mutex_set_owner(lock, NULL); | 593 | rt_mutex_set_owner(lock, NULL); |
492 | 594 | ||
@@ -510,7 +612,7 @@ static void remove_waiter(struct rt_mutex *lock, | |||
510 | int chain_walk = 0; | 612 | int chain_walk = 0; |
511 | 613 | ||
512 | raw_spin_lock_irqsave(¤t->pi_lock, flags); | 614 | raw_spin_lock_irqsave(¤t->pi_lock, flags); |
513 | plist_del(&waiter->list_entry, &lock->wait_list); | 615 | rt_mutex_dequeue(lock, waiter); |
514 | current->pi_blocked_on = NULL; | 616 | current->pi_blocked_on = NULL; |
515 | raw_spin_unlock_irqrestore(¤t->pi_lock, flags); | 617 | raw_spin_unlock_irqrestore(¤t->pi_lock, flags); |
516 | 618 | ||
@@ -521,13 +623,13 @@ static void remove_waiter(struct rt_mutex *lock, | |||
521 | 623 | ||
522 | raw_spin_lock_irqsave(&owner->pi_lock, flags); | 624 | raw_spin_lock_irqsave(&owner->pi_lock, flags); |
523 | 625 | ||
524 | plist_del(&waiter->pi_list_entry, &owner->pi_waiters); | 626 | rt_mutex_dequeue_pi(owner, waiter); |
525 | 627 | ||
526 | if (rt_mutex_has_waiters(lock)) { | 628 | if (rt_mutex_has_waiters(lock)) { |
527 | struct rt_mutex_waiter *next; | 629 | struct rt_mutex_waiter *next; |
528 | 630 | ||
529 | next = rt_mutex_top_waiter(lock); | 631 | next = rt_mutex_top_waiter(lock); |
530 | plist_add(&next->pi_list_entry, &owner->pi_waiters); | 632 | rt_mutex_enqueue_pi(owner, next); |
531 | } | 633 | } |
532 | __rt_mutex_adjust_prio(owner); | 634 | __rt_mutex_adjust_prio(owner); |
533 | 635 | ||
@@ -537,8 +639,6 @@ static void remove_waiter(struct rt_mutex *lock, | |||
537 | raw_spin_unlock_irqrestore(&owner->pi_lock, flags); | 639 | raw_spin_unlock_irqrestore(&owner->pi_lock, flags); |
538 | } | 640 | } |
539 | 641 | ||
540 | WARN_ON(!plist_node_empty(&waiter->pi_list_entry)); | ||
541 | |||
542 | if (!chain_walk) | 642 | if (!chain_walk) |
543 | return; | 643 | return; |
544 | 644 | ||
@@ -565,7 +665,8 @@ void rt_mutex_adjust_pi(struct task_struct *task) | |||
565 | raw_spin_lock_irqsave(&task->pi_lock, flags); | 665 | raw_spin_lock_irqsave(&task->pi_lock, flags); |
566 | 666 | ||
567 | waiter = task->pi_blocked_on; | 667 | waiter = task->pi_blocked_on; |
568 | if (!waiter || waiter->list_entry.prio == task->prio) { | 668 | if (!waiter || (waiter->prio == task->prio && |
669 | !dl_prio(task->prio))) { | ||
569 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | 670 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
570 | return; | 671 | return; |
571 | } | 672 | } |
@@ -638,6 +739,8 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state, | |||
638 | int ret = 0; | 739 | int ret = 0; |
639 | 740 | ||
640 | debug_rt_mutex_init_waiter(&waiter); | 741 | debug_rt_mutex_init_waiter(&waiter); |
742 | RB_CLEAR_NODE(&waiter.pi_tree_entry); | ||
743 | RB_CLEAR_NODE(&waiter.tree_entry); | ||
641 | 744 | ||
642 | raw_spin_lock(&lock->wait_lock); | 745 | raw_spin_lock(&lock->wait_lock); |
643 | 746 | ||
@@ -904,7 +1007,8 @@ void __rt_mutex_init(struct rt_mutex *lock, const char *name) | |||
904 | { | 1007 | { |
905 | lock->owner = NULL; | 1008 | lock->owner = NULL; |
906 | raw_spin_lock_init(&lock->wait_lock); | 1009 | raw_spin_lock_init(&lock->wait_lock); |
907 | plist_head_init(&lock->wait_list); | 1010 | lock->waiters = RB_ROOT; |
1011 | lock->waiters_leftmost = NULL; | ||
908 | 1012 | ||
909 | debug_rt_mutex_init(lock, name); | 1013 | debug_rt_mutex_init(lock, name); |
910 | } | 1014 | } |
diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h index 53a66c85261b..7431a9c86f35 100644 --- a/kernel/locking/rtmutex_common.h +++ b/kernel/locking/rtmutex_common.h | |||
@@ -40,13 +40,13 @@ extern void schedule_rt_mutex_test(struct rt_mutex *lock); | |||
40 | * This is the control structure for tasks blocked on a rt_mutex, | 40 | * This is the control structure for tasks blocked on a rt_mutex, |
41 | * which is allocated on the kernel stack on of the blocked task. | 41 | * which is allocated on the kernel stack on of the blocked task. |
42 | * | 42 | * |
43 | * @list_entry: pi node to enqueue into the mutex waiters list | 43 | * @tree_entry: pi node to enqueue into the mutex waiters tree |
44 | * @pi_list_entry: pi node to enqueue into the mutex owner waiters list | 44 | * @pi_tree_entry: pi node to enqueue into the mutex owner waiters tree |
45 | * @task: task reference to the blocked task | 45 | * @task: task reference to the blocked task |
46 | */ | 46 | */ |
47 | struct rt_mutex_waiter { | 47 | struct rt_mutex_waiter { |
48 | struct plist_node list_entry; | 48 | struct rb_node tree_entry; |
49 | struct plist_node pi_list_entry; | 49 | struct rb_node pi_tree_entry; |
50 | struct task_struct *task; | 50 | struct task_struct *task; |
51 | struct rt_mutex *lock; | 51 | struct rt_mutex *lock; |
52 | #ifdef CONFIG_DEBUG_RT_MUTEXES | 52 | #ifdef CONFIG_DEBUG_RT_MUTEXES |
@@ -54,14 +54,15 @@ struct rt_mutex_waiter { | |||
54 | struct pid *deadlock_task_pid; | 54 | struct pid *deadlock_task_pid; |
55 | struct rt_mutex *deadlock_lock; | 55 | struct rt_mutex *deadlock_lock; |
56 | #endif | 56 | #endif |
57 | int prio; | ||
57 | }; | 58 | }; |
58 | 59 | ||
59 | /* | 60 | /* |
60 | * Various helpers to access the waiters-plist: | 61 | * Various helpers to access the waiters-tree: |
61 | */ | 62 | */ |
62 | static inline int rt_mutex_has_waiters(struct rt_mutex *lock) | 63 | static inline int rt_mutex_has_waiters(struct rt_mutex *lock) |
63 | { | 64 | { |
64 | return !plist_head_empty(&lock->wait_list); | 65 | return !RB_EMPTY_ROOT(&lock->waiters); |
65 | } | 66 | } |
66 | 67 | ||
67 | static inline struct rt_mutex_waiter * | 68 | static inline struct rt_mutex_waiter * |
@@ -69,8 +70,8 @@ rt_mutex_top_waiter(struct rt_mutex *lock) | |||
69 | { | 70 | { |
70 | struct rt_mutex_waiter *w; | 71 | struct rt_mutex_waiter *w; |
71 | 72 | ||
72 | w = plist_first_entry(&lock->wait_list, struct rt_mutex_waiter, | 73 | w = rb_entry(lock->waiters_leftmost, struct rt_mutex_waiter, |
73 | list_entry); | 74 | tree_entry); |
74 | BUG_ON(w->lock != lock); | 75 | BUG_ON(w->lock != lock); |
75 | 76 | ||
76 | return w; | 77 | return w; |
@@ -78,14 +79,14 @@ rt_mutex_top_waiter(struct rt_mutex *lock) | |||
78 | 79 | ||
79 | static inline int task_has_pi_waiters(struct task_struct *p) | 80 | static inline int task_has_pi_waiters(struct task_struct *p) |
80 | { | 81 | { |
81 | return !plist_head_empty(&p->pi_waiters); | 82 | return !RB_EMPTY_ROOT(&p->pi_waiters); |
82 | } | 83 | } |
83 | 84 | ||
84 | static inline struct rt_mutex_waiter * | 85 | static inline struct rt_mutex_waiter * |
85 | task_top_pi_waiter(struct task_struct *p) | 86 | task_top_pi_waiter(struct task_struct *p) |
86 | { | 87 | { |
87 | return plist_first_entry(&p->pi_waiters, struct rt_mutex_waiter, | 88 | return rb_entry(p->pi_waiters_leftmost, struct rt_mutex_waiter, |
88 | pi_list_entry); | 89 | pi_tree_entry); |
89 | } | 90 | } |
90 | 91 | ||
91 | /* | 92 | /* |
diff --git a/kernel/panic.c b/kernel/panic.c index c00b4ceb39e8..6d6300375090 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
@@ -33,7 +33,7 @@ static int pause_on_oops; | |||
33 | static int pause_on_oops_flag; | 33 | static int pause_on_oops_flag; |
34 | static DEFINE_SPINLOCK(pause_on_oops_lock); | 34 | static DEFINE_SPINLOCK(pause_on_oops_lock); |
35 | 35 | ||
36 | int panic_timeout; | 36 | int panic_timeout = CONFIG_PANIC_TIMEOUT; |
37 | EXPORT_SYMBOL_GPL(panic_timeout); | 37 | EXPORT_SYMBOL_GPL(panic_timeout); |
38 | 38 | ||
39 | ATOMIC_NOTIFIER_HEAD(panic_notifier_list); | 39 | ATOMIC_NOTIFIER_HEAD(panic_notifier_list); |
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index c7f31aa272f7..3b8946416a5f 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -233,7 +233,8 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times) | |||
233 | 233 | ||
234 | /* | 234 | /* |
235 | * Sample a process (thread group) clock for the given group_leader task. | 235 | * Sample a process (thread group) clock for the given group_leader task. |
236 | * Must be called with tasklist_lock held for reading. | 236 | * Must be called with task sighand lock held for safe while_each_thread() |
237 | * traversal. | ||
237 | */ | 238 | */ |
238 | static int cpu_clock_sample_group(const clockid_t which_clock, | 239 | static int cpu_clock_sample_group(const clockid_t which_clock, |
239 | struct task_struct *p, | 240 | struct task_struct *p, |
@@ -260,30 +261,53 @@ static int cpu_clock_sample_group(const clockid_t which_clock, | |||
260 | return 0; | 261 | return 0; |
261 | } | 262 | } |
262 | 263 | ||
264 | static int posix_cpu_clock_get_task(struct task_struct *tsk, | ||
265 | const clockid_t which_clock, | ||
266 | struct timespec *tp) | ||
267 | { | ||
268 | int err = -EINVAL; | ||
269 | unsigned long long rtn; | ||
270 | |||
271 | if (CPUCLOCK_PERTHREAD(which_clock)) { | ||
272 | if (same_thread_group(tsk, current)) | ||
273 | err = cpu_clock_sample(which_clock, tsk, &rtn); | ||
274 | } else { | ||
275 | unsigned long flags; | ||
276 | struct sighand_struct *sighand; | ||
277 | |||
278 | /* | ||
279 | * while_each_thread() is not yet entirely RCU safe, | ||
280 | * keep locking the group while sampling process | ||
281 | * clock for now. | ||
282 | */ | ||
283 | sighand = lock_task_sighand(tsk, &flags); | ||
284 | if (!sighand) | ||
285 | return err; | ||
286 | |||
287 | if (tsk == current || thread_group_leader(tsk)) | ||
288 | err = cpu_clock_sample_group(which_clock, tsk, &rtn); | ||
289 | |||
290 | unlock_task_sighand(tsk, &flags); | ||
291 | } | ||
292 | |||
293 | if (!err) | ||
294 | sample_to_timespec(which_clock, rtn, tp); | ||
295 | |||
296 | return err; | ||
297 | } | ||
298 | |||
263 | 299 | ||
264 | static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) | 300 | static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) |
265 | { | 301 | { |
266 | const pid_t pid = CPUCLOCK_PID(which_clock); | 302 | const pid_t pid = CPUCLOCK_PID(which_clock); |
267 | int error = -EINVAL; | 303 | int err = -EINVAL; |
268 | unsigned long long rtn; | ||
269 | 304 | ||
270 | if (pid == 0) { | 305 | if (pid == 0) { |
271 | /* | 306 | /* |
272 | * Special case constant value for our own clocks. | 307 | * Special case constant value for our own clocks. |
273 | * We don't have to do any lookup to find ourselves. | 308 | * We don't have to do any lookup to find ourselves. |
274 | */ | 309 | */ |
275 | if (CPUCLOCK_PERTHREAD(which_clock)) { | 310 | err = posix_cpu_clock_get_task(current, which_clock, tp); |
276 | /* | ||
277 | * Sampling just ourselves we can do with no locking. | ||
278 | */ | ||
279 | error = cpu_clock_sample(which_clock, | ||
280 | current, &rtn); | ||
281 | } else { | ||
282 | read_lock(&tasklist_lock); | ||
283 | error = cpu_clock_sample_group(which_clock, | ||
284 | current, &rtn); | ||
285 | read_unlock(&tasklist_lock); | ||
286 | } | ||
287 | } else { | 311 | } else { |
288 | /* | 312 | /* |
289 | * Find the given PID, and validate that the caller | 313 | * Find the given PID, and validate that the caller |
@@ -292,29 +316,12 @@ static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) | |||
292 | struct task_struct *p; | 316 | struct task_struct *p; |
293 | rcu_read_lock(); | 317 | rcu_read_lock(); |
294 | p = find_task_by_vpid(pid); | 318 | p = find_task_by_vpid(pid); |
295 | if (p) { | 319 | if (p) |
296 | if (CPUCLOCK_PERTHREAD(which_clock)) { | 320 | err = posix_cpu_clock_get_task(p, which_clock, tp); |
297 | if (same_thread_group(p, current)) { | ||
298 | error = cpu_clock_sample(which_clock, | ||
299 | p, &rtn); | ||
300 | } | ||
301 | } else { | ||
302 | read_lock(&tasklist_lock); | ||
303 | if (thread_group_leader(p) && p->sighand) { | ||
304 | error = | ||
305 | cpu_clock_sample_group(which_clock, | ||
306 | p, &rtn); | ||
307 | } | ||
308 | read_unlock(&tasklist_lock); | ||
309 | } | ||
310 | } | ||
311 | rcu_read_unlock(); | 321 | rcu_read_unlock(); |
312 | } | 322 | } |
313 | 323 | ||
314 | if (error) | 324 | return err; |
315 | return error; | ||
316 | sample_to_timespec(which_clock, rtn, tp); | ||
317 | return 0; | ||
318 | } | 325 | } |
319 | 326 | ||
320 | 327 | ||
@@ -371,36 +378,40 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer) | |||
371 | */ | 378 | */ |
372 | static int posix_cpu_timer_del(struct k_itimer *timer) | 379 | static int posix_cpu_timer_del(struct k_itimer *timer) |
373 | { | 380 | { |
374 | struct task_struct *p = timer->it.cpu.task; | ||
375 | int ret = 0; | 381 | int ret = 0; |
382 | unsigned long flags; | ||
383 | struct sighand_struct *sighand; | ||
384 | struct task_struct *p = timer->it.cpu.task; | ||
376 | 385 | ||
377 | if (likely(p != NULL)) { | 386 | WARN_ON_ONCE(p == NULL); |
378 | read_lock(&tasklist_lock); | ||
379 | if (unlikely(p->sighand == NULL)) { | ||
380 | /* | ||
381 | * We raced with the reaping of the task. | ||
382 | * The deletion should have cleared us off the list. | ||
383 | */ | ||
384 | BUG_ON(!list_empty(&timer->it.cpu.entry)); | ||
385 | } else { | ||
386 | spin_lock(&p->sighand->siglock); | ||
387 | if (timer->it.cpu.firing) | ||
388 | ret = TIMER_RETRY; | ||
389 | else | ||
390 | list_del(&timer->it.cpu.entry); | ||
391 | spin_unlock(&p->sighand->siglock); | ||
392 | } | ||
393 | read_unlock(&tasklist_lock); | ||
394 | 387 | ||
395 | if (!ret) | 388 | /* |
396 | put_task_struct(p); | 389 | * Protect against sighand release/switch in exit/exec and process/ |
390 | * thread timer list entry concurrent read/writes. | ||
391 | */ | ||
392 | sighand = lock_task_sighand(p, &flags); | ||
393 | if (unlikely(sighand == NULL)) { | ||
394 | /* | ||
395 | * We raced with the reaping of the task. | ||
396 | * The deletion should have cleared us off the list. | ||
397 | */ | ||
398 | WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry)); | ||
399 | } else { | ||
400 | if (timer->it.cpu.firing) | ||
401 | ret = TIMER_RETRY; | ||
402 | else | ||
403 | list_del(&timer->it.cpu.entry); | ||
404 | |||
405 | unlock_task_sighand(p, &flags); | ||
397 | } | 406 | } |
398 | 407 | ||
408 | if (!ret) | ||
409 | put_task_struct(p); | ||
410 | |||
399 | return ret; | 411 | return ret; |
400 | } | 412 | } |
401 | 413 | ||
402 | static void cleanup_timers_list(struct list_head *head, | 414 | static void cleanup_timers_list(struct list_head *head) |
403 | unsigned long long curr) | ||
404 | { | 415 | { |
405 | struct cpu_timer_list *timer, *next; | 416 | struct cpu_timer_list *timer, *next; |
406 | 417 | ||
@@ -414,16 +425,11 @@ static void cleanup_timers_list(struct list_head *head, | |||
414 | * time for later timer_gettime calls to return. | 425 | * time for later timer_gettime calls to return. |
415 | * This must be called with the siglock held. | 426 | * This must be called with the siglock held. |
416 | */ | 427 | */ |
417 | static void cleanup_timers(struct list_head *head, | 428 | static void cleanup_timers(struct list_head *head) |
418 | cputime_t utime, cputime_t stime, | ||
419 | unsigned long long sum_exec_runtime) | ||
420 | { | 429 | { |
421 | 430 | cleanup_timers_list(head); | |
422 | cputime_t ptime = utime + stime; | 431 | cleanup_timers_list(++head); |
423 | 432 | cleanup_timers_list(++head); | |
424 | cleanup_timers_list(head, cputime_to_expires(ptime)); | ||
425 | cleanup_timers_list(++head, cputime_to_expires(utime)); | ||
426 | cleanup_timers_list(++head, sum_exec_runtime); | ||
427 | } | 433 | } |
428 | 434 | ||
429 | /* | 435 | /* |
@@ -433,41 +439,14 @@ static void cleanup_timers(struct list_head *head, | |||
433 | */ | 439 | */ |
434 | void posix_cpu_timers_exit(struct task_struct *tsk) | 440 | void posix_cpu_timers_exit(struct task_struct *tsk) |
435 | { | 441 | { |
436 | cputime_t utime, stime; | ||
437 | |||
438 | add_device_randomness((const void*) &tsk->se.sum_exec_runtime, | 442 | add_device_randomness((const void*) &tsk->se.sum_exec_runtime, |
439 | sizeof(unsigned long long)); | 443 | sizeof(unsigned long long)); |
440 | task_cputime(tsk, &utime, &stime); | 444 | cleanup_timers(tsk->cpu_timers); |
441 | cleanup_timers(tsk->cpu_timers, | ||
442 | utime, stime, tsk->se.sum_exec_runtime); | ||
443 | 445 | ||
444 | } | 446 | } |
445 | void posix_cpu_timers_exit_group(struct task_struct *tsk) | 447 | void posix_cpu_timers_exit_group(struct task_struct *tsk) |
446 | { | 448 | { |
447 | struct signal_struct *const sig = tsk->signal; | 449 | cleanup_timers(tsk->signal->cpu_timers); |
448 | cputime_t utime, stime; | ||
449 | |||
450 | task_cputime(tsk, &utime, &stime); | ||
451 | cleanup_timers(tsk->signal->cpu_timers, | ||
452 | utime + sig->utime, stime + sig->stime, | ||
453 | tsk->se.sum_exec_runtime + sig->sum_sched_runtime); | ||
454 | } | ||
455 | |||
456 | static void clear_dead_task(struct k_itimer *itimer, unsigned long long now) | ||
457 | { | ||
458 | struct cpu_timer_list *timer = &itimer->it.cpu; | ||
459 | |||
460 | /* | ||
461 | * That's all for this thread or process. | ||
462 | * We leave our residual in expires to be reported. | ||
463 | */ | ||
464 | put_task_struct(timer->task); | ||
465 | timer->task = NULL; | ||
466 | if (timer->expires < now) { | ||
467 | timer->expires = 0; | ||
468 | } else { | ||
469 | timer->expires -= now; | ||
470 | } | ||
471 | } | 450 | } |
472 | 451 | ||
473 | static inline int expires_gt(cputime_t expires, cputime_t new_exp) | 452 | static inline int expires_gt(cputime_t expires, cputime_t new_exp) |
@@ -477,8 +456,7 @@ static inline int expires_gt(cputime_t expires, cputime_t new_exp) | |||
477 | 456 | ||
478 | /* | 457 | /* |
479 | * Insert the timer on the appropriate list before any timers that | 458 | * Insert the timer on the appropriate list before any timers that |
480 | * expire later. This must be called with the tasklist_lock held | 459 | * expire later. This must be called with the sighand lock held. |
481 | * for reading, interrupts disabled and p->sighand->siglock taken. | ||
482 | */ | 460 | */ |
483 | static void arm_timer(struct k_itimer *timer) | 461 | static void arm_timer(struct k_itimer *timer) |
484 | { | 462 | { |
@@ -569,7 +547,8 @@ static void cpu_timer_fire(struct k_itimer *timer) | |||
569 | 547 | ||
570 | /* | 548 | /* |
571 | * Sample a process (thread group) timer for the given group_leader task. | 549 | * Sample a process (thread group) timer for the given group_leader task. |
572 | * Must be called with tasklist_lock held for reading. | 550 | * Must be called with task sighand lock held for safe while_each_thread() |
551 | * traversal. | ||
573 | */ | 552 | */ |
574 | static int cpu_timer_sample_group(const clockid_t which_clock, | 553 | static int cpu_timer_sample_group(const clockid_t which_clock, |
575 | struct task_struct *p, | 554 | struct task_struct *p, |
@@ -608,7 +587,8 @@ static DECLARE_WORK(nohz_kick_work, nohz_kick_work_fn); | |||
608 | */ | 587 | */ |
609 | static void posix_cpu_timer_kick_nohz(void) | 588 | static void posix_cpu_timer_kick_nohz(void) |
610 | { | 589 | { |
611 | schedule_work(&nohz_kick_work); | 590 | if (context_tracking_is_enabled()) |
591 | schedule_work(&nohz_kick_work); | ||
612 | } | 592 | } |
613 | 593 | ||
614 | bool posix_cpu_timers_can_stop_tick(struct task_struct *tsk) | 594 | bool posix_cpu_timers_can_stop_tick(struct task_struct *tsk) |
@@ -631,43 +611,39 @@ static inline void posix_cpu_timer_kick_nohz(void) { } | |||
631 | * If we return TIMER_RETRY, it's necessary to release the timer's lock | 611 | * If we return TIMER_RETRY, it's necessary to release the timer's lock |
632 | * and try again. (This happens when the timer is in the middle of firing.) | 612 | * and try again. (This happens when the timer is in the middle of firing.) |
633 | */ | 613 | */ |
634 | static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | 614 | static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, |
635 | struct itimerspec *new, struct itimerspec *old) | 615 | struct itimerspec *new, struct itimerspec *old) |
636 | { | 616 | { |
617 | unsigned long flags; | ||
618 | struct sighand_struct *sighand; | ||
637 | struct task_struct *p = timer->it.cpu.task; | 619 | struct task_struct *p = timer->it.cpu.task; |
638 | unsigned long long old_expires, new_expires, old_incr, val; | 620 | unsigned long long old_expires, new_expires, old_incr, val; |
639 | int ret; | 621 | int ret; |
640 | 622 | ||
641 | if (unlikely(p == NULL)) { | 623 | WARN_ON_ONCE(p == NULL); |
642 | /* | ||
643 | * Timer refers to a dead task's clock. | ||
644 | */ | ||
645 | return -ESRCH; | ||
646 | } | ||
647 | 624 | ||
648 | new_expires = timespec_to_sample(timer->it_clock, &new->it_value); | 625 | new_expires = timespec_to_sample(timer->it_clock, &new->it_value); |
649 | 626 | ||
650 | read_lock(&tasklist_lock); | ||
651 | /* | 627 | /* |
652 | * We need the tasklist_lock to protect against reaping that | 628 | * Protect against sighand release/switch in exit/exec and p->cpu_timers |
653 | * clears p->sighand. If p has just been reaped, we can no | 629 | * and p->signal->cpu_timers read/write in arm_timer() |
630 | */ | ||
631 | sighand = lock_task_sighand(p, &flags); | ||
632 | /* | ||
633 | * If p has just been reaped, we can no | ||
654 | * longer get any information about it at all. | 634 | * longer get any information about it at all. |
655 | */ | 635 | */ |
656 | if (unlikely(p->sighand == NULL)) { | 636 | if (unlikely(sighand == NULL)) { |
657 | read_unlock(&tasklist_lock); | ||
658 | put_task_struct(p); | ||
659 | timer->it.cpu.task = NULL; | ||
660 | return -ESRCH; | 637 | return -ESRCH; |
661 | } | 638 | } |
662 | 639 | ||
663 | /* | 640 | /* |
664 | * Disarm any old timer after extracting its expiry time. | 641 | * Disarm any old timer after extracting its expiry time. |
665 | */ | 642 | */ |
666 | BUG_ON(!irqs_disabled()); | 643 | WARN_ON_ONCE(!irqs_disabled()); |
667 | 644 | ||
668 | ret = 0; | 645 | ret = 0; |
669 | old_incr = timer->it.cpu.incr; | 646 | old_incr = timer->it.cpu.incr; |
670 | spin_lock(&p->sighand->siglock); | ||
671 | old_expires = timer->it.cpu.expires; | 647 | old_expires = timer->it.cpu.expires; |
672 | if (unlikely(timer->it.cpu.firing)) { | 648 | if (unlikely(timer->it.cpu.firing)) { |
673 | timer->it.cpu.firing = -1; | 649 | timer->it.cpu.firing = -1; |
@@ -724,12 +700,11 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
724 | * disable this firing since we are already reporting | 700 | * disable this firing since we are already reporting |
725 | * it as an overrun (thanks to bump_cpu_timer above). | 701 | * it as an overrun (thanks to bump_cpu_timer above). |
726 | */ | 702 | */ |
727 | spin_unlock(&p->sighand->siglock); | 703 | unlock_task_sighand(p, &flags); |
728 | read_unlock(&tasklist_lock); | ||
729 | goto out; | 704 | goto out; |
730 | } | 705 | } |
731 | 706 | ||
732 | if (new_expires != 0 && !(flags & TIMER_ABSTIME)) { | 707 | if (new_expires != 0 && !(timer_flags & TIMER_ABSTIME)) { |
733 | new_expires += val; | 708 | new_expires += val; |
734 | } | 709 | } |
735 | 710 | ||
@@ -743,9 +718,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
743 | arm_timer(timer); | 718 | arm_timer(timer); |
744 | } | 719 | } |
745 | 720 | ||
746 | spin_unlock(&p->sighand->siglock); | 721 | unlock_task_sighand(p, &flags); |
747 | read_unlock(&tasklist_lock); | ||
748 | |||
749 | /* | 722 | /* |
750 | * Install the new reload setting, and | 723 | * Install the new reload setting, and |
751 | * set up the signal and overrun bookkeeping. | 724 | * set up the signal and overrun bookkeeping. |
@@ -787,7 +760,8 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
787 | { | 760 | { |
788 | unsigned long long now; | 761 | unsigned long long now; |
789 | struct task_struct *p = timer->it.cpu.task; | 762 | struct task_struct *p = timer->it.cpu.task; |
790 | int clear_dead; | 763 | |
764 | WARN_ON_ONCE(p == NULL); | ||
791 | 765 | ||
792 | /* | 766 | /* |
793 | * Easy part: convert the reload time. | 767 | * Easy part: convert the reload time. |
@@ -800,52 +774,34 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
800 | return; | 774 | return; |
801 | } | 775 | } |
802 | 776 | ||
803 | if (unlikely(p == NULL)) { | ||
804 | /* | ||
805 | * This task already died and the timer will never fire. | ||
806 | * In this case, expires is actually the dead value. | ||
807 | */ | ||
808 | dead: | ||
809 | sample_to_timespec(timer->it_clock, timer->it.cpu.expires, | ||
810 | &itp->it_value); | ||
811 | return; | ||
812 | } | ||
813 | |||
814 | /* | 777 | /* |
815 | * Sample the clock to take the difference with the expiry time. | 778 | * Sample the clock to take the difference with the expiry time. |
816 | */ | 779 | */ |
817 | if (CPUCLOCK_PERTHREAD(timer->it_clock)) { | 780 | if (CPUCLOCK_PERTHREAD(timer->it_clock)) { |
818 | cpu_clock_sample(timer->it_clock, p, &now); | 781 | cpu_clock_sample(timer->it_clock, p, &now); |
819 | clear_dead = p->exit_state; | ||
820 | } else { | 782 | } else { |
821 | read_lock(&tasklist_lock); | 783 | struct sighand_struct *sighand; |
822 | if (unlikely(p->sighand == NULL)) { | 784 | unsigned long flags; |
785 | |||
786 | /* | ||
787 | * Protect against sighand release/switch in exit/exec and | ||
788 | * also make timer sampling safe if it ends up calling | ||
789 | * thread_group_cputime(). | ||
790 | */ | ||
791 | sighand = lock_task_sighand(p, &flags); | ||
792 | if (unlikely(sighand == NULL)) { | ||
823 | /* | 793 | /* |
824 | * The process has been reaped. | 794 | * The process has been reaped. |
825 | * We can't even collect a sample any more. | 795 | * We can't even collect a sample any more. |
826 | * Call the timer disarmed, nothing else to do. | 796 | * Call the timer disarmed, nothing else to do. |
827 | */ | 797 | */ |
828 | put_task_struct(p); | ||
829 | timer->it.cpu.task = NULL; | ||
830 | timer->it.cpu.expires = 0; | 798 | timer->it.cpu.expires = 0; |
831 | read_unlock(&tasklist_lock); | 799 | sample_to_timespec(timer->it_clock, timer->it.cpu.expires, |
832 | goto dead; | 800 | &itp->it_value); |
833 | } else { | 801 | } else { |
834 | cpu_timer_sample_group(timer->it_clock, p, &now); | 802 | cpu_timer_sample_group(timer->it_clock, p, &now); |
835 | clear_dead = (unlikely(p->exit_state) && | 803 | unlock_task_sighand(p, &flags); |
836 | thread_group_empty(p)); | ||
837 | } | 804 | } |
838 | read_unlock(&tasklist_lock); | ||
839 | } | ||
840 | |||
841 | if (unlikely(clear_dead)) { | ||
842 | /* | ||
843 | * We've noticed that the thread is dead, but | ||
844 | * not yet reaped. Take this opportunity to | ||
845 | * drop our task ref. | ||
846 | */ | ||
847 | clear_dead_task(timer, now); | ||
848 | goto dead; | ||
849 | } | 805 | } |
850 | 806 | ||
851 | if (now < timer->it.cpu.expires) { | 807 | if (now < timer->it.cpu.expires) { |
@@ -1059,14 +1015,12 @@ static void check_process_timers(struct task_struct *tsk, | |||
1059 | */ | 1015 | */ |
1060 | void posix_cpu_timer_schedule(struct k_itimer *timer) | 1016 | void posix_cpu_timer_schedule(struct k_itimer *timer) |
1061 | { | 1017 | { |
1018 | struct sighand_struct *sighand; | ||
1019 | unsigned long flags; | ||
1062 | struct task_struct *p = timer->it.cpu.task; | 1020 | struct task_struct *p = timer->it.cpu.task; |
1063 | unsigned long long now; | 1021 | unsigned long long now; |
1064 | 1022 | ||
1065 | if (unlikely(p == NULL)) | 1023 | WARN_ON_ONCE(p == NULL); |
1066 | /* | ||
1067 | * The task was cleaned up already, no future firings. | ||
1068 | */ | ||
1069 | goto out; | ||
1070 | 1024 | ||
1071 | /* | 1025 | /* |
1072 | * Fetch the current sample and update the timer's expiry time. | 1026 | * Fetch the current sample and update the timer's expiry time. |
@@ -1074,49 +1028,45 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
1074 | if (CPUCLOCK_PERTHREAD(timer->it_clock)) { | 1028 | if (CPUCLOCK_PERTHREAD(timer->it_clock)) { |
1075 | cpu_clock_sample(timer->it_clock, p, &now); | 1029 | cpu_clock_sample(timer->it_clock, p, &now); |
1076 | bump_cpu_timer(timer, now); | 1030 | bump_cpu_timer(timer, now); |
1077 | if (unlikely(p->exit_state)) { | 1031 | if (unlikely(p->exit_state)) |
1078 | clear_dead_task(timer, now); | 1032 | goto out; |
1033 | |||
1034 | /* Protect timer list r/w in arm_timer() */ | ||
1035 | sighand = lock_task_sighand(p, &flags); | ||
1036 | if (!sighand) | ||
1079 | goto out; | 1037 | goto out; |
1080 | } | ||
1081 | read_lock(&tasklist_lock); /* arm_timer needs it. */ | ||
1082 | spin_lock(&p->sighand->siglock); | ||
1083 | } else { | 1038 | } else { |
1084 | read_lock(&tasklist_lock); | 1039 | /* |
1085 | if (unlikely(p->sighand == NULL)) { | 1040 | * Protect arm_timer() and timer sampling in case of call to |
1041 | * thread_group_cputime(). | ||
1042 | */ | ||
1043 | sighand = lock_task_sighand(p, &flags); | ||
1044 | if (unlikely(sighand == NULL)) { | ||
1086 | /* | 1045 | /* |
1087 | * The process has been reaped. | 1046 | * The process has been reaped. |
1088 | * We can't even collect a sample any more. | 1047 | * We can't even collect a sample any more. |
1089 | */ | 1048 | */ |
1090 | put_task_struct(p); | ||
1091 | timer->it.cpu.task = p = NULL; | ||
1092 | timer->it.cpu.expires = 0; | 1049 | timer->it.cpu.expires = 0; |
1093 | goto out_unlock; | 1050 | goto out; |
1094 | } else if (unlikely(p->exit_state) && thread_group_empty(p)) { | 1051 | } else if (unlikely(p->exit_state) && thread_group_empty(p)) { |
1095 | /* | 1052 | unlock_task_sighand(p, &flags); |
1096 | * We've noticed that the thread is dead, but | 1053 | /* Optimizations: if the process is dying, no need to rearm */ |
1097 | * not yet reaped. Take this opportunity to | 1054 | goto out; |
1098 | * drop our task ref. | ||
1099 | */ | ||
1100 | cpu_timer_sample_group(timer->it_clock, p, &now); | ||
1101 | clear_dead_task(timer, now); | ||
1102 | goto out_unlock; | ||
1103 | } | 1055 | } |
1104 | spin_lock(&p->sighand->siglock); | ||
1105 | cpu_timer_sample_group(timer->it_clock, p, &now); | 1056 | cpu_timer_sample_group(timer->it_clock, p, &now); |
1106 | bump_cpu_timer(timer, now); | 1057 | bump_cpu_timer(timer, now); |
1107 | /* Leave the tasklist_lock locked for the call below. */ | 1058 | /* Leave the sighand locked for the call below. */ |
1108 | } | 1059 | } |
1109 | 1060 | ||
1110 | /* | 1061 | /* |
1111 | * Now re-arm for the new expiry time. | 1062 | * Now re-arm for the new expiry time. |
1112 | */ | 1063 | */ |
1113 | BUG_ON(!irqs_disabled()); | 1064 | WARN_ON_ONCE(!irqs_disabled()); |
1114 | arm_timer(timer); | 1065 | arm_timer(timer); |
1115 | spin_unlock(&p->sighand->siglock); | 1066 | unlock_task_sighand(p, &flags); |
1116 | |||
1117 | out_unlock: | ||
1118 | read_unlock(&tasklist_lock); | ||
1119 | 1067 | ||
1068 | /* Kick full dynticks CPUs in case they need to tick on the new timer */ | ||
1069 | posix_cpu_timer_kick_nohz(); | ||
1120 | out: | 1070 | out: |
1121 | timer->it_overrun_last = timer->it_overrun; | 1071 | timer->it_overrun_last = timer->it_overrun; |
1122 | timer->it_overrun = -1; | 1072 | timer->it_overrun = -1; |
@@ -1200,7 +1150,7 @@ void run_posix_cpu_timers(struct task_struct *tsk) | |||
1200 | struct k_itimer *timer, *next; | 1150 | struct k_itimer *timer, *next; |
1201 | unsigned long flags; | 1151 | unsigned long flags; |
1202 | 1152 | ||
1203 | BUG_ON(!irqs_disabled()); | 1153 | WARN_ON_ONCE(!irqs_disabled()); |
1204 | 1154 | ||
1205 | /* | 1155 | /* |
1206 | * The fast path checks that there are no expired thread or thread | 1156 | * The fast path checks that there are no expired thread or thread |
@@ -1256,13 +1206,6 @@ void run_posix_cpu_timers(struct task_struct *tsk) | |||
1256 | cpu_timer_fire(timer); | 1206 | cpu_timer_fire(timer); |
1257 | spin_unlock(&timer->it_lock); | 1207 | spin_unlock(&timer->it_lock); |
1258 | } | 1208 | } |
1259 | |||
1260 | /* | ||
1261 | * In case some timers were rescheduled after the queue got emptied, | ||
1262 | * wake up full dynticks CPUs. | ||
1263 | */ | ||
1264 | if (tsk->signal->cputimer.running) | ||
1265 | posix_cpu_timer_kick_nohz(); | ||
1266 | } | 1209 | } |
1267 | 1210 | ||
1268 | /* | 1211 | /* |
@@ -1274,7 +1217,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, | |||
1274 | { | 1217 | { |
1275 | unsigned long long now; | 1218 | unsigned long long now; |
1276 | 1219 | ||
1277 | BUG_ON(clock_idx == CPUCLOCK_SCHED); | 1220 | WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED); |
1278 | cpu_timer_sample_group(clock_idx, tsk, &now); | 1221 | cpu_timer_sample_group(clock_idx, tsk, &now); |
1279 | 1222 | ||
1280 | if (oldval) { | 1223 | if (oldval) { |
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h index 7859a0a3951e..79c3877e9c5b 100644 --- a/kernel/rcu/rcu.h +++ b/kernel/rcu/rcu.h | |||
@@ -96,19 +96,22 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) | |||
96 | } | 96 | } |
97 | #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ | 97 | #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ |
98 | 98 | ||
99 | extern void kfree(const void *); | 99 | void kfree(const void *); |
100 | 100 | ||
101 | static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head) | 101 | static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head) |
102 | { | 102 | { |
103 | unsigned long offset = (unsigned long)head->func; | 103 | unsigned long offset = (unsigned long)head->func; |
104 | 104 | ||
105 | rcu_lock_acquire(&rcu_callback_map); | ||
105 | if (__is_kfree_rcu_offset(offset)) { | 106 | if (__is_kfree_rcu_offset(offset)) { |
106 | RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset)); | 107 | RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset)); |
107 | kfree((void *)head - offset); | 108 | kfree((void *)head - offset); |
109 | rcu_lock_release(&rcu_callback_map); | ||
108 | return 1; | 110 | return 1; |
109 | } else { | 111 | } else { |
110 | RCU_TRACE(trace_rcu_invoke_callback(rn, head)); | 112 | RCU_TRACE(trace_rcu_invoke_callback(rn, head)); |
111 | head->func(head); | 113 | head->func(head); |
114 | rcu_lock_release(&rcu_callback_map); | ||
112 | return 0; | 115 | return 0; |
113 | } | 116 | } |
114 | } | 117 | } |
diff --git a/kernel/rcu/srcu.c b/kernel/rcu/srcu.c index 01d5ccb8bfe3..3318d8284384 100644 --- a/kernel/rcu/srcu.c +++ b/kernel/rcu/srcu.c | |||
@@ -363,6 +363,29 @@ static void srcu_flip(struct srcu_struct *sp) | |||
363 | /* | 363 | /* |
364 | * Enqueue an SRCU callback on the specified srcu_struct structure, | 364 | * Enqueue an SRCU callback on the specified srcu_struct structure, |
365 | * initiating grace-period processing if it is not already running. | 365 | * initiating grace-period processing if it is not already running. |
366 | * | ||
367 | * Note that all CPUs must agree that the grace period extended beyond | ||
368 | * all pre-existing SRCU read-side critical section. On systems with | ||
369 | * more than one CPU, this means that when "func()" is invoked, each CPU | ||
370 | * is guaranteed to have executed a full memory barrier since the end of | ||
371 | * its last corresponding SRCU read-side critical section whose beginning | ||
372 | * preceded the call to call_rcu(). It also means that each CPU executing | ||
373 | * an SRCU read-side critical section that continues beyond the start of | ||
374 | * "func()" must have executed a memory barrier after the call_rcu() | ||
375 | * but before the beginning of that SRCU read-side critical section. | ||
376 | * Note that these guarantees include CPUs that are offline, idle, or | ||
377 | * executing in user mode, as well as CPUs that are executing in the kernel. | ||
378 | * | ||
379 | * Furthermore, if CPU A invoked call_rcu() and CPU B invoked the | ||
380 | * resulting SRCU callback function "func()", then both CPU A and CPU | ||
381 | * B are guaranteed to execute a full memory barrier during the time | ||
382 | * interval between the call to call_rcu() and the invocation of "func()". | ||
383 | * This guarantee applies even if CPU A and CPU B are the same CPU (but | ||
384 | * again only if the system has more than one CPU). | ||
385 | * | ||
386 | * Of course, these guarantees apply only for invocations of call_srcu(), | ||
387 | * srcu_read_lock(), and srcu_read_unlock() that are all passed the same | ||
388 | * srcu_struct structure. | ||
366 | */ | 389 | */ |
367 | void call_srcu(struct srcu_struct *sp, struct rcu_head *head, | 390 | void call_srcu(struct srcu_struct *sp, struct rcu_head *head, |
368 | void (*func)(struct rcu_head *head)) | 391 | void (*func)(struct rcu_head *head)) |
@@ -459,7 +482,30 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount) | |||
459 | * Note that it is illegal to call synchronize_srcu() from the corresponding | 482 | * Note that it is illegal to call synchronize_srcu() from the corresponding |
460 | * SRCU read-side critical section; doing so will result in deadlock. | 483 | * SRCU read-side critical section; doing so will result in deadlock. |
461 | * However, it is perfectly legal to call synchronize_srcu() on one | 484 | * However, it is perfectly legal to call synchronize_srcu() on one |
462 | * srcu_struct from some other srcu_struct's read-side critical section. | 485 | * srcu_struct from some other srcu_struct's read-side critical section, |
486 | * as long as the resulting graph of srcu_structs is acyclic. | ||
487 | * | ||
488 | * There are memory-ordering constraints implied by synchronize_srcu(). | ||
489 | * On systems with more than one CPU, when synchronize_srcu() returns, | ||
490 | * each CPU is guaranteed to have executed a full memory barrier since | ||
491 | * the end of its last corresponding SRCU-sched read-side critical section | ||
492 | * whose beginning preceded the call to synchronize_srcu(). In addition, | ||
493 | * each CPU having an SRCU read-side critical section that extends beyond | ||
494 | * the return from synchronize_srcu() is guaranteed to have executed a | ||
495 | * full memory barrier after the beginning of synchronize_srcu() and before | ||
496 | * the beginning of that SRCU read-side critical section. Note that these | ||
497 | * guarantees include CPUs that are offline, idle, or executing in user mode, | ||
498 | * as well as CPUs that are executing in the kernel. | ||
499 | * | ||
500 | * Furthermore, if CPU A invoked synchronize_srcu(), which returned | ||
501 | * to its caller on CPU B, then both CPU A and CPU B are guaranteed | ||
502 | * to have executed a full memory barrier during the execution of | ||
503 | * synchronize_srcu(). This guarantee applies even if CPU A and CPU B | ||
504 | * are the same CPU, but again only if the system has more than one CPU. | ||
505 | * | ||
506 | * Of course, these memory-ordering guarantees apply only when | ||
507 | * synchronize_srcu(), srcu_read_lock(), and srcu_read_unlock() are | ||
508 | * passed the same srcu_struct structure. | ||
463 | */ | 509 | */ |
464 | void synchronize_srcu(struct srcu_struct *sp) | 510 | void synchronize_srcu(struct srcu_struct *sp) |
465 | { | 511 | { |
@@ -476,12 +522,8 @@ EXPORT_SYMBOL_GPL(synchronize_srcu); | |||
476 | * Wait for an SRCU grace period to elapse, but be more aggressive about | 522 | * Wait for an SRCU grace period to elapse, but be more aggressive about |
477 | * spinning rather than blocking when waiting. | 523 | * spinning rather than blocking when waiting. |
478 | * | 524 | * |
479 | * Note that it is also illegal to call synchronize_srcu_expedited() | 525 | * Note that synchronize_srcu_expedited() has the same deadlock and |
480 | * from the corresponding SRCU read-side critical section; | 526 | * memory-ordering properties as does synchronize_srcu(). |
481 | * doing so will result in deadlock. However, it is perfectly legal | ||
482 | * to call synchronize_srcu_expedited() on one srcu_struct from some | ||
483 | * other srcu_struct's read-side critical section, as long as | ||
484 | * the resulting graph of srcu_structs is acyclic. | ||
485 | */ | 527 | */ |
486 | void synchronize_srcu_expedited(struct srcu_struct *sp) | 528 | void synchronize_srcu_expedited(struct srcu_struct *sp) |
487 | { | 529 | { |
@@ -491,6 +533,7 @@ EXPORT_SYMBOL_GPL(synchronize_srcu_expedited); | |||
491 | 533 | ||
492 | /** | 534 | /** |
493 | * srcu_barrier - Wait until all in-flight call_srcu() callbacks complete. | 535 | * srcu_barrier - Wait until all in-flight call_srcu() callbacks complete. |
536 | * @sp: srcu_struct on which to wait for in-flight callbacks. | ||
494 | */ | 537 | */ |
495 | void srcu_barrier(struct srcu_struct *sp) | 538 | void srcu_barrier(struct srcu_struct *sp) |
496 | { | 539 | { |
diff --git a/kernel/rcu/torture.c b/kernel/rcu/torture.c index 3929cd451511..732f8ae3086a 100644 --- a/kernel/rcu/torture.c +++ b/kernel/rcu/torture.c | |||
@@ -139,8 +139,6 @@ MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s"); | |||
139 | #define VERBOSE_PRINTK_ERRSTRING(s) \ | 139 | #define VERBOSE_PRINTK_ERRSTRING(s) \ |
140 | do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0) | 140 | do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0) |
141 | 141 | ||
142 | static char printk_buf[4096]; | ||
143 | |||
144 | static int nrealreaders; | 142 | static int nrealreaders; |
145 | static struct task_struct *writer_task; | 143 | static struct task_struct *writer_task; |
146 | static struct task_struct **fakewriter_tasks; | 144 | static struct task_struct **fakewriter_tasks; |
@@ -376,7 +374,7 @@ struct rcu_torture_ops { | |||
376 | void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); | 374 | void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); |
377 | void (*cb_barrier)(void); | 375 | void (*cb_barrier)(void); |
378 | void (*fqs)(void); | 376 | void (*fqs)(void); |
379 | int (*stats)(char *page); | 377 | void (*stats)(char *page); |
380 | int irq_capable; | 378 | int irq_capable; |
381 | int can_boost; | 379 | int can_boost; |
382 | const char *name; | 380 | const char *name; |
@@ -578,21 +576,19 @@ static void srcu_torture_barrier(void) | |||
578 | srcu_barrier(&srcu_ctl); | 576 | srcu_barrier(&srcu_ctl); |
579 | } | 577 | } |
580 | 578 | ||
581 | static int srcu_torture_stats(char *page) | 579 | static void srcu_torture_stats(char *page) |
582 | { | 580 | { |
583 | int cnt = 0; | ||
584 | int cpu; | 581 | int cpu; |
585 | int idx = srcu_ctl.completed & 0x1; | 582 | int idx = srcu_ctl.completed & 0x1; |
586 | 583 | ||
587 | cnt += sprintf(&page[cnt], "%s%s per-CPU(idx=%d):", | 584 | page += sprintf(page, "%s%s per-CPU(idx=%d):", |
588 | torture_type, TORTURE_FLAG, idx); | 585 | torture_type, TORTURE_FLAG, idx); |
589 | for_each_possible_cpu(cpu) { | 586 | for_each_possible_cpu(cpu) { |
590 | cnt += sprintf(&page[cnt], " %d(%lu,%lu)", cpu, | 587 | page += sprintf(page, " %d(%lu,%lu)", cpu, |
591 | per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx], | 588 | per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx], |
592 | per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]); | 589 | per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]); |
593 | } | 590 | } |
594 | cnt += sprintf(&page[cnt], "\n"); | 591 | sprintf(page, "\n"); |
595 | return cnt; | ||
596 | } | 592 | } |
597 | 593 | ||
598 | static void srcu_torture_synchronize_expedited(void) | 594 | static void srcu_torture_synchronize_expedited(void) |
@@ -1052,10 +1048,9 @@ rcu_torture_reader(void *arg) | |||
1052 | /* | 1048 | /* |
1053 | * Create an RCU-torture statistics message in the specified buffer. | 1049 | * Create an RCU-torture statistics message in the specified buffer. |
1054 | */ | 1050 | */ |
1055 | static int | 1051 | static void |
1056 | rcu_torture_printk(char *page) | 1052 | rcu_torture_printk(char *page) |
1057 | { | 1053 | { |
1058 | int cnt = 0; | ||
1059 | int cpu; | 1054 | int cpu; |
1060 | int i; | 1055 | int i; |
1061 | long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; | 1056 | long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; |
@@ -1071,8 +1066,8 @@ rcu_torture_printk(char *page) | |||
1071 | if (pipesummary[i] != 0) | 1066 | if (pipesummary[i] != 0) |
1072 | break; | 1067 | break; |
1073 | } | 1068 | } |
1074 | cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG); | 1069 | page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG); |
1075 | cnt += sprintf(&page[cnt], | 1070 | page += sprintf(page, |
1076 | "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ", | 1071 | "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ", |
1077 | rcu_torture_current, | 1072 | rcu_torture_current, |
1078 | rcu_torture_current_version, | 1073 | rcu_torture_current_version, |
@@ -1080,53 +1075,52 @@ rcu_torture_printk(char *page) | |||
1080 | atomic_read(&n_rcu_torture_alloc), | 1075 | atomic_read(&n_rcu_torture_alloc), |
1081 | atomic_read(&n_rcu_torture_alloc_fail), | 1076 | atomic_read(&n_rcu_torture_alloc_fail), |
1082 | atomic_read(&n_rcu_torture_free)); | 1077 | atomic_read(&n_rcu_torture_free)); |
1083 | cnt += sprintf(&page[cnt], "rtmbe: %d rtbke: %ld rtbre: %ld ", | 1078 | page += sprintf(page, "rtmbe: %d rtbke: %ld rtbre: %ld ", |
1084 | atomic_read(&n_rcu_torture_mberror), | 1079 | atomic_read(&n_rcu_torture_mberror), |
1085 | n_rcu_torture_boost_ktrerror, | 1080 | n_rcu_torture_boost_ktrerror, |
1086 | n_rcu_torture_boost_rterror); | 1081 | n_rcu_torture_boost_rterror); |
1087 | cnt += sprintf(&page[cnt], "rtbf: %ld rtb: %ld nt: %ld ", | 1082 | page += sprintf(page, "rtbf: %ld rtb: %ld nt: %ld ", |
1088 | n_rcu_torture_boost_failure, | 1083 | n_rcu_torture_boost_failure, |
1089 | n_rcu_torture_boosts, | 1084 | n_rcu_torture_boosts, |
1090 | n_rcu_torture_timers); | 1085 | n_rcu_torture_timers); |
1091 | cnt += sprintf(&page[cnt], | 1086 | page += sprintf(page, |
1092 | "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ", | 1087 | "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ", |
1093 | n_online_successes, n_online_attempts, | 1088 | n_online_successes, n_online_attempts, |
1094 | n_offline_successes, n_offline_attempts, | 1089 | n_offline_successes, n_offline_attempts, |
1095 | min_online, max_online, | 1090 | min_online, max_online, |
1096 | min_offline, max_offline, | 1091 | min_offline, max_offline, |
1097 | sum_online, sum_offline, HZ); | 1092 | sum_online, sum_offline, HZ); |
1098 | cnt += sprintf(&page[cnt], "barrier: %ld/%ld:%ld", | 1093 | page += sprintf(page, "barrier: %ld/%ld:%ld", |
1099 | n_barrier_successes, | 1094 | n_barrier_successes, |
1100 | n_barrier_attempts, | 1095 | n_barrier_attempts, |
1101 | n_rcu_torture_barrier_error); | 1096 | n_rcu_torture_barrier_error); |
1102 | cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); | 1097 | page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG); |
1103 | if (atomic_read(&n_rcu_torture_mberror) != 0 || | 1098 | if (atomic_read(&n_rcu_torture_mberror) != 0 || |
1104 | n_rcu_torture_barrier_error != 0 || | 1099 | n_rcu_torture_barrier_error != 0 || |
1105 | n_rcu_torture_boost_ktrerror != 0 || | 1100 | n_rcu_torture_boost_ktrerror != 0 || |
1106 | n_rcu_torture_boost_rterror != 0 || | 1101 | n_rcu_torture_boost_rterror != 0 || |
1107 | n_rcu_torture_boost_failure != 0 || | 1102 | n_rcu_torture_boost_failure != 0 || |
1108 | i > 1) { | 1103 | i > 1) { |
1109 | cnt += sprintf(&page[cnt], "!!! "); | 1104 | page += sprintf(page, "!!! "); |
1110 | atomic_inc(&n_rcu_torture_error); | 1105 | atomic_inc(&n_rcu_torture_error); |
1111 | WARN_ON_ONCE(1); | 1106 | WARN_ON_ONCE(1); |
1112 | } | 1107 | } |
1113 | cnt += sprintf(&page[cnt], "Reader Pipe: "); | 1108 | page += sprintf(page, "Reader Pipe: "); |
1114 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) | 1109 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) |
1115 | cnt += sprintf(&page[cnt], " %ld", pipesummary[i]); | 1110 | page += sprintf(page, " %ld", pipesummary[i]); |
1116 | cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); | 1111 | page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG); |
1117 | cnt += sprintf(&page[cnt], "Reader Batch: "); | 1112 | page += sprintf(page, "Reader Batch: "); |
1118 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) | 1113 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) |
1119 | cnt += sprintf(&page[cnt], " %ld", batchsummary[i]); | 1114 | page += sprintf(page, " %ld", batchsummary[i]); |
1120 | cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); | 1115 | page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG); |
1121 | cnt += sprintf(&page[cnt], "Free-Block Circulation: "); | 1116 | page += sprintf(page, "Free-Block Circulation: "); |
1122 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { | 1117 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { |
1123 | cnt += sprintf(&page[cnt], " %d", | 1118 | page += sprintf(page, " %d", |
1124 | atomic_read(&rcu_torture_wcount[i])); | 1119 | atomic_read(&rcu_torture_wcount[i])); |
1125 | } | 1120 | } |
1126 | cnt += sprintf(&page[cnt], "\n"); | 1121 | page += sprintf(page, "\n"); |
1127 | if (cur_ops->stats) | 1122 | if (cur_ops->stats) |
1128 | cnt += cur_ops->stats(&page[cnt]); | 1123 | cur_ops->stats(page); |
1129 | return cnt; | ||
1130 | } | 1124 | } |
1131 | 1125 | ||
1132 | /* | 1126 | /* |
@@ -1140,10 +1134,17 @@ rcu_torture_printk(char *page) | |||
1140 | static void | 1134 | static void |
1141 | rcu_torture_stats_print(void) | 1135 | rcu_torture_stats_print(void) |
1142 | { | 1136 | { |
1143 | int cnt; | 1137 | int size = nr_cpu_ids * 200 + 8192; |
1138 | char *buf; | ||
1144 | 1139 | ||
1145 | cnt = rcu_torture_printk(printk_buf); | 1140 | buf = kmalloc(size, GFP_KERNEL); |
1146 | pr_alert("%s", printk_buf); | 1141 | if (!buf) { |
1142 | pr_err("rcu-torture: Out of memory, need: %d", size); | ||
1143 | return; | ||
1144 | } | ||
1145 | rcu_torture_printk(buf); | ||
1146 | pr_alert("%s", buf); | ||
1147 | kfree(buf); | ||
1147 | } | 1148 | } |
1148 | 1149 | ||
1149 | /* | 1150 | /* |
@@ -1578,6 +1579,7 @@ static int rcu_torture_barrier_cbs(void *arg) | |||
1578 | { | 1579 | { |
1579 | long myid = (long)arg; | 1580 | long myid = (long)arg; |
1580 | bool lastphase = 0; | 1581 | bool lastphase = 0; |
1582 | bool newphase; | ||
1581 | struct rcu_head rcu; | 1583 | struct rcu_head rcu; |
1582 | 1584 | ||
1583 | init_rcu_head_on_stack(&rcu); | 1585 | init_rcu_head_on_stack(&rcu); |
@@ -1585,10 +1587,11 @@ static int rcu_torture_barrier_cbs(void *arg) | |||
1585 | set_user_nice(current, 19); | 1587 | set_user_nice(current, 19); |
1586 | do { | 1588 | do { |
1587 | wait_event(barrier_cbs_wq[myid], | 1589 | wait_event(barrier_cbs_wq[myid], |
1588 | barrier_phase != lastphase || | 1590 | (newphase = |
1591 | ACCESS_ONCE(barrier_phase)) != lastphase || | ||
1589 | kthread_should_stop() || | 1592 | kthread_should_stop() || |
1590 | fullstop != FULLSTOP_DONTSTOP); | 1593 | fullstop != FULLSTOP_DONTSTOP); |
1591 | lastphase = barrier_phase; | 1594 | lastphase = newphase; |
1592 | smp_mb(); /* ensure barrier_phase load before ->call(). */ | 1595 | smp_mb(); /* ensure barrier_phase load before ->call(). */ |
1593 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) | 1596 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) |
1594 | break; | 1597 | break; |
@@ -1625,7 +1628,7 @@ static int rcu_torture_barrier(void *arg) | |||
1625 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) | 1628 | if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) |
1626 | break; | 1629 | break; |
1627 | n_barrier_attempts++; | 1630 | n_barrier_attempts++; |
1628 | cur_ops->cb_barrier(); | 1631 | cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */ |
1629 | if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) { | 1632 | if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) { |
1630 | n_rcu_torture_barrier_error++; | 1633 | n_rcu_torture_barrier_error++; |
1631 | WARN_ON_ONCE(1); | 1634 | WARN_ON_ONCE(1); |
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index dd081987a8ec..b3d116cd072d 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
@@ -369,6 +369,9 @@ static struct rcu_node *rcu_get_root(struct rcu_state *rsp) | |||
369 | static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, | 369 | static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, |
370 | bool user) | 370 | bool user) |
371 | { | 371 | { |
372 | struct rcu_state *rsp; | ||
373 | struct rcu_data *rdp; | ||
374 | |||
372 | trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting); | 375 | trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting); |
373 | if (!user && !is_idle_task(current)) { | 376 | if (!user && !is_idle_task(current)) { |
374 | struct task_struct *idle __maybe_unused = | 377 | struct task_struct *idle __maybe_unused = |
@@ -380,6 +383,10 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, | |||
380 | current->pid, current->comm, | 383 | current->pid, current->comm, |
381 | idle->pid, idle->comm); /* must be idle task! */ | 384 | idle->pid, idle->comm); /* must be idle task! */ |
382 | } | 385 | } |
386 | for_each_rcu_flavor(rsp) { | ||
387 | rdp = this_cpu_ptr(rsp->rda); | ||
388 | do_nocb_deferred_wakeup(rdp); | ||
389 | } | ||
383 | rcu_prepare_for_idle(smp_processor_id()); | 390 | rcu_prepare_for_idle(smp_processor_id()); |
384 | /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */ | 391 | /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */ |
385 | smp_mb__before_atomic_inc(); /* See above. */ | 392 | smp_mb__before_atomic_inc(); /* See above. */ |
@@ -411,11 +418,12 @@ static void rcu_eqs_enter(bool user) | |||
411 | rdtp = this_cpu_ptr(&rcu_dynticks); | 418 | rdtp = this_cpu_ptr(&rcu_dynticks); |
412 | oldval = rdtp->dynticks_nesting; | 419 | oldval = rdtp->dynticks_nesting; |
413 | WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0); | 420 | WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0); |
414 | if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) | 421 | if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) { |
415 | rdtp->dynticks_nesting = 0; | 422 | rdtp->dynticks_nesting = 0; |
416 | else | 423 | rcu_eqs_enter_common(rdtp, oldval, user); |
424 | } else { | ||
417 | rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; | 425 | rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; |
418 | rcu_eqs_enter_common(rdtp, oldval, user); | 426 | } |
419 | } | 427 | } |
420 | 428 | ||
421 | /** | 429 | /** |
@@ -533,11 +541,12 @@ static void rcu_eqs_exit(bool user) | |||
533 | rdtp = this_cpu_ptr(&rcu_dynticks); | 541 | rdtp = this_cpu_ptr(&rcu_dynticks); |
534 | oldval = rdtp->dynticks_nesting; | 542 | oldval = rdtp->dynticks_nesting; |
535 | WARN_ON_ONCE(oldval < 0); | 543 | WARN_ON_ONCE(oldval < 0); |
536 | if (oldval & DYNTICK_TASK_NEST_MASK) | 544 | if (oldval & DYNTICK_TASK_NEST_MASK) { |
537 | rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE; | 545 | rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE; |
538 | else | 546 | } else { |
539 | rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; | 547 | rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; |
540 | rcu_eqs_exit_common(rdtp, oldval, user); | 548 | rcu_eqs_exit_common(rdtp, oldval, user); |
549 | } | ||
541 | } | 550 | } |
542 | 551 | ||
543 | /** | 552 | /** |
@@ -716,7 +725,7 @@ bool rcu_lockdep_current_cpu_online(void) | |||
716 | bool ret; | 725 | bool ret; |
717 | 726 | ||
718 | if (in_nmi()) | 727 | if (in_nmi()) |
719 | return 1; | 728 | return true; |
720 | preempt_disable(); | 729 | preempt_disable(); |
721 | rdp = this_cpu_ptr(&rcu_sched_data); | 730 | rdp = this_cpu_ptr(&rcu_sched_data); |
722 | rnp = rdp->mynode; | 731 | rnp = rdp->mynode; |
@@ -755,6 +764,12 @@ static int dyntick_save_progress_counter(struct rcu_data *rdp, | |||
755 | } | 764 | } |
756 | 765 | ||
757 | /* | 766 | /* |
767 | * This function really isn't for public consumption, but RCU is special in | ||
768 | * that context switches can allow the state machine to make progress. | ||
769 | */ | ||
770 | extern void resched_cpu(int cpu); | ||
771 | |||
772 | /* | ||
758 | * Return true if the specified CPU has passed through a quiescent | 773 | * Return true if the specified CPU has passed through a quiescent |
759 | * state by virtue of being in or having passed through an dynticks | 774 | * state by virtue of being in or having passed through an dynticks |
760 | * idle state since the last call to dyntick_save_progress_counter() | 775 | * idle state since the last call to dyntick_save_progress_counter() |
@@ -812,16 +827,34 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp, | |||
812 | */ | 827 | */ |
813 | rcu_kick_nohz_cpu(rdp->cpu); | 828 | rcu_kick_nohz_cpu(rdp->cpu); |
814 | 829 | ||
830 | /* | ||
831 | * Alternatively, the CPU might be running in the kernel | ||
832 | * for an extended period of time without a quiescent state. | ||
833 | * Attempt to force the CPU through the scheduler to gain the | ||
834 | * needed quiescent state, but only if the grace period has gone | ||
835 | * on for an uncommonly long time. If there are many stuck CPUs, | ||
836 | * we will beat on the first one until it gets unstuck, then move | ||
837 | * to the next. Only do this for the primary flavor of RCU. | ||
838 | */ | ||
839 | if (rdp->rsp == rcu_state && | ||
840 | ULONG_CMP_GE(ACCESS_ONCE(jiffies), rdp->rsp->jiffies_resched)) { | ||
841 | rdp->rsp->jiffies_resched += 5; | ||
842 | resched_cpu(rdp->cpu); | ||
843 | } | ||
844 | |||
815 | return 0; | 845 | return 0; |
816 | } | 846 | } |
817 | 847 | ||
818 | static void record_gp_stall_check_time(struct rcu_state *rsp) | 848 | static void record_gp_stall_check_time(struct rcu_state *rsp) |
819 | { | 849 | { |
820 | unsigned long j = ACCESS_ONCE(jiffies); | 850 | unsigned long j = ACCESS_ONCE(jiffies); |
851 | unsigned long j1; | ||
821 | 852 | ||
822 | rsp->gp_start = j; | 853 | rsp->gp_start = j; |
823 | smp_wmb(); /* Record start time before stall time. */ | 854 | smp_wmb(); /* Record start time before stall time. */ |
824 | rsp->jiffies_stall = j + rcu_jiffies_till_stall_check(); | 855 | j1 = rcu_jiffies_till_stall_check(); |
856 | rsp->jiffies_stall = j + j1; | ||
857 | rsp->jiffies_resched = j + j1 / 2; | ||
825 | } | 858 | } |
826 | 859 | ||
827 | /* | 860 | /* |
@@ -1133,8 +1166,10 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp) | |||
1133 | * hold it, acquire the root rcu_node structure's lock in order to | 1166 | * hold it, acquire the root rcu_node structure's lock in order to |
1134 | * start one (if needed). | 1167 | * start one (if needed). |
1135 | */ | 1168 | */ |
1136 | if (rnp != rnp_root) | 1169 | if (rnp != rnp_root) { |
1137 | raw_spin_lock(&rnp_root->lock); | 1170 | raw_spin_lock(&rnp_root->lock); |
1171 | smp_mb__after_unlock_lock(); | ||
1172 | } | ||
1138 | 1173 | ||
1139 | /* | 1174 | /* |
1140 | * Get a new grace-period number. If there really is no grace | 1175 | * Get a new grace-period number. If there really is no grace |
@@ -1354,6 +1389,7 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp) | |||
1354 | local_irq_restore(flags); | 1389 | local_irq_restore(flags); |
1355 | return; | 1390 | return; |
1356 | } | 1391 | } |
1392 | smp_mb__after_unlock_lock(); | ||
1357 | __note_gp_changes(rsp, rnp, rdp); | 1393 | __note_gp_changes(rsp, rnp, rdp); |
1358 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 1394 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
1359 | } | 1395 | } |
@@ -1368,6 +1404,7 @@ static int rcu_gp_init(struct rcu_state *rsp) | |||
1368 | 1404 | ||
1369 | rcu_bind_gp_kthread(); | 1405 | rcu_bind_gp_kthread(); |
1370 | raw_spin_lock_irq(&rnp->lock); | 1406 | raw_spin_lock_irq(&rnp->lock); |
1407 | smp_mb__after_unlock_lock(); | ||
1371 | if (rsp->gp_flags == 0) { | 1408 | if (rsp->gp_flags == 0) { |
1372 | /* Spurious wakeup, tell caller to go back to sleep. */ | 1409 | /* Spurious wakeup, tell caller to go back to sleep. */ |
1373 | raw_spin_unlock_irq(&rnp->lock); | 1410 | raw_spin_unlock_irq(&rnp->lock); |
@@ -1409,6 +1446,7 @@ static int rcu_gp_init(struct rcu_state *rsp) | |||
1409 | */ | 1446 | */ |
1410 | rcu_for_each_node_breadth_first(rsp, rnp) { | 1447 | rcu_for_each_node_breadth_first(rsp, rnp) { |
1411 | raw_spin_lock_irq(&rnp->lock); | 1448 | raw_spin_lock_irq(&rnp->lock); |
1449 | smp_mb__after_unlock_lock(); | ||
1412 | rdp = this_cpu_ptr(rsp->rda); | 1450 | rdp = this_cpu_ptr(rsp->rda); |
1413 | rcu_preempt_check_blocked_tasks(rnp); | 1451 | rcu_preempt_check_blocked_tasks(rnp); |
1414 | rnp->qsmask = rnp->qsmaskinit; | 1452 | rnp->qsmask = rnp->qsmaskinit; |
@@ -1463,6 +1501,7 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in) | |||
1463 | /* Clear flag to prevent immediate re-entry. */ | 1501 | /* Clear flag to prevent immediate re-entry. */ |
1464 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { | 1502 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { |
1465 | raw_spin_lock_irq(&rnp->lock); | 1503 | raw_spin_lock_irq(&rnp->lock); |
1504 | smp_mb__after_unlock_lock(); | ||
1466 | rsp->gp_flags &= ~RCU_GP_FLAG_FQS; | 1505 | rsp->gp_flags &= ~RCU_GP_FLAG_FQS; |
1467 | raw_spin_unlock_irq(&rnp->lock); | 1506 | raw_spin_unlock_irq(&rnp->lock); |
1468 | } | 1507 | } |
@@ -1480,6 +1519,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
1480 | struct rcu_node *rnp = rcu_get_root(rsp); | 1519 | struct rcu_node *rnp = rcu_get_root(rsp); |
1481 | 1520 | ||
1482 | raw_spin_lock_irq(&rnp->lock); | 1521 | raw_spin_lock_irq(&rnp->lock); |
1522 | smp_mb__after_unlock_lock(); | ||
1483 | gp_duration = jiffies - rsp->gp_start; | 1523 | gp_duration = jiffies - rsp->gp_start; |
1484 | if (gp_duration > rsp->gp_max) | 1524 | if (gp_duration > rsp->gp_max) |
1485 | rsp->gp_max = gp_duration; | 1525 | rsp->gp_max = gp_duration; |
@@ -1505,16 +1545,19 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
1505 | */ | 1545 | */ |
1506 | rcu_for_each_node_breadth_first(rsp, rnp) { | 1546 | rcu_for_each_node_breadth_first(rsp, rnp) { |
1507 | raw_spin_lock_irq(&rnp->lock); | 1547 | raw_spin_lock_irq(&rnp->lock); |
1548 | smp_mb__after_unlock_lock(); | ||
1508 | ACCESS_ONCE(rnp->completed) = rsp->gpnum; | 1549 | ACCESS_ONCE(rnp->completed) = rsp->gpnum; |
1509 | rdp = this_cpu_ptr(rsp->rda); | 1550 | rdp = this_cpu_ptr(rsp->rda); |
1510 | if (rnp == rdp->mynode) | 1551 | if (rnp == rdp->mynode) |
1511 | __note_gp_changes(rsp, rnp, rdp); | 1552 | __note_gp_changes(rsp, rnp, rdp); |
1553 | /* smp_mb() provided by prior unlock-lock pair. */ | ||
1512 | nocb += rcu_future_gp_cleanup(rsp, rnp); | 1554 | nocb += rcu_future_gp_cleanup(rsp, rnp); |
1513 | raw_spin_unlock_irq(&rnp->lock); | 1555 | raw_spin_unlock_irq(&rnp->lock); |
1514 | cond_resched(); | 1556 | cond_resched(); |
1515 | } | 1557 | } |
1516 | rnp = rcu_get_root(rsp); | 1558 | rnp = rcu_get_root(rsp); |
1517 | raw_spin_lock_irq(&rnp->lock); | 1559 | raw_spin_lock_irq(&rnp->lock); |
1560 | smp_mb__after_unlock_lock(); | ||
1518 | rcu_nocb_gp_set(rnp, nocb); | 1561 | rcu_nocb_gp_set(rnp, nocb); |
1519 | 1562 | ||
1520 | rsp->completed = rsp->gpnum; /* Declare grace period done. */ | 1563 | rsp->completed = rsp->gpnum; /* Declare grace period done. */ |
@@ -1553,6 +1596,7 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1553 | wait_event_interruptible(rsp->gp_wq, | 1596 | wait_event_interruptible(rsp->gp_wq, |
1554 | ACCESS_ONCE(rsp->gp_flags) & | 1597 | ACCESS_ONCE(rsp->gp_flags) & |
1555 | RCU_GP_FLAG_INIT); | 1598 | RCU_GP_FLAG_INIT); |
1599 | /* Locking provides needed memory barrier. */ | ||
1556 | if (rcu_gp_init(rsp)) | 1600 | if (rcu_gp_init(rsp)) |
1557 | break; | 1601 | break; |
1558 | cond_resched(); | 1602 | cond_resched(); |
@@ -1582,6 +1626,7 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1582 | (!ACCESS_ONCE(rnp->qsmask) && | 1626 | (!ACCESS_ONCE(rnp->qsmask) && |
1583 | !rcu_preempt_blocked_readers_cgp(rnp)), | 1627 | !rcu_preempt_blocked_readers_cgp(rnp)), |
1584 | j); | 1628 | j); |
1629 | /* Locking provides needed memory barriers. */ | ||
1585 | /* If grace period done, leave loop. */ | 1630 | /* If grace period done, leave loop. */ |
1586 | if (!ACCESS_ONCE(rnp->qsmask) && | 1631 | if (!ACCESS_ONCE(rnp->qsmask) && |
1587 | !rcu_preempt_blocked_readers_cgp(rnp)) | 1632 | !rcu_preempt_blocked_readers_cgp(rnp)) |
@@ -1749,6 +1794,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp, | |||
1749 | rnp_c = rnp; | 1794 | rnp_c = rnp; |
1750 | rnp = rnp->parent; | 1795 | rnp = rnp->parent; |
1751 | raw_spin_lock_irqsave(&rnp->lock, flags); | 1796 | raw_spin_lock_irqsave(&rnp->lock, flags); |
1797 | smp_mb__after_unlock_lock(); | ||
1752 | WARN_ON_ONCE(rnp_c->qsmask); | 1798 | WARN_ON_ONCE(rnp_c->qsmask); |
1753 | } | 1799 | } |
1754 | 1800 | ||
@@ -1778,6 +1824,7 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp) | |||
1778 | 1824 | ||
1779 | rnp = rdp->mynode; | 1825 | rnp = rdp->mynode; |
1780 | raw_spin_lock_irqsave(&rnp->lock, flags); | 1826 | raw_spin_lock_irqsave(&rnp->lock, flags); |
1827 | smp_mb__after_unlock_lock(); | ||
1781 | if (rdp->passed_quiesce == 0 || rdp->gpnum != rnp->gpnum || | 1828 | if (rdp->passed_quiesce == 0 || rdp->gpnum != rnp->gpnum || |
1782 | rnp->completed == rnp->gpnum) { | 1829 | rnp->completed == rnp->gpnum) { |
1783 | 1830 | ||
@@ -1901,13 +1948,13 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp, | |||
1901 | * Adopt the RCU callbacks from the specified rcu_state structure's | 1948 | * Adopt the RCU callbacks from the specified rcu_state structure's |
1902 | * orphanage. The caller must hold the ->orphan_lock. | 1949 | * orphanage. The caller must hold the ->orphan_lock. |
1903 | */ | 1950 | */ |
1904 | static void rcu_adopt_orphan_cbs(struct rcu_state *rsp) | 1951 | static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags) |
1905 | { | 1952 | { |
1906 | int i; | 1953 | int i; |
1907 | struct rcu_data *rdp = __this_cpu_ptr(rsp->rda); | 1954 | struct rcu_data *rdp = __this_cpu_ptr(rsp->rda); |
1908 | 1955 | ||
1909 | /* No-CBs CPUs are handled specially. */ | 1956 | /* No-CBs CPUs are handled specially. */ |
1910 | if (rcu_nocb_adopt_orphan_cbs(rsp, rdp)) | 1957 | if (rcu_nocb_adopt_orphan_cbs(rsp, rdp, flags)) |
1911 | return; | 1958 | return; |
1912 | 1959 | ||
1913 | /* Do the accounting first. */ | 1960 | /* Do the accounting first. */ |
@@ -1986,12 +2033,13 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp) | |||
1986 | 2033 | ||
1987 | /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */ | 2034 | /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */ |
1988 | rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp); | 2035 | rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp); |
1989 | rcu_adopt_orphan_cbs(rsp); | 2036 | rcu_adopt_orphan_cbs(rsp, flags); |
1990 | 2037 | ||
1991 | /* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */ | 2038 | /* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */ |
1992 | mask = rdp->grpmask; /* rnp->grplo is constant. */ | 2039 | mask = rdp->grpmask; /* rnp->grplo is constant. */ |
1993 | do { | 2040 | do { |
1994 | raw_spin_lock(&rnp->lock); /* irqs already disabled. */ | 2041 | raw_spin_lock(&rnp->lock); /* irqs already disabled. */ |
2042 | smp_mb__after_unlock_lock(); | ||
1995 | rnp->qsmaskinit &= ~mask; | 2043 | rnp->qsmaskinit &= ~mask; |
1996 | if (rnp->qsmaskinit != 0) { | 2044 | if (rnp->qsmaskinit != 0) { |
1997 | if (rnp != rdp->mynode) | 2045 | if (rnp != rdp->mynode) |
@@ -2202,6 +2250,7 @@ static void force_qs_rnp(struct rcu_state *rsp, | |||
2202 | cond_resched(); | 2250 | cond_resched(); |
2203 | mask = 0; | 2251 | mask = 0; |
2204 | raw_spin_lock_irqsave(&rnp->lock, flags); | 2252 | raw_spin_lock_irqsave(&rnp->lock, flags); |
2253 | smp_mb__after_unlock_lock(); | ||
2205 | if (!rcu_gp_in_progress(rsp)) { | 2254 | if (!rcu_gp_in_progress(rsp)) { |
2206 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 2255 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
2207 | return; | 2256 | return; |
@@ -2231,6 +2280,7 @@ static void force_qs_rnp(struct rcu_state *rsp, | |||
2231 | rnp = rcu_get_root(rsp); | 2280 | rnp = rcu_get_root(rsp); |
2232 | if (rnp->qsmask == 0) { | 2281 | if (rnp->qsmask == 0) { |
2233 | raw_spin_lock_irqsave(&rnp->lock, flags); | 2282 | raw_spin_lock_irqsave(&rnp->lock, flags); |
2283 | smp_mb__after_unlock_lock(); | ||
2234 | rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */ | 2284 | rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */ |
2235 | } | 2285 | } |
2236 | } | 2286 | } |
@@ -2263,6 +2313,7 @@ static void force_quiescent_state(struct rcu_state *rsp) | |||
2263 | 2313 | ||
2264 | /* Reached the root of the rcu_node tree, acquire lock. */ | 2314 | /* Reached the root of the rcu_node tree, acquire lock. */ |
2265 | raw_spin_lock_irqsave(&rnp_old->lock, flags); | 2315 | raw_spin_lock_irqsave(&rnp_old->lock, flags); |
2316 | smp_mb__after_unlock_lock(); | ||
2266 | raw_spin_unlock(&rnp_old->fqslock); | 2317 | raw_spin_unlock(&rnp_old->fqslock); |
2267 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { | 2318 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { |
2268 | rsp->n_force_qs_lh++; | 2319 | rsp->n_force_qs_lh++; |
@@ -2303,6 +2354,9 @@ __rcu_process_callbacks(struct rcu_state *rsp) | |||
2303 | /* If there are callbacks ready, invoke them. */ | 2354 | /* If there are callbacks ready, invoke them. */ |
2304 | if (cpu_has_callbacks_ready_to_invoke(rdp)) | 2355 | if (cpu_has_callbacks_ready_to_invoke(rdp)) |
2305 | invoke_rcu_callbacks(rsp, rdp); | 2356 | invoke_rcu_callbacks(rsp, rdp); |
2357 | |||
2358 | /* Do any needed deferred wakeups of rcuo kthreads. */ | ||
2359 | do_nocb_deferred_wakeup(rdp); | ||
2306 | } | 2360 | } |
2307 | 2361 | ||
2308 | /* | 2362 | /* |
@@ -2378,6 +2432,7 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, | |||
2378 | struct rcu_node *rnp_root = rcu_get_root(rsp); | 2432 | struct rcu_node *rnp_root = rcu_get_root(rsp); |
2379 | 2433 | ||
2380 | raw_spin_lock(&rnp_root->lock); | 2434 | raw_spin_lock(&rnp_root->lock); |
2435 | smp_mb__after_unlock_lock(); | ||
2381 | rcu_start_gp(rsp); | 2436 | rcu_start_gp(rsp); |
2382 | raw_spin_unlock(&rnp_root->lock); | 2437 | raw_spin_unlock(&rnp_root->lock); |
2383 | } else { | 2438 | } else { |
@@ -2437,7 +2492,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), | |||
2437 | 2492 | ||
2438 | if (cpu != -1) | 2493 | if (cpu != -1) |
2439 | rdp = per_cpu_ptr(rsp->rda, cpu); | 2494 | rdp = per_cpu_ptr(rsp->rda, cpu); |
2440 | offline = !__call_rcu_nocb(rdp, head, lazy); | 2495 | offline = !__call_rcu_nocb(rdp, head, lazy, flags); |
2441 | WARN_ON_ONCE(offline); | 2496 | WARN_ON_ONCE(offline); |
2442 | /* _call_rcu() is illegal on offline CPU; leak the callback. */ | 2497 | /* _call_rcu() is illegal on offline CPU; leak the callback. */ |
2443 | local_irq_restore(flags); | 2498 | local_irq_restore(flags); |
@@ -2757,6 +2812,10 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) | |||
2757 | /* Check for CPU stalls, if enabled. */ | 2812 | /* Check for CPU stalls, if enabled. */ |
2758 | check_cpu_stall(rsp, rdp); | 2813 | check_cpu_stall(rsp, rdp); |
2759 | 2814 | ||
2815 | /* Is this CPU a NO_HZ_FULL CPU that should ignore RCU? */ | ||
2816 | if (rcu_nohz_full_cpu(rsp)) | ||
2817 | return 0; | ||
2818 | |||
2760 | /* Is the RCU core waiting for a quiescent state from this CPU? */ | 2819 | /* Is the RCU core waiting for a quiescent state from this CPU? */ |
2761 | if (rcu_scheduler_fully_active && | 2820 | if (rcu_scheduler_fully_active && |
2762 | rdp->qs_pending && !rdp->passed_quiesce) { | 2821 | rdp->qs_pending && !rdp->passed_quiesce) { |
@@ -2790,6 +2849,12 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) | |||
2790 | return 1; | 2849 | return 1; |
2791 | } | 2850 | } |
2792 | 2851 | ||
2852 | /* Does this CPU need a deferred NOCB wakeup? */ | ||
2853 | if (rcu_nocb_need_deferred_wakeup(rdp)) { | ||
2854 | rdp->n_rp_nocb_defer_wakeup++; | ||
2855 | return 1; | ||
2856 | } | ||
2857 | |||
2793 | /* nothing to do */ | 2858 | /* nothing to do */ |
2794 | rdp->n_rp_need_nothing++; | 2859 | rdp->n_rp_need_nothing++; |
2795 | return 0; | 2860 | return 0; |
@@ -3214,9 +3279,9 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp) | |||
3214 | { | 3279 | { |
3215 | int i; | 3280 | int i; |
3216 | 3281 | ||
3217 | for (i = rcu_num_lvls - 1; i > 0; i--) | 3282 | rsp->levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf; |
3283 | for (i = rcu_num_lvls - 2; i >= 0; i--) | ||
3218 | rsp->levelspread[i] = CONFIG_RCU_FANOUT; | 3284 | rsp->levelspread[i] = CONFIG_RCU_FANOUT; |
3219 | rsp->levelspread[0] = rcu_fanout_leaf; | ||
3220 | } | 3285 | } |
3221 | #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */ | 3286 | #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */ |
3222 | static void __init rcu_init_levelspread(struct rcu_state *rsp) | 3287 | static void __init rcu_init_levelspread(struct rcu_state *rsp) |
@@ -3346,6 +3411,8 @@ static void __init rcu_init_geometry(void) | |||
3346 | if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF && | 3411 | if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF && |
3347 | nr_cpu_ids == NR_CPUS) | 3412 | nr_cpu_ids == NR_CPUS) |
3348 | return; | 3413 | return; |
3414 | pr_info("RCU: Adjusting geometry for rcu_fanout_leaf=%d, nr_cpu_ids=%d\n", | ||
3415 | rcu_fanout_leaf, nr_cpu_ids); | ||
3349 | 3416 | ||
3350 | /* | 3417 | /* |
3351 | * Compute number of nodes that can be handled an rcu_node tree | 3418 | * Compute number of nodes that can be handled an rcu_node tree |
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index 52be957c9fe2..8c19873f1ac9 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h | |||
@@ -317,6 +317,7 @@ struct rcu_data { | |||
317 | unsigned long n_rp_cpu_needs_gp; | 317 | unsigned long n_rp_cpu_needs_gp; |
318 | unsigned long n_rp_gp_completed; | 318 | unsigned long n_rp_gp_completed; |
319 | unsigned long n_rp_gp_started; | 319 | unsigned long n_rp_gp_started; |
320 | unsigned long n_rp_nocb_defer_wakeup; | ||
320 | unsigned long n_rp_need_nothing; | 321 | unsigned long n_rp_need_nothing; |
321 | 322 | ||
322 | /* 6) _rcu_barrier() and OOM callbacks. */ | 323 | /* 6) _rcu_barrier() and OOM callbacks. */ |
@@ -335,6 +336,7 @@ struct rcu_data { | |||
335 | int nocb_p_count_lazy; /* (approximate). */ | 336 | int nocb_p_count_lazy; /* (approximate). */ |
336 | wait_queue_head_t nocb_wq; /* For nocb kthreads to sleep on. */ | 337 | wait_queue_head_t nocb_wq; /* For nocb kthreads to sleep on. */ |
337 | struct task_struct *nocb_kthread; | 338 | struct task_struct *nocb_kthread; |
339 | bool nocb_defer_wakeup; /* Defer wakeup of nocb_kthread. */ | ||
338 | #endif /* #ifdef CONFIG_RCU_NOCB_CPU */ | 340 | #endif /* #ifdef CONFIG_RCU_NOCB_CPU */ |
339 | 341 | ||
340 | /* 8) RCU CPU stall data. */ | 342 | /* 8) RCU CPU stall data. */ |
@@ -453,6 +455,8 @@ struct rcu_state { | |||
453 | /* but in jiffies. */ | 455 | /* but in jiffies. */ |
454 | unsigned long jiffies_stall; /* Time at which to check */ | 456 | unsigned long jiffies_stall; /* Time at which to check */ |
455 | /* for CPU stalls. */ | 457 | /* for CPU stalls. */ |
458 | unsigned long jiffies_resched; /* Time at which to resched */ | ||
459 | /* a reluctant CPU. */ | ||
456 | unsigned long gp_max; /* Maximum GP duration in */ | 460 | unsigned long gp_max; /* Maximum GP duration in */ |
457 | /* jiffies. */ | 461 | /* jiffies. */ |
458 | const char *name; /* Name of structure. */ | 462 | const char *name; /* Name of structure. */ |
@@ -548,9 +552,12 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq); | |||
548 | static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp); | 552 | static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp); |
549 | static void rcu_init_one_nocb(struct rcu_node *rnp); | 553 | static void rcu_init_one_nocb(struct rcu_node *rnp); |
550 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, | 554 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, |
551 | bool lazy); | 555 | bool lazy, unsigned long flags); |
552 | static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, | 556 | static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, |
553 | struct rcu_data *rdp); | 557 | struct rcu_data *rdp, |
558 | unsigned long flags); | ||
559 | static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp); | ||
560 | static void do_nocb_deferred_wakeup(struct rcu_data *rdp); | ||
554 | static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp); | 561 | static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp); |
555 | static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp); | 562 | static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp); |
556 | static void rcu_kick_nohz_cpu(int cpu); | 563 | static void rcu_kick_nohz_cpu(int cpu); |
@@ -564,6 +571,7 @@ static void rcu_sysidle_report_gp(struct rcu_state *rsp, int isidle, | |||
564 | unsigned long maxj); | 571 | unsigned long maxj); |
565 | static void rcu_bind_gp_kthread(void); | 572 | static void rcu_bind_gp_kthread(void); |
566 | static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp); | 573 | static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp); |
574 | static bool rcu_nohz_full_cpu(struct rcu_state *rsp); | ||
567 | 575 | ||
568 | #endif /* #ifndef RCU_TREE_NONCORE */ | 576 | #endif /* #ifndef RCU_TREE_NONCORE */ |
569 | 577 | ||
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 08a765232432..6e2ef4b2b920 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h | |||
@@ -204,6 +204,7 @@ static void rcu_preempt_note_context_switch(int cpu) | |||
204 | rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu); | 204 | rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu); |
205 | rnp = rdp->mynode; | 205 | rnp = rdp->mynode; |
206 | raw_spin_lock_irqsave(&rnp->lock, flags); | 206 | raw_spin_lock_irqsave(&rnp->lock, flags); |
207 | smp_mb__after_unlock_lock(); | ||
207 | t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED; | 208 | t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED; |
208 | t->rcu_blocked_node = rnp; | 209 | t->rcu_blocked_node = rnp; |
209 | 210 | ||
@@ -312,6 +313,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) | |||
312 | mask = rnp->grpmask; | 313 | mask = rnp->grpmask; |
313 | raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ | 314 | raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ |
314 | raw_spin_lock(&rnp_p->lock); /* irqs already disabled. */ | 315 | raw_spin_lock(&rnp_p->lock); /* irqs already disabled. */ |
316 | smp_mb__after_unlock_lock(); | ||
315 | rcu_report_qs_rnp(mask, &rcu_preempt_state, rnp_p, flags); | 317 | rcu_report_qs_rnp(mask, &rcu_preempt_state, rnp_p, flags); |
316 | } | 318 | } |
317 | 319 | ||
@@ -361,10 +363,14 @@ void rcu_read_unlock_special(struct task_struct *t) | |||
361 | special = t->rcu_read_unlock_special; | 363 | special = t->rcu_read_unlock_special; |
362 | if (special & RCU_READ_UNLOCK_NEED_QS) { | 364 | if (special & RCU_READ_UNLOCK_NEED_QS) { |
363 | rcu_preempt_qs(smp_processor_id()); | 365 | rcu_preempt_qs(smp_processor_id()); |
366 | if (!t->rcu_read_unlock_special) { | ||
367 | local_irq_restore(flags); | ||
368 | return; | ||
369 | } | ||
364 | } | 370 | } |
365 | 371 | ||
366 | /* Hardware IRQ handlers cannot block. */ | 372 | /* Hardware IRQ handlers cannot block, complain if they get here. */ |
367 | if (in_irq() || in_serving_softirq()) { | 373 | if (WARN_ON_ONCE(in_irq() || in_serving_softirq())) { |
368 | local_irq_restore(flags); | 374 | local_irq_restore(flags); |
369 | return; | 375 | return; |
370 | } | 376 | } |
@@ -381,6 +387,7 @@ void rcu_read_unlock_special(struct task_struct *t) | |||
381 | for (;;) { | 387 | for (;;) { |
382 | rnp = t->rcu_blocked_node; | 388 | rnp = t->rcu_blocked_node; |
383 | raw_spin_lock(&rnp->lock); /* irqs already disabled. */ | 389 | raw_spin_lock(&rnp->lock); /* irqs already disabled. */ |
390 | smp_mb__after_unlock_lock(); | ||
384 | if (rnp == t->rcu_blocked_node) | 391 | if (rnp == t->rcu_blocked_node) |
385 | break; | 392 | break; |
386 | raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ | 393 | raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ |
@@ -605,6 +612,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp, | |||
605 | while (!list_empty(lp)) { | 612 | while (!list_empty(lp)) { |
606 | t = list_entry(lp->next, typeof(*t), rcu_node_entry); | 613 | t = list_entry(lp->next, typeof(*t), rcu_node_entry); |
607 | raw_spin_lock(&rnp_root->lock); /* irqs already disabled */ | 614 | raw_spin_lock(&rnp_root->lock); /* irqs already disabled */ |
615 | smp_mb__after_unlock_lock(); | ||
608 | list_del(&t->rcu_node_entry); | 616 | list_del(&t->rcu_node_entry); |
609 | t->rcu_blocked_node = rnp_root; | 617 | t->rcu_blocked_node = rnp_root; |
610 | list_add(&t->rcu_node_entry, lp_root); | 618 | list_add(&t->rcu_node_entry, lp_root); |
@@ -629,6 +637,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp, | |||
629 | * in this case. | 637 | * in this case. |
630 | */ | 638 | */ |
631 | raw_spin_lock(&rnp_root->lock); /* irqs already disabled */ | 639 | raw_spin_lock(&rnp_root->lock); /* irqs already disabled */ |
640 | smp_mb__after_unlock_lock(); | ||
632 | if (rnp_root->boost_tasks != NULL && | 641 | if (rnp_root->boost_tasks != NULL && |
633 | rnp_root->boost_tasks != rnp_root->gp_tasks && | 642 | rnp_root->boost_tasks != rnp_root->gp_tasks && |
634 | rnp_root->boost_tasks != rnp_root->exp_tasks) | 643 | rnp_root->boost_tasks != rnp_root->exp_tasks) |
@@ -772,6 +781,7 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, | |||
772 | unsigned long mask; | 781 | unsigned long mask; |
773 | 782 | ||
774 | raw_spin_lock_irqsave(&rnp->lock, flags); | 783 | raw_spin_lock_irqsave(&rnp->lock, flags); |
784 | smp_mb__after_unlock_lock(); | ||
775 | for (;;) { | 785 | for (;;) { |
776 | if (!sync_rcu_preempt_exp_done(rnp)) { | 786 | if (!sync_rcu_preempt_exp_done(rnp)) { |
777 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 787 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
@@ -779,14 +789,17 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, | |||
779 | } | 789 | } |
780 | if (rnp->parent == NULL) { | 790 | if (rnp->parent == NULL) { |
781 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 791 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
782 | if (wake) | 792 | if (wake) { |
793 | smp_mb(); /* EGP done before wake_up(). */ | ||
783 | wake_up(&sync_rcu_preempt_exp_wq); | 794 | wake_up(&sync_rcu_preempt_exp_wq); |
795 | } | ||
784 | break; | 796 | break; |
785 | } | 797 | } |
786 | mask = rnp->grpmask; | 798 | mask = rnp->grpmask; |
787 | raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ | 799 | raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ |
788 | rnp = rnp->parent; | 800 | rnp = rnp->parent; |
789 | raw_spin_lock(&rnp->lock); /* irqs already disabled */ | 801 | raw_spin_lock(&rnp->lock); /* irqs already disabled */ |
802 | smp_mb__after_unlock_lock(); | ||
790 | rnp->expmask &= ~mask; | 803 | rnp->expmask &= ~mask; |
791 | } | 804 | } |
792 | } | 805 | } |
@@ -806,6 +819,7 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp) | |||
806 | int must_wait = 0; | 819 | int must_wait = 0; |
807 | 820 | ||
808 | raw_spin_lock_irqsave(&rnp->lock, flags); | 821 | raw_spin_lock_irqsave(&rnp->lock, flags); |
822 | smp_mb__after_unlock_lock(); | ||
809 | if (list_empty(&rnp->blkd_tasks)) { | 823 | if (list_empty(&rnp->blkd_tasks)) { |
810 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 824 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
811 | } else { | 825 | } else { |
@@ -886,6 +900,7 @@ void synchronize_rcu_expedited(void) | |||
886 | /* Initialize ->expmask for all non-leaf rcu_node structures. */ | 900 | /* Initialize ->expmask for all non-leaf rcu_node structures. */ |
887 | rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) { | 901 | rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) { |
888 | raw_spin_lock_irqsave(&rnp->lock, flags); | 902 | raw_spin_lock_irqsave(&rnp->lock, flags); |
903 | smp_mb__after_unlock_lock(); | ||
889 | rnp->expmask = rnp->qsmaskinit; | 904 | rnp->expmask = rnp->qsmaskinit; |
890 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 905 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
891 | } | 906 | } |
@@ -1191,6 +1206,7 @@ static int rcu_boost(struct rcu_node *rnp) | |||
1191 | return 0; /* Nothing left to boost. */ | 1206 | return 0; /* Nothing left to boost. */ |
1192 | 1207 | ||
1193 | raw_spin_lock_irqsave(&rnp->lock, flags); | 1208 | raw_spin_lock_irqsave(&rnp->lock, flags); |
1209 | smp_mb__after_unlock_lock(); | ||
1194 | 1210 | ||
1195 | /* | 1211 | /* |
1196 | * Recheck under the lock: all tasks in need of boosting | 1212 | * Recheck under the lock: all tasks in need of boosting |
@@ -1377,6 +1393,7 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp, | |||
1377 | if (IS_ERR(t)) | 1393 | if (IS_ERR(t)) |
1378 | return PTR_ERR(t); | 1394 | return PTR_ERR(t); |
1379 | raw_spin_lock_irqsave(&rnp->lock, flags); | 1395 | raw_spin_lock_irqsave(&rnp->lock, flags); |
1396 | smp_mb__after_unlock_lock(); | ||
1380 | rnp->boost_kthread_task = t; | 1397 | rnp->boost_kthread_task = t; |
1381 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 1398 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
1382 | sp.sched_priority = RCU_BOOST_PRIO; | 1399 | sp.sched_priority = RCU_BOOST_PRIO; |
@@ -1769,6 +1786,7 @@ static void rcu_prepare_for_idle(int cpu) | |||
1769 | continue; | 1786 | continue; |
1770 | rnp = rdp->mynode; | 1787 | rnp = rdp->mynode; |
1771 | raw_spin_lock(&rnp->lock); /* irqs already disabled. */ | 1788 | raw_spin_lock(&rnp->lock); /* irqs already disabled. */ |
1789 | smp_mb__after_unlock_lock(); | ||
1772 | rcu_accelerate_cbs(rsp, rnp, rdp); | 1790 | rcu_accelerate_cbs(rsp, rnp, rdp); |
1773 | raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ | 1791 | raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ |
1774 | } | 1792 | } |
@@ -1852,6 +1870,7 @@ static int rcu_oom_notify(struct notifier_block *self, | |||
1852 | 1870 | ||
1853 | /* Wait for callbacks from earlier instance to complete. */ | 1871 | /* Wait for callbacks from earlier instance to complete. */ |
1854 | wait_event(oom_callback_wq, atomic_read(&oom_callback_count) == 0); | 1872 | wait_event(oom_callback_wq, atomic_read(&oom_callback_count) == 0); |
1873 | smp_mb(); /* Ensure callback reuse happens after callback invocation. */ | ||
1855 | 1874 | ||
1856 | /* | 1875 | /* |
1857 | * Prevent premature wakeup: ensure that all increments happen | 1876 | * Prevent premature wakeup: ensure that all increments happen |
@@ -2101,7 +2120,8 @@ bool rcu_is_nocb_cpu(int cpu) | |||
2101 | static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | 2120 | static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, |
2102 | struct rcu_head *rhp, | 2121 | struct rcu_head *rhp, |
2103 | struct rcu_head **rhtp, | 2122 | struct rcu_head **rhtp, |
2104 | int rhcount, int rhcount_lazy) | 2123 | int rhcount, int rhcount_lazy, |
2124 | unsigned long flags) | ||
2105 | { | 2125 | { |
2106 | int len; | 2126 | int len; |
2107 | struct rcu_head **old_rhpp; | 2127 | struct rcu_head **old_rhpp; |
@@ -2122,9 +2142,16 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | |||
2122 | } | 2142 | } |
2123 | len = atomic_long_read(&rdp->nocb_q_count); | 2143 | len = atomic_long_read(&rdp->nocb_q_count); |
2124 | if (old_rhpp == &rdp->nocb_head) { | 2144 | if (old_rhpp == &rdp->nocb_head) { |
2125 | wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */ | 2145 | if (!irqs_disabled_flags(flags)) { |
2146 | wake_up(&rdp->nocb_wq); /* ... if queue was empty ... */ | ||
2147 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2148 | TPS("WakeEmpty")); | ||
2149 | } else { | ||
2150 | rdp->nocb_defer_wakeup = true; | ||
2151 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2152 | TPS("WakeEmptyIsDeferred")); | ||
2153 | } | ||
2126 | rdp->qlen_last_fqs_check = 0; | 2154 | rdp->qlen_last_fqs_check = 0; |
2127 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeEmpty")); | ||
2128 | } else if (len > rdp->qlen_last_fqs_check + qhimark) { | 2155 | } else if (len > rdp->qlen_last_fqs_check + qhimark) { |
2129 | wake_up_process(t); /* ... or if many callbacks queued. */ | 2156 | wake_up_process(t); /* ... or if many callbacks queued. */ |
2130 | rdp->qlen_last_fqs_check = LONG_MAX / 2; | 2157 | rdp->qlen_last_fqs_check = LONG_MAX / 2; |
@@ -2145,12 +2172,12 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | |||
2145 | * "rcuo" kthread can find it. | 2172 | * "rcuo" kthread can find it. |
2146 | */ | 2173 | */ |
2147 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, | 2174 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, |
2148 | bool lazy) | 2175 | bool lazy, unsigned long flags) |
2149 | { | 2176 | { |
2150 | 2177 | ||
2151 | if (!rcu_is_nocb_cpu(rdp->cpu)) | 2178 | if (!rcu_is_nocb_cpu(rdp->cpu)) |
2152 | return 0; | 2179 | return 0; |
2153 | __call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy); | 2180 | __call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy, flags); |
2154 | if (__is_kfree_rcu_offset((unsigned long)rhp->func)) | 2181 | if (__is_kfree_rcu_offset((unsigned long)rhp->func)) |
2155 | trace_rcu_kfree_callback(rdp->rsp->name, rhp, | 2182 | trace_rcu_kfree_callback(rdp->rsp->name, rhp, |
2156 | (unsigned long)rhp->func, | 2183 | (unsigned long)rhp->func, |
@@ -2168,7 +2195,8 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, | |||
2168 | * not a no-CBs CPU. | 2195 | * not a no-CBs CPU. |
2169 | */ | 2196 | */ |
2170 | static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, | 2197 | static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, |
2171 | struct rcu_data *rdp) | 2198 | struct rcu_data *rdp, |
2199 | unsigned long flags) | ||
2172 | { | 2200 | { |
2173 | long ql = rsp->qlen; | 2201 | long ql = rsp->qlen; |
2174 | long qll = rsp->qlen_lazy; | 2202 | long qll = rsp->qlen_lazy; |
@@ -2182,14 +2210,14 @@ static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, | |||
2182 | /* First, enqueue the donelist, if any. This preserves CB ordering. */ | 2210 | /* First, enqueue the donelist, if any. This preserves CB ordering. */ |
2183 | if (rsp->orphan_donelist != NULL) { | 2211 | if (rsp->orphan_donelist != NULL) { |
2184 | __call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist, | 2212 | __call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist, |
2185 | rsp->orphan_donetail, ql, qll); | 2213 | rsp->orphan_donetail, ql, qll, flags); |
2186 | ql = qll = 0; | 2214 | ql = qll = 0; |
2187 | rsp->orphan_donelist = NULL; | 2215 | rsp->orphan_donelist = NULL; |
2188 | rsp->orphan_donetail = &rsp->orphan_donelist; | 2216 | rsp->orphan_donetail = &rsp->orphan_donelist; |
2189 | } | 2217 | } |
2190 | if (rsp->orphan_nxtlist != NULL) { | 2218 | if (rsp->orphan_nxtlist != NULL) { |
2191 | __call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist, | 2219 | __call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist, |
2192 | rsp->orphan_nxttail, ql, qll); | 2220 | rsp->orphan_nxttail, ql, qll, flags); |
2193 | ql = qll = 0; | 2221 | ql = qll = 0; |
2194 | rsp->orphan_nxtlist = NULL; | 2222 | rsp->orphan_nxtlist = NULL; |
2195 | rsp->orphan_nxttail = &rsp->orphan_nxtlist; | 2223 | rsp->orphan_nxttail = &rsp->orphan_nxtlist; |
@@ -2209,6 +2237,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) | |||
2209 | struct rcu_node *rnp = rdp->mynode; | 2237 | struct rcu_node *rnp = rdp->mynode; |
2210 | 2238 | ||
2211 | raw_spin_lock_irqsave(&rnp->lock, flags); | 2239 | raw_spin_lock_irqsave(&rnp->lock, flags); |
2240 | smp_mb__after_unlock_lock(); | ||
2212 | c = rcu_start_future_gp(rnp, rdp); | 2241 | c = rcu_start_future_gp(rnp, rdp); |
2213 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 2242 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
2214 | 2243 | ||
@@ -2250,6 +2279,7 @@ static int rcu_nocb_kthread(void *arg) | |||
2250 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | 2279 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, |
2251 | TPS("Sleep")); | 2280 | TPS("Sleep")); |
2252 | wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); | 2281 | wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); |
2282 | /* Memory barrier provide by xchg() below. */ | ||
2253 | } else if (firsttime) { | 2283 | } else if (firsttime) { |
2254 | firsttime = 0; | 2284 | firsttime = 0; |
2255 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | 2285 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, |
@@ -2310,6 +2340,22 @@ static int rcu_nocb_kthread(void *arg) | |||
2310 | return 0; | 2340 | return 0; |
2311 | } | 2341 | } |
2312 | 2342 | ||
2343 | /* Is a deferred wakeup of rcu_nocb_kthread() required? */ | ||
2344 | static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp) | ||
2345 | { | ||
2346 | return ACCESS_ONCE(rdp->nocb_defer_wakeup); | ||
2347 | } | ||
2348 | |||
2349 | /* Do a deferred wakeup of rcu_nocb_kthread(). */ | ||
2350 | static void do_nocb_deferred_wakeup(struct rcu_data *rdp) | ||
2351 | { | ||
2352 | if (!rcu_nocb_need_deferred_wakeup(rdp)) | ||
2353 | return; | ||
2354 | ACCESS_ONCE(rdp->nocb_defer_wakeup) = false; | ||
2355 | wake_up(&rdp->nocb_wq); | ||
2356 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("DeferredWakeEmpty")); | ||
2357 | } | ||
2358 | |||
2313 | /* Initialize per-rcu_data variables for no-CBs CPUs. */ | 2359 | /* Initialize per-rcu_data variables for no-CBs CPUs. */ |
2314 | static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) | 2360 | static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) |
2315 | { | 2361 | { |
@@ -2365,13 +2411,14 @@ static void rcu_init_one_nocb(struct rcu_node *rnp) | |||
2365 | } | 2411 | } |
2366 | 2412 | ||
2367 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, | 2413 | static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, |
2368 | bool lazy) | 2414 | bool lazy, unsigned long flags) |
2369 | { | 2415 | { |
2370 | return 0; | 2416 | return 0; |
2371 | } | 2417 | } |
2372 | 2418 | ||
2373 | static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, | 2419 | static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, |
2374 | struct rcu_data *rdp) | 2420 | struct rcu_data *rdp, |
2421 | unsigned long flags) | ||
2375 | { | 2422 | { |
2376 | return 0; | 2423 | return 0; |
2377 | } | 2424 | } |
@@ -2380,6 +2427,15 @@ static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) | |||
2380 | { | 2427 | { |
2381 | } | 2428 | } |
2382 | 2429 | ||
2430 | static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp) | ||
2431 | { | ||
2432 | return false; | ||
2433 | } | ||
2434 | |||
2435 | static void do_nocb_deferred_wakeup(struct rcu_data *rdp) | ||
2436 | { | ||
2437 | } | ||
2438 | |||
2383 | static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp) | 2439 | static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp) |
2384 | { | 2440 | { |
2385 | } | 2441 | } |
@@ -2829,3 +2885,23 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp) | |||
2829 | } | 2885 | } |
2830 | 2886 | ||
2831 | #endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ | 2887 | #endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ |
2888 | |||
2889 | /* | ||
2890 | * Is this CPU a NO_HZ_FULL CPU that should ignore RCU so that the | ||
2891 | * grace-period kthread will do force_quiescent_state() processing? | ||
2892 | * The idea is to avoid waking up RCU core processing on such a | ||
2893 | * CPU unless the grace period has extended for too long. | ||
2894 | * | ||
2895 | * This code relies on the fact that all NO_HZ_FULL CPUs are also | ||
2896 | * CONFIG_RCU_NOCB_CPUs. | ||
2897 | */ | ||
2898 | static bool rcu_nohz_full_cpu(struct rcu_state *rsp) | ||
2899 | { | ||
2900 | #ifdef CONFIG_NO_HZ_FULL | ||
2901 | if (tick_nohz_full_cpu(smp_processor_id()) && | ||
2902 | (!rcu_gp_in_progress(rsp) || | ||
2903 | ULONG_CMP_LT(jiffies, ACCESS_ONCE(rsp->gp_start) + HZ))) | ||
2904 | return 1; | ||
2905 | #endif /* #ifdef CONFIG_NO_HZ_FULL */ | ||
2906 | return 0; | ||
2907 | } | ||
diff --git a/kernel/rcu/tree_trace.c b/kernel/rcu/tree_trace.c index 3596797b7e46..4def475336d4 100644 --- a/kernel/rcu/tree_trace.c +++ b/kernel/rcu/tree_trace.c | |||
@@ -364,9 +364,10 @@ static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) | |||
364 | rdp->n_rp_report_qs, | 364 | rdp->n_rp_report_qs, |
365 | rdp->n_rp_cb_ready, | 365 | rdp->n_rp_cb_ready, |
366 | rdp->n_rp_cpu_needs_gp); | 366 | rdp->n_rp_cpu_needs_gp); |
367 | seq_printf(m, "gpc=%ld gps=%ld nn=%ld\n", | 367 | seq_printf(m, "gpc=%ld gps=%ld nn=%ld ndw%ld\n", |
368 | rdp->n_rp_gp_completed, | 368 | rdp->n_rp_gp_completed, |
369 | rdp->n_rp_gp_started, | 369 | rdp->n_rp_gp_started, |
370 | rdp->n_rp_nocb_defer_wakeup, | ||
370 | rdp->n_rp_need_nothing); | 371 | rdp->n_rp_need_nothing); |
371 | } | 372 | } |
372 | 373 | ||
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 6cb3dff89e2b..802365ccd591 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c | |||
@@ -128,6 +128,11 @@ struct lockdep_map rcu_sched_lock_map = | |||
128 | STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key); | 128 | STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key); |
129 | EXPORT_SYMBOL_GPL(rcu_sched_lock_map); | 129 | EXPORT_SYMBOL_GPL(rcu_sched_lock_map); |
130 | 130 | ||
131 | static struct lock_class_key rcu_callback_key; | ||
132 | struct lockdep_map rcu_callback_map = | ||
133 | STATIC_LOCKDEP_MAP_INIT("rcu_callback", &rcu_callback_key); | ||
134 | EXPORT_SYMBOL_GPL(rcu_callback_map); | ||
135 | |||
131 | int notrace debug_lockdep_rcu_enabled(void) | 136 | int notrace debug_lockdep_rcu_enabled(void) |
132 | { | 137 | { |
133 | return rcu_scheduler_active && debug_locks && | 138 | return rcu_scheduler_active && debug_locks && |
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile index 7b621409cf15..9a95c8c2af2a 100644 --- a/kernel/sched/Makefile +++ b/kernel/sched/Makefile | |||
@@ -11,9 +11,10 @@ ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) | |||
11 | CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer | 11 | CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer |
12 | endif | 12 | endif |
13 | 13 | ||
14 | obj-y += core.o proc.o clock.o cputime.o idle_task.o fair.o rt.o stop_task.o | 14 | obj-y += core.o proc.o clock.o cputime.o |
15 | obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o | ||
15 | obj-y += wait.o completion.o | 16 | obj-y += wait.o completion.o |
16 | obj-$(CONFIG_SMP) += cpupri.o | 17 | obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o |
17 | obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o | 18 | obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o |
18 | obj-$(CONFIG_SCHEDSTATS) += stats.o | 19 | obj-$(CONFIG_SCHEDSTATS) += stats.o |
19 | obj-$(CONFIG_SCHED_DEBUG) += debug.o | 20 | obj-$(CONFIG_SCHED_DEBUG) += debug.o |
diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c index c3ae1446461c..6bd6a6731b21 100644 --- a/kernel/sched/clock.c +++ b/kernel/sched/clock.c | |||
@@ -26,9 +26,10 @@ | |||
26 | * at 0 on boot (but people really shouldn't rely on that). | 26 | * at 0 on boot (but people really shouldn't rely on that). |
27 | * | 27 | * |
28 | * cpu_clock(i) -- can be used from any context, including NMI. | 28 | * cpu_clock(i) -- can be used from any context, including NMI. |
29 | * sched_clock_cpu(i) -- must be used with local IRQs disabled (implied by NMI) | ||
30 | * local_clock() -- is cpu_clock() on the current cpu. | 29 | * local_clock() -- is cpu_clock() on the current cpu. |
31 | * | 30 | * |
31 | * sched_clock_cpu(i) | ||
32 | * | ||
32 | * How: | 33 | * How: |
33 | * | 34 | * |
34 | * The implementation either uses sched_clock() when | 35 | * The implementation either uses sched_clock() when |
@@ -50,15 +51,6 @@ | |||
50 | * Furthermore, explicit sleep and wakeup hooks allow us to account for time | 51 | * Furthermore, explicit sleep and wakeup hooks allow us to account for time |
51 | * that is otherwise invisible (TSC gets stopped). | 52 | * that is otherwise invisible (TSC gets stopped). |
52 | * | 53 | * |
53 | * | ||
54 | * Notes: | ||
55 | * | ||
56 | * The !IRQ-safetly of sched_clock() and sched_clock_cpu() comes from things | ||
57 | * like cpufreq interrupts that can change the base clock (TSC) multiplier | ||
58 | * and cause funny jumps in time -- although the filtering provided by | ||
59 | * sched_clock_cpu() should mitigate serious artifacts we cannot rely on it | ||
60 | * in general since for !CONFIG_HAVE_UNSTABLE_SCHED_CLOCK we fully rely on | ||
61 | * sched_clock(). | ||
62 | */ | 54 | */ |
63 | #include <linux/spinlock.h> | 55 | #include <linux/spinlock.h> |
64 | #include <linux/hardirq.h> | 56 | #include <linux/hardirq.h> |
@@ -66,6 +58,8 @@ | |||
66 | #include <linux/percpu.h> | 58 | #include <linux/percpu.h> |
67 | #include <linux/ktime.h> | 59 | #include <linux/ktime.h> |
68 | #include <linux/sched.h> | 60 | #include <linux/sched.h> |
61 | #include <linux/static_key.h> | ||
62 | #include <linux/workqueue.h> | ||
69 | 63 | ||
70 | /* | 64 | /* |
71 | * Scheduler clock - returns current time in nanosec units. | 65 | * Scheduler clock - returns current time in nanosec units. |
@@ -82,7 +76,37 @@ EXPORT_SYMBOL_GPL(sched_clock); | |||
82 | __read_mostly int sched_clock_running; | 76 | __read_mostly int sched_clock_running; |
83 | 77 | ||
84 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK | 78 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK |
85 | __read_mostly int sched_clock_stable; | 79 | static struct static_key __sched_clock_stable = STATIC_KEY_INIT; |
80 | |||
81 | int sched_clock_stable(void) | ||
82 | { | ||
83 | if (static_key_false(&__sched_clock_stable)) | ||
84 | return false; | ||
85 | return true; | ||
86 | } | ||
87 | |||
88 | void set_sched_clock_stable(void) | ||
89 | { | ||
90 | if (!sched_clock_stable()) | ||
91 | static_key_slow_dec(&__sched_clock_stable); | ||
92 | } | ||
93 | |||
94 | static void __clear_sched_clock_stable(struct work_struct *work) | ||
95 | { | ||
96 | /* XXX worry about clock continuity */ | ||
97 | if (sched_clock_stable()) | ||
98 | static_key_slow_inc(&__sched_clock_stable); | ||
99 | } | ||
100 | |||
101 | static DECLARE_WORK(sched_clock_work, __clear_sched_clock_stable); | ||
102 | |||
103 | void clear_sched_clock_stable(void) | ||
104 | { | ||
105 | if (keventd_up()) | ||
106 | schedule_work(&sched_clock_work); | ||
107 | else | ||
108 | __clear_sched_clock_stable(&sched_clock_work); | ||
109 | } | ||
86 | 110 | ||
87 | struct sched_clock_data { | 111 | struct sched_clock_data { |
88 | u64 tick_raw; | 112 | u64 tick_raw; |
@@ -242,20 +266,20 @@ u64 sched_clock_cpu(int cpu) | |||
242 | struct sched_clock_data *scd; | 266 | struct sched_clock_data *scd; |
243 | u64 clock; | 267 | u64 clock; |
244 | 268 | ||
245 | WARN_ON_ONCE(!irqs_disabled()); | 269 | if (sched_clock_stable()) |
246 | |||
247 | if (sched_clock_stable) | ||
248 | return sched_clock(); | 270 | return sched_clock(); |
249 | 271 | ||
250 | if (unlikely(!sched_clock_running)) | 272 | if (unlikely(!sched_clock_running)) |
251 | return 0ull; | 273 | return 0ull; |
252 | 274 | ||
275 | preempt_disable(); | ||
253 | scd = cpu_sdc(cpu); | 276 | scd = cpu_sdc(cpu); |
254 | 277 | ||
255 | if (cpu != smp_processor_id()) | 278 | if (cpu != smp_processor_id()) |
256 | clock = sched_clock_remote(scd); | 279 | clock = sched_clock_remote(scd); |
257 | else | 280 | else |
258 | clock = sched_clock_local(scd); | 281 | clock = sched_clock_local(scd); |
282 | preempt_enable(); | ||
259 | 283 | ||
260 | return clock; | 284 | return clock; |
261 | } | 285 | } |
@@ -265,7 +289,7 @@ void sched_clock_tick(void) | |||
265 | struct sched_clock_data *scd; | 289 | struct sched_clock_data *scd; |
266 | u64 now, now_gtod; | 290 | u64 now, now_gtod; |
267 | 291 | ||
268 | if (sched_clock_stable) | 292 | if (sched_clock_stable()) |
269 | return; | 293 | return; |
270 | 294 | ||
271 | if (unlikely(!sched_clock_running)) | 295 | if (unlikely(!sched_clock_running)) |
@@ -316,14 +340,10 @@ EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event); | |||
316 | */ | 340 | */ |
317 | u64 cpu_clock(int cpu) | 341 | u64 cpu_clock(int cpu) |
318 | { | 342 | { |
319 | u64 clock; | 343 | if (static_key_false(&__sched_clock_stable)) |
320 | unsigned long flags; | 344 | return sched_clock_cpu(cpu); |
321 | |||
322 | local_irq_save(flags); | ||
323 | clock = sched_clock_cpu(cpu); | ||
324 | local_irq_restore(flags); | ||
325 | 345 | ||
326 | return clock; | 346 | return sched_clock(); |
327 | } | 347 | } |
328 | 348 | ||
329 | /* | 349 | /* |
@@ -335,14 +355,10 @@ u64 cpu_clock(int cpu) | |||
335 | */ | 355 | */ |
336 | u64 local_clock(void) | 356 | u64 local_clock(void) |
337 | { | 357 | { |
338 | u64 clock; | 358 | if (static_key_false(&__sched_clock_stable)) |
339 | unsigned long flags; | 359 | return sched_clock_cpu(raw_smp_processor_id()); |
340 | 360 | ||
341 | local_irq_save(flags); | 361 | return sched_clock(); |
342 | clock = sched_clock_cpu(smp_processor_id()); | ||
343 | local_irq_restore(flags); | ||
344 | |||
345 | return clock; | ||
346 | } | 362 | } |
347 | 363 | ||
348 | #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ | 364 | #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ |
@@ -362,12 +378,12 @@ u64 sched_clock_cpu(int cpu) | |||
362 | 378 | ||
363 | u64 cpu_clock(int cpu) | 379 | u64 cpu_clock(int cpu) |
364 | { | 380 | { |
365 | return sched_clock_cpu(cpu); | 381 | return sched_clock(); |
366 | } | 382 | } |
367 | 383 | ||
368 | u64 local_clock(void) | 384 | u64 local_clock(void) |
369 | { | 385 | { |
370 | return sched_clock_cpu(0); | 386 | return sched_clock(); |
371 | } | 387 | } |
372 | 388 | ||
373 | #endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ | 389 | #endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a88f4a485c5e..36c951b7eef8 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -296,8 +296,6 @@ __read_mostly int scheduler_running; | |||
296 | */ | 296 | */ |
297 | int sysctl_sched_rt_runtime = 950000; | 297 | int sysctl_sched_rt_runtime = 950000; |
298 | 298 | ||
299 | |||
300 | |||
301 | /* | 299 | /* |
302 | * __task_rq_lock - lock the rq @p resides on. | 300 | * __task_rq_lock - lock the rq @p resides on. |
303 | */ | 301 | */ |
@@ -899,7 +897,9 @@ static inline int normal_prio(struct task_struct *p) | |||
899 | { | 897 | { |
900 | int prio; | 898 | int prio; |
901 | 899 | ||
902 | if (task_has_rt_policy(p)) | 900 | if (task_has_dl_policy(p)) |
901 | prio = MAX_DL_PRIO-1; | ||
902 | else if (task_has_rt_policy(p)) | ||
903 | prio = MAX_RT_PRIO-1 - p->rt_priority; | 903 | prio = MAX_RT_PRIO-1 - p->rt_priority; |
904 | else | 904 | else |
905 | prio = __normal_prio(p); | 905 | prio = __normal_prio(p); |
@@ -945,7 +945,7 @@ static inline void check_class_changed(struct rq *rq, struct task_struct *p, | |||
945 | if (prev_class->switched_from) | 945 | if (prev_class->switched_from) |
946 | prev_class->switched_from(rq, p); | 946 | prev_class->switched_from(rq, p); |
947 | p->sched_class->switched_to(rq, p); | 947 | p->sched_class->switched_to(rq, p); |
948 | } else if (oldprio != p->prio) | 948 | } else if (oldprio != p->prio || dl_task(p)) |
949 | p->sched_class->prio_changed(rq, p, oldprio); | 949 | p->sched_class->prio_changed(rq, p, oldprio); |
950 | } | 950 | } |
951 | 951 | ||
@@ -1499,8 +1499,7 @@ void scheduler_ipi(void) | |||
1499 | * TIF_NEED_RESCHED remotely (for the first time) will also send | 1499 | * TIF_NEED_RESCHED remotely (for the first time) will also send |
1500 | * this IPI. | 1500 | * this IPI. |
1501 | */ | 1501 | */ |
1502 | if (tif_need_resched()) | 1502 | preempt_fold_need_resched(); |
1503 | set_preempt_need_resched(); | ||
1504 | 1503 | ||
1505 | if (llist_empty(&this_rq()->wake_list) | 1504 | if (llist_empty(&this_rq()->wake_list) |
1506 | && !tick_nohz_full_cpu(smp_processor_id()) | 1505 | && !tick_nohz_full_cpu(smp_processor_id()) |
@@ -1717,6 +1716,13 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p) | |||
1717 | memset(&p->se.statistics, 0, sizeof(p->se.statistics)); | 1716 | memset(&p->se.statistics, 0, sizeof(p->se.statistics)); |
1718 | #endif | 1717 | #endif |
1719 | 1718 | ||
1719 | RB_CLEAR_NODE(&p->dl.rb_node); | ||
1720 | hrtimer_init(&p->dl.dl_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
1721 | p->dl.dl_runtime = p->dl.runtime = 0; | ||
1722 | p->dl.dl_deadline = p->dl.deadline = 0; | ||
1723 | p->dl.dl_period = 0; | ||
1724 | p->dl.flags = 0; | ||
1725 | |||
1720 | INIT_LIST_HEAD(&p->rt.run_list); | 1726 | INIT_LIST_HEAD(&p->rt.run_list); |
1721 | 1727 | ||
1722 | #ifdef CONFIG_PREEMPT_NOTIFIERS | 1728 | #ifdef CONFIG_PREEMPT_NOTIFIERS |
@@ -1768,7 +1774,7 @@ void set_numabalancing_state(bool enabled) | |||
1768 | /* | 1774 | /* |
1769 | * fork()/clone()-time setup: | 1775 | * fork()/clone()-time setup: |
1770 | */ | 1776 | */ |
1771 | void sched_fork(unsigned long clone_flags, struct task_struct *p) | 1777 | int sched_fork(unsigned long clone_flags, struct task_struct *p) |
1772 | { | 1778 | { |
1773 | unsigned long flags; | 1779 | unsigned long flags; |
1774 | int cpu = get_cpu(); | 1780 | int cpu = get_cpu(); |
@@ -1790,7 +1796,7 @@ void sched_fork(unsigned long clone_flags, struct task_struct *p) | |||
1790 | * Revert to default priority/policy on fork if requested. | 1796 | * Revert to default priority/policy on fork if requested. |
1791 | */ | 1797 | */ |
1792 | if (unlikely(p->sched_reset_on_fork)) { | 1798 | if (unlikely(p->sched_reset_on_fork)) { |
1793 | if (task_has_rt_policy(p)) { | 1799 | if (task_has_dl_policy(p) || task_has_rt_policy(p)) { |
1794 | p->policy = SCHED_NORMAL; | 1800 | p->policy = SCHED_NORMAL; |
1795 | p->static_prio = NICE_TO_PRIO(0); | 1801 | p->static_prio = NICE_TO_PRIO(0); |
1796 | p->rt_priority = 0; | 1802 | p->rt_priority = 0; |
@@ -1807,8 +1813,14 @@ void sched_fork(unsigned long clone_flags, struct task_struct *p) | |||
1807 | p->sched_reset_on_fork = 0; | 1813 | p->sched_reset_on_fork = 0; |
1808 | } | 1814 | } |
1809 | 1815 | ||
1810 | if (!rt_prio(p->prio)) | 1816 | if (dl_prio(p->prio)) { |
1817 | put_cpu(); | ||
1818 | return -EAGAIN; | ||
1819 | } else if (rt_prio(p->prio)) { | ||
1820 | p->sched_class = &rt_sched_class; | ||
1821 | } else { | ||
1811 | p->sched_class = &fair_sched_class; | 1822 | p->sched_class = &fair_sched_class; |
1823 | } | ||
1812 | 1824 | ||
1813 | if (p->sched_class->task_fork) | 1825 | if (p->sched_class->task_fork) |
1814 | p->sched_class->task_fork(p); | 1826 | p->sched_class->task_fork(p); |
@@ -1834,11 +1846,124 @@ void sched_fork(unsigned long clone_flags, struct task_struct *p) | |||
1834 | init_task_preempt_count(p); | 1846 | init_task_preempt_count(p); |
1835 | #ifdef CONFIG_SMP | 1847 | #ifdef CONFIG_SMP |
1836 | plist_node_init(&p->pushable_tasks, MAX_PRIO); | 1848 | plist_node_init(&p->pushable_tasks, MAX_PRIO); |
1849 | RB_CLEAR_NODE(&p->pushable_dl_tasks); | ||
1837 | #endif | 1850 | #endif |
1838 | 1851 | ||
1839 | put_cpu(); | 1852 | put_cpu(); |
1853 | return 0; | ||
1854 | } | ||
1855 | |||
1856 | unsigned long to_ratio(u64 period, u64 runtime) | ||
1857 | { | ||
1858 | if (runtime == RUNTIME_INF) | ||
1859 | return 1ULL << 20; | ||
1860 | |||
1861 | /* | ||
1862 | * Doing this here saves a lot of checks in all | ||
1863 | * the calling paths, and returning zero seems | ||
1864 | * safe for them anyway. | ||
1865 | */ | ||
1866 | if (period == 0) | ||
1867 | return 0; | ||
1868 | |||
1869 | return div64_u64(runtime << 20, period); | ||
1870 | } | ||
1871 | |||
1872 | #ifdef CONFIG_SMP | ||
1873 | inline struct dl_bw *dl_bw_of(int i) | ||
1874 | { | ||
1875 | return &cpu_rq(i)->rd->dl_bw; | ||
1840 | } | 1876 | } |
1841 | 1877 | ||
1878 | static inline int dl_bw_cpus(int i) | ||
1879 | { | ||
1880 | struct root_domain *rd = cpu_rq(i)->rd; | ||
1881 | int cpus = 0; | ||
1882 | |||
1883 | for_each_cpu_and(i, rd->span, cpu_active_mask) | ||
1884 | cpus++; | ||
1885 | |||
1886 | return cpus; | ||
1887 | } | ||
1888 | #else | ||
1889 | inline struct dl_bw *dl_bw_of(int i) | ||
1890 | { | ||
1891 | return &cpu_rq(i)->dl.dl_bw; | ||
1892 | } | ||
1893 | |||
1894 | static inline int dl_bw_cpus(int i) | ||
1895 | { | ||
1896 | return 1; | ||
1897 | } | ||
1898 | #endif | ||
1899 | |||
1900 | static inline | ||
1901 | void __dl_clear(struct dl_bw *dl_b, u64 tsk_bw) | ||
1902 | { | ||
1903 | dl_b->total_bw -= tsk_bw; | ||
1904 | } | ||
1905 | |||
1906 | static inline | ||
1907 | void __dl_add(struct dl_bw *dl_b, u64 tsk_bw) | ||
1908 | { | ||
1909 | dl_b->total_bw += tsk_bw; | ||
1910 | } | ||
1911 | |||
1912 | static inline | ||
1913 | bool __dl_overflow(struct dl_bw *dl_b, int cpus, u64 old_bw, u64 new_bw) | ||
1914 | { | ||
1915 | return dl_b->bw != -1 && | ||
1916 | dl_b->bw * cpus < dl_b->total_bw - old_bw + new_bw; | ||
1917 | } | ||
1918 | |||
1919 | /* | ||
1920 | * We must be sure that accepting a new task (or allowing changing the | ||
1921 | * parameters of an existing one) is consistent with the bandwidth | ||
1922 | * constraints. If yes, this function also accordingly updates the currently | ||
1923 | * allocated bandwidth to reflect the new situation. | ||
1924 | * | ||
1925 | * This function is called while holding p's rq->lock. | ||
1926 | */ | ||
1927 | static int dl_overflow(struct task_struct *p, int policy, | ||
1928 | const struct sched_attr *attr) | ||
1929 | { | ||
1930 | |||
1931 | struct dl_bw *dl_b = dl_bw_of(task_cpu(p)); | ||
1932 | u64 period = attr->sched_period; | ||
1933 | u64 runtime = attr->sched_runtime; | ||
1934 | u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0; | ||
1935 | int cpus, err = -1; | ||
1936 | |||
1937 | if (new_bw == p->dl.dl_bw) | ||
1938 | return 0; | ||
1939 | |||
1940 | /* | ||
1941 | * Either if a task, enters, leave, or stays -deadline but changes | ||
1942 | * its parameters, we may need to update accordingly the total | ||
1943 | * allocated bandwidth of the container. | ||
1944 | */ | ||
1945 | raw_spin_lock(&dl_b->lock); | ||
1946 | cpus = dl_bw_cpus(task_cpu(p)); | ||
1947 | if (dl_policy(policy) && !task_has_dl_policy(p) && | ||
1948 | !__dl_overflow(dl_b, cpus, 0, new_bw)) { | ||
1949 | __dl_add(dl_b, new_bw); | ||
1950 | err = 0; | ||
1951 | } else if (dl_policy(policy) && task_has_dl_policy(p) && | ||
1952 | !__dl_overflow(dl_b, cpus, p->dl.dl_bw, new_bw)) { | ||
1953 | __dl_clear(dl_b, p->dl.dl_bw); | ||
1954 | __dl_add(dl_b, new_bw); | ||
1955 | err = 0; | ||
1956 | } else if (!dl_policy(policy) && task_has_dl_policy(p)) { | ||
1957 | __dl_clear(dl_b, p->dl.dl_bw); | ||
1958 | err = 0; | ||
1959 | } | ||
1960 | raw_spin_unlock(&dl_b->lock); | ||
1961 | |||
1962 | return err; | ||
1963 | } | ||
1964 | |||
1965 | extern void init_dl_bw(struct dl_bw *dl_b); | ||
1966 | |||
1842 | /* | 1967 | /* |
1843 | * wake_up_new_task - wake up a newly created task for the first time. | 1968 | * wake_up_new_task - wake up a newly created task for the first time. |
1844 | * | 1969 | * |
@@ -2003,6 +2128,9 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) | |||
2003 | if (unlikely(prev_state == TASK_DEAD)) { | 2128 | if (unlikely(prev_state == TASK_DEAD)) { |
2004 | task_numa_free(prev); | 2129 | task_numa_free(prev); |
2005 | 2130 | ||
2131 | if (prev->sched_class->task_dead) | ||
2132 | prev->sched_class->task_dead(prev); | ||
2133 | |||
2006 | /* | 2134 | /* |
2007 | * Remove function-return probe instances associated with this | 2135 | * Remove function-return probe instances associated with this |
2008 | * task and put them back on the free list. | 2136 | * task and put them back on the free list. |
@@ -2296,7 +2424,7 @@ void scheduler_tick(void) | |||
2296 | 2424 | ||
2297 | #ifdef CONFIG_SMP | 2425 | #ifdef CONFIG_SMP |
2298 | rq->idle_balance = idle_cpu(cpu); | 2426 | rq->idle_balance = idle_cpu(cpu); |
2299 | trigger_load_balance(rq, cpu); | 2427 | trigger_load_balance(rq); |
2300 | #endif | 2428 | #endif |
2301 | rq_last_tick_reset(rq); | 2429 | rq_last_tick_reset(rq); |
2302 | } | 2430 | } |
@@ -2414,10 +2542,10 @@ static inline void schedule_debug(struct task_struct *prev) | |||
2414 | { | 2542 | { |
2415 | /* | 2543 | /* |
2416 | * Test if we are atomic. Since do_exit() needs to call into | 2544 | * Test if we are atomic. Since do_exit() needs to call into |
2417 | * schedule() atomically, we ignore that path for now. | 2545 | * schedule() atomically, we ignore that path. Otherwise whine |
2418 | * Otherwise, whine if we are scheduling when we should not be. | 2546 | * if we are scheduling when we should not. |
2419 | */ | 2547 | */ |
2420 | if (unlikely(in_atomic_preempt_off() && !prev->exit_state)) | 2548 | if (unlikely(in_atomic_preempt_off() && prev->state != TASK_DEAD)) |
2421 | __schedule_bug(prev); | 2549 | __schedule_bug(prev); |
2422 | rcu_sleep_check(); | 2550 | rcu_sleep_check(); |
2423 | 2551 | ||
@@ -2761,11 +2889,11 @@ EXPORT_SYMBOL(sleep_on_timeout); | |||
2761 | */ | 2889 | */ |
2762 | void rt_mutex_setprio(struct task_struct *p, int prio) | 2890 | void rt_mutex_setprio(struct task_struct *p, int prio) |
2763 | { | 2891 | { |
2764 | int oldprio, on_rq, running; | 2892 | int oldprio, on_rq, running, enqueue_flag = 0; |
2765 | struct rq *rq; | 2893 | struct rq *rq; |
2766 | const struct sched_class *prev_class; | 2894 | const struct sched_class *prev_class; |
2767 | 2895 | ||
2768 | BUG_ON(prio < 0 || prio > MAX_PRIO); | 2896 | BUG_ON(prio > MAX_PRIO); |
2769 | 2897 | ||
2770 | rq = __task_rq_lock(p); | 2898 | rq = __task_rq_lock(p); |
2771 | 2899 | ||
@@ -2788,6 +2916,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio) | |||
2788 | } | 2916 | } |
2789 | 2917 | ||
2790 | trace_sched_pi_setprio(p, prio); | 2918 | trace_sched_pi_setprio(p, prio); |
2919 | p->pi_top_task = rt_mutex_get_top_task(p); | ||
2791 | oldprio = p->prio; | 2920 | oldprio = p->prio; |
2792 | prev_class = p->sched_class; | 2921 | prev_class = p->sched_class; |
2793 | on_rq = p->on_rq; | 2922 | on_rq = p->on_rq; |
@@ -2797,23 +2926,49 @@ void rt_mutex_setprio(struct task_struct *p, int prio) | |||
2797 | if (running) | 2926 | if (running) |
2798 | p->sched_class->put_prev_task(rq, p); | 2927 | p->sched_class->put_prev_task(rq, p); |
2799 | 2928 | ||
2800 | if (rt_prio(prio)) | 2929 | /* |
2930 | * Boosting condition are: | ||
2931 | * 1. -rt task is running and holds mutex A | ||
2932 | * --> -dl task blocks on mutex A | ||
2933 | * | ||
2934 | * 2. -dl task is running and holds mutex A | ||
2935 | * --> -dl task blocks on mutex A and could preempt the | ||
2936 | * running task | ||
2937 | */ | ||
2938 | if (dl_prio(prio)) { | ||
2939 | if (!dl_prio(p->normal_prio) || (p->pi_top_task && | ||
2940 | dl_entity_preempt(&p->pi_top_task->dl, &p->dl))) { | ||
2941 | p->dl.dl_boosted = 1; | ||
2942 | p->dl.dl_throttled = 0; | ||
2943 | enqueue_flag = ENQUEUE_REPLENISH; | ||
2944 | } else | ||
2945 | p->dl.dl_boosted = 0; | ||
2946 | p->sched_class = &dl_sched_class; | ||
2947 | } else if (rt_prio(prio)) { | ||
2948 | if (dl_prio(oldprio)) | ||
2949 | p->dl.dl_boosted = 0; | ||
2950 | if (oldprio < prio) | ||
2951 | enqueue_flag = ENQUEUE_HEAD; | ||
2801 | p->sched_class = &rt_sched_class; | 2952 | p->sched_class = &rt_sched_class; |
2802 | else | 2953 | } else { |
2954 | if (dl_prio(oldprio)) | ||
2955 | p->dl.dl_boosted = 0; | ||
2803 | p->sched_class = &fair_sched_class; | 2956 | p->sched_class = &fair_sched_class; |
2957 | } | ||
2804 | 2958 | ||
2805 | p->prio = prio; | 2959 | p->prio = prio; |
2806 | 2960 | ||
2807 | if (running) | 2961 | if (running) |
2808 | p->sched_class->set_curr_task(rq); | 2962 | p->sched_class->set_curr_task(rq); |
2809 | if (on_rq) | 2963 | if (on_rq) |
2810 | enqueue_task(rq, p, oldprio < prio ? ENQUEUE_HEAD : 0); | 2964 | enqueue_task(rq, p, enqueue_flag); |
2811 | 2965 | ||
2812 | check_class_changed(rq, p, prev_class, oldprio); | 2966 | check_class_changed(rq, p, prev_class, oldprio); |
2813 | out_unlock: | 2967 | out_unlock: |
2814 | __task_rq_unlock(rq); | 2968 | __task_rq_unlock(rq); |
2815 | } | 2969 | } |
2816 | #endif | 2970 | #endif |
2971 | |||
2817 | void set_user_nice(struct task_struct *p, long nice) | 2972 | void set_user_nice(struct task_struct *p, long nice) |
2818 | { | 2973 | { |
2819 | int old_prio, delta, on_rq; | 2974 | int old_prio, delta, on_rq; |
@@ -2831,9 +2986,9 @@ void set_user_nice(struct task_struct *p, long nice) | |||
2831 | * The RT priorities are set via sched_setscheduler(), but we still | 2986 | * The RT priorities are set via sched_setscheduler(), but we still |
2832 | * allow the 'normal' nice value to be set - but as expected | 2987 | * allow the 'normal' nice value to be set - but as expected |
2833 | * it wont have any effect on scheduling until the task is | 2988 | * it wont have any effect on scheduling until the task is |
2834 | * SCHED_FIFO/SCHED_RR: | 2989 | * SCHED_DEADLINE, SCHED_FIFO or SCHED_RR: |
2835 | */ | 2990 | */ |
2836 | if (task_has_rt_policy(p)) { | 2991 | if (task_has_dl_policy(p) || task_has_rt_policy(p)) { |
2837 | p->static_prio = NICE_TO_PRIO(nice); | 2992 | p->static_prio = NICE_TO_PRIO(nice); |
2838 | goto out_unlock; | 2993 | goto out_unlock; |
2839 | } | 2994 | } |
@@ -2988,22 +3143,95 @@ static struct task_struct *find_process_by_pid(pid_t pid) | |||
2988 | return pid ? find_task_by_vpid(pid) : current; | 3143 | return pid ? find_task_by_vpid(pid) : current; |
2989 | } | 3144 | } |
2990 | 3145 | ||
2991 | /* Actually do priority change: must hold rq lock. */ | 3146 | /* |
3147 | * This function initializes the sched_dl_entity of a newly becoming | ||
3148 | * SCHED_DEADLINE task. | ||
3149 | * | ||
3150 | * Only the static values are considered here, the actual runtime and the | ||
3151 | * absolute deadline will be properly calculated when the task is enqueued | ||
3152 | * for the first time with its new policy. | ||
3153 | */ | ||
2992 | static void | 3154 | static void |
2993 | __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio) | 3155 | __setparam_dl(struct task_struct *p, const struct sched_attr *attr) |
3156 | { | ||
3157 | struct sched_dl_entity *dl_se = &p->dl; | ||
3158 | |||
3159 | init_dl_task_timer(dl_se); | ||
3160 | dl_se->dl_runtime = attr->sched_runtime; | ||
3161 | dl_se->dl_deadline = attr->sched_deadline; | ||
3162 | dl_se->dl_period = attr->sched_period ?: dl_se->dl_deadline; | ||
3163 | dl_se->flags = attr->sched_flags; | ||
3164 | dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime); | ||
3165 | dl_se->dl_throttled = 0; | ||
3166 | dl_se->dl_new = 1; | ||
3167 | } | ||
3168 | |||
3169 | /* Actually do priority change: must hold pi & rq lock. */ | ||
3170 | static void __setscheduler(struct rq *rq, struct task_struct *p, | ||
3171 | const struct sched_attr *attr) | ||
2994 | { | 3172 | { |
3173 | int policy = attr->sched_policy; | ||
3174 | |||
3175 | if (policy == -1) /* setparam */ | ||
3176 | policy = p->policy; | ||
3177 | |||
2995 | p->policy = policy; | 3178 | p->policy = policy; |
2996 | p->rt_priority = prio; | 3179 | |
3180 | if (dl_policy(policy)) | ||
3181 | __setparam_dl(p, attr); | ||
3182 | else if (fair_policy(policy)) | ||
3183 | p->static_prio = NICE_TO_PRIO(attr->sched_nice); | ||
3184 | |||
3185 | /* | ||
3186 | * __sched_setscheduler() ensures attr->sched_priority == 0 when | ||
3187 | * !rt_policy. Always setting this ensures that things like | ||
3188 | * getparam()/getattr() don't report silly values for !rt tasks. | ||
3189 | */ | ||
3190 | p->rt_priority = attr->sched_priority; | ||
3191 | |||
2997 | p->normal_prio = normal_prio(p); | 3192 | p->normal_prio = normal_prio(p); |
2998 | /* we are holding p->pi_lock already */ | ||
2999 | p->prio = rt_mutex_getprio(p); | 3193 | p->prio = rt_mutex_getprio(p); |
3000 | if (rt_prio(p->prio)) | 3194 | |
3195 | if (dl_prio(p->prio)) | ||
3196 | p->sched_class = &dl_sched_class; | ||
3197 | else if (rt_prio(p->prio)) | ||
3001 | p->sched_class = &rt_sched_class; | 3198 | p->sched_class = &rt_sched_class; |
3002 | else | 3199 | else |
3003 | p->sched_class = &fair_sched_class; | 3200 | p->sched_class = &fair_sched_class; |
3201 | |||
3004 | set_load_weight(p); | 3202 | set_load_weight(p); |
3005 | } | 3203 | } |
3006 | 3204 | ||
3205 | static void | ||
3206 | __getparam_dl(struct task_struct *p, struct sched_attr *attr) | ||
3207 | { | ||
3208 | struct sched_dl_entity *dl_se = &p->dl; | ||
3209 | |||
3210 | attr->sched_priority = p->rt_priority; | ||
3211 | attr->sched_runtime = dl_se->dl_runtime; | ||
3212 | attr->sched_deadline = dl_se->dl_deadline; | ||
3213 | attr->sched_period = dl_se->dl_period; | ||
3214 | attr->sched_flags = dl_se->flags; | ||
3215 | } | ||
3216 | |||
3217 | /* | ||
3218 | * This function validates the new parameters of a -deadline task. | ||
3219 | * We ask for the deadline not being zero, and greater or equal | ||
3220 | * than the runtime, as well as the period of being zero or | ||
3221 | * greater than deadline. Furthermore, we have to be sure that | ||
3222 | * user parameters are above the internal resolution (1us); we | ||
3223 | * check sched_runtime only since it is always the smaller one. | ||
3224 | */ | ||
3225 | static bool | ||
3226 | __checkparam_dl(const struct sched_attr *attr) | ||
3227 | { | ||
3228 | return attr && attr->sched_deadline != 0 && | ||
3229 | (attr->sched_period == 0 || | ||
3230 | (s64)(attr->sched_period - attr->sched_deadline) >= 0) && | ||
3231 | (s64)(attr->sched_deadline - attr->sched_runtime ) >= 0 && | ||
3232 | attr->sched_runtime >= (2 << (DL_SCALE - 1)); | ||
3233 | } | ||
3234 | |||
3007 | /* | 3235 | /* |
3008 | * check the target process has a UID that matches the current process's | 3236 | * check the target process has a UID that matches the current process's |
3009 | */ | 3237 | */ |
@@ -3020,10 +3248,12 @@ static bool check_same_owner(struct task_struct *p) | |||
3020 | return match; | 3248 | return match; |
3021 | } | 3249 | } |
3022 | 3250 | ||
3023 | static int __sched_setscheduler(struct task_struct *p, int policy, | 3251 | static int __sched_setscheduler(struct task_struct *p, |
3024 | const struct sched_param *param, bool user) | 3252 | const struct sched_attr *attr, |
3253 | bool user) | ||
3025 | { | 3254 | { |
3026 | int retval, oldprio, oldpolicy = -1, on_rq, running; | 3255 | int retval, oldprio, oldpolicy = -1, on_rq, running; |
3256 | int policy = attr->sched_policy; | ||
3027 | unsigned long flags; | 3257 | unsigned long flags; |
3028 | const struct sched_class *prev_class; | 3258 | const struct sched_class *prev_class; |
3029 | struct rq *rq; | 3259 | struct rq *rq; |
@@ -3037,31 +3267,40 @@ recheck: | |||
3037 | reset_on_fork = p->sched_reset_on_fork; | 3267 | reset_on_fork = p->sched_reset_on_fork; |
3038 | policy = oldpolicy = p->policy; | 3268 | policy = oldpolicy = p->policy; |
3039 | } else { | 3269 | } else { |
3040 | reset_on_fork = !!(policy & SCHED_RESET_ON_FORK); | 3270 | reset_on_fork = !!(attr->sched_flags & SCHED_FLAG_RESET_ON_FORK); |
3041 | policy &= ~SCHED_RESET_ON_FORK; | ||
3042 | 3271 | ||
3043 | if (policy != SCHED_FIFO && policy != SCHED_RR && | 3272 | if (policy != SCHED_DEADLINE && |
3273 | policy != SCHED_FIFO && policy != SCHED_RR && | ||
3044 | policy != SCHED_NORMAL && policy != SCHED_BATCH && | 3274 | policy != SCHED_NORMAL && policy != SCHED_BATCH && |
3045 | policy != SCHED_IDLE) | 3275 | policy != SCHED_IDLE) |
3046 | return -EINVAL; | 3276 | return -EINVAL; |
3047 | } | 3277 | } |
3048 | 3278 | ||
3279 | if (attr->sched_flags & ~(SCHED_FLAG_RESET_ON_FORK)) | ||
3280 | return -EINVAL; | ||
3281 | |||
3049 | /* | 3282 | /* |
3050 | * Valid priorities for SCHED_FIFO and SCHED_RR are | 3283 | * Valid priorities for SCHED_FIFO and SCHED_RR are |
3051 | * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL, | 3284 | * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL, |
3052 | * SCHED_BATCH and SCHED_IDLE is 0. | 3285 | * SCHED_BATCH and SCHED_IDLE is 0. |
3053 | */ | 3286 | */ |
3054 | if (param->sched_priority < 0 || | 3287 | if ((p->mm && attr->sched_priority > MAX_USER_RT_PRIO-1) || |
3055 | (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) || | 3288 | (!p->mm && attr->sched_priority > MAX_RT_PRIO-1)) |
3056 | (!p->mm && param->sched_priority > MAX_RT_PRIO-1)) | ||
3057 | return -EINVAL; | 3289 | return -EINVAL; |
3058 | if (rt_policy(policy) != (param->sched_priority != 0)) | 3290 | if ((dl_policy(policy) && !__checkparam_dl(attr)) || |
3291 | (rt_policy(policy) != (attr->sched_priority != 0))) | ||
3059 | return -EINVAL; | 3292 | return -EINVAL; |
3060 | 3293 | ||
3061 | /* | 3294 | /* |
3062 | * Allow unprivileged RT tasks to decrease priority: | 3295 | * Allow unprivileged RT tasks to decrease priority: |
3063 | */ | 3296 | */ |
3064 | if (user && !capable(CAP_SYS_NICE)) { | 3297 | if (user && !capable(CAP_SYS_NICE)) { |
3298 | if (fair_policy(policy)) { | ||
3299 | if (attr->sched_nice < TASK_NICE(p) && | ||
3300 | !can_nice(p, attr->sched_nice)) | ||
3301 | return -EPERM; | ||
3302 | } | ||
3303 | |||
3065 | if (rt_policy(policy)) { | 3304 | if (rt_policy(policy)) { |
3066 | unsigned long rlim_rtprio = | 3305 | unsigned long rlim_rtprio = |
3067 | task_rlimit(p, RLIMIT_RTPRIO); | 3306 | task_rlimit(p, RLIMIT_RTPRIO); |
@@ -3071,8 +3310,8 @@ recheck: | |||
3071 | return -EPERM; | 3310 | return -EPERM; |
3072 | 3311 | ||
3073 | /* can't increase priority */ | 3312 | /* can't increase priority */ |
3074 | if (param->sched_priority > p->rt_priority && | 3313 | if (attr->sched_priority > p->rt_priority && |
3075 | param->sched_priority > rlim_rtprio) | 3314 | attr->sched_priority > rlim_rtprio) |
3076 | return -EPERM; | 3315 | return -EPERM; |
3077 | } | 3316 | } |
3078 | 3317 | ||
@@ -3120,14 +3359,21 @@ recheck: | |||
3120 | /* | 3359 | /* |
3121 | * If not changing anything there's no need to proceed further: | 3360 | * If not changing anything there's no need to proceed further: |
3122 | */ | 3361 | */ |
3123 | if (unlikely(policy == p->policy && (!rt_policy(policy) || | 3362 | if (unlikely(policy == p->policy)) { |
3124 | param->sched_priority == p->rt_priority))) { | 3363 | if (fair_policy(policy) && attr->sched_nice != TASK_NICE(p)) |
3364 | goto change; | ||
3365 | if (rt_policy(policy) && attr->sched_priority != p->rt_priority) | ||
3366 | goto change; | ||
3367 | if (dl_policy(policy)) | ||
3368 | goto change; | ||
3369 | |||
3125 | task_rq_unlock(rq, p, &flags); | 3370 | task_rq_unlock(rq, p, &flags); |
3126 | return 0; | 3371 | return 0; |
3127 | } | 3372 | } |
3373 | change: | ||
3128 | 3374 | ||
3129 | #ifdef CONFIG_RT_GROUP_SCHED | ||
3130 | if (user) { | 3375 | if (user) { |
3376 | #ifdef CONFIG_RT_GROUP_SCHED | ||
3131 | /* | 3377 | /* |
3132 | * Do not allow realtime tasks into groups that have no runtime | 3378 | * Do not allow realtime tasks into groups that have no runtime |
3133 | * assigned. | 3379 | * assigned. |
@@ -3138,8 +3384,24 @@ recheck: | |||
3138 | task_rq_unlock(rq, p, &flags); | 3384 | task_rq_unlock(rq, p, &flags); |
3139 | return -EPERM; | 3385 | return -EPERM; |
3140 | } | 3386 | } |
3141 | } | ||
3142 | #endif | 3387 | #endif |
3388 | #ifdef CONFIG_SMP | ||
3389 | if (dl_bandwidth_enabled() && dl_policy(policy)) { | ||
3390 | cpumask_t *span = rq->rd->span; | ||
3391 | |||
3392 | /* | ||
3393 | * Don't allow tasks with an affinity mask smaller than | ||
3394 | * the entire root_domain to become SCHED_DEADLINE. We | ||
3395 | * will also fail if there's no bandwidth available. | ||
3396 | */ | ||
3397 | if (!cpumask_subset(span, &p->cpus_allowed) || | ||
3398 | rq->rd->dl_bw.bw == 0) { | ||
3399 | task_rq_unlock(rq, p, &flags); | ||
3400 | return -EPERM; | ||
3401 | } | ||
3402 | } | ||
3403 | #endif | ||
3404 | } | ||
3143 | 3405 | ||
3144 | /* recheck policy now with rq lock held */ | 3406 | /* recheck policy now with rq lock held */ |
3145 | if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { | 3407 | if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { |
@@ -3147,6 +3409,17 @@ recheck: | |||
3147 | task_rq_unlock(rq, p, &flags); | 3409 | task_rq_unlock(rq, p, &flags); |
3148 | goto recheck; | 3410 | goto recheck; |
3149 | } | 3411 | } |
3412 | |||
3413 | /* | ||
3414 | * If setscheduling to SCHED_DEADLINE (or changing the parameters | ||
3415 | * of a SCHED_DEADLINE task) we need to check if enough bandwidth | ||
3416 | * is available. | ||
3417 | */ | ||
3418 | if ((dl_policy(policy) || dl_task(p)) && dl_overflow(p, policy, attr)) { | ||
3419 | task_rq_unlock(rq, p, &flags); | ||
3420 | return -EBUSY; | ||
3421 | } | ||
3422 | |||
3150 | on_rq = p->on_rq; | 3423 | on_rq = p->on_rq; |
3151 | running = task_current(rq, p); | 3424 | running = task_current(rq, p); |
3152 | if (on_rq) | 3425 | if (on_rq) |
@@ -3158,7 +3431,7 @@ recheck: | |||
3158 | 3431 | ||
3159 | oldprio = p->prio; | 3432 | oldprio = p->prio; |
3160 | prev_class = p->sched_class; | 3433 | prev_class = p->sched_class; |
3161 | __setscheduler(rq, p, policy, param->sched_priority); | 3434 | __setscheduler(rq, p, attr); |
3162 | 3435 | ||
3163 | if (running) | 3436 | if (running) |
3164 | p->sched_class->set_curr_task(rq); | 3437 | p->sched_class->set_curr_task(rq); |
@@ -3173,6 +3446,26 @@ recheck: | |||
3173 | return 0; | 3446 | return 0; |
3174 | } | 3447 | } |
3175 | 3448 | ||
3449 | static int _sched_setscheduler(struct task_struct *p, int policy, | ||
3450 | const struct sched_param *param, bool check) | ||
3451 | { | ||
3452 | struct sched_attr attr = { | ||
3453 | .sched_policy = policy, | ||
3454 | .sched_priority = param->sched_priority, | ||
3455 | .sched_nice = PRIO_TO_NICE(p->static_prio), | ||
3456 | }; | ||
3457 | |||
3458 | /* | ||
3459 | * Fixup the legacy SCHED_RESET_ON_FORK hack | ||
3460 | */ | ||
3461 | if (policy & SCHED_RESET_ON_FORK) { | ||
3462 | attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; | ||
3463 | policy &= ~SCHED_RESET_ON_FORK; | ||
3464 | attr.sched_policy = policy; | ||
3465 | } | ||
3466 | |||
3467 | return __sched_setscheduler(p, &attr, check); | ||
3468 | } | ||
3176 | /** | 3469 | /** |
3177 | * sched_setscheduler - change the scheduling policy and/or RT priority of a thread. | 3470 | * sched_setscheduler - change the scheduling policy and/or RT priority of a thread. |
3178 | * @p: the task in question. | 3471 | * @p: the task in question. |
@@ -3186,10 +3479,16 @@ recheck: | |||
3186 | int sched_setscheduler(struct task_struct *p, int policy, | 3479 | int sched_setscheduler(struct task_struct *p, int policy, |
3187 | const struct sched_param *param) | 3480 | const struct sched_param *param) |
3188 | { | 3481 | { |
3189 | return __sched_setscheduler(p, policy, param, true); | 3482 | return _sched_setscheduler(p, policy, param, true); |
3190 | } | 3483 | } |
3191 | EXPORT_SYMBOL_GPL(sched_setscheduler); | 3484 | EXPORT_SYMBOL_GPL(sched_setscheduler); |
3192 | 3485 | ||
3486 | int sched_setattr(struct task_struct *p, const struct sched_attr *attr) | ||
3487 | { | ||
3488 | return __sched_setscheduler(p, attr, true); | ||
3489 | } | ||
3490 | EXPORT_SYMBOL_GPL(sched_setattr); | ||
3491 | |||
3193 | /** | 3492 | /** |
3194 | * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace. | 3493 | * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace. |
3195 | * @p: the task in question. | 3494 | * @p: the task in question. |
@@ -3206,7 +3505,7 @@ EXPORT_SYMBOL_GPL(sched_setscheduler); | |||
3206 | int sched_setscheduler_nocheck(struct task_struct *p, int policy, | 3505 | int sched_setscheduler_nocheck(struct task_struct *p, int policy, |
3207 | const struct sched_param *param) | 3506 | const struct sched_param *param) |
3208 | { | 3507 | { |
3209 | return __sched_setscheduler(p, policy, param, false); | 3508 | return _sched_setscheduler(p, policy, param, false); |
3210 | } | 3509 | } |
3211 | 3510 | ||
3212 | static int | 3511 | static int |
@@ -3231,6 +3530,79 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) | |||
3231 | return retval; | 3530 | return retval; |
3232 | } | 3531 | } |
3233 | 3532 | ||
3533 | /* | ||
3534 | * Mimics kernel/events/core.c perf_copy_attr(). | ||
3535 | */ | ||
3536 | static int sched_copy_attr(struct sched_attr __user *uattr, | ||
3537 | struct sched_attr *attr) | ||
3538 | { | ||
3539 | u32 size; | ||
3540 | int ret; | ||
3541 | |||
3542 | if (!access_ok(VERIFY_WRITE, uattr, SCHED_ATTR_SIZE_VER0)) | ||
3543 | return -EFAULT; | ||
3544 | |||
3545 | /* | ||
3546 | * zero the full structure, so that a short copy will be nice. | ||
3547 | */ | ||
3548 | memset(attr, 0, sizeof(*attr)); | ||
3549 | |||
3550 | ret = get_user(size, &uattr->size); | ||
3551 | if (ret) | ||
3552 | return ret; | ||
3553 | |||
3554 | if (size > PAGE_SIZE) /* silly large */ | ||
3555 | goto err_size; | ||
3556 | |||
3557 | if (!size) /* abi compat */ | ||
3558 | size = SCHED_ATTR_SIZE_VER0; | ||
3559 | |||
3560 | if (size < SCHED_ATTR_SIZE_VER0) | ||
3561 | goto err_size; | ||
3562 | |||
3563 | /* | ||
3564 | * If we're handed a bigger struct than we know of, | ||
3565 | * ensure all the unknown bits are 0 - i.e. new | ||
3566 | * user-space does not rely on any kernel feature | ||
3567 | * extensions we dont know about yet. | ||
3568 | */ | ||
3569 | if (size > sizeof(*attr)) { | ||
3570 | unsigned char __user *addr; | ||
3571 | unsigned char __user *end; | ||
3572 | unsigned char val; | ||
3573 | |||
3574 | addr = (void __user *)uattr + sizeof(*attr); | ||
3575 | end = (void __user *)uattr + size; | ||
3576 | |||
3577 | for (; addr < end; addr++) { | ||
3578 | ret = get_user(val, addr); | ||
3579 | if (ret) | ||
3580 | return ret; | ||
3581 | if (val) | ||
3582 | goto err_size; | ||
3583 | } | ||
3584 | size = sizeof(*attr); | ||
3585 | } | ||
3586 | |||
3587 | ret = copy_from_user(attr, uattr, size); | ||
3588 | if (ret) | ||
3589 | return -EFAULT; | ||
3590 | |||
3591 | /* | ||
3592 | * XXX: do we want to be lenient like existing syscalls; or do we want | ||
3593 | * to be strict and return an error on out-of-bounds values? | ||
3594 | */ | ||
3595 | attr->sched_nice = clamp(attr->sched_nice, -20, 19); | ||
3596 | |||
3597 | out: | ||
3598 | return ret; | ||
3599 | |||
3600 | err_size: | ||
3601 | put_user(sizeof(*attr), &uattr->size); | ||
3602 | ret = -E2BIG; | ||
3603 | goto out; | ||
3604 | } | ||
3605 | |||
3234 | /** | 3606 | /** |
3235 | * sys_sched_setscheduler - set/change the scheduler policy and RT priority | 3607 | * sys_sched_setscheduler - set/change the scheduler policy and RT priority |
3236 | * @pid: the pid in question. | 3608 | * @pid: the pid in question. |
@@ -3262,6 +3634,33 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) | |||
3262 | } | 3634 | } |
3263 | 3635 | ||
3264 | /** | 3636 | /** |
3637 | * sys_sched_setattr - same as above, but with extended sched_attr | ||
3638 | * @pid: the pid in question. | ||
3639 | * @uattr: structure containing the extended parameters. | ||
3640 | */ | ||
3641 | SYSCALL_DEFINE2(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr) | ||
3642 | { | ||
3643 | struct sched_attr attr; | ||
3644 | struct task_struct *p; | ||
3645 | int retval; | ||
3646 | |||
3647 | if (!uattr || pid < 0) | ||
3648 | return -EINVAL; | ||
3649 | |||
3650 | if (sched_copy_attr(uattr, &attr)) | ||
3651 | return -EFAULT; | ||
3652 | |||
3653 | rcu_read_lock(); | ||
3654 | retval = -ESRCH; | ||
3655 | p = find_process_by_pid(pid); | ||
3656 | if (p != NULL) | ||
3657 | retval = sched_setattr(p, &attr); | ||
3658 | rcu_read_unlock(); | ||
3659 | |||
3660 | return retval; | ||
3661 | } | ||
3662 | |||
3663 | /** | ||
3265 | * sys_sched_getscheduler - get the policy (scheduling class) of a thread | 3664 | * sys_sched_getscheduler - get the policy (scheduling class) of a thread |
3266 | * @pid: the pid in question. | 3665 | * @pid: the pid in question. |
3267 | * | 3666 | * |
@@ -3316,6 +3715,10 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) | |||
3316 | if (retval) | 3715 | if (retval) |
3317 | goto out_unlock; | 3716 | goto out_unlock; |
3318 | 3717 | ||
3718 | if (task_has_dl_policy(p)) { | ||
3719 | retval = -EINVAL; | ||
3720 | goto out_unlock; | ||
3721 | } | ||
3319 | lp.sched_priority = p->rt_priority; | 3722 | lp.sched_priority = p->rt_priority; |
3320 | rcu_read_unlock(); | 3723 | rcu_read_unlock(); |
3321 | 3724 | ||
@@ -3331,6 +3734,96 @@ out_unlock: | |||
3331 | return retval; | 3734 | return retval; |
3332 | } | 3735 | } |
3333 | 3736 | ||
3737 | static int sched_read_attr(struct sched_attr __user *uattr, | ||
3738 | struct sched_attr *attr, | ||
3739 | unsigned int usize) | ||
3740 | { | ||
3741 | int ret; | ||
3742 | |||
3743 | if (!access_ok(VERIFY_WRITE, uattr, usize)) | ||
3744 | return -EFAULT; | ||
3745 | |||
3746 | /* | ||
3747 | * If we're handed a smaller struct than we know of, | ||
3748 | * ensure all the unknown bits are 0 - i.e. old | ||
3749 | * user-space does not get uncomplete information. | ||
3750 | */ | ||
3751 | if (usize < sizeof(*attr)) { | ||
3752 | unsigned char *addr; | ||
3753 | unsigned char *end; | ||
3754 | |||
3755 | addr = (void *)attr + usize; | ||
3756 | end = (void *)attr + sizeof(*attr); | ||
3757 | |||
3758 | for (; addr < end; addr++) { | ||
3759 | if (*addr) | ||
3760 | goto err_size; | ||
3761 | } | ||
3762 | |||
3763 | attr->size = usize; | ||
3764 | } | ||
3765 | |||
3766 | ret = copy_to_user(uattr, attr, usize); | ||
3767 | if (ret) | ||
3768 | return -EFAULT; | ||
3769 | |||
3770 | out: | ||
3771 | return ret; | ||
3772 | |||
3773 | err_size: | ||
3774 | ret = -E2BIG; | ||
3775 | goto out; | ||
3776 | } | ||
3777 | |||
3778 | /** | ||
3779 | * sys_sched_getattr - similar to sched_getparam, but with sched_attr | ||
3780 | * @pid: the pid in question. | ||
3781 | * @uattr: structure containing the extended parameters. | ||
3782 | * @size: sizeof(attr) for fwd/bwd comp. | ||
3783 | */ | ||
3784 | SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, | ||
3785 | unsigned int, size) | ||
3786 | { | ||
3787 | struct sched_attr attr = { | ||
3788 | .size = sizeof(struct sched_attr), | ||
3789 | }; | ||
3790 | struct task_struct *p; | ||
3791 | int retval; | ||
3792 | |||
3793 | if (!uattr || pid < 0 || size > PAGE_SIZE || | ||
3794 | size < SCHED_ATTR_SIZE_VER0) | ||
3795 | return -EINVAL; | ||
3796 | |||
3797 | rcu_read_lock(); | ||
3798 | p = find_process_by_pid(pid); | ||
3799 | retval = -ESRCH; | ||
3800 | if (!p) | ||
3801 | goto out_unlock; | ||
3802 | |||
3803 | retval = security_task_getscheduler(p); | ||
3804 | if (retval) | ||
3805 | goto out_unlock; | ||
3806 | |||
3807 | attr.sched_policy = p->policy; | ||
3808 | if (p->sched_reset_on_fork) | ||
3809 | attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; | ||
3810 | if (task_has_dl_policy(p)) | ||
3811 | __getparam_dl(p, &attr); | ||
3812 | else if (task_has_rt_policy(p)) | ||
3813 | attr.sched_priority = p->rt_priority; | ||
3814 | else | ||
3815 | attr.sched_nice = TASK_NICE(p); | ||
3816 | |||
3817 | rcu_read_unlock(); | ||
3818 | |||
3819 | retval = sched_read_attr(uattr, &attr, size); | ||
3820 | return retval; | ||
3821 | |||
3822 | out_unlock: | ||
3823 | rcu_read_unlock(); | ||
3824 | return retval; | ||
3825 | } | ||
3826 | |||
3334 | long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) | 3827 | long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) |
3335 | { | 3828 | { |
3336 | cpumask_var_t cpus_allowed, new_mask; | 3829 | cpumask_var_t cpus_allowed, new_mask; |
@@ -3375,8 +3868,26 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) | |||
3375 | if (retval) | 3868 | if (retval) |
3376 | goto out_unlock; | 3869 | goto out_unlock; |
3377 | 3870 | ||
3871 | |||
3378 | cpuset_cpus_allowed(p, cpus_allowed); | 3872 | cpuset_cpus_allowed(p, cpus_allowed); |
3379 | cpumask_and(new_mask, in_mask, cpus_allowed); | 3873 | cpumask_and(new_mask, in_mask, cpus_allowed); |
3874 | |||
3875 | /* | ||
3876 | * Since bandwidth control happens on root_domain basis, | ||
3877 | * if admission test is enabled, we only admit -deadline | ||
3878 | * tasks allowed to run on all the CPUs in the task's | ||
3879 | * root_domain. | ||
3880 | */ | ||
3881 | #ifdef CONFIG_SMP | ||
3882 | if (task_has_dl_policy(p)) { | ||
3883 | const struct cpumask *span = task_rq(p)->rd->span; | ||
3884 | |||
3885 | if (dl_bandwidth_enabled() && !cpumask_subset(span, new_mask)) { | ||
3886 | retval = -EBUSY; | ||
3887 | goto out_unlock; | ||
3888 | } | ||
3889 | } | ||
3890 | #endif | ||
3380 | again: | 3891 | again: |
3381 | retval = set_cpus_allowed_ptr(p, new_mask); | 3892 | retval = set_cpus_allowed_ptr(p, new_mask); |
3382 | 3893 | ||
@@ -3653,7 +4164,7 @@ again: | |||
3653 | } | 4164 | } |
3654 | 4165 | ||
3655 | double_rq_lock(rq, p_rq); | 4166 | double_rq_lock(rq, p_rq); |
3656 | while (task_rq(p) != p_rq) { | 4167 | if (task_rq(p) != p_rq) { |
3657 | double_rq_unlock(rq, p_rq); | 4168 | double_rq_unlock(rq, p_rq); |
3658 | goto again; | 4169 | goto again; |
3659 | } | 4170 | } |
@@ -3742,6 +4253,7 @@ SYSCALL_DEFINE1(sched_get_priority_max, int, policy) | |||
3742 | case SCHED_RR: | 4253 | case SCHED_RR: |
3743 | ret = MAX_USER_RT_PRIO-1; | 4254 | ret = MAX_USER_RT_PRIO-1; |
3744 | break; | 4255 | break; |
4256 | case SCHED_DEADLINE: | ||
3745 | case SCHED_NORMAL: | 4257 | case SCHED_NORMAL: |
3746 | case SCHED_BATCH: | 4258 | case SCHED_BATCH: |
3747 | case SCHED_IDLE: | 4259 | case SCHED_IDLE: |
@@ -3768,6 +4280,7 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy) | |||
3768 | case SCHED_RR: | 4280 | case SCHED_RR: |
3769 | ret = 1; | 4281 | ret = 1; |
3770 | break; | 4282 | break; |
4283 | case SCHED_DEADLINE: | ||
3771 | case SCHED_NORMAL: | 4284 | case SCHED_NORMAL: |
3772 | case SCHED_BATCH: | 4285 | case SCHED_BATCH: |
3773 | case SCHED_IDLE: | 4286 | case SCHED_IDLE: |
@@ -4514,13 +5027,31 @@ static int sched_cpu_active(struct notifier_block *nfb, | |||
4514 | static int sched_cpu_inactive(struct notifier_block *nfb, | 5027 | static int sched_cpu_inactive(struct notifier_block *nfb, |
4515 | unsigned long action, void *hcpu) | 5028 | unsigned long action, void *hcpu) |
4516 | { | 5029 | { |
5030 | unsigned long flags; | ||
5031 | long cpu = (long)hcpu; | ||
5032 | |||
4517 | switch (action & ~CPU_TASKS_FROZEN) { | 5033 | switch (action & ~CPU_TASKS_FROZEN) { |
4518 | case CPU_DOWN_PREPARE: | 5034 | case CPU_DOWN_PREPARE: |
4519 | set_cpu_active((long)hcpu, false); | 5035 | set_cpu_active(cpu, false); |
5036 | |||
5037 | /* explicitly allow suspend */ | ||
5038 | if (!(action & CPU_TASKS_FROZEN)) { | ||
5039 | struct dl_bw *dl_b = dl_bw_of(cpu); | ||
5040 | bool overflow; | ||
5041 | int cpus; | ||
5042 | |||
5043 | raw_spin_lock_irqsave(&dl_b->lock, flags); | ||
5044 | cpus = dl_bw_cpus(cpu); | ||
5045 | overflow = __dl_overflow(dl_b, cpus, 0, 0); | ||
5046 | raw_spin_unlock_irqrestore(&dl_b->lock, flags); | ||
5047 | |||
5048 | if (overflow) | ||
5049 | return notifier_from_errno(-EBUSY); | ||
5050 | } | ||
4520 | return NOTIFY_OK; | 5051 | return NOTIFY_OK; |
4521 | default: | ||
4522 | return NOTIFY_DONE; | ||
4523 | } | 5052 | } |
5053 | |||
5054 | return NOTIFY_DONE; | ||
4524 | } | 5055 | } |
4525 | 5056 | ||
4526 | static int __init migration_init(void) | 5057 | static int __init migration_init(void) |
@@ -4739,6 +5270,8 @@ static void free_rootdomain(struct rcu_head *rcu) | |||
4739 | struct root_domain *rd = container_of(rcu, struct root_domain, rcu); | 5270 | struct root_domain *rd = container_of(rcu, struct root_domain, rcu); |
4740 | 5271 | ||
4741 | cpupri_cleanup(&rd->cpupri); | 5272 | cpupri_cleanup(&rd->cpupri); |
5273 | cpudl_cleanup(&rd->cpudl); | ||
5274 | free_cpumask_var(rd->dlo_mask); | ||
4742 | free_cpumask_var(rd->rto_mask); | 5275 | free_cpumask_var(rd->rto_mask); |
4743 | free_cpumask_var(rd->online); | 5276 | free_cpumask_var(rd->online); |
4744 | free_cpumask_var(rd->span); | 5277 | free_cpumask_var(rd->span); |
@@ -4790,8 +5323,14 @@ static int init_rootdomain(struct root_domain *rd) | |||
4790 | goto out; | 5323 | goto out; |
4791 | if (!alloc_cpumask_var(&rd->online, GFP_KERNEL)) | 5324 | if (!alloc_cpumask_var(&rd->online, GFP_KERNEL)) |
4792 | goto free_span; | 5325 | goto free_span; |
4793 | if (!alloc_cpumask_var(&rd->rto_mask, GFP_KERNEL)) | 5326 | if (!alloc_cpumask_var(&rd->dlo_mask, GFP_KERNEL)) |
4794 | goto free_online; | 5327 | goto free_online; |
5328 | if (!alloc_cpumask_var(&rd->rto_mask, GFP_KERNEL)) | ||
5329 | goto free_dlo_mask; | ||
5330 | |||
5331 | init_dl_bw(&rd->dl_bw); | ||
5332 | if (cpudl_init(&rd->cpudl) != 0) | ||
5333 | goto free_dlo_mask; | ||
4795 | 5334 | ||
4796 | if (cpupri_init(&rd->cpupri) != 0) | 5335 | if (cpupri_init(&rd->cpupri) != 0) |
4797 | goto free_rto_mask; | 5336 | goto free_rto_mask; |
@@ -4799,6 +5338,8 @@ static int init_rootdomain(struct root_domain *rd) | |||
4799 | 5338 | ||
4800 | free_rto_mask: | 5339 | free_rto_mask: |
4801 | free_cpumask_var(rd->rto_mask); | 5340 | free_cpumask_var(rd->rto_mask); |
5341 | free_dlo_mask: | ||
5342 | free_cpumask_var(rd->dlo_mask); | ||
4802 | free_online: | 5343 | free_online: |
4803 | free_cpumask_var(rd->online); | 5344 | free_cpumask_var(rd->online); |
4804 | free_span: | 5345 | free_span: |
@@ -6150,6 +6691,7 @@ void __init sched_init_smp(void) | |||
6150 | free_cpumask_var(non_isolated_cpus); | 6691 | free_cpumask_var(non_isolated_cpus); |
6151 | 6692 | ||
6152 | init_sched_rt_class(); | 6693 | init_sched_rt_class(); |
6694 | init_sched_dl_class(); | ||
6153 | } | 6695 | } |
6154 | #else | 6696 | #else |
6155 | void __init sched_init_smp(void) | 6697 | void __init sched_init_smp(void) |
@@ -6219,13 +6761,15 @@ void __init sched_init(void) | |||
6219 | #endif /* CONFIG_CPUMASK_OFFSTACK */ | 6761 | #endif /* CONFIG_CPUMASK_OFFSTACK */ |
6220 | } | 6762 | } |
6221 | 6763 | ||
6764 | init_rt_bandwidth(&def_rt_bandwidth, | ||
6765 | global_rt_period(), global_rt_runtime()); | ||
6766 | init_dl_bandwidth(&def_dl_bandwidth, | ||
6767 | global_rt_period(), global_rt_runtime()); | ||
6768 | |||
6222 | #ifdef CONFIG_SMP | 6769 | #ifdef CONFIG_SMP |
6223 | init_defrootdomain(); | 6770 | init_defrootdomain(); |
6224 | #endif | 6771 | #endif |
6225 | 6772 | ||
6226 | init_rt_bandwidth(&def_rt_bandwidth, | ||
6227 | global_rt_period(), global_rt_runtime()); | ||
6228 | |||
6229 | #ifdef CONFIG_RT_GROUP_SCHED | 6773 | #ifdef CONFIG_RT_GROUP_SCHED |
6230 | init_rt_bandwidth(&root_task_group.rt_bandwidth, | 6774 | init_rt_bandwidth(&root_task_group.rt_bandwidth, |
6231 | global_rt_period(), global_rt_runtime()); | 6775 | global_rt_period(), global_rt_runtime()); |
@@ -6249,6 +6793,7 @@ void __init sched_init(void) | |||
6249 | rq->calc_load_update = jiffies + LOAD_FREQ; | 6793 | rq->calc_load_update = jiffies + LOAD_FREQ; |
6250 | init_cfs_rq(&rq->cfs); | 6794 | init_cfs_rq(&rq->cfs); |
6251 | init_rt_rq(&rq->rt, rq); | 6795 | init_rt_rq(&rq->rt, rq); |
6796 | init_dl_rq(&rq->dl, rq); | ||
6252 | #ifdef CONFIG_FAIR_GROUP_SCHED | 6797 | #ifdef CONFIG_FAIR_GROUP_SCHED |
6253 | root_task_group.shares = ROOT_TASK_GROUP_LOAD; | 6798 | root_task_group.shares = ROOT_TASK_GROUP_LOAD; |
6254 | INIT_LIST_HEAD(&rq->leaf_cfs_rq_list); | 6799 | INIT_LIST_HEAD(&rq->leaf_cfs_rq_list); |
@@ -6320,10 +6865,6 @@ void __init sched_init(void) | |||
6320 | INIT_HLIST_HEAD(&init_task.preempt_notifiers); | 6865 | INIT_HLIST_HEAD(&init_task.preempt_notifiers); |
6321 | #endif | 6866 | #endif |
6322 | 6867 | ||
6323 | #ifdef CONFIG_RT_MUTEXES | ||
6324 | plist_head_init(&init_task.pi_waiters); | ||
6325 | #endif | ||
6326 | |||
6327 | /* | 6868 | /* |
6328 | * The boot idle thread does lazy MMU switching as well: | 6869 | * The boot idle thread does lazy MMU switching as well: |
6329 | */ | 6870 | */ |
@@ -6397,13 +6938,16 @@ EXPORT_SYMBOL(__might_sleep); | |||
6397 | static void normalize_task(struct rq *rq, struct task_struct *p) | 6938 | static void normalize_task(struct rq *rq, struct task_struct *p) |
6398 | { | 6939 | { |
6399 | const struct sched_class *prev_class = p->sched_class; | 6940 | const struct sched_class *prev_class = p->sched_class; |
6941 | struct sched_attr attr = { | ||
6942 | .sched_policy = SCHED_NORMAL, | ||
6943 | }; | ||
6400 | int old_prio = p->prio; | 6944 | int old_prio = p->prio; |
6401 | int on_rq; | 6945 | int on_rq; |
6402 | 6946 | ||
6403 | on_rq = p->on_rq; | 6947 | on_rq = p->on_rq; |
6404 | if (on_rq) | 6948 | if (on_rq) |
6405 | dequeue_task(rq, p, 0); | 6949 | dequeue_task(rq, p, 0); |
6406 | __setscheduler(rq, p, SCHED_NORMAL, 0); | 6950 | __setscheduler(rq, p, &attr); |
6407 | if (on_rq) { | 6951 | if (on_rq) { |
6408 | enqueue_task(rq, p, 0); | 6952 | enqueue_task(rq, p, 0); |
6409 | resched_task(rq->curr); | 6953 | resched_task(rq->curr); |
@@ -6433,7 +6977,7 @@ void normalize_rt_tasks(void) | |||
6433 | p->se.statistics.block_start = 0; | 6977 | p->se.statistics.block_start = 0; |
6434 | #endif | 6978 | #endif |
6435 | 6979 | ||
6436 | if (!rt_task(p)) { | 6980 | if (!dl_task(p) && !rt_task(p)) { |
6437 | /* | 6981 | /* |
6438 | * Renice negative nice level userspace | 6982 | * Renice negative nice level userspace |
6439 | * tasks back to 0: | 6983 | * tasks back to 0: |
@@ -6628,16 +7172,6 @@ void sched_move_task(struct task_struct *tsk) | |||
6628 | } | 7172 | } |
6629 | #endif /* CONFIG_CGROUP_SCHED */ | 7173 | #endif /* CONFIG_CGROUP_SCHED */ |
6630 | 7174 | ||
6631 | #if defined(CONFIG_RT_GROUP_SCHED) || defined(CONFIG_CFS_BANDWIDTH) | ||
6632 | static unsigned long to_ratio(u64 period, u64 runtime) | ||
6633 | { | ||
6634 | if (runtime == RUNTIME_INF) | ||
6635 | return 1ULL << 20; | ||
6636 | |||
6637 | return div64_u64(runtime << 20, period); | ||
6638 | } | ||
6639 | #endif | ||
6640 | |||
6641 | #ifdef CONFIG_RT_GROUP_SCHED | 7175 | #ifdef CONFIG_RT_GROUP_SCHED |
6642 | /* | 7176 | /* |
6643 | * Ensure that the real time constraints are schedulable. | 7177 | * Ensure that the real time constraints are schedulable. |
@@ -6811,24 +7345,13 @@ static long sched_group_rt_period(struct task_group *tg) | |||
6811 | do_div(rt_period_us, NSEC_PER_USEC); | 7345 | do_div(rt_period_us, NSEC_PER_USEC); |
6812 | return rt_period_us; | 7346 | return rt_period_us; |
6813 | } | 7347 | } |
7348 | #endif /* CONFIG_RT_GROUP_SCHED */ | ||
6814 | 7349 | ||
7350 | #ifdef CONFIG_RT_GROUP_SCHED | ||
6815 | static int sched_rt_global_constraints(void) | 7351 | static int sched_rt_global_constraints(void) |
6816 | { | 7352 | { |
6817 | u64 runtime, period; | ||
6818 | int ret = 0; | 7353 | int ret = 0; |
6819 | 7354 | ||
6820 | if (sysctl_sched_rt_period <= 0) | ||
6821 | return -EINVAL; | ||
6822 | |||
6823 | runtime = global_rt_runtime(); | ||
6824 | period = global_rt_period(); | ||
6825 | |||
6826 | /* | ||
6827 | * Sanity check on the sysctl variables. | ||
6828 | */ | ||
6829 | if (runtime > period && runtime != RUNTIME_INF) | ||
6830 | return -EINVAL; | ||
6831 | |||
6832 | mutex_lock(&rt_constraints_mutex); | 7355 | mutex_lock(&rt_constraints_mutex); |
6833 | read_lock(&tasklist_lock); | 7356 | read_lock(&tasklist_lock); |
6834 | ret = __rt_schedulable(NULL, 0, 0); | 7357 | ret = __rt_schedulable(NULL, 0, 0); |
@@ -6851,17 +7374,7 @@ static int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk) | |||
6851 | static int sched_rt_global_constraints(void) | 7374 | static int sched_rt_global_constraints(void) |
6852 | { | 7375 | { |
6853 | unsigned long flags; | 7376 | unsigned long flags; |
6854 | int i; | 7377 | int i, ret = 0; |
6855 | |||
6856 | if (sysctl_sched_rt_period <= 0) | ||
6857 | return -EINVAL; | ||
6858 | |||
6859 | /* | ||
6860 | * There's always some RT tasks in the root group | ||
6861 | * -- migration, kstopmachine etc.. | ||
6862 | */ | ||
6863 | if (sysctl_sched_rt_runtime == 0) | ||
6864 | return -EBUSY; | ||
6865 | 7378 | ||
6866 | raw_spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags); | 7379 | raw_spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags); |
6867 | for_each_possible_cpu(i) { | 7380 | for_each_possible_cpu(i) { |
@@ -6873,36 +7386,88 @@ static int sched_rt_global_constraints(void) | |||
6873 | } | 7386 | } |
6874 | raw_spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags); | 7387 | raw_spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags); |
6875 | 7388 | ||
6876 | return 0; | 7389 | return ret; |
6877 | } | 7390 | } |
6878 | #endif /* CONFIG_RT_GROUP_SCHED */ | 7391 | #endif /* CONFIG_RT_GROUP_SCHED */ |
6879 | 7392 | ||
6880 | int sched_rr_handler(struct ctl_table *table, int write, | 7393 | static int sched_dl_global_constraints(void) |
6881 | void __user *buffer, size_t *lenp, | ||
6882 | loff_t *ppos) | ||
6883 | { | 7394 | { |
6884 | int ret; | 7395 | u64 runtime = global_rt_runtime(); |
6885 | static DEFINE_MUTEX(mutex); | 7396 | u64 period = global_rt_period(); |
7397 | u64 new_bw = to_ratio(period, runtime); | ||
7398 | int cpu, ret = 0; | ||
6886 | 7399 | ||
6887 | mutex_lock(&mutex); | 7400 | /* |
6888 | ret = proc_dointvec(table, write, buffer, lenp, ppos); | 7401 | * Here we want to check the bandwidth not being set to some |
6889 | /* make sure that internally we keep jiffies */ | 7402 | * value smaller than the currently allocated bandwidth in |
6890 | /* also, writing zero resets timeslice to default */ | 7403 | * any of the root_domains. |
6891 | if (!ret && write) { | 7404 | * |
6892 | sched_rr_timeslice = sched_rr_timeslice <= 0 ? | 7405 | * FIXME: Cycling on all the CPUs is overdoing, but simpler than |
6893 | RR_TIMESLICE : msecs_to_jiffies(sched_rr_timeslice); | 7406 | * cycling on root_domains... Discussion on different/better |
7407 | * solutions is welcome! | ||
7408 | */ | ||
7409 | for_each_possible_cpu(cpu) { | ||
7410 | struct dl_bw *dl_b = dl_bw_of(cpu); | ||
7411 | |||
7412 | raw_spin_lock(&dl_b->lock); | ||
7413 | if (new_bw < dl_b->total_bw) | ||
7414 | ret = -EBUSY; | ||
7415 | raw_spin_unlock(&dl_b->lock); | ||
7416 | |||
7417 | if (ret) | ||
7418 | break; | ||
6894 | } | 7419 | } |
6895 | mutex_unlock(&mutex); | 7420 | |
6896 | return ret; | 7421 | return ret; |
6897 | } | 7422 | } |
6898 | 7423 | ||
7424 | static void sched_dl_do_global(void) | ||
7425 | { | ||
7426 | u64 new_bw = -1; | ||
7427 | int cpu; | ||
7428 | |||
7429 | def_dl_bandwidth.dl_period = global_rt_period(); | ||
7430 | def_dl_bandwidth.dl_runtime = global_rt_runtime(); | ||
7431 | |||
7432 | if (global_rt_runtime() != RUNTIME_INF) | ||
7433 | new_bw = to_ratio(global_rt_period(), global_rt_runtime()); | ||
7434 | |||
7435 | /* | ||
7436 | * FIXME: As above... | ||
7437 | */ | ||
7438 | for_each_possible_cpu(cpu) { | ||
7439 | struct dl_bw *dl_b = dl_bw_of(cpu); | ||
7440 | |||
7441 | raw_spin_lock(&dl_b->lock); | ||
7442 | dl_b->bw = new_bw; | ||
7443 | raw_spin_unlock(&dl_b->lock); | ||
7444 | } | ||
7445 | } | ||
7446 | |||
7447 | static int sched_rt_global_validate(void) | ||
7448 | { | ||
7449 | if (sysctl_sched_rt_period <= 0) | ||
7450 | return -EINVAL; | ||
7451 | |||
7452 | if (sysctl_sched_rt_runtime > sysctl_sched_rt_period) | ||
7453 | return -EINVAL; | ||
7454 | |||
7455 | return 0; | ||
7456 | } | ||
7457 | |||
7458 | static void sched_rt_do_global(void) | ||
7459 | { | ||
7460 | def_rt_bandwidth.rt_runtime = global_rt_runtime(); | ||
7461 | def_rt_bandwidth.rt_period = ns_to_ktime(global_rt_period()); | ||
7462 | } | ||
7463 | |||
6899 | int sched_rt_handler(struct ctl_table *table, int write, | 7464 | int sched_rt_handler(struct ctl_table *table, int write, |
6900 | void __user *buffer, size_t *lenp, | 7465 | void __user *buffer, size_t *lenp, |
6901 | loff_t *ppos) | 7466 | loff_t *ppos) |
6902 | { | 7467 | { |
6903 | int ret; | ||
6904 | int old_period, old_runtime; | 7468 | int old_period, old_runtime; |
6905 | static DEFINE_MUTEX(mutex); | 7469 | static DEFINE_MUTEX(mutex); |
7470 | int ret; | ||
6906 | 7471 | ||
6907 | mutex_lock(&mutex); | 7472 | mutex_lock(&mutex); |
6908 | old_period = sysctl_sched_rt_period; | 7473 | old_period = sysctl_sched_rt_period; |
@@ -6911,21 +7476,50 @@ int sched_rt_handler(struct ctl_table *table, int write, | |||
6911 | ret = proc_dointvec(table, write, buffer, lenp, ppos); | 7476 | ret = proc_dointvec(table, write, buffer, lenp, ppos); |
6912 | 7477 | ||
6913 | if (!ret && write) { | 7478 | if (!ret && write) { |
7479 | ret = sched_rt_global_validate(); | ||
7480 | if (ret) | ||
7481 | goto undo; | ||
7482 | |||
6914 | ret = sched_rt_global_constraints(); | 7483 | ret = sched_rt_global_constraints(); |
6915 | if (ret) { | 7484 | if (ret) |
6916 | sysctl_sched_rt_period = old_period; | 7485 | goto undo; |
6917 | sysctl_sched_rt_runtime = old_runtime; | 7486 | |
6918 | } else { | 7487 | ret = sched_dl_global_constraints(); |
6919 | def_rt_bandwidth.rt_runtime = global_rt_runtime(); | 7488 | if (ret) |
6920 | def_rt_bandwidth.rt_period = | 7489 | goto undo; |
6921 | ns_to_ktime(global_rt_period()); | 7490 | |
6922 | } | 7491 | sched_rt_do_global(); |
7492 | sched_dl_do_global(); | ||
7493 | } | ||
7494 | if (0) { | ||
7495 | undo: | ||
7496 | sysctl_sched_rt_period = old_period; | ||
7497 | sysctl_sched_rt_runtime = old_runtime; | ||
6923 | } | 7498 | } |
6924 | mutex_unlock(&mutex); | 7499 | mutex_unlock(&mutex); |
6925 | 7500 | ||
6926 | return ret; | 7501 | return ret; |
6927 | } | 7502 | } |
6928 | 7503 | ||
7504 | int sched_rr_handler(struct ctl_table *table, int write, | ||
7505 | void __user *buffer, size_t *lenp, | ||
7506 | loff_t *ppos) | ||
7507 | { | ||
7508 | int ret; | ||
7509 | static DEFINE_MUTEX(mutex); | ||
7510 | |||
7511 | mutex_lock(&mutex); | ||
7512 | ret = proc_dointvec(table, write, buffer, lenp, ppos); | ||
7513 | /* make sure that internally we keep jiffies */ | ||
7514 | /* also, writing zero resets timeslice to default */ | ||
7515 | if (!ret && write) { | ||
7516 | sched_rr_timeslice = sched_rr_timeslice <= 0 ? | ||
7517 | RR_TIMESLICE : msecs_to_jiffies(sched_rr_timeslice); | ||
7518 | } | ||
7519 | mutex_unlock(&mutex); | ||
7520 | return ret; | ||
7521 | } | ||
7522 | |||
6929 | #ifdef CONFIG_CGROUP_SCHED | 7523 | #ifdef CONFIG_CGROUP_SCHED |
6930 | 7524 | ||
6931 | static inline struct task_group *css_tg(struct cgroup_subsys_state *css) | 7525 | static inline struct task_group *css_tg(struct cgroup_subsys_state *css) |
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c new file mode 100644 index 000000000000..045fc74e3f09 --- /dev/null +++ b/kernel/sched/cpudeadline.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * kernel/sched/cpudl.c | ||
3 | * | ||
4 | * Global CPU deadline management | ||
5 | * | ||
6 | * Author: Juri Lelli <j.lelli@sssup.it> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; version 2 | ||
11 | * of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/gfp.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include "cpudeadline.h" | ||
17 | |||
18 | static inline int parent(int i) | ||
19 | { | ||
20 | return (i - 1) >> 1; | ||
21 | } | ||
22 | |||
23 | static inline int left_child(int i) | ||
24 | { | ||
25 | return (i << 1) + 1; | ||
26 | } | ||
27 | |||
28 | static inline int right_child(int i) | ||
29 | { | ||
30 | return (i << 1) + 2; | ||
31 | } | ||
32 | |||
33 | static inline int dl_time_before(u64 a, u64 b) | ||
34 | { | ||
35 | return (s64)(a - b) < 0; | ||
36 | } | ||
37 | |||
38 | static void cpudl_exchange(struct cpudl *cp, int a, int b) | ||
39 | { | ||
40 | int cpu_a = cp->elements[a].cpu, cpu_b = cp->elements[b].cpu; | ||
41 | |||
42 | swap(cp->elements[a], cp->elements[b]); | ||
43 | swap(cp->cpu_to_idx[cpu_a], cp->cpu_to_idx[cpu_b]); | ||
44 | } | ||
45 | |||
46 | static void cpudl_heapify(struct cpudl *cp, int idx) | ||
47 | { | ||
48 | int l, r, largest; | ||
49 | |||
50 | /* adapted from lib/prio_heap.c */ | ||
51 | while(1) { | ||
52 | l = left_child(idx); | ||
53 | r = right_child(idx); | ||
54 | largest = idx; | ||
55 | |||
56 | if ((l < cp->size) && dl_time_before(cp->elements[idx].dl, | ||
57 | cp->elements[l].dl)) | ||
58 | largest = l; | ||
59 | if ((r < cp->size) && dl_time_before(cp->elements[largest].dl, | ||
60 | cp->elements[r].dl)) | ||
61 | largest = r; | ||
62 | if (largest == idx) | ||
63 | break; | ||
64 | |||
65 | /* Push idx down the heap one level and bump one up */ | ||
66 | cpudl_exchange(cp, largest, idx); | ||
67 | idx = largest; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | static void cpudl_change_key(struct cpudl *cp, int idx, u64 new_dl) | ||
72 | { | ||
73 | WARN_ON(idx > num_present_cpus() || idx == IDX_INVALID); | ||
74 | |||
75 | if (dl_time_before(new_dl, cp->elements[idx].dl)) { | ||
76 | cp->elements[idx].dl = new_dl; | ||
77 | cpudl_heapify(cp, idx); | ||
78 | } else { | ||
79 | cp->elements[idx].dl = new_dl; | ||
80 | while (idx > 0 && dl_time_before(cp->elements[parent(idx)].dl, | ||
81 | cp->elements[idx].dl)) { | ||
82 | cpudl_exchange(cp, idx, parent(idx)); | ||
83 | idx = parent(idx); | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static inline int cpudl_maximum(struct cpudl *cp) | ||
89 | { | ||
90 | return cp->elements[0].cpu; | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * cpudl_find - find the best (later-dl) CPU in the system | ||
95 | * @cp: the cpudl max-heap context | ||
96 | * @p: the task | ||
97 | * @later_mask: a mask to fill in with the selected CPUs (or NULL) | ||
98 | * | ||
99 | * Returns: int - best CPU (heap maximum if suitable) | ||
100 | */ | ||
101 | int cpudl_find(struct cpudl *cp, struct task_struct *p, | ||
102 | struct cpumask *later_mask) | ||
103 | { | ||
104 | int best_cpu = -1; | ||
105 | const struct sched_dl_entity *dl_se = &p->dl; | ||
106 | |||
107 | if (later_mask && cpumask_and(later_mask, cp->free_cpus, | ||
108 | &p->cpus_allowed) && cpumask_and(later_mask, | ||
109 | later_mask, cpu_active_mask)) { | ||
110 | best_cpu = cpumask_any(later_mask); | ||
111 | goto out; | ||
112 | } else if (cpumask_test_cpu(cpudl_maximum(cp), &p->cpus_allowed) && | ||
113 | dl_time_before(dl_se->deadline, cp->elements[0].dl)) { | ||
114 | best_cpu = cpudl_maximum(cp); | ||
115 | if (later_mask) | ||
116 | cpumask_set_cpu(best_cpu, later_mask); | ||
117 | } | ||
118 | |||
119 | out: | ||
120 | WARN_ON(best_cpu > num_present_cpus() && best_cpu != -1); | ||
121 | |||
122 | return best_cpu; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * cpudl_set - update the cpudl max-heap | ||
127 | * @cp: the cpudl max-heap context | ||
128 | * @cpu: the target cpu | ||
129 | * @dl: the new earliest deadline for this cpu | ||
130 | * | ||
131 | * Notes: assumes cpu_rq(cpu)->lock is locked | ||
132 | * | ||
133 | * Returns: (void) | ||
134 | */ | ||
135 | void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid) | ||
136 | { | ||
137 | int old_idx, new_cpu; | ||
138 | unsigned long flags; | ||
139 | |||
140 | WARN_ON(cpu > num_present_cpus()); | ||
141 | |||
142 | raw_spin_lock_irqsave(&cp->lock, flags); | ||
143 | old_idx = cp->cpu_to_idx[cpu]; | ||
144 | if (!is_valid) { | ||
145 | /* remove item */ | ||
146 | if (old_idx == IDX_INVALID) { | ||
147 | /* | ||
148 | * Nothing to remove if old_idx was invalid. | ||
149 | * This could happen if a rq_offline_dl is | ||
150 | * called for a CPU without -dl tasks running. | ||
151 | */ | ||
152 | goto out; | ||
153 | } | ||
154 | new_cpu = cp->elements[cp->size - 1].cpu; | ||
155 | cp->elements[old_idx].dl = cp->elements[cp->size - 1].dl; | ||
156 | cp->elements[old_idx].cpu = new_cpu; | ||
157 | cp->size--; | ||
158 | cp->cpu_to_idx[new_cpu] = old_idx; | ||
159 | cp->cpu_to_idx[cpu] = IDX_INVALID; | ||
160 | while (old_idx > 0 && dl_time_before( | ||
161 | cp->elements[parent(old_idx)].dl, | ||
162 | cp->elements[old_idx].dl)) { | ||
163 | cpudl_exchange(cp, old_idx, parent(old_idx)); | ||
164 | old_idx = parent(old_idx); | ||
165 | } | ||
166 | cpumask_set_cpu(cpu, cp->free_cpus); | ||
167 | cpudl_heapify(cp, old_idx); | ||
168 | |||
169 | goto out; | ||
170 | } | ||
171 | |||
172 | if (old_idx == IDX_INVALID) { | ||
173 | cp->size++; | ||
174 | cp->elements[cp->size - 1].dl = 0; | ||
175 | cp->elements[cp->size - 1].cpu = cpu; | ||
176 | cp->cpu_to_idx[cpu] = cp->size - 1; | ||
177 | cpudl_change_key(cp, cp->size - 1, dl); | ||
178 | cpumask_clear_cpu(cpu, cp->free_cpus); | ||
179 | } else { | ||
180 | cpudl_change_key(cp, old_idx, dl); | ||
181 | } | ||
182 | |||
183 | out: | ||
184 | raw_spin_unlock_irqrestore(&cp->lock, flags); | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * cpudl_init - initialize the cpudl structure | ||
189 | * @cp: the cpudl max-heap context | ||
190 | */ | ||
191 | int cpudl_init(struct cpudl *cp) | ||
192 | { | ||
193 | int i; | ||
194 | |||
195 | memset(cp, 0, sizeof(*cp)); | ||
196 | raw_spin_lock_init(&cp->lock); | ||
197 | cp->size = 0; | ||
198 | for (i = 0; i < NR_CPUS; i++) | ||
199 | cp->cpu_to_idx[i] = IDX_INVALID; | ||
200 | if (!alloc_cpumask_var(&cp->free_cpus, GFP_KERNEL)) | ||
201 | return -ENOMEM; | ||
202 | cpumask_setall(cp->free_cpus); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * cpudl_cleanup - clean up the cpudl structure | ||
209 | * @cp: the cpudl max-heap context | ||
210 | */ | ||
211 | void cpudl_cleanup(struct cpudl *cp) | ||
212 | { | ||
213 | /* | ||
214 | * nothing to do for the moment | ||
215 | */ | ||
216 | } | ||
diff --git a/kernel/sched/cpudeadline.h b/kernel/sched/cpudeadline.h new file mode 100644 index 000000000000..a202789a412c --- /dev/null +++ b/kernel/sched/cpudeadline.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef _LINUX_CPUDL_H | ||
2 | #define _LINUX_CPUDL_H | ||
3 | |||
4 | #include <linux/sched.h> | ||
5 | |||
6 | #define IDX_INVALID -1 | ||
7 | |||
8 | struct array_item { | ||
9 | u64 dl; | ||
10 | int cpu; | ||
11 | }; | ||
12 | |||
13 | struct cpudl { | ||
14 | raw_spinlock_t lock; | ||
15 | int size; | ||
16 | int cpu_to_idx[NR_CPUS]; | ||
17 | struct array_item elements[NR_CPUS]; | ||
18 | cpumask_var_t free_cpus; | ||
19 | }; | ||
20 | |||
21 | |||
22 | #ifdef CONFIG_SMP | ||
23 | int cpudl_find(struct cpudl *cp, struct task_struct *p, | ||
24 | struct cpumask *later_mask); | ||
25 | void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid); | ||
26 | int cpudl_init(struct cpudl *cp); | ||
27 | void cpudl_cleanup(struct cpudl *cp); | ||
28 | #else | ||
29 | #define cpudl_set(cp, cpu, dl) do { } while (0) | ||
30 | #define cpudl_init() do { } while (0) | ||
31 | #endif /* CONFIG_SMP */ | ||
32 | |||
33 | #endif /* _LINUX_CPUDL_H */ | ||
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c new file mode 100644 index 000000000000..0de248202879 --- /dev/null +++ b/kernel/sched/deadline.c | |||
@@ -0,0 +1,1640 @@ | |||
1 | /* | ||
2 | * Deadline Scheduling Class (SCHED_DEADLINE) | ||
3 | * | ||
4 | * Earliest Deadline First (EDF) + Constant Bandwidth Server (CBS). | ||
5 | * | ||
6 | * Tasks that periodically executes their instances for less than their | ||
7 | * runtime won't miss any of their deadlines. | ||
8 | * Tasks that are not periodic or sporadic or that tries to execute more | ||
9 | * than their reserved bandwidth will be slowed down (and may potentially | ||
10 | * miss some of their deadlines), and won't affect any other task. | ||
11 | * | ||
12 | * Copyright (C) 2012 Dario Faggioli <raistlin@linux.it>, | ||
13 | * Juri Lelli <juri.lelli@gmail.com>, | ||
14 | * Michael Trimarchi <michael@amarulasolutions.com>, | ||
15 | * Fabio Checconi <fchecconi@gmail.com> | ||
16 | */ | ||
17 | #include "sched.h" | ||
18 | |||
19 | #include <linux/slab.h> | ||
20 | |||
21 | struct dl_bandwidth def_dl_bandwidth; | ||
22 | |||
23 | static inline struct task_struct *dl_task_of(struct sched_dl_entity *dl_se) | ||
24 | { | ||
25 | return container_of(dl_se, struct task_struct, dl); | ||
26 | } | ||
27 | |||
28 | static inline struct rq *rq_of_dl_rq(struct dl_rq *dl_rq) | ||
29 | { | ||
30 | return container_of(dl_rq, struct rq, dl); | ||
31 | } | ||
32 | |||
33 | static inline struct dl_rq *dl_rq_of_se(struct sched_dl_entity *dl_se) | ||
34 | { | ||
35 | struct task_struct *p = dl_task_of(dl_se); | ||
36 | struct rq *rq = task_rq(p); | ||
37 | |||
38 | return &rq->dl; | ||
39 | } | ||
40 | |||
41 | static inline int on_dl_rq(struct sched_dl_entity *dl_se) | ||
42 | { | ||
43 | return !RB_EMPTY_NODE(&dl_se->rb_node); | ||
44 | } | ||
45 | |||
46 | static inline int is_leftmost(struct task_struct *p, struct dl_rq *dl_rq) | ||
47 | { | ||
48 | struct sched_dl_entity *dl_se = &p->dl; | ||
49 | |||
50 | return dl_rq->rb_leftmost == &dl_se->rb_node; | ||
51 | } | ||
52 | |||
53 | void init_dl_bandwidth(struct dl_bandwidth *dl_b, u64 period, u64 runtime) | ||
54 | { | ||
55 | raw_spin_lock_init(&dl_b->dl_runtime_lock); | ||
56 | dl_b->dl_period = period; | ||
57 | dl_b->dl_runtime = runtime; | ||
58 | } | ||
59 | |||
60 | extern unsigned long to_ratio(u64 period, u64 runtime); | ||
61 | |||
62 | void init_dl_bw(struct dl_bw *dl_b) | ||
63 | { | ||
64 | raw_spin_lock_init(&dl_b->lock); | ||
65 | raw_spin_lock(&def_dl_bandwidth.dl_runtime_lock); | ||
66 | if (global_rt_runtime() == RUNTIME_INF) | ||
67 | dl_b->bw = -1; | ||
68 | else | ||
69 | dl_b->bw = to_ratio(global_rt_period(), global_rt_runtime()); | ||
70 | raw_spin_unlock(&def_dl_bandwidth.dl_runtime_lock); | ||
71 | dl_b->total_bw = 0; | ||
72 | } | ||
73 | |||
74 | void init_dl_rq(struct dl_rq *dl_rq, struct rq *rq) | ||
75 | { | ||
76 | dl_rq->rb_root = RB_ROOT; | ||
77 | |||
78 | #ifdef CONFIG_SMP | ||
79 | /* zero means no -deadline tasks */ | ||
80 | dl_rq->earliest_dl.curr = dl_rq->earliest_dl.next = 0; | ||
81 | |||
82 | dl_rq->dl_nr_migratory = 0; | ||
83 | dl_rq->overloaded = 0; | ||
84 | dl_rq->pushable_dl_tasks_root = RB_ROOT; | ||
85 | #else | ||
86 | init_dl_bw(&dl_rq->dl_bw); | ||
87 | #endif | ||
88 | } | ||
89 | |||
90 | #ifdef CONFIG_SMP | ||
91 | |||
92 | static inline int dl_overloaded(struct rq *rq) | ||
93 | { | ||
94 | return atomic_read(&rq->rd->dlo_count); | ||
95 | } | ||
96 | |||
97 | static inline void dl_set_overload(struct rq *rq) | ||
98 | { | ||
99 | if (!rq->online) | ||
100 | return; | ||
101 | |||
102 | cpumask_set_cpu(rq->cpu, rq->rd->dlo_mask); | ||
103 | /* | ||
104 | * Must be visible before the overload count is | ||
105 | * set (as in sched_rt.c). | ||
106 | * | ||
107 | * Matched by the barrier in pull_dl_task(). | ||
108 | */ | ||
109 | smp_wmb(); | ||
110 | atomic_inc(&rq->rd->dlo_count); | ||
111 | } | ||
112 | |||
113 | static inline void dl_clear_overload(struct rq *rq) | ||
114 | { | ||
115 | if (!rq->online) | ||
116 | return; | ||
117 | |||
118 | atomic_dec(&rq->rd->dlo_count); | ||
119 | cpumask_clear_cpu(rq->cpu, rq->rd->dlo_mask); | ||
120 | } | ||
121 | |||
122 | static void update_dl_migration(struct dl_rq *dl_rq) | ||
123 | { | ||
124 | if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_total > 1) { | ||
125 | if (!dl_rq->overloaded) { | ||
126 | dl_set_overload(rq_of_dl_rq(dl_rq)); | ||
127 | dl_rq->overloaded = 1; | ||
128 | } | ||
129 | } else if (dl_rq->overloaded) { | ||
130 | dl_clear_overload(rq_of_dl_rq(dl_rq)); | ||
131 | dl_rq->overloaded = 0; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) | ||
136 | { | ||
137 | struct task_struct *p = dl_task_of(dl_se); | ||
138 | dl_rq = &rq_of_dl_rq(dl_rq)->dl; | ||
139 | |||
140 | dl_rq->dl_nr_total++; | ||
141 | if (p->nr_cpus_allowed > 1) | ||
142 | dl_rq->dl_nr_migratory++; | ||
143 | |||
144 | update_dl_migration(dl_rq); | ||
145 | } | ||
146 | |||
147 | static void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) | ||
148 | { | ||
149 | struct task_struct *p = dl_task_of(dl_se); | ||
150 | dl_rq = &rq_of_dl_rq(dl_rq)->dl; | ||
151 | |||
152 | dl_rq->dl_nr_total--; | ||
153 | if (p->nr_cpus_allowed > 1) | ||
154 | dl_rq->dl_nr_migratory--; | ||
155 | |||
156 | update_dl_migration(dl_rq); | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * The list of pushable -deadline task is not a plist, like in | ||
161 | * sched_rt.c, it is an rb-tree with tasks ordered by deadline. | ||
162 | */ | ||
163 | static void enqueue_pushable_dl_task(struct rq *rq, struct task_struct *p) | ||
164 | { | ||
165 | struct dl_rq *dl_rq = &rq->dl; | ||
166 | struct rb_node **link = &dl_rq->pushable_dl_tasks_root.rb_node; | ||
167 | struct rb_node *parent = NULL; | ||
168 | struct task_struct *entry; | ||
169 | int leftmost = 1; | ||
170 | |||
171 | BUG_ON(!RB_EMPTY_NODE(&p->pushable_dl_tasks)); | ||
172 | |||
173 | while (*link) { | ||
174 | parent = *link; | ||
175 | entry = rb_entry(parent, struct task_struct, | ||
176 | pushable_dl_tasks); | ||
177 | if (dl_entity_preempt(&p->dl, &entry->dl)) | ||
178 | link = &parent->rb_left; | ||
179 | else { | ||
180 | link = &parent->rb_right; | ||
181 | leftmost = 0; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | if (leftmost) | ||
186 | dl_rq->pushable_dl_tasks_leftmost = &p->pushable_dl_tasks; | ||
187 | |||
188 | rb_link_node(&p->pushable_dl_tasks, parent, link); | ||
189 | rb_insert_color(&p->pushable_dl_tasks, &dl_rq->pushable_dl_tasks_root); | ||
190 | } | ||
191 | |||
192 | static void dequeue_pushable_dl_task(struct rq *rq, struct task_struct *p) | ||
193 | { | ||
194 | struct dl_rq *dl_rq = &rq->dl; | ||
195 | |||
196 | if (RB_EMPTY_NODE(&p->pushable_dl_tasks)) | ||
197 | return; | ||
198 | |||
199 | if (dl_rq->pushable_dl_tasks_leftmost == &p->pushable_dl_tasks) { | ||
200 | struct rb_node *next_node; | ||
201 | |||
202 | next_node = rb_next(&p->pushable_dl_tasks); | ||
203 | dl_rq->pushable_dl_tasks_leftmost = next_node; | ||
204 | } | ||
205 | |||
206 | rb_erase(&p->pushable_dl_tasks, &dl_rq->pushable_dl_tasks_root); | ||
207 | RB_CLEAR_NODE(&p->pushable_dl_tasks); | ||
208 | } | ||
209 | |||
210 | static inline int has_pushable_dl_tasks(struct rq *rq) | ||
211 | { | ||
212 | return !RB_EMPTY_ROOT(&rq->dl.pushable_dl_tasks_root); | ||
213 | } | ||
214 | |||
215 | static int push_dl_task(struct rq *rq); | ||
216 | |||
217 | #else | ||
218 | |||
219 | static inline | ||
220 | void enqueue_pushable_dl_task(struct rq *rq, struct task_struct *p) | ||
221 | { | ||
222 | } | ||
223 | |||
224 | static inline | ||
225 | void dequeue_pushable_dl_task(struct rq *rq, struct task_struct *p) | ||
226 | { | ||
227 | } | ||
228 | |||
229 | static inline | ||
230 | void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) | ||
231 | { | ||
232 | } | ||
233 | |||
234 | static inline | ||
235 | void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) | ||
236 | { | ||
237 | } | ||
238 | |||
239 | #endif /* CONFIG_SMP */ | ||
240 | |||
241 | static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags); | ||
242 | static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags); | ||
243 | static void check_preempt_curr_dl(struct rq *rq, struct task_struct *p, | ||
244 | int flags); | ||
245 | |||
246 | /* | ||
247 | * We are being explicitly informed that a new instance is starting, | ||
248 | * and this means that: | ||
249 | * - the absolute deadline of the entity has to be placed at | ||
250 | * current time + relative deadline; | ||
251 | * - the runtime of the entity has to be set to the maximum value. | ||
252 | * | ||
253 | * The capability of specifying such event is useful whenever a -deadline | ||
254 | * entity wants to (try to!) synchronize its behaviour with the scheduler's | ||
255 | * one, and to (try to!) reconcile itself with its own scheduling | ||
256 | * parameters. | ||
257 | */ | ||
258 | static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se, | ||
259 | struct sched_dl_entity *pi_se) | ||
260 | { | ||
261 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); | ||
262 | struct rq *rq = rq_of_dl_rq(dl_rq); | ||
263 | |||
264 | WARN_ON(!dl_se->dl_new || dl_se->dl_throttled); | ||
265 | |||
266 | /* | ||
267 | * We use the regular wall clock time to set deadlines in the | ||
268 | * future; in fact, we must consider execution overheads (time | ||
269 | * spent on hardirq context, etc.). | ||
270 | */ | ||
271 | dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; | ||
272 | dl_se->runtime = pi_se->dl_runtime; | ||
273 | dl_se->dl_new = 0; | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * Pure Earliest Deadline First (EDF) scheduling does not deal with the | ||
278 | * possibility of a entity lasting more than what it declared, and thus | ||
279 | * exhausting its runtime. | ||
280 | * | ||
281 | * Here we are interested in making runtime overrun possible, but we do | ||
282 | * not want a entity which is misbehaving to affect the scheduling of all | ||
283 | * other entities. | ||
284 | * Therefore, a budgeting strategy called Constant Bandwidth Server (CBS) | ||
285 | * is used, in order to confine each entity within its own bandwidth. | ||
286 | * | ||
287 | * This function deals exactly with that, and ensures that when the runtime | ||
288 | * of a entity is replenished, its deadline is also postponed. That ensures | ||
289 | * the overrunning entity can't interfere with other entity in the system and | ||
290 | * can't make them miss their deadlines. Reasons why this kind of overruns | ||
291 | * could happen are, typically, a entity voluntarily trying to overcome its | ||
292 | * runtime, or it just underestimated it during sched_setscheduler_ex(). | ||
293 | */ | ||
294 | static void replenish_dl_entity(struct sched_dl_entity *dl_se, | ||
295 | struct sched_dl_entity *pi_se) | ||
296 | { | ||
297 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); | ||
298 | struct rq *rq = rq_of_dl_rq(dl_rq); | ||
299 | |||
300 | BUG_ON(pi_se->dl_runtime <= 0); | ||
301 | |||
302 | /* | ||
303 | * This could be the case for a !-dl task that is boosted. | ||
304 | * Just go with full inherited parameters. | ||
305 | */ | ||
306 | if (dl_se->dl_deadline == 0) { | ||
307 | dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; | ||
308 | dl_se->runtime = pi_se->dl_runtime; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * We keep moving the deadline away until we get some | ||
313 | * available runtime for the entity. This ensures correct | ||
314 | * handling of situations where the runtime overrun is | ||
315 | * arbitrary large. | ||
316 | */ | ||
317 | while (dl_se->runtime <= 0) { | ||
318 | dl_se->deadline += pi_se->dl_period; | ||
319 | dl_se->runtime += pi_se->dl_runtime; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * At this point, the deadline really should be "in | ||
324 | * the future" with respect to rq->clock. If it's | ||
325 | * not, we are, for some reason, lagging too much! | ||
326 | * Anyway, after having warn userspace abut that, | ||
327 | * we still try to keep the things running by | ||
328 | * resetting the deadline and the budget of the | ||
329 | * entity. | ||
330 | */ | ||
331 | if (dl_time_before(dl_se->deadline, rq_clock(rq))) { | ||
332 | static bool lag_once = false; | ||
333 | |||
334 | if (!lag_once) { | ||
335 | lag_once = true; | ||
336 | printk_sched("sched: DL replenish lagged to much\n"); | ||
337 | } | ||
338 | dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; | ||
339 | dl_se->runtime = pi_se->dl_runtime; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * Here we check if --at time t-- an entity (which is probably being | ||
345 | * [re]activated or, in general, enqueued) can use its remaining runtime | ||
346 | * and its current deadline _without_ exceeding the bandwidth it is | ||
347 | * assigned (function returns true if it can't). We are in fact applying | ||
348 | * one of the CBS rules: when a task wakes up, if the residual runtime | ||
349 | * over residual deadline fits within the allocated bandwidth, then we | ||
350 | * can keep the current (absolute) deadline and residual budget without | ||
351 | * disrupting the schedulability of the system. Otherwise, we should | ||
352 | * refill the runtime and set the deadline a period in the future, | ||
353 | * because keeping the current (absolute) deadline of the task would | ||
354 | * result in breaking guarantees promised to other tasks. | ||
355 | * | ||
356 | * This function returns true if: | ||
357 | * | ||
358 | * runtime / (deadline - t) > dl_runtime / dl_period , | ||
359 | * | ||
360 | * IOW we can't recycle current parameters. | ||
361 | * | ||
362 | * Notice that the bandwidth check is done against the period. For | ||
363 | * task with deadline equal to period this is the same of using | ||
364 | * dl_deadline instead of dl_period in the equation above. | ||
365 | */ | ||
366 | static bool dl_entity_overflow(struct sched_dl_entity *dl_se, | ||
367 | struct sched_dl_entity *pi_se, u64 t) | ||
368 | { | ||
369 | u64 left, right; | ||
370 | |||
371 | /* | ||
372 | * left and right are the two sides of the equation above, | ||
373 | * after a bit of shuffling to use multiplications instead | ||
374 | * of divisions. | ||
375 | * | ||
376 | * Note that none of the time values involved in the two | ||
377 | * multiplications are absolute: dl_deadline and dl_runtime | ||
378 | * are the relative deadline and the maximum runtime of each | ||
379 | * instance, runtime is the runtime left for the last instance | ||
380 | * and (deadline - t), since t is rq->clock, is the time left | ||
381 | * to the (absolute) deadline. Even if overflowing the u64 type | ||
382 | * is very unlikely to occur in both cases, here we scale down | ||
383 | * as we want to avoid that risk at all. Scaling down by 10 | ||
384 | * means that we reduce granularity to 1us. We are fine with it, | ||
385 | * since this is only a true/false check and, anyway, thinking | ||
386 | * of anything below microseconds resolution is actually fiction | ||
387 | * (but still we want to give the user that illusion >;). | ||
388 | */ | ||
389 | left = (pi_se->dl_period >> DL_SCALE) * (dl_se->runtime >> DL_SCALE); | ||
390 | right = ((dl_se->deadline - t) >> DL_SCALE) * | ||
391 | (pi_se->dl_runtime >> DL_SCALE); | ||
392 | |||
393 | return dl_time_before(right, left); | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | * When a -deadline entity is queued back on the runqueue, its runtime and | ||
398 | * deadline might need updating. | ||
399 | * | ||
400 | * The policy here is that we update the deadline of the entity only if: | ||
401 | * - the current deadline is in the past, | ||
402 | * - using the remaining runtime with the current deadline would make | ||
403 | * the entity exceed its bandwidth. | ||
404 | */ | ||
405 | static void update_dl_entity(struct sched_dl_entity *dl_se, | ||
406 | struct sched_dl_entity *pi_se) | ||
407 | { | ||
408 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); | ||
409 | struct rq *rq = rq_of_dl_rq(dl_rq); | ||
410 | |||
411 | /* | ||
412 | * The arrival of a new instance needs special treatment, i.e., | ||
413 | * the actual scheduling parameters have to be "renewed". | ||
414 | */ | ||
415 | if (dl_se->dl_new) { | ||
416 | setup_new_dl_entity(dl_se, pi_se); | ||
417 | return; | ||
418 | } | ||
419 | |||
420 | if (dl_time_before(dl_se->deadline, rq_clock(rq)) || | ||
421 | dl_entity_overflow(dl_se, pi_se, rq_clock(rq))) { | ||
422 | dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; | ||
423 | dl_se->runtime = pi_se->dl_runtime; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * If the entity depleted all its runtime, and if we want it to sleep | ||
429 | * while waiting for some new execution time to become available, we | ||
430 | * set the bandwidth enforcement timer to the replenishment instant | ||
431 | * and try to activate it. | ||
432 | * | ||
433 | * Notice that it is important for the caller to know if the timer | ||
434 | * actually started or not (i.e., the replenishment instant is in | ||
435 | * the future or in the past). | ||
436 | */ | ||
437 | static int start_dl_timer(struct sched_dl_entity *dl_se, bool boosted) | ||
438 | { | ||
439 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); | ||
440 | struct rq *rq = rq_of_dl_rq(dl_rq); | ||
441 | ktime_t now, act; | ||
442 | ktime_t soft, hard; | ||
443 | unsigned long range; | ||
444 | s64 delta; | ||
445 | |||
446 | if (boosted) | ||
447 | return 0; | ||
448 | /* | ||
449 | * We want the timer to fire at the deadline, but considering | ||
450 | * that it is actually coming from rq->clock and not from | ||
451 | * hrtimer's time base reading. | ||
452 | */ | ||
453 | act = ns_to_ktime(dl_se->deadline); | ||
454 | now = hrtimer_cb_get_time(&dl_se->dl_timer); | ||
455 | delta = ktime_to_ns(now) - rq_clock(rq); | ||
456 | act = ktime_add_ns(act, delta); | ||
457 | |||
458 | /* | ||
459 | * If the expiry time already passed, e.g., because the value | ||
460 | * chosen as the deadline is too small, don't even try to | ||
461 | * start the timer in the past! | ||
462 | */ | ||
463 | if (ktime_us_delta(act, now) < 0) | ||
464 | return 0; | ||
465 | |||
466 | hrtimer_set_expires(&dl_se->dl_timer, act); | ||
467 | |||
468 | soft = hrtimer_get_softexpires(&dl_se->dl_timer); | ||
469 | hard = hrtimer_get_expires(&dl_se->dl_timer); | ||
470 | range = ktime_to_ns(ktime_sub(hard, soft)); | ||
471 | __hrtimer_start_range_ns(&dl_se->dl_timer, soft, | ||
472 | range, HRTIMER_MODE_ABS, 0); | ||
473 | |||
474 | return hrtimer_active(&dl_se->dl_timer); | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * This is the bandwidth enforcement timer callback. If here, we know | ||
479 | * a task is not on its dl_rq, since the fact that the timer was running | ||
480 | * means the task is throttled and needs a runtime replenishment. | ||
481 | * | ||
482 | * However, what we actually do depends on the fact the task is active, | ||
483 | * (it is on its rq) or has been removed from there by a call to | ||
484 | * dequeue_task_dl(). In the former case we must issue the runtime | ||
485 | * replenishment and add the task back to the dl_rq; in the latter, we just | ||
486 | * do nothing but clearing dl_throttled, so that runtime and deadline | ||
487 | * updating (and the queueing back to dl_rq) will be done by the | ||
488 | * next call to enqueue_task_dl(). | ||
489 | */ | ||
490 | static enum hrtimer_restart dl_task_timer(struct hrtimer *timer) | ||
491 | { | ||
492 | struct sched_dl_entity *dl_se = container_of(timer, | ||
493 | struct sched_dl_entity, | ||
494 | dl_timer); | ||
495 | struct task_struct *p = dl_task_of(dl_se); | ||
496 | struct rq *rq = task_rq(p); | ||
497 | raw_spin_lock(&rq->lock); | ||
498 | |||
499 | /* | ||
500 | * We need to take care of a possible races here. In fact, the | ||
501 | * task might have changed its scheduling policy to something | ||
502 | * different from SCHED_DEADLINE or changed its reservation | ||
503 | * parameters (through sched_setscheduler()). | ||
504 | */ | ||
505 | if (!dl_task(p) || dl_se->dl_new) | ||
506 | goto unlock; | ||
507 | |||
508 | sched_clock_tick(); | ||
509 | update_rq_clock(rq); | ||
510 | dl_se->dl_throttled = 0; | ||
511 | if (p->on_rq) { | ||
512 | enqueue_task_dl(rq, p, ENQUEUE_REPLENISH); | ||
513 | if (task_has_dl_policy(rq->curr)) | ||
514 | check_preempt_curr_dl(rq, p, 0); | ||
515 | else | ||
516 | resched_task(rq->curr); | ||
517 | #ifdef CONFIG_SMP | ||
518 | /* | ||
519 | * Queueing this task back might have overloaded rq, | ||
520 | * check if we need to kick someone away. | ||
521 | */ | ||
522 | if (has_pushable_dl_tasks(rq)) | ||
523 | push_dl_task(rq); | ||
524 | #endif | ||
525 | } | ||
526 | unlock: | ||
527 | raw_spin_unlock(&rq->lock); | ||
528 | |||
529 | return HRTIMER_NORESTART; | ||
530 | } | ||
531 | |||
532 | void init_dl_task_timer(struct sched_dl_entity *dl_se) | ||
533 | { | ||
534 | struct hrtimer *timer = &dl_se->dl_timer; | ||
535 | |||
536 | if (hrtimer_active(timer)) { | ||
537 | hrtimer_try_to_cancel(timer); | ||
538 | return; | ||
539 | } | ||
540 | |||
541 | hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
542 | timer->function = dl_task_timer; | ||
543 | } | ||
544 | |||
545 | static | ||
546 | int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se) | ||
547 | { | ||
548 | int dmiss = dl_time_before(dl_se->deadline, rq_clock(rq)); | ||
549 | int rorun = dl_se->runtime <= 0; | ||
550 | |||
551 | if (!rorun && !dmiss) | ||
552 | return 0; | ||
553 | |||
554 | /* | ||
555 | * If we are beyond our current deadline and we are still | ||
556 | * executing, then we have already used some of the runtime of | ||
557 | * the next instance. Thus, if we do not account that, we are | ||
558 | * stealing bandwidth from the system at each deadline miss! | ||
559 | */ | ||
560 | if (dmiss) { | ||
561 | dl_se->runtime = rorun ? dl_se->runtime : 0; | ||
562 | dl_se->runtime -= rq_clock(rq) - dl_se->deadline; | ||
563 | } | ||
564 | |||
565 | return 1; | ||
566 | } | ||
567 | |||
568 | /* | ||
569 | * Update the current task's runtime statistics (provided it is still | ||
570 | * a -deadline task and has not been removed from the dl_rq). | ||
571 | */ | ||
572 | static void update_curr_dl(struct rq *rq) | ||
573 | { | ||
574 | struct task_struct *curr = rq->curr; | ||
575 | struct sched_dl_entity *dl_se = &curr->dl; | ||
576 | u64 delta_exec; | ||
577 | |||
578 | if (!dl_task(curr) || !on_dl_rq(dl_se)) | ||
579 | return; | ||
580 | |||
581 | /* | ||
582 | * Consumed budget is computed considering the time as | ||
583 | * observed by schedulable tasks (excluding time spent | ||
584 | * in hardirq context, etc.). Deadlines are instead | ||
585 | * computed using hard walltime. This seems to be the more | ||
586 | * natural solution, but the full ramifications of this | ||
587 | * approach need further study. | ||
588 | */ | ||
589 | delta_exec = rq_clock_task(rq) - curr->se.exec_start; | ||
590 | if (unlikely((s64)delta_exec < 0)) | ||
591 | delta_exec = 0; | ||
592 | |||
593 | schedstat_set(curr->se.statistics.exec_max, | ||
594 | max(curr->se.statistics.exec_max, delta_exec)); | ||
595 | |||
596 | curr->se.sum_exec_runtime += delta_exec; | ||
597 | account_group_exec_runtime(curr, delta_exec); | ||
598 | |||
599 | curr->se.exec_start = rq_clock_task(rq); | ||
600 | cpuacct_charge(curr, delta_exec); | ||
601 | |||
602 | sched_rt_avg_update(rq, delta_exec); | ||
603 | |||
604 | dl_se->runtime -= delta_exec; | ||
605 | if (dl_runtime_exceeded(rq, dl_se)) { | ||
606 | __dequeue_task_dl(rq, curr, 0); | ||
607 | if (likely(start_dl_timer(dl_se, curr->dl.dl_boosted))) | ||
608 | dl_se->dl_throttled = 1; | ||
609 | else | ||
610 | enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH); | ||
611 | |||
612 | if (!is_leftmost(curr, &rq->dl)) | ||
613 | resched_task(curr); | ||
614 | } | ||
615 | |||
616 | /* | ||
617 | * Because -- for now -- we share the rt bandwidth, we need to | ||
618 | * account our runtime there too, otherwise actual rt tasks | ||
619 | * would be able to exceed the shared quota. | ||
620 | * | ||
621 | * Account to the root rt group for now. | ||
622 | * | ||
623 | * The solution we're working towards is having the RT groups scheduled | ||
624 | * using deadline servers -- however there's a few nasties to figure | ||
625 | * out before that can happen. | ||
626 | */ | ||
627 | if (rt_bandwidth_enabled()) { | ||
628 | struct rt_rq *rt_rq = &rq->rt; | ||
629 | |||
630 | raw_spin_lock(&rt_rq->rt_runtime_lock); | ||
631 | rt_rq->rt_time += delta_exec; | ||
632 | /* | ||
633 | * We'll let actual RT tasks worry about the overflow here, we | ||
634 | * have our own CBS to keep us inline -- see above. | ||
635 | */ | ||
636 | raw_spin_unlock(&rt_rq->rt_runtime_lock); | ||
637 | } | ||
638 | } | ||
639 | |||
640 | #ifdef CONFIG_SMP | ||
641 | |||
642 | static struct task_struct *pick_next_earliest_dl_task(struct rq *rq, int cpu); | ||
643 | |||
644 | static inline u64 next_deadline(struct rq *rq) | ||
645 | { | ||
646 | struct task_struct *next = pick_next_earliest_dl_task(rq, rq->cpu); | ||
647 | |||
648 | if (next && dl_prio(next->prio)) | ||
649 | return next->dl.deadline; | ||
650 | else | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | static void inc_dl_deadline(struct dl_rq *dl_rq, u64 deadline) | ||
655 | { | ||
656 | struct rq *rq = rq_of_dl_rq(dl_rq); | ||
657 | |||
658 | if (dl_rq->earliest_dl.curr == 0 || | ||
659 | dl_time_before(deadline, dl_rq->earliest_dl.curr)) { | ||
660 | /* | ||
661 | * If the dl_rq had no -deadline tasks, or if the new task | ||
662 | * has shorter deadline than the current one on dl_rq, we | ||
663 | * know that the previous earliest becomes our next earliest, | ||
664 | * as the new task becomes the earliest itself. | ||
665 | */ | ||
666 | dl_rq->earliest_dl.next = dl_rq->earliest_dl.curr; | ||
667 | dl_rq->earliest_dl.curr = deadline; | ||
668 | cpudl_set(&rq->rd->cpudl, rq->cpu, deadline, 1); | ||
669 | } else if (dl_rq->earliest_dl.next == 0 || | ||
670 | dl_time_before(deadline, dl_rq->earliest_dl.next)) { | ||
671 | /* | ||
672 | * On the other hand, if the new -deadline task has a | ||
673 | * a later deadline than the earliest one on dl_rq, but | ||
674 | * it is earlier than the next (if any), we must | ||
675 | * recompute the next-earliest. | ||
676 | */ | ||
677 | dl_rq->earliest_dl.next = next_deadline(rq); | ||
678 | } | ||
679 | } | ||
680 | |||
681 | static void dec_dl_deadline(struct dl_rq *dl_rq, u64 deadline) | ||
682 | { | ||
683 | struct rq *rq = rq_of_dl_rq(dl_rq); | ||
684 | |||
685 | /* | ||
686 | * Since we may have removed our earliest (and/or next earliest) | ||
687 | * task we must recompute them. | ||
688 | */ | ||
689 | if (!dl_rq->dl_nr_running) { | ||
690 | dl_rq->earliest_dl.curr = 0; | ||
691 | dl_rq->earliest_dl.next = 0; | ||
692 | cpudl_set(&rq->rd->cpudl, rq->cpu, 0, 0); | ||
693 | } else { | ||
694 | struct rb_node *leftmost = dl_rq->rb_leftmost; | ||
695 | struct sched_dl_entity *entry; | ||
696 | |||
697 | entry = rb_entry(leftmost, struct sched_dl_entity, rb_node); | ||
698 | dl_rq->earliest_dl.curr = entry->deadline; | ||
699 | dl_rq->earliest_dl.next = next_deadline(rq); | ||
700 | cpudl_set(&rq->rd->cpudl, rq->cpu, entry->deadline, 1); | ||
701 | } | ||
702 | } | ||
703 | |||
704 | #else | ||
705 | |||
706 | static inline void inc_dl_deadline(struct dl_rq *dl_rq, u64 deadline) {} | ||
707 | static inline void dec_dl_deadline(struct dl_rq *dl_rq, u64 deadline) {} | ||
708 | |||
709 | #endif /* CONFIG_SMP */ | ||
710 | |||
711 | static inline | ||
712 | void inc_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) | ||
713 | { | ||
714 | int prio = dl_task_of(dl_se)->prio; | ||
715 | u64 deadline = dl_se->deadline; | ||
716 | |||
717 | WARN_ON(!dl_prio(prio)); | ||
718 | dl_rq->dl_nr_running++; | ||
719 | |||
720 | inc_dl_deadline(dl_rq, deadline); | ||
721 | inc_dl_migration(dl_se, dl_rq); | ||
722 | } | ||
723 | |||
724 | static inline | ||
725 | void dec_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) | ||
726 | { | ||
727 | int prio = dl_task_of(dl_se)->prio; | ||
728 | |||
729 | WARN_ON(!dl_prio(prio)); | ||
730 | WARN_ON(!dl_rq->dl_nr_running); | ||
731 | dl_rq->dl_nr_running--; | ||
732 | |||
733 | dec_dl_deadline(dl_rq, dl_se->deadline); | ||
734 | dec_dl_migration(dl_se, dl_rq); | ||
735 | } | ||
736 | |||
737 | static void __enqueue_dl_entity(struct sched_dl_entity *dl_se) | ||
738 | { | ||
739 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); | ||
740 | struct rb_node **link = &dl_rq->rb_root.rb_node; | ||
741 | struct rb_node *parent = NULL; | ||
742 | struct sched_dl_entity *entry; | ||
743 | int leftmost = 1; | ||
744 | |||
745 | BUG_ON(!RB_EMPTY_NODE(&dl_se->rb_node)); | ||
746 | |||
747 | while (*link) { | ||
748 | parent = *link; | ||
749 | entry = rb_entry(parent, struct sched_dl_entity, rb_node); | ||
750 | if (dl_time_before(dl_se->deadline, entry->deadline)) | ||
751 | link = &parent->rb_left; | ||
752 | else { | ||
753 | link = &parent->rb_right; | ||
754 | leftmost = 0; | ||
755 | } | ||
756 | } | ||
757 | |||
758 | if (leftmost) | ||
759 | dl_rq->rb_leftmost = &dl_se->rb_node; | ||
760 | |||
761 | rb_link_node(&dl_se->rb_node, parent, link); | ||
762 | rb_insert_color(&dl_se->rb_node, &dl_rq->rb_root); | ||
763 | |||
764 | inc_dl_tasks(dl_se, dl_rq); | ||
765 | } | ||
766 | |||
767 | static void __dequeue_dl_entity(struct sched_dl_entity *dl_se) | ||
768 | { | ||
769 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); | ||
770 | |||
771 | if (RB_EMPTY_NODE(&dl_se->rb_node)) | ||
772 | return; | ||
773 | |||
774 | if (dl_rq->rb_leftmost == &dl_se->rb_node) { | ||
775 | struct rb_node *next_node; | ||
776 | |||
777 | next_node = rb_next(&dl_se->rb_node); | ||
778 | dl_rq->rb_leftmost = next_node; | ||
779 | } | ||
780 | |||
781 | rb_erase(&dl_se->rb_node, &dl_rq->rb_root); | ||
782 | RB_CLEAR_NODE(&dl_se->rb_node); | ||
783 | |||
784 | dec_dl_tasks(dl_se, dl_rq); | ||
785 | } | ||
786 | |||
787 | static void | ||
788 | enqueue_dl_entity(struct sched_dl_entity *dl_se, | ||
789 | struct sched_dl_entity *pi_se, int flags) | ||
790 | { | ||
791 | BUG_ON(on_dl_rq(dl_se)); | ||
792 | |||
793 | /* | ||
794 | * If this is a wakeup or a new instance, the scheduling | ||
795 | * parameters of the task might need updating. Otherwise, | ||
796 | * we want a replenishment of its runtime. | ||
797 | */ | ||
798 | if (!dl_se->dl_new && flags & ENQUEUE_REPLENISH) | ||
799 | replenish_dl_entity(dl_se, pi_se); | ||
800 | else | ||
801 | update_dl_entity(dl_se, pi_se); | ||
802 | |||
803 | __enqueue_dl_entity(dl_se); | ||
804 | } | ||
805 | |||
806 | static void dequeue_dl_entity(struct sched_dl_entity *dl_se) | ||
807 | { | ||
808 | __dequeue_dl_entity(dl_se); | ||
809 | } | ||
810 | |||
811 | static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) | ||
812 | { | ||
813 | struct task_struct *pi_task = rt_mutex_get_top_task(p); | ||
814 | struct sched_dl_entity *pi_se = &p->dl; | ||
815 | |||
816 | /* | ||
817 | * Use the scheduling parameters of the top pi-waiter | ||
818 | * task if we have one and its (relative) deadline is | ||
819 | * smaller than our one... OTW we keep our runtime and | ||
820 | * deadline. | ||
821 | */ | ||
822 | if (pi_task && p->dl.dl_boosted && dl_prio(pi_task->normal_prio)) | ||
823 | pi_se = &pi_task->dl; | ||
824 | |||
825 | /* | ||
826 | * If p is throttled, we do nothing. In fact, if it exhausted | ||
827 | * its budget it needs a replenishment and, since it now is on | ||
828 | * its rq, the bandwidth timer callback (which clearly has not | ||
829 | * run yet) will take care of this. | ||
830 | */ | ||
831 | if (p->dl.dl_throttled) | ||
832 | return; | ||
833 | |||
834 | enqueue_dl_entity(&p->dl, pi_se, flags); | ||
835 | |||
836 | if (!task_current(rq, p) && p->nr_cpus_allowed > 1) | ||
837 | enqueue_pushable_dl_task(rq, p); | ||
838 | |||
839 | inc_nr_running(rq); | ||
840 | } | ||
841 | |||
842 | static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) | ||
843 | { | ||
844 | dequeue_dl_entity(&p->dl); | ||
845 | dequeue_pushable_dl_task(rq, p); | ||
846 | } | ||
847 | |||
848 | static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) | ||
849 | { | ||
850 | update_curr_dl(rq); | ||
851 | __dequeue_task_dl(rq, p, flags); | ||
852 | |||
853 | dec_nr_running(rq); | ||
854 | } | ||
855 | |||
856 | /* | ||
857 | * Yield task semantic for -deadline tasks is: | ||
858 | * | ||
859 | * get off from the CPU until our next instance, with | ||
860 | * a new runtime. This is of little use now, since we | ||
861 | * don't have a bandwidth reclaiming mechanism. Anyway, | ||
862 | * bandwidth reclaiming is planned for the future, and | ||
863 | * yield_task_dl will indicate that some spare budget | ||
864 | * is available for other task instances to use it. | ||
865 | */ | ||
866 | static void yield_task_dl(struct rq *rq) | ||
867 | { | ||
868 | struct task_struct *p = rq->curr; | ||
869 | |||
870 | /* | ||
871 | * We make the task go to sleep until its current deadline by | ||
872 | * forcing its runtime to zero. This way, update_curr_dl() stops | ||
873 | * it and the bandwidth timer will wake it up and will give it | ||
874 | * new scheduling parameters (thanks to dl_new=1). | ||
875 | */ | ||
876 | if (p->dl.runtime > 0) { | ||
877 | rq->curr->dl.dl_new = 1; | ||
878 | p->dl.runtime = 0; | ||
879 | } | ||
880 | update_curr_dl(rq); | ||
881 | } | ||
882 | |||
883 | #ifdef CONFIG_SMP | ||
884 | |||
885 | static int find_later_rq(struct task_struct *task); | ||
886 | |||
887 | static int | ||
888 | select_task_rq_dl(struct task_struct *p, int cpu, int sd_flag, int flags) | ||
889 | { | ||
890 | struct task_struct *curr; | ||
891 | struct rq *rq; | ||
892 | |||
893 | if (sd_flag != SD_BALANCE_WAKE && sd_flag != SD_BALANCE_FORK) | ||
894 | goto out; | ||
895 | |||
896 | rq = cpu_rq(cpu); | ||
897 | |||
898 | rcu_read_lock(); | ||
899 | curr = ACCESS_ONCE(rq->curr); /* unlocked access */ | ||
900 | |||
901 | /* | ||
902 | * If we are dealing with a -deadline task, we must | ||
903 | * decide where to wake it up. | ||
904 | * If it has a later deadline and the current task | ||
905 | * on this rq can't move (provided the waking task | ||
906 | * can!) we prefer to send it somewhere else. On the | ||
907 | * other hand, if it has a shorter deadline, we | ||
908 | * try to make it stay here, it might be important. | ||
909 | */ | ||
910 | if (unlikely(dl_task(curr)) && | ||
911 | (curr->nr_cpus_allowed < 2 || | ||
912 | !dl_entity_preempt(&p->dl, &curr->dl)) && | ||
913 | (p->nr_cpus_allowed > 1)) { | ||
914 | int target = find_later_rq(p); | ||
915 | |||
916 | if (target != -1) | ||
917 | cpu = target; | ||
918 | } | ||
919 | rcu_read_unlock(); | ||
920 | |||
921 | out: | ||
922 | return cpu; | ||
923 | } | ||
924 | |||
925 | static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p) | ||
926 | { | ||
927 | /* | ||
928 | * Current can't be migrated, useless to reschedule, | ||
929 | * let's hope p can move out. | ||
930 | */ | ||
931 | if (rq->curr->nr_cpus_allowed == 1 || | ||
932 | cpudl_find(&rq->rd->cpudl, rq->curr, NULL) == -1) | ||
933 | return; | ||
934 | |||
935 | /* | ||
936 | * p is migratable, so let's not schedule it and | ||
937 | * see if it is pushed or pulled somewhere else. | ||
938 | */ | ||
939 | if (p->nr_cpus_allowed != 1 && | ||
940 | cpudl_find(&rq->rd->cpudl, p, NULL) != -1) | ||
941 | return; | ||
942 | |||
943 | resched_task(rq->curr); | ||
944 | } | ||
945 | |||
946 | #endif /* CONFIG_SMP */ | ||
947 | |||
948 | /* | ||
949 | * Only called when both the current and waking task are -deadline | ||
950 | * tasks. | ||
951 | */ | ||
952 | static void check_preempt_curr_dl(struct rq *rq, struct task_struct *p, | ||
953 | int flags) | ||
954 | { | ||
955 | if (dl_entity_preempt(&p->dl, &rq->curr->dl)) { | ||
956 | resched_task(rq->curr); | ||
957 | return; | ||
958 | } | ||
959 | |||
960 | #ifdef CONFIG_SMP | ||
961 | /* | ||
962 | * In the unlikely case current and p have the same deadline | ||
963 | * let us try to decide what's the best thing to do... | ||
964 | */ | ||
965 | if ((p->dl.deadline == rq->curr->dl.deadline) && | ||
966 | !test_tsk_need_resched(rq->curr)) | ||
967 | check_preempt_equal_dl(rq, p); | ||
968 | #endif /* CONFIG_SMP */ | ||
969 | } | ||
970 | |||
971 | #ifdef CONFIG_SCHED_HRTICK | ||
972 | static void start_hrtick_dl(struct rq *rq, struct task_struct *p) | ||
973 | { | ||
974 | s64 delta = p->dl.dl_runtime - p->dl.runtime; | ||
975 | |||
976 | if (delta > 10000) | ||
977 | hrtick_start(rq, p->dl.runtime); | ||
978 | } | ||
979 | #endif | ||
980 | |||
981 | static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq, | ||
982 | struct dl_rq *dl_rq) | ||
983 | { | ||
984 | struct rb_node *left = dl_rq->rb_leftmost; | ||
985 | |||
986 | if (!left) | ||
987 | return NULL; | ||
988 | |||
989 | return rb_entry(left, struct sched_dl_entity, rb_node); | ||
990 | } | ||
991 | |||
992 | struct task_struct *pick_next_task_dl(struct rq *rq) | ||
993 | { | ||
994 | struct sched_dl_entity *dl_se; | ||
995 | struct task_struct *p; | ||
996 | struct dl_rq *dl_rq; | ||
997 | |||
998 | dl_rq = &rq->dl; | ||
999 | |||
1000 | if (unlikely(!dl_rq->dl_nr_running)) | ||
1001 | return NULL; | ||
1002 | |||
1003 | dl_se = pick_next_dl_entity(rq, dl_rq); | ||
1004 | BUG_ON(!dl_se); | ||
1005 | |||
1006 | p = dl_task_of(dl_se); | ||
1007 | p->se.exec_start = rq_clock_task(rq); | ||
1008 | |||
1009 | /* Running task will never be pushed. */ | ||
1010 | dequeue_pushable_dl_task(rq, p); | ||
1011 | |||
1012 | #ifdef CONFIG_SCHED_HRTICK | ||
1013 | if (hrtick_enabled(rq)) | ||
1014 | start_hrtick_dl(rq, p); | ||
1015 | #endif | ||
1016 | |||
1017 | #ifdef CONFIG_SMP | ||
1018 | rq->post_schedule = has_pushable_dl_tasks(rq); | ||
1019 | #endif /* CONFIG_SMP */ | ||
1020 | |||
1021 | return p; | ||
1022 | } | ||
1023 | |||
1024 | static void put_prev_task_dl(struct rq *rq, struct task_struct *p) | ||
1025 | { | ||
1026 | update_curr_dl(rq); | ||
1027 | |||
1028 | if (on_dl_rq(&p->dl) && p->nr_cpus_allowed > 1) | ||
1029 | enqueue_pushable_dl_task(rq, p); | ||
1030 | } | ||
1031 | |||
1032 | static void task_tick_dl(struct rq *rq, struct task_struct *p, int queued) | ||
1033 | { | ||
1034 | update_curr_dl(rq); | ||
1035 | |||
1036 | #ifdef CONFIG_SCHED_HRTICK | ||
1037 | if (hrtick_enabled(rq) && queued && p->dl.runtime > 0) | ||
1038 | start_hrtick_dl(rq, p); | ||
1039 | #endif | ||
1040 | } | ||
1041 | |||
1042 | static void task_fork_dl(struct task_struct *p) | ||
1043 | { | ||
1044 | /* | ||
1045 | * SCHED_DEADLINE tasks cannot fork and this is achieved through | ||
1046 | * sched_fork() | ||
1047 | */ | ||
1048 | } | ||
1049 | |||
1050 | static void task_dead_dl(struct task_struct *p) | ||
1051 | { | ||
1052 | struct hrtimer *timer = &p->dl.dl_timer; | ||
1053 | struct dl_bw *dl_b = dl_bw_of(task_cpu(p)); | ||
1054 | |||
1055 | /* | ||
1056 | * Since we are TASK_DEAD we won't slip out of the domain! | ||
1057 | */ | ||
1058 | raw_spin_lock_irq(&dl_b->lock); | ||
1059 | dl_b->total_bw -= p->dl.dl_bw; | ||
1060 | raw_spin_unlock_irq(&dl_b->lock); | ||
1061 | |||
1062 | hrtimer_cancel(timer); | ||
1063 | } | ||
1064 | |||
1065 | static void set_curr_task_dl(struct rq *rq) | ||
1066 | { | ||
1067 | struct task_struct *p = rq->curr; | ||
1068 | |||
1069 | p->se.exec_start = rq_clock_task(rq); | ||
1070 | |||
1071 | /* You can't push away the running task */ | ||
1072 | dequeue_pushable_dl_task(rq, p); | ||
1073 | } | ||
1074 | |||
1075 | #ifdef CONFIG_SMP | ||
1076 | |||
1077 | /* Only try algorithms three times */ | ||
1078 | #define DL_MAX_TRIES 3 | ||
1079 | |||
1080 | static int pick_dl_task(struct rq *rq, struct task_struct *p, int cpu) | ||
1081 | { | ||
1082 | if (!task_running(rq, p) && | ||
1083 | (cpu < 0 || cpumask_test_cpu(cpu, &p->cpus_allowed)) && | ||
1084 | (p->nr_cpus_allowed > 1)) | ||
1085 | return 1; | ||
1086 | |||
1087 | return 0; | ||
1088 | } | ||
1089 | |||
1090 | /* Returns the second earliest -deadline task, NULL otherwise */ | ||
1091 | static struct task_struct *pick_next_earliest_dl_task(struct rq *rq, int cpu) | ||
1092 | { | ||
1093 | struct rb_node *next_node = rq->dl.rb_leftmost; | ||
1094 | struct sched_dl_entity *dl_se; | ||
1095 | struct task_struct *p = NULL; | ||
1096 | |||
1097 | next_node: | ||
1098 | next_node = rb_next(next_node); | ||
1099 | if (next_node) { | ||
1100 | dl_se = rb_entry(next_node, struct sched_dl_entity, rb_node); | ||
1101 | p = dl_task_of(dl_se); | ||
1102 | |||
1103 | if (pick_dl_task(rq, p, cpu)) | ||
1104 | return p; | ||
1105 | |||
1106 | goto next_node; | ||
1107 | } | ||
1108 | |||
1109 | return NULL; | ||
1110 | } | ||
1111 | |||
1112 | static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask_dl); | ||
1113 | |||
1114 | static int find_later_rq(struct task_struct *task) | ||
1115 | { | ||
1116 | struct sched_domain *sd; | ||
1117 | struct cpumask *later_mask = __get_cpu_var(local_cpu_mask_dl); | ||
1118 | int this_cpu = smp_processor_id(); | ||
1119 | int best_cpu, cpu = task_cpu(task); | ||
1120 | |||
1121 | /* Make sure the mask is initialized first */ | ||
1122 | if (unlikely(!later_mask)) | ||
1123 | return -1; | ||
1124 | |||
1125 | if (task->nr_cpus_allowed == 1) | ||
1126 | return -1; | ||
1127 | |||
1128 | best_cpu = cpudl_find(&task_rq(task)->rd->cpudl, | ||
1129 | task, later_mask); | ||
1130 | if (best_cpu == -1) | ||
1131 | return -1; | ||
1132 | |||
1133 | /* | ||
1134 | * If we are here, some target has been found, | ||
1135 | * the most suitable of which is cached in best_cpu. | ||
1136 | * This is, among the runqueues where the current tasks | ||
1137 | * have later deadlines than the task's one, the rq | ||
1138 | * with the latest possible one. | ||
1139 | * | ||
1140 | * Now we check how well this matches with task's | ||
1141 | * affinity and system topology. | ||
1142 | * | ||
1143 | * The last cpu where the task run is our first | ||
1144 | * guess, since it is most likely cache-hot there. | ||
1145 | */ | ||
1146 | if (cpumask_test_cpu(cpu, later_mask)) | ||
1147 | return cpu; | ||
1148 | /* | ||
1149 | * Check if this_cpu is to be skipped (i.e., it is | ||
1150 | * not in the mask) or not. | ||
1151 | */ | ||
1152 | if (!cpumask_test_cpu(this_cpu, later_mask)) | ||
1153 | this_cpu = -1; | ||
1154 | |||
1155 | rcu_read_lock(); | ||
1156 | for_each_domain(cpu, sd) { | ||
1157 | if (sd->flags & SD_WAKE_AFFINE) { | ||
1158 | |||
1159 | /* | ||
1160 | * If possible, preempting this_cpu is | ||
1161 | * cheaper than migrating. | ||
1162 | */ | ||
1163 | if (this_cpu != -1 && | ||
1164 | cpumask_test_cpu(this_cpu, sched_domain_span(sd))) { | ||
1165 | rcu_read_unlock(); | ||
1166 | return this_cpu; | ||
1167 | } | ||
1168 | |||
1169 | /* | ||
1170 | * Last chance: if best_cpu is valid and is | ||
1171 | * in the mask, that becomes our choice. | ||
1172 | */ | ||
1173 | if (best_cpu < nr_cpu_ids && | ||
1174 | cpumask_test_cpu(best_cpu, sched_domain_span(sd))) { | ||
1175 | rcu_read_unlock(); | ||
1176 | return best_cpu; | ||
1177 | } | ||
1178 | } | ||
1179 | } | ||
1180 | rcu_read_unlock(); | ||
1181 | |||
1182 | /* | ||
1183 | * At this point, all our guesses failed, we just return | ||
1184 | * 'something', and let the caller sort the things out. | ||
1185 | */ | ||
1186 | if (this_cpu != -1) | ||
1187 | return this_cpu; | ||
1188 | |||
1189 | cpu = cpumask_any(later_mask); | ||
1190 | if (cpu < nr_cpu_ids) | ||
1191 | return cpu; | ||
1192 | |||
1193 | return -1; | ||
1194 | } | ||
1195 | |||
1196 | /* Locks the rq it finds */ | ||
1197 | static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq) | ||
1198 | { | ||
1199 | struct rq *later_rq = NULL; | ||
1200 | int tries; | ||
1201 | int cpu; | ||
1202 | |||
1203 | for (tries = 0; tries < DL_MAX_TRIES; tries++) { | ||
1204 | cpu = find_later_rq(task); | ||
1205 | |||
1206 | if ((cpu == -1) || (cpu == rq->cpu)) | ||
1207 | break; | ||
1208 | |||
1209 | later_rq = cpu_rq(cpu); | ||
1210 | |||
1211 | /* Retry if something changed. */ | ||
1212 | if (double_lock_balance(rq, later_rq)) { | ||
1213 | if (unlikely(task_rq(task) != rq || | ||
1214 | !cpumask_test_cpu(later_rq->cpu, | ||
1215 | &task->cpus_allowed) || | ||
1216 | task_running(rq, task) || !task->on_rq)) { | ||
1217 | double_unlock_balance(rq, later_rq); | ||
1218 | later_rq = NULL; | ||
1219 | break; | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1223 | /* | ||
1224 | * If the rq we found has no -deadline task, or | ||
1225 | * its earliest one has a later deadline than our | ||
1226 | * task, the rq is a good one. | ||
1227 | */ | ||
1228 | if (!later_rq->dl.dl_nr_running || | ||
1229 | dl_time_before(task->dl.deadline, | ||
1230 | later_rq->dl.earliest_dl.curr)) | ||
1231 | break; | ||
1232 | |||
1233 | /* Otherwise we try again. */ | ||
1234 | double_unlock_balance(rq, later_rq); | ||
1235 | later_rq = NULL; | ||
1236 | } | ||
1237 | |||
1238 | return later_rq; | ||
1239 | } | ||
1240 | |||
1241 | static struct task_struct *pick_next_pushable_dl_task(struct rq *rq) | ||
1242 | { | ||
1243 | struct task_struct *p; | ||
1244 | |||
1245 | if (!has_pushable_dl_tasks(rq)) | ||
1246 | return NULL; | ||
1247 | |||
1248 | p = rb_entry(rq->dl.pushable_dl_tasks_leftmost, | ||
1249 | struct task_struct, pushable_dl_tasks); | ||
1250 | |||
1251 | BUG_ON(rq->cpu != task_cpu(p)); | ||
1252 | BUG_ON(task_current(rq, p)); | ||
1253 | BUG_ON(p->nr_cpus_allowed <= 1); | ||
1254 | |||
1255 | BUG_ON(!p->on_rq); | ||
1256 | BUG_ON(!dl_task(p)); | ||
1257 | |||
1258 | return p; | ||
1259 | } | ||
1260 | |||
1261 | /* | ||
1262 | * See if the non running -deadline tasks on this rq | ||
1263 | * can be sent to some other CPU where they can preempt | ||
1264 | * and start executing. | ||
1265 | */ | ||
1266 | static int push_dl_task(struct rq *rq) | ||
1267 | { | ||
1268 | struct task_struct *next_task; | ||
1269 | struct rq *later_rq; | ||
1270 | |||
1271 | if (!rq->dl.overloaded) | ||
1272 | return 0; | ||
1273 | |||
1274 | next_task = pick_next_pushable_dl_task(rq); | ||
1275 | if (!next_task) | ||
1276 | return 0; | ||
1277 | |||
1278 | retry: | ||
1279 | if (unlikely(next_task == rq->curr)) { | ||
1280 | WARN_ON(1); | ||
1281 | return 0; | ||
1282 | } | ||
1283 | |||
1284 | /* | ||
1285 | * If next_task preempts rq->curr, and rq->curr | ||
1286 | * can move away, it makes sense to just reschedule | ||
1287 | * without going further in pushing next_task. | ||
1288 | */ | ||
1289 | if (dl_task(rq->curr) && | ||
1290 | dl_time_before(next_task->dl.deadline, rq->curr->dl.deadline) && | ||
1291 | rq->curr->nr_cpus_allowed > 1) { | ||
1292 | resched_task(rq->curr); | ||
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1296 | /* We might release rq lock */ | ||
1297 | get_task_struct(next_task); | ||
1298 | |||
1299 | /* Will lock the rq it'll find */ | ||
1300 | later_rq = find_lock_later_rq(next_task, rq); | ||
1301 | if (!later_rq) { | ||
1302 | struct task_struct *task; | ||
1303 | |||
1304 | /* | ||
1305 | * We must check all this again, since | ||
1306 | * find_lock_later_rq releases rq->lock and it is | ||
1307 | * then possible that next_task has migrated. | ||
1308 | */ | ||
1309 | task = pick_next_pushable_dl_task(rq); | ||
1310 | if (task_cpu(next_task) == rq->cpu && task == next_task) { | ||
1311 | /* | ||
1312 | * The task is still there. We don't try | ||
1313 | * again, some other cpu will pull it when ready. | ||
1314 | */ | ||
1315 | dequeue_pushable_dl_task(rq, next_task); | ||
1316 | goto out; | ||
1317 | } | ||
1318 | |||
1319 | if (!task) | ||
1320 | /* No more tasks */ | ||
1321 | goto out; | ||
1322 | |||
1323 | put_task_struct(next_task); | ||
1324 | next_task = task; | ||
1325 | goto retry; | ||
1326 | } | ||
1327 | |||
1328 | deactivate_task(rq, next_task, 0); | ||
1329 | set_task_cpu(next_task, later_rq->cpu); | ||
1330 | activate_task(later_rq, next_task, 0); | ||
1331 | |||
1332 | resched_task(later_rq->curr); | ||
1333 | |||
1334 | double_unlock_balance(rq, later_rq); | ||
1335 | |||
1336 | out: | ||
1337 | put_task_struct(next_task); | ||
1338 | |||
1339 | return 1; | ||
1340 | } | ||
1341 | |||
1342 | static void push_dl_tasks(struct rq *rq) | ||
1343 | { | ||
1344 | /* Terminates as it moves a -deadline task */ | ||
1345 | while (push_dl_task(rq)) | ||
1346 | ; | ||
1347 | } | ||
1348 | |||
1349 | static int pull_dl_task(struct rq *this_rq) | ||
1350 | { | ||
1351 | int this_cpu = this_rq->cpu, ret = 0, cpu; | ||
1352 | struct task_struct *p; | ||
1353 | struct rq *src_rq; | ||
1354 | u64 dmin = LONG_MAX; | ||
1355 | |||
1356 | if (likely(!dl_overloaded(this_rq))) | ||
1357 | return 0; | ||
1358 | |||
1359 | /* | ||
1360 | * Match the barrier from dl_set_overloaded; this guarantees that if we | ||
1361 | * see overloaded we must also see the dlo_mask bit. | ||
1362 | */ | ||
1363 | smp_rmb(); | ||
1364 | |||
1365 | for_each_cpu(cpu, this_rq->rd->dlo_mask) { | ||
1366 | if (this_cpu == cpu) | ||
1367 | continue; | ||
1368 | |||
1369 | src_rq = cpu_rq(cpu); | ||
1370 | |||
1371 | /* | ||
1372 | * It looks racy, abd it is! However, as in sched_rt.c, | ||
1373 | * we are fine with this. | ||
1374 | */ | ||
1375 | if (this_rq->dl.dl_nr_running && | ||
1376 | dl_time_before(this_rq->dl.earliest_dl.curr, | ||
1377 | src_rq->dl.earliest_dl.next)) | ||
1378 | continue; | ||
1379 | |||
1380 | /* Might drop this_rq->lock */ | ||
1381 | double_lock_balance(this_rq, src_rq); | ||
1382 | |||
1383 | /* | ||
1384 | * If there are no more pullable tasks on the | ||
1385 | * rq, we're done with it. | ||
1386 | */ | ||
1387 | if (src_rq->dl.dl_nr_running <= 1) | ||
1388 | goto skip; | ||
1389 | |||
1390 | p = pick_next_earliest_dl_task(src_rq, this_cpu); | ||
1391 | |||
1392 | /* | ||
1393 | * We found a task to be pulled if: | ||
1394 | * - it preempts our current (if there's one), | ||
1395 | * - it will preempt the last one we pulled (if any). | ||
1396 | */ | ||
1397 | if (p && dl_time_before(p->dl.deadline, dmin) && | ||
1398 | (!this_rq->dl.dl_nr_running || | ||
1399 | dl_time_before(p->dl.deadline, | ||
1400 | this_rq->dl.earliest_dl.curr))) { | ||
1401 | WARN_ON(p == src_rq->curr); | ||
1402 | WARN_ON(!p->on_rq); | ||
1403 | |||
1404 | /* | ||
1405 | * Then we pull iff p has actually an earlier | ||
1406 | * deadline than the current task of its runqueue. | ||
1407 | */ | ||
1408 | if (dl_time_before(p->dl.deadline, | ||
1409 | src_rq->curr->dl.deadline)) | ||
1410 | goto skip; | ||
1411 | |||
1412 | ret = 1; | ||
1413 | |||
1414 | deactivate_task(src_rq, p, 0); | ||
1415 | set_task_cpu(p, this_cpu); | ||
1416 | activate_task(this_rq, p, 0); | ||
1417 | dmin = p->dl.deadline; | ||
1418 | |||
1419 | /* Is there any other task even earlier? */ | ||
1420 | } | ||
1421 | skip: | ||
1422 | double_unlock_balance(this_rq, src_rq); | ||
1423 | } | ||
1424 | |||
1425 | return ret; | ||
1426 | } | ||
1427 | |||
1428 | static void pre_schedule_dl(struct rq *rq, struct task_struct *prev) | ||
1429 | { | ||
1430 | /* Try to pull other tasks here */ | ||
1431 | if (dl_task(prev)) | ||
1432 | pull_dl_task(rq); | ||
1433 | } | ||
1434 | |||
1435 | static void post_schedule_dl(struct rq *rq) | ||
1436 | { | ||
1437 | push_dl_tasks(rq); | ||
1438 | } | ||
1439 | |||
1440 | /* | ||
1441 | * Since the task is not running and a reschedule is not going to happen | ||
1442 | * anytime soon on its runqueue, we try pushing it away now. | ||
1443 | */ | ||
1444 | static void task_woken_dl(struct rq *rq, struct task_struct *p) | ||
1445 | { | ||
1446 | if (!task_running(rq, p) && | ||
1447 | !test_tsk_need_resched(rq->curr) && | ||
1448 | has_pushable_dl_tasks(rq) && | ||
1449 | p->nr_cpus_allowed > 1 && | ||
1450 | dl_task(rq->curr) && | ||
1451 | (rq->curr->nr_cpus_allowed < 2 || | ||
1452 | dl_entity_preempt(&rq->curr->dl, &p->dl))) { | ||
1453 | push_dl_tasks(rq); | ||
1454 | } | ||
1455 | } | ||
1456 | |||
1457 | static void set_cpus_allowed_dl(struct task_struct *p, | ||
1458 | const struct cpumask *new_mask) | ||
1459 | { | ||
1460 | struct rq *rq; | ||
1461 | int weight; | ||
1462 | |||
1463 | BUG_ON(!dl_task(p)); | ||
1464 | |||
1465 | /* | ||
1466 | * Update only if the task is actually running (i.e., | ||
1467 | * it is on the rq AND it is not throttled). | ||
1468 | */ | ||
1469 | if (!on_dl_rq(&p->dl)) | ||
1470 | return; | ||
1471 | |||
1472 | weight = cpumask_weight(new_mask); | ||
1473 | |||
1474 | /* | ||
1475 | * Only update if the process changes its state from whether it | ||
1476 | * can migrate or not. | ||
1477 | */ | ||
1478 | if ((p->nr_cpus_allowed > 1) == (weight > 1)) | ||
1479 | return; | ||
1480 | |||
1481 | rq = task_rq(p); | ||
1482 | |||
1483 | /* | ||
1484 | * The process used to be able to migrate OR it can now migrate | ||
1485 | */ | ||
1486 | if (weight <= 1) { | ||
1487 | if (!task_current(rq, p)) | ||
1488 | dequeue_pushable_dl_task(rq, p); | ||
1489 | BUG_ON(!rq->dl.dl_nr_migratory); | ||
1490 | rq->dl.dl_nr_migratory--; | ||
1491 | } else { | ||
1492 | if (!task_current(rq, p)) | ||
1493 | enqueue_pushable_dl_task(rq, p); | ||
1494 | rq->dl.dl_nr_migratory++; | ||
1495 | } | ||
1496 | |||
1497 | update_dl_migration(&rq->dl); | ||
1498 | } | ||
1499 | |||
1500 | /* Assumes rq->lock is held */ | ||
1501 | static void rq_online_dl(struct rq *rq) | ||
1502 | { | ||
1503 | if (rq->dl.overloaded) | ||
1504 | dl_set_overload(rq); | ||
1505 | |||
1506 | if (rq->dl.dl_nr_running > 0) | ||
1507 | cpudl_set(&rq->rd->cpudl, rq->cpu, rq->dl.earliest_dl.curr, 1); | ||
1508 | } | ||
1509 | |||
1510 | /* Assumes rq->lock is held */ | ||
1511 | static void rq_offline_dl(struct rq *rq) | ||
1512 | { | ||
1513 | if (rq->dl.overloaded) | ||
1514 | dl_clear_overload(rq); | ||
1515 | |||
1516 | cpudl_set(&rq->rd->cpudl, rq->cpu, 0, 0); | ||
1517 | } | ||
1518 | |||
1519 | void init_sched_dl_class(void) | ||
1520 | { | ||
1521 | unsigned int i; | ||
1522 | |||
1523 | for_each_possible_cpu(i) | ||
1524 | zalloc_cpumask_var_node(&per_cpu(local_cpu_mask_dl, i), | ||
1525 | GFP_KERNEL, cpu_to_node(i)); | ||
1526 | } | ||
1527 | |||
1528 | #endif /* CONFIG_SMP */ | ||
1529 | |||
1530 | static void switched_from_dl(struct rq *rq, struct task_struct *p) | ||
1531 | { | ||
1532 | if (hrtimer_active(&p->dl.dl_timer) && !dl_policy(p->policy)) | ||
1533 | hrtimer_try_to_cancel(&p->dl.dl_timer); | ||
1534 | |||
1535 | #ifdef CONFIG_SMP | ||
1536 | /* | ||
1537 | * Since this might be the only -deadline task on the rq, | ||
1538 | * this is the right place to try to pull some other one | ||
1539 | * from an overloaded cpu, if any. | ||
1540 | */ | ||
1541 | if (!rq->dl.dl_nr_running) | ||
1542 | pull_dl_task(rq); | ||
1543 | #endif | ||
1544 | } | ||
1545 | |||
1546 | /* | ||
1547 | * When switching to -deadline, we may overload the rq, then | ||
1548 | * we try to push someone off, if possible. | ||
1549 | */ | ||
1550 | static void switched_to_dl(struct rq *rq, struct task_struct *p) | ||
1551 | { | ||
1552 | int check_resched = 1; | ||
1553 | |||
1554 | /* | ||
1555 | * If p is throttled, don't consider the possibility | ||
1556 | * of preempting rq->curr, the check will be done right | ||
1557 | * after its runtime will get replenished. | ||
1558 | */ | ||
1559 | if (unlikely(p->dl.dl_throttled)) | ||
1560 | return; | ||
1561 | |||
1562 | if (p->on_rq || rq->curr != p) { | ||
1563 | #ifdef CONFIG_SMP | ||
1564 | if (rq->dl.overloaded && push_dl_task(rq) && rq != task_rq(p)) | ||
1565 | /* Only reschedule if pushing failed */ | ||
1566 | check_resched = 0; | ||
1567 | #endif /* CONFIG_SMP */ | ||
1568 | if (check_resched && task_has_dl_policy(rq->curr)) | ||
1569 | check_preempt_curr_dl(rq, p, 0); | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | /* | ||
1574 | * If the scheduling parameters of a -deadline task changed, | ||
1575 | * a push or pull operation might be needed. | ||
1576 | */ | ||
1577 | static void prio_changed_dl(struct rq *rq, struct task_struct *p, | ||
1578 | int oldprio) | ||
1579 | { | ||
1580 | if (p->on_rq || rq->curr == p) { | ||
1581 | #ifdef CONFIG_SMP | ||
1582 | /* | ||
1583 | * This might be too much, but unfortunately | ||
1584 | * we don't have the old deadline value, and | ||
1585 | * we can't argue if the task is increasing | ||
1586 | * or lowering its prio, so... | ||
1587 | */ | ||
1588 | if (!rq->dl.overloaded) | ||
1589 | pull_dl_task(rq); | ||
1590 | |||
1591 | /* | ||
1592 | * If we now have a earlier deadline task than p, | ||
1593 | * then reschedule, provided p is still on this | ||
1594 | * runqueue. | ||
1595 | */ | ||
1596 | if (dl_time_before(rq->dl.earliest_dl.curr, p->dl.deadline) && | ||
1597 | rq->curr == p) | ||
1598 | resched_task(p); | ||
1599 | #else | ||
1600 | /* | ||
1601 | * Again, we don't know if p has a earlier | ||
1602 | * or later deadline, so let's blindly set a | ||
1603 | * (maybe not needed) rescheduling point. | ||
1604 | */ | ||
1605 | resched_task(p); | ||
1606 | #endif /* CONFIG_SMP */ | ||
1607 | } else | ||
1608 | switched_to_dl(rq, p); | ||
1609 | } | ||
1610 | |||
1611 | const struct sched_class dl_sched_class = { | ||
1612 | .next = &rt_sched_class, | ||
1613 | .enqueue_task = enqueue_task_dl, | ||
1614 | .dequeue_task = dequeue_task_dl, | ||
1615 | .yield_task = yield_task_dl, | ||
1616 | |||
1617 | .check_preempt_curr = check_preempt_curr_dl, | ||
1618 | |||
1619 | .pick_next_task = pick_next_task_dl, | ||
1620 | .put_prev_task = put_prev_task_dl, | ||
1621 | |||
1622 | #ifdef CONFIG_SMP | ||
1623 | .select_task_rq = select_task_rq_dl, | ||
1624 | .set_cpus_allowed = set_cpus_allowed_dl, | ||
1625 | .rq_online = rq_online_dl, | ||
1626 | .rq_offline = rq_offline_dl, | ||
1627 | .pre_schedule = pre_schedule_dl, | ||
1628 | .post_schedule = post_schedule_dl, | ||
1629 | .task_woken = task_woken_dl, | ||
1630 | #endif | ||
1631 | |||
1632 | .set_curr_task = set_curr_task_dl, | ||
1633 | .task_tick = task_tick_dl, | ||
1634 | .task_fork = task_fork_dl, | ||
1635 | .task_dead = task_dead_dl, | ||
1636 | |||
1637 | .prio_changed = prio_changed_dl, | ||
1638 | .switched_from = switched_from_dl, | ||
1639 | .switched_to = switched_to_dl, | ||
1640 | }; | ||
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 5c34d1817e8f..dd52e7ffb10e 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c | |||
@@ -139,7 +139,7 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p) | |||
139 | 0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L); | 139 | 0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L); |
140 | #endif | 140 | #endif |
141 | #ifdef CONFIG_NUMA_BALANCING | 141 | #ifdef CONFIG_NUMA_BALANCING |
142 | SEQ_printf(m, " %d", cpu_to_node(task_cpu(p))); | 142 | SEQ_printf(m, " %d", task_node(p)); |
143 | #endif | 143 | #endif |
144 | #ifdef CONFIG_CGROUP_SCHED | 144 | #ifdef CONFIG_CGROUP_SCHED |
145 | SEQ_printf(m, " %s", task_group_path(task_group(p))); | 145 | SEQ_printf(m, " %s", task_group_path(task_group(p))); |
@@ -371,7 +371,7 @@ static void sched_debug_header(struct seq_file *m) | |||
371 | PN(cpu_clk); | 371 | PN(cpu_clk); |
372 | P(jiffies); | 372 | P(jiffies); |
373 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK | 373 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK |
374 | P(sched_clock_stable); | 374 | P(sched_clock_stable()); |
375 | #endif | 375 | #endif |
376 | #undef PN | 376 | #undef PN |
377 | #undef P | 377 | #undef P |
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index c7395d97e4cb..b24b6cfde9aa 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c | |||
@@ -872,15 +872,6 @@ static unsigned int task_scan_max(struct task_struct *p) | |||
872 | return max(smin, smax); | 872 | return max(smin, smax); |
873 | } | 873 | } |
874 | 874 | ||
875 | /* | ||
876 | * Once a preferred node is selected the scheduler balancer will prefer moving | ||
877 | * a task to that node for sysctl_numa_balancing_settle_count number of PTE | ||
878 | * scans. This will give the process the chance to accumulate more faults on | ||
879 | * the preferred node but still allow the scheduler to move the task again if | ||
880 | * the nodes CPUs are overloaded. | ||
881 | */ | ||
882 | unsigned int sysctl_numa_balancing_settle_count __read_mostly = 4; | ||
883 | |||
884 | static void account_numa_enqueue(struct rq *rq, struct task_struct *p) | 875 | static void account_numa_enqueue(struct rq *rq, struct task_struct *p) |
885 | { | 876 | { |
886 | rq->nr_numa_running += (p->numa_preferred_nid != -1); | 877 | rq->nr_numa_running += (p->numa_preferred_nid != -1); |
@@ -930,7 +921,8 @@ static inline unsigned long group_faults(struct task_struct *p, int nid) | |||
930 | if (!p->numa_group) | 921 | if (!p->numa_group) |
931 | return 0; | 922 | return 0; |
932 | 923 | ||
933 | return p->numa_group->faults[2*nid] + p->numa_group->faults[2*nid+1]; | 924 | return p->numa_group->faults[task_faults_idx(nid, 0)] + |
925 | p->numa_group->faults[task_faults_idx(nid, 1)]; | ||
934 | } | 926 | } |
935 | 927 | ||
936 | /* | 928 | /* |
@@ -1023,7 +1015,7 @@ struct task_numa_env { | |||
1023 | 1015 | ||
1024 | struct numa_stats src_stats, dst_stats; | 1016 | struct numa_stats src_stats, dst_stats; |
1025 | 1017 | ||
1026 | int imbalance_pct, idx; | 1018 | int imbalance_pct; |
1027 | 1019 | ||
1028 | struct task_struct *best_task; | 1020 | struct task_struct *best_task; |
1029 | long best_imp; | 1021 | long best_imp; |
@@ -1211,7 +1203,7 @@ static int task_numa_migrate(struct task_struct *p) | |||
1211 | * elsewhere, so there is no point in (re)trying. | 1203 | * elsewhere, so there is no point in (re)trying. |
1212 | */ | 1204 | */ |
1213 | if (unlikely(!sd)) { | 1205 | if (unlikely(!sd)) { |
1214 | p->numa_preferred_nid = cpu_to_node(task_cpu(p)); | 1206 | p->numa_preferred_nid = task_node(p); |
1215 | return -EINVAL; | 1207 | return -EINVAL; |
1216 | } | 1208 | } |
1217 | 1209 | ||
@@ -1278,7 +1270,7 @@ static void numa_migrate_preferred(struct task_struct *p) | |||
1278 | p->numa_migrate_retry = jiffies + HZ; | 1270 | p->numa_migrate_retry = jiffies + HZ; |
1279 | 1271 | ||
1280 | /* Success if task is already running on preferred CPU */ | 1272 | /* Success if task is already running on preferred CPU */ |
1281 | if (cpu_to_node(task_cpu(p)) == p->numa_preferred_nid) | 1273 | if (task_node(p) == p->numa_preferred_nid) |
1282 | return; | 1274 | return; |
1283 | 1275 | ||
1284 | /* Otherwise, try migrate to a CPU on the preferred node */ | 1276 | /* Otherwise, try migrate to a CPU on the preferred node */ |
@@ -1350,7 +1342,6 @@ static void update_task_scan_period(struct task_struct *p, | |||
1350 | * scanning faster if shared accesses dominate as it may | 1342 | * scanning faster if shared accesses dominate as it may |
1351 | * simply bounce migrations uselessly | 1343 | * simply bounce migrations uselessly |
1352 | */ | 1344 | */ |
1353 | period_slot = DIV_ROUND_UP(diff, NUMA_PERIOD_SLOTS); | ||
1354 | ratio = DIV_ROUND_UP(private * NUMA_PERIOD_SLOTS, (private + shared)); | 1345 | ratio = DIV_ROUND_UP(private * NUMA_PERIOD_SLOTS, (private + shared)); |
1355 | diff = (diff * ratio) / NUMA_PERIOD_SLOTS; | 1346 | diff = (diff * ratio) / NUMA_PERIOD_SLOTS; |
1356 | } | 1347 | } |
@@ -3923,7 +3914,7 @@ static long effective_load(struct task_group *tg, int cpu, long wl, long wg) | |||
3923 | { | 3914 | { |
3924 | struct sched_entity *se = tg->se[cpu]; | 3915 | struct sched_entity *se = tg->se[cpu]; |
3925 | 3916 | ||
3926 | if (!tg->parent || !wl) /* the trivial, non-cgroup case */ | 3917 | if (!tg->parent) /* the trivial, non-cgroup case */ |
3927 | return wl; | 3918 | return wl; |
3928 | 3919 | ||
3929 | for_each_sched_entity(se) { | 3920 | for_each_sched_entity(se) { |
@@ -4101,12 +4092,16 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) | |||
4101 | */ | 4092 | */ |
4102 | static struct sched_group * | 4093 | static struct sched_group * |
4103 | find_idlest_group(struct sched_domain *sd, struct task_struct *p, | 4094 | find_idlest_group(struct sched_domain *sd, struct task_struct *p, |
4104 | int this_cpu, int load_idx) | 4095 | int this_cpu, int sd_flag) |
4105 | { | 4096 | { |
4106 | struct sched_group *idlest = NULL, *group = sd->groups; | 4097 | struct sched_group *idlest = NULL, *group = sd->groups; |
4107 | unsigned long min_load = ULONG_MAX, this_load = 0; | 4098 | unsigned long min_load = ULONG_MAX, this_load = 0; |
4099 | int load_idx = sd->forkexec_idx; | ||
4108 | int imbalance = 100 + (sd->imbalance_pct-100)/2; | 4100 | int imbalance = 100 + (sd->imbalance_pct-100)/2; |
4109 | 4101 | ||
4102 | if (sd_flag & SD_BALANCE_WAKE) | ||
4103 | load_idx = sd->wake_idx; | ||
4104 | |||
4110 | do { | 4105 | do { |
4111 | unsigned long load, avg_load; | 4106 | unsigned long load, avg_load; |
4112 | int local_group; | 4107 | int local_group; |
@@ -4274,7 +4269,6 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f | |||
4274 | } | 4269 | } |
4275 | 4270 | ||
4276 | while (sd) { | 4271 | while (sd) { |
4277 | int load_idx = sd->forkexec_idx; | ||
4278 | struct sched_group *group; | 4272 | struct sched_group *group; |
4279 | int weight; | 4273 | int weight; |
4280 | 4274 | ||
@@ -4283,10 +4277,7 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f | |||
4283 | continue; | 4277 | continue; |
4284 | } | 4278 | } |
4285 | 4279 | ||
4286 | if (sd_flag & SD_BALANCE_WAKE) | 4280 | group = find_idlest_group(sd, p, cpu, sd_flag); |
4287 | load_idx = sd->wake_idx; | ||
4288 | |||
4289 | group = find_idlest_group(sd, p, cpu, load_idx); | ||
4290 | if (!group) { | 4281 | if (!group) { |
4291 | sd = sd->child; | 4282 | sd = sd->child; |
4292 | continue; | 4283 | continue; |
@@ -5512,7 +5503,6 @@ static inline void update_sg_lb_stats(struct lb_env *env, | |||
5512 | struct sched_group *group, int load_idx, | 5503 | struct sched_group *group, int load_idx, |
5513 | int local_group, struct sg_lb_stats *sgs) | 5504 | int local_group, struct sg_lb_stats *sgs) |
5514 | { | 5505 | { |
5515 | unsigned long nr_running; | ||
5516 | unsigned long load; | 5506 | unsigned long load; |
5517 | int i; | 5507 | int i; |
5518 | 5508 | ||
@@ -5521,8 +5511,6 @@ static inline void update_sg_lb_stats(struct lb_env *env, | |||
5521 | for_each_cpu_and(i, sched_group_cpus(group), env->cpus) { | 5511 | for_each_cpu_and(i, sched_group_cpus(group), env->cpus) { |
5522 | struct rq *rq = cpu_rq(i); | 5512 | struct rq *rq = cpu_rq(i); |
5523 | 5513 | ||
5524 | nr_running = rq->nr_running; | ||
5525 | |||
5526 | /* Bias balancing toward cpus of our domain */ | 5514 | /* Bias balancing toward cpus of our domain */ |
5527 | if (local_group) | 5515 | if (local_group) |
5528 | load = target_load(i, load_idx); | 5516 | load = target_load(i, load_idx); |
@@ -5530,7 +5518,7 @@ static inline void update_sg_lb_stats(struct lb_env *env, | |||
5530 | load = source_load(i, load_idx); | 5518 | load = source_load(i, load_idx); |
5531 | 5519 | ||
5532 | sgs->group_load += load; | 5520 | sgs->group_load += load; |
5533 | sgs->sum_nr_running += nr_running; | 5521 | sgs->sum_nr_running += rq->nr_running; |
5534 | #ifdef CONFIG_NUMA_BALANCING | 5522 | #ifdef CONFIG_NUMA_BALANCING |
5535 | sgs->nr_numa_running += rq->nr_numa_running; | 5523 | sgs->nr_numa_running += rq->nr_numa_running; |
5536 | sgs->nr_preferred_running += rq->nr_preferred_running; | 5524 | sgs->nr_preferred_running += rq->nr_preferred_running; |
@@ -6521,7 +6509,7 @@ static struct { | |||
6521 | unsigned long next_balance; /* in jiffy units */ | 6509 | unsigned long next_balance; /* in jiffy units */ |
6522 | } nohz ____cacheline_aligned; | 6510 | } nohz ____cacheline_aligned; |
6523 | 6511 | ||
6524 | static inline int find_new_ilb(int call_cpu) | 6512 | static inline int find_new_ilb(void) |
6525 | { | 6513 | { |
6526 | int ilb = cpumask_first(nohz.idle_cpus_mask); | 6514 | int ilb = cpumask_first(nohz.idle_cpus_mask); |
6527 | 6515 | ||
@@ -6536,13 +6524,13 @@ static inline int find_new_ilb(int call_cpu) | |||
6536 | * nohz_load_balancer CPU (if there is one) otherwise fallback to any idle | 6524 | * nohz_load_balancer CPU (if there is one) otherwise fallback to any idle |
6537 | * CPU (if there is one). | 6525 | * CPU (if there is one). |
6538 | */ | 6526 | */ |
6539 | static void nohz_balancer_kick(int cpu) | 6527 | static void nohz_balancer_kick(void) |
6540 | { | 6528 | { |
6541 | int ilb_cpu; | 6529 | int ilb_cpu; |
6542 | 6530 | ||
6543 | nohz.next_balance++; | 6531 | nohz.next_balance++; |
6544 | 6532 | ||
6545 | ilb_cpu = find_new_ilb(cpu); | 6533 | ilb_cpu = find_new_ilb(); |
6546 | 6534 | ||
6547 | if (ilb_cpu >= nr_cpu_ids) | 6535 | if (ilb_cpu >= nr_cpu_ids) |
6548 | return; | 6536 | return; |
@@ -6652,10 +6640,10 @@ void update_max_interval(void) | |||
6652 | * | 6640 | * |
6653 | * Balancing parameters are set up in init_sched_domains. | 6641 | * Balancing parameters are set up in init_sched_domains. |
6654 | */ | 6642 | */ |
6655 | static void rebalance_domains(int cpu, enum cpu_idle_type idle) | 6643 | static void rebalance_domains(struct rq *rq, enum cpu_idle_type idle) |
6656 | { | 6644 | { |
6657 | int continue_balancing = 1; | 6645 | int continue_balancing = 1; |
6658 | struct rq *rq = cpu_rq(cpu); | 6646 | int cpu = rq->cpu; |
6659 | unsigned long interval; | 6647 | unsigned long interval; |
6660 | struct sched_domain *sd; | 6648 | struct sched_domain *sd; |
6661 | /* Earliest time when we have to do rebalance again */ | 6649 | /* Earliest time when we have to do rebalance again */ |
@@ -6752,9 +6740,9 @@ out: | |||
6752 | * In CONFIG_NO_HZ_COMMON case, the idle balance kickee will do the | 6740 | * In CONFIG_NO_HZ_COMMON case, the idle balance kickee will do the |
6753 | * rebalancing for all the cpus for whom scheduler ticks are stopped. | 6741 | * rebalancing for all the cpus for whom scheduler ticks are stopped. |
6754 | */ | 6742 | */ |
6755 | static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle) | 6743 | static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle) |
6756 | { | 6744 | { |
6757 | struct rq *this_rq = cpu_rq(this_cpu); | 6745 | int this_cpu = this_rq->cpu; |
6758 | struct rq *rq; | 6746 | struct rq *rq; |
6759 | int balance_cpu; | 6747 | int balance_cpu; |
6760 | 6748 | ||
@@ -6781,7 +6769,7 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle) | |||
6781 | update_idle_cpu_load(rq); | 6769 | update_idle_cpu_load(rq); |
6782 | raw_spin_unlock_irq(&rq->lock); | 6770 | raw_spin_unlock_irq(&rq->lock); |
6783 | 6771 | ||
6784 | rebalance_domains(balance_cpu, CPU_IDLE); | 6772 | rebalance_domains(rq, CPU_IDLE); |
6785 | 6773 | ||
6786 | if (time_after(this_rq->next_balance, rq->next_balance)) | 6774 | if (time_after(this_rq->next_balance, rq->next_balance)) |
6787 | this_rq->next_balance = rq->next_balance; | 6775 | this_rq->next_balance = rq->next_balance; |
@@ -6800,14 +6788,14 @@ end: | |||
6800 | * - For SD_ASYM_PACKING, if the lower numbered cpu's in the scheduler | 6788 | * - For SD_ASYM_PACKING, if the lower numbered cpu's in the scheduler |
6801 | * domain span are idle. | 6789 | * domain span are idle. |
6802 | */ | 6790 | */ |
6803 | static inline int nohz_kick_needed(struct rq *rq, int cpu) | 6791 | static inline int nohz_kick_needed(struct rq *rq) |
6804 | { | 6792 | { |
6805 | unsigned long now = jiffies; | 6793 | unsigned long now = jiffies; |
6806 | struct sched_domain *sd; | 6794 | struct sched_domain *sd; |
6807 | struct sched_group_power *sgp; | 6795 | struct sched_group_power *sgp; |
6808 | int nr_busy; | 6796 | int nr_busy, cpu = rq->cpu; |
6809 | 6797 | ||
6810 | if (unlikely(idle_cpu(cpu))) | 6798 | if (unlikely(rq->idle_balance)) |
6811 | return 0; | 6799 | return 0; |
6812 | 6800 | ||
6813 | /* | 6801 | /* |
@@ -6856,7 +6844,7 @@ need_kick: | |||
6856 | return 1; | 6844 | return 1; |
6857 | } | 6845 | } |
6858 | #else | 6846 | #else |
6859 | static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle) { } | 6847 | static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle) { } |
6860 | #endif | 6848 | #endif |
6861 | 6849 | ||
6862 | /* | 6850 | /* |
@@ -6865,38 +6853,39 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle) { } | |||
6865 | */ | 6853 | */ |
6866 | static void run_rebalance_domains(struct softirq_action *h) | 6854 | static void run_rebalance_domains(struct softirq_action *h) |
6867 | { | 6855 | { |
6868 | int this_cpu = smp_processor_id(); | 6856 | struct rq *this_rq = this_rq(); |
6869 | struct rq *this_rq = cpu_rq(this_cpu); | ||
6870 | enum cpu_idle_type idle = this_rq->idle_balance ? | 6857 | enum cpu_idle_type idle = this_rq->idle_balance ? |
6871 | CPU_IDLE : CPU_NOT_IDLE; | 6858 | CPU_IDLE : CPU_NOT_IDLE; |
6872 | 6859 | ||
6873 | rebalance_domains(this_cpu, idle); | 6860 | rebalance_domains(this_rq, idle); |
6874 | 6861 | ||
6875 | /* | 6862 | /* |
6876 | * If this cpu has a pending nohz_balance_kick, then do the | 6863 | * If this cpu has a pending nohz_balance_kick, then do the |
6877 | * balancing on behalf of the other idle cpus whose ticks are | 6864 | * balancing on behalf of the other idle cpus whose ticks are |
6878 | * stopped. | 6865 | * stopped. |
6879 | */ | 6866 | */ |
6880 | nohz_idle_balance(this_cpu, idle); | 6867 | nohz_idle_balance(this_rq, idle); |
6881 | } | 6868 | } |
6882 | 6869 | ||
6883 | static inline int on_null_domain(int cpu) | 6870 | static inline int on_null_domain(struct rq *rq) |
6884 | { | 6871 | { |
6885 | return !rcu_dereference_sched(cpu_rq(cpu)->sd); | 6872 | return !rcu_dereference_sched(rq->sd); |
6886 | } | 6873 | } |
6887 | 6874 | ||
6888 | /* | 6875 | /* |
6889 | * Trigger the SCHED_SOFTIRQ if it is time to do periodic load balancing. | 6876 | * Trigger the SCHED_SOFTIRQ if it is time to do periodic load balancing. |
6890 | */ | 6877 | */ |
6891 | void trigger_load_balance(struct rq *rq, int cpu) | 6878 | void trigger_load_balance(struct rq *rq) |
6892 | { | 6879 | { |
6893 | /* Don't need to rebalance while attached to NULL domain */ | 6880 | /* Don't need to rebalance while attached to NULL domain */ |
6894 | if (time_after_eq(jiffies, rq->next_balance) && | 6881 | if (unlikely(on_null_domain(rq))) |
6895 | likely(!on_null_domain(cpu))) | 6882 | return; |
6883 | |||
6884 | if (time_after_eq(jiffies, rq->next_balance)) | ||
6896 | raise_softirq(SCHED_SOFTIRQ); | 6885 | raise_softirq(SCHED_SOFTIRQ); |
6897 | #ifdef CONFIG_NO_HZ_COMMON | 6886 | #ifdef CONFIG_NO_HZ_COMMON |
6898 | if (nohz_kick_needed(rq, cpu) && likely(!on_null_domain(cpu))) | 6887 | if (nohz_kick_needed(rq)) |
6899 | nohz_balancer_kick(cpu); | 6888 | nohz_balancer_kick(); |
6900 | #endif | 6889 | #endif |
6901 | } | 6890 | } |
6902 | 6891 | ||
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 1c4065575fa2..a2740b775b45 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c | |||
@@ -1738,7 +1738,7 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p) | |||
1738 | !test_tsk_need_resched(rq->curr) && | 1738 | !test_tsk_need_resched(rq->curr) && |
1739 | has_pushable_tasks(rq) && | 1739 | has_pushable_tasks(rq) && |
1740 | p->nr_cpus_allowed > 1 && | 1740 | p->nr_cpus_allowed > 1 && |
1741 | rt_task(rq->curr) && | 1741 | (dl_task(rq->curr) || rt_task(rq->curr)) && |
1742 | (rq->curr->nr_cpus_allowed < 2 || | 1742 | (rq->curr->nr_cpus_allowed < 2 || |
1743 | rq->curr->prio <= p->prio)) | 1743 | rq->curr->prio <= p->prio)) |
1744 | push_rt_tasks(rq); | 1744 | push_rt_tasks(rq); |
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 88c85b21d633..c2119fd20f8b 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <linux/sched.h> | 2 | #include <linux/sched.h> |
3 | #include <linux/sched/sysctl.h> | 3 | #include <linux/sched/sysctl.h> |
4 | #include <linux/sched/rt.h> | 4 | #include <linux/sched/rt.h> |
5 | #include <linux/sched/deadline.h> | ||
5 | #include <linux/mutex.h> | 6 | #include <linux/mutex.h> |
6 | #include <linux/spinlock.h> | 7 | #include <linux/spinlock.h> |
7 | #include <linux/stop_machine.h> | 8 | #include <linux/stop_machine.h> |
@@ -9,6 +10,7 @@ | |||
9 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
10 | 11 | ||
11 | #include "cpupri.h" | 12 | #include "cpupri.h" |
13 | #include "cpudeadline.h" | ||
12 | #include "cpuacct.h" | 14 | #include "cpuacct.h" |
13 | 15 | ||
14 | struct rq; | 16 | struct rq; |
@@ -73,6 +75,13 @@ extern void update_cpu_load_active(struct rq *this_rq); | |||
73 | #define NICE_0_SHIFT SCHED_LOAD_SHIFT | 75 | #define NICE_0_SHIFT SCHED_LOAD_SHIFT |
74 | 76 | ||
75 | /* | 77 | /* |
78 | * Single value that decides SCHED_DEADLINE internal math precision. | ||
79 | * 10 -> just above 1us | ||
80 | * 9 -> just above 0.5us | ||
81 | */ | ||
82 | #define DL_SCALE (10) | ||
83 | |||
84 | /* | ||
76 | * These are the 'tuning knobs' of the scheduler: | 85 | * These are the 'tuning knobs' of the scheduler: |
77 | */ | 86 | */ |
78 | 87 | ||
@@ -81,11 +90,19 @@ extern void update_cpu_load_active(struct rq *this_rq); | |||
81 | */ | 90 | */ |
82 | #define RUNTIME_INF ((u64)~0ULL) | 91 | #define RUNTIME_INF ((u64)~0ULL) |
83 | 92 | ||
93 | static inline int fair_policy(int policy) | ||
94 | { | ||
95 | return policy == SCHED_NORMAL || policy == SCHED_BATCH; | ||
96 | } | ||
97 | |||
84 | static inline int rt_policy(int policy) | 98 | static inline int rt_policy(int policy) |
85 | { | 99 | { |
86 | if (policy == SCHED_FIFO || policy == SCHED_RR) | 100 | return policy == SCHED_FIFO || policy == SCHED_RR; |
87 | return 1; | 101 | } |
88 | return 0; | 102 | |
103 | static inline int dl_policy(int policy) | ||
104 | { | ||
105 | return policy == SCHED_DEADLINE; | ||
89 | } | 106 | } |
90 | 107 | ||
91 | static inline int task_has_rt_policy(struct task_struct *p) | 108 | static inline int task_has_rt_policy(struct task_struct *p) |
@@ -93,6 +110,25 @@ static inline int task_has_rt_policy(struct task_struct *p) | |||
93 | return rt_policy(p->policy); | 110 | return rt_policy(p->policy); |
94 | } | 111 | } |
95 | 112 | ||
113 | static inline int task_has_dl_policy(struct task_struct *p) | ||
114 | { | ||
115 | return dl_policy(p->policy); | ||
116 | } | ||
117 | |||
118 | static inline bool dl_time_before(u64 a, u64 b) | ||
119 | { | ||
120 | return (s64)(a - b) < 0; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Tells if entity @a should preempt entity @b. | ||
125 | */ | ||
126 | static inline bool | ||
127 | dl_entity_preempt(struct sched_dl_entity *a, struct sched_dl_entity *b) | ||
128 | { | ||
129 | return dl_time_before(a->deadline, b->deadline); | ||
130 | } | ||
131 | |||
96 | /* | 132 | /* |
97 | * This is the priority-queue data structure of the RT scheduling class: | 133 | * This is the priority-queue data structure of the RT scheduling class: |
98 | */ | 134 | */ |
@@ -108,6 +144,47 @@ struct rt_bandwidth { | |||
108 | u64 rt_runtime; | 144 | u64 rt_runtime; |
109 | struct hrtimer rt_period_timer; | 145 | struct hrtimer rt_period_timer; |
110 | }; | 146 | }; |
147 | /* | ||
148 | * To keep the bandwidth of -deadline tasks and groups under control | ||
149 | * we need some place where: | ||
150 | * - store the maximum -deadline bandwidth of the system (the group); | ||
151 | * - cache the fraction of that bandwidth that is currently allocated. | ||
152 | * | ||
153 | * This is all done in the data structure below. It is similar to the | ||
154 | * one used for RT-throttling (rt_bandwidth), with the main difference | ||
155 | * that, since here we are only interested in admission control, we | ||
156 | * do not decrease any runtime while the group "executes", neither we | ||
157 | * need a timer to replenish it. | ||
158 | * | ||
159 | * With respect to SMP, the bandwidth is given on a per-CPU basis, | ||
160 | * meaning that: | ||
161 | * - dl_bw (< 100%) is the bandwidth of the system (group) on each CPU; | ||
162 | * - dl_total_bw array contains, in the i-eth element, the currently | ||
163 | * allocated bandwidth on the i-eth CPU. | ||
164 | * Moreover, groups consume bandwidth on each CPU, while tasks only | ||
165 | * consume bandwidth on the CPU they're running on. | ||
166 | * Finally, dl_total_bw_cpu is used to cache the index of dl_total_bw | ||
167 | * that will be shown the next time the proc or cgroup controls will | ||
168 | * be red. It on its turn can be changed by writing on its own | ||
169 | * control. | ||
170 | */ | ||
171 | struct dl_bandwidth { | ||
172 | raw_spinlock_t dl_runtime_lock; | ||
173 | u64 dl_runtime; | ||
174 | u64 dl_period; | ||
175 | }; | ||
176 | |||
177 | static inline int dl_bandwidth_enabled(void) | ||
178 | { | ||
179 | return sysctl_sched_rt_runtime >= 0; | ||
180 | } | ||
181 | |||
182 | extern struct dl_bw *dl_bw_of(int i); | ||
183 | |||
184 | struct dl_bw { | ||
185 | raw_spinlock_t lock; | ||
186 | u64 bw, total_bw; | ||
187 | }; | ||
111 | 188 | ||
112 | extern struct mutex sched_domains_mutex; | 189 | extern struct mutex sched_domains_mutex; |
113 | 190 | ||
@@ -364,6 +441,42 @@ struct rt_rq { | |||
364 | #endif | 441 | #endif |
365 | }; | 442 | }; |
366 | 443 | ||
444 | /* Deadline class' related fields in a runqueue */ | ||
445 | struct dl_rq { | ||
446 | /* runqueue is an rbtree, ordered by deadline */ | ||
447 | struct rb_root rb_root; | ||
448 | struct rb_node *rb_leftmost; | ||
449 | |||
450 | unsigned long dl_nr_running; | ||
451 | |||
452 | #ifdef CONFIG_SMP | ||
453 | /* | ||
454 | * Deadline values of the currently executing and the | ||
455 | * earliest ready task on this rq. Caching these facilitates | ||
456 | * the decision wether or not a ready but not running task | ||
457 | * should migrate somewhere else. | ||
458 | */ | ||
459 | struct { | ||
460 | u64 curr; | ||
461 | u64 next; | ||
462 | } earliest_dl; | ||
463 | |||
464 | unsigned long dl_nr_migratory; | ||
465 | unsigned long dl_nr_total; | ||
466 | int overloaded; | ||
467 | |||
468 | /* | ||
469 | * Tasks on this rq that can be pushed away. They are kept in | ||
470 | * an rb-tree, ordered by tasks' deadlines, with caching | ||
471 | * of the leftmost (earliest deadline) element. | ||
472 | */ | ||
473 | struct rb_root pushable_dl_tasks_root; | ||
474 | struct rb_node *pushable_dl_tasks_leftmost; | ||
475 | #else | ||
476 | struct dl_bw dl_bw; | ||
477 | #endif | ||
478 | }; | ||
479 | |||
367 | #ifdef CONFIG_SMP | 480 | #ifdef CONFIG_SMP |
368 | 481 | ||
369 | /* | 482 | /* |
@@ -382,6 +495,15 @@ struct root_domain { | |||
382 | cpumask_var_t online; | 495 | cpumask_var_t online; |
383 | 496 | ||
384 | /* | 497 | /* |
498 | * The bit corresponding to a CPU gets set here if such CPU has more | ||
499 | * than one runnable -deadline task (as it is below for RT tasks). | ||
500 | */ | ||
501 | cpumask_var_t dlo_mask; | ||
502 | atomic_t dlo_count; | ||
503 | struct dl_bw dl_bw; | ||
504 | struct cpudl cpudl; | ||
505 | |||
506 | /* | ||
385 | * The "RT overload" flag: it gets set if a CPU has more than | 507 | * The "RT overload" flag: it gets set if a CPU has more than |
386 | * one runnable RT task. | 508 | * one runnable RT task. |
387 | */ | 509 | */ |
@@ -432,6 +554,7 @@ struct rq { | |||
432 | 554 | ||
433 | struct cfs_rq cfs; | 555 | struct cfs_rq cfs; |
434 | struct rt_rq rt; | 556 | struct rt_rq rt; |
557 | struct dl_rq dl; | ||
435 | 558 | ||
436 | #ifdef CONFIG_FAIR_GROUP_SCHED | 559 | #ifdef CONFIG_FAIR_GROUP_SCHED |
437 | /* list of leaf cfs_rq on this cpu: */ | 560 | /* list of leaf cfs_rq on this cpu: */ |
@@ -827,8 +950,6 @@ static inline u64 global_rt_runtime(void) | |||
827 | return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC; | 950 | return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC; |
828 | } | 951 | } |
829 | 952 | ||
830 | |||
831 | |||
832 | static inline int task_current(struct rq *rq, struct task_struct *p) | 953 | static inline int task_current(struct rq *rq, struct task_struct *p) |
833 | { | 954 | { |
834 | return rq->curr == p; | 955 | return rq->curr == p; |
@@ -988,6 +1109,7 @@ static const u32 prio_to_wmult[40] = { | |||
988 | #else | 1109 | #else |
989 | #define ENQUEUE_WAKING 0 | 1110 | #define ENQUEUE_WAKING 0 |
990 | #endif | 1111 | #endif |
1112 | #define ENQUEUE_REPLENISH 8 | ||
991 | 1113 | ||
992 | #define DEQUEUE_SLEEP 1 | 1114 | #define DEQUEUE_SLEEP 1 |
993 | 1115 | ||
@@ -1023,6 +1145,7 @@ struct sched_class { | |||
1023 | void (*set_curr_task) (struct rq *rq); | 1145 | void (*set_curr_task) (struct rq *rq); |
1024 | void (*task_tick) (struct rq *rq, struct task_struct *p, int queued); | 1146 | void (*task_tick) (struct rq *rq, struct task_struct *p, int queued); |
1025 | void (*task_fork) (struct task_struct *p); | 1147 | void (*task_fork) (struct task_struct *p); |
1148 | void (*task_dead) (struct task_struct *p); | ||
1026 | 1149 | ||
1027 | void (*switched_from) (struct rq *this_rq, struct task_struct *task); | 1150 | void (*switched_from) (struct rq *this_rq, struct task_struct *task); |
1028 | void (*switched_to) (struct rq *this_rq, struct task_struct *task); | 1151 | void (*switched_to) (struct rq *this_rq, struct task_struct *task); |
@@ -1042,6 +1165,7 @@ struct sched_class { | |||
1042 | for (class = sched_class_highest; class; class = class->next) | 1165 | for (class = sched_class_highest; class; class = class->next) |
1043 | 1166 | ||
1044 | extern const struct sched_class stop_sched_class; | 1167 | extern const struct sched_class stop_sched_class; |
1168 | extern const struct sched_class dl_sched_class; | ||
1045 | extern const struct sched_class rt_sched_class; | 1169 | extern const struct sched_class rt_sched_class; |
1046 | extern const struct sched_class fair_sched_class; | 1170 | extern const struct sched_class fair_sched_class; |
1047 | extern const struct sched_class idle_sched_class; | 1171 | extern const struct sched_class idle_sched_class; |
@@ -1051,7 +1175,7 @@ extern const struct sched_class idle_sched_class; | |||
1051 | 1175 | ||
1052 | extern void update_group_power(struct sched_domain *sd, int cpu); | 1176 | extern void update_group_power(struct sched_domain *sd, int cpu); |
1053 | 1177 | ||
1054 | extern void trigger_load_balance(struct rq *rq, int cpu); | 1178 | extern void trigger_load_balance(struct rq *rq); |
1055 | extern void idle_balance(int this_cpu, struct rq *this_rq); | 1179 | extern void idle_balance(int this_cpu, struct rq *this_rq); |
1056 | 1180 | ||
1057 | extern void idle_enter_fair(struct rq *this_rq); | 1181 | extern void idle_enter_fair(struct rq *this_rq); |
@@ -1068,8 +1192,11 @@ static inline void idle_balance(int cpu, struct rq *rq) | |||
1068 | extern void sysrq_sched_debug_show(void); | 1192 | extern void sysrq_sched_debug_show(void); |
1069 | extern void sched_init_granularity(void); | 1193 | extern void sched_init_granularity(void); |
1070 | extern void update_max_interval(void); | 1194 | extern void update_max_interval(void); |
1195 | |||
1196 | extern void init_sched_dl_class(void); | ||
1071 | extern void init_sched_rt_class(void); | 1197 | extern void init_sched_rt_class(void); |
1072 | extern void init_sched_fair_class(void); | 1198 | extern void init_sched_fair_class(void); |
1199 | extern void init_sched_dl_class(void); | ||
1073 | 1200 | ||
1074 | extern void resched_task(struct task_struct *p); | 1201 | extern void resched_task(struct task_struct *p); |
1075 | extern void resched_cpu(int cpu); | 1202 | extern void resched_cpu(int cpu); |
@@ -1077,6 +1204,12 @@ extern void resched_cpu(int cpu); | |||
1077 | extern struct rt_bandwidth def_rt_bandwidth; | 1204 | extern struct rt_bandwidth def_rt_bandwidth; |
1078 | extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime); | 1205 | extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime); |
1079 | 1206 | ||
1207 | extern struct dl_bandwidth def_dl_bandwidth; | ||
1208 | extern void init_dl_bandwidth(struct dl_bandwidth *dl_b, u64 period, u64 runtime); | ||
1209 | extern void init_dl_task_timer(struct sched_dl_entity *dl_se); | ||
1210 | |||
1211 | unsigned long to_ratio(u64 period, u64 runtime); | ||
1212 | |||
1080 | extern void update_idle_cpu_load(struct rq *this_rq); | 1213 | extern void update_idle_cpu_load(struct rq *this_rq); |
1081 | 1214 | ||
1082 | extern void init_task_runnable_average(struct task_struct *p); | 1215 | extern void init_task_runnable_average(struct task_struct *p); |
@@ -1353,6 +1486,7 @@ extern void print_rt_stats(struct seq_file *m, int cpu); | |||
1353 | 1486 | ||
1354 | extern void init_cfs_rq(struct cfs_rq *cfs_rq); | 1487 | extern void init_cfs_rq(struct cfs_rq *cfs_rq); |
1355 | extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq); | 1488 | extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq); |
1489 | extern void init_dl_rq(struct dl_rq *dl_rq, struct rq *rq); | ||
1356 | 1490 | ||
1357 | extern void cfs_bandwidth_usage_inc(void); | 1491 | extern void cfs_bandwidth_usage_inc(void); |
1358 | extern void cfs_bandwidth_usage_dec(void); | 1492 | extern void cfs_bandwidth_usage_dec(void); |
diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index 47197de8abd9..fdb6bb0b3356 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c | |||
@@ -103,7 +103,7 @@ get_rr_interval_stop(struct rq *rq, struct task_struct *task) | |||
103 | * Simple, special scheduling class for the per-CPU stop tasks: | 103 | * Simple, special scheduling class for the per-CPU stop tasks: |
104 | */ | 104 | */ |
105 | const struct sched_class stop_sched_class = { | 105 | const struct sched_class stop_sched_class = { |
106 | .next = &rt_sched_class, | 106 | .next = &dl_sched_class, |
107 | 107 | ||
108 | .enqueue_task = enqueue_task_stop, | 108 | .enqueue_task = enqueue_task_stop, |
109 | .dequeue_task = dequeue_task_stop, | 109 | .dequeue_task = dequeue_task_stop, |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 11025ccc06dd..8a1e6e104892 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -89,7 +89,7 @@ static void wakeup_softirqd(void) | |||
89 | * where hardirqs are disabled legitimately: | 89 | * where hardirqs are disabled legitimately: |
90 | */ | 90 | */ |
91 | #ifdef CONFIG_TRACE_IRQFLAGS | 91 | #ifdef CONFIG_TRACE_IRQFLAGS |
92 | static void __local_bh_disable(unsigned long ip, unsigned int cnt) | 92 | void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) |
93 | { | 93 | { |
94 | unsigned long flags; | 94 | unsigned long flags; |
95 | 95 | ||
@@ -107,33 +107,21 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt) | |||
107 | /* | 107 | /* |
108 | * Were softirqs turned off above: | 108 | * Were softirqs turned off above: |
109 | */ | 109 | */ |
110 | if (softirq_count() == cnt) | 110 | if (softirq_count() == (cnt & SOFTIRQ_MASK)) |
111 | trace_softirqs_off(ip); | 111 | trace_softirqs_off(ip); |
112 | raw_local_irq_restore(flags); | 112 | raw_local_irq_restore(flags); |
113 | 113 | ||
114 | if (preempt_count() == cnt) | 114 | if (preempt_count() == cnt) |
115 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); | 115 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); |
116 | } | 116 | } |
117 | #else /* !CONFIG_TRACE_IRQFLAGS */ | 117 | EXPORT_SYMBOL(__local_bh_disable_ip); |
118 | static inline void __local_bh_disable(unsigned long ip, unsigned int cnt) | ||
119 | { | ||
120 | preempt_count_add(cnt); | ||
121 | barrier(); | ||
122 | } | ||
123 | #endif /* CONFIG_TRACE_IRQFLAGS */ | 118 | #endif /* CONFIG_TRACE_IRQFLAGS */ |
124 | 119 | ||
125 | void local_bh_disable(void) | ||
126 | { | ||
127 | __local_bh_disable(_RET_IP_, SOFTIRQ_DISABLE_OFFSET); | ||
128 | } | ||
129 | |||
130 | EXPORT_SYMBOL(local_bh_disable); | ||
131 | |||
132 | static void __local_bh_enable(unsigned int cnt) | 120 | static void __local_bh_enable(unsigned int cnt) |
133 | { | 121 | { |
134 | WARN_ON_ONCE(!irqs_disabled()); | 122 | WARN_ON_ONCE(!irqs_disabled()); |
135 | 123 | ||
136 | if (softirq_count() == cnt) | 124 | if (softirq_count() == (cnt & SOFTIRQ_MASK)) |
137 | trace_softirqs_on(_RET_IP_); | 125 | trace_softirqs_on(_RET_IP_); |
138 | preempt_count_sub(cnt); | 126 | preempt_count_sub(cnt); |
139 | } | 127 | } |
@@ -151,7 +139,7 @@ void _local_bh_enable(void) | |||
151 | 139 | ||
152 | EXPORT_SYMBOL(_local_bh_enable); | 140 | EXPORT_SYMBOL(_local_bh_enable); |
153 | 141 | ||
154 | static inline void _local_bh_enable_ip(unsigned long ip) | 142 | void __local_bh_enable_ip(unsigned long ip, unsigned int cnt) |
155 | { | 143 | { |
156 | WARN_ON_ONCE(in_irq() || irqs_disabled()); | 144 | WARN_ON_ONCE(in_irq() || irqs_disabled()); |
157 | #ifdef CONFIG_TRACE_IRQFLAGS | 145 | #ifdef CONFIG_TRACE_IRQFLAGS |
@@ -166,7 +154,7 @@ static inline void _local_bh_enable_ip(unsigned long ip) | |||
166 | * Keep preemption disabled until we are done with | 154 | * Keep preemption disabled until we are done with |
167 | * softirq processing: | 155 | * softirq processing: |
168 | */ | 156 | */ |
169 | preempt_count_sub(SOFTIRQ_DISABLE_OFFSET - 1); | 157 | preempt_count_sub(cnt - 1); |
170 | 158 | ||
171 | if (unlikely(!in_interrupt() && local_softirq_pending())) { | 159 | if (unlikely(!in_interrupt() && local_softirq_pending())) { |
172 | /* | 160 | /* |
@@ -182,18 +170,7 @@ static inline void _local_bh_enable_ip(unsigned long ip) | |||
182 | #endif | 170 | #endif |
183 | preempt_check_resched(); | 171 | preempt_check_resched(); |
184 | } | 172 | } |
185 | 173 | EXPORT_SYMBOL(__local_bh_enable_ip); | |
186 | void local_bh_enable(void) | ||
187 | { | ||
188 | _local_bh_enable_ip(_RET_IP_); | ||
189 | } | ||
190 | EXPORT_SYMBOL(local_bh_enable); | ||
191 | |||
192 | void local_bh_enable_ip(unsigned long ip) | ||
193 | { | ||
194 | _local_bh_enable_ip(ip); | ||
195 | } | ||
196 | EXPORT_SYMBOL(local_bh_enable_ip); | ||
197 | 174 | ||
198 | /* | 175 | /* |
199 | * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times, | 176 | * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times, |
@@ -211,14 +188,48 @@ EXPORT_SYMBOL(local_bh_enable_ip); | |||
211 | #define MAX_SOFTIRQ_TIME msecs_to_jiffies(2) | 188 | #define MAX_SOFTIRQ_TIME msecs_to_jiffies(2) |
212 | #define MAX_SOFTIRQ_RESTART 10 | 189 | #define MAX_SOFTIRQ_RESTART 10 |
213 | 190 | ||
191 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
192 | /* | ||
193 | * When we run softirqs from irq_exit() and thus on the hardirq stack we need | ||
194 | * to keep the lockdep irq context tracking as tight as possible in order to | ||
195 | * not miss-qualify lock contexts and miss possible deadlocks. | ||
196 | */ | ||
197 | |||
198 | static inline bool lockdep_softirq_start(void) | ||
199 | { | ||
200 | bool in_hardirq = false; | ||
201 | |||
202 | if (trace_hardirq_context(current)) { | ||
203 | in_hardirq = true; | ||
204 | trace_hardirq_exit(); | ||
205 | } | ||
206 | |||
207 | lockdep_softirq_enter(); | ||
208 | |||
209 | return in_hardirq; | ||
210 | } | ||
211 | |||
212 | static inline void lockdep_softirq_end(bool in_hardirq) | ||
213 | { | ||
214 | lockdep_softirq_exit(); | ||
215 | |||
216 | if (in_hardirq) | ||
217 | trace_hardirq_enter(); | ||
218 | } | ||
219 | #else | ||
220 | static inline bool lockdep_softirq_start(void) { return false; } | ||
221 | static inline void lockdep_softirq_end(bool in_hardirq) { } | ||
222 | #endif | ||
223 | |||
214 | asmlinkage void __do_softirq(void) | 224 | asmlinkage void __do_softirq(void) |
215 | { | 225 | { |
216 | struct softirq_action *h; | ||
217 | __u32 pending; | ||
218 | unsigned long end = jiffies + MAX_SOFTIRQ_TIME; | 226 | unsigned long end = jiffies + MAX_SOFTIRQ_TIME; |
219 | int cpu; | ||
220 | unsigned long old_flags = current->flags; | 227 | unsigned long old_flags = current->flags; |
221 | int max_restart = MAX_SOFTIRQ_RESTART; | 228 | int max_restart = MAX_SOFTIRQ_RESTART; |
229 | struct softirq_action *h; | ||
230 | bool in_hardirq; | ||
231 | __u32 pending; | ||
232 | int cpu; | ||
222 | 233 | ||
223 | /* | 234 | /* |
224 | * Mask out PF_MEMALLOC s current task context is borrowed for the | 235 | * Mask out PF_MEMALLOC s current task context is borrowed for the |
@@ -230,8 +241,8 @@ asmlinkage void __do_softirq(void) | |||
230 | pending = local_softirq_pending(); | 241 | pending = local_softirq_pending(); |
231 | account_irq_enter_time(current); | 242 | account_irq_enter_time(current); |
232 | 243 | ||
233 | __local_bh_disable(_RET_IP_, SOFTIRQ_OFFSET); | 244 | __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); |
234 | lockdep_softirq_enter(); | 245 | in_hardirq = lockdep_softirq_start(); |
235 | 246 | ||
236 | cpu = smp_processor_id(); | 247 | cpu = smp_processor_id(); |
237 | restart: | 248 | restart: |
@@ -278,16 +289,13 @@ restart: | |||
278 | wakeup_softirqd(); | 289 | wakeup_softirqd(); |
279 | } | 290 | } |
280 | 291 | ||
281 | lockdep_softirq_exit(); | 292 | lockdep_softirq_end(in_hardirq); |
282 | |||
283 | account_irq_exit_time(current); | 293 | account_irq_exit_time(current); |
284 | __local_bh_enable(SOFTIRQ_OFFSET); | 294 | __local_bh_enable(SOFTIRQ_OFFSET); |
285 | WARN_ON_ONCE(in_interrupt()); | 295 | WARN_ON_ONCE(in_interrupt()); |
286 | tsk_restore_flags(current, old_flags, PF_MEMALLOC); | 296 | tsk_restore_flags(current, old_flags, PF_MEMALLOC); |
287 | } | 297 | } |
288 | 298 | ||
289 | |||
290 | |||
291 | asmlinkage void do_softirq(void) | 299 | asmlinkage void do_softirq(void) |
292 | { | 300 | { |
293 | __u32 pending; | 301 | __u32 pending; |
@@ -311,8 +319,6 @@ asmlinkage void do_softirq(void) | |||
311 | */ | 319 | */ |
312 | void irq_enter(void) | 320 | void irq_enter(void) |
313 | { | 321 | { |
314 | int cpu = smp_processor_id(); | ||
315 | |||
316 | rcu_irq_enter(); | 322 | rcu_irq_enter(); |
317 | if (is_idle_task(current) && !in_interrupt()) { | 323 | if (is_idle_task(current) && !in_interrupt()) { |
318 | /* | 324 | /* |
@@ -320,7 +326,7 @@ void irq_enter(void) | |||
320 | * here, as softirq will be serviced on return from interrupt. | 326 | * here, as softirq will be serviced on return from interrupt. |
321 | */ | 327 | */ |
322 | local_bh_disable(); | 328 | local_bh_disable(); |
323 | tick_check_idle(cpu); | 329 | tick_check_idle(); |
324 | _local_bh_enable(); | 330 | _local_bh_enable(); |
325 | } | 331 | } |
326 | 332 | ||
@@ -375,13 +381,13 @@ void irq_exit(void) | |||
375 | #endif | 381 | #endif |
376 | 382 | ||
377 | account_irq_exit_time(current); | 383 | account_irq_exit_time(current); |
378 | trace_hardirq_exit(); | ||
379 | preempt_count_sub(HARDIRQ_OFFSET); | 384 | preempt_count_sub(HARDIRQ_OFFSET); |
380 | if (!in_interrupt() && local_softirq_pending()) | 385 | if (!in_interrupt() && local_softirq_pending()) |
381 | invoke_softirq(); | 386 | invoke_softirq(); |
382 | 387 | ||
383 | tick_irq_exit(); | 388 | tick_irq_exit(); |
384 | rcu_irq_exit(); | 389 | rcu_irq_exit(); |
390 | trace_hardirq_exit(); /* must be last! */ | ||
385 | } | 391 | } |
386 | 392 | ||
387 | /* | 393 | /* |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 34a604726d0b..c8da99f905cf 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -385,13 +385,6 @@ static struct ctl_table kern_table[] = { | |||
385 | .proc_handler = proc_dointvec, | 385 | .proc_handler = proc_dointvec, |
386 | }, | 386 | }, |
387 | { | 387 | { |
388 | .procname = "numa_balancing_settle_count", | ||
389 | .data = &sysctl_numa_balancing_settle_count, | ||
390 | .maxlen = sizeof(unsigned int), | ||
391 | .mode = 0644, | ||
392 | .proc_handler = proc_dointvec, | ||
393 | }, | ||
394 | { | ||
395 | .procname = "numa_balancing_migrate_deferred", | 388 | .procname = "numa_balancing_migrate_deferred", |
396 | .data = &sysctl_numa_balancing_migrate_deferred, | 389 | .data = &sysctl_numa_balancing_migrate_deferred, |
397 | .maxlen = sizeof(unsigned int), | 390 | .maxlen = sizeof(unsigned int), |
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index 68b799375981..0abb36464281 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c | |||
@@ -74,7 +74,7 @@ unsigned long long notrace sched_clock(void) | |||
74 | return cd.epoch_ns; | 74 | return cd.epoch_ns; |
75 | 75 | ||
76 | do { | 76 | do { |
77 | seq = read_seqcount_begin(&cd.seq); | 77 | seq = raw_read_seqcount_begin(&cd.seq); |
78 | epoch_cyc = cd.epoch_cyc; | 78 | epoch_cyc = cd.epoch_cyc; |
79 | epoch_ns = cd.epoch_ns; | 79 | epoch_ns = cd.epoch_ns; |
80 | } while (read_seqcount_retry(&cd.seq, seq)); | 80 | } while (read_seqcount_retry(&cd.seq, seq)); |
@@ -99,10 +99,10 @@ static void notrace update_sched_clock(void) | |||
99 | cd.mult, cd.shift); | 99 | cd.mult, cd.shift); |
100 | 100 | ||
101 | raw_local_irq_save(flags); | 101 | raw_local_irq_save(flags); |
102 | write_seqcount_begin(&cd.seq); | 102 | raw_write_seqcount_begin(&cd.seq); |
103 | cd.epoch_ns = ns; | 103 | cd.epoch_ns = ns; |
104 | cd.epoch_cyc = cyc; | 104 | cd.epoch_cyc = cyc; |
105 | write_seqcount_end(&cd.seq); | 105 | raw_write_seqcount_end(&cd.seq); |
106 | raw_local_irq_restore(flags); | 106 | raw_local_irq_restore(flags); |
107 | } | 107 | } |
108 | 108 | ||
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 9532690daaa9..43780ab5e279 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
@@ -538,10 +538,10 @@ int tick_resume_broadcast_oneshot(struct clock_event_device *bc) | |||
538 | * Called from irq_enter() when idle was interrupted to reenable the | 538 | * Called from irq_enter() when idle was interrupted to reenable the |
539 | * per cpu device. | 539 | * per cpu device. |
540 | */ | 540 | */ |
541 | void tick_check_oneshot_broadcast(int cpu) | 541 | void tick_check_oneshot_broadcast_this_cpu(void) |
542 | { | 542 | { |
543 | if (cpumask_test_cpu(cpu, tick_broadcast_oneshot_mask)) { | 543 | if (cpumask_test_cpu(smp_processor_id(), tick_broadcast_oneshot_mask)) { |
544 | struct tick_device *td = &per_cpu(tick_cpu_device, cpu); | 544 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); |
545 | 545 | ||
546 | /* | 546 | /* |
547 | * We might be in the middle of switching over from | 547 | * We might be in the middle of switching over from |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 162b03ab0ad2..20b2fe37d105 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -85,6 +85,7 @@ static void tick_periodic(int cpu) | |||
85 | 85 | ||
86 | do_timer(1); | 86 | do_timer(1); |
87 | write_sequnlock(&jiffies_lock); | 87 | write_sequnlock(&jiffies_lock); |
88 | update_wall_time(); | ||
88 | } | 89 | } |
89 | 90 | ||
90 | update_process_times(user_mode(get_irq_regs())); | 91 | update_process_times(user_mode(get_irq_regs())); |
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index 18e71f7fbc2a..8329669b51ec 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h | |||
@@ -51,7 +51,7 @@ extern void tick_broadcast_switch_to_oneshot(void); | |||
51 | extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup); | 51 | extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup); |
52 | extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc); | 52 | extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc); |
53 | extern int tick_broadcast_oneshot_active(void); | 53 | extern int tick_broadcast_oneshot_active(void); |
54 | extern void tick_check_oneshot_broadcast(int cpu); | 54 | extern void tick_check_oneshot_broadcast_this_cpu(void); |
55 | bool tick_broadcast_oneshot_available(void); | 55 | bool tick_broadcast_oneshot_available(void); |
56 | # else /* BROADCAST */ | 56 | # else /* BROADCAST */ |
57 | static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) | 57 | static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) |
@@ -62,7 +62,7 @@ static inline void tick_broadcast_oneshot_control(unsigned long reason) { } | |||
62 | static inline void tick_broadcast_switch_to_oneshot(void) { } | 62 | static inline void tick_broadcast_switch_to_oneshot(void) { } |
63 | static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { } | 63 | static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { } |
64 | static inline int tick_broadcast_oneshot_active(void) { return 0; } | 64 | static inline int tick_broadcast_oneshot_active(void) { return 0; } |
65 | static inline void tick_check_oneshot_broadcast(int cpu) { } | 65 | static inline void tick_check_oneshot_broadcast_this_cpu(void) { } |
66 | static inline bool tick_broadcast_oneshot_available(void) { return true; } | 66 | static inline bool tick_broadcast_oneshot_available(void) { return true; } |
67 | # endif /* !BROADCAST */ | 67 | # endif /* !BROADCAST */ |
68 | 68 | ||
@@ -155,3 +155,4 @@ static inline int tick_device_is_functional(struct clock_event_device *dev) | |||
155 | #endif | 155 | #endif |
156 | 156 | ||
157 | extern void do_timer(unsigned long ticks); | 157 | extern void do_timer(unsigned long ticks); |
158 | extern void update_wall_time(void); | ||
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index ea20f7d1ac2c..08cb0c3b8ccb 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -86,6 +86,7 @@ static void tick_do_update_jiffies64(ktime_t now) | |||
86 | tick_next_period = ktime_add(last_jiffies_update, tick_period); | 86 | tick_next_period = ktime_add(last_jiffies_update, tick_period); |
87 | } | 87 | } |
88 | write_sequnlock(&jiffies_lock); | 88 | write_sequnlock(&jiffies_lock); |
89 | update_wall_time(); | ||
89 | } | 90 | } |
90 | 91 | ||
91 | /* | 92 | /* |
@@ -177,7 +178,7 @@ static bool can_stop_full_tick(void) | |||
177 | * TODO: kick full dynticks CPUs when | 178 | * TODO: kick full dynticks CPUs when |
178 | * sched_clock_stable is set. | 179 | * sched_clock_stable is set. |
179 | */ | 180 | */ |
180 | if (!sched_clock_stable) { | 181 | if (!sched_clock_stable()) { |
181 | trace_tick_stop(0, "unstable sched clock\n"); | 182 | trace_tick_stop(0, "unstable sched clock\n"); |
182 | /* | 183 | /* |
183 | * Don't allow the user to think they can get | 184 | * Don't allow the user to think they can get |
@@ -391,11 +392,9 @@ __setup("nohz=", setup_tick_nohz); | |||
391 | */ | 392 | */ |
392 | static void tick_nohz_update_jiffies(ktime_t now) | 393 | static void tick_nohz_update_jiffies(ktime_t now) |
393 | { | 394 | { |
394 | int cpu = smp_processor_id(); | ||
395 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | ||
396 | unsigned long flags; | 395 | unsigned long flags; |
397 | 396 | ||
398 | ts->idle_waketime = now; | 397 | __this_cpu_write(tick_cpu_sched.idle_waketime, now); |
399 | 398 | ||
400 | local_irq_save(flags); | 399 | local_irq_save(flags); |
401 | tick_do_update_jiffies64(now); | 400 | tick_do_update_jiffies64(now); |
@@ -426,17 +425,15 @@ update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_upda | |||
426 | 425 | ||
427 | } | 426 | } |
428 | 427 | ||
429 | static void tick_nohz_stop_idle(int cpu, ktime_t now) | 428 | static void tick_nohz_stop_idle(struct tick_sched *ts, ktime_t now) |
430 | { | 429 | { |
431 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 430 | update_ts_time_stats(smp_processor_id(), ts, now, NULL); |
432 | |||
433 | update_ts_time_stats(cpu, ts, now, NULL); | ||
434 | ts->idle_active = 0; | 431 | ts->idle_active = 0; |
435 | 432 | ||
436 | sched_clock_idle_wakeup_event(0); | 433 | sched_clock_idle_wakeup_event(0); |
437 | } | 434 | } |
438 | 435 | ||
439 | static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts) | 436 | static ktime_t tick_nohz_start_idle(struct tick_sched *ts) |
440 | { | 437 | { |
441 | ktime_t now = ktime_get(); | 438 | ktime_t now = ktime_get(); |
442 | 439 | ||
@@ -754,7 +751,7 @@ static void __tick_nohz_idle_enter(struct tick_sched *ts) | |||
754 | ktime_t now, expires; | 751 | ktime_t now, expires; |
755 | int cpu = smp_processor_id(); | 752 | int cpu = smp_processor_id(); |
756 | 753 | ||
757 | now = tick_nohz_start_idle(cpu, ts); | 754 | now = tick_nohz_start_idle(ts); |
758 | 755 | ||
759 | if (can_stop_idle_tick(cpu, ts)) { | 756 | if (can_stop_idle_tick(cpu, ts)) { |
760 | int was_stopped = ts->tick_stopped; | 757 | int was_stopped = ts->tick_stopped; |
@@ -911,8 +908,7 @@ static void tick_nohz_account_idle_ticks(struct tick_sched *ts) | |||
911 | */ | 908 | */ |
912 | void tick_nohz_idle_exit(void) | 909 | void tick_nohz_idle_exit(void) |
913 | { | 910 | { |
914 | int cpu = smp_processor_id(); | 911 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); |
915 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | ||
916 | ktime_t now; | 912 | ktime_t now; |
917 | 913 | ||
918 | local_irq_disable(); | 914 | local_irq_disable(); |
@@ -925,7 +921,7 @@ void tick_nohz_idle_exit(void) | |||
925 | now = ktime_get(); | 921 | now = ktime_get(); |
926 | 922 | ||
927 | if (ts->idle_active) | 923 | if (ts->idle_active) |
928 | tick_nohz_stop_idle(cpu, now); | 924 | tick_nohz_stop_idle(ts, now); |
929 | 925 | ||
930 | if (ts->tick_stopped) { | 926 | if (ts->tick_stopped) { |
931 | tick_nohz_restart_sched_tick(ts, now); | 927 | tick_nohz_restart_sched_tick(ts, now); |
@@ -1009,12 +1005,10 @@ static void tick_nohz_switch_to_nohz(void) | |||
1009 | * timer and do not touch the other magic bits which need to be done | 1005 | * timer and do not touch the other magic bits which need to be done |
1010 | * when idle is left. | 1006 | * when idle is left. |
1011 | */ | 1007 | */ |
1012 | static void tick_nohz_kick_tick(int cpu, ktime_t now) | 1008 | static void tick_nohz_kick_tick(struct tick_sched *ts, ktime_t now) |
1013 | { | 1009 | { |
1014 | #if 0 | 1010 | #if 0 |
1015 | /* Switch back to 2.6.27 behaviour */ | 1011 | /* Switch back to 2.6.27 behaviour */ |
1016 | |||
1017 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | ||
1018 | ktime_t delta; | 1012 | ktime_t delta; |
1019 | 1013 | ||
1020 | /* | 1014 | /* |
@@ -1029,36 +1023,36 @@ static void tick_nohz_kick_tick(int cpu, ktime_t now) | |||
1029 | #endif | 1023 | #endif |
1030 | } | 1024 | } |
1031 | 1025 | ||
1032 | static inline void tick_check_nohz(int cpu) | 1026 | static inline void tick_check_nohz_this_cpu(void) |
1033 | { | 1027 | { |
1034 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 1028 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); |
1035 | ktime_t now; | 1029 | ktime_t now; |
1036 | 1030 | ||
1037 | if (!ts->idle_active && !ts->tick_stopped) | 1031 | if (!ts->idle_active && !ts->tick_stopped) |
1038 | return; | 1032 | return; |
1039 | now = ktime_get(); | 1033 | now = ktime_get(); |
1040 | if (ts->idle_active) | 1034 | if (ts->idle_active) |
1041 | tick_nohz_stop_idle(cpu, now); | 1035 | tick_nohz_stop_idle(ts, now); |
1042 | if (ts->tick_stopped) { | 1036 | if (ts->tick_stopped) { |
1043 | tick_nohz_update_jiffies(now); | 1037 | tick_nohz_update_jiffies(now); |
1044 | tick_nohz_kick_tick(cpu, now); | 1038 | tick_nohz_kick_tick(ts, now); |
1045 | } | 1039 | } |
1046 | } | 1040 | } |
1047 | 1041 | ||
1048 | #else | 1042 | #else |
1049 | 1043 | ||
1050 | static inline void tick_nohz_switch_to_nohz(void) { } | 1044 | static inline void tick_nohz_switch_to_nohz(void) { } |
1051 | static inline void tick_check_nohz(int cpu) { } | 1045 | static inline void tick_check_nohz_this_cpu(void) { } |
1052 | 1046 | ||
1053 | #endif /* CONFIG_NO_HZ_COMMON */ | 1047 | #endif /* CONFIG_NO_HZ_COMMON */ |
1054 | 1048 | ||
1055 | /* | 1049 | /* |
1056 | * Called from irq_enter to notify about the possible interruption of idle() | 1050 | * Called from irq_enter to notify about the possible interruption of idle() |
1057 | */ | 1051 | */ |
1058 | void tick_check_idle(int cpu) | 1052 | void tick_check_idle(void) |
1059 | { | 1053 | { |
1060 | tick_check_oneshot_broadcast(cpu); | 1054 | tick_check_oneshot_broadcast_this_cpu(); |
1061 | tick_check_nohz(cpu); | 1055 | tick_check_nohz_this_cpu(); |
1062 | } | 1056 | } |
1063 | 1057 | ||
1064 | /* | 1058 | /* |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 87b4f00284c9..0aa4ce81bc16 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -77,7 +77,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) | |||
77 | tk->wall_to_monotonic = wtm; | 77 | tk->wall_to_monotonic = wtm; |
78 | set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); | 78 | set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); |
79 | tk->offs_real = timespec_to_ktime(tmp); | 79 | tk->offs_real = timespec_to_ktime(tmp); |
80 | tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tk->tai_offset, 0)); | 80 | tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tk->tai_offset, 0)); |
81 | } | 81 | } |
82 | 82 | ||
83 | static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) | 83 | static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) |
@@ -90,8 +90,9 @@ static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) | |||
90 | } | 90 | } |
91 | 91 | ||
92 | /** | 92 | /** |
93 | * timekeeper_setup_internals - Set up internals to use clocksource clock. | 93 | * tk_setup_internals - Set up internals to use clocksource clock. |
94 | * | 94 | * |
95 | * @tk: The target timekeeper to setup. | ||
95 | * @clock: Pointer to clocksource. | 96 | * @clock: Pointer to clocksource. |
96 | * | 97 | * |
97 | * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment | 98 | * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment |
@@ -595,7 +596,7 @@ s32 timekeeping_get_tai_offset(void) | |||
595 | static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) | 596 | static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) |
596 | { | 597 | { |
597 | tk->tai_offset = tai_offset; | 598 | tk->tai_offset = tai_offset; |
598 | tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tai_offset, 0)); | 599 | tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tai_offset, 0)); |
599 | } | 600 | } |
600 | 601 | ||
601 | /** | 602 | /** |
@@ -610,6 +611,7 @@ void timekeeping_set_tai_offset(s32 tai_offset) | |||
610 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 611 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
611 | write_seqcount_begin(&timekeeper_seq); | 612 | write_seqcount_begin(&timekeeper_seq); |
612 | __timekeeping_set_tai_offset(tk, tai_offset); | 613 | __timekeeping_set_tai_offset(tk, tai_offset); |
614 | timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET); | ||
613 | write_seqcount_end(&timekeeper_seq); | 615 | write_seqcount_end(&timekeeper_seq); |
614 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 616 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
615 | clock_was_set(); | 617 | clock_was_set(); |
@@ -1023,6 +1025,8 @@ static int timekeeping_suspend(void) | |||
1023 | timekeeping_suspend_time = | 1025 | timekeeping_suspend_time = |
1024 | timespec_add(timekeeping_suspend_time, delta_delta); | 1026 | timespec_add(timekeeping_suspend_time, delta_delta); |
1025 | } | 1027 | } |
1028 | |||
1029 | timekeeping_update(tk, TK_MIRROR); | ||
1026 | write_seqcount_end(&timekeeper_seq); | 1030 | write_seqcount_end(&timekeeper_seq); |
1027 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1031 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
1028 | 1032 | ||
@@ -1130,16 +1134,6 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) | |||
1130 | * we can adjust by 1. | 1134 | * we can adjust by 1. |
1131 | */ | 1135 | */ |
1132 | error >>= 2; | 1136 | error >>= 2; |
1133 | /* | ||
1134 | * XXX - In update_wall_time, we round up to the next | ||
1135 | * nanosecond, and store the amount rounded up into | ||
1136 | * the error. This causes the likely below to be unlikely. | ||
1137 | * | ||
1138 | * The proper fix is to avoid rounding up by using | ||
1139 | * the high precision tk->xtime_nsec instead of | ||
1140 | * xtime.tv_nsec everywhere. Fixing this will take some | ||
1141 | * time. | ||
1142 | */ | ||
1143 | if (likely(error <= interval)) | 1137 | if (likely(error <= interval)) |
1144 | adj = 1; | 1138 | adj = 1; |
1145 | else | 1139 | else |
@@ -1255,7 +1249,7 @@ out_adjust: | |||
1255 | static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | 1249 | static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) |
1256 | { | 1250 | { |
1257 | u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; | 1251 | u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; |
1258 | unsigned int action = 0; | 1252 | unsigned int clock_set = 0; |
1259 | 1253 | ||
1260 | while (tk->xtime_nsec >= nsecps) { | 1254 | while (tk->xtime_nsec >= nsecps) { |
1261 | int leap; | 1255 | int leap; |
@@ -1277,11 +1271,10 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | |||
1277 | 1271 | ||
1278 | __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); | 1272 | __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); |
1279 | 1273 | ||
1280 | clock_was_set_delayed(); | 1274 | clock_set = TK_CLOCK_WAS_SET; |
1281 | action = TK_CLOCK_WAS_SET; | ||
1282 | } | 1275 | } |
1283 | } | 1276 | } |
1284 | return action; | 1277 | return clock_set; |
1285 | } | 1278 | } |
1286 | 1279 | ||
1287 | /** | 1280 | /** |
@@ -1294,7 +1287,8 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | |||
1294 | * Returns the unconsumed cycles. | 1287 | * Returns the unconsumed cycles. |
1295 | */ | 1288 | */ |
1296 | static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, | 1289 | static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, |
1297 | u32 shift) | 1290 | u32 shift, |
1291 | unsigned int *clock_set) | ||
1298 | { | 1292 | { |
1299 | cycle_t interval = tk->cycle_interval << shift; | 1293 | cycle_t interval = tk->cycle_interval << shift; |
1300 | u64 raw_nsecs; | 1294 | u64 raw_nsecs; |
@@ -1308,7 +1302,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, | |||
1308 | tk->cycle_last += interval; | 1302 | tk->cycle_last += interval; |
1309 | 1303 | ||
1310 | tk->xtime_nsec += tk->xtime_interval << shift; | 1304 | tk->xtime_nsec += tk->xtime_interval << shift; |
1311 | accumulate_nsecs_to_secs(tk); | 1305 | *clock_set |= accumulate_nsecs_to_secs(tk); |
1312 | 1306 | ||
1313 | /* Accumulate raw time */ | 1307 | /* Accumulate raw time */ |
1314 | raw_nsecs = (u64)tk->raw_interval << shift; | 1308 | raw_nsecs = (u64)tk->raw_interval << shift; |
@@ -1359,14 +1353,14 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk) | |||
1359 | * update_wall_time - Uses the current clocksource to increment the wall time | 1353 | * update_wall_time - Uses the current clocksource to increment the wall time |
1360 | * | 1354 | * |
1361 | */ | 1355 | */ |
1362 | static void update_wall_time(void) | 1356 | void update_wall_time(void) |
1363 | { | 1357 | { |
1364 | struct clocksource *clock; | 1358 | struct clocksource *clock; |
1365 | struct timekeeper *real_tk = &timekeeper; | 1359 | struct timekeeper *real_tk = &timekeeper; |
1366 | struct timekeeper *tk = &shadow_timekeeper; | 1360 | struct timekeeper *tk = &shadow_timekeeper; |
1367 | cycle_t offset; | 1361 | cycle_t offset; |
1368 | int shift = 0, maxshift; | 1362 | int shift = 0, maxshift; |
1369 | unsigned int action; | 1363 | unsigned int clock_set = 0; |
1370 | unsigned long flags; | 1364 | unsigned long flags; |
1371 | 1365 | ||
1372 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 1366 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
@@ -1401,7 +1395,8 @@ static void update_wall_time(void) | |||
1401 | maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; | 1395 | maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; |
1402 | shift = min(shift, maxshift); | 1396 | shift = min(shift, maxshift); |
1403 | while (offset >= tk->cycle_interval) { | 1397 | while (offset >= tk->cycle_interval) { |
1404 | offset = logarithmic_accumulation(tk, offset, shift); | 1398 | offset = logarithmic_accumulation(tk, offset, shift, |
1399 | &clock_set); | ||
1405 | if (offset < tk->cycle_interval<<shift) | 1400 | if (offset < tk->cycle_interval<<shift) |
1406 | shift--; | 1401 | shift--; |
1407 | } | 1402 | } |
@@ -1419,7 +1414,7 @@ static void update_wall_time(void) | |||
1419 | * Finally, make sure that after the rounding | 1414 | * Finally, make sure that after the rounding |
1420 | * xtime_nsec isn't larger than NSEC_PER_SEC | 1415 | * xtime_nsec isn't larger than NSEC_PER_SEC |
1421 | */ | 1416 | */ |
1422 | action = accumulate_nsecs_to_secs(tk); | 1417 | clock_set |= accumulate_nsecs_to_secs(tk); |
1423 | 1418 | ||
1424 | write_seqcount_begin(&timekeeper_seq); | 1419 | write_seqcount_begin(&timekeeper_seq); |
1425 | /* Update clock->cycle_last with the new value */ | 1420 | /* Update clock->cycle_last with the new value */ |
@@ -1435,10 +1430,12 @@ static void update_wall_time(void) | |||
1435 | * updating. | 1430 | * updating. |
1436 | */ | 1431 | */ |
1437 | memcpy(real_tk, tk, sizeof(*tk)); | 1432 | memcpy(real_tk, tk, sizeof(*tk)); |
1438 | timekeeping_update(real_tk, action); | 1433 | timekeeping_update(real_tk, clock_set); |
1439 | write_seqcount_end(&timekeeper_seq); | 1434 | write_seqcount_end(&timekeeper_seq); |
1440 | out: | 1435 | out: |
1441 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1436 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
1437 | if (clock_set) | ||
1438 | clock_was_set(); | ||
1442 | } | 1439 | } |
1443 | 1440 | ||
1444 | /** | 1441 | /** |
@@ -1583,7 +1580,6 @@ struct timespec get_monotonic_coarse(void) | |||
1583 | void do_timer(unsigned long ticks) | 1580 | void do_timer(unsigned long ticks) |
1584 | { | 1581 | { |
1585 | jiffies_64 += ticks; | 1582 | jiffies_64 += ticks; |
1586 | update_wall_time(); | ||
1587 | calc_global_load(ticks); | 1583 | calc_global_load(ticks); |
1588 | } | 1584 | } |
1589 | 1585 | ||
@@ -1698,12 +1694,14 @@ int do_adjtimex(struct timex *txc) | |||
1698 | 1694 | ||
1699 | if (tai != orig_tai) { | 1695 | if (tai != orig_tai) { |
1700 | __timekeeping_set_tai_offset(tk, tai); | 1696 | __timekeeping_set_tai_offset(tk, tai); |
1701 | update_pvclock_gtod(tk, true); | 1697 | timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET); |
1702 | clock_was_set_delayed(); | ||
1703 | } | 1698 | } |
1704 | write_seqcount_end(&timekeeper_seq); | 1699 | write_seqcount_end(&timekeeper_seq); |
1705 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1700 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
1706 | 1701 | ||
1702 | if (tai != orig_tai) | ||
1703 | clock_was_set(); | ||
1704 | |||
1707 | ntp_notify_cmos_timer(); | 1705 | ntp_notify_cmos_timer(); |
1708 | 1706 | ||
1709 | return ret; | 1707 | return ret; |
@@ -1739,4 +1737,5 @@ void xtime_update(unsigned long ticks) | |||
1739 | write_seqlock(&jiffies_lock); | 1737 | write_seqlock(&jiffies_lock); |
1740 | do_timer(ticks); | 1738 | do_timer(ticks); |
1741 | write_sequnlock(&jiffies_lock); | 1739 | write_sequnlock(&jiffies_lock); |
1740 | update_wall_time(); | ||
1742 | } | 1741 | } |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index cc2f66f68dc5..294b8a271a04 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -2558,7 +2558,7 @@ rb_reserve_next_event(struct ring_buffer *buffer, | |||
2558 | if (unlikely(test_time_stamp(delta))) { | 2558 | if (unlikely(test_time_stamp(delta))) { |
2559 | int local_clock_stable = 1; | 2559 | int local_clock_stable = 1; |
2560 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK | 2560 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK |
2561 | local_clock_stable = sched_clock_stable; | 2561 | local_clock_stable = sched_clock_stable(); |
2562 | #endif | 2562 | #endif |
2563 | WARN_ONCE(delta > (1ULL << 59), | 2563 | WARN_ONCE(delta > (1ULL << 59), |
2564 | KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n%s", | 2564 | KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n%s", |
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index fee77e15d815..6e32635e5e57 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
17 | #include <linux/ftrace.h> | 17 | #include <linux/ftrace.h> |
18 | #include <linux/sched/rt.h> | 18 | #include <linux/sched/rt.h> |
19 | #include <linux/sched/deadline.h> | ||
19 | #include <trace/events/sched.h> | 20 | #include <trace/events/sched.h> |
20 | #include "trace.h" | 21 | #include "trace.h" |
21 | 22 | ||
@@ -27,6 +28,8 @@ static int wakeup_cpu; | |||
27 | static int wakeup_current_cpu; | 28 | static int wakeup_current_cpu; |
28 | static unsigned wakeup_prio = -1; | 29 | static unsigned wakeup_prio = -1; |
29 | static int wakeup_rt; | 30 | static int wakeup_rt; |
31 | static int wakeup_dl; | ||
32 | static int tracing_dl = 0; | ||
30 | 33 | ||
31 | static arch_spinlock_t wakeup_lock = | 34 | static arch_spinlock_t wakeup_lock = |
32 | (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; | 35 | (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; |
@@ -437,6 +440,7 @@ static void __wakeup_reset(struct trace_array *tr) | |||
437 | { | 440 | { |
438 | wakeup_cpu = -1; | 441 | wakeup_cpu = -1; |
439 | wakeup_prio = -1; | 442 | wakeup_prio = -1; |
443 | tracing_dl = 0; | ||
440 | 444 | ||
441 | if (wakeup_task) | 445 | if (wakeup_task) |
442 | put_task_struct(wakeup_task); | 446 | put_task_struct(wakeup_task); |
@@ -472,9 +476,17 @@ probe_wakeup(void *ignore, struct task_struct *p, int success) | |||
472 | tracing_record_cmdline(p); | 476 | tracing_record_cmdline(p); |
473 | tracing_record_cmdline(current); | 477 | tracing_record_cmdline(current); |
474 | 478 | ||
475 | if ((wakeup_rt && !rt_task(p)) || | 479 | /* |
476 | p->prio >= wakeup_prio || | 480 | * Semantic is like this: |
477 | p->prio >= current->prio) | 481 | * - wakeup tracer handles all tasks in the system, independently |
482 | * from their scheduling class; | ||
483 | * - wakeup_rt tracer handles tasks belonging to sched_dl and | ||
484 | * sched_rt class; | ||
485 | * - wakeup_dl handles tasks belonging to sched_dl class only. | ||
486 | */ | ||
487 | if (tracing_dl || (wakeup_dl && !dl_task(p)) || | ||
488 | (wakeup_rt && !dl_task(p) && !rt_task(p)) || | ||
489 | (!dl_task(p) && (p->prio >= wakeup_prio || p->prio >= current->prio))) | ||
478 | return; | 490 | return; |
479 | 491 | ||
480 | pc = preempt_count(); | 492 | pc = preempt_count(); |
@@ -486,7 +498,8 @@ probe_wakeup(void *ignore, struct task_struct *p, int success) | |||
486 | arch_spin_lock(&wakeup_lock); | 498 | arch_spin_lock(&wakeup_lock); |
487 | 499 | ||
488 | /* check for races. */ | 500 | /* check for races. */ |
489 | if (!tracer_enabled || p->prio >= wakeup_prio) | 501 | if (!tracer_enabled || tracing_dl || |
502 | (!dl_task(p) && p->prio >= wakeup_prio)) | ||
490 | goto out_locked; | 503 | goto out_locked; |
491 | 504 | ||
492 | /* reset the trace */ | 505 | /* reset the trace */ |
@@ -496,6 +509,15 @@ probe_wakeup(void *ignore, struct task_struct *p, int success) | |||
496 | wakeup_current_cpu = wakeup_cpu; | 509 | wakeup_current_cpu = wakeup_cpu; |
497 | wakeup_prio = p->prio; | 510 | wakeup_prio = p->prio; |
498 | 511 | ||
512 | /* | ||
513 | * Once you start tracing a -deadline task, don't bother tracing | ||
514 | * another task until the first one wakes up. | ||
515 | */ | ||
516 | if (dl_task(p)) | ||
517 | tracing_dl = 1; | ||
518 | else | ||
519 | tracing_dl = 0; | ||
520 | |||
499 | wakeup_task = p; | 521 | wakeup_task = p; |
500 | get_task_struct(wakeup_task); | 522 | get_task_struct(wakeup_task); |
501 | 523 | ||
@@ -597,16 +619,25 @@ static int __wakeup_tracer_init(struct trace_array *tr) | |||
597 | 619 | ||
598 | static int wakeup_tracer_init(struct trace_array *tr) | 620 | static int wakeup_tracer_init(struct trace_array *tr) |
599 | { | 621 | { |
622 | wakeup_dl = 0; | ||
600 | wakeup_rt = 0; | 623 | wakeup_rt = 0; |
601 | return __wakeup_tracer_init(tr); | 624 | return __wakeup_tracer_init(tr); |
602 | } | 625 | } |
603 | 626 | ||
604 | static int wakeup_rt_tracer_init(struct trace_array *tr) | 627 | static int wakeup_rt_tracer_init(struct trace_array *tr) |
605 | { | 628 | { |
629 | wakeup_dl = 0; | ||
606 | wakeup_rt = 1; | 630 | wakeup_rt = 1; |
607 | return __wakeup_tracer_init(tr); | 631 | return __wakeup_tracer_init(tr); |
608 | } | 632 | } |
609 | 633 | ||
634 | static int wakeup_dl_tracer_init(struct trace_array *tr) | ||
635 | { | ||
636 | wakeup_dl = 1; | ||
637 | wakeup_rt = 0; | ||
638 | return __wakeup_tracer_init(tr); | ||
639 | } | ||
640 | |||
610 | static void wakeup_tracer_reset(struct trace_array *tr) | 641 | static void wakeup_tracer_reset(struct trace_array *tr) |
611 | { | 642 | { |
612 | int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT; | 643 | int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT; |
@@ -674,6 +705,28 @@ static struct tracer wakeup_rt_tracer __read_mostly = | |||
674 | .use_max_tr = true, | 705 | .use_max_tr = true, |
675 | }; | 706 | }; |
676 | 707 | ||
708 | static struct tracer wakeup_dl_tracer __read_mostly = | ||
709 | { | ||
710 | .name = "wakeup_dl", | ||
711 | .init = wakeup_dl_tracer_init, | ||
712 | .reset = wakeup_tracer_reset, | ||
713 | .start = wakeup_tracer_start, | ||
714 | .stop = wakeup_tracer_stop, | ||
715 | .wait_pipe = poll_wait_pipe, | ||
716 | .print_max = true, | ||
717 | .print_header = wakeup_print_header, | ||
718 | .print_line = wakeup_print_line, | ||
719 | .flags = &tracer_flags, | ||
720 | .set_flag = wakeup_set_flag, | ||
721 | .flag_changed = wakeup_flag_changed, | ||
722 | #ifdef CONFIG_FTRACE_SELFTEST | ||
723 | .selftest = trace_selftest_startup_wakeup, | ||
724 | #endif | ||
725 | .open = wakeup_trace_open, | ||
726 | .close = wakeup_trace_close, | ||
727 | .use_max_tr = true, | ||
728 | }; | ||
729 | |||
677 | __init static int init_wakeup_tracer(void) | 730 | __init static int init_wakeup_tracer(void) |
678 | { | 731 | { |
679 | int ret; | 732 | int ret; |
@@ -686,6 +739,10 @@ __init static int init_wakeup_tracer(void) | |||
686 | if (ret) | 739 | if (ret) |
687 | return ret; | 740 | return ret; |
688 | 741 | ||
742 | ret = register_tracer(&wakeup_dl_tracer); | ||
743 | if (ret) | ||
744 | return ret; | ||
745 | |||
689 | return 0; | 746 | return 0; |
690 | } | 747 | } |
691 | core_initcall(init_wakeup_tracer); | 748 | core_initcall(init_wakeup_tracer); |
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index a7329b7902f8..e98fca60974f 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c | |||
@@ -1022,11 +1022,16 @@ trace_selftest_startup_nop(struct tracer *trace, struct trace_array *tr) | |||
1022 | #ifdef CONFIG_SCHED_TRACER | 1022 | #ifdef CONFIG_SCHED_TRACER |
1023 | static int trace_wakeup_test_thread(void *data) | 1023 | static int trace_wakeup_test_thread(void *data) |
1024 | { | 1024 | { |
1025 | /* Make this a RT thread, doesn't need to be too high */ | 1025 | /* Make this a -deadline thread */ |
1026 | static const struct sched_param param = { .sched_priority = 5 }; | 1026 | static const struct sched_attr attr = { |
1027 | .sched_policy = SCHED_DEADLINE, | ||
1028 | .sched_runtime = 100000ULL, | ||
1029 | .sched_deadline = 10000000ULL, | ||
1030 | .sched_period = 10000000ULL | ||
1031 | }; | ||
1027 | struct completion *x = data; | 1032 | struct completion *x = data; |
1028 | 1033 | ||
1029 | sched_setscheduler(current, SCHED_FIFO, ¶m); | 1034 | sched_setattr(current, &attr); |
1030 | 1035 | ||
1031 | /* Make it know we have a new prio */ | 1036 | /* Make it know we have a new prio */ |
1032 | complete(x); | 1037 | complete(x); |
@@ -1040,8 +1045,8 @@ static int trace_wakeup_test_thread(void *data) | |||
1040 | /* we are awake, now wait to disappear */ | 1045 | /* we are awake, now wait to disappear */ |
1041 | while (!kthread_should_stop()) { | 1046 | while (!kthread_should_stop()) { |
1042 | /* | 1047 | /* |
1043 | * This is an RT task, do short sleeps to let | 1048 | * This will likely be the system top priority |
1044 | * others run. | 1049 | * task, do short sleeps to let others run. |
1045 | */ | 1050 | */ |
1046 | msleep(100); | 1051 | msleep(100); |
1047 | } | 1052 | } |
@@ -1054,21 +1059,21 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) | |||
1054 | { | 1059 | { |
1055 | unsigned long save_max = tracing_max_latency; | 1060 | unsigned long save_max = tracing_max_latency; |
1056 | struct task_struct *p; | 1061 | struct task_struct *p; |
1057 | struct completion isrt; | 1062 | struct completion is_ready; |
1058 | unsigned long count; | 1063 | unsigned long count; |
1059 | int ret; | 1064 | int ret; |
1060 | 1065 | ||
1061 | init_completion(&isrt); | 1066 | init_completion(&is_ready); |
1062 | 1067 | ||
1063 | /* create a high prio thread */ | 1068 | /* create a -deadline thread */ |
1064 | p = kthread_run(trace_wakeup_test_thread, &isrt, "ftrace-test"); | 1069 | p = kthread_run(trace_wakeup_test_thread, &is_ready, "ftrace-test"); |
1065 | if (IS_ERR(p)) { | 1070 | if (IS_ERR(p)) { |
1066 | printk(KERN_CONT "Failed to create ftrace wakeup test thread "); | 1071 | printk(KERN_CONT "Failed to create ftrace wakeup test thread "); |
1067 | return -1; | 1072 | return -1; |
1068 | } | 1073 | } |
1069 | 1074 | ||
1070 | /* make sure the thread is running at an RT prio */ | 1075 | /* make sure the thread is running at -deadline policy */ |
1071 | wait_for_completion(&isrt); | 1076 | wait_for_completion(&is_ready); |
1072 | 1077 | ||
1073 | /* start the tracing */ | 1078 | /* start the tracing */ |
1074 | ret = tracer_init(trace, tr); | 1079 | ret = tracer_init(trace, tr); |
@@ -1082,19 +1087,19 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) | |||
1082 | 1087 | ||
1083 | while (p->on_rq) { | 1088 | while (p->on_rq) { |
1084 | /* | 1089 | /* |
1085 | * Sleep to make sure the RT thread is asleep too. | 1090 | * Sleep to make sure the -deadline thread is asleep too. |
1086 | * On virtual machines we can't rely on timings, | 1091 | * On virtual machines we can't rely on timings, |
1087 | * but we want to make sure this test still works. | 1092 | * but we want to make sure this test still works. |
1088 | */ | 1093 | */ |
1089 | msleep(100); | 1094 | msleep(100); |
1090 | } | 1095 | } |
1091 | 1096 | ||
1092 | init_completion(&isrt); | 1097 | init_completion(&is_ready); |
1093 | 1098 | ||
1094 | wake_up_process(p); | 1099 | wake_up_process(p); |
1095 | 1100 | ||
1096 | /* Wait for the task to wake up */ | 1101 | /* Wait for the task to wake up */ |
1097 | wait_for_completion(&isrt); | 1102 | wait_for_completion(&is_ready); |
1098 | 1103 | ||
1099 | /* stop the tracing. */ | 1104 | /* stop the tracing. */ |
1100 | tracing_stop(); | 1105 | tracing_stop(); |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index db25707aa41b..6982094a7e74 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -761,6 +761,15 @@ config PANIC_ON_OOPS_VALUE | |||
761 | default 0 if !PANIC_ON_OOPS | 761 | default 0 if !PANIC_ON_OOPS |
762 | default 1 if PANIC_ON_OOPS | 762 | default 1 if PANIC_ON_OOPS |
763 | 763 | ||
764 | config PANIC_TIMEOUT | ||
765 | int "panic timeout" | ||
766 | default 0 | ||
767 | help | ||
768 | Set the timeout value (in seconds) until a reboot occurs when the | ||
769 | the kernel panics. If n = 0, then we wait forever. A timeout | ||
770 | value n > 0 will wait n seconds before rebooting, while a timeout | ||
771 | value n < 0 will reboot immediately. | ||
772 | |||
764 | config SCHED_DEBUG | 773 | config SCHED_DEBUG |
765 | bool "Collect scheduler debugging info" | 774 | bool "Collect scheduler debugging info" |
766 | depends on DEBUG_KERNEL && PROC_FS | 775 | depends on DEBUG_KERNEL && PROC_FS |
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index 7473ee3b4ee7..8280a5dd1727 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c | |||
@@ -82,10 +82,10 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch) | |||
82 | unsigned long flags; | 82 | unsigned long flags; |
83 | raw_spin_lock_irqsave(&fbc->lock, flags); | 83 | raw_spin_lock_irqsave(&fbc->lock, flags); |
84 | fbc->count += count; | 84 | fbc->count += count; |
85 | __this_cpu_sub(*fbc->counters, count - amount); | ||
85 | raw_spin_unlock_irqrestore(&fbc->lock, flags); | 86 | raw_spin_unlock_irqrestore(&fbc->lock, flags); |
86 | __this_cpu_write(*fbc->counters, 0); | ||
87 | } else { | 87 | } else { |
88 | __this_cpu_write(*fbc->counters, count); | 88 | this_cpu_add(*fbc->counters, amount); |
89 | } | 89 | } |
90 | preempt_enable(); | 90 | preempt_enable(); |
91 | } | 91 | } |
@@ -390,7 +390,10 @@ struct address_space *page_mapping(struct page *page) | |||
390 | { | 390 | { |
391 | struct address_space *mapping = page->mapping; | 391 | struct address_space *mapping = page->mapping; |
392 | 392 | ||
393 | VM_BUG_ON(PageSlab(page)); | 393 | /* This happens if someone calls flush_dcache_page on slab page */ |
394 | if (unlikely(PageSlab(page))) | ||
395 | return NULL; | ||
396 | |||
394 | if (unlikely(PageSwapCache(page))) { | 397 | if (unlikely(PageSwapCache(page))) { |
395 | swp_entry_t entry; | 398 | swp_entry_t entry; |
396 | 399 | ||
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 1511f64a6cea..faba0f61ad53 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -277,7 +277,7 @@ int batadv_max_header_len(void) | |||
277 | sizeof(struct batadv_coded_packet)); | 277 | sizeof(struct batadv_coded_packet)); |
278 | #endif | 278 | #endif |
279 | 279 | ||
280 | return header_len; | 280 | return header_len + ETH_HLEN; |
281 | } | 281 | } |
282 | 282 | ||
283 | /** | 283 | /** |
diff --git a/net/core/filter.c b/net/core/filter.c index 01b780856db2..ad30d626a5bd 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
37 | #include <asm/unaligned.h> | 37 | #include <asm/unaligned.h> |
38 | #include <linux/filter.h> | 38 | #include <linux/filter.h> |
39 | #include <linux/reciprocal_div.h> | ||
40 | #include <linux/ratelimit.h> | 39 | #include <linux/ratelimit.h> |
41 | #include <linux/seccomp.h> | 40 | #include <linux/seccomp.h> |
42 | #include <linux/if_vlan.h> | 41 | #include <linux/if_vlan.h> |
@@ -166,7 +165,7 @@ unsigned int sk_run_filter(const struct sk_buff *skb, | |||
166 | A /= X; | 165 | A /= X; |
167 | continue; | 166 | continue; |
168 | case BPF_S_ALU_DIV_K: | 167 | case BPF_S_ALU_DIV_K: |
169 | A = reciprocal_divide(A, K); | 168 | A /= K; |
170 | continue; | 169 | continue; |
171 | case BPF_S_ALU_MOD_X: | 170 | case BPF_S_ALU_MOD_X: |
172 | if (X == 0) | 171 | if (X == 0) |
@@ -553,11 +552,6 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) | |||
553 | /* Some instructions need special checks */ | 552 | /* Some instructions need special checks */ |
554 | switch (code) { | 553 | switch (code) { |
555 | case BPF_S_ALU_DIV_K: | 554 | case BPF_S_ALU_DIV_K: |
556 | /* check for division by zero */ | ||
557 | if (ftest->k == 0) | ||
558 | return -EINVAL; | ||
559 | ftest->k = reciprocal_value(ftest->k); | ||
560 | break; | ||
561 | case BPF_S_ALU_MOD_K: | 555 | case BPF_S_ALU_MOD_K: |
562 | /* check for division by zero */ | 556 | /* check for division by zero */ |
563 | if (ftest->k == 0) | 557 | if (ftest->k == 0) |
@@ -853,27 +847,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) | |||
853 | to->code = decodes[code]; | 847 | to->code = decodes[code]; |
854 | to->jt = filt->jt; | 848 | to->jt = filt->jt; |
855 | to->jf = filt->jf; | 849 | to->jf = filt->jf; |
856 | 850 | to->k = filt->k; | |
857 | if (code == BPF_S_ALU_DIV_K) { | ||
858 | /* | ||
859 | * When loaded this rule user gave us X, which was | ||
860 | * translated into R = r(X). Now we calculate the | ||
861 | * RR = r(R) and report it back. If next time this | ||
862 | * value is loaded and RRR = r(RR) is calculated | ||
863 | * then the R == RRR will be true. | ||
864 | * | ||
865 | * One exception. X == 1 translates into R == 0 and | ||
866 | * we can't calculate RR out of it with r(). | ||
867 | */ | ||
868 | |||
869 | if (filt->k == 0) | ||
870 | to->k = 1; | ||
871 | else | ||
872 | to->k = reciprocal_value(filt->k); | ||
873 | |||
874 | BUG_ON(reciprocal_value(to->k) != filt->k); | ||
875 | } else | ||
876 | to->k = filt->k; | ||
877 | } | 851 | } |
878 | 852 | ||
879 | int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len) | 853 | int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len) |
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index d08c7a43dcd1..89b265aea151 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c | |||
@@ -221,8 +221,10 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
221 | 221 | ||
222 | if (info->attrs[IEEE802154_ATTR_DEV_TYPE]) { | 222 | if (info->attrs[IEEE802154_ATTR_DEV_TYPE]) { |
223 | type = nla_get_u8(info->attrs[IEEE802154_ATTR_DEV_TYPE]); | 223 | type = nla_get_u8(info->attrs[IEEE802154_ATTR_DEV_TYPE]); |
224 | if (type >= __IEEE802154_DEV_MAX) | 224 | if (type >= __IEEE802154_DEV_MAX) { |
225 | return -EINVAL; | 225 | rc = -EINVAL; |
226 | goto nla_put_failure; | ||
227 | } | ||
226 | } | 228 | } |
227 | 229 | ||
228 | dev = phy->add_iface(phy, devname, type); | 230 | dev = phy->add_iface(phy, devname, type); |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index a0f52dac8940..e34dccbc4d70 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -930,12 +930,15 @@ skip_listen_ht: | |||
930 | spin_lock_bh(lock); | 930 | spin_lock_bh(lock); |
931 | sk_nulls_for_each(sk, node, &head->chain) { | 931 | sk_nulls_for_each(sk, node, &head->chain) { |
932 | int res; | 932 | int res; |
933 | int state; | ||
933 | 934 | ||
934 | if (!net_eq(sock_net(sk), net)) | 935 | if (!net_eq(sock_net(sk), net)) |
935 | continue; | 936 | continue; |
936 | if (num < s_num) | 937 | if (num < s_num) |
937 | goto next_normal; | 938 | goto next_normal; |
938 | if (!(r->idiag_states & (1 << sk->sk_state))) | 939 | state = (sk->sk_state == TCP_TIME_WAIT) ? |
940 | inet_twsk(sk)->tw_substate : sk->sk_state; | ||
941 | if (!(r->idiag_states & (1 << state))) | ||
939 | goto next_normal; | 942 | goto next_normal; |
940 | if (r->sdiag_family != AF_UNSPEC && | 943 | if (r->sdiag_family != AF_UNSPEC && |
941 | sk->sk_family != r->sdiag_family) | 944 | sk->sk_family != r->sdiag_family) |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 62212c772a4b..1672409f5ba5 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -157,9 +157,12 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id) | |||
157 | static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, | 157 | static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, |
158 | struct mr_table **mrt) | 158 | struct mr_table **mrt) |
159 | { | 159 | { |
160 | struct ipmr_result res; | ||
161 | struct fib_lookup_arg arg = { .result = &res, }; | ||
162 | int err; | 160 | int err; |
161 | struct ipmr_result res; | ||
162 | struct fib_lookup_arg arg = { | ||
163 | .result = &res, | ||
164 | .flags = FIB_LOOKUP_NOREF, | ||
165 | }; | ||
163 | 166 | ||
164 | err = fib_rules_lookup(net->ipv4.mr_rules_ops, | 167 | err = fib_rules_lookup(net->ipv4.mr_rules_ops, |
165 | flowi4_to_flowi(flp4), 0, &arg); | 168 | flowi4_to_flowi(flp4), 0, &arg); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c4638e6f0238..82de78603686 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1623,11 +1623,11 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1623 | (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && | 1623 | (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && |
1624 | !sysctl_tcp_low_latency && | 1624 | !sysctl_tcp_low_latency && |
1625 | net_dma_find_channel()) { | 1625 | net_dma_find_channel()) { |
1626 | preempt_enable_no_resched(); | 1626 | preempt_enable(); |
1627 | tp->ucopy.pinned_list = | 1627 | tp->ucopy.pinned_list = |
1628 | dma_pin_iovec_pages(msg->msg_iov, len); | 1628 | dma_pin_iovec_pages(msg->msg_iov, len); |
1629 | } else { | 1629 | } else { |
1630 | preempt_enable_no_resched(); | 1630 | preempt_enable(); |
1631 | } | 1631 | } |
1632 | } | 1632 | } |
1633 | #endif | 1633 | #endif |
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 06493736fbc8..098b3a29f6f3 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -22,6 +22,9 @@ | |||
22 | 22 | ||
23 | int sysctl_tcp_nometrics_save __read_mostly; | 23 | int sysctl_tcp_nometrics_save __read_mostly; |
24 | 24 | ||
25 | static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr, | ||
26 | struct net *net, unsigned int hash); | ||
27 | |||
25 | struct tcp_fastopen_metrics { | 28 | struct tcp_fastopen_metrics { |
26 | u16 mss; | 29 | u16 mss; |
27 | u16 syn_loss:10; /* Recurring Fast Open SYN losses */ | 30 | u16 syn_loss:10; /* Recurring Fast Open SYN losses */ |
@@ -130,16 +133,41 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst, | |||
130 | } | 133 | } |
131 | } | 134 | } |
132 | 135 | ||
136 | #define TCP_METRICS_TIMEOUT (60 * 60 * HZ) | ||
137 | |||
138 | static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst) | ||
139 | { | ||
140 | if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT))) | ||
141 | tcpm_suck_dst(tm, dst, false); | ||
142 | } | ||
143 | |||
144 | #define TCP_METRICS_RECLAIM_DEPTH 5 | ||
145 | #define TCP_METRICS_RECLAIM_PTR (struct tcp_metrics_block *) 0x1UL | ||
146 | |||
133 | static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, | 147 | static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, |
134 | struct inetpeer_addr *addr, | 148 | struct inetpeer_addr *addr, |
135 | unsigned int hash, | 149 | unsigned int hash) |
136 | bool reclaim) | ||
137 | { | 150 | { |
138 | struct tcp_metrics_block *tm; | 151 | struct tcp_metrics_block *tm; |
139 | struct net *net; | 152 | struct net *net; |
153 | bool reclaim = false; | ||
140 | 154 | ||
141 | spin_lock_bh(&tcp_metrics_lock); | 155 | spin_lock_bh(&tcp_metrics_lock); |
142 | net = dev_net(dst->dev); | 156 | net = dev_net(dst->dev); |
157 | |||
158 | /* While waiting for the spin-lock the cache might have been populated | ||
159 | * with this entry and so we have to check again. | ||
160 | */ | ||
161 | tm = __tcp_get_metrics(addr, net, hash); | ||
162 | if (tm == TCP_METRICS_RECLAIM_PTR) { | ||
163 | reclaim = true; | ||
164 | tm = NULL; | ||
165 | } | ||
166 | if (tm) { | ||
167 | tcpm_check_stamp(tm, dst); | ||
168 | goto out_unlock; | ||
169 | } | ||
170 | |||
143 | if (unlikely(reclaim)) { | 171 | if (unlikely(reclaim)) { |
144 | struct tcp_metrics_block *oldest; | 172 | struct tcp_metrics_block *oldest; |
145 | 173 | ||
@@ -169,17 +197,6 @@ out_unlock: | |||
169 | return tm; | 197 | return tm; |
170 | } | 198 | } |
171 | 199 | ||
172 | #define TCP_METRICS_TIMEOUT (60 * 60 * HZ) | ||
173 | |||
174 | static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst) | ||
175 | { | ||
176 | if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT))) | ||
177 | tcpm_suck_dst(tm, dst, false); | ||
178 | } | ||
179 | |||
180 | #define TCP_METRICS_RECLAIM_DEPTH 5 | ||
181 | #define TCP_METRICS_RECLAIM_PTR (struct tcp_metrics_block *) 0x1UL | ||
182 | |||
183 | static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, int depth) | 200 | static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, int depth) |
184 | { | 201 | { |
185 | if (tm) | 202 | if (tm) |
@@ -282,7 +299,6 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk, | |||
282 | struct inetpeer_addr addr; | 299 | struct inetpeer_addr addr; |
283 | unsigned int hash; | 300 | unsigned int hash; |
284 | struct net *net; | 301 | struct net *net; |
285 | bool reclaim; | ||
286 | 302 | ||
287 | addr.family = sk->sk_family; | 303 | addr.family = sk->sk_family; |
288 | switch (addr.family) { | 304 | switch (addr.family) { |
@@ -304,13 +320,10 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk, | |||
304 | hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log); | 320 | hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log); |
305 | 321 | ||
306 | tm = __tcp_get_metrics(&addr, net, hash); | 322 | tm = __tcp_get_metrics(&addr, net, hash); |
307 | reclaim = false; | 323 | if (tm == TCP_METRICS_RECLAIM_PTR) |
308 | if (tm == TCP_METRICS_RECLAIM_PTR) { | ||
309 | reclaim = true; | ||
310 | tm = NULL; | 324 | tm = NULL; |
311 | } | ||
312 | if (!tm && create) | 325 | if (!tm && create) |
313 | tm = tcpm_new(dst, &addr, hash, reclaim); | 326 | tm = tcpm_new(dst, &addr, hash); |
314 | else | 327 | else |
315 | tcpm_check_stamp(tm, dst); | 328 | tcpm_check_stamp(tm, dst); |
316 | 329 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index abe46a4228ce..4b6b720971b9 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3189,6 +3189,22 @@ out: | |||
3189 | in6_ifa_put(ifp); | 3189 | in6_ifa_put(ifp); |
3190 | } | 3190 | } |
3191 | 3191 | ||
3192 | /* ifp->idev must be at least read locked */ | ||
3193 | static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp) | ||
3194 | { | ||
3195 | struct inet6_ifaddr *ifpiter; | ||
3196 | struct inet6_dev *idev = ifp->idev; | ||
3197 | |||
3198 | list_for_each_entry(ifpiter, &idev->addr_list, if_list) { | ||
3199 | if (ifp != ifpiter && ifpiter->scope == IFA_LINK && | ||
3200 | (ifpiter->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE| | ||
3201 | IFA_F_OPTIMISTIC|IFA_F_DADFAILED)) == | ||
3202 | IFA_F_PERMANENT) | ||
3203 | return false; | ||
3204 | } | ||
3205 | return true; | ||
3206 | } | ||
3207 | |||
3192 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | 3208 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) |
3193 | { | 3209 | { |
3194 | struct net_device *dev = ifp->idev->dev; | 3210 | struct net_device *dev = ifp->idev->dev; |
@@ -3208,14 +3224,11 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
3208 | */ | 3224 | */ |
3209 | 3225 | ||
3210 | read_lock_bh(&ifp->idev->lock); | 3226 | read_lock_bh(&ifp->idev->lock); |
3211 | spin_lock(&ifp->lock); | 3227 | send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp); |
3212 | send_mld = ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL && | ||
3213 | ifp->idev->valid_ll_addr_cnt == 1; | ||
3214 | send_rs = send_mld && | 3228 | send_rs = send_mld && |
3215 | ipv6_accept_ra(ifp->idev) && | 3229 | ipv6_accept_ra(ifp->idev) && |
3216 | ifp->idev->cnf.rtr_solicits > 0 && | 3230 | ifp->idev->cnf.rtr_solicits > 0 && |
3217 | (dev->flags&IFF_LOOPBACK) == 0; | 3231 | (dev->flags&IFF_LOOPBACK) == 0; |
3218 | spin_unlock(&ifp->lock); | ||
3219 | read_unlock_bh(&ifp->idev->lock); | 3232 | read_unlock_bh(&ifp->idev->lock); |
3220 | 3233 | ||
3221 | /* While dad is in progress mld report's source address is in6_addrany. | 3234 | /* While dad is in progress mld report's source address is in6_addrany. |
@@ -4512,19 +4525,6 @@ errout: | |||
4512 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); | 4525 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); |
4513 | } | 4526 | } |
4514 | 4527 | ||
4515 | static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count) | ||
4516 | { | ||
4517 | write_lock_bh(&ifp->idev->lock); | ||
4518 | spin_lock(&ifp->lock); | ||
4519 | if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC| | ||
4520 | IFA_F_DADFAILED)) == IFA_F_PERMANENT) && | ||
4521 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) | ||
4522 | ifp->idev->valid_ll_addr_cnt += count; | ||
4523 | WARN_ON(ifp->idev->valid_ll_addr_cnt < 0); | ||
4524 | spin_unlock(&ifp->lock); | ||
4525 | write_unlock_bh(&ifp->idev->lock); | ||
4526 | } | ||
4527 | |||
4528 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 4528 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
4529 | { | 4529 | { |
4530 | struct net *net = dev_net(ifp->idev->dev); | 4530 | struct net *net = dev_net(ifp->idev->dev); |
@@ -4533,8 +4533,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4533 | 4533 | ||
4534 | switch (event) { | 4534 | switch (event) { |
4535 | case RTM_NEWADDR: | 4535 | case RTM_NEWADDR: |
4536 | update_valid_ll_addr_cnt(ifp, 1); | ||
4537 | |||
4538 | /* | 4536 | /* |
4539 | * If the address was optimistic | 4537 | * If the address was optimistic |
4540 | * we inserted the route at the start of | 4538 | * we inserted the route at the start of |
@@ -4550,8 +4548,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4550 | ifp->idev->dev, 0, 0); | 4548 | ifp->idev->dev, 0, 0); |
4551 | break; | 4549 | break; |
4552 | case RTM_DELADDR: | 4550 | case RTM_DELADDR: |
4553 | update_valid_ll_addr_cnt(ifp, -1); | ||
4554 | |||
4555 | if (ifp->idev->cnf.forwarding) | 4551 | if (ifp->idev->cnf.forwarding) |
4556 | addrconf_leave_anycast(ifp); | 4552 | addrconf_leave_anycast(ifp); |
4557 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4553 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index f365310bfcca..0eb4038a4d63 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -141,9 +141,12 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | |||
141 | static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, | 141 | static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, |
142 | struct mr6_table **mrt) | 142 | struct mr6_table **mrt) |
143 | { | 143 | { |
144 | struct ip6mr_result res; | ||
145 | struct fib_lookup_arg arg = { .result = &res, }; | ||
146 | int err; | 144 | int err; |
145 | struct ip6mr_result res; | ||
146 | struct fib_lookup_arg arg = { | ||
147 | .result = &res, | ||
148 | .flags = FIB_LOOKUP_NOREF, | ||
149 | }; | ||
147 | 150 | ||
148 | err = fib_rules_lookup(net->ipv6.mr6_rules_ops, | 151 | err = fib_rules_lookup(net->ipv6.mr6_rules_ops, |
149 | flowi6_to_flowi(flp6), 0, &arg); | 152 | flowi6_to_flowi(flp6), 0, &arg); |
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index 8eb9501e3d60..b7ebe23cdedf 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c | |||
@@ -421,8 +421,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item, | |||
421 | struct rds_ib_refill_cache *cache) | 421 | struct rds_ib_refill_cache *cache) |
422 | { | 422 | { |
423 | unsigned long flags; | 423 | unsigned long flags; |
424 | struct list_head *old; | 424 | struct list_head *old, *chpfirst; |
425 | struct list_head __percpu *chpfirst; | ||
426 | 425 | ||
427 | local_irq_save(flags); | 426 | local_irq_save(flags); |
428 | 427 | ||
@@ -432,7 +431,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item, | |||
432 | else /* put on front */ | 431 | else /* put on front */ |
433 | list_add_tail(new_item, chpfirst); | 432 | list_add_tail(new_item, chpfirst); |
434 | 433 | ||
435 | __this_cpu_write(chpfirst, new_item); | 434 | __this_cpu_write(cache->percpu->first, new_item); |
436 | __this_cpu_inc(cache->percpu->count); | 435 | __this_cpu_inc(cache->percpu->count); |
437 | 436 | ||
438 | if (__this_cpu_read(cache->percpu->count) < RDS_IB_RECYCLE_BATCH_COUNT) | 437 | if (__this_cpu_read(cache->percpu->count) < RDS_IB_RECYCLE_BATCH_COUNT) |
@@ -452,7 +451,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item, | |||
452 | } while (old); | 451 | } while (old); |
453 | 452 | ||
454 | 453 | ||
455 | __this_cpu_write(chpfirst, NULL); | 454 | __this_cpu_write(cache->percpu->first, NULL); |
456 | __this_cpu_write(cache->percpu->count, 0); | 455 | __this_cpu_write(cache->percpu->count, 0); |
457 | end: | 456 | end: |
458 | local_irq_restore(flags); | 457 | local_irq_restore(flags); |
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 4606cdfb859d..31331723e810 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl | |||
@@ -219,6 +219,13 @@ sub read_kconfig { | |||
219 | $depends{$config} = $1; | 219 | $depends{$config} = $1; |
220 | } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) { | 220 | } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) { |
221 | $depends{$config} .= " " . $1; | 221 | $depends{$config} .= " " . $1; |
222 | } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) { | ||
223 | my $dep = $3; | ||
224 | if ($dep !~ /^\s*(y|m|n)\s*$/) { | ||
225 | $dep =~ s/.*\sif\s+//; | ||
226 | $depends{$config} .= " " . $dep; | ||
227 | dprint "Added default depends $dep to $config\n"; | ||
228 | } | ||
222 | 229 | ||
223 | # Get the configs that select this config | 230 | # Get the configs that select this config |
224 | } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { | 231 | } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { |
diff --git a/tools/Makefile b/tools/Makefile index a9b02008443c..927cd46d36dc 100644 --- a/tools/Makefile +++ b/tools/Makefile | |||
@@ -39,10 +39,10 @@ cpupower: FORCE | |||
39 | cgroup firewire guest usb virtio vm net: FORCE | 39 | cgroup firewire guest usb virtio vm net: FORCE |
40 | $(call descend,$@) | 40 | $(call descend,$@) |
41 | 41 | ||
42 | liblk: FORCE | 42 | libapikfs: FORCE |
43 | $(call descend,lib/lk) | 43 | $(call descend,lib/api) |
44 | 44 | ||
45 | perf: liblk FORCE | 45 | perf: libapikfs FORCE |
46 | $(call descend,$@) | 46 | $(call descend,$@) |
47 | 47 | ||
48 | selftests: FORCE | 48 | selftests: FORCE |
@@ -80,10 +80,10 @@ cpupower_clean: | |||
80 | cgroup_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean: | 80 | cgroup_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean: |
81 | $(call descend,$(@:_clean=),clean) | 81 | $(call descend,$(@:_clean=),clean) |
82 | 82 | ||
83 | liblk_clean: | 83 | libapikfs_clean: |
84 | $(call descend,lib/lk,clean) | 84 | $(call descend,lib/api,clean) |
85 | 85 | ||
86 | perf_clean: liblk_clean | 86 | perf_clean: libapikfs_clean |
87 | $(call descend,$(@:_clean=),clean) | 87 | $(call descend,$(@:_clean=),clean) |
88 | 88 | ||
89 | selftests_clean: | 89 | selftests_clean: |
diff --git a/tools/perf/util/include/asm/bug.h b/tools/include/asm/bug.h index 7fcc6810adc2..9e5f4846967f 100644 --- a/tools/perf/util/include/asm/bug.h +++ b/tools/include/asm/bug.h | |||
@@ -1,5 +1,7 @@ | |||
1 | #ifndef _PERF_ASM_GENERIC_BUG_H | 1 | #ifndef _TOOLS_ASM_BUG_H |
2 | #define _PERF_ASM_GENERIC_BUG_H | 2 | #define _TOOLS_ASM_BUG_H |
3 | |||
4 | #include <linux/compiler.h> | ||
3 | 5 | ||
4 | #define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0) | 6 | #define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0) |
5 | 7 | ||
@@ -19,4 +21,5 @@ | |||
19 | __warned = 1; \ | 21 | __warned = 1; \ |
20 | unlikely(__ret_warn_once); \ | 22 | unlikely(__ret_warn_once); \ |
21 | }) | 23 | }) |
22 | #endif | 24 | |
25 | #endif /* _TOOLS_ASM_BUG_H */ | ||
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/include/linux/compiler.h index b003ad7200b2..fbc6665c6d53 100644 --- a/tools/perf/util/include/linux/compiler.h +++ b/tools/include/linux/compiler.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _PERF_LINUX_COMPILER_H_ | 1 | #ifndef _TOOLS_LINUX_COMPILER_H_ |
2 | #define _PERF_LINUX_COMPILER_H_ | 2 | #define _TOOLS_LINUX_COMPILER_H_ |
3 | 3 | ||
4 | #ifndef __always_inline | 4 | #ifndef __always_inline |
5 | # define __always_inline inline __attribute__((always_inline)) | 5 | # define __always_inline inline __attribute__((always_inline)) |
@@ -27,4 +27,12 @@ | |||
27 | # define __weak __attribute__((weak)) | 27 | # define __weak __attribute__((weak)) |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #ifndef likely | ||
31 | # define likely(x) __builtin_expect(!!(x), 1) | ||
30 | #endif | 32 | #endif |
33 | |||
34 | #ifndef unlikely | ||
35 | # define unlikely(x) __builtin_expect(!!(x), 0) | ||
36 | #endif | ||
37 | |||
38 | #endif /* _TOOLS_LINUX_COMPILER_H */ | ||
diff --git a/tools/lib/lk/Makefile b/tools/lib/api/Makefile index 3dba0a4aebbf..ed2f51e11b80 100644 --- a/tools/lib/lk/Makefile +++ b/tools/lib/api/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | include ../../scripts/Makefile.include | 1 | include ../../scripts/Makefile.include |
2 | include ../../perf/config/utilities.mak # QUIET_CLEAN | ||
2 | 3 | ||
3 | CC = $(CROSS_COMPILE)gcc | 4 | CC = $(CROSS_COMPILE)gcc |
4 | AR = $(CROSS_COMPILE)ar | 5 | AR = $(CROSS_COMPILE)ar |
@@ -7,11 +8,11 @@ AR = $(CROSS_COMPILE)ar | |||
7 | LIB_H= | 8 | LIB_H= |
8 | LIB_OBJS= | 9 | LIB_OBJS= |
9 | 10 | ||
10 | LIB_H += debugfs.h | 11 | LIB_H += fs/debugfs.h |
11 | 12 | ||
12 | LIB_OBJS += $(OUTPUT)debugfs.o | 13 | LIB_OBJS += $(OUTPUT)fs/debugfs.o |
13 | 14 | ||
14 | LIBFILE = liblk.a | 15 | LIBFILE = libapikfs.a |
15 | 16 | ||
16 | CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC | 17 | CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC |
17 | EXTLIBS = -lelf -lpthread -lrt -lm | 18 | EXTLIBS = -lelf -lpthread -lrt -lm |
@@ -25,14 +26,17 @@ $(LIBFILE): $(LIB_OBJS) | |||
25 | 26 | ||
26 | $(LIB_OBJS): $(LIB_H) | 27 | $(LIB_OBJS): $(LIB_H) |
27 | 28 | ||
28 | $(OUTPUT)%.o: %.c | 29 | libapi_dirs: |
30 | $(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/ | ||
31 | |||
32 | $(OUTPUT)%.o: %.c libapi_dirs | ||
29 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< | 33 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< |
30 | $(OUTPUT)%.s: %.c | 34 | $(OUTPUT)%.s: %.c libapi_dirs |
31 | $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< | 35 | $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< |
32 | $(OUTPUT)%.o: %.S | 36 | $(OUTPUT)%.o: %.S libapi_dirs |
33 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< | 37 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< |
34 | 38 | ||
35 | clean: | 39 | clean: |
36 | $(RM) $(LIB_OBJS) $(LIBFILE) | 40 | $(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE) |
37 | 41 | ||
38 | .PHONY: clean | 42 | .PHONY: clean |
diff --git a/tools/lib/lk/debugfs.c b/tools/lib/api/fs/debugfs.c index 7c4347962353..7c4347962353 100644 --- a/tools/lib/lk/debugfs.c +++ b/tools/lib/api/fs/debugfs.c | |||
diff --git a/tools/lib/lk/debugfs.h b/tools/lib/api/fs/debugfs.h index 935c59bdb442..f19d3df9609d 100644 --- a/tools/lib/lk/debugfs.h +++ b/tools/lib/api/fs/debugfs.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef __LK_DEBUGFS_H__ | 1 | #ifndef __API_DEBUGFS_H__ |
2 | #define __LK_DEBUGFS_H__ | 2 | #define __API_DEBUGFS_H__ |
3 | 3 | ||
4 | #define _STR(x) #x | 4 | #define _STR(x) #x |
5 | #define STR(x) _STR(x) | 5 | #define STR(x) _STR(x) |
@@ -26,4 +26,4 @@ char *debugfs_mount(const char *mountpoint); | |||
26 | 26 | ||
27 | extern char debugfs_mountpoint[]; | 27 | extern char debugfs_mountpoint[]; |
28 | 28 | ||
29 | #endif /* __LK_DEBUGFS_H__ */ | 29 | #endif /* __API_DEBUGFS_H__ */ |
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile new file mode 100644 index 000000000000..da8b7aa3d351 --- /dev/null +++ b/tools/lib/lockdep/Makefile | |||
@@ -0,0 +1,251 @@ | |||
1 | # liblockdep version | ||
2 | LL_VERSION = 0 | ||
3 | LL_PATCHLEVEL = 0 | ||
4 | LL_EXTRAVERSION = 1 | ||
5 | |||
6 | # file format version | ||
7 | FILE_VERSION = 1 | ||
8 | |||
9 | MAKEFLAGS += --no-print-directory | ||
10 | |||
11 | |||
12 | # Makefiles suck: This macro sets a default value of $(2) for the | ||
13 | # variable named by $(1), unless the variable has been set by | ||
14 | # environment or command line. This is necessary for CC and AR | ||
15 | # because make sets default values, so the simpler ?= approach | ||
16 | # won't work as expected. | ||
17 | define allow-override | ||
18 | $(if $(or $(findstring environment,$(origin $(1))),\ | ||
19 | $(findstring command line,$(origin $(1)))),,\ | ||
20 | $(eval $(1) = $(2))) | ||
21 | endef | ||
22 | |||
23 | # Allow setting CC and AR, or setting CROSS_COMPILE as a prefix. | ||
24 | $(call allow-override,CC,$(CROSS_COMPILE)gcc) | ||
25 | $(call allow-override,AR,$(CROSS_COMPILE)ar) | ||
26 | |||
27 | INSTALL = install | ||
28 | |||
29 | # Use DESTDIR for installing into a different root directory. | ||
30 | # This is useful for building a package. The program will be | ||
31 | # installed in this directory as if it was the root directory. | ||
32 | # Then the build tool can move it later. | ||
33 | DESTDIR ?= | ||
34 | DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' | ||
35 | |||
36 | prefix ?= /usr/local | ||
37 | libdir_relative = lib | ||
38 | libdir = $(prefix)/$(libdir_relative) | ||
39 | bindir_relative = bin | ||
40 | bindir = $(prefix)/$(bindir_relative) | ||
41 | |||
42 | export DESTDIR DESTDIR_SQ INSTALL | ||
43 | |||
44 | # copy a bit from Linux kbuild | ||
45 | |||
46 | ifeq ("$(origin V)", "command line") | ||
47 | VERBOSE = $(V) | ||
48 | endif | ||
49 | ifndef VERBOSE | ||
50 | VERBOSE = 0 | ||
51 | endif | ||
52 | |||
53 | ifeq ("$(origin O)", "command line") | ||
54 | BUILD_OUTPUT := $(O) | ||
55 | endif | ||
56 | |||
57 | ifeq ($(BUILD_SRC),) | ||
58 | ifneq ($(BUILD_OUTPUT),) | ||
59 | |||
60 | define build_output | ||
61 | $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \ | ||
62 | BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1 | ||
63 | endef | ||
64 | |||
65 | saved-output := $(BUILD_OUTPUT) | ||
66 | BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd) | ||
67 | $(if $(BUILD_OUTPUT),, \ | ||
68 | $(error output directory "$(saved-output)" does not exist)) | ||
69 | |||
70 | all: sub-make | ||
71 | |||
72 | gui: force | ||
73 | $(call build_output, all_cmd) | ||
74 | |||
75 | $(filter-out gui,$(MAKECMDGOALS)): sub-make | ||
76 | |||
77 | sub-make: force | ||
78 | $(call build_output, $(MAKECMDGOALS)) | ||
79 | |||
80 | |||
81 | # Leave processing to above invocation of make | ||
82 | skip-makefile := 1 | ||
83 | |||
84 | endif # BUILD_OUTPUT | ||
85 | endif # BUILD_SRC | ||
86 | |||
87 | # We process the rest of the Makefile if this is the final invocation of make | ||
88 | ifeq ($(skip-makefile),) | ||
89 | |||
90 | srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)) | ||
91 | objtree := $(CURDIR) | ||
92 | src := $(srctree) | ||
93 | obj := $(objtree) | ||
94 | |||
95 | export prefix libdir bindir src obj | ||
96 | |||
97 | # Shell quotes | ||
98 | libdir_SQ = $(subst ','\'',$(libdir)) | ||
99 | bindir_SQ = $(subst ','\'',$(bindir)) | ||
100 | |||
101 | LIB_FILE = liblockdep.a liblockdep.so | ||
102 | BIN_FILE = lockdep | ||
103 | |||
104 | CONFIG_INCLUDES = | ||
105 | CONFIG_LIBS = | ||
106 | CONFIG_FLAGS = | ||
107 | |||
108 | OBJ = $@ | ||
109 | N = | ||
110 | |||
111 | export Q VERBOSE | ||
112 | |||
113 | LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION) | ||
114 | |||
115 | INCLUDES = -I. -I/usr/local/include -I./uinclude $(CONFIG_INCLUDES) | ||
116 | |||
117 | # Set compile option CFLAGS if not set elsewhere | ||
118 | CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g | ||
119 | |||
120 | override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) | ||
121 | |||
122 | ifeq ($(VERBOSE),1) | ||
123 | Q = | ||
124 | print_compile = | ||
125 | print_app_build = | ||
126 | print_fpic_compile = | ||
127 | print_shared_lib_compile = | ||
128 | print_install = | ||
129 | else | ||
130 | Q = @ | ||
131 | print_compile = echo ' CC '$(OBJ); | ||
132 | print_app_build = echo ' BUILD '$(OBJ); | ||
133 | print_fpic_compile = echo ' CC FPIC '$(OBJ); | ||
134 | print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); | ||
135 | print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); | ||
136 | print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; | ||
137 | endif | ||
138 | |||
139 | do_fpic_compile = \ | ||
140 | ($(print_fpic_compile) \ | ||
141 | $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@) | ||
142 | |||
143 | do_app_build = \ | ||
144 | ($(print_app_build) \ | ||
145 | $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS)) | ||
146 | |||
147 | do_compile_shared_library = \ | ||
148 | ($(print_shared_lib_compile) \ | ||
149 | $(CC) --shared $^ -o $@ -lpthread -ldl) | ||
150 | |||
151 | do_build_static_lib = \ | ||
152 | ($(print_static_lib_build) \ | ||
153 | $(RM) $@; $(AR) rcs $@ $^) | ||
154 | |||
155 | |||
156 | define do_compile | ||
157 | $(print_compile) \ | ||
158 | $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@; | ||
159 | endef | ||
160 | |||
161 | $(obj)/%.o: $(src)/%.c | ||
162 | $(Q)$(call do_compile) | ||
163 | |||
164 | %.o: $(src)/%.c | ||
165 | $(Q)$(call do_compile) | ||
166 | |||
167 | PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o | ||
168 | |||
169 | ALL_OBJS = $(PEVENT_LIB_OBJS) | ||
170 | |||
171 | CMD_TARGETS = $(LIB_FILE) | ||
172 | |||
173 | TARGETS = $(CMD_TARGETS) | ||
174 | |||
175 | |||
176 | all: all_cmd | ||
177 | |||
178 | all_cmd: $(CMD_TARGETS) | ||
179 | |||
180 | liblockdep.so: $(PEVENT_LIB_OBJS) | ||
181 | $(Q)$(do_compile_shared_library) | ||
182 | |||
183 | liblockdep.a: $(PEVENT_LIB_OBJS) | ||
184 | $(Q)$(do_build_static_lib) | ||
185 | |||
186 | $(PEVENT_LIB_OBJS): %.o: $(src)/%.c | ||
187 | $(Q)$(do_fpic_compile) | ||
188 | |||
189 | ## make deps | ||
190 | |||
191 | all_objs := $(sort $(ALL_OBJS)) | ||
192 | all_deps := $(all_objs:%.o=.%.d) | ||
193 | |||
194 | # let .d file also depends on the source and header files | ||
195 | define check_deps | ||
196 | @set -e; $(RM) $@; \ | ||
197 | $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ | ||
198 | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ | ||
199 | $(RM) $@.$$$$ | ||
200 | endef | ||
201 | |||
202 | $(all_deps): .%.d: $(src)/%.c | ||
203 | $(Q)$(call check_deps) | ||
204 | |||
205 | $(all_objs) : %.o : .%.d | ||
206 | |||
207 | dep_includes := $(wildcard $(all_deps)) | ||
208 | |||
209 | ifneq ($(dep_includes),) | ||
210 | include $(dep_includes) | ||
211 | endif | ||
212 | |||
213 | ### Detect environment changes | ||
214 | TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE) | ||
215 | |||
216 | tags: force | ||
217 | $(RM) tags | ||
218 | find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ | ||
219 | --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' | ||
220 | |||
221 | TAGS: force | ||
222 | $(RM) TAGS | ||
223 | find . -name '*.[ch]' | xargs etags \ | ||
224 | --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' | ||
225 | |||
226 | define do_install | ||
227 | $(print_install) \ | ||
228 | if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ | ||
229 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ | ||
230 | fi; \ | ||
231 | $(INSTALL) $1 '$(DESTDIR_SQ)$2' | ||
232 | endef | ||
233 | |||
234 | install_lib: all_cmd | ||
235 | $(Q)$(call do_install,$(LIB_FILE),$(libdir_SQ)) | ||
236 | $(Q)$(call do_install,$(BIN_FILE),$(bindir_SQ)) | ||
237 | |||
238 | install: install_lib | ||
239 | |||
240 | clean: | ||
241 | $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d | ||
242 | $(RM) tags TAGS | ||
243 | |||
244 | endif # skip-makefile | ||
245 | |||
246 | PHONY += force | ||
247 | force: | ||
248 | |||
249 | # Declare the contents of the .PHONY variable as phony. We keep that | ||
250 | # information in a variable so we can use it in if_changed and friends. | ||
251 | .PHONY: $(PHONY) | ||
diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c new file mode 100644 index 000000000000..8ef602f18a32 --- /dev/null +++ b/tools/lib/lockdep/common.c | |||
@@ -0,0 +1,33 @@ | |||
1 | #include <stddef.h> | ||
2 | #include <stdbool.h> | ||
3 | #include <linux/compiler.h> | ||
4 | #include <linux/lockdep.h> | ||
5 | #include <unistd.h> | ||
6 | #include <sys/syscall.h> | ||
7 | |||
8 | static __thread struct task_struct current_obj; | ||
9 | |||
10 | /* lockdep wants these */ | ||
11 | bool debug_locks = true; | ||
12 | bool debug_locks_silent; | ||
13 | |||
14 | __attribute__((constructor)) static void liblockdep_init(void) | ||
15 | { | ||
16 | lockdep_init(); | ||
17 | } | ||
18 | |||
19 | __attribute__((destructor)) static void liblockdep_exit(void) | ||
20 | { | ||
21 | debug_check_no_locks_held(¤t_obj); | ||
22 | } | ||
23 | |||
24 | struct task_struct *__curr(void) | ||
25 | { | ||
26 | if (current_obj.pid == 0) { | ||
27 | /* Makes lockdep output pretty */ | ||
28 | prctl(PR_GET_NAME, current_obj.comm); | ||
29 | current_obj.pid = syscall(__NR_gettid); | ||
30 | } | ||
31 | |||
32 | return ¤t_obj; | ||
33 | } | ||
diff --git a/tools/lib/lockdep/include/liblockdep/common.h b/tools/lib/lockdep/include/liblockdep/common.h new file mode 100644 index 000000000000..0bda630027c3 --- /dev/null +++ b/tools/lib/lockdep/include/liblockdep/common.h | |||
@@ -0,0 +1,50 @@ | |||
1 | #ifndef _LIBLOCKDEP_COMMON_H | ||
2 | #define _LIBLOCKDEP_COMMON_H | ||
3 | |||
4 | #include <pthread.h> | ||
5 | |||
6 | #define NR_LOCKDEP_CACHING_CLASSES 2 | ||
7 | #define MAX_LOCKDEP_SUBCLASSES 8UL | ||
8 | |||
9 | #ifndef CALLER_ADDR0 | ||
10 | #define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) | ||
11 | #endif | ||
12 | |||
13 | #ifndef _RET_IP_ | ||
14 | #define _RET_IP_ CALLER_ADDR0 | ||
15 | #endif | ||
16 | |||
17 | #ifndef _THIS_IP_ | ||
18 | #define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) | ||
19 | #endif | ||
20 | |||
21 | struct lockdep_subclass_key { | ||
22 | char __one_byte; | ||
23 | }; | ||
24 | |||
25 | struct lock_class_key { | ||
26 | struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES]; | ||
27 | }; | ||
28 | |||
29 | struct lockdep_map { | ||
30 | struct lock_class_key *key; | ||
31 | struct lock_class *class_cache[NR_LOCKDEP_CACHING_CLASSES]; | ||
32 | const char *name; | ||
33 | #ifdef CONFIG_LOCK_STAT | ||
34 | int cpu; | ||
35 | unsigned long ip; | ||
36 | #endif | ||
37 | }; | ||
38 | |||
39 | void lockdep_init_map(struct lockdep_map *lock, const char *name, | ||
40 | struct lock_class_key *key, int subclass); | ||
41 | void lock_acquire(struct lockdep_map *lock, unsigned int subclass, | ||
42 | int trylock, int read, int check, | ||
43 | struct lockdep_map *nest_lock, unsigned long ip); | ||
44 | void lock_release(struct lockdep_map *lock, int nested, | ||
45 | unsigned long ip); | ||
46 | |||
47 | #define STATIC_LOCKDEP_MAP_INIT(_name, _key) \ | ||
48 | { .name = (_name), .key = (void *)(_key), } | ||
49 | |||
50 | #endif | ||
diff --git a/tools/lib/lockdep/include/liblockdep/mutex.h b/tools/lib/lockdep/include/liblockdep/mutex.h new file mode 100644 index 000000000000..c342f7087147 --- /dev/null +++ b/tools/lib/lockdep/include/liblockdep/mutex.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #ifndef _LIBLOCKDEP_MUTEX_H | ||
2 | #define _LIBLOCKDEP_MUTEX_H | ||
3 | |||
4 | #include <pthread.h> | ||
5 | #include "common.h" | ||
6 | |||
7 | struct liblockdep_pthread_mutex { | ||
8 | pthread_mutex_t mutex; | ||
9 | struct lockdep_map dep_map; | ||
10 | }; | ||
11 | |||
12 | typedef struct liblockdep_pthread_mutex liblockdep_pthread_mutex_t; | ||
13 | |||
14 | #define LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(mtx) \ | ||
15 | (const struct liblockdep_pthread_mutex) { \ | ||
16 | .mutex = PTHREAD_MUTEX_INITIALIZER, \ | ||
17 | .dep_map = STATIC_LOCKDEP_MAP_INIT(#mtx, &((&(mtx))->dep_map)), \ | ||
18 | } | ||
19 | |||
20 | static inline int __mutex_init(liblockdep_pthread_mutex_t *lock, | ||
21 | const char *name, | ||
22 | struct lock_class_key *key, | ||
23 | const pthread_mutexattr_t *__mutexattr) | ||
24 | { | ||
25 | lockdep_init_map(&lock->dep_map, name, key, 0); | ||
26 | return pthread_mutex_init(&lock->mutex, __mutexattr); | ||
27 | } | ||
28 | |||
29 | #define liblockdep_pthread_mutex_init(mutex, mutexattr) \ | ||
30 | ({ \ | ||
31 | static struct lock_class_key __key; \ | ||
32 | \ | ||
33 | __mutex_init((mutex), #mutex, &__key, (mutexattr)); \ | ||
34 | }) | ||
35 | |||
36 | static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock) | ||
37 | { | ||
38 | lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
39 | return pthread_mutex_lock(&lock->mutex); | ||
40 | } | ||
41 | |||
42 | static inline int liblockdep_pthread_mutex_unlock(liblockdep_pthread_mutex_t *lock) | ||
43 | { | ||
44 | lock_release(&lock->dep_map, 0, (unsigned long)_RET_IP_); | ||
45 | return pthread_mutex_unlock(&lock->mutex); | ||
46 | } | ||
47 | |||
48 | static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock) | ||
49 | { | ||
50 | lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
51 | return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0; | ||
52 | } | ||
53 | |||
54 | static inline int liblockdep_pthread_mutex_destroy(liblockdep_pthread_mutex_t *lock) | ||
55 | { | ||
56 | return pthread_mutex_destroy(&lock->mutex); | ||
57 | } | ||
58 | |||
59 | #ifdef __USE_LIBLOCKDEP | ||
60 | |||
61 | #define pthread_mutex_t liblockdep_pthread_mutex_t | ||
62 | #define pthread_mutex_init liblockdep_pthread_mutex_init | ||
63 | #define pthread_mutex_lock liblockdep_pthread_mutex_lock | ||
64 | #define pthread_mutex_unlock liblockdep_pthread_mutex_unlock | ||
65 | #define pthread_mutex_trylock liblockdep_pthread_mutex_trylock | ||
66 | #define pthread_mutex_destroy liblockdep_pthread_mutex_destroy | ||
67 | |||
68 | #endif | ||
69 | |||
70 | #endif | ||
diff --git a/tools/lib/lockdep/include/liblockdep/rwlock.h b/tools/lib/lockdep/include/liblockdep/rwlock.h new file mode 100644 index 000000000000..a680ab8c2e36 --- /dev/null +++ b/tools/lib/lockdep/include/liblockdep/rwlock.h | |||
@@ -0,0 +1,86 @@ | |||
1 | #ifndef _LIBLOCKDEP_RWLOCK_H | ||
2 | #define _LIBLOCKDEP_RWLOCK_H | ||
3 | |||
4 | #include <pthread.h> | ||
5 | #include "common.h" | ||
6 | |||
7 | struct liblockdep_pthread_rwlock { | ||
8 | pthread_rwlock_t rwlock; | ||
9 | struct lockdep_map dep_map; | ||
10 | }; | ||
11 | |||
12 | typedef struct liblockdep_pthread_rwlock liblockdep_pthread_rwlock_t; | ||
13 | |||
14 | #define LIBLOCKDEP_PTHREAD_RWLOCK_INITIALIZER(rwl) \ | ||
15 | (struct liblockdep_pthread_rwlock) { \ | ||
16 | .rwlock = PTHREAD_RWLOCK_INITIALIZER, \ | ||
17 | .dep_map = STATIC_LOCKDEP_MAP_INIT(#rwl, &((&(rwl))->dep_map)), \ | ||
18 | } | ||
19 | |||
20 | static inline int __rwlock_init(liblockdep_pthread_rwlock_t *lock, | ||
21 | const char *name, | ||
22 | struct lock_class_key *key, | ||
23 | const pthread_rwlockattr_t *attr) | ||
24 | { | ||
25 | lockdep_init_map(&lock->dep_map, name, key, 0); | ||
26 | |||
27 | return pthread_rwlock_init(&lock->rwlock, attr); | ||
28 | } | ||
29 | |||
30 | #define liblockdep_pthread_rwlock_init(lock, attr) \ | ||
31 | ({ \ | ||
32 | static struct lock_class_key __key; \ | ||
33 | \ | ||
34 | __rwlock_init((lock), #lock, &__key, (attr)); \ | ||
35 | }) | ||
36 | |||
37 | static inline int liblockdep_pthread_rwlock_rdlock(liblockdep_pthread_rwlock_t *lock) | ||
38 | { | ||
39 | lock_acquire(&lock->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_); | ||
40 | return pthread_rwlock_rdlock(&lock->rwlock); | ||
41 | |||
42 | } | ||
43 | |||
44 | static inline int liblockdep_pthread_rwlock_unlock(liblockdep_pthread_rwlock_t *lock) | ||
45 | { | ||
46 | lock_release(&lock->dep_map, 0, (unsigned long)_RET_IP_); | ||
47 | return pthread_rwlock_unlock(&lock->rwlock); | ||
48 | } | ||
49 | |||
50 | static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock) | ||
51 | { | ||
52 | lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
53 | return pthread_rwlock_wrlock(&lock->rwlock); | ||
54 | } | ||
55 | |||
56 | static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock) | ||
57 | { | ||
58 | lock_acquire(&lock->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_); | ||
59 | return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0; | ||
60 | } | ||
61 | |||
62 | static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock) | ||
63 | { | ||
64 | lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
65 | return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0; | ||
66 | } | ||
67 | |||
68 | static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock) | ||
69 | { | ||
70 | return pthread_rwlock_destroy(&lock->rwlock); | ||
71 | } | ||
72 | |||
73 | #ifdef __USE_LIBLOCKDEP | ||
74 | |||
75 | #define pthread_rwlock_t liblockdep_pthread_rwlock_t | ||
76 | #define pthread_rwlock_init liblockdep_pthread_rwlock_init | ||
77 | #define pthread_rwlock_rdlock liblockdep_pthread_rwlock_rdlock | ||
78 | #define pthread_rwlock_unlock liblockdep_pthread_rwlock_unlock | ||
79 | #define pthread_rwlock_wrlock liblockdep_pthread_rwlock_wrlock | ||
80 | #define pthread_rwlock_tryrdlock liblockdep_pthread_rwlock_tryrdlock | ||
81 | #define pthread_rwlock_trywlock liblockdep_pthread_rwlock_trywlock | ||
82 | #define pthread_rwlock_destroy liblockdep_rwlock_destroy | ||
83 | |||
84 | #endif | ||
85 | |||
86 | #endif | ||
diff --git a/tools/lib/lockdep/lockdep b/tools/lib/lockdep/lockdep new file mode 100755 index 000000000000..49af9fe19f5b --- /dev/null +++ b/tools/lib/lockdep/lockdep | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | LD_PRELOAD="./liblockdep.so $LD_PRELOAD" "$@" | ||
diff --git a/tools/lib/lockdep/lockdep.c b/tools/lib/lockdep/lockdep.c new file mode 100644 index 000000000000..f42b7e9aa48f --- /dev/null +++ b/tools/lib/lockdep/lockdep.c | |||
@@ -0,0 +1,2 @@ | |||
1 | #include <linux/lockdep.h> | ||
2 | #include "../../../kernel/locking/lockdep.c" | ||
diff --git a/tools/lib/lockdep/lockdep_internals.h b/tools/lib/lockdep/lockdep_internals.h new file mode 100644 index 000000000000..29d0c954cc24 --- /dev/null +++ b/tools/lib/lockdep/lockdep_internals.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../kernel/locking/lockdep_internals.h" | |||
diff --git a/tools/lib/lockdep/lockdep_states.h b/tools/lib/lockdep/lockdep_states.h new file mode 100644 index 000000000000..248d235efda9 --- /dev/null +++ b/tools/lib/lockdep/lockdep_states.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../kernel/locking/lockdep_states.h" | |||
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c new file mode 100644 index 000000000000..f8465a811aa5 --- /dev/null +++ b/tools/lib/lockdep/preload.c | |||
@@ -0,0 +1,447 @@ | |||
1 | #define _GNU_SOURCE | ||
2 | #include <pthread.h> | ||
3 | #include <stdio.h> | ||
4 | #include <dlfcn.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <sysexits.h> | ||
7 | #include "include/liblockdep/mutex.h" | ||
8 | #include "../../../include/linux/rbtree.h" | ||
9 | |||
10 | /** | ||
11 | * struct lock_lookup - liblockdep's view of a single unique lock | ||
12 | * @orig: pointer to the original pthread lock, used for lookups | ||
13 | * @dep_map: lockdep's dep_map structure | ||
14 | * @key: lockdep's key structure | ||
15 | * @node: rb-tree node used to store the lock in a global tree | ||
16 | * @name: a unique name for the lock | ||
17 | */ | ||
18 | struct lock_lookup { | ||
19 | void *orig; /* Original pthread lock, used for lookups */ | ||
20 | struct lockdep_map dep_map; /* Since all locks are dynamic, we need | ||
21 | * a dep_map and a key for each lock */ | ||
22 | /* | ||
23 | * Wait, there's no support for key classes? Yup :( | ||
24 | * Most big projects wrap the pthread api with their own calls to | ||
25 | * be compatible with different locking methods. This means that | ||
26 | * "classes" will be brokes since the function that creates all | ||
27 | * locks will point to a generic locking function instead of the | ||
28 | * actual code that wants to do the locking. | ||
29 | */ | ||
30 | struct lock_class_key key; | ||
31 | struct rb_node node; | ||
32 | #define LIBLOCKDEP_MAX_LOCK_NAME 22 | ||
33 | char name[LIBLOCKDEP_MAX_LOCK_NAME]; | ||
34 | }; | ||
35 | |||
36 | /* This is where we store our locks */ | ||
37 | static struct rb_root locks = RB_ROOT; | ||
38 | static pthread_rwlock_t locks_rwlock = PTHREAD_RWLOCK_INITIALIZER; | ||
39 | |||
40 | /* pthread mutex API */ | ||
41 | |||
42 | #ifdef __GLIBC__ | ||
43 | extern int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); | ||
44 | extern int __pthread_mutex_lock(pthread_mutex_t *mutex); | ||
45 | extern int __pthread_mutex_trylock(pthread_mutex_t *mutex); | ||
46 | extern int __pthread_mutex_unlock(pthread_mutex_t *mutex); | ||
47 | extern int __pthread_mutex_destroy(pthread_mutex_t *mutex); | ||
48 | #else | ||
49 | #define __pthread_mutex_init NULL | ||
50 | #define __pthread_mutex_lock NULL | ||
51 | #define __pthread_mutex_trylock NULL | ||
52 | #define __pthread_mutex_unlock NULL | ||
53 | #define __pthread_mutex_destroy NULL | ||
54 | #endif | ||
55 | static int (*ll_pthread_mutex_init)(pthread_mutex_t *mutex, | ||
56 | const pthread_mutexattr_t *attr) = __pthread_mutex_init; | ||
57 | static int (*ll_pthread_mutex_lock)(pthread_mutex_t *mutex) = __pthread_mutex_lock; | ||
58 | static int (*ll_pthread_mutex_trylock)(pthread_mutex_t *mutex) = __pthread_mutex_trylock; | ||
59 | static int (*ll_pthread_mutex_unlock)(pthread_mutex_t *mutex) = __pthread_mutex_unlock; | ||
60 | static int (*ll_pthread_mutex_destroy)(pthread_mutex_t *mutex) = __pthread_mutex_destroy; | ||
61 | |||
62 | /* pthread rwlock API */ | ||
63 | |||
64 | #ifdef __GLIBC__ | ||
65 | extern int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); | ||
66 | extern int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock); | ||
67 | extern int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); | ||
68 | extern int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); | ||
69 | extern int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); | ||
70 | extern int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); | ||
71 | extern int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock); | ||
72 | #else | ||
73 | #define __pthread_rwlock_init NULL | ||
74 | #define __pthread_rwlock_destroy NULL | ||
75 | #define __pthread_rwlock_wrlock NULL | ||
76 | #define __pthread_rwlock_trywrlock NULL | ||
77 | #define __pthread_rwlock_rdlock NULL | ||
78 | #define __pthread_rwlock_tryrdlock NULL | ||
79 | #define __pthread_rwlock_unlock NULL | ||
80 | #endif | ||
81 | |||
82 | static int (*ll_pthread_rwlock_init)(pthread_rwlock_t *rwlock, | ||
83 | const pthread_rwlockattr_t *attr) = __pthread_rwlock_init; | ||
84 | static int (*ll_pthread_rwlock_destroy)(pthread_rwlock_t *rwlock) = __pthread_rwlock_destroy; | ||
85 | static int (*ll_pthread_rwlock_rdlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_rdlock; | ||
86 | static int (*ll_pthread_rwlock_tryrdlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_tryrdlock; | ||
87 | static int (*ll_pthread_rwlock_trywrlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_trywrlock; | ||
88 | static int (*ll_pthread_rwlock_wrlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_wrlock; | ||
89 | static int (*ll_pthread_rwlock_unlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_unlock; | ||
90 | |||
91 | enum { none, prepare, done, } __init_state; | ||
92 | static void init_preload(void); | ||
93 | static void try_init_preload(void) | ||
94 | { | ||
95 | if (!__init_state != done) | ||
96 | init_preload(); | ||
97 | } | ||
98 | |||
99 | static struct rb_node **__get_lock_node(void *lock, struct rb_node **parent) | ||
100 | { | ||
101 | struct rb_node **node = &locks.rb_node; | ||
102 | struct lock_lookup *l; | ||
103 | |||
104 | *parent = NULL; | ||
105 | |||
106 | while (*node) { | ||
107 | l = rb_entry(*node, struct lock_lookup, node); | ||
108 | |||
109 | *parent = *node; | ||
110 | if (lock < l->orig) | ||
111 | node = &l->node.rb_left; | ||
112 | else if (lock > l->orig) | ||
113 | node = &l->node.rb_right; | ||
114 | else | ||
115 | return node; | ||
116 | } | ||
117 | |||
118 | return node; | ||
119 | } | ||
120 | |||
121 | #ifndef LIBLOCKDEP_STATIC_ENTRIES | ||
122 | #define LIBLOCKDEP_STATIC_ENTRIES 1024 | ||
123 | #endif | ||
124 | |||
125 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) | ||
126 | |||
127 | static struct lock_lookup __locks[LIBLOCKDEP_STATIC_ENTRIES]; | ||
128 | static int __locks_nr; | ||
129 | |||
130 | static inline bool is_static_lock(struct lock_lookup *lock) | ||
131 | { | ||
132 | return lock >= __locks && lock < __locks + ARRAY_SIZE(__locks); | ||
133 | } | ||
134 | |||
135 | static struct lock_lookup *alloc_lock(void) | ||
136 | { | ||
137 | if (__init_state != done) { | ||
138 | /* | ||
139 | * Some programs attempt to initialize and use locks in their | ||
140 | * allocation path. This means that a call to malloc() would | ||
141 | * result in locks being initialized and locked. | ||
142 | * | ||
143 | * Why is it an issue for us? dlsym() below will try allocating | ||
144 | * to give us the original function. Since this allocation will | ||
145 | * result in a locking operations, we have to let pthread deal | ||
146 | * with it, but we can't! we don't have the pointer to the | ||
147 | * original API since we're inside dlsym() trying to get it | ||
148 | */ | ||
149 | |||
150 | int idx = __locks_nr++; | ||
151 | if (idx >= ARRAY_SIZE(__locks)) { | ||
152 | fprintf(stderr, | ||
153 | "LOCKDEP error: insufficient LIBLOCKDEP_STATIC_ENTRIES\n"); | ||
154 | exit(EX_UNAVAILABLE); | ||
155 | } | ||
156 | return __locks + idx; | ||
157 | } | ||
158 | |||
159 | return malloc(sizeof(struct lock_lookup)); | ||
160 | } | ||
161 | |||
162 | static inline void free_lock(struct lock_lookup *lock) | ||
163 | { | ||
164 | if (likely(!is_static_lock(lock))) | ||
165 | free(lock); | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * __get_lock - find or create a lock instance | ||
170 | * @lock: pointer to a pthread lock function | ||
171 | * | ||
172 | * Try to find an existing lock in the rbtree using the provided pointer. If | ||
173 | * one wasn't found - create it. | ||
174 | */ | ||
175 | static struct lock_lookup *__get_lock(void *lock) | ||
176 | { | ||
177 | struct rb_node **node, *parent; | ||
178 | struct lock_lookup *l; | ||
179 | |||
180 | ll_pthread_rwlock_rdlock(&locks_rwlock); | ||
181 | node = __get_lock_node(lock, &parent); | ||
182 | ll_pthread_rwlock_unlock(&locks_rwlock); | ||
183 | if (*node) { | ||
184 | return rb_entry(*node, struct lock_lookup, node); | ||
185 | } | ||
186 | |||
187 | /* We didn't find the lock, let's create it */ | ||
188 | l = alloc_lock(); | ||
189 | if (l == NULL) | ||
190 | return NULL; | ||
191 | |||
192 | l->orig = lock; | ||
193 | /* | ||
194 | * Currently the name of the lock is the ptr value of the pthread lock, | ||
195 | * while not optimal, it makes debugging a bit easier. | ||
196 | * | ||
197 | * TODO: Get the real name of the lock using libdwarf | ||
198 | */ | ||
199 | sprintf(l->name, "%p", lock); | ||
200 | lockdep_init_map(&l->dep_map, l->name, &l->key, 0); | ||
201 | |||
202 | ll_pthread_rwlock_wrlock(&locks_rwlock); | ||
203 | /* This might have changed since the last time we fetched it */ | ||
204 | node = __get_lock_node(lock, &parent); | ||
205 | rb_link_node(&l->node, parent, node); | ||
206 | rb_insert_color(&l->node, &locks); | ||
207 | ll_pthread_rwlock_unlock(&locks_rwlock); | ||
208 | |||
209 | return l; | ||
210 | } | ||
211 | |||
212 | static void __del_lock(struct lock_lookup *lock) | ||
213 | { | ||
214 | ll_pthread_rwlock_wrlock(&locks_rwlock); | ||
215 | rb_erase(&lock->node, &locks); | ||
216 | ll_pthread_rwlock_unlock(&locks_rwlock); | ||
217 | free_lock(lock); | ||
218 | } | ||
219 | |||
220 | int pthread_mutex_init(pthread_mutex_t *mutex, | ||
221 | const pthread_mutexattr_t *attr) | ||
222 | { | ||
223 | int r; | ||
224 | |||
225 | /* | ||
226 | * We keep trying to init our preload module because there might be | ||
227 | * code in init sections that tries to touch locks before we are | ||
228 | * initialized, in that case we'll need to manually call preload | ||
229 | * to get us going. | ||
230 | * | ||
231 | * Funny enough, kernel's lockdep had the same issue, and used | ||
232 | * (almost) the same solution. See look_up_lock_class() in | ||
233 | * kernel/locking/lockdep.c for details. | ||
234 | */ | ||
235 | try_init_preload(); | ||
236 | |||
237 | r = ll_pthread_mutex_init(mutex, attr); | ||
238 | if (r == 0) | ||
239 | /* | ||
240 | * We do a dummy initialization here so that lockdep could | ||
241 | * warn us if something fishy is going on - such as | ||
242 | * initializing a held lock. | ||
243 | */ | ||
244 | __get_lock(mutex); | ||
245 | |||
246 | return r; | ||
247 | } | ||
248 | |||
249 | int pthread_mutex_lock(pthread_mutex_t *mutex) | ||
250 | { | ||
251 | int r; | ||
252 | |||
253 | try_init_preload(); | ||
254 | |||
255 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL, | ||
256 | (unsigned long)_RET_IP_); | ||
257 | /* | ||
258 | * Here's the thing with pthread mutexes: unlike the kernel variant, | ||
259 | * they can fail. | ||
260 | * | ||
261 | * This means that the behaviour here is a bit different from what's | ||
262 | * going on in the kernel: there we just tell lockdep that we took the | ||
263 | * lock before actually taking it, but here we must deal with the case | ||
264 | * that locking failed. | ||
265 | * | ||
266 | * To do that we'll "release" the lock if locking failed - this way | ||
267 | * we'll get lockdep doing the correct checks when we try to take | ||
268 | * the lock, and if that fails - we'll be back to the correct | ||
269 | * state by releasing it. | ||
270 | */ | ||
271 | r = ll_pthread_mutex_lock(mutex); | ||
272 | if (r) | ||
273 | lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_); | ||
274 | |||
275 | return r; | ||
276 | } | ||
277 | |||
278 | int pthread_mutex_trylock(pthread_mutex_t *mutex) | ||
279 | { | ||
280 | int r; | ||
281 | |||
282 | try_init_preload(); | ||
283 | |||
284 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
285 | r = ll_pthread_mutex_trylock(mutex); | ||
286 | if (r) | ||
287 | lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_); | ||
288 | |||
289 | return r; | ||
290 | } | ||
291 | |||
292 | int pthread_mutex_unlock(pthread_mutex_t *mutex) | ||
293 | { | ||
294 | int r; | ||
295 | |||
296 | try_init_preload(); | ||
297 | |||
298 | lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_); | ||
299 | /* | ||
300 | * Just like taking a lock, only in reverse! | ||
301 | * | ||
302 | * If we fail releasing the lock, tell lockdep we're holding it again. | ||
303 | */ | ||
304 | r = ll_pthread_mutex_unlock(mutex); | ||
305 | if (r) | ||
306 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
307 | |||
308 | return r; | ||
309 | } | ||
310 | |||
311 | int pthread_mutex_destroy(pthread_mutex_t *mutex) | ||
312 | { | ||
313 | try_init_preload(); | ||
314 | |||
315 | /* | ||
316 | * Let's see if we're releasing a lock that's held. | ||
317 | * | ||
318 | * TODO: Hook into free() and add that check there as well. | ||
319 | */ | ||
320 | debug_check_no_locks_freed(mutex, mutex + sizeof(*mutex)); | ||
321 | __del_lock(__get_lock(mutex)); | ||
322 | return ll_pthread_mutex_destroy(mutex); | ||
323 | } | ||
324 | |||
325 | /* This is the rwlock part, very similar to what happened with mutex above */ | ||
326 | int pthread_rwlock_init(pthread_rwlock_t *rwlock, | ||
327 | const pthread_rwlockattr_t *attr) | ||
328 | { | ||
329 | int r; | ||
330 | |||
331 | try_init_preload(); | ||
332 | |||
333 | r = ll_pthread_rwlock_init(rwlock, attr); | ||
334 | if (r == 0) | ||
335 | __get_lock(rwlock); | ||
336 | |||
337 | return r; | ||
338 | } | ||
339 | |||
340 | int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) | ||
341 | { | ||
342 | try_init_preload(); | ||
343 | |||
344 | debug_check_no_locks_freed(rwlock, rwlock + sizeof(*rwlock)); | ||
345 | __del_lock(__get_lock(rwlock)); | ||
346 | return ll_pthread_rwlock_destroy(rwlock); | ||
347 | } | ||
348 | |||
349 | int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) | ||
350 | { | ||
351 | int r; | ||
352 | |||
353 | init_preload(); | ||
354 | |||
355 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_); | ||
356 | r = ll_pthread_rwlock_rdlock(rwlock); | ||
357 | if (r) | ||
358 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
359 | |||
360 | return r; | ||
361 | } | ||
362 | |||
363 | int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) | ||
364 | { | ||
365 | int r; | ||
366 | |||
367 | init_preload(); | ||
368 | |||
369 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_); | ||
370 | r = ll_pthread_rwlock_tryrdlock(rwlock); | ||
371 | if (r) | ||
372 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
373 | |||
374 | return r; | ||
375 | } | ||
376 | |||
377 | int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) | ||
378 | { | ||
379 | int r; | ||
380 | |||
381 | init_preload(); | ||
382 | |||
383 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
384 | r = ll_pthread_rwlock_trywrlock(rwlock); | ||
385 | if (r) | ||
386 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
387 | |||
388 | return r; | ||
389 | } | ||
390 | |||
391 | int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) | ||
392 | { | ||
393 | int r; | ||
394 | |||
395 | init_preload(); | ||
396 | |||
397 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
398 | r = ll_pthread_rwlock_wrlock(rwlock); | ||
399 | if (r) | ||
400 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
401 | |||
402 | return r; | ||
403 | } | ||
404 | |||
405 | int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) | ||
406 | { | ||
407 | int r; | ||
408 | |||
409 | init_preload(); | ||
410 | |||
411 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
412 | r = ll_pthread_rwlock_unlock(rwlock); | ||
413 | if (r) | ||
414 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
415 | |||
416 | return r; | ||
417 | } | ||
418 | |||
419 | __attribute__((constructor)) static void init_preload(void) | ||
420 | { | ||
421 | if (__init_state != done) | ||
422 | return; | ||
423 | |||
424 | #ifndef __GLIBC__ | ||
425 | __init_state = prepare; | ||
426 | |||
427 | ll_pthread_mutex_init = dlsym(RTLD_NEXT, "pthread_mutex_init"); | ||
428 | ll_pthread_mutex_lock = dlsym(RTLD_NEXT, "pthread_mutex_lock"); | ||
429 | ll_pthread_mutex_trylock = dlsym(RTLD_NEXT, "pthread_mutex_trylock"); | ||
430 | ll_pthread_mutex_unlock = dlsym(RTLD_NEXT, "pthread_mutex_unlock"); | ||
431 | ll_pthread_mutex_destroy = dlsym(RTLD_NEXT, "pthread_mutex_destroy"); | ||
432 | |||
433 | ll_pthread_rwlock_init = dlsym(RTLD_NEXT, "pthread_rwlock_init"); | ||
434 | ll_pthread_rwlock_destroy = dlsym(RTLD_NEXT, "pthread_rwlock_destroy"); | ||
435 | ll_pthread_rwlock_rdlock = dlsym(RTLD_NEXT, "pthread_rwlock_rdlock"); | ||
436 | ll_pthread_rwlock_tryrdlock = dlsym(RTLD_NEXT, "pthread_rwlock_tryrdlock"); | ||
437 | ll_pthread_rwlock_wrlock = dlsym(RTLD_NEXT, "pthread_rwlock_wrlock"); | ||
438 | ll_pthread_rwlock_trywrlock = dlsym(RTLD_NEXT, "pthread_rwlock_trywrlock"); | ||
439 | ll_pthread_rwlock_unlock = dlsym(RTLD_NEXT, "pthread_rwlock_unlock"); | ||
440 | #endif | ||
441 | |||
442 | printf("%p\n", ll_pthread_mutex_trylock);fflush(stdout); | ||
443 | |||
444 | lockdep_init(); | ||
445 | |||
446 | __init_state = done; | ||
447 | } | ||
diff --git a/tools/lib/lockdep/rbtree.c b/tools/lib/lockdep/rbtree.c new file mode 100644 index 000000000000..f7f43033c8b7 --- /dev/null +++ b/tools/lib/lockdep/rbtree.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../lib/rbtree.c" | |||
diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh new file mode 100644 index 000000000000..5334ad9d39b7 --- /dev/null +++ b/tools/lib/lockdep/run_tests.sh | |||
@@ -0,0 +1,27 @@ | |||
1 | #! /bin/bash | ||
2 | |||
3 | make &> /dev/null | ||
4 | |||
5 | for i in `ls tests/*.c`; do | ||
6 | testname=$(basename -s .c "$i") | ||
7 | gcc -o tests/$testname -pthread -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null | ||
8 | echo -ne "$testname... " | ||
9 | if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then | ||
10 | echo "PASSED!" | ||
11 | else | ||
12 | echo "FAILED!" | ||
13 | fi | ||
14 | rm tests/$testname | ||
15 | done | ||
16 | |||
17 | for i in `ls tests/*.c`; do | ||
18 | testname=$(basename -s .c "$i") | ||
19 | gcc -o tests/$testname -pthread -lpthread -Iinclude $i &> /dev/null | ||
20 | echo -ne "(PRELOAD) $testname... " | ||
21 | if [ $(timeout 1 ./lockdep ./tests/$testname | wc -l) -gt 0 ]; then | ||
22 | echo "PASSED!" | ||
23 | else | ||
24 | echo "FAILED!" | ||
25 | fi | ||
26 | rm tests/$testname | ||
27 | done | ||
diff --git a/tools/lib/lockdep/tests/AA.c b/tools/lib/lockdep/tests/AA.c new file mode 100644 index 000000000000..0f782ff404ac --- /dev/null +++ b/tools/lib/lockdep/tests/AA.c | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | |||
3 | void main(void) | ||
4 | { | ||
5 | pthread_mutex_t a, b; | ||
6 | |||
7 | pthread_mutex_init(&a, NULL); | ||
8 | pthread_mutex_init(&b, NULL); | ||
9 | |||
10 | pthread_mutex_lock(&a); | ||
11 | pthread_mutex_lock(&b); | ||
12 | pthread_mutex_lock(&a); | ||
13 | } | ||
diff --git a/tools/lib/lockdep/tests/ABBA.c b/tools/lib/lockdep/tests/ABBA.c new file mode 100644 index 000000000000..07f0e29d5485 --- /dev/null +++ b/tools/lib/lockdep/tests/ABBA.c | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | |||
11 | LOCK_UNLOCK_2(a, b); | ||
12 | LOCK_UNLOCK_2(b, a); | ||
13 | } | ||
diff --git a/tools/lib/lockdep/tests/ABBCCA.c b/tools/lib/lockdep/tests/ABBCCA.c new file mode 100644 index 000000000000..843db09ac666 --- /dev/null +++ b/tools/lib/lockdep/tests/ABBCCA.c | |||
@@ -0,0 +1,15 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | |||
12 | LOCK_UNLOCK_2(a, b); | ||
13 | LOCK_UNLOCK_2(b, c); | ||
14 | LOCK_UNLOCK_2(c, a); | ||
15 | } | ||
diff --git a/tools/lib/lockdep/tests/ABBCCDDA.c b/tools/lib/lockdep/tests/ABBCCDDA.c new file mode 100644 index 000000000000..33620e268f85 --- /dev/null +++ b/tools/lib/lockdep/tests/ABBCCDDA.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c, d; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | pthread_mutex_init(&d, NULL); | ||
12 | |||
13 | LOCK_UNLOCK_2(a, b); | ||
14 | LOCK_UNLOCK_2(b, c); | ||
15 | LOCK_UNLOCK_2(c, d); | ||
16 | LOCK_UNLOCK_2(d, a); | ||
17 | } | ||
diff --git a/tools/lib/lockdep/tests/ABCABC.c b/tools/lib/lockdep/tests/ABCABC.c new file mode 100644 index 000000000000..3fee51e3a68a --- /dev/null +++ b/tools/lib/lockdep/tests/ABCABC.c | |||
@@ -0,0 +1,15 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | |||
12 | LOCK_UNLOCK_2(a, b); | ||
13 | LOCK_UNLOCK_2(c, a); | ||
14 | LOCK_UNLOCK_2(b, c); | ||
15 | } | ||
diff --git a/tools/lib/lockdep/tests/ABCDBCDA.c b/tools/lib/lockdep/tests/ABCDBCDA.c new file mode 100644 index 000000000000..427ba562c75b --- /dev/null +++ b/tools/lib/lockdep/tests/ABCDBCDA.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c, d; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | pthread_mutex_init(&d, NULL); | ||
12 | |||
13 | LOCK_UNLOCK_2(a, b); | ||
14 | LOCK_UNLOCK_2(c, d); | ||
15 | LOCK_UNLOCK_2(b, c); | ||
16 | LOCK_UNLOCK_2(d, a); | ||
17 | } | ||
diff --git a/tools/lib/lockdep/tests/ABCDBDDA.c b/tools/lib/lockdep/tests/ABCDBDDA.c new file mode 100644 index 000000000000..680c6cf3e919 --- /dev/null +++ b/tools/lib/lockdep/tests/ABCDBDDA.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c, d; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | pthread_mutex_init(&d, NULL); | ||
12 | |||
13 | LOCK_UNLOCK_2(a, b); | ||
14 | LOCK_UNLOCK_2(c, d); | ||
15 | LOCK_UNLOCK_2(b, d); | ||
16 | LOCK_UNLOCK_2(d, a); | ||
17 | } | ||
diff --git a/tools/lib/lockdep/tests/WW.c b/tools/lib/lockdep/tests/WW.c new file mode 100644 index 000000000000..d44f77d71029 --- /dev/null +++ b/tools/lib/lockdep/tests/WW.c | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <liblockdep/rwlock.h> | ||
2 | |||
3 | void main(void) | ||
4 | { | ||
5 | pthread_rwlock_t a, b; | ||
6 | |||
7 | pthread_rwlock_init(&a, NULL); | ||
8 | pthread_rwlock_init(&b, NULL); | ||
9 | |||
10 | pthread_rwlock_wrlock(&a); | ||
11 | pthread_rwlock_rdlock(&b); | ||
12 | pthread_rwlock_wrlock(&a); | ||
13 | } | ||
diff --git a/tools/lib/lockdep/tests/common.h b/tools/lib/lockdep/tests/common.h new file mode 100644 index 000000000000..d89e94d47d86 --- /dev/null +++ b/tools/lib/lockdep/tests/common.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _LIBLOCKDEP_TEST_COMMON_H | ||
2 | #define _LIBLOCKDEP_TEST_COMMON_H | ||
3 | |||
4 | #define LOCK_UNLOCK_2(a, b) \ | ||
5 | do { \ | ||
6 | pthread_mutex_lock(&(a)); \ | ||
7 | pthread_mutex_lock(&(b)); \ | ||
8 | pthread_mutex_unlock(&(b)); \ | ||
9 | pthread_mutex_unlock(&(a)); \ | ||
10 | } while(0) | ||
11 | |||
12 | #endif | ||
diff --git a/tools/lib/lockdep/tests/unlock_balance.c b/tools/lib/lockdep/tests/unlock_balance.c new file mode 100644 index 000000000000..0bc62de686f7 --- /dev/null +++ b/tools/lib/lockdep/tests/unlock_balance.c | |||
@@ -0,0 +1,12 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | |||
3 | void main(void) | ||
4 | { | ||
5 | pthread_mutex_t a; | ||
6 | |||
7 | pthread_mutex_init(&a, NULL); | ||
8 | |||
9 | pthread_mutex_lock(&a); | ||
10 | pthread_mutex_unlock(&a); | ||
11 | pthread_mutex_unlock(&a); | ||
12 | } | ||
diff --git a/tools/lib/lockdep/uinclude/asm/hweight.h b/tools/lib/lockdep/uinclude/asm/hweight.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/asm/hweight.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/asm/sections.h b/tools/lib/lockdep/uinclude/asm/sections.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/asm/sections.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/bitops.h b/tools/lib/lockdep/uinclude/linux/bitops.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/bitops.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/compiler.h b/tools/lib/lockdep/uinclude/linux/compiler.h new file mode 100644 index 000000000000..7ac838a1f196 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/compiler.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_COMPILER_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_COMPILER_H_ | ||
3 | |||
4 | #define __used __attribute__((__unused__)) | ||
5 | #define unlikely | ||
6 | |||
7 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/debug_locks.h b/tools/lib/lockdep/uinclude/linux/debug_locks.h new file mode 100644 index 000000000000..f38eb64df794 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/debug_locks.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_ | ||
2 | #define _LIBLOCKDEP_DEBUG_LOCKS_H_ | ||
3 | |||
4 | #include <stddef.h> | ||
5 | #include <linux/compiler.h> | ||
6 | |||
7 | #define DEBUG_LOCKS_WARN_ON(x) (x) | ||
8 | |||
9 | extern bool debug_locks; | ||
10 | extern bool debug_locks_silent; | ||
11 | |||
12 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/delay.h b/tools/lib/lockdep/uinclude/linux/delay.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/delay.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/export.h b/tools/lib/lockdep/uinclude/linux/export.h new file mode 100644 index 000000000000..6bdf3492c535 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/export.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_EXPORT_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_EXPORT_H_ | ||
3 | |||
4 | #define EXPORT_SYMBOL(sym) | ||
5 | #define EXPORT_SYMBOL_GPL(sym) | ||
6 | |||
7 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/ftrace.h b/tools/lib/lockdep/uinclude/linux/ftrace.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/ftrace.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/gfp.h b/tools/lib/lockdep/uinclude/linux/gfp.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/gfp.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/hardirq.h b/tools/lib/lockdep/uinclude/linux/hardirq.h new file mode 100644 index 000000000000..c8f3f8f58729 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/hardirq.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_HARDIRQ_H_ | ||
3 | |||
4 | #define SOFTIRQ_BITS 0UL | ||
5 | #define HARDIRQ_BITS 0UL | ||
6 | #define SOFTIRQ_SHIFT 0UL | ||
7 | #define HARDIRQ_SHIFT 0UL | ||
8 | #define hardirq_count() 0UL | ||
9 | #define softirq_count() 0UL | ||
10 | |||
11 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/hash.h b/tools/lib/lockdep/uinclude/linux/hash.h new file mode 100644 index 000000000000..0f8479858dc0 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/hash.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../include/linux/hash.h" | |||
diff --git a/tools/lib/lockdep/uinclude/linux/interrupt.h b/tools/lib/lockdep/uinclude/linux/interrupt.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/interrupt.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/irqflags.h b/tools/lib/lockdep/uinclude/linux/irqflags.h new file mode 100644 index 000000000000..6cc296f0fad0 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/irqflags.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_ | ||
3 | |||
4 | # define trace_hardirq_context(p) 0 | ||
5 | # define trace_softirq_context(p) 0 | ||
6 | # define trace_hardirqs_enabled(p) 0 | ||
7 | # define trace_softirqs_enabled(p) 0 | ||
8 | # define trace_hardirq_enter() do { } while (0) | ||
9 | # define trace_hardirq_exit() do { } while (0) | ||
10 | # define lockdep_softirq_enter() do { } while (0) | ||
11 | # define lockdep_softirq_exit() do { } while (0) | ||
12 | # define INIT_TRACE_IRQFLAGS | ||
13 | |||
14 | # define stop_critical_timings() do { } while (0) | ||
15 | # define start_critical_timings() do { } while (0) | ||
16 | |||
17 | #define raw_local_irq_disable() do { } while (0) | ||
18 | #define raw_local_irq_enable() do { } while (0) | ||
19 | #define raw_local_irq_save(flags) ((flags) = 0) | ||
20 | #define raw_local_irq_restore(flags) do { } while (0) | ||
21 | #define raw_local_save_flags(flags) ((flags) = 0) | ||
22 | #define raw_irqs_disabled_flags(flags) do { } while (0) | ||
23 | #define raw_irqs_disabled() 0 | ||
24 | #define raw_safe_halt() | ||
25 | |||
26 | #define local_irq_enable() do { } while (0) | ||
27 | #define local_irq_disable() do { } while (0) | ||
28 | #define local_irq_save(flags) ((flags) = 0) | ||
29 | #define local_irq_restore(flags) do { } while (0) | ||
30 | #define local_save_flags(flags) ((flags) = 0) | ||
31 | #define irqs_disabled() (1) | ||
32 | #define irqs_disabled_flags(flags) (0) | ||
33 | #define safe_halt() do { } while (0) | ||
34 | |||
35 | #define trace_lock_release(x, y) | ||
36 | #define trace_lock_acquire(a, b, c, d, e, f, g) | ||
37 | |||
38 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/kallsyms.h b/tools/lib/lockdep/uinclude/linux/kallsyms.h new file mode 100644 index 000000000000..b0f2dbdf1a15 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/kallsyms.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_KALLSYMS_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_KALLSYMS_H_ | ||
3 | |||
4 | #include <linux/kernel.h> | ||
5 | #include <stdio.h> | ||
6 | |||
7 | #define KSYM_NAME_LEN 128 | ||
8 | |||
9 | struct module; | ||
10 | |||
11 | static inline const char *kallsyms_lookup(unsigned long addr, | ||
12 | unsigned long *symbolsize, | ||
13 | unsigned long *offset, | ||
14 | char **modname, char *namebuf) | ||
15 | { | ||
16 | return NULL; | ||
17 | } | ||
18 | |||
19 | #include <execinfo.h> | ||
20 | #include <stdlib.h> | ||
21 | static inline void print_ip_sym(unsigned long ip) | ||
22 | { | ||
23 | char **name; | ||
24 | |||
25 | name = backtrace_symbols((void **)&ip, 1); | ||
26 | |||
27 | printf("%s\n", *name); | ||
28 | |||
29 | free(name); | ||
30 | } | ||
31 | |||
32 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/kern_levels.h b/tools/lib/lockdep/uinclude/linux/kern_levels.h new file mode 100644 index 000000000000..3b9bade28698 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/kern_levels.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef __KERN_LEVELS_H__ | ||
2 | #define __KERN_LEVELS_H__ | ||
3 | |||
4 | #define KERN_SOH "" /* ASCII Start Of Header */ | ||
5 | #define KERN_SOH_ASCII '' | ||
6 | |||
7 | #define KERN_EMERG KERN_SOH "" /* system is unusable */ | ||
8 | #define KERN_ALERT KERN_SOH "" /* action must be taken immediately */ | ||
9 | #define KERN_CRIT KERN_SOH "" /* critical conditions */ | ||
10 | #define KERN_ERR KERN_SOH "" /* error conditions */ | ||
11 | #define KERN_WARNING KERN_SOH "" /* warning conditions */ | ||
12 | #define KERN_NOTICE KERN_SOH "" /* normal but significant condition */ | ||
13 | #define KERN_INFO KERN_SOH "" /* informational */ | ||
14 | #define KERN_DEBUG KERN_SOH "" /* debug-level messages */ | ||
15 | |||
16 | #define KERN_DEFAULT KERN_SOH "" /* the default kernel loglevel */ | ||
17 | |||
18 | /* | ||
19 | * Annotation for a "continued" line of log printout (only done after a | ||
20 | * line that had no enclosing \n). Only to be used by core/arch code | ||
21 | * during early bootup (a continued line is not SMP-safe otherwise). | ||
22 | */ | ||
23 | #define KERN_CONT "" | ||
24 | |||
25 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/kernel.h b/tools/lib/lockdep/uinclude/linux/kernel.h new file mode 100644 index 000000000000..a11e3c357be7 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/kernel.h | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_KERNEL_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_KERNEL_H_ | ||
3 | |||
4 | #include <linux/export.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <linux/rcu.h> | ||
7 | #include <linux/hardirq.h> | ||
8 | #include <linux/kern_levels.h> | ||
9 | |||
10 | #ifndef container_of | ||
11 | #define container_of(ptr, type, member) ({ \ | ||
12 | const typeof(((type *)0)->member) * __mptr = (ptr); \ | ||
13 | (type *)((char *)__mptr - offsetof(type, member)); }) | ||
14 | #endif | ||
15 | |||
16 | #define max(x, y) ({ \ | ||
17 | typeof(x) _max1 = (x); \ | ||
18 | typeof(y) _max2 = (y); \ | ||
19 | (void) (&_max1 == &_max2); \ | ||
20 | _max1 > _max2 ? _max1 : _max2; }) | ||
21 | |||
22 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) | ||
23 | #define WARN_ON(x) (x) | ||
24 | #define WARN_ON_ONCE(x) (x) | ||
25 | #define likely(x) (x) | ||
26 | #define WARN(x, y, z) (x) | ||
27 | #define uninitialized_var(x) x | ||
28 | #define __init | ||
29 | #define noinline | ||
30 | #define list_add_tail_rcu list_add_tail | ||
31 | |||
32 | #ifndef CALLER_ADDR0 | ||
33 | #define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) | ||
34 | #endif | ||
35 | |||
36 | #ifndef _RET_IP_ | ||
37 | #define _RET_IP_ CALLER_ADDR0 | ||
38 | #endif | ||
39 | |||
40 | #ifndef _THIS_IP_ | ||
41 | #define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) | ||
42 | #endif | ||
43 | |||
44 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/kmemcheck.h b/tools/lib/lockdep/uinclude/linux/kmemcheck.h new file mode 100644 index 000000000000..94d598bc6abe --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/kmemcheck.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_KMEMCHECK_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_KMEMCHECK_H_ | ||
3 | |||
4 | static inline void kmemcheck_mark_initialized(void *address, unsigned int n) | ||
5 | { | ||
6 | } | ||
7 | |||
8 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/linkage.h b/tools/lib/lockdep/uinclude/linux/linkage.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/linkage.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/list.h b/tools/lib/lockdep/uinclude/linux/list.h new file mode 100644 index 000000000000..6e9ef31ed82e --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/list.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../include/linux/list.h" | |||
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h new file mode 100644 index 000000000000..d0f5d6e50214 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/lockdep.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #ifndef _LIBLOCKDEP_LOCKDEP_H_ | ||
2 | #define _LIBLOCKDEP_LOCKDEP_H_ | ||
3 | |||
4 | #include <sys/prctl.h> | ||
5 | #include <sys/syscall.h> | ||
6 | #include <string.h> | ||
7 | #include <limits.h> | ||
8 | #include <linux/utsname.h> | ||
9 | |||
10 | |||
11 | #define MAX_LOCK_DEPTH 2000UL | ||
12 | |||
13 | #include "../../../include/linux/lockdep.h" | ||
14 | |||
15 | struct task_struct { | ||
16 | u64 curr_chain_key; | ||
17 | int lockdep_depth; | ||
18 | unsigned int lockdep_recursion; | ||
19 | struct held_lock held_locks[MAX_LOCK_DEPTH]; | ||
20 | gfp_t lockdep_reclaim_gfp; | ||
21 | int pid; | ||
22 | char comm[17]; | ||
23 | }; | ||
24 | |||
25 | extern struct task_struct *__curr(void); | ||
26 | |||
27 | #define current (__curr()) | ||
28 | |||
29 | #define debug_locks_off() 1 | ||
30 | #define task_pid_nr(tsk) ((tsk)->pid) | ||
31 | |||
32 | #define KSYM_NAME_LEN 128 | ||
33 | #define printk printf | ||
34 | |||
35 | #define list_del_rcu list_del | ||
36 | |||
37 | #define atomic_t unsigned long | ||
38 | #define atomic_inc(x) ((*(x))++) | ||
39 | |||
40 | static struct new_utsname *init_utsname(void) | ||
41 | { | ||
42 | static struct new_utsname n = (struct new_utsname) { | ||
43 | .release = "liblockdep", | ||
44 | .version = LIBLOCKDEP_VERSION, | ||
45 | }; | ||
46 | |||
47 | return &n; | ||
48 | } | ||
49 | |||
50 | #define print_tainted() "" | ||
51 | #define static_obj(x) 1 | ||
52 | |||
53 | #define debug_show_all_locks() | ||
54 | |||
55 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/module.h b/tools/lib/lockdep/uinclude/linux/module.h new file mode 100644 index 000000000000..09c7a7be8ccc --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/module.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_MODULE_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_MODULE_H_ | ||
3 | |||
4 | #define module_param(name, type, perm) | ||
5 | |||
6 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/mutex.h b/tools/lib/lockdep/uinclude/linux/mutex.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/mutex.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/poison.h b/tools/lib/lockdep/uinclude/linux/poison.h new file mode 100644 index 000000000000..0c27bdf14233 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/poison.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../include/linux/poison.h" | |||
diff --git a/tools/lib/lockdep/uinclude/linux/prefetch.h b/tools/lib/lockdep/uinclude/linux/prefetch.h new file mode 100644 index 000000000000..d73fe6f850ac --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/prefetch.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_PREFETCH_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_PREFETCH_H | ||
3 | |||
4 | static inline void prefetch(void *a __attribute__((unused))) { } | ||
5 | |||
6 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/proc_fs.h b/tools/lib/lockdep/uinclude/linux/proc_fs.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/proc_fs.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree.h b/tools/lib/lockdep/uinclude/linux/rbtree.h new file mode 100644 index 000000000000..965901db4862 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/rbtree.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../include/linux/rbtree.h" | |||
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h b/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h new file mode 100644 index 000000000000..c3759477379c --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h | |||
@@ -0,0 +1,2 @@ | |||
1 | #define __always_inline | ||
2 | #include "../../../include/linux/rbtree_augmented.h" | ||
diff --git a/tools/lib/lockdep/uinclude/linux/rcu.h b/tools/lib/lockdep/uinclude/linux/rcu.h new file mode 100644 index 000000000000..4c99fcb5da27 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/rcu.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef _LIBLOCKDEP_RCU_H_ | ||
2 | #define _LIBLOCKDEP_RCU_H_ | ||
3 | |||
4 | int rcu_scheduler_active; | ||
5 | |||
6 | static inline int rcu_lockdep_current_cpu_online(void) | ||
7 | { | ||
8 | return 1; | ||
9 | } | ||
10 | |||
11 | static inline int rcu_is_cpu_idle(void) | ||
12 | { | ||
13 | return 1; | ||
14 | } | ||
15 | |||
16 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/seq_file.h b/tools/lib/lockdep/uinclude/linux/seq_file.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/seq_file.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/spinlock.h b/tools/lib/lockdep/uinclude/linux/spinlock.h new file mode 100644 index 000000000000..68c1aa2bcba5 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/spinlock.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _LIBLOCKDEP_SPINLOCK_H_ | ||
2 | #define _LIBLOCKDEP_SPINLOCK_H_ | ||
3 | |||
4 | #include <pthread.h> | ||
5 | #include <stdbool.h> | ||
6 | |||
7 | #define arch_spinlock_t pthread_mutex_t | ||
8 | #define __ARCH_SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER | ||
9 | |||
10 | static inline void arch_spin_lock(arch_spinlock_t *mutex) | ||
11 | { | ||
12 | pthread_mutex_lock(mutex); | ||
13 | } | ||
14 | |||
15 | static inline void arch_spin_unlock(arch_spinlock_t *mutex) | ||
16 | { | ||
17 | pthread_mutex_unlock(mutex); | ||
18 | } | ||
19 | |||
20 | static inline bool arch_spin_is_locked(arch_spinlock_t *mutex) | ||
21 | { | ||
22 | return true; | ||
23 | } | ||
24 | |||
25 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/stacktrace.h b/tools/lib/lockdep/uinclude/linux/stacktrace.h new file mode 100644 index 000000000000..39aecc6b19d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/stacktrace.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_STACKTRACE_H_ | ||
3 | |||
4 | #include <execinfo.h> | ||
5 | |||
6 | struct stack_trace { | ||
7 | unsigned int nr_entries, max_entries; | ||
8 | unsigned long *entries; | ||
9 | int skip; | ||
10 | }; | ||
11 | |||
12 | static inline void print_stack_trace(struct stack_trace *trace, int spaces) | ||
13 | { | ||
14 | backtrace_symbols_fd((void **)trace->entries, trace->nr_entries, 1); | ||
15 | } | ||
16 | |||
17 | #define save_stack_trace(trace) \ | ||
18 | ((trace)->nr_entries = \ | ||
19 | backtrace((void **)(trace)->entries, (trace)->max_entries)) | ||
20 | |||
21 | static inline int dump_stack(void) | ||
22 | { | ||
23 | void *array[64]; | ||
24 | size_t size; | ||
25 | |||
26 | size = backtrace(array, 64); | ||
27 | backtrace_symbols_fd(array, size, 1); | ||
28 | |||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/stringify.h b/tools/lib/lockdep/uinclude/linux/stringify.h new file mode 100644 index 000000000000..05dfcd1ac118 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/stringify.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_STRINGIFY_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_STRINGIFY_H_ | ||
3 | |||
4 | #define __stringify_1(x...) #x | ||
5 | #define __stringify(x...) __stringify_1(x) | ||
6 | |||
7 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/types.h b/tools/lib/lockdep/uinclude/linux/types.h new file mode 100644 index 000000000000..929938f426de --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/types.h | |||
@@ -0,0 +1,58 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_TYPES_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_TYPES_H_ | ||
3 | |||
4 | #include <stdbool.h> | ||
5 | #include <stddef.h> | ||
6 | |||
7 | #define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ | ||
8 | #include <asm/types.h> | ||
9 | |||
10 | struct page; | ||
11 | struct kmem_cache; | ||
12 | |||
13 | typedef unsigned gfp_t; | ||
14 | |||
15 | typedef __u64 u64; | ||
16 | typedef __s64 s64; | ||
17 | |||
18 | typedef __u32 u32; | ||
19 | typedef __s32 s32; | ||
20 | |||
21 | typedef __u16 u16; | ||
22 | typedef __s16 s16; | ||
23 | |||
24 | typedef __u8 u8; | ||
25 | typedef __s8 s8; | ||
26 | |||
27 | #ifdef __CHECKER__ | ||
28 | #define __bitwise__ __attribute__((bitwise)) | ||
29 | #else | ||
30 | #define __bitwise__ | ||
31 | #endif | ||
32 | #ifdef __CHECK_ENDIAN__ | ||
33 | #define __bitwise __bitwise__ | ||
34 | #else | ||
35 | #define __bitwise | ||
36 | #endif | ||
37 | |||
38 | |||
39 | typedef __u16 __bitwise __le16; | ||
40 | typedef __u16 __bitwise __be16; | ||
41 | typedef __u32 __bitwise __le32; | ||
42 | typedef __u32 __bitwise __be32; | ||
43 | typedef __u64 __bitwise __le64; | ||
44 | typedef __u64 __bitwise __be64; | ||
45 | |||
46 | struct list_head { | ||
47 | struct list_head *next, *prev; | ||
48 | }; | ||
49 | |||
50 | struct hlist_head { | ||
51 | struct hlist_node *first; | ||
52 | }; | ||
53 | |||
54 | struct hlist_node { | ||
55 | struct hlist_node *next, **pprev; | ||
56 | }; | ||
57 | |||
58 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/trace/events/lock.h b/tools/lib/lockdep/uinclude/trace/events/lock.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/trace/events/lock.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c new file mode 100644 index 000000000000..18bc271a4bbc --- /dev/null +++ b/tools/lib/symbol/kallsyms.c | |||
@@ -0,0 +1,58 @@ | |||
1 | #include "symbol/kallsyms.h" | ||
2 | #include <stdio.h> | ||
3 | #include <stdlib.h> | ||
4 | |||
5 | int kallsyms__parse(const char *filename, void *arg, | ||
6 | int (*process_symbol)(void *arg, const char *name, | ||
7 | char type, u64 start)) | ||
8 | { | ||
9 | char *line = NULL; | ||
10 | size_t n; | ||
11 | int err = -1; | ||
12 | FILE *file = fopen(filename, "r"); | ||
13 | |||
14 | if (file == NULL) | ||
15 | goto out_failure; | ||
16 | |||
17 | err = 0; | ||
18 | |||
19 | while (!feof(file)) { | ||
20 | u64 start; | ||
21 | int line_len, len; | ||
22 | char symbol_type; | ||
23 | char *symbol_name; | ||
24 | |||
25 | line_len = getline(&line, &n, file); | ||
26 | if (line_len < 0 || !line) | ||
27 | break; | ||
28 | |||
29 | line[--line_len] = '\0'; /* \n */ | ||
30 | |||
31 | len = hex2u64(line, &start); | ||
32 | |||
33 | len++; | ||
34 | if (len + 2 >= line_len) | ||
35 | continue; | ||
36 | |||
37 | symbol_type = line[len]; | ||
38 | len += 2; | ||
39 | symbol_name = line + len; | ||
40 | len = line_len - len; | ||
41 | |||
42 | if (len >= KSYM_NAME_LEN) { | ||
43 | err = -1; | ||
44 | break; | ||
45 | } | ||
46 | |||
47 | err = process_symbol(arg, symbol_name, symbol_type, start); | ||
48 | if (err) | ||
49 | break; | ||
50 | } | ||
51 | |||
52 | free(line); | ||
53 | fclose(file); | ||
54 | return err; | ||
55 | |||
56 | out_failure: | ||
57 | return -1; | ||
58 | } | ||
diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h new file mode 100644 index 000000000000..6084f5e18b3c --- /dev/null +++ b/tools/lib/symbol/kallsyms.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef __TOOLS_KALLSYMS_H_ | ||
2 | #define __TOOLS_KALLSYMS_H_ 1 | ||
3 | |||
4 | #include <elf.h> | ||
5 | #include <linux/ctype.h> | ||
6 | #include <linux/types.h> | ||
7 | |||
8 | #ifndef KSYM_NAME_LEN | ||
9 | #define KSYM_NAME_LEN 256 | ||
10 | #endif | ||
11 | |||
12 | static inline u8 kallsyms2elf_type(char type) | ||
13 | { | ||
14 | if (type == 'W') | ||
15 | return STB_WEAK; | ||
16 | |||
17 | return isupper(type) ? STB_GLOBAL : STB_LOCAL; | ||
18 | } | ||
19 | |||
20 | int kallsyms__parse(const char *filename, void *arg, | ||
21 | int (*process_symbol)(void *arg, const char *name, | ||
22 | char type, u64 start)); | ||
23 | |||
24 | #endif /* __TOOLS_KALLSYMS_H_ */ | ||
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index fc1502098595..56d52a33a3df 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile | |||
@@ -43,6 +43,32 @@ man_dir_SQ = '$(subst ','\'',$(man_dir))' | |||
43 | export man_dir man_dir_SQ INSTALL | 43 | export man_dir man_dir_SQ INSTALL |
44 | export DESTDIR DESTDIR_SQ | 44 | export DESTDIR DESTDIR_SQ |
45 | 45 | ||
46 | set_plugin_dir := 1 | ||
47 | |||
48 | # Set plugin_dir to preffered global plugin location | ||
49 | # If we install under $HOME directory we go under | ||
50 | # $(HOME)/.traceevent/plugins | ||
51 | # | ||
52 | # We dont set PLUGIN_DIR in case we install under $HOME | ||
53 | # directory, because by default the code looks under: | ||
54 | # $(HOME)/.traceevent/plugins by default. | ||
55 | # | ||
56 | ifeq ($(plugin_dir),) | ||
57 | ifeq ($(prefix),$(HOME)) | ||
58 | override plugin_dir = $(HOME)/.traceevent/plugins | ||
59 | set_plugin_dir := 0 | ||
60 | else | ||
61 | override plugin_dir = $(prefix)/lib/traceevent/plugins | ||
62 | endif | ||
63 | endif | ||
64 | |||
65 | ifeq ($(set_plugin_dir),1) | ||
66 | PLUGIN_DIR = -DPLUGIN_DIR="$(DESTDIR)/$(plugin_dir)" | ||
67 | PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' | ||
68 | endif | ||
69 | |||
70 | include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include | ||
71 | |||
46 | # copy a bit from Linux kbuild | 72 | # copy a bit from Linux kbuild |
47 | 73 | ||
48 | ifeq ("$(origin V)", "command line") | 74 | ifeq ("$(origin V)", "command line") |
@@ -57,18 +83,13 @@ ifeq ("$(origin O)", "command line") | |||
57 | endif | 83 | endif |
58 | 84 | ||
59 | ifeq ($(BUILD_SRC),) | 85 | ifeq ($(BUILD_SRC),) |
60 | ifneq ($(BUILD_OUTPUT),) | 86 | ifneq ($(OUTPUT),) |
61 | 87 | ||
62 | define build_output | 88 | define build_output |
63 | $(if $(VERBOSE:1=),@)+$(MAKE) -C $(BUILD_OUTPUT) \ | 89 | $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \ |
64 | BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1 | 90 | BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1 |
65 | endef | 91 | endef |
66 | 92 | ||
67 | saved-output := $(BUILD_OUTPUT) | ||
68 | BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd) | ||
69 | $(if $(BUILD_OUTPUT),, \ | ||
70 | $(error output directory "$(saved-output)" does not exist)) | ||
71 | |||
72 | all: sub-make | 93 | all: sub-make |
73 | 94 | ||
74 | $(MAKECMDGOALS): sub-make | 95 | $(MAKECMDGOALS): sub-make |
@@ -80,7 +101,7 @@ sub-make: force | |||
80 | # Leave processing to above invocation of make | 101 | # Leave processing to above invocation of make |
81 | skip-makefile := 1 | 102 | skip-makefile := 1 |
82 | 103 | ||
83 | endif # BUILD_OUTPUT | 104 | endif # OUTPUT |
84 | endif # BUILD_SRC | 105 | endif # BUILD_SRC |
85 | 106 | ||
86 | # We process the rest of the Makefile if this is the final invocation of make | 107 | # We process the rest of the Makefile if this is the final invocation of make |
@@ -96,6 +117,7 @@ export prefix bindir src obj | |||
96 | # Shell quotes | 117 | # Shell quotes |
97 | bindir_SQ = $(subst ','\'',$(bindir)) | 118 | bindir_SQ = $(subst ','\'',$(bindir)) |
98 | bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) | 119 | bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) |
120 | plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) | ||
99 | 121 | ||
100 | LIB_FILE = libtraceevent.a libtraceevent.so | 122 | LIB_FILE = libtraceevent.a libtraceevent.so |
101 | 123 | ||
@@ -114,7 +136,7 @@ export Q VERBOSE | |||
114 | 136 | ||
115 | EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) | 137 | EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) |
116 | 138 | ||
117 | INCLUDES = -I. $(CONFIG_INCLUDES) | 139 | INCLUDES = -I. -I $(srctree)/../../include $(CONFIG_INCLUDES) |
118 | 140 | ||
119 | # Set compile option CFLAGS if not set elsewhere | 141 | # Set compile option CFLAGS if not set elsewhere |
120 | CFLAGS ?= -g -Wall | 142 | CFLAGS ?= -g -Wall |
@@ -125,41 +147,14 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE | |||
125 | 147 | ||
126 | ifeq ($(VERBOSE),1) | 148 | ifeq ($(VERBOSE),1) |
127 | Q = | 149 | Q = |
128 | print_compile = | ||
129 | print_app_build = | ||
130 | print_fpic_compile = | ||
131 | print_shared_lib_compile = | ||
132 | print_plugin_obj_compile = | ||
133 | print_plugin_build = | ||
134 | print_install = | ||
135 | else | 150 | else |
136 | Q = @ | 151 | Q = @ |
137 | print_compile = echo ' CC '$(OBJ); | ||
138 | print_app_build = echo ' BUILD '$(OBJ); | ||
139 | print_fpic_compile = echo ' CC FPIC '$(OBJ); | ||
140 | print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); | ||
141 | print_plugin_obj_compile = echo ' BUILD PLUGIN OBJ '$(OBJ); | ||
142 | print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); | ||
143 | print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); | ||
144 | print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; | ||
145 | endif | 152 | endif |
146 | 153 | ||
147 | do_fpic_compile = \ | ||
148 | ($(print_fpic_compile) \ | ||
149 | $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@) | ||
150 | |||
151 | do_app_build = \ | ||
152 | ($(print_app_build) \ | ||
153 | $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS)) | ||
154 | |||
155 | do_compile_shared_library = \ | 154 | do_compile_shared_library = \ |
156 | ($(print_shared_lib_compile) \ | 155 | ($(print_shared_lib_compile) \ |
157 | $(CC) --shared $^ -o $@) | 156 | $(CC) --shared $^ -o $@) |
158 | 157 | ||
159 | do_compile_plugin_obj = \ | ||
160 | ($(print_plugin_obj_compile) \ | ||
161 | $(CC) -c $(CFLAGS) -fPIC -o $@ $<) | ||
162 | |||
163 | do_plugin_build = \ | 158 | do_plugin_build = \ |
164 | ($(print_plugin_build) \ | 159 | ($(print_plugin_build) \ |
165 | $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<) | 160 | $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<) |
@@ -169,23 +164,37 @@ do_build_static_lib = \ | |||
169 | $(RM) $@; $(AR) rcs $@ $^) | 164 | $(RM) $@; $(AR) rcs $@ $^) |
170 | 165 | ||
171 | 166 | ||
172 | define do_compile | 167 | do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@; |
173 | $(print_compile) \ | ||
174 | $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@; | ||
175 | endef | ||
176 | 168 | ||
177 | $(obj)/%.o: $(src)/%.c | 169 | $(obj)/%.o: $(src)/%.c |
178 | $(Q)$(call do_compile) | 170 | $(call do_compile) |
179 | 171 | ||
180 | %.o: $(src)/%.c | 172 | %.o: $(src)/%.c |
181 | $(Q)$(call do_compile) | 173 | $(call do_compile) |
182 | 174 | ||
183 | PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o | 175 | PEVENT_LIB_OBJS = event-parse.o |
176 | PEVENT_LIB_OBJS += event-plugin.o | ||
177 | PEVENT_LIB_OBJS += trace-seq.o | ||
178 | PEVENT_LIB_OBJS += parse-filter.o | ||
179 | PEVENT_LIB_OBJS += parse-utils.o | ||
184 | PEVENT_LIB_OBJS += kbuffer-parse.o | 180 | PEVENT_LIB_OBJS += kbuffer-parse.o |
185 | 181 | ||
186 | ALL_OBJS = $(PEVENT_LIB_OBJS) | 182 | PLUGIN_OBJS = plugin_jbd2.o |
183 | PLUGIN_OBJS += plugin_hrtimer.o | ||
184 | PLUGIN_OBJS += plugin_kmem.o | ||
185 | PLUGIN_OBJS += plugin_kvm.o | ||
186 | PLUGIN_OBJS += plugin_mac80211.o | ||
187 | PLUGIN_OBJS += plugin_sched_switch.o | ||
188 | PLUGIN_OBJS += plugin_function.o | ||
189 | PLUGIN_OBJS += plugin_xen.o | ||
190 | PLUGIN_OBJS += plugin_scsi.o | ||
191 | PLUGIN_OBJS += plugin_cfg80211.o | ||
192 | |||
193 | PLUGINS := $(PLUGIN_OBJS:.o=.so) | ||
194 | |||
195 | ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS) | ||
187 | 196 | ||
188 | CMD_TARGETS = $(LIB_FILE) | 197 | CMD_TARGETS = $(LIB_FILE) $(PLUGINS) |
189 | 198 | ||
190 | TARGETS = $(CMD_TARGETS) | 199 | TARGETS = $(CMD_TARGETS) |
191 | 200 | ||
@@ -195,32 +204,40 @@ all: all_cmd | |||
195 | all_cmd: $(CMD_TARGETS) | 204 | all_cmd: $(CMD_TARGETS) |
196 | 205 | ||
197 | libtraceevent.so: $(PEVENT_LIB_OBJS) | 206 | libtraceevent.so: $(PEVENT_LIB_OBJS) |
198 | $(Q)$(do_compile_shared_library) | 207 | $(QUIET_LINK)$(CC) --shared $^ -o $@ |
199 | 208 | ||
200 | libtraceevent.a: $(PEVENT_LIB_OBJS) | 209 | libtraceevent.a: $(PEVENT_LIB_OBJS) |
201 | $(Q)$(do_build_static_lib) | 210 | $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ |
211 | |||
212 | plugins: $(PLUGINS) | ||
202 | 213 | ||
203 | $(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS | 214 | $(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS |
204 | $(Q)$(do_fpic_compile) | 215 | $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@ |
216 | |||
217 | $(PLUGIN_OBJS): %.o : $(src)/%.c | ||
218 | $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< | ||
219 | |||
220 | $(PLUGINS): %.so: %.o | ||
221 | $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< | ||
205 | 222 | ||
206 | define make_version.h | 223 | define make_version.h |
207 | (echo '/* This file is automatically generated. Do not modify. */'; \ | 224 | (echo '/* This file is automatically generated. Do not modify. */'; \ |
208 | echo \#define VERSION_CODE $(shell \ | 225 | echo \#define VERSION_CODE $(shell \ |
209 | expr $(VERSION) \* 256 + $(PATCHLEVEL)); \ | 226 | expr $(VERSION) \* 256 + $(PATCHLEVEL)); \ |
210 | echo '#define EXTRAVERSION ' $(EXTRAVERSION); \ | 227 | echo '#define EXTRAVERSION ' $(EXTRAVERSION); \ |
211 | echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \ | 228 | echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \ |
212 | echo '#define FILE_VERSION '$(FILE_VERSION); \ | 229 | echo '#define FILE_VERSION '$(FILE_VERSION); \ |
213 | ) > $1 | 230 | ) > $1 |
214 | endef | 231 | endef |
215 | 232 | ||
216 | define update_version.h | 233 | define update_version.h |
217 | ($(call make_version.h, $@.tmp); \ | 234 | ($(call make_version.h, $@.tmp); \ |
218 | if [ -r $@ ] && cmp -s $@ $@.tmp; then \ | 235 | if [ -r $@ ] && cmp -s $@ $@.tmp; then \ |
219 | rm -f $@.tmp; \ | 236 | rm -f $@.tmp; \ |
220 | else \ | 237 | else \ |
221 | echo ' UPDATE $@'; \ | 238 | echo ' UPDATE $@'; \ |
222 | mv -f $@.tmp $@; \ | 239 | mv -f $@.tmp $@; \ |
223 | fi); | 240 | fi); |
224 | endef | 241 | endef |
225 | 242 | ||
226 | ep_version.h: force | 243 | ep_version.h: force |
@@ -229,13 +246,13 @@ ep_version.h: force | |||
229 | VERSION_FILES = ep_version.h | 246 | VERSION_FILES = ep_version.h |
230 | 247 | ||
231 | define update_dir | 248 | define update_dir |
232 | (echo $1 > $@.tmp; \ | 249 | (echo $1 > $@.tmp; \ |
233 | if [ -r $@ ] && cmp -s $@ $@.tmp; then \ | 250 | if [ -r $@ ] && cmp -s $@ $@.tmp; then \ |
234 | rm -f $@.tmp; \ | 251 | rm -f $@.tmp; \ |
235 | else \ | 252 | else \ |
236 | echo ' UPDATE $@'; \ | 253 | echo ' UPDATE $@'; \ |
237 | mv -f $@.tmp $@; \ | 254 | mv -f $@.tmp $@; \ |
238 | fi); | 255 | fi); |
239 | endef | 256 | endef |
240 | 257 | ||
241 | ## make deps | 258 | ## make deps |
@@ -245,10 +262,10 @@ all_deps := $(all_objs:%.o=.%.d) | |||
245 | 262 | ||
246 | # let .d file also depends on the source and header files | 263 | # let .d file also depends on the source and header files |
247 | define check_deps | 264 | define check_deps |
248 | @set -e; $(RM) $@; \ | 265 | @set -e; $(RM) $@; \ |
249 | $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ | 266 | $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ |
250 | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ | 267 | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ |
251 | $(RM) $@.$$$$ | 268 | $(RM) $@.$$$$ |
252 | endef | 269 | endef |
253 | 270 | ||
254 | $(all_deps): .%.d: $(src)/%.c | 271 | $(all_deps): .%.d: $(src)/%.c |
@@ -283,27 +300,41 @@ TAGS: force | |||
283 | --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' | 300 | --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' |
284 | 301 | ||
285 | define do_install | 302 | define do_install |
286 | $(print_install) \ | ||
287 | if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ | 303 | if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ |
288 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ | 304 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ |
289 | fi; \ | 305 | fi; \ |
290 | $(INSTALL) $1 '$(DESTDIR_SQ)$2' | 306 | $(INSTALL) $1 '$(DESTDIR_SQ)$2' |
291 | endef | 307 | endef |
292 | 308 | ||
293 | install_lib: all_cmd | 309 | define do_install_plugins |
294 | $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ)) | 310 | for plugin in $1; do \ |
311 | $(call do_install,$$plugin,$(plugin_dir_SQ)); \ | ||
312 | done | ||
313 | endef | ||
314 | |||
315 | install_lib: all_cmd install_plugins | ||
316 | $(call QUIET_INSTALL, $(LIB_FILE)) \ | ||
317 | $(call do_install,$(LIB_FILE),$(bindir_SQ)) | ||
318 | |||
319 | install_plugins: $(PLUGINS) | ||
320 | $(call QUIET_INSTALL, trace_plugins) \ | ||
321 | $(call do_install_plugins, $(PLUGINS)) | ||
295 | 322 | ||
296 | install: install_lib | 323 | install: install_lib |
297 | 324 | ||
298 | clean: | 325 | clean: |
299 | $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d | 326 | $(call QUIET_CLEAN, libtraceevent) \ |
300 | $(RM) TRACEEVENT-CFLAGS tags TAGS | 327 | $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ |
328 | $(RM) TRACEEVENT-CFLAGS tags TAGS | ||
301 | 329 | ||
302 | endif # skip-makefile | 330 | endif # skip-makefile |
303 | 331 | ||
304 | PHONY += force | 332 | PHONY += force plugins |
305 | force: | 333 | force: |
306 | 334 | ||
335 | plugins: | ||
336 | @echo > /dev/null | ||
337 | |||
307 | # Declare the contents of the .PHONY variable as phony. We keep that | 338 | # Declare the contents of the .PHONY variable as phony. We keep that |
308 | # information in a variable so we can use it in if_changed and friends. | 339 | # information in a variable so we can use it in if_changed and friends. |
309 | .PHONY: $(PHONY) | 340 | .PHONY: $(PHONY) |
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 217c82ee3665..1587ea392ad6 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -2710,7 +2710,6 @@ process_func_handler(struct event_format *event, struct pevent_function_handler | |||
2710 | struct print_arg *farg; | 2710 | struct print_arg *farg; |
2711 | enum event_type type; | 2711 | enum event_type type; |
2712 | char *token; | 2712 | char *token; |
2713 | const char *test; | ||
2714 | int i; | 2713 | int i; |
2715 | 2714 | ||
2716 | arg->type = PRINT_FUNC; | 2715 | arg->type = PRINT_FUNC; |
@@ -2727,15 +2726,19 @@ process_func_handler(struct event_format *event, struct pevent_function_handler | |||
2727 | } | 2726 | } |
2728 | 2727 | ||
2729 | type = process_arg(event, farg, &token); | 2728 | type = process_arg(event, farg, &token); |
2730 | if (i < (func->nr_args - 1)) | 2729 | if (i < (func->nr_args - 1)) { |
2731 | test = ","; | 2730 | if (type != EVENT_DELIM || strcmp(token, ",") != 0) { |
2732 | else | 2731 | warning("Error: function '%s()' expects %d arguments but event %s only uses %d", |
2733 | test = ")"; | 2732 | func->name, func->nr_args, |
2734 | 2733 | event->name, i + 1); | |
2735 | if (test_type_token(type, token, EVENT_DELIM, test)) { | 2734 | goto err; |
2736 | free_arg(farg); | 2735 | } |
2737 | free_token(token); | 2736 | } else { |
2738 | return EVENT_ERROR; | 2737 | if (type != EVENT_DELIM || strcmp(token, ")") != 0) { |
2738 | warning("Error: function '%s()' only expects %d arguments but event %s has more", | ||
2739 | func->name, func->nr_args, event->name); | ||
2740 | goto err; | ||
2741 | } | ||
2739 | } | 2742 | } |
2740 | 2743 | ||
2741 | *next_arg = farg; | 2744 | *next_arg = farg; |
@@ -2747,6 +2750,11 @@ process_func_handler(struct event_format *event, struct pevent_function_handler | |||
2747 | *tok = token; | 2750 | *tok = token; |
2748 | 2751 | ||
2749 | return type; | 2752 | return type; |
2753 | |||
2754 | err: | ||
2755 | free_arg(farg); | ||
2756 | free_token(token); | ||
2757 | return EVENT_ERROR; | ||
2750 | } | 2758 | } |
2751 | 2759 | ||
2752 | static enum event_type | 2760 | static enum event_type |
@@ -4099,6 +4107,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
4099 | unsigned long long val; | 4107 | unsigned long long val; |
4100 | struct func_map *func; | 4108 | struct func_map *func; |
4101 | const char *saveptr; | 4109 | const char *saveptr; |
4110 | struct trace_seq p; | ||
4102 | char *bprint_fmt = NULL; | 4111 | char *bprint_fmt = NULL; |
4103 | char format[32]; | 4112 | char format[32]; |
4104 | int show_func; | 4113 | int show_func; |
@@ -4306,8 +4315,12 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
4306 | format[len] = 0; | 4315 | format[len] = 0; |
4307 | if (!len_as_arg) | 4316 | if (!len_as_arg) |
4308 | len_arg = -1; | 4317 | len_arg = -1; |
4309 | print_str_arg(s, data, size, event, | 4318 | /* Use helper trace_seq */ |
4319 | trace_seq_init(&p); | ||
4320 | print_str_arg(&p, data, size, event, | ||
4310 | format, len_arg, arg); | 4321 | format, len_arg, arg); |
4322 | trace_seq_terminate(&p); | ||
4323 | trace_seq_puts(s, p.buffer); | ||
4311 | arg = arg->next; | 4324 | arg = arg->next; |
4312 | break; | 4325 | break; |
4313 | default: | 4326 | default: |
@@ -5116,8 +5129,38 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp, | |||
5116 | return ret; | 5129 | return ret; |
5117 | } | 5130 | } |
5118 | 5131 | ||
5132 | static enum pevent_errno | ||
5133 | __pevent_parse_event(struct pevent *pevent, | ||
5134 | struct event_format **eventp, | ||
5135 | const char *buf, unsigned long size, | ||
5136 | const char *sys) | ||
5137 | { | ||
5138 | int ret = __pevent_parse_format(eventp, pevent, buf, size, sys); | ||
5139 | struct event_format *event = *eventp; | ||
5140 | |||
5141 | if (event == NULL) | ||
5142 | return ret; | ||
5143 | |||
5144 | if (pevent && add_event(pevent, event)) { | ||
5145 | ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
5146 | goto event_add_failed; | ||
5147 | } | ||
5148 | |||
5149 | #define PRINT_ARGS 0 | ||
5150 | if (PRINT_ARGS && event->print_fmt.args) | ||
5151 | print_args(event->print_fmt.args); | ||
5152 | |||
5153 | return 0; | ||
5154 | |||
5155 | event_add_failed: | ||
5156 | pevent_free_format(event); | ||
5157 | return ret; | ||
5158 | } | ||
5159 | |||
5119 | /** | 5160 | /** |
5120 | * pevent_parse_format - parse the event format | 5161 | * pevent_parse_format - parse the event format |
5162 | * @pevent: the handle to the pevent | ||
5163 | * @eventp: returned format | ||
5121 | * @buf: the buffer storing the event format string | 5164 | * @buf: the buffer storing the event format string |
5122 | * @size: the size of @buf | 5165 | * @size: the size of @buf |
5123 | * @sys: the system the event belongs to | 5166 | * @sys: the system the event belongs to |
@@ -5129,10 +5172,12 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp, | |||
5129 | * | 5172 | * |
5130 | * /sys/kernel/debug/tracing/events/.../.../format | 5173 | * /sys/kernel/debug/tracing/events/.../.../format |
5131 | */ | 5174 | */ |
5132 | enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, | 5175 | enum pevent_errno pevent_parse_format(struct pevent *pevent, |
5176 | struct event_format **eventp, | ||
5177 | const char *buf, | ||
5133 | unsigned long size, const char *sys) | 5178 | unsigned long size, const char *sys) |
5134 | { | 5179 | { |
5135 | return __pevent_parse_format(eventp, NULL, buf, size, sys); | 5180 | return __pevent_parse_event(pevent, eventp, buf, size, sys); |
5136 | } | 5181 | } |
5137 | 5182 | ||
5138 | /** | 5183 | /** |
@@ -5153,25 +5198,7 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, | |||
5153 | unsigned long size, const char *sys) | 5198 | unsigned long size, const char *sys) |
5154 | { | 5199 | { |
5155 | struct event_format *event = NULL; | 5200 | struct event_format *event = NULL; |
5156 | int ret = __pevent_parse_format(&event, pevent, buf, size, sys); | 5201 | return __pevent_parse_event(pevent, &event, buf, size, sys); |
5157 | |||
5158 | if (event == NULL) | ||
5159 | return ret; | ||
5160 | |||
5161 | if (add_event(pevent, event)) { | ||
5162 | ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
5163 | goto event_add_failed; | ||
5164 | } | ||
5165 | |||
5166 | #define PRINT_ARGS 0 | ||
5167 | if (PRINT_ARGS && event->print_fmt.args) | ||
5168 | print_args(event->print_fmt.args); | ||
5169 | |||
5170 | return 0; | ||
5171 | |||
5172 | event_add_failed: | ||
5173 | pevent_free_format(event); | ||
5174 | return ret; | ||
5175 | } | 5202 | } |
5176 | 5203 | ||
5177 | #undef _PE | 5204 | #undef _PE |
@@ -5203,22 +5230,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused, | |||
5203 | 5230 | ||
5204 | idx = errnum - __PEVENT_ERRNO__START - 1; | 5231 | idx = errnum - __PEVENT_ERRNO__START - 1; |
5205 | msg = pevent_error_str[idx]; | 5232 | msg = pevent_error_str[idx]; |
5206 | 5233 | snprintf(buf, buflen, "%s", msg); | |
5207 | switch (errnum) { | ||
5208 | case PEVENT_ERRNO__MEM_ALLOC_FAILED: | ||
5209 | case PEVENT_ERRNO__PARSE_EVENT_FAILED: | ||
5210 | case PEVENT_ERRNO__READ_ID_FAILED: | ||
5211 | case PEVENT_ERRNO__READ_FORMAT_FAILED: | ||
5212 | case PEVENT_ERRNO__READ_PRINT_FAILED: | ||
5213 | case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED: | ||
5214 | case PEVENT_ERRNO__INVALID_ARG_TYPE: | ||
5215 | snprintf(buf, buflen, "%s", msg); | ||
5216 | break; | ||
5217 | |||
5218 | default: | ||
5219 | /* cannot reach here */ | ||
5220 | break; | ||
5221 | } | ||
5222 | 5234 | ||
5223 | return 0; | 5235 | return 0; |
5224 | } | 5236 | } |
@@ -5549,6 +5561,52 @@ int pevent_register_print_function(struct pevent *pevent, | |||
5549 | } | 5561 | } |
5550 | 5562 | ||
5551 | /** | 5563 | /** |
5564 | * pevent_unregister_print_function - unregister a helper function | ||
5565 | * @pevent: the handle to the pevent | ||
5566 | * @func: the function to process the helper function | ||
5567 | * @name: the name of the helper function | ||
5568 | * | ||
5569 | * This function removes existing print handler for function @name. | ||
5570 | * | ||
5571 | * Returns 0 if the handler was removed successully, -1 otherwise. | ||
5572 | */ | ||
5573 | int pevent_unregister_print_function(struct pevent *pevent, | ||
5574 | pevent_func_handler func, char *name) | ||
5575 | { | ||
5576 | struct pevent_function_handler *func_handle; | ||
5577 | |||
5578 | func_handle = find_func_handler(pevent, name); | ||
5579 | if (func_handle && func_handle->func == func) { | ||
5580 | remove_func_handler(pevent, name); | ||
5581 | return 0; | ||
5582 | } | ||
5583 | return -1; | ||
5584 | } | ||
5585 | |||
5586 | static struct event_format *pevent_search_event(struct pevent *pevent, int id, | ||
5587 | const char *sys_name, | ||
5588 | const char *event_name) | ||
5589 | { | ||
5590 | struct event_format *event; | ||
5591 | |||
5592 | if (id >= 0) { | ||
5593 | /* search by id */ | ||
5594 | event = pevent_find_event(pevent, id); | ||
5595 | if (!event) | ||
5596 | return NULL; | ||
5597 | if (event_name && (strcmp(event_name, event->name) != 0)) | ||
5598 | return NULL; | ||
5599 | if (sys_name && (strcmp(sys_name, event->system) != 0)) | ||
5600 | return NULL; | ||
5601 | } else { | ||
5602 | event = pevent_find_event_by_name(pevent, sys_name, event_name); | ||
5603 | if (!event) | ||
5604 | return NULL; | ||
5605 | } | ||
5606 | return event; | ||
5607 | } | ||
5608 | |||
5609 | /** | ||
5552 | * pevent_register_event_handler - register a way to parse an event | 5610 | * pevent_register_event_handler - register a way to parse an event |
5553 | * @pevent: the handle to the pevent | 5611 | * @pevent: the handle to the pevent |
5554 | * @id: the id of the event to register | 5612 | * @id: the id of the event to register |
@@ -5572,20 +5630,9 @@ int pevent_register_event_handler(struct pevent *pevent, int id, | |||
5572 | struct event_format *event; | 5630 | struct event_format *event; |
5573 | struct event_handler *handle; | 5631 | struct event_handler *handle; |
5574 | 5632 | ||
5575 | if (id >= 0) { | 5633 | event = pevent_search_event(pevent, id, sys_name, event_name); |
5576 | /* search by id */ | 5634 | if (event == NULL) |
5577 | event = pevent_find_event(pevent, id); | 5635 | goto not_found; |
5578 | if (!event) | ||
5579 | goto not_found; | ||
5580 | if (event_name && (strcmp(event_name, event->name) != 0)) | ||
5581 | goto not_found; | ||
5582 | if (sys_name && (strcmp(sys_name, event->system) != 0)) | ||
5583 | goto not_found; | ||
5584 | } else { | ||
5585 | event = pevent_find_event_by_name(pevent, sys_name, event_name); | ||
5586 | if (!event) | ||
5587 | goto not_found; | ||
5588 | } | ||
5589 | 5636 | ||
5590 | pr_stat("overriding event (%d) %s:%s with new print handler", | 5637 | pr_stat("overriding event (%d) %s:%s with new print handler", |
5591 | event->id, event->system, event->name); | 5638 | event->id, event->system, event->name); |
@@ -5625,6 +5672,79 @@ int pevent_register_event_handler(struct pevent *pevent, int id, | |||
5625 | return -1; | 5672 | return -1; |
5626 | } | 5673 | } |
5627 | 5674 | ||
5675 | static int handle_matches(struct event_handler *handler, int id, | ||
5676 | const char *sys_name, const char *event_name, | ||
5677 | pevent_event_handler_func func, void *context) | ||
5678 | { | ||
5679 | if (id >= 0 && id != handler->id) | ||
5680 | return 0; | ||
5681 | |||
5682 | if (event_name && (strcmp(event_name, handler->event_name) != 0)) | ||
5683 | return 0; | ||
5684 | |||
5685 | if (sys_name && (strcmp(sys_name, handler->sys_name) != 0)) | ||
5686 | return 0; | ||
5687 | |||
5688 | if (func != handler->func || context != handler->context) | ||
5689 | return 0; | ||
5690 | |||
5691 | return 1; | ||
5692 | } | ||
5693 | |||
5694 | /** | ||
5695 | * pevent_unregister_event_handler - unregister an existing event handler | ||
5696 | * @pevent: the handle to the pevent | ||
5697 | * @id: the id of the event to unregister | ||
5698 | * @sys_name: the system name the handler belongs to | ||
5699 | * @event_name: the name of the event handler | ||
5700 | * @func: the function to call to parse the event information | ||
5701 | * @context: the data to be passed to @func | ||
5702 | * | ||
5703 | * This function removes existing event handler (parser). | ||
5704 | * | ||
5705 | * If @id is >= 0, then it is used to find the event. | ||
5706 | * else @sys_name and @event_name are used. | ||
5707 | * | ||
5708 | * Returns 0 if handler was removed successfully, -1 if event was not found. | ||
5709 | */ | ||
5710 | int pevent_unregister_event_handler(struct pevent *pevent, int id, | ||
5711 | const char *sys_name, const char *event_name, | ||
5712 | pevent_event_handler_func func, void *context) | ||
5713 | { | ||
5714 | struct event_format *event; | ||
5715 | struct event_handler *handle; | ||
5716 | struct event_handler **next; | ||
5717 | |||
5718 | event = pevent_search_event(pevent, id, sys_name, event_name); | ||
5719 | if (event == NULL) | ||
5720 | goto not_found; | ||
5721 | |||
5722 | if (event->handler == func && event->context == context) { | ||
5723 | pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.", | ||
5724 | event->id, event->system, event->name); | ||
5725 | |||
5726 | event->handler = NULL; | ||
5727 | event->context = NULL; | ||
5728 | return 0; | ||
5729 | } | ||
5730 | |||
5731 | not_found: | ||
5732 | for (next = &pevent->handlers; *next; next = &(*next)->next) { | ||
5733 | handle = *next; | ||
5734 | if (handle_matches(handle, id, sys_name, event_name, | ||
5735 | func, context)) | ||
5736 | break; | ||
5737 | } | ||
5738 | |||
5739 | if (!(*next)) | ||
5740 | return -1; | ||
5741 | |||
5742 | *next = handle->next; | ||
5743 | free_handler(handle); | ||
5744 | |||
5745 | return 0; | ||
5746 | } | ||
5747 | |||
5628 | /** | 5748 | /** |
5629 | * pevent_alloc - create a pevent handle | 5749 | * pevent_alloc - create a pevent handle |
5630 | */ | 5750 | */ |
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 8d73d2594f65..791c539374c7 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <stdbool.h> | 23 | #include <stdbool.h> |
24 | #include <stdarg.h> | 24 | #include <stdarg.h> |
25 | #include <regex.h> | 25 | #include <regex.h> |
26 | #include <string.h> | ||
26 | 27 | ||
27 | #ifndef __maybe_unused | 28 | #ifndef __maybe_unused |
28 | #define __maybe_unused __attribute__((unused)) | 29 | #define __maybe_unused __attribute__((unused)) |
@@ -57,6 +58,12 @@ struct pevent_record { | |||
57 | #endif | 58 | #endif |
58 | }; | 59 | }; |
59 | 60 | ||
61 | enum trace_seq_fail { | ||
62 | TRACE_SEQ__GOOD, | ||
63 | TRACE_SEQ__BUFFER_POISONED, | ||
64 | TRACE_SEQ__MEM_ALLOC_FAILED, | ||
65 | }; | ||
66 | |||
60 | /* | 67 | /* |
61 | * Trace sequences are used to allow a function to call several other functions | 68 | * Trace sequences are used to allow a function to call several other functions |
62 | * to create a string of data to use (up to a max of PAGE_SIZE). | 69 | * to create a string of data to use (up to a max of PAGE_SIZE). |
@@ -67,6 +74,7 @@ struct trace_seq { | |||
67 | unsigned int buffer_size; | 74 | unsigned int buffer_size; |
68 | unsigned int len; | 75 | unsigned int len; |
69 | unsigned int readpos; | 76 | unsigned int readpos; |
77 | enum trace_seq_fail state; | ||
70 | }; | 78 | }; |
71 | 79 | ||
72 | void trace_seq_init(struct trace_seq *s); | 80 | void trace_seq_init(struct trace_seq *s); |
@@ -97,7 +105,7 @@ typedef int (*pevent_event_handler_func)(struct trace_seq *s, | |||
97 | void *context); | 105 | void *context); |
98 | 106 | ||
99 | typedef int (*pevent_plugin_load_func)(struct pevent *pevent); | 107 | typedef int (*pevent_plugin_load_func)(struct pevent *pevent); |
100 | typedef int (*pevent_plugin_unload_func)(void); | 108 | typedef int (*pevent_plugin_unload_func)(struct pevent *pevent); |
101 | 109 | ||
102 | struct plugin_option { | 110 | struct plugin_option { |
103 | struct plugin_option *next; | 111 | struct plugin_option *next; |
@@ -122,7 +130,7 @@ struct plugin_option { | |||
122 | * PEVENT_PLUGIN_UNLOADER: (optional) | 130 | * PEVENT_PLUGIN_UNLOADER: (optional) |
123 | * The function called just before unloading | 131 | * The function called just before unloading |
124 | * | 132 | * |
125 | * int PEVENT_PLUGIN_UNLOADER(void) | 133 | * int PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) |
126 | * | 134 | * |
127 | * PEVENT_PLUGIN_OPTIONS: (optional) | 135 | * PEVENT_PLUGIN_OPTIONS: (optional) |
128 | * Plugin options that can be set before loading | 136 | * Plugin options that can be set before loading |
@@ -355,12 +363,35 @@ enum pevent_flag { | |||
355 | _PE(READ_FORMAT_FAILED, "failed to read event format"), \ | 363 | _PE(READ_FORMAT_FAILED, "failed to read event format"), \ |
356 | _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ | 364 | _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ |
357 | _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ | 365 | _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ |
358 | _PE(INVALID_ARG_TYPE, "invalid argument type") | 366 | _PE(INVALID_ARG_TYPE, "invalid argument type"), \ |
367 | _PE(INVALID_EXP_TYPE, "invalid expression type"), \ | ||
368 | _PE(INVALID_OP_TYPE, "invalid operator type"), \ | ||
369 | _PE(INVALID_EVENT_NAME, "invalid event name"), \ | ||
370 | _PE(EVENT_NOT_FOUND, "no event found"), \ | ||
371 | _PE(SYNTAX_ERROR, "syntax error"), \ | ||
372 | _PE(ILLEGAL_RVALUE, "illegal rvalue"), \ | ||
373 | _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \ | ||
374 | _PE(INVALID_REGEX, "regex did not compute"), \ | ||
375 | _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \ | ||
376 | _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), \ | ||
377 | _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \ | ||
378 | _PE(REPARENT_FAILED, "failed to reparent filter OP"), \ | ||
379 | _PE(BAD_FILTER_ARG, "bad arg in filter tree"), \ | ||
380 | _PE(UNEXPECTED_TYPE, "unexpected type (not a value)"), \ | ||
381 | _PE(ILLEGAL_TOKEN, "illegal token"), \ | ||
382 | _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ | ||
383 | _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ | ||
384 | _PE(UNKNOWN_TOKEN, "unknown token"), \ | ||
385 | _PE(FILTER_NOT_FOUND, "no filter found"), \ | ||
386 | _PE(NOT_A_NUMBER, "must have number field"), \ | ||
387 | _PE(NO_FILTER, "no filters exists"), \ | ||
388 | _PE(FILTER_MISS, "record does not match to filter") | ||
359 | 389 | ||
360 | #undef _PE | 390 | #undef _PE |
361 | #define _PE(__code, __str) PEVENT_ERRNO__ ## __code | 391 | #define _PE(__code, __str) PEVENT_ERRNO__ ## __code |
362 | enum pevent_errno { | 392 | enum pevent_errno { |
363 | PEVENT_ERRNO__SUCCESS = 0, | 393 | PEVENT_ERRNO__SUCCESS = 0, |
394 | PEVENT_ERRNO__FILTER_MATCH = PEVENT_ERRNO__SUCCESS, | ||
364 | 395 | ||
365 | /* | 396 | /* |
366 | * Choose an arbitrary negative big number not to clash with standard | 397 | * Choose an arbitrary negative big number not to clash with standard |
@@ -377,6 +408,12 @@ enum pevent_errno { | |||
377 | }; | 408 | }; |
378 | #undef _PE | 409 | #undef _PE |
379 | 410 | ||
411 | struct plugin_list; | ||
412 | |||
413 | struct plugin_list *traceevent_load_plugins(struct pevent *pevent); | ||
414 | void traceevent_unload_plugins(struct plugin_list *plugin_list, | ||
415 | struct pevent *pevent); | ||
416 | |||
380 | struct cmdline; | 417 | struct cmdline; |
381 | struct cmdline_list; | 418 | struct cmdline_list; |
382 | struct func_map; | 419 | struct func_map; |
@@ -522,6 +559,15 @@ __data2host8(struct pevent *pevent, unsigned long long data) | |||
522 | __data2host8(pevent, __val); \ | 559 | __data2host8(pevent, __val); \ |
523 | }) | 560 | }) |
524 | 561 | ||
562 | static inline int traceevent_host_bigendian(void) | ||
563 | { | ||
564 | unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 }; | ||
565 | unsigned int val; | ||
566 | |||
567 | memcpy(&val, str, 4); | ||
568 | return val == 0x01020304; | ||
569 | } | ||
570 | |||
525 | /* taken from kernel/trace/trace.h */ | 571 | /* taken from kernel/trace/trace.h */ |
526 | enum trace_flag_type { | 572 | enum trace_flag_type { |
527 | TRACE_FLAG_IRQS_OFF = 0x01, | 573 | TRACE_FLAG_IRQS_OFF = 0x01, |
@@ -547,7 +593,9 @@ int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long siz | |||
547 | 593 | ||
548 | enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, | 594 | enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, |
549 | unsigned long size, const char *sys); | 595 | unsigned long size, const char *sys); |
550 | enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, | 596 | enum pevent_errno pevent_parse_format(struct pevent *pevent, |
597 | struct event_format **eventp, | ||
598 | const char *buf, | ||
551 | unsigned long size, const char *sys); | 599 | unsigned long size, const char *sys); |
552 | void pevent_free_format(struct event_format *event); | 600 | void pevent_free_format(struct event_format *event); |
553 | 601 | ||
@@ -576,10 +624,15 @@ int pevent_print_func_field(struct trace_seq *s, const char *fmt, | |||
576 | int pevent_register_event_handler(struct pevent *pevent, int id, | 624 | int pevent_register_event_handler(struct pevent *pevent, int id, |
577 | const char *sys_name, const char *event_name, | 625 | const char *sys_name, const char *event_name, |
578 | pevent_event_handler_func func, void *context); | 626 | pevent_event_handler_func func, void *context); |
627 | int pevent_unregister_event_handler(struct pevent *pevent, int id, | ||
628 | const char *sys_name, const char *event_name, | ||
629 | pevent_event_handler_func func, void *context); | ||
579 | int pevent_register_print_function(struct pevent *pevent, | 630 | int pevent_register_print_function(struct pevent *pevent, |
580 | pevent_func_handler func, | 631 | pevent_func_handler func, |
581 | enum pevent_func_arg_type ret_type, | 632 | enum pevent_func_arg_type ret_type, |
582 | char *name, ...); | 633 | char *name, ...); |
634 | int pevent_unregister_print_function(struct pevent *pevent, | ||
635 | pevent_func_handler func, char *name); | ||
583 | 636 | ||
584 | struct format_field *pevent_find_common_field(struct event_format *event, const char *name); | 637 | struct format_field *pevent_find_common_field(struct event_format *event, const char *name); |
585 | struct format_field *pevent_find_field(struct event_format *event, const char *name); | 638 | struct format_field *pevent_find_field(struct event_format *event, const char *name); |
@@ -811,18 +864,22 @@ struct filter_type { | |||
811 | struct filter_arg *filter; | 864 | struct filter_arg *filter; |
812 | }; | 865 | }; |
813 | 866 | ||
867 | #define PEVENT_FILTER_ERROR_BUFSZ 1024 | ||
868 | |||
814 | struct event_filter { | 869 | struct event_filter { |
815 | struct pevent *pevent; | 870 | struct pevent *pevent; |
816 | int filters; | 871 | int filters; |
817 | struct filter_type *event_filters; | 872 | struct filter_type *event_filters; |
873 | char error_buffer[PEVENT_FILTER_ERROR_BUFSZ]; | ||
818 | }; | 874 | }; |
819 | 875 | ||
820 | struct event_filter *pevent_filter_alloc(struct pevent *pevent); | 876 | struct event_filter *pevent_filter_alloc(struct pevent *pevent); |
821 | 877 | ||
822 | #define FILTER_NONE -2 | 878 | /* for backward compatibility */ |
823 | #define FILTER_NOEXIST -1 | 879 | #define FILTER_NONE PEVENT_ERRNO__FILTER_NOT_FOUND |
824 | #define FILTER_MISS 0 | 880 | #define FILTER_NOEXIST PEVENT_ERRNO__NO_FILTER |
825 | #define FILTER_MATCH 1 | 881 | #define FILTER_MISS PEVENT_ERRNO__FILTER_MISS |
882 | #define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH | ||
826 | 883 | ||
827 | enum filter_trivial_type { | 884 | enum filter_trivial_type { |
828 | FILTER_TRIVIAL_FALSE, | 885 | FILTER_TRIVIAL_FALSE, |
@@ -830,20 +887,21 @@ enum filter_trivial_type { | |||
830 | FILTER_TRIVIAL_BOTH, | 887 | FILTER_TRIVIAL_BOTH, |
831 | }; | 888 | }; |
832 | 889 | ||
833 | int pevent_filter_add_filter_str(struct event_filter *filter, | 890 | enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, |
834 | const char *filter_str, | 891 | const char *filter_str); |
835 | char **error_str); | ||
836 | 892 | ||
893 | enum pevent_errno pevent_filter_match(struct event_filter *filter, | ||
894 | struct pevent_record *record); | ||
837 | 895 | ||
838 | int pevent_filter_match(struct event_filter *filter, | 896 | int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err, |
839 | struct pevent_record *record); | 897 | char *buf, size_t buflen); |
840 | 898 | ||
841 | int pevent_event_filtered(struct event_filter *filter, | 899 | int pevent_event_filtered(struct event_filter *filter, |
842 | int event_id); | 900 | int event_id); |
843 | 901 | ||
844 | void pevent_filter_reset(struct event_filter *filter); | 902 | void pevent_filter_reset(struct event_filter *filter); |
845 | 903 | ||
846 | void pevent_filter_clear_trivial(struct event_filter *filter, | 904 | int pevent_filter_clear_trivial(struct event_filter *filter, |
847 | enum filter_trivial_type type); | 905 | enum filter_trivial_type type); |
848 | 906 | ||
849 | void pevent_filter_free(struct event_filter *filter); | 907 | void pevent_filter_free(struct event_filter *filter); |
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c new file mode 100644 index 000000000000..0c8bf6780e4d --- /dev/null +++ b/tools/lib/traceevent/event-plugin.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | ||
3 | * | ||
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * version 2.1 of the License (not later!) | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this program; if not, see <http://www.gnu.org/licenses> | ||
17 | * | ||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | */ | ||
20 | |||
21 | #include <string.h> | ||
22 | #include <dlfcn.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/stat.h> | ||
26 | #include <unistd.h> | ||
27 | #include <dirent.h> | ||
28 | #include "event-parse.h" | ||
29 | #include "event-utils.h" | ||
30 | |||
31 | #define LOCAL_PLUGIN_DIR ".traceevent/plugins" | ||
32 | |||
33 | struct plugin_list { | ||
34 | struct plugin_list *next; | ||
35 | char *name; | ||
36 | void *handle; | ||
37 | }; | ||
38 | |||
39 | static void | ||
40 | load_plugin(struct pevent *pevent, const char *path, | ||
41 | const char *file, void *data) | ||
42 | { | ||
43 | struct plugin_list **plugin_list = data; | ||
44 | pevent_plugin_load_func func; | ||
45 | struct plugin_list *list; | ||
46 | const char *alias; | ||
47 | char *plugin; | ||
48 | void *handle; | ||
49 | |||
50 | plugin = malloc(strlen(path) + strlen(file) + 2); | ||
51 | if (!plugin) { | ||
52 | warning("could not allocate plugin memory\n"); | ||
53 | return; | ||
54 | } | ||
55 | |||
56 | strcpy(plugin, path); | ||
57 | strcat(plugin, "/"); | ||
58 | strcat(plugin, file); | ||
59 | |||
60 | handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL); | ||
61 | if (!handle) { | ||
62 | warning("could not load plugin '%s'\n%s\n", | ||
63 | plugin, dlerror()); | ||
64 | goto out_free; | ||
65 | } | ||
66 | |||
67 | alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME); | ||
68 | if (!alias) | ||
69 | alias = file; | ||
70 | |||
71 | func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME); | ||
72 | if (!func) { | ||
73 | warning("could not find func '%s' in plugin '%s'\n%s\n", | ||
74 | PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror()); | ||
75 | goto out_free; | ||
76 | } | ||
77 | |||
78 | list = malloc(sizeof(*list)); | ||
79 | if (!list) { | ||
80 | warning("could not allocate plugin memory\n"); | ||
81 | goto out_free; | ||
82 | } | ||
83 | |||
84 | list->next = *plugin_list; | ||
85 | list->handle = handle; | ||
86 | list->name = plugin; | ||
87 | *plugin_list = list; | ||
88 | |||
89 | pr_stat("registering plugin: %s", plugin); | ||
90 | func(pevent); | ||
91 | return; | ||
92 | |||
93 | out_free: | ||
94 | free(plugin); | ||
95 | } | ||
96 | |||
97 | static void | ||
98 | load_plugins_dir(struct pevent *pevent, const char *suffix, | ||
99 | const char *path, | ||
100 | void (*load_plugin)(struct pevent *pevent, | ||
101 | const char *path, | ||
102 | const char *name, | ||
103 | void *data), | ||
104 | void *data) | ||
105 | { | ||
106 | struct dirent *dent; | ||
107 | struct stat st; | ||
108 | DIR *dir; | ||
109 | int ret; | ||
110 | |||
111 | ret = stat(path, &st); | ||
112 | if (ret < 0) | ||
113 | return; | ||
114 | |||
115 | if (!S_ISDIR(st.st_mode)) | ||
116 | return; | ||
117 | |||
118 | dir = opendir(path); | ||
119 | if (!dir) | ||
120 | return; | ||
121 | |||
122 | while ((dent = readdir(dir))) { | ||
123 | const char *name = dent->d_name; | ||
124 | |||
125 | if (strcmp(name, ".") == 0 || | ||
126 | strcmp(name, "..") == 0) | ||
127 | continue; | ||
128 | |||
129 | /* Only load plugins that end in suffix */ | ||
130 | if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0) | ||
131 | continue; | ||
132 | |||
133 | load_plugin(pevent, path, name, data); | ||
134 | } | ||
135 | |||
136 | closedir(dir); | ||
137 | } | ||
138 | |||
139 | static void | ||
140 | load_plugins(struct pevent *pevent, const char *suffix, | ||
141 | void (*load_plugin)(struct pevent *pevent, | ||
142 | const char *path, | ||
143 | const char *name, | ||
144 | void *data), | ||
145 | void *data) | ||
146 | { | ||
147 | char *home; | ||
148 | char *path; | ||
149 | char *envdir; | ||
150 | |||
151 | /* | ||
152 | * If a system plugin directory was defined, | ||
153 | * check that first. | ||
154 | */ | ||
155 | #ifdef PLUGIN_DIR | ||
156 | load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data); | ||
157 | #endif | ||
158 | |||
159 | /* | ||
160 | * Next let the environment-set plugin directory | ||
161 | * override the system defaults. | ||
162 | */ | ||
163 | envdir = getenv("TRACEEVENT_PLUGIN_DIR"); | ||
164 | if (envdir) | ||
165 | load_plugins_dir(pevent, suffix, envdir, load_plugin, data); | ||
166 | |||
167 | /* | ||
168 | * Now let the home directory override the environment | ||
169 | * or system defaults. | ||
170 | */ | ||
171 | home = getenv("HOME"); | ||
172 | if (!home) | ||
173 | return; | ||
174 | |||
175 | path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2); | ||
176 | if (!path) { | ||
177 | warning("could not allocate plugin memory\n"); | ||
178 | return; | ||
179 | } | ||
180 | |||
181 | strcpy(path, home); | ||
182 | strcat(path, "/"); | ||
183 | strcat(path, LOCAL_PLUGIN_DIR); | ||
184 | |||
185 | load_plugins_dir(pevent, suffix, path, load_plugin, data); | ||
186 | |||
187 | free(path); | ||
188 | } | ||
189 | |||
190 | struct plugin_list* | ||
191 | traceevent_load_plugins(struct pevent *pevent) | ||
192 | { | ||
193 | struct plugin_list *list = NULL; | ||
194 | |||
195 | load_plugins(pevent, ".so", load_plugin, &list); | ||
196 | return list; | ||
197 | } | ||
198 | |||
199 | void | ||
200 | traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent) | ||
201 | { | ||
202 | pevent_plugin_unload_func func; | ||
203 | struct plugin_list *list; | ||
204 | |||
205 | while (plugin_list) { | ||
206 | list = plugin_list; | ||
207 | plugin_list = list->next; | ||
208 | func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME); | ||
209 | if (func) | ||
210 | func(pevent); | ||
211 | dlclose(list->handle); | ||
212 | free(list->name); | ||
213 | free(list); | ||
214 | } | ||
215 | } | ||
diff --git a/tools/lib/traceevent/event-utils.h b/tools/lib/traceevent/event-utils.h index e76c9acb92cd..d1dc2170e402 100644 --- a/tools/lib/traceevent/event-utils.h +++ b/tools/lib/traceevent/event-utils.h | |||
@@ -23,18 +23,14 @@ | |||
23 | #include <ctype.h> | 23 | #include <ctype.h> |
24 | 24 | ||
25 | /* Can be overridden */ | 25 | /* Can be overridden */ |
26 | void die(const char *fmt, ...); | ||
27 | void *malloc_or_die(unsigned int size); | ||
28 | void warning(const char *fmt, ...); | 26 | void warning(const char *fmt, ...); |
29 | void pr_stat(const char *fmt, ...); | 27 | void pr_stat(const char *fmt, ...); |
30 | void vpr_stat(const char *fmt, va_list ap); | 28 | void vpr_stat(const char *fmt, va_list ap); |
31 | 29 | ||
32 | /* Always available */ | 30 | /* Always available */ |
33 | void __die(const char *fmt, ...); | ||
34 | void __warning(const char *fmt, ...); | 31 | void __warning(const char *fmt, ...); |
35 | void __pr_stat(const char *fmt, ...); | 32 | void __pr_stat(const char *fmt, ...); |
36 | 33 | ||
37 | void __vdie(const char *fmt, ...); | ||
38 | void __vwarning(const char *fmt, ...); | 34 | void __vwarning(const char *fmt, ...); |
39 | void __vpr_stat(const char *fmt, ...); | 35 | void __vpr_stat(const char *fmt, ...); |
40 | 36 | ||
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 2500e75583fc..b50234402fc2 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c | |||
@@ -38,41 +38,31 @@ struct event_list { | |||
38 | struct event_format *event; | 38 | struct event_format *event; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | #define MAX_ERR_STR_SIZE 256 | 41 | static void show_error(char *error_buf, const char *fmt, ...) |
42 | |||
43 | static void show_error(char **error_str, const char *fmt, ...) | ||
44 | { | 42 | { |
45 | unsigned long long index; | 43 | unsigned long long index; |
46 | const char *input; | 44 | const char *input; |
47 | char *error; | ||
48 | va_list ap; | 45 | va_list ap; |
49 | int len; | 46 | int len; |
50 | int i; | 47 | int i; |
51 | 48 | ||
52 | if (!error_str) | ||
53 | return; | ||
54 | |||
55 | input = pevent_get_input_buf(); | 49 | input = pevent_get_input_buf(); |
56 | index = pevent_get_input_buf_ptr(); | 50 | index = pevent_get_input_buf_ptr(); |
57 | len = input ? strlen(input) : 0; | 51 | len = input ? strlen(input) : 0; |
58 | 52 | ||
59 | error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3); | ||
60 | |||
61 | if (len) { | 53 | if (len) { |
62 | strcpy(error, input); | 54 | strcpy(error_buf, input); |
63 | error[len] = '\n'; | 55 | error_buf[len] = '\n'; |
64 | for (i = 1; i < len && i < index; i++) | 56 | for (i = 1; i < len && i < index; i++) |
65 | error[len+i] = ' '; | 57 | error_buf[len+i] = ' '; |
66 | error[len + i] = '^'; | 58 | error_buf[len + i] = '^'; |
67 | error[len + i + 1] = '\n'; | 59 | error_buf[len + i + 1] = '\n'; |
68 | len += i+2; | 60 | len += i+2; |
69 | } | 61 | } |
70 | 62 | ||
71 | va_start(ap, fmt); | 63 | va_start(ap, fmt); |
72 | vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap); | 64 | vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap); |
73 | va_end(ap); | 65 | va_end(ap); |
74 | |||
75 | *error_str = error; | ||
76 | } | 66 | } |
77 | 67 | ||
78 | static void free_token(char *token) | 68 | static void free_token(char *token) |
@@ -95,7 +85,11 @@ static enum event_type read_token(char **tok) | |||
95 | (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && | 85 | (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && |
96 | pevent_peek_char() == '~') { | 86 | pevent_peek_char() == '~') { |
97 | /* append it */ | 87 | /* append it */ |
98 | *tok = malloc_or_die(3); | 88 | *tok = malloc(3); |
89 | if (*tok == NULL) { | ||
90 | free_token(token); | ||
91 | return EVENT_ERROR; | ||
92 | } | ||
99 | sprintf(*tok, "%c%c", *token, '~'); | 93 | sprintf(*tok, "%c%c", *token, '~'); |
100 | free_token(token); | 94 | free_token(token); |
101 | /* Now remove the '~' from the buffer */ | 95 | /* Now remove the '~' from the buffer */ |
@@ -147,11 +141,13 @@ add_filter_type(struct event_filter *filter, int id) | |||
147 | if (filter_type) | 141 | if (filter_type) |
148 | return filter_type; | 142 | return filter_type; |
149 | 143 | ||
150 | filter->event_filters = realloc(filter->event_filters, | 144 | filter_type = realloc(filter->event_filters, |
151 | sizeof(*filter->event_filters) * | 145 | sizeof(*filter->event_filters) * |
152 | (filter->filters + 1)); | 146 | (filter->filters + 1)); |
153 | if (!filter->event_filters) | 147 | if (!filter_type) |
154 | die("Could not allocate filter"); | 148 | return NULL; |
149 | |||
150 | filter->event_filters = filter_type; | ||
155 | 151 | ||
156 | for (i = 0; i < filter->filters; i++) { | 152 | for (i = 0; i < filter->filters; i++) { |
157 | if (filter->event_filters[i].event_id > id) | 153 | if (filter->event_filters[i].event_id > id) |
@@ -182,7 +178,10 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent) | |||
182 | { | 178 | { |
183 | struct event_filter *filter; | 179 | struct event_filter *filter; |
184 | 180 | ||
185 | filter = malloc_or_die(sizeof(*filter)); | 181 | filter = malloc(sizeof(*filter)); |
182 | if (filter == NULL) | ||
183 | return NULL; | ||
184 | |||
186 | memset(filter, 0, sizeof(*filter)); | 185 | memset(filter, 0, sizeof(*filter)); |
187 | filter->pevent = pevent; | 186 | filter->pevent = pevent; |
188 | pevent_ref(pevent); | 187 | pevent_ref(pevent); |
@@ -192,12 +191,7 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent) | |||
192 | 191 | ||
193 | static struct filter_arg *allocate_arg(void) | 192 | static struct filter_arg *allocate_arg(void) |
194 | { | 193 | { |
195 | struct filter_arg *arg; | 194 | return calloc(1, sizeof(struct filter_arg)); |
196 | |||
197 | arg = malloc_or_die(sizeof(*arg)); | ||
198 | memset(arg, 0, sizeof(*arg)); | ||
199 | |||
200 | return arg; | ||
201 | } | 195 | } |
202 | 196 | ||
203 | static void free_arg(struct filter_arg *arg) | 197 | static void free_arg(struct filter_arg *arg) |
@@ -242,15 +236,19 @@ static void free_arg(struct filter_arg *arg) | |||
242 | free(arg); | 236 | free(arg); |
243 | } | 237 | } |
244 | 238 | ||
245 | static void add_event(struct event_list **events, | 239 | static int add_event(struct event_list **events, |
246 | struct event_format *event) | 240 | struct event_format *event) |
247 | { | 241 | { |
248 | struct event_list *list; | 242 | struct event_list *list; |
249 | 243 | ||
250 | list = malloc_or_die(sizeof(*list)); | 244 | list = malloc(sizeof(*list)); |
245 | if (list == NULL) | ||
246 | return -1; | ||
247 | |||
251 | list->next = *events; | 248 | list->next = *events; |
252 | *events = list; | 249 | *events = list; |
253 | list->event = event; | 250 | list->event = event; |
251 | return 0; | ||
254 | } | 252 | } |
255 | 253 | ||
256 | static int event_match(struct event_format *event, | 254 | static int event_match(struct event_format *event, |
@@ -265,7 +263,7 @@ static int event_match(struct event_format *event, | |||
265 | !regexec(ereg, event->name, 0, NULL, 0); | 263 | !regexec(ereg, event->name, 0, NULL, 0); |
266 | } | 264 | } |
267 | 265 | ||
268 | static int | 266 | static enum pevent_errno |
269 | find_event(struct pevent *pevent, struct event_list **events, | 267 | find_event(struct pevent *pevent, struct event_list **events, |
270 | char *sys_name, char *event_name) | 268 | char *sys_name, char *event_name) |
271 | { | 269 | { |
@@ -273,6 +271,7 @@ find_event(struct pevent *pevent, struct event_list **events, | |||
273 | regex_t ereg; | 271 | regex_t ereg; |
274 | regex_t sreg; | 272 | regex_t sreg; |
275 | int match = 0; | 273 | int match = 0; |
274 | int fail = 0; | ||
276 | char *reg; | 275 | char *reg; |
277 | int ret; | 276 | int ret; |
278 | int i; | 277 | int i; |
@@ -283,23 +282,31 @@ find_event(struct pevent *pevent, struct event_list **events, | |||
283 | sys_name = NULL; | 282 | sys_name = NULL; |
284 | } | 283 | } |
285 | 284 | ||
286 | reg = malloc_or_die(strlen(event_name) + 3); | 285 | reg = malloc(strlen(event_name) + 3); |
286 | if (reg == NULL) | ||
287 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
288 | |||
287 | sprintf(reg, "^%s$", event_name); | 289 | sprintf(reg, "^%s$", event_name); |
288 | 290 | ||
289 | ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB); | 291 | ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB); |
290 | free(reg); | 292 | free(reg); |
291 | 293 | ||
292 | if (ret) | 294 | if (ret) |
293 | return -1; | 295 | return PEVENT_ERRNO__INVALID_EVENT_NAME; |
294 | 296 | ||
295 | if (sys_name) { | 297 | if (sys_name) { |
296 | reg = malloc_or_die(strlen(sys_name) + 3); | 298 | reg = malloc(strlen(sys_name) + 3); |
299 | if (reg == NULL) { | ||
300 | regfree(&ereg); | ||
301 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
302 | } | ||
303 | |||
297 | sprintf(reg, "^%s$", sys_name); | 304 | sprintf(reg, "^%s$", sys_name); |
298 | ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB); | 305 | ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB); |
299 | free(reg); | 306 | free(reg); |
300 | if (ret) { | 307 | if (ret) { |
301 | regfree(&ereg); | 308 | regfree(&ereg); |
302 | return -1; | 309 | return PEVENT_ERRNO__INVALID_EVENT_NAME; |
303 | } | 310 | } |
304 | } | 311 | } |
305 | 312 | ||
@@ -307,7 +314,10 @@ find_event(struct pevent *pevent, struct event_list **events, | |||
307 | event = pevent->events[i]; | 314 | event = pevent->events[i]; |
308 | if (event_match(event, sys_name ? &sreg : NULL, &ereg)) { | 315 | if (event_match(event, sys_name ? &sreg : NULL, &ereg)) { |
309 | match = 1; | 316 | match = 1; |
310 | add_event(events, event); | 317 | if (add_event(events, event) < 0) { |
318 | fail = 1; | ||
319 | break; | ||
320 | } | ||
311 | } | 321 | } |
312 | } | 322 | } |
313 | 323 | ||
@@ -316,7 +326,9 @@ find_event(struct pevent *pevent, struct event_list **events, | |||
316 | regfree(&sreg); | 326 | regfree(&sreg); |
317 | 327 | ||
318 | if (!match) | 328 | if (!match) |
319 | return -1; | 329 | return PEVENT_ERRNO__EVENT_NOT_FOUND; |
330 | if (fail) | ||
331 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
320 | 332 | ||
321 | return 0; | 333 | return 0; |
322 | } | 334 | } |
@@ -332,14 +344,18 @@ static void free_events(struct event_list *events) | |||
332 | } | 344 | } |
333 | } | 345 | } |
334 | 346 | ||
335 | static struct filter_arg * | 347 | static enum pevent_errno |
336 | create_arg_item(struct event_format *event, const char *token, | 348 | create_arg_item(struct event_format *event, const char *token, |
337 | enum event_type type, char **error_str) | 349 | enum event_type type, struct filter_arg **parg, char *error_str) |
338 | { | 350 | { |
339 | struct format_field *field; | 351 | struct format_field *field; |
340 | struct filter_arg *arg; | 352 | struct filter_arg *arg; |
341 | 353 | ||
342 | arg = allocate_arg(); | 354 | arg = allocate_arg(); |
355 | if (arg == NULL) { | ||
356 | show_error(error_str, "failed to allocate filter arg"); | ||
357 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
358 | } | ||
343 | 359 | ||
344 | switch (type) { | 360 | switch (type) { |
345 | 361 | ||
@@ -349,8 +365,11 @@ create_arg_item(struct event_format *event, const char *token, | |||
349 | arg->value.type = | 365 | arg->value.type = |
350 | type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR; | 366 | type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR; |
351 | arg->value.str = strdup(token); | 367 | arg->value.str = strdup(token); |
352 | if (!arg->value.str) | 368 | if (!arg->value.str) { |
353 | die("malloc string"); | 369 | free_arg(arg); |
370 | show_error(error_str, "failed to allocate string filter arg"); | ||
371 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
372 | } | ||
354 | break; | 373 | break; |
355 | case EVENT_ITEM: | 374 | case EVENT_ITEM: |
356 | /* if it is a number, then convert it */ | 375 | /* if it is a number, then convert it */ |
@@ -377,11 +396,11 @@ create_arg_item(struct event_format *event, const char *token, | |||
377 | break; | 396 | break; |
378 | default: | 397 | default: |
379 | free_arg(arg); | 398 | free_arg(arg); |
380 | show_error(error_str, "expected a value but found %s", | 399 | show_error(error_str, "expected a value but found %s", token); |
381 | token); | 400 | return PEVENT_ERRNO__UNEXPECTED_TYPE; |
382 | return NULL; | ||
383 | } | 401 | } |
384 | return arg; | 402 | *parg = arg; |
403 | return 0; | ||
385 | } | 404 | } |
386 | 405 | ||
387 | static struct filter_arg * | 406 | static struct filter_arg * |
@@ -390,6 +409,9 @@ create_arg_op(enum filter_op_type btype) | |||
390 | struct filter_arg *arg; | 409 | struct filter_arg *arg; |
391 | 410 | ||
392 | arg = allocate_arg(); | 411 | arg = allocate_arg(); |
412 | if (!arg) | ||
413 | return NULL; | ||
414 | |||
393 | arg->type = FILTER_ARG_OP; | 415 | arg->type = FILTER_ARG_OP; |
394 | arg->op.type = btype; | 416 | arg->op.type = btype; |
395 | 417 | ||
@@ -402,6 +424,9 @@ create_arg_exp(enum filter_exp_type etype) | |||
402 | struct filter_arg *arg; | 424 | struct filter_arg *arg; |
403 | 425 | ||
404 | arg = allocate_arg(); | 426 | arg = allocate_arg(); |
427 | if (!arg) | ||
428 | return NULL; | ||
429 | |||
405 | arg->type = FILTER_ARG_EXP; | 430 | arg->type = FILTER_ARG_EXP; |
406 | arg->op.type = etype; | 431 | arg->op.type = etype; |
407 | 432 | ||
@@ -414,6 +439,9 @@ create_arg_cmp(enum filter_exp_type etype) | |||
414 | struct filter_arg *arg; | 439 | struct filter_arg *arg; |
415 | 440 | ||
416 | arg = allocate_arg(); | 441 | arg = allocate_arg(); |
442 | if (!arg) | ||
443 | return NULL; | ||
444 | |||
417 | /* Use NUM and change if necessary */ | 445 | /* Use NUM and change if necessary */ |
418 | arg->type = FILTER_ARG_NUM; | 446 | arg->type = FILTER_ARG_NUM; |
419 | arg->op.type = etype; | 447 | arg->op.type = etype; |
@@ -421,8 +449,8 @@ create_arg_cmp(enum filter_exp_type etype) | |||
421 | return arg; | 449 | return arg; |
422 | } | 450 | } |
423 | 451 | ||
424 | static int add_right(struct filter_arg *op, struct filter_arg *arg, | 452 | static enum pevent_errno |
425 | char **error_str) | 453 | add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) |
426 | { | 454 | { |
427 | struct filter_arg *left; | 455 | struct filter_arg *left; |
428 | char *str; | 456 | char *str; |
@@ -453,9 +481,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, | |||
453 | case FILTER_ARG_FIELD: | 481 | case FILTER_ARG_FIELD: |
454 | break; | 482 | break; |
455 | default: | 483 | default: |
456 | show_error(error_str, | 484 | show_error(error_str, "Illegal rvalue"); |
457 | "Illegal rvalue"); | 485 | return PEVENT_ERRNO__ILLEGAL_RVALUE; |
458 | return -1; | ||
459 | } | 486 | } |
460 | 487 | ||
461 | /* | 488 | /* |
@@ -502,7 +529,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, | |||
502 | if (left->type != FILTER_ARG_FIELD) { | 529 | if (left->type != FILTER_ARG_FIELD) { |
503 | show_error(error_str, | 530 | show_error(error_str, |
504 | "Illegal lvalue for string comparison"); | 531 | "Illegal lvalue for string comparison"); |
505 | return -1; | 532 | return PEVENT_ERRNO__ILLEGAL_LVALUE; |
506 | } | 533 | } |
507 | 534 | ||
508 | /* Make sure this is a valid string compare */ | 535 | /* Make sure this is a valid string compare */ |
@@ -521,25 +548,31 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, | |||
521 | show_error(error_str, | 548 | show_error(error_str, |
522 | "RegEx '%s' did not compute", | 549 | "RegEx '%s' did not compute", |
523 | str); | 550 | str); |
524 | return -1; | 551 | return PEVENT_ERRNO__INVALID_REGEX; |
525 | } | 552 | } |
526 | break; | 553 | break; |
527 | default: | 554 | default: |
528 | show_error(error_str, | 555 | show_error(error_str, |
529 | "Illegal comparison for string"); | 556 | "Illegal comparison for string"); |
530 | return -1; | 557 | return PEVENT_ERRNO__ILLEGAL_STRING_CMP; |
531 | } | 558 | } |
532 | 559 | ||
533 | op->type = FILTER_ARG_STR; | 560 | op->type = FILTER_ARG_STR; |
534 | op->str.type = op_type; | 561 | op->str.type = op_type; |
535 | op->str.field = left->field.field; | 562 | op->str.field = left->field.field; |
536 | op->str.val = strdup(str); | 563 | op->str.val = strdup(str); |
537 | if (!op->str.val) | 564 | if (!op->str.val) { |
538 | die("malloc string"); | 565 | show_error(error_str, "Failed to allocate string filter"); |
566 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
567 | } | ||
539 | /* | 568 | /* |
540 | * Need a buffer to copy data for tests | 569 | * Need a buffer to copy data for tests |
541 | */ | 570 | */ |
542 | op->str.buffer = malloc_or_die(op->str.field->size + 1); | 571 | op->str.buffer = malloc(op->str.field->size + 1); |
572 | if (!op->str.buffer) { | ||
573 | show_error(error_str, "Failed to allocate string filter"); | ||
574 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
575 | } | ||
543 | /* Null terminate this buffer */ | 576 | /* Null terminate this buffer */ |
544 | op->str.buffer[op->str.field->size] = 0; | 577 | op->str.buffer[op->str.field->size] = 0; |
545 | 578 | ||
@@ -557,7 +590,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, | |||
557 | case FILTER_CMP_NOT_REGEX: | 590 | case FILTER_CMP_NOT_REGEX: |
558 | show_error(error_str, | 591 | show_error(error_str, |
559 | "Op not allowed with integers"); | 592 | "Op not allowed with integers"); |
560 | return -1; | 593 | return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; |
561 | 594 | ||
562 | default: | 595 | default: |
563 | break; | 596 | break; |
@@ -577,9 +610,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, | |||
577 | return 0; | 610 | return 0; |
578 | 611 | ||
579 | out_fail: | 612 | out_fail: |
580 | show_error(error_str, | 613 | show_error(error_str, "Syntax error"); |
581 | "Syntax error"); | 614 | return PEVENT_ERRNO__SYNTAX_ERROR; |
582 | return -1; | ||
583 | } | 615 | } |
584 | 616 | ||
585 | static struct filter_arg * | 617 | static struct filter_arg * |
@@ -592,7 +624,7 @@ rotate_op_right(struct filter_arg *a, struct filter_arg *b) | |||
592 | return arg; | 624 | return arg; |
593 | } | 625 | } |
594 | 626 | ||
595 | static int add_left(struct filter_arg *op, struct filter_arg *arg) | 627 | static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg) |
596 | { | 628 | { |
597 | switch (op->type) { | 629 | switch (op->type) { |
598 | case FILTER_ARG_EXP: | 630 | case FILTER_ARG_EXP: |
@@ -611,11 +643,11 @@ static int add_left(struct filter_arg *op, struct filter_arg *arg) | |||
611 | /* left arg of compares must be a field */ | 643 | /* left arg of compares must be a field */ |
612 | if (arg->type != FILTER_ARG_FIELD && | 644 | if (arg->type != FILTER_ARG_FIELD && |
613 | arg->type != FILTER_ARG_BOOLEAN) | 645 | arg->type != FILTER_ARG_BOOLEAN) |
614 | return -1; | 646 | return PEVENT_ERRNO__INVALID_ARG_TYPE; |
615 | op->num.left = arg; | 647 | op->num.left = arg; |
616 | break; | 648 | break; |
617 | default: | 649 | default: |
618 | return -1; | 650 | return PEVENT_ERRNO__INVALID_ARG_TYPE; |
619 | } | 651 | } |
620 | return 0; | 652 | return 0; |
621 | } | 653 | } |
@@ -728,15 +760,18 @@ enum filter_vals { | |||
728 | FILTER_VAL_TRUE, | 760 | FILTER_VAL_TRUE, |
729 | }; | 761 | }; |
730 | 762 | ||
731 | void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, | 763 | static enum pevent_errno |
732 | struct filter_arg *arg) | 764 | reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, |
765 | struct filter_arg *arg, char *error_str) | ||
733 | { | 766 | { |
734 | struct filter_arg *other_child; | 767 | struct filter_arg *other_child; |
735 | struct filter_arg **ptr; | 768 | struct filter_arg **ptr; |
736 | 769 | ||
737 | if (parent->type != FILTER_ARG_OP && | 770 | if (parent->type != FILTER_ARG_OP && |
738 | arg->type != FILTER_ARG_OP) | 771 | arg->type != FILTER_ARG_OP) { |
739 | die("can not reparent other than OP"); | 772 | show_error(error_str, "can not reparent other than OP"); |
773 | return PEVENT_ERRNO__REPARENT_NOT_OP; | ||
774 | } | ||
740 | 775 | ||
741 | /* Get the sibling */ | 776 | /* Get the sibling */ |
742 | if (old_child->op.right == arg) { | 777 | if (old_child->op.right == arg) { |
@@ -745,8 +780,10 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, | |||
745 | } else if (old_child->op.left == arg) { | 780 | } else if (old_child->op.left == arg) { |
746 | ptr = &old_child->op.left; | 781 | ptr = &old_child->op.left; |
747 | other_child = old_child->op.right; | 782 | other_child = old_child->op.right; |
748 | } else | 783 | } else { |
749 | die("Error in reparent op, find other child"); | 784 | show_error(error_str, "Error in reparent op, find other child"); |
785 | return PEVENT_ERRNO__REPARENT_FAILED; | ||
786 | } | ||
750 | 787 | ||
751 | /* Detach arg from old_child */ | 788 | /* Detach arg from old_child */ |
752 | *ptr = NULL; | 789 | *ptr = NULL; |
@@ -757,23 +794,29 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, | |||
757 | *parent = *arg; | 794 | *parent = *arg; |
758 | /* Free arg without recussion */ | 795 | /* Free arg without recussion */ |
759 | free(arg); | 796 | free(arg); |
760 | return; | 797 | return 0; |
761 | } | 798 | } |
762 | 799 | ||
763 | if (parent->op.right == old_child) | 800 | if (parent->op.right == old_child) |
764 | ptr = &parent->op.right; | 801 | ptr = &parent->op.right; |
765 | else if (parent->op.left == old_child) | 802 | else if (parent->op.left == old_child) |
766 | ptr = &parent->op.left; | 803 | ptr = &parent->op.left; |
767 | else | 804 | else { |
768 | die("Error in reparent op"); | 805 | show_error(error_str, "Error in reparent op"); |
806 | return PEVENT_ERRNO__REPARENT_FAILED; | ||
807 | } | ||
808 | |||
769 | *ptr = arg; | 809 | *ptr = arg; |
770 | 810 | ||
771 | free_arg(old_child); | 811 | free_arg(old_child); |
812 | return 0; | ||
772 | } | 813 | } |
773 | 814 | ||
774 | enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) | 815 | /* Returns either filter_vals (success) or pevent_errno (failfure) */ |
816 | static int test_arg(struct filter_arg *parent, struct filter_arg *arg, | ||
817 | char *error_str) | ||
775 | { | 818 | { |
776 | enum filter_vals lval, rval; | 819 | int lval, rval; |
777 | 820 | ||
778 | switch (arg->type) { | 821 | switch (arg->type) { |
779 | 822 | ||
@@ -788,63 +831,68 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) | |||
788 | return FILTER_VAL_NORM; | 831 | return FILTER_VAL_NORM; |
789 | 832 | ||
790 | case FILTER_ARG_EXP: | 833 | case FILTER_ARG_EXP: |
791 | lval = test_arg(arg, arg->exp.left); | 834 | lval = test_arg(arg, arg->exp.left, error_str); |
792 | if (lval != FILTER_VAL_NORM) | 835 | if (lval != FILTER_VAL_NORM) |
793 | return lval; | 836 | return lval; |
794 | rval = test_arg(arg, arg->exp.right); | 837 | rval = test_arg(arg, arg->exp.right, error_str); |
795 | if (rval != FILTER_VAL_NORM) | 838 | if (rval != FILTER_VAL_NORM) |
796 | return rval; | 839 | return rval; |
797 | return FILTER_VAL_NORM; | 840 | return FILTER_VAL_NORM; |
798 | 841 | ||
799 | case FILTER_ARG_NUM: | 842 | case FILTER_ARG_NUM: |
800 | lval = test_arg(arg, arg->num.left); | 843 | lval = test_arg(arg, arg->num.left, error_str); |
801 | if (lval != FILTER_VAL_NORM) | 844 | if (lval != FILTER_VAL_NORM) |
802 | return lval; | 845 | return lval; |
803 | rval = test_arg(arg, arg->num.right); | 846 | rval = test_arg(arg, arg->num.right, error_str); |
804 | if (rval != FILTER_VAL_NORM) | 847 | if (rval != FILTER_VAL_NORM) |
805 | return rval; | 848 | return rval; |
806 | return FILTER_VAL_NORM; | 849 | return FILTER_VAL_NORM; |
807 | 850 | ||
808 | case FILTER_ARG_OP: | 851 | case FILTER_ARG_OP: |
809 | if (arg->op.type != FILTER_OP_NOT) { | 852 | if (arg->op.type != FILTER_OP_NOT) { |
810 | lval = test_arg(arg, arg->op.left); | 853 | lval = test_arg(arg, arg->op.left, error_str); |
811 | switch (lval) { | 854 | switch (lval) { |
812 | case FILTER_VAL_NORM: | 855 | case FILTER_VAL_NORM: |
813 | break; | 856 | break; |
814 | case FILTER_VAL_TRUE: | 857 | case FILTER_VAL_TRUE: |
815 | if (arg->op.type == FILTER_OP_OR) | 858 | if (arg->op.type == FILTER_OP_OR) |
816 | return FILTER_VAL_TRUE; | 859 | return FILTER_VAL_TRUE; |
817 | rval = test_arg(arg, arg->op.right); | 860 | rval = test_arg(arg, arg->op.right, error_str); |
818 | if (rval != FILTER_VAL_NORM) | 861 | if (rval != FILTER_VAL_NORM) |
819 | return rval; | 862 | return rval; |
820 | 863 | ||
821 | reparent_op_arg(parent, arg, arg->op.right); | 864 | return reparent_op_arg(parent, arg, arg->op.right, |
822 | return FILTER_VAL_NORM; | 865 | error_str); |
823 | 866 | ||
824 | case FILTER_VAL_FALSE: | 867 | case FILTER_VAL_FALSE: |
825 | if (arg->op.type == FILTER_OP_AND) | 868 | if (arg->op.type == FILTER_OP_AND) |
826 | return FILTER_VAL_FALSE; | 869 | return FILTER_VAL_FALSE; |
827 | rval = test_arg(arg, arg->op.right); | 870 | rval = test_arg(arg, arg->op.right, error_str); |
828 | if (rval != FILTER_VAL_NORM) | 871 | if (rval != FILTER_VAL_NORM) |
829 | return rval; | 872 | return rval; |
830 | 873 | ||
831 | reparent_op_arg(parent, arg, arg->op.right); | 874 | return reparent_op_arg(parent, arg, arg->op.right, |
832 | return FILTER_VAL_NORM; | 875 | error_str); |
876 | |||
877 | default: | ||
878 | return lval; | ||
833 | } | 879 | } |
834 | } | 880 | } |
835 | 881 | ||
836 | rval = test_arg(arg, arg->op.right); | 882 | rval = test_arg(arg, arg->op.right, error_str); |
837 | switch (rval) { | 883 | switch (rval) { |
838 | case FILTER_VAL_NORM: | 884 | case FILTER_VAL_NORM: |
885 | default: | ||
839 | break; | 886 | break; |
887 | |||
840 | case FILTER_VAL_TRUE: | 888 | case FILTER_VAL_TRUE: |
841 | if (arg->op.type == FILTER_OP_OR) | 889 | if (arg->op.type == FILTER_OP_OR) |
842 | return FILTER_VAL_TRUE; | 890 | return FILTER_VAL_TRUE; |
843 | if (arg->op.type == FILTER_OP_NOT) | 891 | if (arg->op.type == FILTER_OP_NOT) |
844 | return FILTER_VAL_FALSE; | 892 | return FILTER_VAL_FALSE; |
845 | 893 | ||
846 | reparent_op_arg(parent, arg, arg->op.left); | 894 | return reparent_op_arg(parent, arg, arg->op.left, |
847 | return FILTER_VAL_NORM; | 895 | error_str); |
848 | 896 | ||
849 | case FILTER_VAL_FALSE: | 897 | case FILTER_VAL_FALSE: |
850 | if (arg->op.type == FILTER_OP_AND) | 898 | if (arg->op.type == FILTER_OP_AND) |
@@ -852,41 +900,56 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) | |||
852 | if (arg->op.type == FILTER_OP_NOT) | 900 | if (arg->op.type == FILTER_OP_NOT) |
853 | return FILTER_VAL_TRUE; | 901 | return FILTER_VAL_TRUE; |
854 | 902 | ||
855 | reparent_op_arg(parent, arg, arg->op.left); | 903 | return reparent_op_arg(parent, arg, arg->op.left, |
856 | return FILTER_VAL_NORM; | 904 | error_str); |
857 | } | 905 | } |
858 | 906 | ||
859 | return FILTER_VAL_NORM; | 907 | return rval; |
860 | default: | 908 | default: |
861 | die("bad arg in filter tree"); | 909 | show_error(error_str, "bad arg in filter tree"); |
910 | return PEVENT_ERRNO__BAD_FILTER_ARG; | ||
862 | } | 911 | } |
863 | return FILTER_VAL_NORM; | 912 | return FILTER_VAL_NORM; |
864 | } | 913 | } |
865 | 914 | ||
866 | /* Remove any unknown event fields */ | 915 | /* Remove any unknown event fields */ |
867 | static struct filter_arg *collapse_tree(struct filter_arg *arg) | 916 | static int collapse_tree(struct filter_arg *arg, |
917 | struct filter_arg **arg_collapsed, char *error_str) | ||
868 | { | 918 | { |
869 | enum filter_vals ret; | 919 | int ret; |
870 | 920 | ||
871 | ret = test_arg(arg, arg); | 921 | ret = test_arg(arg, arg, error_str); |
872 | switch (ret) { | 922 | switch (ret) { |
873 | case FILTER_VAL_NORM: | 923 | case FILTER_VAL_NORM: |
874 | return arg; | 924 | break; |
875 | 925 | ||
876 | case FILTER_VAL_TRUE: | 926 | case FILTER_VAL_TRUE: |
877 | case FILTER_VAL_FALSE: | 927 | case FILTER_VAL_FALSE: |
878 | free_arg(arg); | 928 | free_arg(arg); |
879 | arg = allocate_arg(); | 929 | arg = allocate_arg(); |
880 | arg->type = FILTER_ARG_BOOLEAN; | 930 | if (arg) { |
881 | arg->boolean.value = ret == FILTER_VAL_TRUE; | 931 | arg->type = FILTER_ARG_BOOLEAN; |
932 | arg->boolean.value = ret == FILTER_VAL_TRUE; | ||
933 | } else { | ||
934 | show_error(error_str, "Failed to allocate filter arg"); | ||
935 | ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
936 | } | ||
937 | break; | ||
938 | |||
939 | default: | ||
940 | /* test_arg() already set the error_str */ | ||
941 | free_arg(arg); | ||
942 | arg = NULL; | ||
943 | break; | ||
882 | } | 944 | } |
883 | 945 | ||
884 | return arg; | 946 | *arg_collapsed = arg; |
947 | return ret; | ||
885 | } | 948 | } |
886 | 949 | ||
887 | static int | 950 | static enum pevent_errno |
888 | process_filter(struct event_format *event, struct filter_arg **parg, | 951 | process_filter(struct event_format *event, struct filter_arg **parg, |
889 | char **error_str, int not) | 952 | char *error_str, int not) |
890 | { | 953 | { |
891 | enum event_type type; | 954 | enum event_type type; |
892 | char *token = NULL; | 955 | char *token = NULL; |
@@ -898,7 +961,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
898 | enum filter_op_type btype; | 961 | enum filter_op_type btype; |
899 | enum filter_exp_type etype; | 962 | enum filter_exp_type etype; |
900 | enum filter_cmp_type ctype; | 963 | enum filter_cmp_type ctype; |
901 | int ret; | 964 | enum pevent_errno ret; |
902 | 965 | ||
903 | *parg = NULL; | 966 | *parg = NULL; |
904 | 967 | ||
@@ -909,8 +972,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
909 | case EVENT_SQUOTE: | 972 | case EVENT_SQUOTE: |
910 | case EVENT_DQUOTE: | 973 | case EVENT_DQUOTE: |
911 | case EVENT_ITEM: | 974 | case EVENT_ITEM: |
912 | arg = create_arg_item(event, token, type, error_str); | 975 | ret = create_arg_item(event, token, type, &arg, error_str); |
913 | if (!arg) | 976 | if (ret < 0) |
914 | goto fail; | 977 | goto fail; |
915 | if (!left_item) | 978 | if (!left_item) |
916 | left_item = arg; | 979 | left_item = arg; |
@@ -923,20 +986,20 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
923 | if (not) { | 986 | if (not) { |
924 | arg = NULL; | 987 | arg = NULL; |
925 | if (current_op) | 988 | if (current_op) |
926 | goto fail_print; | 989 | goto fail_syntax; |
927 | free(token); | 990 | free(token); |
928 | *parg = current_exp; | 991 | *parg = current_exp; |
929 | return 0; | 992 | return 0; |
930 | } | 993 | } |
931 | } else | 994 | } else |
932 | goto fail_print; | 995 | goto fail_syntax; |
933 | arg = NULL; | 996 | arg = NULL; |
934 | break; | 997 | break; |
935 | 998 | ||
936 | case EVENT_DELIM: | 999 | case EVENT_DELIM: |
937 | if (*token == ',') { | 1000 | if (*token == ',') { |
938 | show_error(error_str, | 1001 | show_error(error_str, "Illegal token ','"); |
939 | "Illegal token ','"); | 1002 | ret = PEVENT_ERRNO__ILLEGAL_TOKEN; |
940 | goto fail; | 1003 | goto fail; |
941 | } | 1004 | } |
942 | 1005 | ||
@@ -944,19 +1007,23 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
944 | if (left_item) { | 1007 | if (left_item) { |
945 | show_error(error_str, | 1008 | show_error(error_str, |
946 | "Open paren can not come after item"); | 1009 | "Open paren can not come after item"); |
1010 | ret = PEVENT_ERRNO__INVALID_PAREN; | ||
947 | goto fail; | 1011 | goto fail; |
948 | } | 1012 | } |
949 | if (current_exp) { | 1013 | if (current_exp) { |
950 | show_error(error_str, | 1014 | show_error(error_str, |
951 | "Open paren can not come after expression"); | 1015 | "Open paren can not come after expression"); |
1016 | ret = PEVENT_ERRNO__INVALID_PAREN; | ||
952 | goto fail; | 1017 | goto fail; |
953 | } | 1018 | } |
954 | 1019 | ||
955 | ret = process_filter(event, &arg, error_str, 0); | 1020 | ret = process_filter(event, &arg, error_str, 0); |
956 | if (ret != 1) { | 1021 | if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) { |
957 | if (ret == 0) | 1022 | if (ret == 0) { |
958 | show_error(error_str, | 1023 | show_error(error_str, |
959 | "Unbalanced number of '('"); | 1024 | "Unbalanced number of '('"); |
1025 | ret = PEVENT_ERRNO__UNBALANCED_PAREN; | ||
1026 | } | ||
960 | goto fail; | 1027 | goto fail; |
961 | } | 1028 | } |
962 | ret = 0; | 1029 | ret = 0; |
@@ -964,7 +1031,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
964 | /* A not wants just one expression */ | 1031 | /* A not wants just one expression */ |
965 | if (not) { | 1032 | if (not) { |
966 | if (current_op) | 1033 | if (current_op) |
967 | goto fail_print; | 1034 | goto fail_syntax; |
968 | *parg = arg; | 1035 | *parg = arg; |
969 | return 0; | 1036 | return 0; |
970 | } | 1037 | } |
@@ -979,19 +1046,19 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
979 | 1046 | ||
980 | } else { /* ')' */ | 1047 | } else { /* ')' */ |
981 | if (!current_op && !current_exp) | 1048 | if (!current_op && !current_exp) |
982 | goto fail_print; | 1049 | goto fail_syntax; |
983 | 1050 | ||
984 | /* Make sure everything is finished at this level */ | 1051 | /* Make sure everything is finished at this level */ |
985 | if (current_exp && !check_op_done(current_exp)) | 1052 | if (current_exp && !check_op_done(current_exp)) |
986 | goto fail_print; | 1053 | goto fail_syntax; |
987 | if (current_op && !check_op_done(current_op)) | 1054 | if (current_op && !check_op_done(current_op)) |
988 | goto fail_print; | 1055 | goto fail_syntax; |
989 | 1056 | ||
990 | if (current_op) | 1057 | if (current_op) |
991 | *parg = current_op; | 1058 | *parg = current_op; |
992 | else | 1059 | else |
993 | *parg = current_exp; | 1060 | *parg = current_exp; |
994 | return 1; | 1061 | return PEVENT_ERRNO__UNBALANCED_PAREN; |
995 | } | 1062 | } |
996 | break; | 1063 | break; |
997 | 1064 | ||
@@ -1003,21 +1070,22 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
1003 | case OP_BOOL: | 1070 | case OP_BOOL: |
1004 | /* Logic ops need a left expression */ | 1071 | /* Logic ops need a left expression */ |
1005 | if (!current_exp && !current_op) | 1072 | if (!current_exp && !current_op) |
1006 | goto fail_print; | 1073 | goto fail_syntax; |
1007 | /* fall through */ | 1074 | /* fall through */ |
1008 | case OP_NOT: | 1075 | case OP_NOT: |
1009 | /* logic only processes ops and exp */ | 1076 | /* logic only processes ops and exp */ |
1010 | if (left_item) | 1077 | if (left_item) |
1011 | goto fail_print; | 1078 | goto fail_syntax; |
1012 | break; | 1079 | break; |
1013 | case OP_EXP: | 1080 | case OP_EXP: |
1014 | case OP_CMP: | 1081 | case OP_CMP: |
1015 | if (!left_item) | 1082 | if (!left_item) |
1016 | goto fail_print; | 1083 | goto fail_syntax; |
1017 | break; | 1084 | break; |
1018 | case OP_NONE: | 1085 | case OP_NONE: |
1019 | show_error(error_str, | 1086 | show_error(error_str, |
1020 | "Unknown op token %s", token); | 1087 | "Unknown op token %s", token); |
1088 | ret = PEVENT_ERRNO__UNKNOWN_TOKEN; | ||
1021 | goto fail; | 1089 | goto fail; |
1022 | } | 1090 | } |
1023 | 1091 | ||
@@ -1025,6 +1093,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
1025 | switch (op_type) { | 1093 | switch (op_type) { |
1026 | case OP_BOOL: | 1094 | case OP_BOOL: |
1027 | arg = create_arg_op(btype); | 1095 | arg = create_arg_op(btype); |
1096 | if (arg == NULL) | ||
1097 | goto fail_alloc; | ||
1028 | if (current_op) | 1098 | if (current_op) |
1029 | ret = add_left(arg, current_op); | 1099 | ret = add_left(arg, current_op); |
1030 | else | 1100 | else |
@@ -1035,6 +1105,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
1035 | 1105 | ||
1036 | case OP_NOT: | 1106 | case OP_NOT: |
1037 | arg = create_arg_op(btype); | 1107 | arg = create_arg_op(btype); |
1108 | if (arg == NULL) | ||
1109 | goto fail_alloc; | ||
1038 | if (current_op) | 1110 | if (current_op) |
1039 | ret = add_right(current_op, arg, error_str); | 1111 | ret = add_right(current_op, arg, error_str); |
1040 | if (ret < 0) | 1112 | if (ret < 0) |
@@ -1054,6 +1126,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
1054 | arg = create_arg_exp(etype); | 1126 | arg = create_arg_exp(etype); |
1055 | else | 1127 | else |
1056 | arg = create_arg_cmp(ctype); | 1128 | arg = create_arg_cmp(ctype); |
1129 | if (arg == NULL) | ||
1130 | goto fail_alloc; | ||
1057 | 1131 | ||
1058 | if (current_op) | 1132 | if (current_op) |
1059 | ret = add_right(current_op, arg, error_str); | 1133 | ret = add_right(current_op, arg, error_str); |
@@ -1062,7 +1136,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
1062 | ret = add_left(arg, left_item); | 1136 | ret = add_left(arg, left_item); |
1063 | if (ret < 0) { | 1137 | if (ret < 0) { |
1064 | arg = NULL; | 1138 | arg = NULL; |
1065 | goto fail_print; | 1139 | goto fail_syntax; |
1066 | } | 1140 | } |
1067 | current_exp = arg; | 1141 | current_exp = arg; |
1068 | break; | 1142 | break; |
@@ -1071,57 +1145,64 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
1071 | } | 1145 | } |
1072 | arg = NULL; | 1146 | arg = NULL; |
1073 | if (ret < 0) | 1147 | if (ret < 0) |
1074 | goto fail_print; | 1148 | goto fail_syntax; |
1075 | break; | 1149 | break; |
1076 | case EVENT_NONE: | 1150 | case EVENT_NONE: |
1077 | break; | 1151 | break; |
1152 | case EVENT_ERROR: | ||
1153 | goto fail_alloc; | ||
1078 | default: | 1154 | default: |
1079 | goto fail_print; | 1155 | goto fail_syntax; |
1080 | } | 1156 | } |
1081 | } while (type != EVENT_NONE); | 1157 | } while (type != EVENT_NONE); |
1082 | 1158 | ||
1083 | if (!current_op && !current_exp) | 1159 | if (!current_op && !current_exp) |
1084 | goto fail_print; | 1160 | goto fail_syntax; |
1085 | 1161 | ||
1086 | if (!current_op) | 1162 | if (!current_op) |
1087 | current_op = current_exp; | 1163 | current_op = current_exp; |
1088 | 1164 | ||
1089 | current_op = collapse_tree(current_op); | 1165 | ret = collapse_tree(current_op, parg, error_str); |
1166 | if (ret < 0) | ||
1167 | goto fail; | ||
1090 | 1168 | ||
1091 | *parg = current_op; | 1169 | *parg = current_op; |
1092 | 1170 | ||
1093 | return 0; | 1171 | return 0; |
1094 | 1172 | ||
1095 | fail_print: | 1173 | fail_alloc: |
1174 | show_error(error_str, "failed to allocate filter arg"); | ||
1175 | ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
1176 | goto fail; | ||
1177 | fail_syntax: | ||
1096 | show_error(error_str, "Syntax error"); | 1178 | show_error(error_str, "Syntax error"); |
1179 | ret = PEVENT_ERRNO__SYNTAX_ERROR; | ||
1097 | fail: | 1180 | fail: |
1098 | free_arg(current_op); | 1181 | free_arg(current_op); |
1099 | free_arg(current_exp); | 1182 | free_arg(current_exp); |
1100 | free_arg(arg); | 1183 | free_arg(arg); |
1101 | free(token); | 1184 | free(token); |
1102 | return -1; | 1185 | return ret; |
1103 | } | 1186 | } |
1104 | 1187 | ||
1105 | static int | 1188 | static enum pevent_errno |
1106 | process_event(struct event_format *event, const char *filter_str, | 1189 | process_event(struct event_format *event, const char *filter_str, |
1107 | struct filter_arg **parg, char **error_str) | 1190 | struct filter_arg **parg, char *error_str) |
1108 | { | 1191 | { |
1109 | int ret; | 1192 | int ret; |
1110 | 1193 | ||
1111 | pevent_buffer_init(filter_str, strlen(filter_str)); | 1194 | pevent_buffer_init(filter_str, strlen(filter_str)); |
1112 | 1195 | ||
1113 | ret = process_filter(event, parg, error_str, 0); | 1196 | ret = process_filter(event, parg, error_str, 0); |
1114 | if (ret == 1) { | ||
1115 | show_error(error_str, | ||
1116 | "Unbalanced number of ')'"); | ||
1117 | return -1; | ||
1118 | } | ||
1119 | if (ret < 0) | 1197 | if (ret < 0) |
1120 | return ret; | 1198 | return ret; |
1121 | 1199 | ||
1122 | /* If parg is NULL, then make it into FALSE */ | 1200 | /* If parg is NULL, then make it into FALSE */ |
1123 | if (!*parg) { | 1201 | if (!*parg) { |
1124 | *parg = allocate_arg(); | 1202 | *parg = allocate_arg(); |
1203 | if (*parg == NULL) | ||
1204 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
1205 | |||
1125 | (*parg)->type = FILTER_ARG_BOOLEAN; | 1206 | (*parg)->type = FILTER_ARG_BOOLEAN; |
1126 | (*parg)->boolean.value = FILTER_FALSE; | 1207 | (*parg)->boolean.value = FILTER_FALSE; |
1127 | } | 1208 | } |
@@ -1129,13 +1210,13 @@ process_event(struct event_format *event, const char *filter_str, | |||
1129 | return 0; | 1210 | return 0; |
1130 | } | 1211 | } |
1131 | 1212 | ||
1132 | static int filter_event(struct event_filter *filter, | 1213 | static enum pevent_errno |
1133 | struct event_format *event, | 1214 | filter_event(struct event_filter *filter, struct event_format *event, |
1134 | const char *filter_str, char **error_str) | 1215 | const char *filter_str, char *error_str) |
1135 | { | 1216 | { |
1136 | struct filter_type *filter_type; | 1217 | struct filter_type *filter_type; |
1137 | struct filter_arg *arg; | 1218 | struct filter_arg *arg; |
1138 | int ret; | 1219 | enum pevent_errno ret; |
1139 | 1220 | ||
1140 | if (filter_str) { | 1221 | if (filter_str) { |
1141 | ret = process_event(event, filter_str, &arg, error_str); | 1222 | ret = process_event(event, filter_str, &arg, error_str); |
@@ -1145,11 +1226,17 @@ static int filter_event(struct event_filter *filter, | |||
1145 | } else { | 1226 | } else { |
1146 | /* just add a TRUE arg */ | 1227 | /* just add a TRUE arg */ |
1147 | arg = allocate_arg(); | 1228 | arg = allocate_arg(); |
1229 | if (arg == NULL) | ||
1230 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
1231 | |||
1148 | arg->type = FILTER_ARG_BOOLEAN; | 1232 | arg->type = FILTER_ARG_BOOLEAN; |
1149 | arg->boolean.value = FILTER_TRUE; | 1233 | arg->boolean.value = FILTER_TRUE; |
1150 | } | 1234 | } |
1151 | 1235 | ||
1152 | filter_type = add_filter_type(filter, event->id); | 1236 | filter_type = add_filter_type(filter, event->id); |
1237 | if (filter_type == NULL) | ||
1238 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
1239 | |||
1153 | if (filter_type->filter) | 1240 | if (filter_type->filter) |
1154 | free_arg(filter_type->filter); | 1241 | free_arg(filter_type->filter); |
1155 | filter_type->filter = arg; | 1242 | filter_type->filter = arg; |
@@ -1157,22 +1244,24 @@ static int filter_event(struct event_filter *filter, | |||
1157 | return 0; | 1244 | return 0; |
1158 | } | 1245 | } |
1159 | 1246 | ||
1247 | static void filter_init_error_buf(struct event_filter *filter) | ||
1248 | { | ||
1249 | /* clear buffer to reset show error */ | ||
1250 | pevent_buffer_init("", 0); | ||
1251 | filter->error_buffer[0] = '\0'; | ||
1252 | } | ||
1253 | |||
1160 | /** | 1254 | /** |
1161 | * pevent_filter_add_filter_str - add a new filter | 1255 | * pevent_filter_add_filter_str - add a new filter |
1162 | * @filter: the event filter to add to | 1256 | * @filter: the event filter to add to |
1163 | * @filter_str: the filter string that contains the filter | 1257 | * @filter_str: the filter string that contains the filter |
1164 | * @error_str: string containing reason for failed filter | ||
1165 | * | ||
1166 | * Returns 0 if the filter was successfully added | ||
1167 | * -1 if there was an error. | ||
1168 | * | 1258 | * |
1169 | * On error, if @error_str points to a string pointer, | 1259 | * Returns 0 if the filter was successfully added or a |
1170 | * it is set to the reason that the filter failed. | 1260 | * negative error code. Use pevent_filter_strerror() to see |
1171 | * This string must be freed with "free". | 1261 | * actual error message in case of error. |
1172 | */ | 1262 | */ |
1173 | int pevent_filter_add_filter_str(struct event_filter *filter, | 1263 | enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, |
1174 | const char *filter_str, | 1264 | const char *filter_str) |
1175 | char **error_str) | ||
1176 | { | 1265 | { |
1177 | struct pevent *pevent = filter->pevent; | 1266 | struct pevent *pevent = filter->pevent; |
1178 | struct event_list *event; | 1267 | struct event_list *event; |
@@ -1183,15 +1272,11 @@ int pevent_filter_add_filter_str(struct event_filter *filter, | |||
1183 | char *event_name = NULL; | 1272 | char *event_name = NULL; |
1184 | char *sys_name = NULL; | 1273 | char *sys_name = NULL; |
1185 | char *sp; | 1274 | char *sp; |
1186 | int rtn = 0; | 1275 | enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */ |
1187 | int len; | 1276 | int len; |
1188 | int ret; | 1277 | int ret; |
1189 | 1278 | ||
1190 | /* clear buffer to reset show error */ | 1279 | filter_init_error_buf(filter); |
1191 | pevent_buffer_init("", 0); | ||
1192 | |||
1193 | if (error_str) | ||
1194 | *error_str = NULL; | ||
1195 | 1280 | ||
1196 | filter_start = strchr(filter_str, ':'); | 1281 | filter_start = strchr(filter_str, ':'); |
1197 | if (filter_start) | 1282 | if (filter_start) |
@@ -1199,7 +1284,6 @@ int pevent_filter_add_filter_str(struct event_filter *filter, | |||
1199 | else | 1284 | else |
1200 | len = strlen(filter_str); | 1285 | len = strlen(filter_str); |
1201 | 1286 | ||
1202 | |||
1203 | do { | 1287 | do { |
1204 | next_event = strchr(filter_str, ','); | 1288 | next_event = strchr(filter_str, ','); |
1205 | if (next_event && | 1289 | if (next_event && |
@@ -1210,7 +1294,12 @@ int pevent_filter_add_filter_str(struct event_filter *filter, | |||
1210 | else | 1294 | else |
1211 | len = strlen(filter_str); | 1295 | len = strlen(filter_str); |
1212 | 1296 | ||
1213 | this_event = malloc_or_die(len + 1); | 1297 | this_event = malloc(len + 1); |
1298 | if (this_event == NULL) { | ||
1299 | /* This can only happen when events is NULL, but still */ | ||
1300 | free_events(events); | ||
1301 | return PEVENT_ERRNO__MEM_ALLOC_FAILED; | ||
1302 | } | ||
1214 | memcpy(this_event, filter_str, len); | 1303 | memcpy(this_event, filter_str, len); |
1215 | this_event[len] = 0; | 1304 | this_event[len] = 0; |
1216 | 1305 | ||
@@ -1223,27 +1312,18 @@ int pevent_filter_add_filter_str(struct event_filter *filter, | |||
1223 | event_name = strtok_r(NULL, "/", &sp); | 1312 | event_name = strtok_r(NULL, "/", &sp); |
1224 | 1313 | ||
1225 | if (!sys_name) { | 1314 | if (!sys_name) { |
1226 | show_error(error_str, "No filter found"); | ||
1227 | /* This can only happen when events is NULL, but still */ | 1315 | /* This can only happen when events is NULL, but still */ |
1228 | free_events(events); | 1316 | free_events(events); |
1229 | free(this_event); | 1317 | free(this_event); |
1230 | return -1; | 1318 | return PEVENT_ERRNO__FILTER_NOT_FOUND; |
1231 | } | 1319 | } |
1232 | 1320 | ||
1233 | /* Find this event */ | 1321 | /* Find this event */ |
1234 | ret = find_event(pevent, &events, strim(sys_name), strim(event_name)); | 1322 | ret = find_event(pevent, &events, strim(sys_name), strim(event_name)); |
1235 | if (ret < 0) { | 1323 | if (ret < 0) { |
1236 | if (event_name) | ||
1237 | show_error(error_str, | ||
1238 | "No event found under '%s.%s'", | ||
1239 | sys_name, event_name); | ||
1240 | else | ||
1241 | show_error(error_str, | ||
1242 | "No event found under '%s'", | ||
1243 | sys_name); | ||
1244 | free_events(events); | 1324 | free_events(events); |
1245 | free(this_event); | 1325 | free(this_event); |
1246 | return -1; | 1326 | return ret; |
1247 | } | 1327 | } |
1248 | free(this_event); | 1328 | free(this_event); |
1249 | } while (filter_str); | 1329 | } while (filter_str); |
@@ -1255,7 +1335,7 @@ int pevent_filter_add_filter_str(struct event_filter *filter, | |||
1255 | /* filter starts here */ | 1335 | /* filter starts here */ |
1256 | for (event = events; event; event = event->next) { | 1336 | for (event = events; event; event = event->next) { |
1257 | ret = filter_event(filter, event->event, filter_start, | 1337 | ret = filter_event(filter, event->event, filter_start, |
1258 | error_str); | 1338 | filter->error_buffer); |
1259 | /* Failures are returned if a parse error happened */ | 1339 | /* Failures are returned if a parse error happened */ |
1260 | if (ret < 0) | 1340 | if (ret < 0) |
1261 | rtn = ret; | 1341 | rtn = ret; |
@@ -1263,8 +1343,10 @@ int pevent_filter_add_filter_str(struct event_filter *filter, | |||
1263 | if (ret >= 0 && pevent->test_filters) { | 1343 | if (ret >= 0 && pevent->test_filters) { |
1264 | char *test; | 1344 | char *test; |
1265 | test = pevent_filter_make_string(filter, event->event->id); | 1345 | test = pevent_filter_make_string(filter, event->event->id); |
1266 | printf(" '%s: %s'\n", event->event->name, test); | 1346 | if (test) { |
1267 | free(test); | 1347 | printf(" '%s: %s'\n", event->event->name, test); |
1348 | free(test); | ||
1349 | } | ||
1268 | } | 1350 | } |
1269 | } | 1351 | } |
1270 | 1352 | ||
@@ -1282,6 +1364,32 @@ static void free_filter_type(struct filter_type *filter_type) | |||
1282 | } | 1364 | } |
1283 | 1365 | ||
1284 | /** | 1366 | /** |
1367 | * pevent_filter_strerror - fill error message in a buffer | ||
1368 | * @filter: the event filter contains error | ||
1369 | * @err: the error code | ||
1370 | * @buf: the buffer to be filled in | ||
1371 | * @buflen: the size of the buffer | ||
1372 | * | ||
1373 | * Returns 0 if message was filled successfully, -1 if error | ||
1374 | */ | ||
1375 | int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err, | ||
1376 | char *buf, size_t buflen) | ||
1377 | { | ||
1378 | if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END) | ||
1379 | return -1; | ||
1380 | |||
1381 | if (strlen(filter->error_buffer) > 0) { | ||
1382 | size_t len = snprintf(buf, buflen, "%s", filter->error_buffer); | ||
1383 | |||
1384 | if (len > buflen) | ||
1385 | return -1; | ||
1386 | return 0; | ||
1387 | } | ||
1388 | |||
1389 | return pevent_strerror(filter->pevent, err, buf, buflen); | ||
1390 | } | ||
1391 | |||
1392 | /** | ||
1285 | * pevent_filter_remove_event - remove a filter for an event | 1393 | * pevent_filter_remove_event - remove a filter for an event |
1286 | * @filter: the event filter to remove from | 1394 | * @filter: the event filter to remove from |
1287 | * @event_id: the event to remove a filter for | 1395 | * @event_id: the event to remove a filter for |
@@ -1374,6 +1482,9 @@ static int copy_filter_type(struct event_filter *filter, | |||
1374 | if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) { | 1482 | if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) { |
1375 | /* Add trivial event */ | 1483 | /* Add trivial event */ |
1376 | arg = allocate_arg(); | 1484 | arg = allocate_arg(); |
1485 | if (arg == NULL) | ||
1486 | return -1; | ||
1487 | |||
1377 | arg->type = FILTER_ARG_BOOLEAN; | 1488 | arg->type = FILTER_ARG_BOOLEAN; |
1378 | if (strcmp(str, "TRUE") == 0) | 1489 | if (strcmp(str, "TRUE") == 0) |
1379 | arg->boolean.value = 1; | 1490 | arg->boolean.value = 1; |
@@ -1381,6 +1492,9 @@ static int copy_filter_type(struct event_filter *filter, | |||
1381 | arg->boolean.value = 0; | 1492 | arg->boolean.value = 0; |
1382 | 1493 | ||
1383 | filter_type = add_filter_type(filter, event->id); | 1494 | filter_type = add_filter_type(filter, event->id); |
1495 | if (filter_type == NULL) | ||
1496 | return -1; | ||
1497 | |||
1384 | filter_type->filter = arg; | 1498 | filter_type->filter = arg; |
1385 | 1499 | ||
1386 | free(str); | 1500 | free(str); |
@@ -1482,8 +1596,10 @@ int pevent_update_trivial(struct event_filter *dest, struct event_filter *source | |||
1482 | * @type: remove only true, false, or both | 1596 | * @type: remove only true, false, or both |
1483 | * | 1597 | * |
1484 | * Removes filters that only contain a TRUE or FALES boolean arg. | 1598 | * Removes filters that only contain a TRUE or FALES boolean arg. |
1599 | * | ||
1600 | * Returns 0 on success and -1 if there was a problem. | ||
1485 | */ | 1601 | */ |
1486 | void pevent_filter_clear_trivial(struct event_filter *filter, | 1602 | int pevent_filter_clear_trivial(struct event_filter *filter, |
1487 | enum filter_trivial_type type) | 1603 | enum filter_trivial_type type) |
1488 | { | 1604 | { |
1489 | struct filter_type *filter_type; | 1605 | struct filter_type *filter_type; |
@@ -1492,13 +1608,15 @@ void pevent_filter_clear_trivial(struct event_filter *filter, | |||
1492 | int i; | 1608 | int i; |
1493 | 1609 | ||
1494 | if (!filter->filters) | 1610 | if (!filter->filters) |
1495 | return; | 1611 | return 0; |
1496 | 1612 | ||
1497 | /* | 1613 | /* |
1498 | * Two steps, first get all ids with trivial filters. | 1614 | * Two steps, first get all ids with trivial filters. |
1499 | * then remove those ids. | 1615 | * then remove those ids. |
1500 | */ | 1616 | */ |
1501 | for (i = 0; i < filter->filters; i++) { | 1617 | for (i = 0; i < filter->filters; i++) { |
1618 | int *new_ids; | ||
1619 | |||
1502 | filter_type = &filter->event_filters[i]; | 1620 | filter_type = &filter->event_filters[i]; |
1503 | if (filter_type->filter->type != FILTER_ARG_BOOLEAN) | 1621 | if (filter_type->filter->type != FILTER_ARG_BOOLEAN) |
1504 | continue; | 1622 | continue; |
@@ -1513,19 +1631,24 @@ void pevent_filter_clear_trivial(struct event_filter *filter, | |||
1513 | break; | 1631 | break; |
1514 | } | 1632 | } |
1515 | 1633 | ||
1516 | ids = realloc(ids, sizeof(*ids) * (count + 1)); | 1634 | new_ids = realloc(ids, sizeof(*ids) * (count + 1)); |
1517 | if (!ids) | 1635 | if (!new_ids) { |
1518 | die("Can't allocate ids"); | 1636 | free(ids); |
1637 | return -1; | ||
1638 | } | ||
1639 | |||
1640 | ids = new_ids; | ||
1519 | ids[count++] = filter_type->event_id; | 1641 | ids[count++] = filter_type->event_id; |
1520 | } | 1642 | } |
1521 | 1643 | ||
1522 | if (!count) | 1644 | if (!count) |
1523 | return; | 1645 | return 0; |
1524 | 1646 | ||
1525 | for (i = 0; i < count; i++) | 1647 | for (i = 0; i < count; i++) |
1526 | pevent_filter_remove_event(filter, ids[i]); | 1648 | pevent_filter_remove_event(filter, ids[i]); |
1527 | 1649 | ||
1528 | free(ids); | 1650 | free(ids); |
1651 | return 0; | ||
1529 | } | 1652 | } |
1530 | 1653 | ||
1531 | /** | 1654 | /** |
@@ -1565,8 +1688,8 @@ int pevent_filter_event_has_trivial(struct event_filter *filter, | |||
1565 | } | 1688 | } |
1566 | } | 1689 | } |
1567 | 1690 | ||
1568 | static int test_filter(struct event_format *event, | 1691 | static int test_filter(struct event_format *event, struct filter_arg *arg, |
1569 | struct filter_arg *arg, struct pevent_record *record); | 1692 | struct pevent_record *record, enum pevent_errno *err); |
1570 | 1693 | ||
1571 | static const char * | 1694 | static const char * |
1572 | get_comm(struct event_format *event, struct pevent_record *record) | 1695 | get_comm(struct event_format *event, struct pevent_record *record) |
@@ -1612,15 +1735,24 @@ get_value(struct event_format *event, | |||
1612 | } | 1735 | } |
1613 | 1736 | ||
1614 | static unsigned long long | 1737 | static unsigned long long |
1615 | get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record); | 1738 | get_arg_value(struct event_format *event, struct filter_arg *arg, |
1739 | struct pevent_record *record, enum pevent_errno *err); | ||
1616 | 1740 | ||
1617 | static unsigned long long | 1741 | static unsigned long long |
1618 | get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) | 1742 | get_exp_value(struct event_format *event, struct filter_arg *arg, |
1743 | struct pevent_record *record, enum pevent_errno *err) | ||
1619 | { | 1744 | { |
1620 | unsigned long long lval, rval; | 1745 | unsigned long long lval, rval; |
1621 | 1746 | ||
1622 | lval = get_arg_value(event, arg->exp.left, record); | 1747 | lval = get_arg_value(event, arg->exp.left, record, err); |
1623 | rval = get_arg_value(event, arg->exp.right, record); | 1748 | rval = get_arg_value(event, arg->exp.right, record, err); |
1749 | |||
1750 | if (*err) { | ||
1751 | /* | ||
1752 | * There was an error, no need to process anymore. | ||
1753 | */ | ||
1754 | return 0; | ||
1755 | } | ||
1624 | 1756 | ||
1625 | switch (arg->exp.type) { | 1757 | switch (arg->exp.type) { |
1626 | case FILTER_EXP_ADD: | 1758 | case FILTER_EXP_ADD: |
@@ -1655,39 +1787,51 @@ get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_ | |||
1655 | 1787 | ||
1656 | case FILTER_EXP_NOT: | 1788 | case FILTER_EXP_NOT: |
1657 | default: | 1789 | default: |
1658 | die("error in exp"); | 1790 | if (!*err) |
1791 | *err = PEVENT_ERRNO__INVALID_EXP_TYPE; | ||
1659 | } | 1792 | } |
1660 | return 0; | 1793 | return 0; |
1661 | } | 1794 | } |
1662 | 1795 | ||
1663 | static unsigned long long | 1796 | static unsigned long long |
1664 | get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) | 1797 | get_arg_value(struct event_format *event, struct filter_arg *arg, |
1798 | struct pevent_record *record, enum pevent_errno *err) | ||
1665 | { | 1799 | { |
1666 | switch (arg->type) { | 1800 | switch (arg->type) { |
1667 | case FILTER_ARG_FIELD: | 1801 | case FILTER_ARG_FIELD: |
1668 | return get_value(event, arg->field.field, record); | 1802 | return get_value(event, arg->field.field, record); |
1669 | 1803 | ||
1670 | case FILTER_ARG_VALUE: | 1804 | case FILTER_ARG_VALUE: |
1671 | if (arg->value.type != FILTER_NUMBER) | 1805 | if (arg->value.type != FILTER_NUMBER) { |
1672 | die("must have number field!"); | 1806 | if (!*err) |
1807 | *err = PEVENT_ERRNO__NOT_A_NUMBER; | ||
1808 | } | ||
1673 | return arg->value.val; | 1809 | return arg->value.val; |
1674 | 1810 | ||
1675 | case FILTER_ARG_EXP: | 1811 | case FILTER_ARG_EXP: |
1676 | return get_exp_value(event, arg, record); | 1812 | return get_exp_value(event, arg, record, err); |
1677 | 1813 | ||
1678 | default: | 1814 | default: |
1679 | die("oops in filter"); | 1815 | if (!*err) |
1816 | *err = PEVENT_ERRNO__INVALID_ARG_TYPE; | ||
1680 | } | 1817 | } |
1681 | return 0; | 1818 | return 0; |
1682 | } | 1819 | } |
1683 | 1820 | ||
1684 | static int test_num(struct event_format *event, | 1821 | static int test_num(struct event_format *event, struct filter_arg *arg, |
1685 | struct filter_arg *arg, struct pevent_record *record) | 1822 | struct pevent_record *record, enum pevent_errno *err) |
1686 | { | 1823 | { |
1687 | unsigned long long lval, rval; | 1824 | unsigned long long lval, rval; |
1688 | 1825 | ||
1689 | lval = get_arg_value(event, arg->num.left, record); | 1826 | lval = get_arg_value(event, arg->num.left, record, err); |
1690 | rval = get_arg_value(event, arg->num.right, record); | 1827 | rval = get_arg_value(event, arg->num.right, record, err); |
1828 | |||
1829 | if (*err) { | ||
1830 | /* | ||
1831 | * There was an error, no need to process anymore. | ||
1832 | */ | ||
1833 | return 0; | ||
1834 | } | ||
1691 | 1835 | ||
1692 | switch (arg->num.type) { | 1836 | switch (arg->num.type) { |
1693 | case FILTER_CMP_EQ: | 1837 | case FILTER_CMP_EQ: |
@@ -1709,7 +1853,8 @@ static int test_num(struct event_format *event, | |||
1709 | return lval <= rval; | 1853 | return lval <= rval; |
1710 | 1854 | ||
1711 | default: | 1855 | default: |
1712 | /* ?? */ | 1856 | if (!*err) |
1857 | *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; | ||
1713 | return 0; | 1858 | return 0; |
1714 | } | 1859 | } |
1715 | } | 1860 | } |
@@ -1756,8 +1901,8 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r | |||
1756 | return val; | 1901 | return val; |
1757 | } | 1902 | } |
1758 | 1903 | ||
1759 | static int test_str(struct event_format *event, | 1904 | static int test_str(struct event_format *event, struct filter_arg *arg, |
1760 | struct filter_arg *arg, struct pevent_record *record) | 1905 | struct pevent_record *record, enum pevent_errno *err) |
1761 | { | 1906 | { |
1762 | const char *val; | 1907 | const char *val; |
1763 | 1908 | ||
@@ -1781,48 +1926,57 @@ static int test_str(struct event_format *event, | |||
1781 | return regexec(&arg->str.reg, val, 0, NULL, 0); | 1926 | return regexec(&arg->str.reg, val, 0, NULL, 0); |
1782 | 1927 | ||
1783 | default: | 1928 | default: |
1784 | /* ?? */ | 1929 | if (!*err) |
1930 | *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP; | ||
1785 | return 0; | 1931 | return 0; |
1786 | } | 1932 | } |
1787 | } | 1933 | } |
1788 | 1934 | ||
1789 | static int test_op(struct event_format *event, | 1935 | static int test_op(struct event_format *event, struct filter_arg *arg, |
1790 | struct filter_arg *arg, struct pevent_record *record) | 1936 | struct pevent_record *record, enum pevent_errno *err) |
1791 | { | 1937 | { |
1792 | switch (arg->op.type) { | 1938 | switch (arg->op.type) { |
1793 | case FILTER_OP_AND: | 1939 | case FILTER_OP_AND: |
1794 | return test_filter(event, arg->op.left, record) && | 1940 | return test_filter(event, arg->op.left, record, err) && |
1795 | test_filter(event, arg->op.right, record); | 1941 | test_filter(event, arg->op.right, record, err); |
1796 | 1942 | ||
1797 | case FILTER_OP_OR: | 1943 | case FILTER_OP_OR: |
1798 | return test_filter(event, arg->op.left, record) || | 1944 | return test_filter(event, arg->op.left, record, err) || |
1799 | test_filter(event, arg->op.right, record); | 1945 | test_filter(event, arg->op.right, record, err); |
1800 | 1946 | ||
1801 | case FILTER_OP_NOT: | 1947 | case FILTER_OP_NOT: |
1802 | return !test_filter(event, arg->op.right, record); | 1948 | return !test_filter(event, arg->op.right, record, err); |
1803 | 1949 | ||
1804 | default: | 1950 | default: |
1805 | /* ?? */ | 1951 | if (!*err) |
1952 | *err = PEVENT_ERRNO__INVALID_OP_TYPE; | ||
1806 | return 0; | 1953 | return 0; |
1807 | } | 1954 | } |
1808 | } | 1955 | } |
1809 | 1956 | ||
1810 | static int test_filter(struct event_format *event, | 1957 | static int test_filter(struct event_format *event, struct filter_arg *arg, |
1811 | struct filter_arg *arg, struct pevent_record *record) | 1958 | struct pevent_record *record, enum pevent_errno *err) |
1812 | { | 1959 | { |
1960 | if (*err) { | ||
1961 | /* | ||
1962 | * There was an error, no need to process anymore. | ||
1963 | */ | ||
1964 | return 0; | ||
1965 | } | ||
1966 | |||
1813 | switch (arg->type) { | 1967 | switch (arg->type) { |
1814 | case FILTER_ARG_BOOLEAN: | 1968 | case FILTER_ARG_BOOLEAN: |
1815 | /* easy case */ | 1969 | /* easy case */ |
1816 | return arg->boolean.value; | 1970 | return arg->boolean.value; |
1817 | 1971 | ||
1818 | case FILTER_ARG_OP: | 1972 | case FILTER_ARG_OP: |
1819 | return test_op(event, arg, record); | 1973 | return test_op(event, arg, record, err); |
1820 | 1974 | ||
1821 | case FILTER_ARG_NUM: | 1975 | case FILTER_ARG_NUM: |
1822 | return test_num(event, arg, record); | 1976 | return test_num(event, arg, record, err); |
1823 | 1977 | ||
1824 | case FILTER_ARG_STR: | 1978 | case FILTER_ARG_STR: |
1825 | return test_str(event, arg, record); | 1979 | return test_str(event, arg, record, err); |
1826 | 1980 | ||
1827 | case FILTER_ARG_EXP: | 1981 | case FILTER_ARG_EXP: |
1828 | case FILTER_ARG_VALUE: | 1982 | case FILTER_ARG_VALUE: |
@@ -1831,11 +1985,11 @@ static int test_filter(struct event_format *event, | |||
1831 | * Expressions, fields and values evaluate | 1985 | * Expressions, fields and values evaluate |
1832 | * to true if they return non zero | 1986 | * to true if they return non zero |
1833 | */ | 1987 | */ |
1834 | return !!get_arg_value(event, arg, record); | 1988 | return !!get_arg_value(event, arg, record, err); |
1835 | 1989 | ||
1836 | default: | 1990 | default: |
1837 | die("oops!"); | 1991 | if (!*err) |
1838 | /* ?? */ | 1992 | *err = PEVENT_ERRNO__INVALID_ARG_TYPE; |
1839 | return 0; | 1993 | return 0; |
1840 | } | 1994 | } |
1841 | } | 1995 | } |
@@ -1848,8 +2002,7 @@ static int test_filter(struct event_format *event, | |||
1848 | * Returns 1 if filter found for @event_id | 2002 | * Returns 1 if filter found for @event_id |
1849 | * otherwise 0; | 2003 | * otherwise 0; |
1850 | */ | 2004 | */ |
1851 | int pevent_event_filtered(struct event_filter *filter, | 2005 | int pevent_event_filtered(struct event_filter *filter, int event_id) |
1852 | int event_id) | ||
1853 | { | 2006 | { |
1854 | struct filter_type *filter_type; | 2007 | struct filter_type *filter_type; |
1855 | 2008 | ||
@@ -1866,31 +2019,38 @@ int pevent_event_filtered(struct event_filter *filter, | |||
1866 | * @filter: filter struct with filter information | 2019 | * @filter: filter struct with filter information |
1867 | * @record: the record to test against the filter | 2020 | * @record: the record to test against the filter |
1868 | * | 2021 | * |
1869 | * Returns: | 2022 | * Returns: match result or error code (prefixed with PEVENT_ERRNO__) |
1870 | * 1 - filter found for event and @record matches | 2023 | * FILTER_MATCH - filter found for event and @record matches |
1871 | * 0 - filter found for event and @record does not match | 2024 | * FILTER_MISS - filter found for event and @record does not match |
1872 | * -1 - no filter found for @record's event | 2025 | * FILTER_NOT_FOUND - no filter found for @record's event |
1873 | * -2 - if no filters exist | 2026 | * NO_FILTER - if no filters exist |
2027 | * otherwise - error occurred during test | ||
1874 | */ | 2028 | */ |
1875 | int pevent_filter_match(struct event_filter *filter, | 2029 | enum pevent_errno pevent_filter_match(struct event_filter *filter, |
1876 | struct pevent_record *record) | 2030 | struct pevent_record *record) |
1877 | { | 2031 | { |
1878 | struct pevent *pevent = filter->pevent; | 2032 | struct pevent *pevent = filter->pevent; |
1879 | struct filter_type *filter_type; | 2033 | struct filter_type *filter_type; |
1880 | int event_id; | 2034 | int event_id; |
2035 | int ret; | ||
2036 | enum pevent_errno err = 0; | ||
2037 | |||
2038 | filter_init_error_buf(filter); | ||
1881 | 2039 | ||
1882 | if (!filter->filters) | 2040 | if (!filter->filters) |
1883 | return FILTER_NONE; | 2041 | return PEVENT_ERRNO__NO_FILTER; |
1884 | 2042 | ||
1885 | event_id = pevent_data_type(pevent, record); | 2043 | event_id = pevent_data_type(pevent, record); |
1886 | 2044 | ||
1887 | filter_type = find_filter_type(filter, event_id); | 2045 | filter_type = find_filter_type(filter, event_id); |
1888 | |||
1889 | if (!filter_type) | 2046 | if (!filter_type) |
1890 | return FILTER_NOEXIST; | 2047 | return PEVENT_ERRNO__FILTER_NOT_FOUND; |
2048 | |||
2049 | ret = test_filter(filter_type->event, filter_type->filter, record, &err); | ||
2050 | if (err) | ||
2051 | return err; | ||
1891 | 2052 | ||
1892 | return test_filter(filter_type->event, filter_type->filter, record) ? | 2053 | return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS; |
1893 | FILTER_MATCH : FILTER_MISS; | ||
1894 | } | 2054 | } |
1895 | 2055 | ||
1896 | static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) | 2056 | static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) |
@@ -1902,7 +2062,6 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
1902 | int left_val = -1; | 2062 | int left_val = -1; |
1903 | int right_val = -1; | 2063 | int right_val = -1; |
1904 | int val; | 2064 | int val; |
1905 | int len; | ||
1906 | 2065 | ||
1907 | switch (arg->op.type) { | 2066 | switch (arg->op.type) { |
1908 | case FILTER_OP_AND: | 2067 | case FILTER_OP_AND: |
@@ -1949,11 +2108,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
1949 | default: | 2108 | default: |
1950 | break; | 2109 | break; |
1951 | } | 2110 | } |
1952 | str = malloc_or_die(6); | 2111 | asprintf(&str, val ? "TRUE" : "FALSE"); |
1953 | if (val) | ||
1954 | strcpy(str, "TRUE"); | ||
1955 | else | ||
1956 | strcpy(str, "FALSE"); | ||
1957 | break; | 2112 | break; |
1958 | } | 2113 | } |
1959 | } | 2114 | } |
@@ -1971,10 +2126,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
1971 | break; | 2126 | break; |
1972 | } | 2127 | } |
1973 | 2128 | ||
1974 | len = strlen(left) + strlen(right) + strlen(op) + 10; | 2129 | asprintf(&str, "(%s) %s (%s)", left, op, right); |
1975 | str = malloc_or_die(len); | ||
1976 | snprintf(str, len, "(%s) %s (%s)", | ||
1977 | left, op, right); | ||
1978 | break; | 2130 | break; |
1979 | 2131 | ||
1980 | case FILTER_OP_NOT: | 2132 | case FILTER_OP_NOT: |
@@ -1990,16 +2142,10 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
1990 | right_val = 0; | 2142 | right_val = 0; |
1991 | if (right_val >= 0) { | 2143 | if (right_val >= 0) { |
1992 | /* just return the opposite */ | 2144 | /* just return the opposite */ |
1993 | str = malloc_or_die(6); | 2145 | asprintf(&str, right_val ? "FALSE" : "TRUE"); |
1994 | if (right_val) | ||
1995 | strcpy(str, "FALSE"); | ||
1996 | else | ||
1997 | strcpy(str, "TRUE"); | ||
1998 | break; | 2146 | break; |
1999 | } | 2147 | } |
2000 | len = strlen(right) + strlen(op) + 3; | 2148 | asprintf(&str, "%s(%s)", op, right); |
2001 | str = malloc_or_die(len); | ||
2002 | snprintf(str, len, "%s(%s)", op, right); | ||
2003 | break; | 2149 | break; |
2004 | 2150 | ||
2005 | default: | 2151 | default: |
@@ -2013,11 +2159,9 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2013 | 2159 | ||
2014 | static char *val_to_str(struct event_filter *filter, struct filter_arg *arg) | 2160 | static char *val_to_str(struct event_filter *filter, struct filter_arg *arg) |
2015 | { | 2161 | { |
2016 | char *str; | 2162 | char *str = NULL; |
2017 | |||
2018 | str = malloc_or_die(30); | ||
2019 | 2163 | ||
2020 | snprintf(str, 30, "%lld", arg->value.val); | 2164 | asprintf(&str, "%lld", arg->value.val); |
2021 | 2165 | ||
2022 | return str; | 2166 | return str; |
2023 | } | 2167 | } |
@@ -2033,7 +2177,6 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2033 | char *rstr; | 2177 | char *rstr; |
2034 | char *op; | 2178 | char *op; |
2035 | char *str = NULL; | 2179 | char *str = NULL; |
2036 | int len; | ||
2037 | 2180 | ||
2038 | lstr = arg_to_str(filter, arg->exp.left); | 2181 | lstr = arg_to_str(filter, arg->exp.left); |
2039 | rstr = arg_to_str(filter, arg->exp.right); | 2182 | rstr = arg_to_str(filter, arg->exp.right); |
@@ -2072,12 +2215,11 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2072 | op = "^"; | 2215 | op = "^"; |
2073 | break; | 2216 | break; |
2074 | default: | 2217 | default: |
2075 | die("oops in exp"); | 2218 | op = "[ERROR IN EXPRESSION TYPE]"; |
2219 | break; | ||
2076 | } | 2220 | } |
2077 | 2221 | ||
2078 | len = strlen(op) + strlen(lstr) + strlen(rstr) + 4; | 2222 | asprintf(&str, "%s %s %s", lstr, op, rstr); |
2079 | str = malloc_or_die(len); | ||
2080 | snprintf(str, len, "%s %s %s", lstr, op, rstr); | ||
2081 | out: | 2223 | out: |
2082 | free(lstr); | 2224 | free(lstr); |
2083 | free(rstr); | 2225 | free(rstr); |
@@ -2091,7 +2233,6 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2091 | char *rstr; | 2233 | char *rstr; |
2092 | char *str = NULL; | 2234 | char *str = NULL; |
2093 | char *op = NULL; | 2235 | char *op = NULL; |
2094 | int len; | ||
2095 | 2236 | ||
2096 | lstr = arg_to_str(filter, arg->num.left); | 2237 | lstr = arg_to_str(filter, arg->num.left); |
2097 | rstr = arg_to_str(filter, arg->num.right); | 2238 | rstr = arg_to_str(filter, arg->num.right); |
@@ -2122,10 +2263,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2122 | if (!op) | 2263 | if (!op) |
2123 | op = "<="; | 2264 | op = "<="; |
2124 | 2265 | ||
2125 | len = strlen(lstr) + strlen(op) + strlen(rstr) + 4; | 2266 | asprintf(&str, "%s %s %s", lstr, op, rstr); |
2126 | str = malloc_or_die(len); | ||
2127 | sprintf(str, "%s %s %s", lstr, op, rstr); | ||
2128 | |||
2129 | break; | 2267 | break; |
2130 | 2268 | ||
2131 | default: | 2269 | default: |
@@ -2143,7 +2281,6 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2143 | { | 2281 | { |
2144 | char *str = NULL; | 2282 | char *str = NULL; |
2145 | char *op = NULL; | 2283 | char *op = NULL; |
2146 | int len; | ||
2147 | 2284 | ||
2148 | switch (arg->str.type) { | 2285 | switch (arg->str.type) { |
2149 | case FILTER_CMP_MATCH: | 2286 | case FILTER_CMP_MATCH: |
@@ -2161,12 +2298,8 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2161 | if (!op) | 2298 | if (!op) |
2162 | op = "!~"; | 2299 | op = "!~"; |
2163 | 2300 | ||
2164 | len = strlen(arg->str.field->name) + strlen(op) + | 2301 | asprintf(&str, "%s %s \"%s\"", |
2165 | strlen(arg->str.val) + 6; | 2302 | arg->str.field->name, op, arg->str.val); |
2166 | str = malloc_or_die(len); | ||
2167 | snprintf(str, len, "%s %s \"%s\"", | ||
2168 | arg->str.field->name, | ||
2169 | op, arg->str.val); | ||
2170 | break; | 2303 | break; |
2171 | 2304 | ||
2172 | default: | 2305 | default: |
@@ -2178,15 +2311,11 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2178 | 2311 | ||
2179 | static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) | 2312 | static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) |
2180 | { | 2313 | { |
2181 | char *str; | 2314 | char *str = NULL; |
2182 | 2315 | ||
2183 | switch (arg->type) { | 2316 | switch (arg->type) { |
2184 | case FILTER_ARG_BOOLEAN: | 2317 | case FILTER_ARG_BOOLEAN: |
2185 | str = malloc_or_die(6); | 2318 | asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE"); |
2186 | if (arg->boolean.value) | ||
2187 | strcpy(str, "TRUE"); | ||
2188 | else | ||
2189 | strcpy(str, "FALSE"); | ||
2190 | return str; | 2319 | return str; |
2191 | 2320 | ||
2192 | case FILTER_ARG_OP: | 2321 | case FILTER_ARG_OP: |
@@ -2221,7 +2350,7 @@ static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2221 | * | 2350 | * |
2222 | * Returns a string that displays the filter contents. | 2351 | * Returns a string that displays the filter contents. |
2223 | * This string must be freed with free(str). | 2352 | * This string must be freed with free(str). |
2224 | * NULL is returned if no filter is found. | 2353 | * NULL is returned if no filter is found or allocation failed. |
2225 | */ | 2354 | */ |
2226 | char * | 2355 | char * |
2227 | pevent_filter_make_string(struct event_filter *filter, int event_id) | 2356 | pevent_filter_make_string(struct event_filter *filter, int event_id) |
diff --git a/tools/lib/traceevent/parse-utils.c b/tools/lib/traceevent/parse-utils.c index bba701cf10e6..eda07fa31dca 100644 --- a/tools/lib/traceevent/parse-utils.c +++ b/tools/lib/traceevent/parse-utils.c | |||
@@ -25,40 +25,6 @@ | |||
25 | 25 | ||
26 | #define __weak __attribute__((weak)) | 26 | #define __weak __attribute__((weak)) |
27 | 27 | ||
28 | void __vdie(const char *fmt, va_list ap) | ||
29 | { | ||
30 | int ret = errno; | ||
31 | |||
32 | if (errno) | ||
33 | perror("trace-cmd"); | ||
34 | else | ||
35 | ret = -1; | ||
36 | |||
37 | fprintf(stderr, " "); | ||
38 | vfprintf(stderr, fmt, ap); | ||
39 | |||
40 | fprintf(stderr, "\n"); | ||
41 | exit(ret); | ||
42 | } | ||
43 | |||
44 | void __die(const char *fmt, ...) | ||
45 | { | ||
46 | va_list ap; | ||
47 | |||
48 | va_start(ap, fmt); | ||
49 | __vdie(fmt, ap); | ||
50 | va_end(ap); | ||
51 | } | ||
52 | |||
53 | void __weak die(const char *fmt, ...) | ||
54 | { | ||
55 | va_list ap; | ||
56 | |||
57 | va_start(ap, fmt); | ||
58 | __vdie(fmt, ap); | ||
59 | va_end(ap); | ||
60 | } | ||
61 | |||
62 | void __vwarning(const char *fmt, va_list ap) | 28 | void __vwarning(const char *fmt, va_list ap) |
63 | { | 29 | { |
64 | if (errno) | 30 | if (errno) |
@@ -117,13 +83,3 @@ void __weak pr_stat(const char *fmt, ...) | |||
117 | __vpr_stat(fmt, ap); | 83 | __vpr_stat(fmt, ap); |
118 | va_end(ap); | 84 | va_end(ap); |
119 | } | 85 | } |
120 | |||
121 | void __weak *malloc_or_die(unsigned int size) | ||
122 | { | ||
123 | void *data; | ||
124 | |||
125 | data = malloc(size); | ||
126 | if (!data) | ||
127 | die("malloc"); | ||
128 | return data; | ||
129 | } | ||
diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c new file mode 100644 index 000000000000..c066b25905f8 --- /dev/null +++ b/tools/lib/traceevent/plugin_cfg80211.c | |||
@@ -0,0 +1,30 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include <inttypes.h> | ||
4 | #include <endian.h> | ||
5 | #include "event-parse.h" | ||
6 | |||
7 | static unsigned long long | ||
8 | process___le16_to_cpup(struct trace_seq *s, | ||
9 | unsigned long long *args) | ||
10 | { | ||
11 | uint16_t *val = (uint16_t *) (unsigned long) args[0]; | ||
12 | return val ? (long long) le16toh(*val) : 0; | ||
13 | } | ||
14 | |||
15 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
16 | { | ||
17 | pevent_register_print_function(pevent, | ||
18 | process___le16_to_cpup, | ||
19 | PEVENT_FUNC_ARG_INT, | ||
20 | "__le16_to_cpup", | ||
21 | PEVENT_FUNC_ARG_PTR, | ||
22 | PEVENT_FUNC_ARG_VOID); | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
27 | { | ||
28 | pevent_unregister_print_function(pevent, process___le16_to_cpup, | ||
29 | "__le16_to_cpup"); | ||
30 | } | ||
diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c new file mode 100644 index 000000000000..80ba4ff1fe84 --- /dev/null +++ b/tools/lib/traceevent/plugin_function.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | ||
3 | * | ||
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * version 2.1 of the License (not later!) | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this program; if not, see <http://www.gnu.org/licenses> | ||
17 | * | ||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | */ | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | |||
24 | #include "event-parse.h" | ||
25 | #include "event-utils.h" | ||
26 | |||
27 | static struct func_stack { | ||
28 | int size; | ||
29 | char **stack; | ||
30 | } *fstack; | ||
31 | |||
32 | static int cpus = -1; | ||
33 | |||
34 | #define STK_BLK 10 | ||
35 | |||
36 | static void add_child(struct func_stack *stack, const char *child, int pos) | ||
37 | { | ||
38 | int i; | ||
39 | |||
40 | if (!child) | ||
41 | return; | ||
42 | |||
43 | if (pos < stack->size) | ||
44 | free(stack->stack[pos]); | ||
45 | else { | ||
46 | char **ptr; | ||
47 | |||
48 | ptr = realloc(stack->stack, sizeof(char *) * | ||
49 | (stack->size + STK_BLK)); | ||
50 | if (!ptr) { | ||
51 | warning("could not allocate plugin memory\n"); | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | stack->stack = ptr; | ||
56 | |||
57 | for (i = stack->size; i < stack->size + STK_BLK; i++) | ||
58 | stack->stack[i] = NULL; | ||
59 | stack->size += STK_BLK; | ||
60 | } | ||
61 | |||
62 | stack->stack[pos] = strdup(child); | ||
63 | } | ||
64 | |||
65 | static int add_and_get_index(const char *parent, const char *child, int cpu) | ||
66 | { | ||
67 | int i; | ||
68 | |||
69 | if (cpu < 0) | ||
70 | return 0; | ||
71 | |||
72 | if (cpu > cpus) { | ||
73 | struct func_stack *ptr; | ||
74 | |||
75 | ptr = realloc(fstack, sizeof(*fstack) * (cpu + 1)); | ||
76 | if (!ptr) { | ||
77 | warning("could not allocate plugin memory\n"); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | fstack = ptr; | ||
82 | |||
83 | /* Account for holes in the cpu count */ | ||
84 | for (i = cpus + 1; i <= cpu; i++) | ||
85 | memset(&fstack[i], 0, sizeof(fstack[i])); | ||
86 | cpus = cpu; | ||
87 | } | ||
88 | |||
89 | for (i = 0; i < fstack[cpu].size && fstack[cpu].stack[i]; i++) { | ||
90 | if (strcmp(parent, fstack[cpu].stack[i]) == 0) { | ||
91 | add_child(&fstack[cpu], child, i+1); | ||
92 | return i; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /* Not found */ | ||
97 | add_child(&fstack[cpu], parent, 0); | ||
98 | add_child(&fstack[cpu], child, 1); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static int function_handler(struct trace_seq *s, struct pevent_record *record, | ||
103 | struct event_format *event, void *context) | ||
104 | { | ||
105 | struct pevent *pevent = event->pevent; | ||
106 | unsigned long long function; | ||
107 | unsigned long long pfunction; | ||
108 | const char *func; | ||
109 | const char *parent; | ||
110 | int index; | ||
111 | |||
112 | if (pevent_get_field_val(s, event, "ip", record, &function, 1)) | ||
113 | return trace_seq_putc(s, '!'); | ||
114 | |||
115 | func = pevent_find_function(pevent, function); | ||
116 | |||
117 | if (pevent_get_field_val(s, event, "parent_ip", record, &pfunction, 1)) | ||
118 | return trace_seq_putc(s, '!'); | ||
119 | |||
120 | parent = pevent_find_function(pevent, pfunction); | ||
121 | |||
122 | index = add_and_get_index(parent, func, record->cpu); | ||
123 | |||
124 | trace_seq_printf(s, "%*s", index*3, ""); | ||
125 | |||
126 | if (func) | ||
127 | trace_seq_printf(s, "%s", func); | ||
128 | else | ||
129 | trace_seq_printf(s, "0x%llx", function); | ||
130 | |||
131 | trace_seq_printf(s, " <-- "); | ||
132 | if (parent) | ||
133 | trace_seq_printf(s, "%s", parent); | ||
134 | else | ||
135 | trace_seq_printf(s, "0x%llx", pfunction); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
141 | { | ||
142 | pevent_register_event_handler(pevent, -1, "ftrace", "function", | ||
143 | function_handler, NULL); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
148 | { | ||
149 | int i, x; | ||
150 | |||
151 | pevent_unregister_event_handler(pevent, -1, "ftrace", "function", | ||
152 | function_handler, NULL); | ||
153 | |||
154 | for (i = 0; i <= cpus; i++) { | ||
155 | for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++) | ||
156 | free(fstack[i].stack[x]); | ||
157 | free(fstack[i].stack); | ||
158 | } | ||
159 | |||
160 | free(fstack); | ||
161 | fstack = NULL; | ||
162 | cpus = -1; | ||
163 | } | ||
diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c new file mode 100644 index 000000000000..12bf14cc1152 --- /dev/null +++ b/tools/lib/traceevent/plugin_hrtimer.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | ||
3 | * Copyright (C) 2009 Johannes Berg <johannes@sipsolutions.net> | ||
4 | * | ||
5 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; | ||
9 | * version 2.1 of the License (not later!) | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with this program; if not, see <http://www.gnu.org/licenses> | ||
18 | * | ||
19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
20 | */ | ||
21 | #include <stdio.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | #include "event-parse.h" | ||
26 | |||
27 | static int timer_expire_handler(struct trace_seq *s, | ||
28 | struct pevent_record *record, | ||
29 | struct event_format *event, void *context) | ||
30 | { | ||
31 | trace_seq_printf(s, "hrtimer="); | ||
32 | |||
33 | if (pevent_print_num_field(s, "0x%llx", event, "timer", | ||
34 | record, 0) == -1) | ||
35 | pevent_print_num_field(s, "0x%llx", event, "hrtimer", | ||
36 | record, 1); | ||
37 | |||
38 | trace_seq_printf(s, " now="); | ||
39 | |||
40 | pevent_print_num_field(s, "%llu", event, "now", record, 1); | ||
41 | |||
42 | pevent_print_func_field(s, " function=%s", event, "function", | ||
43 | record, 0); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static int timer_start_handler(struct trace_seq *s, | ||
48 | struct pevent_record *record, | ||
49 | struct event_format *event, void *context) | ||
50 | { | ||
51 | trace_seq_printf(s, "hrtimer="); | ||
52 | |||
53 | if (pevent_print_num_field(s, "0x%llx", event, "timer", | ||
54 | record, 0) == -1) | ||
55 | pevent_print_num_field(s, "0x%llx", event, "hrtimer", | ||
56 | record, 1); | ||
57 | |||
58 | pevent_print_func_field(s, " function=%s", event, "function", | ||
59 | record, 0); | ||
60 | |||
61 | trace_seq_printf(s, " expires="); | ||
62 | pevent_print_num_field(s, "%llu", event, "expires", record, 1); | ||
63 | |||
64 | trace_seq_printf(s, " softexpires="); | ||
65 | pevent_print_num_field(s, "%llu", event, "softexpires", record, 1); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
70 | { | ||
71 | pevent_register_event_handler(pevent, -1, | ||
72 | "timer", "hrtimer_expire_entry", | ||
73 | timer_expire_handler, NULL); | ||
74 | |||
75 | pevent_register_event_handler(pevent, -1, "timer", "hrtimer_start", | ||
76 | timer_start_handler, NULL); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
81 | { | ||
82 | pevent_unregister_event_handler(pevent, -1, | ||
83 | "timer", "hrtimer_expire_entry", | ||
84 | timer_expire_handler, NULL); | ||
85 | |||
86 | pevent_unregister_event_handler(pevent, -1, "timer", "hrtimer_start", | ||
87 | timer_start_handler, NULL); | ||
88 | } | ||
diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c new file mode 100644 index 000000000000..0db714c721be --- /dev/null +++ b/tools/lib/traceevent/plugin_jbd2.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | ||
3 | * | ||
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * version 2.1 of the License (not later!) | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this program; if not, see <http://www.gnu.org/licenses> | ||
17 | * | ||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | */ | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | |||
24 | #include "event-parse.h" | ||
25 | |||
26 | #define MINORBITS 20 | ||
27 | #define MINORMASK ((1U << MINORBITS) - 1) | ||
28 | |||
29 | #define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) | ||
30 | #define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) | ||
31 | |||
32 | static unsigned long long | ||
33 | process_jbd2_dev_to_name(struct trace_seq *s, | ||
34 | unsigned long long *args) | ||
35 | { | ||
36 | unsigned int dev = args[0]; | ||
37 | |||
38 | trace_seq_printf(s, "%d:%d", MAJOR(dev), MINOR(dev)); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static unsigned long long | ||
43 | process_jiffies_to_msecs(struct trace_seq *s, | ||
44 | unsigned long long *args) | ||
45 | { | ||
46 | unsigned long long jiffies = args[0]; | ||
47 | |||
48 | trace_seq_printf(s, "%lld", jiffies); | ||
49 | return jiffies; | ||
50 | } | ||
51 | |||
52 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
53 | { | ||
54 | pevent_register_print_function(pevent, | ||
55 | process_jbd2_dev_to_name, | ||
56 | PEVENT_FUNC_ARG_STRING, | ||
57 | "jbd2_dev_to_name", | ||
58 | PEVENT_FUNC_ARG_INT, | ||
59 | PEVENT_FUNC_ARG_VOID); | ||
60 | |||
61 | pevent_register_print_function(pevent, | ||
62 | process_jiffies_to_msecs, | ||
63 | PEVENT_FUNC_ARG_LONG, | ||
64 | "jiffies_to_msecs", | ||
65 | PEVENT_FUNC_ARG_LONG, | ||
66 | PEVENT_FUNC_ARG_VOID); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
71 | { | ||
72 | pevent_unregister_print_function(pevent, process_jbd2_dev_to_name, | ||
73 | "jbd2_dev_to_name"); | ||
74 | |||
75 | pevent_unregister_print_function(pevent, process_jiffies_to_msecs, | ||
76 | "jiffies_to_msecs"); | ||
77 | } | ||
diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c new file mode 100644 index 000000000000..70650ff48d78 --- /dev/null +++ b/tools/lib/traceevent/plugin_kmem.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | ||
3 | * | ||
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * version 2.1 of the License (not later!) | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this program; if not, see <http://www.gnu.org/licenses> | ||
17 | * | ||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | */ | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | |||
24 | #include "event-parse.h" | ||
25 | |||
26 | static int call_site_handler(struct trace_seq *s, struct pevent_record *record, | ||
27 | struct event_format *event, void *context) | ||
28 | { | ||
29 | struct format_field *field; | ||
30 | unsigned long long val, addr; | ||
31 | void *data = record->data; | ||
32 | const char *func; | ||
33 | |||
34 | field = pevent_find_field(event, "call_site"); | ||
35 | if (!field) | ||
36 | return 1; | ||
37 | |||
38 | if (pevent_read_number_field(field, data, &val)) | ||
39 | return 1; | ||
40 | |||
41 | func = pevent_find_function(event->pevent, val); | ||
42 | if (!func) | ||
43 | return 1; | ||
44 | |||
45 | addr = pevent_find_function_address(event->pevent, val); | ||
46 | |||
47 | trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr)); | ||
48 | return 1; | ||
49 | } | ||
50 | |||
51 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
52 | { | ||
53 | pevent_register_event_handler(pevent, -1, "kmem", "kfree", | ||
54 | call_site_handler, NULL); | ||
55 | |||
56 | pevent_register_event_handler(pevent, -1, "kmem", "kmalloc", | ||
57 | call_site_handler, NULL); | ||
58 | |||
59 | pevent_register_event_handler(pevent, -1, "kmem", "kmalloc_node", | ||
60 | call_site_handler, NULL); | ||
61 | |||
62 | pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_alloc", | ||
63 | call_site_handler, NULL); | ||
64 | |||
65 | pevent_register_event_handler(pevent, -1, "kmem", | ||
66 | "kmem_cache_alloc_node", | ||
67 | call_site_handler, NULL); | ||
68 | |||
69 | pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_free", | ||
70 | call_site_handler, NULL); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
75 | { | ||
76 | pevent_unregister_event_handler(pevent, -1, "kmem", "kfree", | ||
77 | call_site_handler, NULL); | ||
78 | |||
79 | pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc", | ||
80 | call_site_handler, NULL); | ||
81 | |||
82 | pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc_node", | ||
83 | call_site_handler, NULL); | ||
84 | |||
85 | pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_alloc", | ||
86 | call_site_handler, NULL); | ||
87 | |||
88 | pevent_unregister_event_handler(pevent, -1, "kmem", | ||
89 | "kmem_cache_alloc_node", | ||
90 | call_site_handler, NULL); | ||
91 | |||
92 | pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_free", | ||
93 | call_site_handler, NULL); | ||
94 | } | ||
diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c new file mode 100644 index 000000000000..9e0e8c61b43b --- /dev/null +++ b/tools/lib/traceevent/plugin_kvm.c | |||
@@ -0,0 +1,465 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | ||
3 | * | ||
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * version 2.1 of the License (not later!) | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this program; if not, see <http://www.gnu.org/licenses> | ||
17 | * | ||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | */ | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | #include <stdint.h> | ||
24 | |||
25 | #include "event-parse.h" | ||
26 | |||
27 | #ifdef HAVE_UDIS86 | ||
28 | |||
29 | #include <udis86.h> | ||
30 | |||
31 | static ud_t ud; | ||
32 | |||
33 | static void init_disassembler(void) | ||
34 | { | ||
35 | ud_init(&ud); | ||
36 | ud_set_syntax(&ud, UD_SYN_ATT); | ||
37 | } | ||
38 | |||
39 | static const char *disassemble(unsigned char *insn, int len, uint64_t rip, | ||
40 | int cr0_pe, int eflags_vm, | ||
41 | int cs_d, int cs_l) | ||
42 | { | ||
43 | int mode; | ||
44 | |||
45 | if (!cr0_pe) | ||
46 | mode = 16; | ||
47 | else if (eflags_vm) | ||
48 | mode = 16; | ||
49 | else if (cs_l) | ||
50 | mode = 64; | ||
51 | else if (cs_d) | ||
52 | mode = 32; | ||
53 | else | ||
54 | mode = 16; | ||
55 | |||
56 | ud_set_pc(&ud, rip); | ||
57 | ud_set_mode(&ud, mode); | ||
58 | ud_set_input_buffer(&ud, insn, len); | ||
59 | ud_disassemble(&ud); | ||
60 | return ud_insn_asm(&ud); | ||
61 | } | ||
62 | |||
63 | #else | ||
64 | |||
65 | static void init_disassembler(void) | ||
66 | { | ||
67 | } | ||
68 | |||
69 | static const char *disassemble(unsigned char *insn, int len, uint64_t rip, | ||
70 | int cr0_pe, int eflags_vm, | ||
71 | int cs_d, int cs_l) | ||
72 | { | ||
73 | static char out[15*3+1]; | ||
74 | int i; | ||
75 | |||
76 | for (i = 0; i < len; ++i) | ||
77 | sprintf(out + i * 3, "%02x ", insn[i]); | ||
78 | out[len*3-1] = '\0'; | ||
79 | return out; | ||
80 | } | ||
81 | |||
82 | #endif | ||
83 | |||
84 | |||
85 | #define VMX_EXIT_REASONS \ | ||
86 | _ER(EXCEPTION_NMI, 0) \ | ||
87 | _ER(EXTERNAL_INTERRUPT, 1) \ | ||
88 | _ER(TRIPLE_FAULT, 2) \ | ||
89 | _ER(PENDING_INTERRUPT, 7) \ | ||
90 | _ER(NMI_WINDOW, 8) \ | ||
91 | _ER(TASK_SWITCH, 9) \ | ||
92 | _ER(CPUID, 10) \ | ||
93 | _ER(HLT, 12) \ | ||
94 | _ER(INVD, 13) \ | ||
95 | _ER(INVLPG, 14) \ | ||
96 | _ER(RDPMC, 15) \ | ||
97 | _ER(RDTSC, 16) \ | ||
98 | _ER(VMCALL, 18) \ | ||
99 | _ER(VMCLEAR, 19) \ | ||
100 | _ER(VMLAUNCH, 20) \ | ||
101 | _ER(VMPTRLD, 21) \ | ||
102 | _ER(VMPTRST, 22) \ | ||
103 | _ER(VMREAD, 23) \ | ||
104 | _ER(VMRESUME, 24) \ | ||
105 | _ER(VMWRITE, 25) \ | ||
106 | _ER(VMOFF, 26) \ | ||
107 | _ER(VMON, 27) \ | ||
108 | _ER(CR_ACCESS, 28) \ | ||
109 | _ER(DR_ACCESS, 29) \ | ||
110 | _ER(IO_INSTRUCTION, 30) \ | ||
111 | _ER(MSR_READ, 31) \ | ||
112 | _ER(MSR_WRITE, 32) \ | ||
113 | _ER(MWAIT_INSTRUCTION, 36) \ | ||
114 | _ER(MONITOR_INSTRUCTION, 39) \ | ||
115 | _ER(PAUSE_INSTRUCTION, 40) \ | ||
116 | _ER(MCE_DURING_VMENTRY, 41) \ | ||
117 | _ER(TPR_BELOW_THRESHOLD, 43) \ | ||
118 | _ER(APIC_ACCESS, 44) \ | ||
119 | _ER(EOI_INDUCED, 45) \ | ||
120 | _ER(EPT_VIOLATION, 48) \ | ||
121 | _ER(EPT_MISCONFIG, 49) \ | ||
122 | _ER(INVEPT, 50) \ | ||
123 | _ER(PREEMPTION_TIMER, 52) \ | ||
124 | _ER(WBINVD, 54) \ | ||
125 | _ER(XSETBV, 55) \ | ||
126 | _ER(APIC_WRITE, 56) \ | ||
127 | _ER(INVPCID, 58) | ||
128 | |||
129 | #define SVM_EXIT_REASONS \ | ||
130 | _ER(EXIT_READ_CR0, 0x000) \ | ||
131 | _ER(EXIT_READ_CR3, 0x003) \ | ||
132 | _ER(EXIT_READ_CR4, 0x004) \ | ||
133 | _ER(EXIT_READ_CR8, 0x008) \ | ||
134 | _ER(EXIT_WRITE_CR0, 0x010) \ | ||
135 | _ER(EXIT_WRITE_CR3, 0x013) \ | ||
136 | _ER(EXIT_WRITE_CR4, 0x014) \ | ||
137 | _ER(EXIT_WRITE_CR8, 0x018) \ | ||
138 | _ER(EXIT_READ_DR0, 0x020) \ | ||
139 | _ER(EXIT_READ_DR1, 0x021) \ | ||
140 | _ER(EXIT_READ_DR2, 0x022) \ | ||
141 | _ER(EXIT_READ_DR3, 0x023) \ | ||
142 | _ER(EXIT_READ_DR4, 0x024) \ | ||
143 | _ER(EXIT_READ_DR5, 0x025) \ | ||
144 | _ER(EXIT_READ_DR6, 0x026) \ | ||
145 | _ER(EXIT_READ_DR7, 0x027) \ | ||
146 | _ER(EXIT_WRITE_DR0, 0x030) \ | ||
147 | _ER(EXIT_WRITE_DR1, 0x031) \ | ||
148 | _ER(EXIT_WRITE_DR2, 0x032) \ | ||
149 | _ER(EXIT_WRITE_DR3, 0x033) \ | ||
150 | _ER(EXIT_WRITE_DR4, 0x034) \ | ||
151 | _ER(EXIT_WRITE_DR5, 0x035) \ | ||
152 | _ER(EXIT_WRITE_DR6, 0x036) \ | ||
153 | _ER(EXIT_WRITE_DR7, 0x037) \ | ||
154 | _ER(EXIT_EXCP_BASE, 0x040) \ | ||
155 | _ER(EXIT_INTR, 0x060) \ | ||
156 | _ER(EXIT_NMI, 0x061) \ | ||
157 | _ER(EXIT_SMI, 0x062) \ | ||
158 | _ER(EXIT_INIT, 0x063) \ | ||
159 | _ER(EXIT_VINTR, 0x064) \ | ||
160 | _ER(EXIT_CR0_SEL_WRITE, 0x065) \ | ||
161 | _ER(EXIT_IDTR_READ, 0x066) \ | ||
162 | _ER(EXIT_GDTR_READ, 0x067) \ | ||
163 | _ER(EXIT_LDTR_READ, 0x068) \ | ||
164 | _ER(EXIT_TR_READ, 0x069) \ | ||
165 | _ER(EXIT_IDTR_WRITE, 0x06a) \ | ||
166 | _ER(EXIT_GDTR_WRITE, 0x06b) \ | ||
167 | _ER(EXIT_LDTR_WRITE, 0x06c) \ | ||
168 | _ER(EXIT_TR_WRITE, 0x06d) \ | ||
169 | _ER(EXIT_RDTSC, 0x06e) \ | ||
170 | _ER(EXIT_RDPMC, 0x06f) \ | ||
171 | _ER(EXIT_PUSHF, 0x070) \ | ||
172 | _ER(EXIT_POPF, 0x071) \ | ||
173 | _ER(EXIT_CPUID, 0x072) \ | ||
174 | _ER(EXIT_RSM, 0x073) \ | ||
175 | _ER(EXIT_IRET, 0x074) \ | ||
176 | _ER(EXIT_SWINT, 0x075) \ | ||
177 | _ER(EXIT_INVD, 0x076) \ | ||
178 | _ER(EXIT_PAUSE, 0x077) \ | ||
179 | _ER(EXIT_HLT, 0x078) \ | ||
180 | _ER(EXIT_INVLPG, 0x079) \ | ||
181 | _ER(EXIT_INVLPGA, 0x07a) \ | ||
182 | _ER(EXIT_IOIO, 0x07b) \ | ||
183 | _ER(EXIT_MSR, 0x07c) \ | ||
184 | _ER(EXIT_TASK_SWITCH, 0x07d) \ | ||
185 | _ER(EXIT_FERR_FREEZE, 0x07e) \ | ||
186 | _ER(EXIT_SHUTDOWN, 0x07f) \ | ||
187 | _ER(EXIT_VMRUN, 0x080) \ | ||
188 | _ER(EXIT_VMMCALL, 0x081) \ | ||
189 | _ER(EXIT_VMLOAD, 0x082) \ | ||
190 | _ER(EXIT_VMSAVE, 0x083) \ | ||
191 | _ER(EXIT_STGI, 0x084) \ | ||
192 | _ER(EXIT_CLGI, 0x085) \ | ||
193 | _ER(EXIT_SKINIT, 0x086) \ | ||
194 | _ER(EXIT_RDTSCP, 0x087) \ | ||
195 | _ER(EXIT_ICEBP, 0x088) \ | ||
196 | _ER(EXIT_WBINVD, 0x089) \ | ||
197 | _ER(EXIT_MONITOR, 0x08a) \ | ||
198 | _ER(EXIT_MWAIT, 0x08b) \ | ||
199 | _ER(EXIT_MWAIT_COND, 0x08c) \ | ||
200 | _ER(EXIT_NPF, 0x400) \ | ||
201 | _ER(EXIT_ERR, -1) | ||
202 | |||
203 | #define _ER(reason, val) { #reason, val }, | ||
204 | struct str_values { | ||
205 | const char *str; | ||
206 | int val; | ||
207 | }; | ||
208 | |||
209 | static struct str_values vmx_exit_reasons[] = { | ||
210 | VMX_EXIT_REASONS | ||
211 | { NULL, -1} | ||
212 | }; | ||
213 | |||
214 | static struct str_values svm_exit_reasons[] = { | ||
215 | SVM_EXIT_REASONS | ||
216 | { NULL, -1} | ||
217 | }; | ||
218 | |||
219 | static struct isa_exit_reasons { | ||
220 | unsigned isa; | ||
221 | struct str_values *strings; | ||
222 | } isa_exit_reasons[] = { | ||
223 | { .isa = 1, .strings = vmx_exit_reasons }, | ||
224 | { .isa = 2, .strings = svm_exit_reasons }, | ||
225 | { } | ||
226 | }; | ||
227 | |||
228 | static const char *find_exit_reason(unsigned isa, int val) | ||
229 | { | ||
230 | struct str_values *strings = NULL; | ||
231 | int i; | ||
232 | |||
233 | for (i = 0; isa_exit_reasons[i].strings; ++i) | ||
234 | if (isa_exit_reasons[i].isa == isa) { | ||
235 | strings = isa_exit_reasons[i].strings; | ||
236 | break; | ||
237 | } | ||
238 | if (!strings) | ||
239 | return "UNKNOWN-ISA"; | ||
240 | for (i = 0; strings[i].val >= 0; i++) | ||
241 | if (strings[i].val == val) | ||
242 | break; | ||
243 | if (strings[i].str) | ||
244 | return strings[i].str; | ||
245 | return "UNKNOWN"; | ||
246 | } | ||
247 | |||
248 | static int kvm_exit_handler(struct trace_seq *s, struct pevent_record *record, | ||
249 | struct event_format *event, void *context) | ||
250 | { | ||
251 | unsigned long long isa; | ||
252 | unsigned long long val; | ||
253 | unsigned long long info1 = 0, info2 = 0; | ||
254 | |||
255 | if (pevent_get_field_val(s, event, "exit_reason", record, &val, 1) < 0) | ||
256 | return -1; | ||
257 | |||
258 | if (pevent_get_field_val(s, event, "isa", record, &isa, 0) < 0) | ||
259 | isa = 1; | ||
260 | |||
261 | trace_seq_printf(s, "reason %s", find_exit_reason(isa, val)); | ||
262 | |||
263 | pevent_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1); | ||
264 | |||
265 | if (pevent_get_field_val(s, event, "info1", record, &info1, 0) >= 0 | ||
266 | && pevent_get_field_val(s, event, "info2", record, &info2, 0) >= 0) | ||
267 | trace_seq_printf(s, " info %llx %llx", info1, info2); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | #define KVM_EMUL_INSN_F_CR0_PE (1 << 0) | ||
273 | #define KVM_EMUL_INSN_F_EFL_VM (1 << 1) | ||
274 | #define KVM_EMUL_INSN_F_CS_D (1 << 2) | ||
275 | #define KVM_EMUL_INSN_F_CS_L (1 << 3) | ||
276 | |||
277 | static int kvm_emulate_insn_handler(struct trace_seq *s, | ||
278 | struct pevent_record *record, | ||
279 | struct event_format *event, void *context) | ||
280 | { | ||
281 | unsigned long long rip, csbase, len, flags, failed; | ||
282 | int llen; | ||
283 | uint8_t *insn; | ||
284 | const char *disasm; | ||
285 | |||
286 | if (pevent_get_field_val(s, event, "rip", record, &rip, 1) < 0) | ||
287 | return -1; | ||
288 | |||
289 | if (pevent_get_field_val(s, event, "csbase", record, &csbase, 1) < 0) | ||
290 | return -1; | ||
291 | |||
292 | if (pevent_get_field_val(s, event, "len", record, &len, 1) < 0) | ||
293 | return -1; | ||
294 | |||
295 | if (pevent_get_field_val(s, event, "flags", record, &flags, 1) < 0) | ||
296 | return -1; | ||
297 | |||
298 | if (pevent_get_field_val(s, event, "failed", record, &failed, 1) < 0) | ||
299 | return -1; | ||
300 | |||
301 | insn = pevent_get_field_raw(s, event, "insn", record, &llen, 1); | ||
302 | if (!insn) | ||
303 | return -1; | ||
304 | |||
305 | disasm = disassemble(insn, len, rip, | ||
306 | flags & KVM_EMUL_INSN_F_CR0_PE, | ||
307 | flags & KVM_EMUL_INSN_F_EFL_VM, | ||
308 | flags & KVM_EMUL_INSN_F_CS_D, | ||
309 | flags & KVM_EMUL_INSN_F_CS_L); | ||
310 | |||
311 | trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm, | ||
312 | failed ? " FAIL" : ""); | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | union kvm_mmu_page_role { | ||
317 | unsigned word; | ||
318 | struct { | ||
319 | unsigned glevels:4; | ||
320 | unsigned level:4; | ||
321 | unsigned quadrant:2; | ||
322 | unsigned pad_for_nice_hex_output:6; | ||
323 | unsigned direct:1; | ||
324 | unsigned access:3; | ||
325 | unsigned invalid:1; | ||
326 | unsigned cr4_pge:1; | ||
327 | unsigned nxe:1; | ||
328 | }; | ||
329 | }; | ||
330 | |||
331 | static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record, | ||
332 | struct event_format *event, void *context) | ||
333 | { | ||
334 | unsigned long long val; | ||
335 | static const char *access_str[] = { | ||
336 | "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux" | ||
337 | }; | ||
338 | union kvm_mmu_page_role role; | ||
339 | |||
340 | if (pevent_get_field_val(s, event, "role", record, &val, 1) < 0) | ||
341 | return -1; | ||
342 | |||
343 | role.word = (int)val; | ||
344 | |||
345 | /* | ||
346 | * We can only use the structure if file is of the same | ||
347 | * endianess. | ||
348 | */ | ||
349 | if (pevent_is_file_bigendian(event->pevent) == | ||
350 | pevent_is_host_bigendian(event->pevent)) { | ||
351 | |||
352 | trace_seq_printf(s, "%u/%u q%u%s %s%s %spge %snxe", | ||
353 | role.level, | ||
354 | role.glevels, | ||
355 | role.quadrant, | ||
356 | role.direct ? " direct" : "", | ||
357 | access_str[role.access], | ||
358 | role.invalid ? " invalid" : "", | ||
359 | role.cr4_pge ? "" : "!", | ||
360 | role.nxe ? "" : "!"); | ||
361 | } else | ||
362 | trace_seq_printf(s, "WORD: %08x", role.word); | ||
363 | |||
364 | pevent_print_num_field(s, " root %u ", event, | ||
365 | "root_count", record, 1); | ||
366 | |||
367 | if (pevent_get_field_val(s, event, "unsync", record, &val, 1) < 0) | ||
368 | return -1; | ||
369 | |||
370 | trace_seq_printf(s, "%s%c", val ? "unsync" : "sync", 0); | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int kvm_mmu_get_page_handler(struct trace_seq *s, | ||
375 | struct pevent_record *record, | ||
376 | struct event_format *event, void *context) | ||
377 | { | ||
378 | unsigned long long val; | ||
379 | |||
380 | if (pevent_get_field_val(s, event, "created", record, &val, 1) < 0) | ||
381 | return -1; | ||
382 | |||
383 | trace_seq_printf(s, "%s ", val ? "new" : "existing"); | ||
384 | |||
385 | if (pevent_get_field_val(s, event, "gfn", record, &val, 1) < 0) | ||
386 | return -1; | ||
387 | |||
388 | trace_seq_printf(s, "sp gfn %llx ", val); | ||
389 | return kvm_mmu_print_role(s, record, event, context); | ||
390 | } | ||
391 | |||
392 | #define PT_WRITABLE_SHIFT 1 | ||
393 | #define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT) | ||
394 | |||
395 | static unsigned long long | ||
396 | process_is_writable_pte(struct trace_seq *s, unsigned long long *args) | ||
397 | { | ||
398 | unsigned long pte = args[0]; | ||
399 | return pte & PT_WRITABLE_MASK; | ||
400 | } | ||
401 | |||
402 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
403 | { | ||
404 | init_disassembler(); | ||
405 | |||
406 | pevent_register_event_handler(pevent, -1, "kvm", "kvm_exit", | ||
407 | kvm_exit_handler, NULL); | ||
408 | |||
409 | pevent_register_event_handler(pevent, -1, "kvm", "kvm_emulate_insn", | ||
410 | kvm_emulate_insn_handler, NULL); | ||
411 | |||
412 | pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page", | ||
413 | kvm_mmu_get_page_handler, NULL); | ||
414 | |||
415 | pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page", | ||
416 | kvm_mmu_print_role, NULL); | ||
417 | |||
418 | pevent_register_event_handler(pevent, -1, | ||
419 | "kvmmmu", "kvm_mmu_unsync_page", | ||
420 | kvm_mmu_print_role, NULL); | ||
421 | |||
422 | pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page", | ||
423 | kvm_mmu_print_role, NULL); | ||
424 | |||
425 | pevent_register_event_handler(pevent, -1, "kvmmmu", | ||
426 | "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, | ||
427 | NULL); | ||
428 | |||
429 | pevent_register_print_function(pevent, | ||
430 | process_is_writable_pte, | ||
431 | PEVENT_FUNC_ARG_INT, | ||
432 | "is_writable_pte", | ||
433 | PEVENT_FUNC_ARG_LONG, | ||
434 | PEVENT_FUNC_ARG_VOID); | ||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
439 | { | ||
440 | pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_exit", | ||
441 | kvm_exit_handler, NULL); | ||
442 | |||
443 | pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_emulate_insn", | ||
444 | kvm_emulate_insn_handler, NULL); | ||
445 | |||
446 | pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page", | ||
447 | kvm_mmu_get_page_handler, NULL); | ||
448 | |||
449 | pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page", | ||
450 | kvm_mmu_print_role, NULL); | ||
451 | |||
452 | pevent_unregister_event_handler(pevent, -1, | ||
453 | "kvmmmu", "kvm_mmu_unsync_page", | ||
454 | kvm_mmu_print_role, NULL); | ||
455 | |||
456 | pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page", | ||
457 | kvm_mmu_print_role, NULL); | ||
458 | |||
459 | pevent_unregister_event_handler(pevent, -1, "kvmmmu", | ||
460 | "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, | ||
461 | NULL); | ||
462 | |||
463 | pevent_unregister_print_function(pevent, process_is_writable_pte, | ||
464 | "is_writable_pte"); | ||
465 | } | ||
diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c new file mode 100644 index 000000000000..7e15a0f1c2fd --- /dev/null +++ b/tools/lib/traceevent/plugin_mac80211.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Johannes Berg <johannes@sipsolutions.net> | ||
3 | * | ||
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * version 2.1 of the License (not later!) | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this program; if not, see <http://www.gnu.org/licenses> | ||
17 | * | ||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | */ | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | |||
24 | #include "event-parse.h" | ||
25 | |||
26 | #define INDENT 65 | ||
27 | |||
28 | static void print_string(struct trace_seq *s, struct event_format *event, | ||
29 | const char *name, const void *data) | ||
30 | { | ||
31 | struct format_field *f = pevent_find_field(event, name); | ||
32 | int offset; | ||
33 | int length; | ||
34 | |||
35 | if (!f) { | ||
36 | trace_seq_printf(s, "NOTFOUND:%s", name); | ||
37 | return; | ||
38 | } | ||
39 | |||
40 | offset = f->offset; | ||
41 | length = f->size; | ||
42 | |||
43 | if (!strncmp(f->type, "__data_loc", 10)) { | ||
44 | unsigned long long v; | ||
45 | if (pevent_read_number_field(f, data, &v)) { | ||
46 | trace_seq_printf(s, "invalid_data_loc"); | ||
47 | return; | ||
48 | } | ||
49 | offset = v & 0xffff; | ||
50 | length = v >> 16; | ||
51 | } | ||
52 | |||
53 | trace_seq_printf(s, "%.*s", length, (char *)data + offset); | ||
54 | } | ||
55 | |||
56 | #define SF(fn) pevent_print_num_field(s, fn ":%d", event, fn, record, 0) | ||
57 | #define SFX(fn) pevent_print_num_field(s, fn ":%#x", event, fn, record, 0) | ||
58 | #define SP() trace_seq_putc(s, ' ') | ||
59 | |||
60 | static int drv_bss_info_changed(struct trace_seq *s, | ||
61 | struct pevent_record *record, | ||
62 | struct event_format *event, void *context) | ||
63 | { | ||
64 | void *data = record->data; | ||
65 | |||
66 | print_string(s, event, "wiphy_name", data); | ||
67 | trace_seq_printf(s, " vif:"); | ||
68 | print_string(s, event, "vif_name", data); | ||
69 | pevent_print_num_field(s, "(%d)", event, "vif_type", record, 1); | ||
70 | |||
71 | trace_seq_printf(s, "\n%*s", INDENT, ""); | ||
72 | SF("assoc"); SP(); | ||
73 | SF("aid"); SP(); | ||
74 | SF("cts"); SP(); | ||
75 | SF("shortpre"); SP(); | ||
76 | SF("shortslot"); SP(); | ||
77 | SF("dtimper"); SP(); | ||
78 | trace_seq_printf(s, "\n%*s", INDENT, ""); | ||
79 | SF("bcnint"); SP(); | ||
80 | SFX("assoc_cap"); SP(); | ||
81 | SFX("basic_rates"); SP(); | ||
82 | SF("enable_beacon"); | ||
83 | trace_seq_printf(s, "\n%*s", INDENT, ""); | ||
84 | SF("ht_operation_mode"); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
90 | { | ||
91 | pevent_register_event_handler(pevent, -1, "mac80211", | ||
92 | "drv_bss_info_changed", | ||
93 | drv_bss_info_changed, NULL); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
98 | { | ||
99 | pevent_unregister_event_handler(pevent, -1, "mac80211", | ||
100 | "drv_bss_info_changed", | ||
101 | drv_bss_info_changed, NULL); | ||
102 | } | ||
diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c new file mode 100644 index 000000000000..f1ce60065258 --- /dev/null +++ b/tools/lib/traceevent/plugin_sched_switch.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | ||
3 | * | ||
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * version 2.1 of the License (not later!) | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this program; if not, see <http://www.gnu.org/licenses> | ||
17 | * | ||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
19 | */ | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | |||
24 | #include "event-parse.h" | ||
25 | |||
26 | static void write_state(struct trace_seq *s, int val) | ||
27 | { | ||
28 | const char states[] = "SDTtZXxW"; | ||
29 | int found = 0; | ||
30 | int i; | ||
31 | |||
32 | for (i = 0; i < (sizeof(states) - 1); i++) { | ||
33 | if (!(val & (1 << i))) | ||
34 | continue; | ||
35 | |||
36 | if (found) | ||
37 | trace_seq_putc(s, '|'); | ||
38 | |||
39 | found = 1; | ||
40 | trace_seq_putc(s, states[i]); | ||
41 | } | ||
42 | |||
43 | if (!found) | ||
44 | trace_seq_putc(s, 'R'); | ||
45 | } | ||
46 | |||
47 | static void write_and_save_comm(struct format_field *field, | ||
48 | struct pevent_record *record, | ||
49 | struct trace_seq *s, int pid) | ||
50 | { | ||
51 | const char *comm; | ||
52 | int len; | ||
53 | |||
54 | comm = (char *)(record->data + field->offset); | ||
55 | len = s->len; | ||
56 | trace_seq_printf(s, "%.*s", | ||
57 | field->size, comm); | ||
58 | |||
59 | /* make sure the comm has a \0 at the end. */ | ||
60 | trace_seq_terminate(s); | ||
61 | comm = &s->buffer[len]; | ||
62 | |||
63 | /* Help out the comm to ids. This will handle dups */ | ||
64 | pevent_register_comm(field->event->pevent, comm, pid); | ||
65 | } | ||
66 | |||
67 | static int sched_wakeup_handler(struct trace_seq *s, | ||
68 | struct pevent_record *record, | ||
69 | struct event_format *event, void *context) | ||
70 | { | ||
71 | struct format_field *field; | ||
72 | unsigned long long val; | ||
73 | |||
74 | if (pevent_get_field_val(s, event, "pid", record, &val, 1)) | ||
75 | return trace_seq_putc(s, '!'); | ||
76 | |||
77 | field = pevent_find_any_field(event, "comm"); | ||
78 | if (field) { | ||
79 | write_and_save_comm(field, record, s, val); | ||
80 | trace_seq_putc(s, ':'); | ||
81 | } | ||
82 | trace_seq_printf(s, "%lld", val); | ||
83 | |||
84 | if (pevent_get_field_val(s, event, "prio", record, &val, 0) == 0) | ||
85 | trace_seq_printf(s, " [%lld]", val); | ||
86 | |||
87 | if (pevent_get_field_val(s, event, "success", record, &val, 1) == 0) | ||
88 | trace_seq_printf(s, " success=%lld", val); | ||
89 | |||
90 | if (pevent_get_field_val(s, event, "target_cpu", record, &val, 0) == 0) | ||
91 | trace_seq_printf(s, " CPU:%03llu", val); | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int sched_switch_handler(struct trace_seq *s, | ||
97 | struct pevent_record *record, | ||
98 | struct event_format *event, void *context) | ||
99 | { | ||
100 | struct format_field *field; | ||
101 | unsigned long long val; | ||
102 | |||
103 | if (pevent_get_field_val(s, event, "prev_pid", record, &val, 1)) | ||
104 | return trace_seq_putc(s, '!'); | ||
105 | |||
106 | field = pevent_find_any_field(event, "prev_comm"); | ||
107 | if (field) { | ||
108 | write_and_save_comm(field, record, s, val); | ||
109 | trace_seq_putc(s, ':'); | ||
110 | } | ||
111 | trace_seq_printf(s, "%lld ", val); | ||
112 | |||
113 | if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) | ||
114 | trace_seq_printf(s, "[%lld] ", val); | ||
115 | |||
116 | if (pevent_get_field_val(s, event, "prev_state", record, &val, 0) == 0) | ||
117 | write_state(s, val); | ||
118 | |||
119 | trace_seq_puts(s, " ==> "); | ||
120 | |||
121 | if (pevent_get_field_val(s, event, "next_pid", record, &val, 1)) | ||
122 | return trace_seq_putc(s, '!'); | ||
123 | |||
124 | field = pevent_find_any_field(event, "next_comm"); | ||
125 | if (field) { | ||
126 | write_and_save_comm(field, record, s, val); | ||
127 | trace_seq_putc(s, ':'); | ||
128 | } | ||
129 | trace_seq_printf(s, "%lld", val); | ||
130 | |||
131 | if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0) | ||
132 | trace_seq_printf(s, " [%lld]", val); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
138 | { | ||
139 | pevent_register_event_handler(pevent, -1, "sched", "sched_switch", | ||
140 | sched_switch_handler, NULL); | ||
141 | |||
142 | pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup", | ||
143 | sched_wakeup_handler, NULL); | ||
144 | |||
145 | pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup_new", | ||
146 | sched_wakeup_handler, NULL); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
151 | { | ||
152 | pevent_unregister_event_handler(pevent, -1, "sched", "sched_switch", | ||
153 | sched_switch_handler, NULL); | ||
154 | |||
155 | pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup", | ||
156 | sched_wakeup_handler, NULL); | ||
157 | |||
158 | pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup_new", | ||
159 | sched_wakeup_handler, NULL); | ||
160 | } | ||
diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c new file mode 100644 index 000000000000..eda326fc8620 --- /dev/null +++ b/tools/lib/traceevent/plugin_scsi.c | |||
@@ -0,0 +1,429 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include <inttypes.h> | ||
4 | #include "event-parse.h" | ||
5 | |||
6 | typedef unsigned long sector_t; | ||
7 | typedef uint64_t u64; | ||
8 | typedef unsigned int u32; | ||
9 | |||
10 | /* | ||
11 | * SCSI opcodes | ||
12 | */ | ||
13 | #define TEST_UNIT_READY 0x00 | ||
14 | #define REZERO_UNIT 0x01 | ||
15 | #define REQUEST_SENSE 0x03 | ||
16 | #define FORMAT_UNIT 0x04 | ||
17 | #define READ_BLOCK_LIMITS 0x05 | ||
18 | #define REASSIGN_BLOCKS 0x07 | ||
19 | #define INITIALIZE_ELEMENT_STATUS 0x07 | ||
20 | #define READ_6 0x08 | ||
21 | #define WRITE_6 0x0a | ||
22 | #define SEEK_6 0x0b | ||
23 | #define READ_REVERSE 0x0f | ||
24 | #define WRITE_FILEMARKS 0x10 | ||
25 | #define SPACE 0x11 | ||
26 | #define INQUIRY 0x12 | ||
27 | #define RECOVER_BUFFERED_DATA 0x14 | ||
28 | #define MODE_SELECT 0x15 | ||
29 | #define RESERVE 0x16 | ||
30 | #define RELEASE 0x17 | ||
31 | #define COPY 0x18 | ||
32 | #define ERASE 0x19 | ||
33 | #define MODE_SENSE 0x1a | ||
34 | #define START_STOP 0x1b | ||
35 | #define RECEIVE_DIAGNOSTIC 0x1c | ||
36 | #define SEND_DIAGNOSTIC 0x1d | ||
37 | #define ALLOW_MEDIUM_REMOVAL 0x1e | ||
38 | |||
39 | #define READ_FORMAT_CAPACITIES 0x23 | ||
40 | #define SET_WINDOW 0x24 | ||
41 | #define READ_CAPACITY 0x25 | ||
42 | #define READ_10 0x28 | ||
43 | #define WRITE_10 0x2a | ||
44 | #define SEEK_10 0x2b | ||
45 | #define POSITION_TO_ELEMENT 0x2b | ||
46 | #define WRITE_VERIFY 0x2e | ||
47 | #define VERIFY 0x2f | ||
48 | #define SEARCH_HIGH 0x30 | ||
49 | #define SEARCH_EQUAL 0x31 | ||
50 | #define SEARCH_LOW 0x32 | ||
51 | #define SET_LIMITS 0x33 | ||
52 | #define PRE_FETCH 0x34 | ||
53 | #define READ_POSITION 0x34 | ||
54 | #define SYNCHRONIZE_CACHE 0x35 | ||
55 | #define LOCK_UNLOCK_CACHE 0x36 | ||
56 | #define READ_DEFECT_DATA 0x37 | ||
57 | #define MEDIUM_SCAN 0x38 | ||
58 | #define COMPARE 0x39 | ||
59 | #define COPY_VERIFY 0x3a | ||
60 | #define WRITE_BUFFER 0x3b | ||
61 | #define READ_BUFFER 0x3c | ||
62 | #define UPDATE_BLOCK 0x3d | ||
63 | #define READ_LONG 0x3e | ||
64 | #define WRITE_LONG 0x3f | ||
65 | #define CHANGE_DEFINITION 0x40 | ||
66 | #define WRITE_SAME 0x41 | ||
67 | #define UNMAP 0x42 | ||
68 | #define READ_TOC 0x43 | ||
69 | #define READ_HEADER 0x44 | ||
70 | #define GET_EVENT_STATUS_NOTIFICATION 0x4a | ||
71 | #define LOG_SELECT 0x4c | ||
72 | #define LOG_SENSE 0x4d | ||
73 | #define XDWRITEREAD_10 0x53 | ||
74 | #define MODE_SELECT_10 0x55 | ||
75 | #define RESERVE_10 0x56 | ||
76 | #define RELEASE_10 0x57 | ||
77 | #define MODE_SENSE_10 0x5a | ||
78 | #define PERSISTENT_RESERVE_IN 0x5e | ||
79 | #define PERSISTENT_RESERVE_OUT 0x5f | ||
80 | #define VARIABLE_LENGTH_CMD 0x7f | ||
81 | #define REPORT_LUNS 0xa0 | ||
82 | #define SECURITY_PROTOCOL_IN 0xa2 | ||
83 | #define MAINTENANCE_IN 0xa3 | ||
84 | #define MAINTENANCE_OUT 0xa4 | ||
85 | #define MOVE_MEDIUM 0xa5 | ||
86 | #define EXCHANGE_MEDIUM 0xa6 | ||
87 | #define READ_12 0xa8 | ||
88 | #define WRITE_12 0xaa | ||
89 | #define READ_MEDIA_SERIAL_NUMBER 0xab | ||
90 | #define WRITE_VERIFY_12 0xae | ||
91 | #define VERIFY_12 0xaf | ||
92 | #define SEARCH_HIGH_12 0xb0 | ||
93 | #define SEARCH_EQUAL_12 0xb1 | ||
94 | #define SEARCH_LOW_12 0xb2 | ||
95 | #define SECURITY_PROTOCOL_OUT 0xb5 | ||
96 | #define READ_ELEMENT_STATUS 0xb8 | ||
97 | #define SEND_VOLUME_TAG 0xb6 | ||
98 | #define WRITE_LONG_2 0xea | ||
99 | #define EXTENDED_COPY 0x83 | ||
100 | #define RECEIVE_COPY_RESULTS 0x84 | ||
101 | #define ACCESS_CONTROL_IN 0x86 | ||
102 | #define ACCESS_CONTROL_OUT 0x87 | ||
103 | #define READ_16 0x88 | ||
104 | #define WRITE_16 0x8a | ||
105 | #define READ_ATTRIBUTE 0x8c | ||
106 | #define WRITE_ATTRIBUTE 0x8d | ||
107 | #define VERIFY_16 0x8f | ||
108 | #define SYNCHRONIZE_CACHE_16 0x91 | ||
109 | #define WRITE_SAME_16 0x93 | ||
110 | #define SERVICE_ACTION_IN 0x9e | ||
111 | /* values for service action in */ | ||
112 | #define SAI_READ_CAPACITY_16 0x10 | ||
113 | #define SAI_GET_LBA_STATUS 0x12 | ||
114 | /* values for VARIABLE_LENGTH_CMD service action codes | ||
115 | * see spc4r17 Section D.3.5, table D.7 and D.8 */ | ||
116 | #define VLC_SA_RECEIVE_CREDENTIAL 0x1800 | ||
117 | /* values for maintenance in */ | ||
118 | #define MI_REPORT_IDENTIFYING_INFORMATION 0x05 | ||
119 | #define MI_REPORT_TARGET_PGS 0x0a | ||
120 | #define MI_REPORT_ALIASES 0x0b | ||
121 | #define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c | ||
122 | #define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d | ||
123 | #define MI_REPORT_PRIORITY 0x0e | ||
124 | #define MI_REPORT_TIMESTAMP 0x0f | ||
125 | #define MI_MANAGEMENT_PROTOCOL_IN 0x10 | ||
126 | /* value for MI_REPORT_TARGET_PGS ext header */ | ||
127 | #define MI_EXT_HDR_PARAM_FMT 0x20 | ||
128 | /* values for maintenance out */ | ||
129 | #define MO_SET_IDENTIFYING_INFORMATION 0x06 | ||
130 | #define MO_SET_TARGET_PGS 0x0a | ||
131 | #define MO_CHANGE_ALIASES 0x0b | ||
132 | #define MO_SET_PRIORITY 0x0e | ||
133 | #define MO_SET_TIMESTAMP 0x0f | ||
134 | #define MO_MANAGEMENT_PROTOCOL_OUT 0x10 | ||
135 | /* values for variable length command */ | ||
136 | #define XDREAD_32 0x03 | ||
137 | #define XDWRITE_32 0x04 | ||
138 | #define XPWRITE_32 0x06 | ||
139 | #define XDWRITEREAD_32 0x07 | ||
140 | #define READ_32 0x09 | ||
141 | #define VERIFY_32 0x0a | ||
142 | #define WRITE_32 0x0b | ||
143 | #define WRITE_SAME_32 0x0d | ||
144 | |||
145 | #define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f) | ||
146 | #define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9]) | ||
147 | |||
148 | static const char * | ||
149 | scsi_trace_misc(struct trace_seq *, unsigned char *, int); | ||
150 | |||
151 | static const char * | ||
152 | scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len) | ||
153 | { | ||
154 | const char *ret = p->buffer + p->len; | ||
155 | sector_t lba = 0, txlen = 0; | ||
156 | |||
157 | lba |= ((cdb[1] & 0x1F) << 16); | ||
158 | lba |= (cdb[2] << 8); | ||
159 | lba |= cdb[3]; | ||
160 | txlen = cdb[4]; | ||
161 | |||
162 | trace_seq_printf(p, "lba=%llu txlen=%llu", | ||
163 | (unsigned long long)lba, (unsigned long long)txlen); | ||
164 | trace_seq_putc(p, 0); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | static const char * | ||
169 | scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len) | ||
170 | { | ||
171 | const char *ret = p->buffer + p->len; | ||
172 | sector_t lba = 0, txlen = 0; | ||
173 | |||
174 | lba |= (cdb[2] << 24); | ||
175 | lba |= (cdb[3] << 16); | ||
176 | lba |= (cdb[4] << 8); | ||
177 | lba |= cdb[5]; | ||
178 | txlen |= (cdb[7] << 8); | ||
179 | txlen |= cdb[8]; | ||
180 | |||
181 | trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", | ||
182 | (unsigned long long)lba, (unsigned long long)txlen, | ||
183 | cdb[1] >> 5); | ||
184 | |||
185 | if (cdb[0] == WRITE_SAME) | ||
186 | trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); | ||
187 | |||
188 | trace_seq_putc(p, 0); | ||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static const char * | ||
193 | scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len) | ||
194 | { | ||
195 | const char *ret = p->buffer + p->len; | ||
196 | sector_t lba = 0, txlen = 0; | ||
197 | |||
198 | lba |= (cdb[2] << 24); | ||
199 | lba |= (cdb[3] << 16); | ||
200 | lba |= (cdb[4] << 8); | ||
201 | lba |= cdb[5]; | ||
202 | txlen |= (cdb[6] << 24); | ||
203 | txlen |= (cdb[7] << 16); | ||
204 | txlen |= (cdb[8] << 8); | ||
205 | txlen |= cdb[9]; | ||
206 | |||
207 | trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", | ||
208 | (unsigned long long)lba, (unsigned long long)txlen, | ||
209 | cdb[1] >> 5); | ||
210 | trace_seq_putc(p, 0); | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | static const char * | ||
215 | scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len) | ||
216 | { | ||
217 | const char *ret = p->buffer + p->len; | ||
218 | sector_t lba = 0, txlen = 0; | ||
219 | |||
220 | lba |= ((u64)cdb[2] << 56); | ||
221 | lba |= ((u64)cdb[3] << 48); | ||
222 | lba |= ((u64)cdb[4] << 40); | ||
223 | lba |= ((u64)cdb[5] << 32); | ||
224 | lba |= (cdb[6] << 24); | ||
225 | lba |= (cdb[7] << 16); | ||
226 | lba |= (cdb[8] << 8); | ||
227 | lba |= cdb[9]; | ||
228 | txlen |= (cdb[10] << 24); | ||
229 | txlen |= (cdb[11] << 16); | ||
230 | txlen |= (cdb[12] << 8); | ||
231 | txlen |= cdb[13]; | ||
232 | |||
233 | trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", | ||
234 | (unsigned long long)lba, (unsigned long long)txlen, | ||
235 | cdb[1] >> 5); | ||
236 | |||
237 | if (cdb[0] == WRITE_SAME_16) | ||
238 | trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); | ||
239 | |||
240 | trace_seq_putc(p, 0); | ||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | static const char * | ||
245 | scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len) | ||
246 | { | ||
247 | const char *ret = p->buffer + p->len, *cmd; | ||
248 | sector_t lba = 0, txlen = 0; | ||
249 | u32 ei_lbrt = 0; | ||
250 | |||
251 | switch (SERVICE_ACTION32(cdb)) { | ||
252 | case READ_32: | ||
253 | cmd = "READ"; | ||
254 | break; | ||
255 | case VERIFY_32: | ||
256 | cmd = "VERIFY"; | ||
257 | break; | ||
258 | case WRITE_32: | ||
259 | cmd = "WRITE"; | ||
260 | break; | ||
261 | case WRITE_SAME_32: | ||
262 | cmd = "WRITE_SAME"; | ||
263 | break; | ||
264 | default: | ||
265 | trace_seq_printf(p, "UNKNOWN"); | ||
266 | goto out; | ||
267 | } | ||
268 | |||
269 | lba |= ((u64)cdb[12] << 56); | ||
270 | lba |= ((u64)cdb[13] << 48); | ||
271 | lba |= ((u64)cdb[14] << 40); | ||
272 | lba |= ((u64)cdb[15] << 32); | ||
273 | lba |= (cdb[16] << 24); | ||
274 | lba |= (cdb[17] << 16); | ||
275 | lba |= (cdb[18] << 8); | ||
276 | lba |= cdb[19]; | ||
277 | ei_lbrt |= (cdb[20] << 24); | ||
278 | ei_lbrt |= (cdb[21] << 16); | ||
279 | ei_lbrt |= (cdb[22] << 8); | ||
280 | ei_lbrt |= cdb[23]; | ||
281 | txlen |= (cdb[28] << 24); | ||
282 | txlen |= (cdb[29] << 16); | ||
283 | txlen |= (cdb[30] << 8); | ||
284 | txlen |= cdb[31]; | ||
285 | |||
286 | trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u", | ||
287 | cmd, (unsigned long long)lba, | ||
288 | (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt); | ||
289 | |||
290 | if (SERVICE_ACTION32(cdb) == WRITE_SAME_32) | ||
291 | trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1); | ||
292 | |||
293 | out: | ||
294 | trace_seq_putc(p, 0); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | static const char * | ||
299 | scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len) | ||
300 | { | ||
301 | const char *ret = p->buffer + p->len; | ||
302 | unsigned int regions = cdb[7] << 8 | cdb[8]; | ||
303 | |||
304 | trace_seq_printf(p, "regions=%u", (regions - 8) / 16); | ||
305 | trace_seq_putc(p, 0); | ||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | static const char * | ||
310 | scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) | ||
311 | { | ||
312 | const char *ret = p->buffer + p->len, *cmd; | ||
313 | sector_t lba = 0; | ||
314 | u32 alloc_len = 0; | ||
315 | |||
316 | switch (SERVICE_ACTION16(cdb)) { | ||
317 | case SAI_READ_CAPACITY_16: | ||
318 | cmd = "READ_CAPACITY_16"; | ||
319 | break; | ||
320 | case SAI_GET_LBA_STATUS: | ||
321 | cmd = "GET_LBA_STATUS"; | ||
322 | break; | ||
323 | default: | ||
324 | trace_seq_printf(p, "UNKNOWN"); | ||
325 | goto out; | ||
326 | } | ||
327 | |||
328 | lba |= ((u64)cdb[2] << 56); | ||
329 | lba |= ((u64)cdb[3] << 48); | ||
330 | lba |= ((u64)cdb[4] << 40); | ||
331 | lba |= ((u64)cdb[5] << 32); | ||
332 | lba |= (cdb[6] << 24); | ||
333 | lba |= (cdb[7] << 16); | ||
334 | lba |= (cdb[8] << 8); | ||
335 | lba |= cdb[9]; | ||
336 | alloc_len |= (cdb[10] << 24); | ||
337 | alloc_len |= (cdb[11] << 16); | ||
338 | alloc_len |= (cdb[12] << 8); | ||
339 | alloc_len |= cdb[13]; | ||
340 | |||
341 | trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, | ||
342 | (unsigned long long)lba, alloc_len); | ||
343 | |||
344 | out: | ||
345 | trace_seq_putc(p, 0); | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static const char * | ||
350 | scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) | ||
351 | { | ||
352 | switch (SERVICE_ACTION32(cdb)) { | ||
353 | case READ_32: | ||
354 | case VERIFY_32: | ||
355 | case WRITE_32: | ||
356 | case WRITE_SAME_32: | ||
357 | return scsi_trace_rw32(p, cdb, len); | ||
358 | default: | ||
359 | return scsi_trace_misc(p, cdb, len); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | static const char * | ||
364 | scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len) | ||
365 | { | ||
366 | const char *ret = p->buffer + p->len; | ||
367 | |||
368 | trace_seq_printf(p, "-"); | ||
369 | trace_seq_putc(p, 0); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | const char * | ||
374 | scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) | ||
375 | { | ||
376 | switch (cdb[0]) { | ||
377 | case READ_6: | ||
378 | case WRITE_6: | ||
379 | return scsi_trace_rw6(p, cdb, len); | ||
380 | case READ_10: | ||
381 | case VERIFY: | ||
382 | case WRITE_10: | ||
383 | case WRITE_SAME: | ||
384 | return scsi_trace_rw10(p, cdb, len); | ||
385 | case READ_12: | ||
386 | case VERIFY_12: | ||
387 | case WRITE_12: | ||
388 | return scsi_trace_rw12(p, cdb, len); | ||
389 | case READ_16: | ||
390 | case VERIFY_16: | ||
391 | case WRITE_16: | ||
392 | case WRITE_SAME_16: | ||
393 | return scsi_trace_rw16(p, cdb, len); | ||
394 | case UNMAP: | ||
395 | return scsi_trace_unmap(p, cdb, len); | ||
396 | case SERVICE_ACTION_IN: | ||
397 | return scsi_trace_service_action_in(p, cdb, len); | ||
398 | case VARIABLE_LENGTH_CMD: | ||
399 | return scsi_trace_varlen(p, cdb, len); | ||
400 | default: | ||
401 | return scsi_trace_misc(p, cdb, len); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s, | ||
406 | unsigned long long *args) | ||
407 | { | ||
408 | scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]); | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
413 | { | ||
414 | pevent_register_print_function(pevent, | ||
415 | process_scsi_trace_parse_cdb, | ||
416 | PEVENT_FUNC_ARG_STRING, | ||
417 | "scsi_trace_parse_cdb", | ||
418 | PEVENT_FUNC_ARG_PTR, | ||
419 | PEVENT_FUNC_ARG_PTR, | ||
420 | PEVENT_FUNC_ARG_INT, | ||
421 | PEVENT_FUNC_ARG_VOID); | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
426 | { | ||
427 | pevent_unregister_print_function(pevent, process_scsi_trace_parse_cdb, | ||
428 | "scsi_trace_parse_cdb"); | ||
429 | } | ||
diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c new file mode 100644 index 000000000000..3a413eaada68 --- /dev/null +++ b/tools/lib/traceevent/plugin_xen.c | |||
@@ -0,0 +1,136 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include "event-parse.h" | ||
5 | |||
6 | #define __HYPERVISOR_set_trap_table 0 | ||
7 | #define __HYPERVISOR_mmu_update 1 | ||
8 | #define __HYPERVISOR_set_gdt 2 | ||
9 | #define __HYPERVISOR_stack_switch 3 | ||
10 | #define __HYPERVISOR_set_callbacks 4 | ||
11 | #define __HYPERVISOR_fpu_taskswitch 5 | ||
12 | #define __HYPERVISOR_sched_op_compat 6 | ||
13 | #define __HYPERVISOR_dom0_op 7 | ||
14 | #define __HYPERVISOR_set_debugreg 8 | ||
15 | #define __HYPERVISOR_get_debugreg 9 | ||
16 | #define __HYPERVISOR_update_descriptor 10 | ||
17 | #define __HYPERVISOR_memory_op 12 | ||
18 | #define __HYPERVISOR_multicall 13 | ||
19 | #define __HYPERVISOR_update_va_mapping 14 | ||
20 | #define __HYPERVISOR_set_timer_op 15 | ||
21 | #define __HYPERVISOR_event_channel_op_compat 16 | ||
22 | #define __HYPERVISOR_xen_version 17 | ||
23 | #define __HYPERVISOR_console_io 18 | ||
24 | #define __HYPERVISOR_physdev_op_compat 19 | ||
25 | #define __HYPERVISOR_grant_table_op 20 | ||
26 | #define __HYPERVISOR_vm_assist 21 | ||
27 | #define __HYPERVISOR_update_va_mapping_otherdomain 22 | ||
28 | #define __HYPERVISOR_iret 23 /* x86 only */ | ||
29 | #define __HYPERVISOR_vcpu_op 24 | ||
30 | #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ | ||
31 | #define __HYPERVISOR_mmuext_op 26 | ||
32 | #define __HYPERVISOR_acm_op 27 | ||
33 | #define __HYPERVISOR_nmi_op 28 | ||
34 | #define __HYPERVISOR_sched_op 29 | ||
35 | #define __HYPERVISOR_callback_op 30 | ||
36 | #define __HYPERVISOR_xenoprof_op 31 | ||
37 | #define __HYPERVISOR_event_channel_op 32 | ||
38 | #define __HYPERVISOR_physdev_op 33 | ||
39 | #define __HYPERVISOR_hvm_op 34 | ||
40 | #define __HYPERVISOR_tmem_op 38 | ||
41 | |||
42 | /* Architecture-specific hypercall definitions. */ | ||
43 | #define __HYPERVISOR_arch_0 48 | ||
44 | #define __HYPERVISOR_arch_1 49 | ||
45 | #define __HYPERVISOR_arch_2 50 | ||
46 | #define __HYPERVISOR_arch_3 51 | ||
47 | #define __HYPERVISOR_arch_4 52 | ||
48 | #define __HYPERVISOR_arch_5 53 | ||
49 | #define __HYPERVISOR_arch_6 54 | ||
50 | #define __HYPERVISOR_arch_7 55 | ||
51 | |||
52 | #define N(x) [__HYPERVISOR_##x] = "("#x")" | ||
53 | static const char *xen_hypercall_names[] = { | ||
54 | N(set_trap_table), | ||
55 | N(mmu_update), | ||
56 | N(set_gdt), | ||
57 | N(stack_switch), | ||
58 | N(set_callbacks), | ||
59 | N(fpu_taskswitch), | ||
60 | N(sched_op_compat), | ||
61 | N(dom0_op), | ||
62 | N(set_debugreg), | ||
63 | N(get_debugreg), | ||
64 | N(update_descriptor), | ||
65 | N(memory_op), | ||
66 | N(multicall), | ||
67 | N(update_va_mapping), | ||
68 | N(set_timer_op), | ||
69 | N(event_channel_op_compat), | ||
70 | N(xen_version), | ||
71 | N(console_io), | ||
72 | N(physdev_op_compat), | ||
73 | N(grant_table_op), | ||
74 | N(vm_assist), | ||
75 | N(update_va_mapping_otherdomain), | ||
76 | N(iret), | ||
77 | N(vcpu_op), | ||
78 | N(set_segment_base), | ||
79 | N(mmuext_op), | ||
80 | N(acm_op), | ||
81 | N(nmi_op), | ||
82 | N(sched_op), | ||
83 | N(callback_op), | ||
84 | N(xenoprof_op), | ||
85 | N(event_channel_op), | ||
86 | N(physdev_op), | ||
87 | N(hvm_op), | ||
88 | |||
89 | /* Architecture-specific hypercall definitions. */ | ||
90 | N(arch_0), | ||
91 | N(arch_1), | ||
92 | N(arch_2), | ||
93 | N(arch_3), | ||
94 | N(arch_4), | ||
95 | N(arch_5), | ||
96 | N(arch_6), | ||
97 | N(arch_7), | ||
98 | }; | ||
99 | #undef N | ||
100 | |||
101 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) | ||
102 | |||
103 | static const char *xen_hypercall_name(unsigned op) | ||
104 | { | ||
105 | if (op < ARRAY_SIZE(xen_hypercall_names) && | ||
106 | xen_hypercall_names[op] != NULL) | ||
107 | return xen_hypercall_names[op]; | ||
108 | |||
109 | return ""; | ||
110 | } | ||
111 | |||
112 | unsigned long long process_xen_hypercall_name(struct trace_seq *s, | ||
113 | unsigned long long *args) | ||
114 | { | ||
115 | unsigned int op = args[0]; | ||
116 | |||
117 | trace_seq_printf(s, "%s", xen_hypercall_name(op)); | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
122 | { | ||
123 | pevent_register_print_function(pevent, | ||
124 | process_xen_hypercall_name, | ||
125 | PEVENT_FUNC_ARG_STRING, | ||
126 | "xen_hypercall_name", | ||
127 | PEVENT_FUNC_ARG_INT, | ||
128 | PEVENT_FUNC_ARG_VOID); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) | ||
133 | { | ||
134 | pevent_unregister_print_function(pevent, process_xen_hypercall_name, | ||
135 | "xen_hypercall_name"); | ||
136 | } | ||
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c index d7f2e68bc5b9..ec3bd16a5488 100644 --- a/tools/lib/traceevent/trace-seq.c +++ b/tools/lib/traceevent/trace-seq.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <string.h> | 22 | #include <string.h> |
23 | #include <stdarg.h> | 23 | #include <stdarg.h> |
24 | 24 | ||
25 | #include <asm/bug.h> | ||
25 | #include "event-parse.h" | 26 | #include "event-parse.h" |
26 | #include "event-utils.h" | 27 | #include "event-utils.h" |
27 | 28 | ||
@@ -32,10 +33,21 @@ | |||
32 | #define TRACE_SEQ_POISON ((void *)0xdeadbeef) | 33 | #define TRACE_SEQ_POISON ((void *)0xdeadbeef) |
33 | #define TRACE_SEQ_CHECK(s) \ | 34 | #define TRACE_SEQ_CHECK(s) \ |
34 | do { \ | 35 | do { \ |
35 | if ((s)->buffer == TRACE_SEQ_POISON) \ | 36 | if (WARN_ONCE((s)->buffer == TRACE_SEQ_POISON, \ |
36 | die("Usage of trace_seq after it was destroyed"); \ | 37 | "Usage of trace_seq after it was destroyed")) \ |
38 | (s)->state = TRACE_SEQ__BUFFER_POISONED; \ | ||
37 | } while (0) | 39 | } while (0) |
38 | 40 | ||
41 | #define TRACE_SEQ_CHECK_RET_N(s, n) \ | ||
42 | do { \ | ||
43 | TRACE_SEQ_CHECK(s); \ | ||
44 | if ((s)->state != TRACE_SEQ__GOOD) \ | ||
45 | return n; \ | ||
46 | } while (0) | ||
47 | |||
48 | #define TRACE_SEQ_CHECK_RET(s) TRACE_SEQ_CHECK_RET_N(s, ) | ||
49 | #define TRACE_SEQ_CHECK_RET0(s) TRACE_SEQ_CHECK_RET_N(s, 0) | ||
50 | |||
39 | /** | 51 | /** |
40 | * trace_seq_init - initialize the trace_seq structure | 52 | * trace_seq_init - initialize the trace_seq structure |
41 | * @s: a pointer to the trace_seq structure to initialize | 53 | * @s: a pointer to the trace_seq structure to initialize |
@@ -45,7 +57,11 @@ void trace_seq_init(struct trace_seq *s) | |||
45 | s->len = 0; | 57 | s->len = 0; |
46 | s->readpos = 0; | 58 | s->readpos = 0; |
47 | s->buffer_size = TRACE_SEQ_BUF_SIZE; | 59 | s->buffer_size = TRACE_SEQ_BUF_SIZE; |
48 | s->buffer = malloc_or_die(s->buffer_size); | 60 | s->buffer = malloc(s->buffer_size); |
61 | if (s->buffer != NULL) | ||
62 | s->state = TRACE_SEQ__GOOD; | ||
63 | else | ||
64 | s->state = TRACE_SEQ__MEM_ALLOC_FAILED; | ||
49 | } | 65 | } |
50 | 66 | ||
51 | /** | 67 | /** |
@@ -71,17 +87,23 @@ void trace_seq_destroy(struct trace_seq *s) | |||
71 | { | 87 | { |
72 | if (!s) | 88 | if (!s) |
73 | return; | 89 | return; |
74 | TRACE_SEQ_CHECK(s); | 90 | TRACE_SEQ_CHECK_RET(s); |
75 | free(s->buffer); | 91 | free(s->buffer); |
76 | s->buffer = TRACE_SEQ_POISON; | 92 | s->buffer = TRACE_SEQ_POISON; |
77 | } | 93 | } |
78 | 94 | ||
79 | static void expand_buffer(struct trace_seq *s) | 95 | static void expand_buffer(struct trace_seq *s) |
80 | { | 96 | { |
97 | char *buf; | ||
98 | |||
99 | buf = realloc(s->buffer, s->buffer_size + TRACE_SEQ_BUF_SIZE); | ||
100 | if (WARN_ONCE(!buf, "Can't allocate trace_seq buffer memory")) { | ||
101 | s->state = TRACE_SEQ__MEM_ALLOC_FAILED; | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | s->buffer = buf; | ||
81 | s->buffer_size += TRACE_SEQ_BUF_SIZE; | 106 | s->buffer_size += TRACE_SEQ_BUF_SIZE; |
82 | s->buffer = realloc(s->buffer, s->buffer_size); | ||
83 | if (!s->buffer) | ||
84 | die("Can't allocate trace_seq buffer memory"); | ||
85 | } | 107 | } |
86 | 108 | ||
87 | /** | 109 | /** |
@@ -105,9 +127,9 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | |||
105 | int len; | 127 | int len; |
106 | int ret; | 128 | int ret; |
107 | 129 | ||
108 | TRACE_SEQ_CHECK(s); | ||
109 | |||
110 | try_again: | 130 | try_again: |
131 | TRACE_SEQ_CHECK_RET0(s); | ||
132 | |||
111 | len = (s->buffer_size - 1) - s->len; | 133 | len = (s->buffer_size - 1) - s->len; |
112 | 134 | ||
113 | va_start(ap, fmt); | 135 | va_start(ap, fmt); |
@@ -141,9 +163,9 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) | |||
141 | int len; | 163 | int len; |
142 | int ret; | 164 | int ret; |
143 | 165 | ||
144 | TRACE_SEQ_CHECK(s); | ||
145 | |||
146 | try_again: | 166 | try_again: |
167 | TRACE_SEQ_CHECK_RET0(s); | ||
168 | |||
147 | len = (s->buffer_size - 1) - s->len; | 169 | len = (s->buffer_size - 1) - s->len; |
148 | 170 | ||
149 | ret = vsnprintf(s->buffer + s->len, len, fmt, args); | 171 | ret = vsnprintf(s->buffer + s->len, len, fmt, args); |
@@ -172,13 +194,15 @@ int trace_seq_puts(struct trace_seq *s, const char *str) | |||
172 | { | 194 | { |
173 | int len; | 195 | int len; |
174 | 196 | ||
175 | TRACE_SEQ_CHECK(s); | 197 | TRACE_SEQ_CHECK_RET0(s); |
176 | 198 | ||
177 | len = strlen(str); | 199 | len = strlen(str); |
178 | 200 | ||
179 | while (len > ((s->buffer_size - 1) - s->len)) | 201 | while (len > ((s->buffer_size - 1) - s->len)) |
180 | expand_buffer(s); | 202 | expand_buffer(s); |
181 | 203 | ||
204 | TRACE_SEQ_CHECK_RET0(s); | ||
205 | |||
182 | memcpy(s->buffer + s->len, str, len); | 206 | memcpy(s->buffer + s->len, str, len); |
183 | s->len += len; | 207 | s->len += len; |
184 | 208 | ||
@@ -187,11 +211,13 @@ int trace_seq_puts(struct trace_seq *s, const char *str) | |||
187 | 211 | ||
188 | int trace_seq_putc(struct trace_seq *s, unsigned char c) | 212 | int trace_seq_putc(struct trace_seq *s, unsigned char c) |
189 | { | 213 | { |
190 | TRACE_SEQ_CHECK(s); | 214 | TRACE_SEQ_CHECK_RET0(s); |
191 | 215 | ||
192 | while (s->len >= (s->buffer_size - 1)) | 216 | while (s->len >= (s->buffer_size - 1)) |
193 | expand_buffer(s); | 217 | expand_buffer(s); |
194 | 218 | ||
219 | TRACE_SEQ_CHECK_RET0(s); | ||
220 | |||
195 | s->buffer[s->len++] = c; | 221 | s->buffer[s->len++] = c; |
196 | 222 | ||
197 | return 1; | 223 | return 1; |
@@ -199,7 +225,7 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c) | |||
199 | 225 | ||
200 | void trace_seq_terminate(struct trace_seq *s) | 226 | void trace_seq_terminate(struct trace_seq *s) |
201 | { | 227 | { |
202 | TRACE_SEQ_CHECK(s); | 228 | TRACE_SEQ_CHECK_RET(s); |
203 | 229 | ||
204 | /* There's always one character left on the buffer */ | 230 | /* There's always one character left on the buffer */ |
205 | s->buffer[s->len] = 0; | 231 | s->buffer[s->len] = 0; |
@@ -208,5 +234,16 @@ void trace_seq_terminate(struct trace_seq *s) | |||
208 | int trace_seq_do_printf(struct trace_seq *s) | 234 | int trace_seq_do_printf(struct trace_seq *s) |
209 | { | 235 | { |
210 | TRACE_SEQ_CHECK(s); | 236 | TRACE_SEQ_CHECK(s); |
211 | return printf("%.*s", s->len, s->buffer); | 237 | |
238 | switch (s->state) { | ||
239 | case TRACE_SEQ__GOOD: | ||
240 | return printf("%.*s", s->len, s->buffer); | ||
241 | case TRACE_SEQ__BUFFER_POISONED: | ||
242 | puts("Usage of trace_seq after it was destroyed"); | ||
243 | break; | ||
244 | case TRACE_SEQ__MEM_ALLOC_FAILED: | ||
245 | puts("Can't allocate trace_seq buffer memory"); | ||
246 | break; | ||
247 | } | ||
248 | return -1; | ||
212 | } | 249 | } |
diff --git a/tools/perf/Documentation/perf-archive.txt b/tools/perf/Documentation/perf-archive.txt index 5032a142853e..ac6ecbb3e669 100644 --- a/tools/perf/Documentation/perf-archive.txt +++ b/tools/perf/Documentation/perf-archive.txt | |||
@@ -12,9 +12,9 @@ SYNOPSIS | |||
12 | 12 | ||
13 | DESCRIPTION | 13 | DESCRIPTION |
14 | ----------- | 14 | ----------- |
15 | This command runs runs perf-buildid-list --with-hits, and collects the files | 15 | This command runs perf-buildid-list --with-hits, and collects the files with the |
16 | with the buildids found so that analysis of perf.data contents can be possible | 16 | buildids found so that analysis of perf.data contents can be possible on another |
17 | on another machine. | 17 | machine. |
18 | 18 | ||
19 | 19 | ||
20 | SEE ALSO | 20 | SEE ALSO |
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt index 6a06cefe9642..52276a6d2b75 100644 --- a/tools/perf/Documentation/perf-kvm.txt +++ b/tools/perf/Documentation/perf-kvm.txt | |||
@@ -10,9 +10,9 @@ SYNOPSIS | |||
10 | [verse] | 10 | [verse] |
11 | 'perf kvm' [--host] [--guest] [--guestmount=<path> | 11 | 'perf kvm' [--host] [--guest] [--guestmount=<path> |
12 | [--guestkallsyms=<path> --guestmodules=<path> | --guestvmlinux=<path>]] | 12 | [--guestkallsyms=<path> --guestmodules=<path> | --guestvmlinux=<path>]] |
13 | {top|record|report|diff|buildid-list} | 13 | {top|record|report|diff|buildid-list} [<options>] |
14 | 'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path> | 14 | 'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path> |
15 | | --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat} | 15 | | --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat} [<options>] |
16 | 'perf kvm stat [record|report|live] [<options>] | 16 | 'perf kvm stat [record|report|live] [<options>] |
17 | 17 | ||
18 | DESCRIPTION | 18 | DESCRIPTION |
@@ -24,10 +24,17 @@ There are a couple of variants of perf kvm: | |||
24 | of an arbitrary workload. | 24 | of an arbitrary workload. |
25 | 25 | ||
26 | 'perf kvm record <command>' to record the performance counter profile | 26 | 'perf kvm record <command>' to record the performance counter profile |
27 | of an arbitrary workload and save it into a perf data file. If both | 27 | of an arbitrary workload and save it into a perf data file. We set the |
28 | --host and --guest are input, the perf data file name is perf.data.kvm. | 28 | default behavior of perf kvm as --guest, so if neither --host nor --guest |
29 | If there is no --host but --guest, the file name is perf.data.guest. | 29 | is input, the perf data file name is perf.data.guest. If --host is input, |
30 | If there is no --guest but --host, the file name is perf.data.host. | 30 | the perf data file name is perf.data.kvm. If you want to record data into |
31 | perf.data.host, please input --host --no-guest. The behaviors are shown as | ||
32 | following: | ||
33 | Default('') -> perf.data.guest | ||
34 | --host -> perf.data.kvm | ||
35 | --guest -> perf.data.guest | ||
36 | --host --guest -> perf.data.kvm | ||
37 | --host --no-guest -> perf.data.host | ||
31 | 38 | ||
32 | 'perf kvm report' to display the performance counter profile information | 39 | 'perf kvm report' to display the performance counter profile information |
33 | recorded via perf kvm record. | 40 | recorded via perf kvm record. |
@@ -37,7 +44,9 @@ There are a couple of variants of perf kvm: | |||
37 | 44 | ||
38 | 'perf kvm buildid-list' to display the buildids found in a perf data file, | 45 | 'perf kvm buildid-list' to display the buildids found in a perf data file, |
39 | so that other tools can be used to fetch packages with matching symbol tables | 46 | so that other tools can be used to fetch packages with matching symbol tables |
40 | for use by perf report. | 47 | for use by perf report. As buildid is read from /sys/kernel/notes in os, then |
48 | if you want to list the buildid for guest, please make sure your perf data file | ||
49 | was captured with --guestmount in perf kvm record. | ||
41 | 50 | ||
42 | 'perf kvm stat <command>' to run a command and gather performance counter | 51 | 'perf kvm stat <command>' to run a command and gather performance counter |
43 | statistics. | 52 | statistics. |
@@ -58,14 +67,14 @@ There are a couple of variants of perf kvm: | |||
58 | OPTIONS | 67 | OPTIONS |
59 | ------- | 68 | ------- |
60 | -i:: | 69 | -i:: |
61 | --input=:: | 70 | --input=<path>:: |
62 | Input file name. | 71 | Input file name. |
63 | -o:: | 72 | -o:: |
64 | --output:: | 73 | --output=<path>:: |
65 | Output file name. | 74 | Output file name. |
66 | --host=:: | 75 | --host:: |
67 | Collect host side performance profile. | 76 | Collect host side performance profile. |
68 | --guest=:: | 77 | --guest:: |
69 | Collect guest side performance profile. | 78 | Collect guest side performance profile. |
70 | --guestmount=<path>:: | 79 | --guestmount=<path>:: |
71 | Guest os root file system mount directory. Users mounts guest os | 80 | Guest os root file system mount directory. Users mounts guest os |
@@ -84,6 +93,9 @@ OPTIONS | |||
84 | kernel module information. Users copy it out from guest os. | 93 | kernel module information. Users copy it out from guest os. |
85 | --guestvmlinux=<path>:: | 94 | --guestvmlinux=<path>:: |
86 | Guest os kernel vmlinux. | 95 | Guest os kernel vmlinux. |
96 | -v:: | ||
97 | --verbose:: | ||
98 | Be more verbose (show counter open errors, etc). | ||
87 | 99 | ||
88 | STAT REPORT OPTIONS | 100 | STAT REPORT OPTIONS |
89 | ------------------- | 101 | ------------------- |
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 43b42c4f4a91..c71b0f36d9e8 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -57,6 +57,8 @@ OPTIONS | |||
57 | -t:: | 57 | -t:: |
58 | --tid=:: | 58 | --tid=:: |
59 | Record events on existing thread ID (comma separated list). | 59 | Record events on existing thread ID (comma separated list). |
60 | This option also disables inheritance by default. Enable it by adding | ||
61 | --inherit. | ||
60 | 62 | ||
61 | -u:: | 63 | -u:: |
62 | --uid=:: | 64 | --uid=:: |
@@ -66,8 +68,7 @@ OPTIONS | |||
66 | --realtime=:: | 68 | --realtime=:: |
67 | Collect data with this RT SCHED_FIFO priority. | 69 | Collect data with this RT SCHED_FIFO priority. |
68 | 70 | ||
69 | -D:: | 71 | --no-buffering:: |
70 | --no-delay:: | ||
71 | Collect data without buffering. | 72 | Collect data without buffering. |
72 | 73 | ||
73 | -c:: | 74 | -c:: |
@@ -201,11 +202,16 @@ abort events and some memory events in precise mode on modern Intel CPUs. | |||
201 | --transaction:: | 202 | --transaction:: |
202 | Record transaction flags for transaction related events. | 203 | Record transaction flags for transaction related events. |
203 | 204 | ||
204 | --force-per-cpu:: | 205 | --per-thread:: |
205 | Force the use of per-cpu mmaps. By default, when tasks are specified (i.e. -p, | 206 | Use per-thread mmaps. By default per-cpu mmaps are created. This option |
206 | -t or -u options) per-thread mmaps are created. This option overrides that and | 207 | overrides that and uses per-thread mmaps. A side-effect of that is that |
207 | forces per-cpu mmaps. A side-effect of that is that inheritance is | 208 | inheritance is automatically disabled. --per-thread is ignored with a warning |
208 | automatically enabled. Add the -i option also to disable inheritance. | 209 | if combined with -a or -C options. |
210 | |||
211 | -D:: | ||
212 | --delay=:: | ||
213 | After starting the program, wait msecs before measuring. This is useful to | ||
214 | filter out the startup phase of the program, which is often very different. | ||
209 | 215 | ||
210 | SEE ALSO | 216 | SEE ALSO |
211 | -------- | 217 | -------- |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 10a279871251..8eab8a4bdeb8 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -237,6 +237,15 @@ OPTIONS | |||
237 | Do not show entries which have an overhead under that percent. | 237 | Do not show entries which have an overhead under that percent. |
238 | (Default: 0). | 238 | (Default: 0). |
239 | 239 | ||
240 | --header:: | ||
241 | Show header information in the perf.data file. This includes | ||
242 | various information like hostname, OS and perf version, cpu/mem | ||
243 | info, perf command line, event list and so on. Currently only | ||
244 | --stdio output supports this feature. | ||
245 | |||
246 | --header-only:: | ||
247 | Show only perf.data header (forces --stdio). | ||
248 | |||
240 | SEE ALSO | 249 | SEE ALSO |
241 | -------- | 250 | -------- |
242 | linkperf:perf-stat[1], linkperf:perf-annotate[1] | 251 | linkperf:perf-stat[1], linkperf:perf-annotate[1] |
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index e9cbfcddfa3f..05f9a0a6784c 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt | |||
@@ -115,7 +115,7 @@ OPTIONS | |||
115 | -f:: | 115 | -f:: |
116 | --fields:: | 116 | --fields:: |
117 | Comma separated list of fields to print. Options are: | 117 | Comma separated list of fields to print. Options are: |
118 | comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff. | 118 | comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline. |
119 | Field list can be prepended with the type, trace, sw or hw, | 119 | Field list can be prepended with the type, trace, sw or hw, |
120 | to indicate to which event type the field list applies. | 120 | to indicate to which event type the field list applies. |
121 | e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace | 121 | e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace |
@@ -203,6 +203,18 @@ OPTIONS | |||
203 | --show-kernel-path:: | 203 | --show-kernel-path:: |
204 | Try to resolve the path of [kernel.kallsyms] | 204 | Try to resolve the path of [kernel.kallsyms] |
205 | 205 | ||
206 | --show-task-events | ||
207 | Display task related events (e.g. FORK, COMM, EXIT). | ||
208 | |||
209 | --show-mmap-events | ||
210 | Display mmap related events (e.g. MMAP, MMAP2). | ||
211 | |||
212 | --header | ||
213 | Show perf.data header. | ||
214 | |||
215 | --header-only | ||
216 | Show only perf.data header. | ||
217 | |||
206 | SEE ALSO | 218 | SEE ALSO |
207 | -------- | 219 | -------- |
208 | linkperf:perf-record[1], linkperf:perf-script-perl[1], | 220 | linkperf:perf-record[1], linkperf:perf-script-perl[1], |
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 80c7da6732f2..29ee857c09c6 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt | |||
@@ -133,7 +133,7 @@ use --per-core in addition to -a. (system-wide). The output includes the | |||
133 | core number and the number of online logical processors on that physical processor. | 133 | core number and the number of online logical processors on that physical processor. |
134 | 134 | ||
135 | -D msecs:: | 135 | -D msecs:: |
136 | --initial-delay msecs:: | 136 | --delay msecs:: |
137 | After starting the program, wait msecs before measuring. This is useful to | 137 | After starting the program, wait msecs before measuring. This is useful to |
138 | filter out the startup phase of the program, which is often very different. | 138 | filter out the startup phase of the program, which is often very different. |
139 | 139 | ||
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt index 3ff8bd4f0b4d..bc5990c33dc0 100644 --- a/tools/perf/Documentation/perf-timechart.txt +++ b/tools/perf/Documentation/perf-timechart.txt | |||
@@ -8,8 +8,7 @@ perf-timechart - Tool to visualize total system behavior during a workload | |||
8 | SYNOPSIS | 8 | SYNOPSIS |
9 | -------- | 9 | -------- |
10 | [verse] | 10 | [verse] |
11 | 'perf timechart' record <command> | 11 | 'perf timechart' [<timechart options>] {record} [<record options>] |
12 | 'perf timechart' [<options>] | ||
13 | 12 | ||
14 | DESCRIPTION | 13 | DESCRIPTION |
15 | ----------- | 14 | ----------- |
@@ -21,8 +20,8 @@ There are two variants of perf timechart: | |||
21 | 'perf timechart' to turn a trace into a Scalable Vector Graphics file, | 20 | 'perf timechart' to turn a trace into a Scalable Vector Graphics file, |
22 | that can be viewed with popular SVG viewers such as 'Inkscape'. | 21 | that can be viewed with popular SVG viewers such as 'Inkscape'. |
23 | 22 | ||
24 | OPTIONS | 23 | TIMECHART OPTIONS |
25 | ------- | 24 | ----------------- |
26 | -o:: | 25 | -o:: |
27 | --output=:: | 26 | --output=:: |
28 | Select the output file (default: output.svg) | 27 | Select the output file (default: output.svg) |
@@ -35,6 +34,9 @@ OPTIONS | |||
35 | -P:: | 34 | -P:: |
36 | --power-only:: | 35 | --power-only:: |
37 | Only output the CPU power section of the diagram | 36 | Only output the CPU power section of the diagram |
37 | -T:: | ||
38 | --tasks-only:: | ||
39 | Don't output processor state transitions | ||
38 | -p:: | 40 | -p:: |
39 | --process:: | 41 | --process:: |
40 | Select the processes to display, by name or PID | 42 | Select the processes to display, by name or PID |
@@ -54,6 +56,38 @@ $ perf timechart | |||
54 | 56 | ||
55 | Written 10.2 seconds of trace to output.svg. | 57 | Written 10.2 seconds of trace to output.svg. |
56 | 58 | ||
59 | Record system-wide timechart: | ||
60 | |||
61 | $ perf timechart record | ||
62 | |||
63 | then generate timechart and highlight 'gcc' tasks: | ||
64 | |||
65 | $ perf timechart --highlight gcc | ||
66 | |||
67 | -n:: | ||
68 | --proc-num:: | ||
69 | Print task info for at least given number of tasks. | ||
70 | -t:: | ||
71 | --topology:: | ||
72 | Sort CPUs according to topology. | ||
73 | --highlight=<duration_nsecs|task_name>:: | ||
74 | Highlight tasks (using different color) that run more than given | ||
75 | duration or tasks with given name. If number is given it's interpreted | ||
76 | as number of nanoseconds. If non-numeric string is given it's | ||
77 | interpreted as task name. | ||
78 | |||
79 | RECORD OPTIONS | ||
80 | -------------- | ||
81 | -P:: | ||
82 | --power-only:: | ||
83 | Record only power-related events | ||
84 | -T:: | ||
85 | --tasks-only:: | ||
86 | Record only tasks-related events | ||
87 | -g:: | ||
88 | --callchain:: | ||
89 | Do call-graph (stack chain/backtrace) recording | ||
90 | |||
57 | SEE ALSO | 91 | SEE ALSO |
58 | -------- | 92 | -------- |
59 | linkperf:perf-record[1] | 93 | linkperf:perf-record[1] |
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 7de01dd79688..cdd8d4946dba 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -50,7 +50,6 @@ Default is to monitor all CPUS. | |||
50 | --count-filter=<count>:: | 50 | --count-filter=<count>:: |
51 | Only display functions with more events than this. | 51 | Only display functions with more events than this. |
52 | 52 | ||
53 | -g:: | ||
54 | --group:: | 53 | --group:: |
55 | Put the counters into a counter group. | 54 | Put the counters into a counter group. |
56 | 55 | ||
@@ -143,12 +142,12 @@ Default is to monitor all CPUS. | |||
143 | --asm-raw:: | 142 | --asm-raw:: |
144 | Show raw instruction encoding of assembly instructions. | 143 | Show raw instruction encoding of assembly instructions. |
145 | 144 | ||
146 | -G:: | 145 | -g:: |
147 | Enables call-graph (stack chain/backtrace) recording. | 146 | Enables call-graph (stack chain/backtrace) recording. |
148 | 147 | ||
149 | --call-graph:: | 148 | --call-graph:: |
150 | Setup and enable call-graph (stack chain/backtrace) recording, | 149 | Setup and enable call-graph (stack chain/backtrace) recording, |
151 | implies -G. | 150 | implies -g. |
152 | 151 | ||
153 | --max-stack:: | 152 | --max-stack:: |
154 | Set the stack depth limit when parsing the callchain, anything | 153 | Set the stack depth limit when parsing the callchain, anything |
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index 025de796067c..f41572d0dd76 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
@@ -1,7 +1,11 @@ | |||
1 | tools/perf | 1 | tools/perf |
2 | tools/scripts | 2 | tools/scripts |
3 | tools/lib/traceevent | 3 | tools/lib/traceevent |
4 | tools/lib/lk | 4 | tools/lib/api |
5 | tools/lib/symbol/kallsyms.c | ||
6 | tools/lib/symbol/kallsyms.h | ||
7 | tools/include/asm/bug.h | ||
8 | tools/include/linux/compiler.h | ||
5 | include/linux/const.h | 9 | include/linux/const.h |
6 | include/linux/perf_event.h | 10 | include/linux/perf_event.h |
7 | include/linux/rbtree.h | 11 | include/linux/rbtree.h |
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 4835618a5608..cb2e5868c8e8 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -60,8 +60,11 @@ endef | |||
60 | 60 | ||
61 | # | 61 | # |
62 | # Needed if no target specified: | 62 | # Needed if no target specified: |
63 | # (Except for tags and TAGS targets. The reason is that the | ||
64 | # Makefile does not treat tags/TAGS as targets but as files | ||
65 | # and thus won't rebuilt them once they are in place.) | ||
63 | # | 66 | # |
64 | all: | 67 | all tags TAGS: |
65 | $(print_msg) | 68 | $(print_msg) |
66 | $(make) | 69 | $(make) |
67 | 70 | ||
@@ -72,8 +75,16 @@ clean: | |||
72 | $(make) | 75 | $(make) |
73 | 76 | ||
74 | # | 77 | # |
78 | # The build-test target is not really parallel, don't print the jobs info: | ||
79 | # | ||
80 | build-test: | ||
81 | @$(MAKE) -f tests/make --no-print-directory | ||
82 | |||
83 | # | ||
75 | # All other targets get passed through: | 84 | # All other targets get passed through: |
76 | # | 85 | # |
77 | %: | 86 | %: |
78 | $(print_msg) | 87 | $(print_msg) |
79 | $(make) | 88 | $(make) |
89 | |||
90 | .PHONY: tags TAGS | ||
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 7fc8f179cae7..7257e7e9e38a 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -76,6 +76,7 @@ $(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD | |||
76 | 76 | ||
77 | CC = $(CROSS_COMPILE)gcc | 77 | CC = $(CROSS_COMPILE)gcc |
78 | AR = $(CROSS_COMPILE)ar | 78 | AR = $(CROSS_COMPILE)ar |
79 | PKG_CONFIG = $(CROSS_COMPILE)pkg-config | ||
79 | 80 | ||
80 | RM = rm -f | 81 | RM = rm -f |
81 | LN = ln -f | 82 | LN = ln -f |
@@ -86,7 +87,7 @@ FLEX = flex | |||
86 | BISON = bison | 87 | BISON = bison |
87 | STRIP = strip | 88 | STRIP = strip |
88 | 89 | ||
89 | LK_DIR = $(srctree)/tools/lib/lk/ | 90 | LIB_DIR = $(srctree)/tools/lib/api/ |
90 | TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ | 91 | TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ |
91 | 92 | ||
92 | # include config/Makefile by default and rule out | 93 | # include config/Makefile by default and rule out |
@@ -105,7 +106,7 @@ ifeq ($(config),1) | |||
105 | include config/Makefile | 106 | include config/Makefile |
106 | endif | 107 | endif |
107 | 108 | ||
108 | export prefix bindir sharedir sysconfdir | 109 | export prefix bindir sharedir sysconfdir DESTDIR |
109 | 110 | ||
110 | # sparse is architecture-neutral, which means that we need to tell it | 111 | # sparse is architecture-neutral, which means that we need to tell it |
111 | # explicitly what architecture to check for. Fix this up for yours.. | 112 | # explicitly what architecture to check for. Fix this up for yours.. |
@@ -127,20 +128,20 @@ strip-libs = $(filter-out -l%,$(1)) | |||
127 | ifneq ($(OUTPUT),) | 128 | ifneq ($(OUTPUT),) |
128 | TE_PATH=$(OUTPUT) | 129 | TE_PATH=$(OUTPUT) |
129 | ifneq ($(subdir),) | 130 | ifneq ($(subdir),) |
130 | LK_PATH=$(OUTPUT)/../lib/lk/ | 131 | LIB_PATH=$(OUTPUT)/../lib/api/ |
131 | else | 132 | else |
132 | LK_PATH=$(OUTPUT) | 133 | LIB_PATH=$(OUTPUT) |
133 | endif | 134 | endif |
134 | else | 135 | else |
135 | TE_PATH=$(TRACE_EVENT_DIR) | 136 | TE_PATH=$(TRACE_EVENT_DIR) |
136 | LK_PATH=$(LK_DIR) | 137 | LIB_PATH=$(LIB_DIR) |
137 | endif | 138 | endif |
138 | 139 | ||
139 | LIBTRACEEVENT = $(TE_PATH)libtraceevent.a | 140 | LIBTRACEEVENT = $(TE_PATH)libtraceevent.a |
140 | export LIBTRACEEVENT | 141 | export LIBTRACEEVENT |
141 | 142 | ||
142 | LIBLK = $(LK_PATH)liblk.a | 143 | LIBAPIKFS = $(LIB_PATH)libapikfs.a |
143 | export LIBLK | 144 | export LIBAPIKFS |
144 | 145 | ||
145 | # python extension build directories | 146 | # python extension build directories |
146 | PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ | 147 | PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ |
@@ -151,7 +152,7 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP | |||
151 | python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so | 152 | python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so |
152 | 153 | ||
153 | PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) | 154 | PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) |
154 | PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK) | 155 | PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPIKFS) |
155 | 156 | ||
156 | $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) | 157 | $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) |
157 | $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ | 158 | $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ |
@@ -202,6 +203,7 @@ $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c | |||
202 | 203 | ||
203 | LIB_FILE=$(OUTPUT)libperf.a | 204 | LIB_FILE=$(OUTPUT)libperf.a |
204 | 205 | ||
206 | LIB_H += ../lib/symbol/kallsyms.h | ||
205 | LIB_H += ../../include/uapi/linux/perf_event.h | 207 | LIB_H += ../../include/uapi/linux/perf_event.h |
206 | LIB_H += ../../include/linux/rbtree.h | 208 | LIB_H += ../../include/linux/rbtree.h |
207 | LIB_H += ../../include/linux/list.h | 209 | LIB_H += ../../include/linux/list.h |
@@ -210,7 +212,7 @@ LIB_H += ../../include/linux/hash.h | |||
210 | LIB_H += ../../include/linux/stringify.h | 212 | LIB_H += ../../include/linux/stringify.h |
211 | LIB_H += util/include/linux/bitmap.h | 213 | LIB_H += util/include/linux/bitmap.h |
212 | LIB_H += util/include/linux/bitops.h | 214 | LIB_H += util/include/linux/bitops.h |
213 | LIB_H += util/include/linux/compiler.h | 215 | LIB_H += ../include/linux/compiler.h |
214 | LIB_H += util/include/linux/const.h | 216 | LIB_H += util/include/linux/const.h |
215 | LIB_H += util/include/linux/ctype.h | 217 | LIB_H += util/include/linux/ctype.h |
216 | LIB_H += util/include/linux/kernel.h | 218 | LIB_H += util/include/linux/kernel.h |
@@ -225,7 +227,7 @@ LIB_H += util/include/linux/string.h | |||
225 | LIB_H += util/include/linux/types.h | 227 | LIB_H += util/include/linux/types.h |
226 | LIB_H += util/include/linux/linkage.h | 228 | LIB_H += util/include/linux/linkage.h |
227 | LIB_H += util/include/asm/asm-offsets.h | 229 | LIB_H += util/include/asm/asm-offsets.h |
228 | LIB_H += util/include/asm/bug.h | 230 | LIB_H += ../include/asm/bug.h |
229 | LIB_H += util/include/asm/byteorder.h | 231 | LIB_H += util/include/asm/byteorder.h |
230 | LIB_H += util/include/asm/hweight.h | 232 | LIB_H += util/include/asm/hweight.h |
231 | LIB_H += util/include/asm/swab.h | 233 | LIB_H += util/include/asm/swab.h |
@@ -312,6 +314,7 @@ LIB_OBJS += $(OUTPUT)util/evlist.o | |||
312 | LIB_OBJS += $(OUTPUT)util/evsel.o | 314 | LIB_OBJS += $(OUTPUT)util/evsel.o |
313 | LIB_OBJS += $(OUTPUT)util/exec_cmd.o | 315 | LIB_OBJS += $(OUTPUT)util/exec_cmd.o |
314 | LIB_OBJS += $(OUTPUT)util/help.o | 316 | LIB_OBJS += $(OUTPUT)util/help.o |
317 | LIB_OBJS += $(OUTPUT)util/kallsyms.o | ||
315 | LIB_OBJS += $(OUTPUT)util/levenshtein.o | 318 | LIB_OBJS += $(OUTPUT)util/levenshtein.o |
316 | LIB_OBJS += $(OUTPUT)util/parse-options.o | 319 | LIB_OBJS += $(OUTPUT)util/parse-options.o |
317 | LIB_OBJS += $(OUTPUT)util/parse-events.o | 320 | LIB_OBJS += $(OUTPUT)util/parse-events.o |
@@ -353,6 +356,7 @@ LIB_OBJS += $(OUTPUT)util/pmu-bison.o | |||
353 | LIB_OBJS += $(OUTPUT)util/trace-event-read.o | 356 | LIB_OBJS += $(OUTPUT)util/trace-event-read.o |
354 | LIB_OBJS += $(OUTPUT)util/trace-event-info.o | 357 | LIB_OBJS += $(OUTPUT)util/trace-event-info.o |
355 | LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o | 358 | LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o |
359 | LIB_OBJS += $(OUTPUT)util/trace-event.o | ||
356 | LIB_OBJS += $(OUTPUT)util/svghelper.o | 360 | LIB_OBJS += $(OUTPUT)util/svghelper.o |
357 | LIB_OBJS += $(OUTPUT)util/sort.o | 361 | LIB_OBJS += $(OUTPUT)util/sort.o |
358 | LIB_OBJS += $(OUTPUT)util/hist.o | 362 | LIB_OBJS += $(OUTPUT)util/hist.o |
@@ -438,7 +442,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o | |||
438 | BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o | 442 | BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o |
439 | BUILTIN_OBJS += $(OUTPUT)builtin-mem.o | 443 | BUILTIN_OBJS += $(OUTPUT)builtin-mem.o |
440 | 444 | ||
441 | PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT) | 445 | PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT) |
442 | 446 | ||
443 | # We choose to avoid "if .. else if .. else .. endif endif" | 447 | # We choose to avoid "if .. else if .. else .. endif endif" |
444 | # because maintaining the nesting to match is a pain. If | 448 | # because maintaining the nesting to match is a pain. If |
@@ -486,6 +490,7 @@ ifndef NO_SLANG | |||
486 | LIB_OBJS += $(OUTPUT)ui/browsers/hists.o | 490 | LIB_OBJS += $(OUTPUT)ui/browsers/hists.o |
487 | LIB_OBJS += $(OUTPUT)ui/browsers/map.o | 491 | LIB_OBJS += $(OUTPUT)ui/browsers/map.o |
488 | LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o | 492 | LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o |
493 | LIB_OBJS += $(OUTPUT)ui/browsers/header.o | ||
489 | LIB_OBJS += $(OUTPUT)ui/tui/setup.o | 494 | LIB_OBJS += $(OUTPUT)ui/tui/setup.o |
490 | LIB_OBJS += $(OUTPUT)ui/tui/util.o | 495 | LIB_OBJS += $(OUTPUT)ui/tui/util.o |
491 | LIB_OBJS += $(OUTPUT)ui/tui/helpline.o | 496 | LIB_OBJS += $(OUTPUT)ui/tui/helpline.o |
@@ -671,6 +676,9 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS | |||
671 | $(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS | 676 | $(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS |
672 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< | 677 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< |
673 | 678 | ||
679 | $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS | ||
680 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $< | ||
681 | |||
674 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS | 682 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS |
675 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | 683 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< |
676 | 684 | ||
@@ -710,26 +718,33 @@ $(LIB_FILE): $(LIB_OBJS) | |||
710 | # libtraceevent.a | 718 | # libtraceevent.a |
711 | TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch]) | 719 | TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch]) |
712 | 720 | ||
713 | $(LIBTRACEEVENT): $(TE_SOURCES) | 721 | LIBTRACEEVENT_FLAGS = $(QUIET_SUBDIR1) O=$(OUTPUT) |
714 | $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) CFLAGS="-g -Wall $(EXTRA_CFLAGS)" libtraceevent.a | 722 | LIBTRACEEVENT_FLAGS += CFLAGS="-g -Wall $(EXTRA_CFLAGS)" |
723 | LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) | ||
724 | |||
725 | $(LIBTRACEEVENT): $(TE_SOURCES) $(OUTPUT)PERF-CFLAGS | ||
726 | $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) libtraceevent.a plugins | ||
715 | 727 | ||
716 | $(LIBTRACEEVENT)-clean: | 728 | $(LIBTRACEEVENT)-clean: |
717 | $(call QUIET_CLEAN, libtraceevent) | 729 | $(call QUIET_CLEAN, libtraceevent) |
718 | @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null | 730 | @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null |
719 | 731 | ||
720 | LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch]) | 732 | install-traceevent-plugins: $(LIBTRACEEVENT) |
733 | $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins | ||
734 | |||
735 | LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch]) | ||
721 | 736 | ||
722 | # if subdir is set, we've been called from above so target has been built | 737 | # if subdir is set, we've been called from above so target has been built |
723 | # already | 738 | # already |
724 | $(LIBLK): $(LIBLK_SOURCES) | 739 | $(LIBAPIKFS): $(LIBAPIKFS_SOURCES) |
725 | ifeq ($(subdir),) | 740 | ifeq ($(subdir),) |
726 | $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a | 741 | $(QUIET_SUBDIR0)$(LIB_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libapikfs.a |
727 | endif | 742 | endif |
728 | 743 | ||
729 | $(LIBLK)-clean: | 744 | $(LIBAPIKFS)-clean: |
730 | ifeq ($(subdir),) | 745 | ifeq ($(subdir),) |
731 | $(call QUIET_CLEAN, liblk) | 746 | $(call QUIET_CLEAN, libapikfs) |
732 | @$(MAKE) -C $(LK_DIR) O=$(OUTPUT) clean >/dev/null | 747 | @$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null |
733 | endif | 748 | endif |
734 | 749 | ||
735 | help: | 750 | help: |
@@ -785,7 +800,7 @@ cscope: | |||
785 | 800 | ||
786 | ### Detect prefix changes | 801 | ### Detect prefix changes |
787 | TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\ | 802 | TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\ |
788 | $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) | 803 | $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):$(plugindir_SQ) |
789 | 804 | ||
790 | $(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS | 805 | $(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS |
791 | @FLAGS='$(TRACK_CFLAGS)'; \ | 806 | @FLAGS='$(TRACK_CFLAGS)'; \ |
@@ -840,16 +855,16 @@ ifndef NO_LIBPYTHON | |||
840 | $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \ | 855 | $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \ |
841 | $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' | 856 | $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' |
842 | endif | 857 | endif |
843 | $(call QUIET_INSTALL, bash_completion-script) \ | 858 | $(call QUIET_INSTALL, perf_completion-script) \ |
844 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \ | 859 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \ |
845 | $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' | 860 | $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' |
846 | $(call QUIET_INSTALL, tests) \ | 861 | $(call QUIET_INSTALL, tests) \ |
847 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ | 862 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ |
848 | $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ | 863 | $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ |
849 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ | 864 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ |
850 | $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' | 865 | $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' |
851 | 866 | ||
852 | install: install-bin try-install-man | 867 | install: install-bin try-install-man install-traceevent-plugins |
853 | 868 | ||
854 | install-python_ext: | 869 | install-python_ext: |
855 | $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' | 870 | $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' |
@@ -868,12 +883,11 @@ config-clean: | |||
868 | $(call QUIET_CLEAN, config) | 883 | $(call QUIET_CLEAN, config) |
869 | @$(MAKE) -C config/feature-checks clean >/dev/null | 884 | @$(MAKE) -C config/feature-checks clean >/dev/null |
870 | 885 | ||
871 | clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean config-clean | 886 | clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean |
872 | $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) | 887 | $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) |
873 | $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf | 888 | $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf |
874 | $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* | 889 | $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* |
875 | $(call QUIET_CLEAN, Documentation) | 890 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean |
876 | @$(MAKE) -C Documentation O=$(OUTPUT) clean >/dev/null | ||
877 | $(python-clean) | 891 | $(python-clean) |
878 | 892 | ||
879 | # | 893 | # |
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index aacef07ebf31..42faf369211c 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c | |||
@@ -154,8 +154,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, | |||
154 | } | 154 | } |
155 | if (lookup_path(buf)) | 155 | if (lookup_path(buf)) |
156 | goto out; | 156 | goto out; |
157 | free(buf); | 157 | zfree(&buf); |
158 | buf = NULL; | ||
159 | } | 158 | } |
160 | 159 | ||
161 | if (!strcmp(arch, "arm")) | 160 | if (!strcmp(arch, "arm")) |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 4087ab19823c..0da603b79b61 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -69,15 +69,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, | |||
69 | if (he == NULL) | 69 | if (he == NULL) |
70 | return -ENOMEM; | 70 | return -ENOMEM; |
71 | 71 | ||
72 | ret = 0; | 72 | ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); |
73 | if (he->ms.sym != NULL) { | ||
74 | struct annotation *notes = symbol__annotation(he->ms.sym); | ||
75 | if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0) | ||
76 | return -ENOMEM; | ||
77 | |||
78 | ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); | ||
79 | } | ||
80 | |||
81 | evsel->hists.stats.total_period += sample->period; | 73 | evsel->hists.stats.total_period += sample->period; |
82 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); | 74 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
83 | return ret; | 75 | return ret; |
@@ -188,8 +180,7 @@ find_next: | |||
188 | * symbol, free he->ms.sym->src to signal we already | 180 | * symbol, free he->ms.sym->src to signal we already |
189 | * processed this symbol. | 181 | * processed this symbol. |
190 | */ | 182 | */ |
191 | free(notes->src); | 183 | zfree(¬es->src); |
192 | notes->src = NULL; | ||
193 | } | 184 | } |
194 | } | 185 | } |
195 | } | 186 | } |
@@ -241,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
241 | perf_session__fprintf_dsos(session, stdout); | 232 | perf_session__fprintf_dsos(session, stdout); |
242 | 233 | ||
243 | total_nr_samples = 0; | 234 | total_nr_samples = 0; |
244 | list_for_each_entry(pos, &session->evlist->entries, node) { | 235 | evlist__for_each(session->evlist, pos) { |
245 | struct hists *hists = &pos->hists; | 236 | struct hists *hists = &pos->hists; |
246 | u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; | 237 | u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; |
247 | 238 | ||
@@ -373,7 +364,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
373 | 364 | ||
374 | if (argc) { | 365 | if (argc) { |
375 | /* | 366 | /* |
376 | * Special case: if there's an argument left then assume tha | 367 | * Special case: if there's an argument left then assume that |
377 | * it's a symbol filter: | 368 | * it's a symbol filter: |
378 | */ | 369 | */ |
379 | if (argc > 1) | 370 | if (argc > 1) |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 3b67ea2444bd..a77e31246c00 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -356,9 +356,10 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel, | |||
356 | { | 356 | { |
357 | struct perf_evsel *e; | 357 | struct perf_evsel *e; |
358 | 358 | ||
359 | list_for_each_entry(e, &evlist->entries, node) | 359 | evlist__for_each(evlist, e) { |
360 | if (perf_evsel__match2(evsel, e)) | 360 | if (perf_evsel__match2(evsel, e)) |
361 | return e; | 361 | return e; |
362 | } | ||
362 | 363 | ||
363 | return NULL; | 364 | return NULL; |
364 | } | 365 | } |
@@ -367,7 +368,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist) | |||
367 | { | 368 | { |
368 | struct perf_evsel *evsel; | 369 | struct perf_evsel *evsel; |
369 | 370 | ||
370 | list_for_each_entry(evsel, &evlist->entries, node) { | 371 | evlist__for_each(evlist, evsel) { |
371 | struct hists *hists = &evsel->hists; | 372 | struct hists *hists = &evsel->hists; |
372 | 373 | ||
373 | hists__collapse_resort(hists, NULL); | 374 | hists__collapse_resort(hists, NULL); |
@@ -614,7 +615,7 @@ static void data_process(void) | |||
614 | struct perf_evsel *evsel_base; | 615 | struct perf_evsel *evsel_base; |
615 | bool first = true; | 616 | bool first = true; |
616 | 617 | ||
617 | list_for_each_entry(evsel_base, &evlist_base->entries, node) { | 618 | evlist__for_each(evlist_base, evsel_base) { |
618 | struct data__file *d; | 619 | struct data__file *d; |
619 | int i; | 620 | int i; |
620 | 621 | ||
@@ -654,7 +655,7 @@ static void data__free(struct data__file *d) | |||
654 | for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) { | 655 | for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) { |
655 | struct diff_hpp_fmt *fmt = &d->fmt[col]; | 656 | struct diff_hpp_fmt *fmt = &d->fmt[col]; |
656 | 657 | ||
657 | free(fmt->header); | 658 | zfree(&fmt->header); |
658 | } | 659 | } |
659 | } | 660 | } |
660 | 661 | ||
@@ -769,6 +770,81 @@ static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size) | |||
769 | return ret; | 770 | return ret; |
770 | } | 771 | } |
771 | 772 | ||
773 | static int __hpp__color_compare(struct perf_hpp_fmt *fmt, | ||
774 | struct perf_hpp *hpp, struct hist_entry *he, | ||
775 | int comparison_method) | ||
776 | { | ||
777 | struct diff_hpp_fmt *dfmt = | ||
778 | container_of(fmt, struct diff_hpp_fmt, fmt); | ||
779 | struct hist_entry *pair = get_pair_fmt(he, dfmt); | ||
780 | double diff; | ||
781 | s64 wdiff; | ||
782 | char pfmt[20] = " "; | ||
783 | |||
784 | if (!pair) | ||
785 | goto dummy_print; | ||
786 | |||
787 | switch (comparison_method) { | ||
788 | case COMPUTE_DELTA: | ||
789 | if (pair->diff.computed) | ||
790 | diff = pair->diff.period_ratio_delta; | ||
791 | else | ||
792 | diff = compute_delta(he, pair); | ||
793 | |||
794 | if (fabs(diff) < 0.01) | ||
795 | goto dummy_print; | ||
796 | scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1); | ||
797 | return percent_color_snprintf(hpp->buf, hpp->size, | ||
798 | pfmt, diff); | ||
799 | case COMPUTE_RATIO: | ||
800 | if (he->dummy) | ||
801 | goto dummy_print; | ||
802 | if (pair->diff.computed) | ||
803 | diff = pair->diff.period_ratio; | ||
804 | else | ||
805 | diff = compute_ratio(he, pair); | ||
806 | |||
807 | scnprintf(pfmt, 20, "%%%d.6f", dfmt->header_width); | ||
808 | return value_color_snprintf(hpp->buf, hpp->size, | ||
809 | pfmt, diff); | ||
810 | case COMPUTE_WEIGHTED_DIFF: | ||
811 | if (he->dummy) | ||
812 | goto dummy_print; | ||
813 | if (pair->diff.computed) | ||
814 | wdiff = pair->diff.wdiff; | ||
815 | else | ||
816 | wdiff = compute_wdiff(he, pair); | ||
817 | |||
818 | scnprintf(pfmt, 20, "%%14ld", dfmt->header_width); | ||
819 | return color_snprintf(hpp->buf, hpp->size, | ||
820 | get_percent_color(wdiff), | ||
821 | pfmt, wdiff); | ||
822 | default: | ||
823 | BUG_ON(1); | ||
824 | } | ||
825 | dummy_print: | ||
826 | return scnprintf(hpp->buf, hpp->size, "%*s", | ||
827 | dfmt->header_width, pfmt); | ||
828 | } | ||
829 | |||
830 | static int hpp__color_delta(struct perf_hpp_fmt *fmt, | ||
831 | struct perf_hpp *hpp, struct hist_entry *he) | ||
832 | { | ||
833 | return __hpp__color_compare(fmt, hpp, he, COMPUTE_DELTA); | ||
834 | } | ||
835 | |||
836 | static int hpp__color_ratio(struct perf_hpp_fmt *fmt, | ||
837 | struct perf_hpp *hpp, struct hist_entry *he) | ||
838 | { | ||
839 | return __hpp__color_compare(fmt, hpp, he, COMPUTE_RATIO); | ||
840 | } | ||
841 | |||
842 | static int hpp__color_wdiff(struct perf_hpp_fmt *fmt, | ||
843 | struct perf_hpp *hpp, struct hist_entry *he) | ||
844 | { | ||
845 | return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF); | ||
846 | } | ||
847 | |||
772 | static void | 848 | static void |
773 | hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size) | 849 | hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size) |
774 | { | 850 | { |
@@ -940,8 +1016,22 @@ static void data__hpp_register(struct data__file *d, int idx) | |||
940 | fmt->entry = hpp__entry_global; | 1016 | fmt->entry = hpp__entry_global; |
941 | 1017 | ||
942 | /* TODO more colors */ | 1018 | /* TODO more colors */ |
943 | if (idx == PERF_HPP_DIFF__BASELINE) | 1019 | switch (idx) { |
1020 | case PERF_HPP_DIFF__BASELINE: | ||
944 | fmt->color = hpp__color_baseline; | 1021 | fmt->color = hpp__color_baseline; |
1022 | break; | ||
1023 | case PERF_HPP_DIFF__DELTA: | ||
1024 | fmt->color = hpp__color_delta; | ||
1025 | break; | ||
1026 | case PERF_HPP_DIFF__RATIO: | ||
1027 | fmt->color = hpp__color_ratio; | ||
1028 | break; | ||
1029 | case PERF_HPP_DIFF__WEIGHTED_DIFF: | ||
1030 | fmt->color = hpp__color_wdiff; | ||
1031 | break; | ||
1032 | default: | ||
1033 | break; | ||
1034 | } | ||
945 | 1035 | ||
946 | init_header(d, dfmt); | 1036 | init_header(d, dfmt); |
947 | perf_hpp__column_register(fmt); | 1037 | perf_hpp__column_register(fmt); |
@@ -1000,8 +1090,7 @@ static int data_init(int argc, const char **argv) | |||
1000 | data__files_cnt = argc; | 1090 | data__files_cnt = argc; |
1001 | use_default = false; | 1091 | use_default = false; |
1002 | } | 1092 | } |
1003 | } else if (symbol_conf.default_guest_vmlinux_name || | 1093 | } else if (perf_guest) { |
1004 | symbol_conf.default_guest_kallsyms) { | ||
1005 | defaults[0] = "perf.data.host"; | 1094 | defaults[0] = "perf.data.host"; |
1006 | defaults[1] = "perf.data.guest"; | 1095 | defaults[1] = "perf.data.guest"; |
1007 | } | 1096 | } |
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index 20b0f12763b0..c99e0de7e54a 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c | |||
@@ -29,7 +29,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details | |||
29 | if (session == NULL) | 29 | if (session == NULL) |
30 | return -ENOMEM; | 30 | return -ENOMEM; |
31 | 31 | ||
32 | list_for_each_entry(pos, &session->evlist->entries, node) | 32 | evlist__for_each(session->evlist, pos) |
33 | perf_evsel__fprintf(pos, details, stdout); | 33 | perf_evsel__fprintf(pos, details, stdout); |
34 | 34 | ||
35 | perf_session__delete(session); | 35 | perf_session__delete(session); |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 6a2508589460..b3466018bbd7 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -22,14 +22,13 @@ | |||
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | 23 | ||
24 | struct perf_inject { | 24 | struct perf_inject { |
25 | struct perf_tool tool; | 25 | struct perf_tool tool; |
26 | bool build_ids; | 26 | bool build_ids; |
27 | bool sched_stat; | 27 | bool sched_stat; |
28 | const char *input_name; | 28 | const char *input_name; |
29 | int pipe_output, | 29 | struct perf_data_file output; |
30 | output; | 30 | u64 bytes_written; |
31 | u64 bytes_written; | 31 | struct list_head samples; |
32 | struct list_head samples; | ||
33 | }; | 32 | }; |
34 | 33 | ||
35 | struct event_entry { | 34 | struct event_entry { |
@@ -42,21 +41,14 @@ static int perf_event__repipe_synth(struct perf_tool *tool, | |||
42 | union perf_event *event) | 41 | union perf_event *event) |
43 | { | 42 | { |
44 | struct perf_inject *inject = container_of(tool, struct perf_inject, tool); | 43 | struct perf_inject *inject = container_of(tool, struct perf_inject, tool); |
45 | uint32_t size; | 44 | ssize_t size; |
46 | void *buf = event; | ||
47 | 45 | ||
48 | size = event->header.size; | 46 | size = perf_data_file__write(&inject->output, event, |
49 | 47 | event->header.size); | |
50 | while (size) { | 48 | if (size < 0) |
51 | int ret = write(inject->output, buf, size); | 49 | return -errno; |
52 | if (ret < 0) | ||
53 | return -errno; | ||
54 | |||
55 | size -= ret; | ||
56 | buf += ret; | ||
57 | inject->bytes_written += ret; | ||
58 | } | ||
59 | 50 | ||
51 | inject->bytes_written += size; | ||
60 | return 0; | 52 | return 0; |
61 | } | 53 | } |
62 | 54 | ||
@@ -80,7 +72,7 @@ static int perf_event__repipe_attr(struct perf_tool *tool, | |||
80 | if (ret) | 72 | if (ret) |
81 | return ret; | 73 | return ret; |
82 | 74 | ||
83 | if (!inject->pipe_output) | 75 | if (&inject->output.is_pipe) |
84 | return 0; | 76 | return 0; |
85 | 77 | ||
86 | return perf_event__repipe_synth(tool, event); | 78 | return perf_event__repipe_synth(tool, event); |
@@ -355,6 +347,7 @@ static int __cmd_inject(struct perf_inject *inject) | |||
355 | .path = inject->input_name, | 347 | .path = inject->input_name, |
356 | .mode = PERF_DATA_MODE_READ, | 348 | .mode = PERF_DATA_MODE_READ, |
357 | }; | 349 | }; |
350 | struct perf_data_file *file_out = &inject->output; | ||
358 | 351 | ||
359 | signal(SIGINT, sig_handler); | 352 | signal(SIGINT, sig_handler); |
360 | 353 | ||
@@ -376,7 +369,7 @@ static int __cmd_inject(struct perf_inject *inject) | |||
376 | 369 | ||
377 | inject->tool.ordered_samples = true; | 370 | inject->tool.ordered_samples = true; |
378 | 371 | ||
379 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 372 | evlist__for_each(session->evlist, evsel) { |
380 | const char *name = perf_evsel__name(evsel); | 373 | const char *name = perf_evsel__name(evsel); |
381 | 374 | ||
382 | if (!strcmp(name, "sched:sched_switch")) { | 375 | if (!strcmp(name, "sched:sched_switch")) { |
@@ -391,14 +384,14 @@ static int __cmd_inject(struct perf_inject *inject) | |||
391 | } | 384 | } |
392 | } | 385 | } |
393 | 386 | ||
394 | if (!inject->pipe_output) | 387 | if (!file_out->is_pipe) |
395 | lseek(inject->output, session->header.data_offset, SEEK_SET); | 388 | lseek(file_out->fd, session->header.data_offset, SEEK_SET); |
396 | 389 | ||
397 | ret = perf_session__process_events(session, &inject->tool); | 390 | ret = perf_session__process_events(session, &inject->tool); |
398 | 391 | ||
399 | if (!inject->pipe_output) { | 392 | if (!file_out->is_pipe) { |
400 | session->header.data_size = inject->bytes_written; | 393 | session->header.data_size = inject->bytes_written; |
401 | perf_session__write_header(session, session->evlist, inject->output, true); | 394 | perf_session__write_header(session, session->evlist, file_out->fd, true); |
402 | } | 395 | } |
403 | 396 | ||
404 | perf_session__delete(session); | 397 | perf_session__delete(session); |
@@ -427,14 +420,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
427 | }, | 420 | }, |
428 | .input_name = "-", | 421 | .input_name = "-", |
429 | .samples = LIST_HEAD_INIT(inject.samples), | 422 | .samples = LIST_HEAD_INIT(inject.samples), |
423 | .output = { | ||
424 | .path = "-", | ||
425 | .mode = PERF_DATA_MODE_WRITE, | ||
426 | }, | ||
430 | }; | 427 | }; |
431 | const char *output_name = "-"; | ||
432 | const struct option options[] = { | 428 | const struct option options[] = { |
433 | OPT_BOOLEAN('b', "build-ids", &inject.build_ids, | 429 | OPT_BOOLEAN('b', "build-ids", &inject.build_ids, |
434 | "Inject build-ids into the output stream"), | 430 | "Inject build-ids into the output stream"), |
435 | OPT_STRING('i', "input", &inject.input_name, "file", | 431 | OPT_STRING('i', "input", &inject.input_name, "file", |
436 | "input file name"), | 432 | "input file name"), |
437 | OPT_STRING('o', "output", &output_name, "file", | 433 | OPT_STRING('o', "output", &inject.output.path, "file", |
438 | "output file name"), | 434 | "output file name"), |
439 | OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, | 435 | OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, |
440 | "Merge sched-stat and sched-switch for getting events " | 436 | "Merge sched-stat and sched-switch for getting events " |
@@ -456,16 +452,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
456 | if (argc) | 452 | if (argc) |
457 | usage_with_options(inject_usage, options); | 453 | usage_with_options(inject_usage, options); |
458 | 454 | ||
459 | if (!strcmp(output_name, "-")) { | 455 | if (perf_data_file__open(&inject.output)) { |
460 | inject.pipe_output = 1; | 456 | perror("failed to create output file"); |
461 | inject.output = STDOUT_FILENO; | 457 | return -1; |
462 | } else { | ||
463 | inject.output = open(output_name, O_CREAT | O_WRONLY | O_TRUNC, | ||
464 | S_IRUSR | S_IWUSR); | ||
465 | if (inject.output < 0) { | ||
466 | perror("failed to create output file"); | ||
467 | return -1; | ||
468 | } | ||
469 | } | 458 | } |
470 | 459 | ||
471 | if (symbol__init() < 0) | 460 | if (symbol__init() < 0) |
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index f8bf5f244d77..a7350519c63f 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include "util/parse-options.h" | 13 | #include "util/parse-options.h" |
14 | #include "util/trace-event.h" | 14 | #include "util/trace-event.h" |
15 | #include "util/debug.h" | 15 | #include "util/debug.h" |
16 | #include <lk/debugfs.h> | 16 | #include <api/fs/debugfs.h> |
17 | #include "util/tool.h" | 17 | #include "util/tool.h" |
18 | #include "util/stat.h" | 18 | #include "util/stat.h" |
19 | #include "util/top.h" | 19 | #include "util/top.h" |
@@ -89,7 +89,7 @@ struct exit_reasons_table { | |||
89 | 89 | ||
90 | struct perf_kvm_stat { | 90 | struct perf_kvm_stat { |
91 | struct perf_tool tool; | 91 | struct perf_tool tool; |
92 | struct perf_record_opts opts; | 92 | struct record_opts opts; |
93 | struct perf_evlist *evlist; | 93 | struct perf_evlist *evlist; |
94 | struct perf_session *session; | 94 | struct perf_session *session; |
95 | 95 | ||
@@ -1158,9 +1158,7 @@ out: | |||
1158 | if (kvm->timerfd >= 0) | 1158 | if (kvm->timerfd >= 0) |
1159 | close(kvm->timerfd); | 1159 | close(kvm->timerfd); |
1160 | 1160 | ||
1161 | if (pollfds) | 1161 | free(pollfds); |
1162 | free(pollfds); | ||
1163 | |||
1164 | return err; | 1162 | return err; |
1165 | } | 1163 | } |
1166 | 1164 | ||
@@ -1176,7 +1174,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) | |||
1176 | * Note: exclude_{guest,host} do not apply here. | 1174 | * Note: exclude_{guest,host} do not apply here. |
1177 | * This command processes KVM tracepoints from host only | 1175 | * This command processes KVM tracepoints from host only |
1178 | */ | 1176 | */ |
1179 | list_for_each_entry(pos, &evlist->entries, node) { | 1177 | evlist__for_each(evlist, pos) { |
1180 | struct perf_event_attr *attr = &pos->attr; | 1178 | struct perf_event_attr *attr = &pos->attr; |
1181 | 1179 | ||
1182 | /* make sure these *are* set */ | 1180 | /* make sure these *are* set */ |
@@ -1232,7 +1230,7 @@ static int read_events(struct perf_kvm_stat *kvm) | |||
1232 | .ordered_samples = true, | 1230 | .ordered_samples = true, |
1233 | }; | 1231 | }; |
1234 | struct perf_data_file file = { | 1232 | struct perf_data_file file = { |
1235 | .path = input_name, | 1233 | .path = kvm->file_name, |
1236 | .mode = PERF_DATA_MODE_READ, | 1234 | .mode = PERF_DATA_MODE_READ, |
1237 | }; | 1235 | }; |
1238 | 1236 | ||
@@ -1558,10 +1556,8 @@ out: | |||
1558 | if (kvm->session) | 1556 | if (kvm->session) |
1559 | perf_session__delete(kvm->session); | 1557 | perf_session__delete(kvm->session); |
1560 | kvm->session = NULL; | 1558 | kvm->session = NULL; |
1561 | if (kvm->evlist) { | 1559 | if (kvm->evlist) |
1562 | perf_evlist__delete_maps(kvm->evlist); | ||
1563 | perf_evlist__delete(kvm->evlist); | 1560 | perf_evlist__delete(kvm->evlist); |
1564 | } | ||
1565 | 1561 | ||
1566 | return err; | 1562 | return err; |
1567 | } | 1563 | } |
@@ -1690,6 +1686,8 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1690 | "file", "file saving guest os /proc/kallsyms"), | 1686 | "file", "file saving guest os /proc/kallsyms"), |
1691 | OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules, | 1687 | OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules, |
1692 | "file", "file saving guest os /proc/modules"), | 1688 | "file", "file saving guest os /proc/modules"), |
1689 | OPT_INCR('v', "verbose", &verbose, | ||
1690 | "be more verbose (show counter open errors, etc)"), | ||
1693 | OPT_END() | 1691 | OPT_END() |
1694 | }; | 1692 | }; |
1695 | 1693 | ||
@@ -1711,12 +1709,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1711 | perf_guest = 1; | 1709 | perf_guest = 1; |
1712 | 1710 | ||
1713 | if (!file_name) { | 1711 | if (!file_name) { |
1714 | if (perf_host && !perf_guest) | 1712 | file_name = get_filename_for_perf_kvm(); |
1715 | file_name = strdup("perf.data.host"); | ||
1716 | else if (!perf_host && perf_guest) | ||
1717 | file_name = strdup("perf.data.guest"); | ||
1718 | else | ||
1719 | file_name = strdup("perf.data.kvm"); | ||
1720 | 1713 | ||
1721 | if (!file_name) { | 1714 | if (!file_name) { |
1722 | pr_err("Failed to allocate memory for filename\n"); | 1715 | pr_err("Failed to allocate memory for filename\n"); |
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 31c00f186da1..2e3ade69a58e 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -62,7 +62,6 @@ static int | |||
62 | dump_raw_samples(struct perf_tool *tool, | 62 | dump_raw_samples(struct perf_tool *tool, |
63 | union perf_event *event, | 63 | union perf_event *event, |
64 | struct perf_sample *sample, | 64 | struct perf_sample *sample, |
65 | struct perf_evsel *evsel __maybe_unused, | ||
66 | struct machine *machine) | 65 | struct machine *machine) |
67 | { | 66 | { |
68 | struct perf_mem *mem = container_of(tool, struct perf_mem, tool); | 67 | struct perf_mem *mem = container_of(tool, struct perf_mem, tool); |
@@ -112,10 +111,10 @@ dump_raw_samples(struct perf_tool *tool, | |||
112 | static int process_sample_event(struct perf_tool *tool, | 111 | static int process_sample_event(struct perf_tool *tool, |
113 | union perf_event *event, | 112 | union perf_event *event, |
114 | struct perf_sample *sample, | 113 | struct perf_sample *sample, |
115 | struct perf_evsel *evsel, | 114 | struct perf_evsel *evsel __maybe_unused, |
116 | struct machine *machine) | 115 | struct machine *machine) |
117 | { | 116 | { |
118 | return dump_raw_samples(tool, event, sample, evsel, machine); | 117 | return dump_raw_samples(tool, event, sample, machine); |
119 | } | 118 | } |
120 | 119 | ||
121 | static int report_raw_events(struct perf_mem *mem) | 120 | static int report_raw_events(struct perf_mem *mem) |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 6ea9e85bdc00..78948882e3de 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include "util/strfilter.h" | 37 | #include "util/strfilter.h" |
38 | #include "util/symbol.h" | 38 | #include "util/symbol.h" |
39 | #include "util/debug.h" | 39 | #include "util/debug.h" |
40 | #include <lk/debugfs.h> | 40 | #include <api/fs/debugfs.h> |
41 | #include "util/parse-options.h" | 41 | #include "util/parse-options.h" |
42 | #include "util/probe-finder.h" | 42 | #include "util/probe-finder.h" |
43 | #include "util/probe-event.h" | 43 | #include "util/probe-event.h" |
@@ -59,7 +59,7 @@ static struct { | |||
59 | struct perf_probe_event events[MAX_PROBES]; | 59 | struct perf_probe_event events[MAX_PROBES]; |
60 | struct strlist *dellist; | 60 | struct strlist *dellist; |
61 | struct line_range line_range; | 61 | struct line_range line_range; |
62 | const char *target; | 62 | char *target; |
63 | int max_probe_points; | 63 | int max_probe_points; |
64 | struct strfilter *filter; | 64 | struct strfilter *filter; |
65 | } params; | 65 | } params; |
@@ -98,7 +98,10 @@ static int set_target(const char *ptr) | |||
98 | * short module name. | 98 | * short module name. |
99 | */ | 99 | */ |
100 | if (!params.target && ptr && *ptr == '/') { | 100 | if (!params.target && ptr && *ptr == '/') { |
101 | params.target = ptr; | 101 | params.target = strdup(ptr); |
102 | if (!params.target) | ||
103 | return -ENOMEM; | ||
104 | |||
102 | found = 1; | 105 | found = 1; |
103 | buf = ptr + (strlen(ptr) - 3); | 106 | buf = ptr + (strlen(ptr) - 3); |
104 | 107 | ||
@@ -116,6 +119,9 @@ static int parse_probe_event_argv(int argc, const char **argv) | |||
116 | char *buf; | 119 | char *buf; |
117 | 120 | ||
118 | found_target = set_target(argv[0]); | 121 | found_target = set_target(argv[0]); |
122 | if (found_target < 0) | ||
123 | return found_target; | ||
124 | |||
119 | if (found_target && argc == 1) | 125 | if (found_target && argc == 1) |
120 | return 0; | 126 | return 0; |
121 | 127 | ||
@@ -169,6 +175,7 @@ static int opt_set_target(const struct option *opt, const char *str, | |||
169 | int unset __maybe_unused) | 175 | int unset __maybe_unused) |
170 | { | 176 | { |
171 | int ret = -ENOENT; | 177 | int ret = -ENOENT; |
178 | char *tmp; | ||
172 | 179 | ||
173 | if (str && !params.target) { | 180 | if (str && !params.target) { |
174 | if (!strcmp(opt->long_name, "exec")) | 181 | if (!strcmp(opt->long_name, "exec")) |
@@ -180,7 +187,19 @@ static int opt_set_target(const struct option *opt, const char *str, | |||
180 | else | 187 | else |
181 | return ret; | 188 | return ret; |
182 | 189 | ||
183 | params.target = str; | 190 | /* Expand given path to absolute path, except for modulename */ |
191 | if (params.uprobes || strchr(str, '/')) { | ||
192 | tmp = realpath(str, NULL); | ||
193 | if (!tmp) { | ||
194 | pr_warning("Failed to get the absolute path of %s: %m\n", str); | ||
195 | return ret; | ||
196 | } | ||
197 | } else { | ||
198 | tmp = strdup(str); | ||
199 | if (!tmp) | ||
200 | return -ENOMEM; | ||
201 | } | ||
202 | params.target = tmp; | ||
184 | ret = 0; | 203 | ret = 0; |
185 | } | 204 | } |
186 | 205 | ||
@@ -204,7 +223,6 @@ static int opt_show_lines(const struct option *opt __maybe_unused, | |||
204 | 223 | ||
205 | params.show_lines = true; | 224 | params.show_lines = true; |
206 | ret = parse_line_range_desc(str, ¶ms.line_range); | 225 | ret = parse_line_range_desc(str, ¶ms.line_range); |
207 | INIT_LIST_HEAD(¶ms.line_range.line_list); | ||
208 | 226 | ||
209 | return ret; | 227 | return ret; |
210 | } | 228 | } |
@@ -250,7 +268,28 @@ static int opt_set_filter(const struct option *opt __maybe_unused, | |||
250 | return 0; | 268 | return 0; |
251 | } | 269 | } |
252 | 270 | ||
253 | int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | 271 | static void init_params(void) |
272 | { | ||
273 | line_range__init(¶ms.line_range); | ||
274 | } | ||
275 | |||
276 | static void cleanup_params(void) | ||
277 | { | ||
278 | int i; | ||
279 | |||
280 | for (i = 0; i < params.nevents; i++) | ||
281 | clear_perf_probe_event(params.events + i); | ||
282 | if (params.dellist) | ||
283 | strlist__delete(params.dellist); | ||
284 | line_range__clear(¶ms.line_range); | ||
285 | free(params.target); | ||
286 | if (params.filter) | ||
287 | strfilter__delete(params.filter); | ||
288 | memset(¶ms, 0, sizeof(params)); | ||
289 | } | ||
290 | |||
291 | static int | ||
292 | __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | ||
254 | { | 293 | { |
255 | const char * const probe_usage[] = { | 294 | const char * const probe_usage[] = { |
256 | "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", | 295 | "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", |
@@ -404,6 +443,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
404 | ret = show_available_funcs(params.target, params.filter, | 443 | ret = show_available_funcs(params.target, params.filter, |
405 | params.uprobes); | 444 | params.uprobes); |
406 | strfilter__delete(params.filter); | 445 | strfilter__delete(params.filter); |
446 | params.filter = NULL; | ||
407 | if (ret < 0) | 447 | if (ret < 0) |
408 | pr_err(" Error: Failed to show functions." | 448 | pr_err(" Error: Failed to show functions." |
409 | " (%d)\n", ret); | 449 | " (%d)\n", ret); |
@@ -411,7 +451,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
411 | } | 451 | } |
412 | 452 | ||
413 | #ifdef HAVE_DWARF_SUPPORT | 453 | #ifdef HAVE_DWARF_SUPPORT |
414 | if (params.show_lines && !params.uprobes) { | 454 | if (params.show_lines) { |
415 | if (params.mod_events) { | 455 | if (params.mod_events) { |
416 | pr_err(" Error: Don't use --line with" | 456 | pr_err(" Error: Don't use --line with" |
417 | " --add/--del.\n"); | 457 | " --add/--del.\n"); |
@@ -443,6 +483,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
443 | params.filter, | 483 | params.filter, |
444 | params.show_ext_vars); | 484 | params.show_ext_vars); |
445 | strfilter__delete(params.filter); | 485 | strfilter__delete(params.filter); |
486 | params.filter = NULL; | ||
446 | if (ret < 0) | 487 | if (ret < 0) |
447 | pr_err(" Error: Failed to show vars. (%d)\n", ret); | 488 | pr_err(" Error: Failed to show vars. (%d)\n", ret); |
448 | return ret; | 489 | return ret; |
@@ -451,7 +492,6 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
451 | 492 | ||
452 | if (params.dellist) { | 493 | if (params.dellist) { |
453 | ret = del_perf_probe_events(params.dellist); | 494 | ret = del_perf_probe_events(params.dellist); |
454 | strlist__delete(params.dellist); | ||
455 | if (ret < 0) { | 495 | if (ret < 0) { |
456 | pr_err(" Error: Failed to delete events. (%d)\n", ret); | 496 | pr_err(" Error: Failed to delete events. (%d)\n", ret); |
457 | return ret; | 497 | return ret; |
@@ -470,3 +510,14 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
470 | } | 510 | } |
471 | return 0; | 511 | return 0; |
472 | } | 512 | } |
513 | |||
514 | int cmd_probe(int argc, const char **argv, const char *prefix) | ||
515 | { | ||
516 | int ret; | ||
517 | |||
518 | init_params(); | ||
519 | ret = __cmd_probe(argc, argv, prefix); | ||
520 | cleanup_params(); | ||
521 | |||
522 | return ret; | ||
523 | } | ||
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 7c8020a32784..3c394bf16fa8 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -62,9 +62,9 @@ static void __handle_on_exit_funcs(void) | |||
62 | } | 62 | } |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | struct perf_record { | 65 | struct record { |
66 | struct perf_tool tool; | 66 | struct perf_tool tool; |
67 | struct perf_record_opts opts; | 67 | struct record_opts opts; |
68 | u64 bytes_written; | 68 | u64 bytes_written; |
69 | struct perf_data_file file; | 69 | struct perf_data_file file; |
70 | struct perf_evlist *evlist; | 70 | struct perf_evlist *evlist; |
@@ -76,46 +76,27 @@ struct perf_record { | |||
76 | long samples; | 76 | long samples; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static int do_write_output(struct perf_record *rec, void *buf, size_t size) | 79 | static int record__write(struct record *rec, void *bf, size_t size) |
80 | { | 80 | { |
81 | struct perf_data_file *file = &rec->file; | 81 | if (perf_data_file__write(rec->session->file, bf, size) < 0) { |
82 | 82 | pr_err("failed to write perf data, error: %m\n"); | |
83 | while (size) { | 83 | return -1; |
84 | ssize_t ret = write(file->fd, buf, size); | ||
85 | |||
86 | if (ret < 0) { | ||
87 | pr_err("failed to write perf data, error: %m\n"); | ||
88 | return -1; | ||
89 | } | ||
90 | |||
91 | size -= ret; | ||
92 | buf += ret; | ||
93 | |||
94 | rec->bytes_written += ret; | ||
95 | } | 84 | } |
96 | 85 | ||
86 | rec->bytes_written += size; | ||
97 | return 0; | 87 | return 0; |
98 | } | 88 | } |
99 | 89 | ||
100 | static int write_output(struct perf_record *rec, void *buf, size_t size) | ||
101 | { | ||
102 | return do_write_output(rec, buf, size); | ||
103 | } | ||
104 | |||
105 | static int process_synthesized_event(struct perf_tool *tool, | 90 | static int process_synthesized_event(struct perf_tool *tool, |
106 | union perf_event *event, | 91 | union perf_event *event, |
107 | struct perf_sample *sample __maybe_unused, | 92 | struct perf_sample *sample __maybe_unused, |
108 | struct machine *machine __maybe_unused) | 93 | struct machine *machine __maybe_unused) |
109 | { | 94 | { |
110 | struct perf_record *rec = container_of(tool, struct perf_record, tool); | 95 | struct record *rec = container_of(tool, struct record, tool); |
111 | if (write_output(rec, event, event->header.size) < 0) | 96 | return record__write(rec, event, event->header.size); |
112 | return -1; | ||
113 | |||
114 | return 0; | ||
115 | } | 97 | } |
116 | 98 | ||
117 | static int perf_record__mmap_read(struct perf_record *rec, | 99 | static int record__mmap_read(struct record *rec, struct perf_mmap *md) |
118 | struct perf_mmap *md) | ||
119 | { | 100 | { |
120 | unsigned int head = perf_mmap__read_head(md); | 101 | unsigned int head = perf_mmap__read_head(md); |
121 | unsigned int old = md->prev; | 102 | unsigned int old = md->prev; |
@@ -136,7 +117,7 @@ static int perf_record__mmap_read(struct perf_record *rec, | |||
136 | size = md->mask + 1 - (old & md->mask); | 117 | size = md->mask + 1 - (old & md->mask); |
137 | old += size; | 118 | old += size; |
138 | 119 | ||
139 | if (write_output(rec, buf, size) < 0) { | 120 | if (record__write(rec, buf, size) < 0) { |
140 | rc = -1; | 121 | rc = -1; |
141 | goto out; | 122 | goto out; |
142 | } | 123 | } |
@@ -146,7 +127,7 @@ static int perf_record__mmap_read(struct perf_record *rec, | |||
146 | size = head - old; | 127 | size = head - old; |
147 | old += size; | 128 | old += size; |
148 | 129 | ||
149 | if (write_output(rec, buf, size) < 0) { | 130 | if (record__write(rec, buf, size) < 0) { |
150 | rc = -1; | 131 | rc = -1; |
151 | goto out; | 132 | goto out; |
152 | } | 133 | } |
@@ -171,9 +152,9 @@ static void sig_handler(int sig) | |||
171 | signr = sig; | 152 | signr = sig; |
172 | } | 153 | } |
173 | 154 | ||
174 | static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) | 155 | static void record__sig_exit(int exit_status __maybe_unused, void *arg) |
175 | { | 156 | { |
176 | struct perf_record *rec = arg; | 157 | struct record *rec = arg; |
177 | int status; | 158 | int status; |
178 | 159 | ||
179 | if (rec->evlist->workload.pid > 0) { | 160 | if (rec->evlist->workload.pid > 0) { |
@@ -191,18 +172,18 @@ static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) | |||
191 | signal(signr, SIG_DFL); | 172 | signal(signr, SIG_DFL); |
192 | } | 173 | } |
193 | 174 | ||
194 | static int perf_record__open(struct perf_record *rec) | 175 | static int record__open(struct record *rec) |
195 | { | 176 | { |
196 | char msg[512]; | 177 | char msg[512]; |
197 | struct perf_evsel *pos; | 178 | struct perf_evsel *pos; |
198 | struct perf_evlist *evlist = rec->evlist; | 179 | struct perf_evlist *evlist = rec->evlist; |
199 | struct perf_session *session = rec->session; | 180 | struct perf_session *session = rec->session; |
200 | struct perf_record_opts *opts = &rec->opts; | 181 | struct record_opts *opts = &rec->opts; |
201 | int rc = 0; | 182 | int rc = 0; |
202 | 183 | ||
203 | perf_evlist__config(evlist, opts); | 184 | perf_evlist__config(evlist, opts); |
204 | 185 | ||
205 | list_for_each_entry(pos, &evlist->entries, node) { | 186 | evlist__for_each(evlist, pos) { |
206 | try_again: | 187 | try_again: |
207 | if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { | 188 | if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { |
208 | if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { | 189 | if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { |
@@ -232,7 +213,7 @@ try_again: | |||
232 | "Consider increasing " | 213 | "Consider increasing " |
233 | "/proc/sys/kernel/perf_event_mlock_kb,\n" | 214 | "/proc/sys/kernel/perf_event_mlock_kb,\n" |
234 | "or try again with a smaller value of -m/--mmap_pages.\n" | 215 | "or try again with a smaller value of -m/--mmap_pages.\n" |
235 | "(current value: %d)\n", opts->mmap_pages); | 216 | "(current value: %u)\n", opts->mmap_pages); |
236 | rc = -errno; | 217 | rc = -errno; |
237 | } else { | 218 | } else { |
238 | pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); | 219 | pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); |
@@ -247,7 +228,7 @@ out: | |||
247 | return rc; | 228 | return rc; |
248 | } | 229 | } |
249 | 230 | ||
250 | static int process_buildids(struct perf_record *rec) | 231 | static int process_buildids(struct record *rec) |
251 | { | 232 | { |
252 | struct perf_data_file *file = &rec->file; | 233 | struct perf_data_file *file = &rec->file; |
253 | struct perf_session *session = rec->session; | 234 | struct perf_session *session = rec->session; |
@@ -262,9 +243,9 @@ static int process_buildids(struct perf_record *rec) | |||
262 | size, &build_id__mark_dso_hit_ops); | 243 | size, &build_id__mark_dso_hit_ops); |
263 | } | 244 | } |
264 | 245 | ||
265 | static void perf_record__exit(int status, void *arg) | 246 | static void record__exit(int status, void *arg) |
266 | { | 247 | { |
267 | struct perf_record *rec = arg; | 248 | struct record *rec = arg; |
268 | struct perf_data_file *file = &rec->file; | 249 | struct perf_data_file *file = &rec->file; |
269 | 250 | ||
270 | if (status != 0) | 251 | if (status != 0) |
@@ -320,14 +301,14 @@ static struct perf_event_header finished_round_event = { | |||
320 | .type = PERF_RECORD_FINISHED_ROUND, | 301 | .type = PERF_RECORD_FINISHED_ROUND, |
321 | }; | 302 | }; |
322 | 303 | ||
323 | static int perf_record__mmap_read_all(struct perf_record *rec) | 304 | static int record__mmap_read_all(struct record *rec) |
324 | { | 305 | { |
325 | int i; | 306 | int i; |
326 | int rc = 0; | 307 | int rc = 0; |
327 | 308 | ||
328 | for (i = 0; i < rec->evlist->nr_mmaps; i++) { | 309 | for (i = 0; i < rec->evlist->nr_mmaps; i++) { |
329 | if (rec->evlist->mmap[i].base) { | 310 | if (rec->evlist->mmap[i].base) { |
330 | if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { | 311 | if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { |
331 | rc = -1; | 312 | rc = -1; |
332 | goto out; | 313 | goto out; |
333 | } | 314 | } |
@@ -335,16 +316,14 @@ static int perf_record__mmap_read_all(struct perf_record *rec) | |||
335 | } | 316 | } |
336 | 317 | ||
337 | if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) | 318 | if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) |
338 | rc = write_output(rec, &finished_round_event, | 319 | rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); |
339 | sizeof(finished_round_event)); | ||
340 | 320 | ||
341 | out: | 321 | out: |
342 | return rc; | 322 | return rc; |
343 | } | 323 | } |
344 | 324 | ||
345 | static void perf_record__init_features(struct perf_record *rec) | 325 | static void record__init_features(struct record *rec) |
346 | { | 326 | { |
347 | struct perf_evlist *evsel_list = rec->evlist; | ||
348 | struct perf_session *session = rec->session; | 327 | struct perf_session *session = rec->session; |
349 | int feat; | 328 | int feat; |
350 | 329 | ||
@@ -354,32 +333,46 @@ static void perf_record__init_features(struct perf_record *rec) | |||
354 | if (rec->no_buildid) | 333 | if (rec->no_buildid) |
355 | perf_header__clear_feat(&session->header, HEADER_BUILD_ID); | 334 | perf_header__clear_feat(&session->header, HEADER_BUILD_ID); |
356 | 335 | ||
357 | if (!have_tracepoints(&evsel_list->entries)) | 336 | if (!have_tracepoints(&rec->evlist->entries)) |
358 | perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); | 337 | perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); |
359 | 338 | ||
360 | if (!rec->opts.branch_stack) | 339 | if (!rec->opts.branch_stack) |
361 | perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); | 340 | perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); |
362 | } | 341 | } |
363 | 342 | ||
364 | static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | 343 | static volatile int workload_exec_errno; |
344 | |||
345 | /* | ||
346 | * perf_evlist__prepare_workload will send a SIGUSR1 | ||
347 | * if the fork fails, since we asked by setting its | ||
348 | * want_signal to true. | ||
349 | */ | ||
350 | static void workload_exec_failed_signal(int signo, siginfo_t *info, | ||
351 | void *ucontext __maybe_unused) | ||
352 | { | ||
353 | workload_exec_errno = info->si_value.sival_int; | ||
354 | done = 1; | ||
355 | signr = signo; | ||
356 | child_finished = 1; | ||
357 | } | ||
358 | |||
359 | static int __cmd_record(struct record *rec, int argc, const char **argv) | ||
365 | { | 360 | { |
366 | int err; | 361 | int err; |
367 | unsigned long waking = 0; | 362 | unsigned long waking = 0; |
368 | const bool forks = argc > 0; | 363 | const bool forks = argc > 0; |
369 | struct machine *machine; | 364 | struct machine *machine; |
370 | struct perf_tool *tool = &rec->tool; | 365 | struct perf_tool *tool = &rec->tool; |
371 | struct perf_record_opts *opts = &rec->opts; | 366 | struct record_opts *opts = &rec->opts; |
372 | struct perf_evlist *evsel_list = rec->evlist; | ||
373 | struct perf_data_file *file = &rec->file; | 367 | struct perf_data_file *file = &rec->file; |
374 | struct perf_session *session; | 368 | struct perf_session *session; |
375 | bool disabled = false; | 369 | bool disabled = false; |
376 | 370 | ||
377 | rec->progname = argv[0]; | 371 | rec->progname = argv[0]; |
378 | 372 | ||
379 | on_exit(perf_record__sig_exit, rec); | 373 | on_exit(record__sig_exit, rec); |
380 | signal(SIGCHLD, sig_handler); | 374 | signal(SIGCHLD, sig_handler); |
381 | signal(SIGINT, sig_handler); | 375 | signal(SIGINT, sig_handler); |
382 | signal(SIGUSR1, sig_handler); | ||
383 | signal(SIGTERM, sig_handler); | 376 | signal(SIGTERM, sig_handler); |
384 | 377 | ||
385 | session = perf_session__new(file, false, NULL); | 378 | session = perf_session__new(file, false, NULL); |
@@ -390,37 +383,37 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
390 | 383 | ||
391 | rec->session = session; | 384 | rec->session = session; |
392 | 385 | ||
393 | perf_record__init_features(rec); | 386 | record__init_features(rec); |
394 | 387 | ||
395 | if (forks) { | 388 | if (forks) { |
396 | err = perf_evlist__prepare_workload(evsel_list, &opts->target, | 389 | err = perf_evlist__prepare_workload(rec->evlist, &opts->target, |
397 | argv, file->is_pipe, | 390 | argv, file->is_pipe, |
398 | true); | 391 | workload_exec_failed_signal); |
399 | if (err < 0) { | 392 | if (err < 0) { |
400 | pr_err("Couldn't run the workload!\n"); | 393 | pr_err("Couldn't run the workload!\n"); |
401 | goto out_delete_session; | 394 | goto out_delete_session; |
402 | } | 395 | } |
403 | } | 396 | } |
404 | 397 | ||
405 | if (perf_record__open(rec) != 0) { | 398 | if (record__open(rec) != 0) { |
406 | err = -1; | 399 | err = -1; |
407 | goto out_delete_session; | 400 | goto out_delete_session; |
408 | } | 401 | } |
409 | 402 | ||
410 | if (!evsel_list->nr_groups) | 403 | if (!rec->evlist->nr_groups) |
411 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); | 404 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); |
412 | 405 | ||
413 | /* | 406 | /* |
414 | * perf_session__delete(session) will be called at perf_record__exit() | 407 | * perf_session__delete(session) will be called at record__exit() |
415 | */ | 408 | */ |
416 | on_exit(perf_record__exit, rec); | 409 | on_exit(record__exit, rec); |
417 | 410 | ||
418 | if (file->is_pipe) { | 411 | if (file->is_pipe) { |
419 | err = perf_header__write_pipe(file->fd); | 412 | err = perf_header__write_pipe(file->fd); |
420 | if (err < 0) | 413 | if (err < 0) |
421 | goto out_delete_session; | 414 | goto out_delete_session; |
422 | } else { | 415 | } else { |
423 | err = perf_session__write_header(session, evsel_list, | 416 | err = perf_session__write_header(session, rec->evlist, |
424 | file->fd, false); | 417 | file->fd, false); |
425 | if (err < 0) | 418 | if (err < 0) |
426 | goto out_delete_session; | 419 | goto out_delete_session; |
@@ -444,7 +437,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
444 | goto out_delete_session; | 437 | goto out_delete_session; |
445 | } | 438 | } |
446 | 439 | ||
447 | if (have_tracepoints(&evsel_list->entries)) { | 440 | if (have_tracepoints(&rec->evlist->entries)) { |
448 | /* | 441 | /* |
449 | * FIXME err <= 0 here actually means that | 442 | * FIXME err <= 0 here actually means that |
450 | * there were no tracepoints so its not really | 443 | * there were no tracepoints so its not really |
@@ -453,7 +446,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
453 | * return this more properly and also | 446 | * return this more properly and also |
454 | * propagate errors that now are calling die() | 447 | * propagate errors that now are calling die() |
455 | */ | 448 | */ |
456 | err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, | 449 | err = perf_event__synthesize_tracing_data(tool, file->fd, rec->evlist, |
457 | process_synthesized_event); | 450 | process_synthesized_event); |
458 | if (err <= 0) { | 451 | if (err <= 0) { |
459 | pr_err("Couldn't record tracing data.\n"); | 452 | pr_err("Couldn't record tracing data.\n"); |
@@ -485,7 +478,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
485 | perf_event__synthesize_guest_os, tool); | 478 | perf_event__synthesize_guest_os, tool); |
486 | } | 479 | } |
487 | 480 | ||
488 | err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, | 481 | err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, |
489 | process_synthesized_event, opts->sample_address); | 482 | process_synthesized_event, opts->sample_address); |
490 | if (err != 0) | 483 | if (err != 0) |
491 | goto out_delete_session; | 484 | goto out_delete_session; |
@@ -506,19 +499,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
506 | * (apart from group members) have enable_on_exec=1 set, | 499 | * (apart from group members) have enable_on_exec=1 set, |
507 | * so don't spoil it by prematurely enabling them. | 500 | * so don't spoil it by prematurely enabling them. |
508 | */ | 501 | */ |
509 | if (!target__none(&opts->target)) | 502 | if (!target__none(&opts->target) && !opts->initial_delay) |
510 | perf_evlist__enable(evsel_list); | 503 | perf_evlist__enable(rec->evlist); |
511 | 504 | ||
512 | /* | 505 | /* |
513 | * Let the child rip | 506 | * Let the child rip |
514 | */ | 507 | */ |
515 | if (forks) | 508 | if (forks) |
516 | perf_evlist__start_workload(evsel_list); | 509 | perf_evlist__start_workload(rec->evlist); |
510 | |||
511 | if (opts->initial_delay) { | ||
512 | usleep(opts->initial_delay * 1000); | ||
513 | perf_evlist__enable(rec->evlist); | ||
514 | } | ||
517 | 515 | ||
518 | for (;;) { | 516 | for (;;) { |
519 | int hits = rec->samples; | 517 | int hits = rec->samples; |
520 | 518 | ||
521 | if (perf_record__mmap_read_all(rec) < 0) { | 519 | if (record__mmap_read_all(rec) < 0) { |
522 | err = -1; | 520 | err = -1; |
523 | goto out_delete_session; | 521 | goto out_delete_session; |
524 | } | 522 | } |
@@ -526,7 +524,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
526 | if (hits == rec->samples) { | 524 | if (hits == rec->samples) { |
527 | if (done) | 525 | if (done) |
528 | break; | 526 | break; |
529 | err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); | 527 | err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1); |
530 | waking++; | 528 | waking++; |
531 | } | 529 | } |
532 | 530 | ||
@@ -536,11 +534,19 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
536 | * disable events in this case. | 534 | * disable events in this case. |
537 | */ | 535 | */ |
538 | if (done && !disabled && !target__none(&opts->target)) { | 536 | if (done && !disabled && !target__none(&opts->target)) { |
539 | perf_evlist__disable(evsel_list); | 537 | perf_evlist__disable(rec->evlist); |
540 | disabled = true; | 538 | disabled = true; |
541 | } | 539 | } |
542 | } | 540 | } |
543 | 541 | ||
542 | if (forks && workload_exec_errno) { | ||
543 | char msg[512]; | ||
544 | const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); | ||
545 | pr_err("Workload failed: %s\n", emsg); | ||
546 | err = -1; | ||
547 | goto out_delete_session; | ||
548 | } | ||
549 | |||
544 | if (quiet || signr == SIGUSR1) | 550 | if (quiet || signr == SIGUSR1) |
545 | return 0; | 551 | return 0; |
546 | 552 | ||
@@ -677,7 +683,7 @@ static int get_stack_size(char *str, unsigned long *_size) | |||
677 | } | 683 | } |
678 | #endif /* HAVE_LIBUNWIND_SUPPORT */ | 684 | #endif /* HAVE_LIBUNWIND_SUPPORT */ |
679 | 685 | ||
680 | int record_parse_callchain(const char *arg, struct perf_record_opts *opts) | 686 | int record_parse_callchain(const char *arg, struct record_opts *opts) |
681 | { | 687 | { |
682 | char *tok, *name, *saveptr = NULL; | 688 | char *tok, *name, *saveptr = NULL; |
683 | char *buf; | 689 | char *buf; |
@@ -733,7 +739,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts) | |||
733 | return ret; | 739 | return ret; |
734 | } | 740 | } |
735 | 741 | ||
736 | static void callchain_debug(struct perf_record_opts *opts) | 742 | static void callchain_debug(struct record_opts *opts) |
737 | { | 743 | { |
738 | pr_debug("callchain: type %d\n", opts->call_graph); | 744 | pr_debug("callchain: type %d\n", opts->call_graph); |
739 | 745 | ||
@@ -746,7 +752,7 @@ int record_parse_callchain_opt(const struct option *opt, | |||
746 | const char *arg, | 752 | const char *arg, |
747 | int unset) | 753 | int unset) |
748 | { | 754 | { |
749 | struct perf_record_opts *opts = opt->value; | 755 | struct record_opts *opts = opt->value; |
750 | int ret; | 756 | int ret; |
751 | 757 | ||
752 | /* --no-call-graph */ | 758 | /* --no-call-graph */ |
@@ -767,7 +773,7 @@ int record_callchain_opt(const struct option *opt, | |||
767 | const char *arg __maybe_unused, | 773 | const char *arg __maybe_unused, |
768 | int unset __maybe_unused) | 774 | int unset __maybe_unused) |
769 | { | 775 | { |
770 | struct perf_record_opts *opts = opt->value; | 776 | struct record_opts *opts = opt->value; |
771 | 777 | ||
772 | if (opts->call_graph == CALLCHAIN_NONE) | 778 | if (opts->call_graph == CALLCHAIN_NONE) |
773 | opts->call_graph = CALLCHAIN_FP; | 779 | opts->call_graph = CALLCHAIN_FP; |
@@ -783,8 +789,8 @@ static const char * const record_usage[] = { | |||
783 | }; | 789 | }; |
784 | 790 | ||
785 | /* | 791 | /* |
786 | * XXX Ideally would be local to cmd_record() and passed to a perf_record__new | 792 | * XXX Ideally would be local to cmd_record() and passed to a record__new |
787 | * because we need to have access to it in perf_record__exit, that is called | 793 | * because we need to have access to it in record__exit, that is called |
788 | * after cmd_record() exits, but since record_options need to be accessible to | 794 | * after cmd_record() exits, but since record_options need to be accessible to |
789 | * builtin-script, leave it here. | 795 | * builtin-script, leave it here. |
790 | * | 796 | * |
@@ -792,7 +798,7 @@ static const char * const record_usage[] = { | |||
792 | * | 798 | * |
793 | * Just say no to tons of global variables, sigh. | 799 | * Just say no to tons of global variables, sigh. |
794 | */ | 800 | */ |
795 | static struct perf_record record = { | 801 | static struct record record = { |
796 | .opts = { | 802 | .opts = { |
797 | .mmap_pages = UINT_MAX, | 803 | .mmap_pages = UINT_MAX, |
798 | .user_freq = UINT_MAX, | 804 | .user_freq = UINT_MAX, |
@@ -800,6 +806,7 @@ static struct perf_record record = { | |||
800 | .freq = 4000, | 806 | .freq = 4000, |
801 | .target = { | 807 | .target = { |
802 | .uses_mmap = true, | 808 | .uses_mmap = true, |
809 | .default_per_cpu = true, | ||
803 | }, | 810 | }, |
804 | }, | 811 | }, |
805 | }; | 812 | }; |
@@ -815,7 +822,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp"; | |||
815 | /* | 822 | /* |
816 | * XXX Will stay a global variable till we fix builtin-script.c to stop messing | 823 | * XXX Will stay a global variable till we fix builtin-script.c to stop messing |
817 | * with it and switch to use the library functions in perf_evlist that came | 824 | * with it and switch to use the library functions in perf_evlist that came |
818 | * from builtin-record.c, i.e. use perf_record_opts, | 825 | * from builtin-record.c, i.e. use record_opts, |
819 | * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', | 826 | * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', |
820 | * using pipes, etc. | 827 | * using pipes, etc. |
821 | */ | 828 | */ |
@@ -831,7 +838,7 @@ const struct option record_options[] = { | |||
831 | "record events on existing thread id"), | 838 | "record events on existing thread id"), |
832 | OPT_INTEGER('r', "realtime", &record.realtime_prio, | 839 | OPT_INTEGER('r', "realtime", &record.realtime_prio, |
833 | "collect data with this RT SCHED_FIFO priority"), | 840 | "collect data with this RT SCHED_FIFO priority"), |
834 | OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, | 841 | OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, |
835 | "collect data without buffering"), | 842 | "collect data without buffering"), |
836 | OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, | 843 | OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, |
837 | "collect raw sample records from all opened counters"), | 844 | "collect raw sample records from all opened counters"), |
@@ -842,8 +849,9 @@ const struct option record_options[] = { | |||
842 | OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), | 849 | OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), |
843 | OPT_STRING('o', "output", &record.file.path, "file", | 850 | OPT_STRING('o', "output", &record.file.path, "file", |
844 | "output file name"), | 851 | "output file name"), |
845 | OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, | 852 | OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, |
846 | "child tasks do not inherit counters"), | 853 | &record.opts.no_inherit_set, |
854 | "child tasks do not inherit counters"), | ||
847 | OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), | 855 | OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), |
848 | OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", | 856 | OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", |
849 | "number of mmap data pages", | 857 | "number of mmap data pages", |
@@ -874,6 +882,8 @@ const struct option record_options[] = { | |||
874 | OPT_CALLBACK('G', "cgroup", &record.evlist, "name", | 882 | OPT_CALLBACK('G', "cgroup", &record.evlist, "name", |
875 | "monitor event in cgroup name only", | 883 | "monitor event in cgroup name only", |
876 | parse_cgroups), | 884 | parse_cgroups), |
885 | OPT_UINTEGER('D', "delay", &record.opts.initial_delay, | ||
886 | "ms to wait before starting measurement after program start"), | ||
877 | OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", | 887 | OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", |
878 | "user to profile"), | 888 | "user to profile"), |
879 | 889 | ||
@@ -888,24 +898,21 @@ const struct option record_options[] = { | |||
888 | "sample by weight (on special events only)"), | 898 | "sample by weight (on special events only)"), |
889 | OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, | 899 | OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, |
890 | "sample transaction flags (special events only)"), | 900 | "sample transaction flags (special events only)"), |
891 | OPT_BOOLEAN(0, "force-per-cpu", &record.opts.target.force_per_cpu, | 901 | OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, |
892 | "force the use of per-cpu mmaps"), | 902 | "use per-thread mmaps"), |
893 | OPT_END() | 903 | OPT_END() |
894 | }; | 904 | }; |
895 | 905 | ||
896 | int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | 906 | int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) |
897 | { | 907 | { |
898 | int err = -ENOMEM; | 908 | int err = -ENOMEM; |
899 | struct perf_evlist *evsel_list; | 909 | struct record *rec = &record; |
900 | struct perf_record *rec = &record; | ||
901 | char errbuf[BUFSIZ]; | 910 | char errbuf[BUFSIZ]; |
902 | 911 | ||
903 | evsel_list = perf_evlist__new(); | 912 | rec->evlist = perf_evlist__new(); |
904 | if (evsel_list == NULL) | 913 | if (rec->evlist == NULL) |
905 | return -ENOMEM; | 914 | return -ENOMEM; |
906 | 915 | ||
907 | rec->evlist = evsel_list; | ||
908 | |||
909 | argc = parse_options(argc, argv, record_options, record_usage, | 916 | argc = parse_options(argc, argv, record_options, record_usage, |
910 | PARSE_OPT_STOP_AT_NON_OPTION); | 917 | PARSE_OPT_STOP_AT_NON_OPTION); |
911 | if (!argc && target__none(&rec->opts.target)) | 918 | if (!argc && target__none(&rec->opts.target)) |
@@ -932,12 +939,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
932 | if (rec->no_buildid_cache || rec->no_buildid) | 939 | if (rec->no_buildid_cache || rec->no_buildid) |
933 | disable_buildid_cache(); | 940 | disable_buildid_cache(); |
934 | 941 | ||
935 | if (evsel_list->nr_entries == 0 && | 942 | if (rec->evlist->nr_entries == 0 && |
936 | perf_evlist__add_default(evsel_list) < 0) { | 943 | perf_evlist__add_default(rec->evlist) < 0) { |
937 | pr_err("Not enough memory for event selector list\n"); | 944 | pr_err("Not enough memory for event selector list\n"); |
938 | goto out_symbol_exit; | 945 | goto out_symbol_exit; |
939 | } | 946 | } |
940 | 947 | ||
948 | if (rec->opts.target.tid && !rec->opts.no_inherit_set) | ||
949 | rec->opts.no_inherit = true; | ||
950 | |||
941 | err = target__validate(&rec->opts.target); | 951 | err = target__validate(&rec->opts.target); |
942 | if (err) { | 952 | if (err) { |
943 | target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); | 953 | target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); |
@@ -956,20 +966,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
956 | } | 966 | } |
957 | 967 | ||
958 | err = -ENOMEM; | 968 | err = -ENOMEM; |
959 | if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) | 969 | if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) |
960 | usage_with_options(record_usage, record_options); | 970 | usage_with_options(record_usage, record_options); |
961 | 971 | ||
962 | if (perf_record_opts__config(&rec->opts)) { | 972 | if (record_opts__config(&rec->opts)) { |
963 | err = -EINVAL; | 973 | err = -EINVAL; |
964 | goto out_free_fd; | 974 | goto out_symbol_exit; |
965 | } | 975 | } |
966 | 976 | ||
967 | err = __cmd_record(&record, argc, argv); | 977 | err = __cmd_record(&record, argc, argv); |
968 | |||
969 | perf_evlist__munmap(evsel_list); | ||
970 | perf_evlist__close(evsel_list); | ||
971 | out_free_fd: | ||
972 | perf_evlist__delete_maps(evsel_list); | ||
973 | out_symbol_exit: | 978 | out_symbol_exit: |
974 | symbol__exit(); | 979 | symbol__exit(); |
975 | return err; | 980 | return err; |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 8cf8e66ba594..3c53ec268fbc 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <dlfcn.h> | 39 | #include <dlfcn.h> |
40 | #include <linux/bitmap.h> | 40 | #include <linux/bitmap.h> |
41 | 41 | ||
42 | struct perf_report { | 42 | struct report { |
43 | struct perf_tool tool; | 43 | struct perf_tool tool; |
44 | struct perf_session *session; | 44 | struct perf_session *session; |
45 | bool force, use_tui, use_gtk, use_stdio; | 45 | bool force, use_tui, use_gtk, use_stdio; |
@@ -49,6 +49,8 @@ struct perf_report { | |||
49 | bool show_threads; | 49 | bool show_threads; |
50 | bool inverted_callchain; | 50 | bool inverted_callchain; |
51 | bool mem_mode; | 51 | bool mem_mode; |
52 | bool header; | ||
53 | bool header_only; | ||
52 | int max_stack; | 54 | int max_stack; |
53 | struct perf_read_values show_threads_values; | 55 | struct perf_read_values show_threads_values; |
54 | const char *pretty_printing_style; | 56 | const char *pretty_printing_style; |
@@ -58,14 +60,14 @@ struct perf_report { | |||
58 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 60 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
59 | }; | 61 | }; |
60 | 62 | ||
61 | static int perf_report_config(const char *var, const char *value, void *cb) | 63 | static int report__config(const char *var, const char *value, void *cb) |
62 | { | 64 | { |
63 | if (!strcmp(var, "report.group")) { | 65 | if (!strcmp(var, "report.group")) { |
64 | symbol_conf.event_group = perf_config_bool(var, value); | 66 | symbol_conf.event_group = perf_config_bool(var, value); |
65 | return 0; | 67 | return 0; |
66 | } | 68 | } |
67 | if (!strcmp(var, "report.percent-limit")) { | 69 | if (!strcmp(var, "report.percent-limit")) { |
68 | struct perf_report *rep = cb; | 70 | struct report *rep = cb; |
69 | rep->min_percent = strtof(value, NULL); | 71 | rep->min_percent = strtof(value, NULL); |
70 | return 0; | 72 | return 0; |
71 | } | 73 | } |
@@ -73,31 +75,22 @@ static int perf_report_config(const char *var, const char *value, void *cb) | |||
73 | return perf_default_config(var, value, cb); | 75 | return perf_default_config(var, value, cb); |
74 | } | 76 | } |
75 | 77 | ||
76 | static int perf_report__add_mem_hist_entry(struct perf_tool *tool, | 78 | static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al, |
77 | struct addr_location *al, | 79 | struct perf_sample *sample, struct perf_evsel *evsel, |
78 | struct perf_sample *sample, | 80 | union perf_event *event) |
79 | struct perf_evsel *evsel, | ||
80 | struct machine *machine, | ||
81 | union perf_event *event) | ||
82 | { | 81 | { |
83 | struct perf_report *rep = container_of(tool, struct perf_report, tool); | 82 | struct report *rep = container_of(tool, struct report, tool); |
84 | struct symbol *parent = NULL; | 83 | struct symbol *parent = NULL; |
85 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 84 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
86 | int err = 0; | ||
87 | struct hist_entry *he; | 85 | struct hist_entry *he; |
88 | struct mem_info *mi, *mx; | 86 | struct mem_info *mi, *mx; |
89 | uint64_t cost; | 87 | uint64_t cost; |
88 | int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack); | ||
90 | 89 | ||
91 | if ((sort__has_parent || symbol_conf.use_callchain) && | 90 | if (err) |
92 | sample->callchain) { | 91 | return err; |
93 | err = machine__resolve_callchain(machine, evsel, al->thread, | ||
94 | sample, &parent, al, | ||
95 | rep->max_stack); | ||
96 | if (err) | ||
97 | return err; | ||
98 | } | ||
99 | 92 | ||
100 | mi = machine__resolve_mem(machine, al->thread, sample, cpumode); | 93 | mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode); |
101 | if (!mi) | 94 | if (!mi) |
102 | return -ENOMEM; | 95 | return -ENOMEM; |
103 | 96 | ||
@@ -120,77 +113,36 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool, | |||
120 | if (!he) | 113 | if (!he) |
121 | return -ENOMEM; | 114 | return -ENOMEM; |
122 | 115 | ||
123 | /* | 116 | err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); |
124 | * In the TUI browser, we are doing integrated annotation, | 117 | if (err) |
125 | * so we don't allocate the extra space needed because the stdio | 118 | goto out; |
126 | * code will not use it. | ||
127 | */ | ||
128 | if (sort__has_sym && he->ms.sym && use_browser > 0) { | ||
129 | struct annotation *notes = symbol__annotation(he->ms.sym); | ||
130 | |||
131 | assert(evsel != NULL); | ||
132 | |||
133 | if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0) | ||
134 | goto out; | ||
135 | |||
136 | err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); | ||
137 | if (err) | ||
138 | goto out; | ||
139 | } | ||
140 | 119 | ||
141 | if (sort__has_sym && he->mem_info->daddr.sym && use_browser > 0) { | 120 | mx = he->mem_info; |
142 | struct annotation *notes; | 121 | err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx); |
143 | 122 | if (err) | |
144 | mx = he->mem_info; | 123 | goto out; |
145 | |||
146 | notes = symbol__annotation(mx->daddr.sym); | ||
147 | if (notes->src == NULL && symbol__alloc_hist(mx->daddr.sym) < 0) | ||
148 | goto out; | ||
149 | |||
150 | err = symbol__inc_addr_samples(mx->daddr.sym, | ||
151 | mx->daddr.map, | ||
152 | evsel->idx, | ||
153 | mx->daddr.al_addr); | ||
154 | if (err) | ||
155 | goto out; | ||
156 | } | ||
157 | 124 | ||
158 | evsel->hists.stats.total_period += cost; | 125 | evsel->hists.stats.total_period += cost; |
159 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); | 126 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
160 | err = 0; | 127 | err = hist_entry__append_callchain(he, sample); |
161 | |||
162 | if (symbol_conf.use_callchain) { | ||
163 | err = callchain_append(he->callchain, | ||
164 | &callchain_cursor, | ||
165 | sample->period); | ||
166 | } | ||
167 | out: | 128 | out: |
168 | return err; | 129 | return err; |
169 | } | 130 | } |
170 | 131 | ||
171 | static int perf_report__add_branch_hist_entry(struct perf_tool *tool, | 132 | static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al, |
172 | struct addr_location *al, | 133 | struct perf_sample *sample, struct perf_evsel *evsel) |
173 | struct perf_sample *sample, | ||
174 | struct perf_evsel *evsel, | ||
175 | struct machine *machine) | ||
176 | { | 134 | { |
177 | struct perf_report *rep = container_of(tool, struct perf_report, tool); | 135 | struct report *rep = container_of(tool, struct report, tool); |
178 | struct symbol *parent = NULL; | 136 | struct symbol *parent = NULL; |
179 | int err = 0; | ||
180 | unsigned i; | 137 | unsigned i; |
181 | struct hist_entry *he; | 138 | struct hist_entry *he; |
182 | struct branch_info *bi, *bx; | 139 | struct branch_info *bi, *bx; |
140 | int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack); | ||
183 | 141 | ||
184 | if ((sort__has_parent || symbol_conf.use_callchain) | 142 | if (err) |
185 | && sample->callchain) { | 143 | return err; |
186 | err = machine__resolve_callchain(machine, evsel, al->thread, | ||
187 | sample, &parent, al, | ||
188 | rep->max_stack); | ||
189 | if (err) | ||
190 | return err; | ||
191 | } | ||
192 | 144 | ||
193 | bi = machine__resolve_bstack(machine, al->thread, | 145 | bi = machine__resolve_bstack(al->machine, al->thread, |
194 | sample->branch_stack); | 146 | sample->branch_stack); |
195 | if (!bi) | 147 | if (!bi) |
196 | return -ENOMEM; | 148 | return -ENOMEM; |
@@ -212,35 +164,15 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, | |||
212 | he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL, | 164 | he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL, |
213 | 1, 1, 0); | 165 | 1, 1, 0); |
214 | if (he) { | 166 | if (he) { |
215 | struct annotation *notes; | ||
216 | bx = he->branch_info; | 167 | bx = he->branch_info; |
217 | if (bx->from.sym && use_browser == 1 && sort__has_sym) { | 168 | err = addr_map_symbol__inc_samples(&bx->from, evsel->idx); |
218 | notes = symbol__annotation(bx->from.sym); | 169 | if (err) |
219 | if (!notes->src | 170 | goto out; |
220 | && symbol__alloc_hist(bx->from.sym) < 0) | 171 | |
221 | goto out; | 172 | err = addr_map_symbol__inc_samples(&bx->to, evsel->idx); |
222 | 173 | if (err) | |
223 | err = symbol__inc_addr_samples(bx->from.sym, | 174 | goto out; |
224 | bx->from.map, | ||
225 | evsel->idx, | ||
226 | bx->from.al_addr); | ||
227 | if (err) | ||
228 | goto out; | ||
229 | } | ||
230 | 175 | ||
231 | if (bx->to.sym && use_browser == 1 && sort__has_sym) { | ||
232 | notes = symbol__annotation(bx->to.sym); | ||
233 | if (!notes->src | ||
234 | && symbol__alloc_hist(bx->to.sym) < 0) | ||
235 | goto out; | ||
236 | |||
237 | err = symbol__inc_addr_samples(bx->to.sym, | ||
238 | bx->to.map, | ||
239 | evsel->idx, | ||
240 | bx->to.al_addr); | ||
241 | if (err) | ||
242 | goto out; | ||
243 | } | ||
244 | evsel->hists.stats.total_period += 1; | 176 | evsel->hists.stats.total_period += 1; |
245 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); | 177 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
246 | } else | 178 | } else |
@@ -252,24 +184,16 @@ out: | |||
252 | return err; | 184 | return err; |
253 | } | 185 | } |
254 | 186 | ||
255 | static int perf_evsel__add_hist_entry(struct perf_tool *tool, | 187 | static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel, |
256 | struct perf_evsel *evsel, | 188 | struct addr_location *al, struct perf_sample *sample) |
257 | struct addr_location *al, | ||
258 | struct perf_sample *sample, | ||
259 | struct machine *machine) | ||
260 | { | 189 | { |
261 | struct perf_report *rep = container_of(tool, struct perf_report, tool); | 190 | struct report *rep = container_of(tool, struct report, tool); |
262 | struct symbol *parent = NULL; | 191 | struct symbol *parent = NULL; |
263 | int err = 0; | ||
264 | struct hist_entry *he; | 192 | struct hist_entry *he; |
193 | int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack); | ||
265 | 194 | ||
266 | if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { | 195 | if (err) |
267 | err = machine__resolve_callchain(machine, evsel, al->thread, | 196 | return err; |
268 | sample, &parent, al, | ||
269 | rep->max_stack); | ||
270 | if (err) | ||
271 | return err; | ||
272 | } | ||
273 | 197 | ||
274 | he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL, | 198 | he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL, |
275 | sample->period, sample->weight, | 199 | sample->period, sample->weight, |
@@ -277,30 +201,11 @@ static int perf_evsel__add_hist_entry(struct perf_tool *tool, | |||
277 | if (he == NULL) | 201 | if (he == NULL) |
278 | return -ENOMEM; | 202 | return -ENOMEM; |
279 | 203 | ||
280 | if (symbol_conf.use_callchain) { | 204 | err = hist_entry__append_callchain(he, sample); |
281 | err = callchain_append(he->callchain, | 205 | if (err) |
282 | &callchain_cursor, | 206 | goto out; |
283 | sample->period); | ||
284 | if (err) | ||
285 | return err; | ||
286 | } | ||
287 | /* | ||
288 | * Only in the TUI browser we are doing integrated annotation, | ||
289 | * so we don't allocated the extra space needed because the stdio | ||
290 | * code will not use it. | ||
291 | */ | ||
292 | if (he->ms.sym != NULL && use_browser == 1 && sort__has_sym) { | ||
293 | struct annotation *notes = symbol__annotation(he->ms.sym); | ||
294 | |||
295 | assert(evsel != NULL); | ||
296 | |||
297 | err = -ENOMEM; | ||
298 | if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0) | ||
299 | goto out; | ||
300 | |||
301 | err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); | ||
302 | } | ||
303 | 207 | ||
208 | err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); | ||
304 | evsel->hists.stats.total_period += sample->period; | 209 | evsel->hists.stats.total_period += sample->period; |
305 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); | 210 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
306 | out: | 211 | out: |
@@ -314,13 +219,13 @@ static int process_sample_event(struct perf_tool *tool, | |||
314 | struct perf_evsel *evsel, | 219 | struct perf_evsel *evsel, |
315 | struct machine *machine) | 220 | struct machine *machine) |
316 | { | 221 | { |
317 | struct perf_report *rep = container_of(tool, struct perf_report, tool); | 222 | struct report *rep = container_of(tool, struct report, tool); |
318 | struct addr_location al; | 223 | struct addr_location al; |
319 | int ret; | 224 | int ret; |
320 | 225 | ||
321 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | 226 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { |
322 | fprintf(stderr, "problem processing %d event, skipping it.\n", | 227 | pr_debug("problem processing %d event, skipping it.\n", |
323 | event->header.type); | 228 | event->header.type); |
324 | return -1; | 229 | return -1; |
325 | } | 230 | } |
326 | 231 | ||
@@ -331,21 +236,18 @@ static int process_sample_event(struct perf_tool *tool, | |||
331 | return 0; | 236 | return 0; |
332 | 237 | ||
333 | if (sort__mode == SORT_MODE__BRANCH) { | 238 | if (sort__mode == SORT_MODE__BRANCH) { |
334 | ret = perf_report__add_branch_hist_entry(tool, &al, sample, | 239 | ret = report__add_branch_hist_entry(tool, &al, sample, evsel); |
335 | evsel, machine); | ||
336 | if (ret < 0) | 240 | if (ret < 0) |
337 | pr_debug("problem adding lbr entry, skipping event\n"); | 241 | pr_debug("problem adding lbr entry, skipping event\n"); |
338 | } else if (rep->mem_mode == 1) { | 242 | } else if (rep->mem_mode == 1) { |
339 | ret = perf_report__add_mem_hist_entry(tool, &al, sample, | 243 | ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event); |
340 | evsel, machine, event); | ||
341 | if (ret < 0) | 244 | if (ret < 0) |
342 | pr_debug("problem adding mem entry, skipping event\n"); | 245 | pr_debug("problem adding mem entry, skipping event\n"); |
343 | } else { | 246 | } else { |
344 | if (al.map != NULL) | 247 | if (al.map != NULL) |
345 | al.map->dso->hit = 1; | 248 | al.map->dso->hit = 1; |
346 | 249 | ||
347 | ret = perf_evsel__add_hist_entry(tool, evsel, &al, sample, | 250 | ret = report__add_hist_entry(tool, evsel, &al, sample); |
348 | machine); | ||
349 | if (ret < 0) | 251 | if (ret < 0) |
350 | pr_debug("problem incrementing symbol period, skipping event\n"); | 252 | pr_debug("problem incrementing symbol period, skipping event\n"); |
351 | } | 253 | } |
@@ -358,7 +260,7 @@ static int process_read_event(struct perf_tool *tool, | |||
358 | struct perf_evsel *evsel, | 260 | struct perf_evsel *evsel, |
359 | struct machine *machine __maybe_unused) | 261 | struct machine *machine __maybe_unused) |
360 | { | 262 | { |
361 | struct perf_report *rep = container_of(tool, struct perf_report, tool); | 263 | struct report *rep = container_of(tool, struct report, tool); |
362 | 264 | ||
363 | if (rep->show_threads) { | 265 | if (rep->show_threads) { |
364 | const char *name = evsel ? perf_evsel__name(evsel) : "unknown"; | 266 | const char *name = evsel ? perf_evsel__name(evsel) : "unknown"; |
@@ -377,7 +279,7 @@ static int process_read_event(struct perf_tool *tool, | |||
377 | } | 279 | } |
378 | 280 | ||
379 | /* For pipe mode, sample_type is not currently set */ | 281 | /* For pipe mode, sample_type is not currently set */ |
380 | static int perf_report__setup_sample_type(struct perf_report *rep) | 282 | static int report__setup_sample_type(struct report *rep) |
381 | { | 283 | { |
382 | struct perf_session *session = rep->session; | 284 | struct perf_session *session = rep->session; |
383 | u64 sample_type = perf_evlist__combined_sample_type(session->evlist); | 285 | u64 sample_type = perf_evlist__combined_sample_type(session->evlist); |
@@ -422,8 +324,7 @@ static void sig_handler(int sig __maybe_unused) | |||
422 | session_done = 1; | 324 | session_done = 1; |
423 | } | 325 | } |
424 | 326 | ||
425 | static size_t hists__fprintf_nr_sample_events(struct perf_report *rep, | 327 | static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep, |
426 | struct hists *hists, | ||
427 | const char *evname, FILE *fp) | 328 | const char *evname, FILE *fp) |
428 | { | 329 | { |
429 | size_t ret; | 330 | size_t ret; |
@@ -460,12 +361,12 @@ static size_t hists__fprintf_nr_sample_events(struct perf_report *rep, | |||
460 | } | 361 | } |
461 | 362 | ||
462 | static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, | 363 | static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, |
463 | struct perf_report *rep, | 364 | struct report *rep, |
464 | const char *help) | 365 | const char *help) |
465 | { | 366 | { |
466 | struct perf_evsel *pos; | 367 | struct perf_evsel *pos; |
467 | 368 | ||
468 | list_for_each_entry(pos, &evlist->entries, node) { | 369 | evlist__for_each(evlist, pos) { |
469 | struct hists *hists = &pos->hists; | 370 | struct hists *hists = &pos->hists; |
470 | const char *evname = perf_evsel__name(pos); | 371 | const char *evname = perf_evsel__name(pos); |
471 | 372 | ||
@@ -473,7 +374,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, | |||
473 | !perf_evsel__is_group_leader(pos)) | 374 | !perf_evsel__is_group_leader(pos)) |
474 | continue; | 375 | continue; |
475 | 376 | ||
476 | hists__fprintf_nr_sample_events(rep, hists, evname, stdout); | 377 | hists__fprintf_nr_sample_events(hists, rep, evname, stdout); |
477 | hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); | 378 | hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); |
478 | fprintf(stdout, "\n\n"); | 379 | fprintf(stdout, "\n\n"); |
479 | } | 380 | } |
@@ -493,43 +394,11 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, | |||
493 | return 0; | 394 | return 0; |
494 | } | 395 | } |
495 | 396 | ||
496 | static int __cmd_report(struct perf_report *rep) | 397 | static void report__warn_kptr_restrict(const struct report *rep) |
497 | { | 398 | { |
498 | int ret = -EINVAL; | 399 | struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; |
499 | u64 nr_samples; | 400 | struct kmap *kernel_kmap = map__kmap(kernel_map); |
500 | struct perf_session *session = rep->session; | ||
501 | struct perf_evsel *pos; | ||
502 | struct map *kernel_map; | ||
503 | struct kmap *kernel_kmap; | ||
504 | const char *help = "For a higher level overview, try: perf report --sort comm,dso"; | ||
505 | struct ui_progress prog; | ||
506 | struct perf_data_file *file = session->file; | ||
507 | |||
508 | signal(SIGINT, sig_handler); | ||
509 | 401 | ||
510 | if (rep->cpu_list) { | ||
511 | ret = perf_session__cpu_bitmap(session, rep->cpu_list, | ||
512 | rep->cpu_bitmap); | ||
513 | if (ret) | ||
514 | return ret; | ||
515 | } | ||
516 | |||
517 | if (use_browser <= 0) | ||
518 | perf_session__fprintf_info(session, stdout, rep->show_full_info); | ||
519 | |||
520 | if (rep->show_threads) | ||
521 | perf_read_values_init(&rep->show_threads_values); | ||
522 | |||
523 | ret = perf_report__setup_sample_type(rep); | ||
524 | if (ret) | ||
525 | return ret; | ||
526 | |||
527 | ret = perf_session__process_events(session, &rep->tool); | ||
528 | if (ret) | ||
529 | return ret; | ||
530 | |||
531 | kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION]; | ||
532 | kernel_kmap = map__kmap(kernel_map); | ||
533 | if (kernel_map == NULL || | 402 | if (kernel_map == NULL || |
534 | (kernel_map->dso->hit && | 403 | (kernel_map->dso->hit && |
535 | (kernel_kmap->ref_reloc_sym == NULL || | 404 | (kernel_kmap->ref_reloc_sym == NULL || |
@@ -552,26 +421,73 @@ static int __cmd_report(struct perf_report *rep) | |||
552 | "Samples in kernel modules can't be resolved as well.\n\n", | 421 | "Samples in kernel modules can't be resolved as well.\n\n", |
553 | desc); | 422 | desc); |
554 | } | 423 | } |
424 | } | ||
555 | 425 | ||
556 | if (verbose > 3) | 426 | static int report__gtk_browse_hists(struct report *rep, const char *help) |
557 | perf_session__fprintf(session, stdout); | 427 | { |
428 | int (*hist_browser)(struct perf_evlist *evlist, const char *help, | ||
429 | struct hist_browser_timer *timer, float min_pcnt); | ||
558 | 430 | ||
559 | if (verbose > 2) | 431 | hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists"); |
560 | perf_session__fprintf_dsos(session, stdout); | ||
561 | 432 | ||
562 | if (dump_trace) { | 433 | if (hist_browser == NULL) { |
563 | perf_session__fprintf_nr_events(session, stdout); | 434 | ui__error("GTK browser not found!\n"); |
564 | return 0; | 435 | return -1; |
565 | } | 436 | } |
566 | 437 | ||
567 | nr_samples = 0; | 438 | return hist_browser(rep->session->evlist, help, NULL, rep->min_percent); |
568 | list_for_each_entry(pos, &session->evlist->entries, node) | 439 | } |
440 | |||
441 | static int report__browse_hists(struct report *rep) | ||
442 | { | ||
443 | int ret; | ||
444 | struct perf_session *session = rep->session; | ||
445 | struct perf_evlist *evlist = session->evlist; | ||
446 | const char *help = "For a higher level overview, try: perf report --sort comm,dso"; | ||
447 | |||
448 | switch (use_browser) { | ||
449 | case 1: | ||
450 | ret = perf_evlist__tui_browse_hists(evlist, help, NULL, | ||
451 | rep->min_percent, | ||
452 | &session->header.env); | ||
453 | /* | ||
454 | * Usually "ret" is the last pressed key, and we only | ||
455 | * care if the key notifies us to switch data file. | ||
456 | */ | ||
457 | if (ret != K_SWITCH_INPUT_DATA) | ||
458 | ret = 0; | ||
459 | break; | ||
460 | case 2: | ||
461 | ret = report__gtk_browse_hists(rep, help); | ||
462 | break; | ||
463 | default: | ||
464 | ret = perf_evlist__tty_browse_hists(evlist, rep, help); | ||
465 | break; | ||
466 | } | ||
467 | |||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | static u64 report__collapse_hists(struct report *rep) | ||
472 | { | ||
473 | struct ui_progress prog; | ||
474 | struct perf_evsel *pos; | ||
475 | u64 nr_samples = 0; | ||
476 | /* | ||
477 | * Count number of histogram entries to use when showing progress, | ||
478 | * reusing nr_samples variable. | ||
479 | */ | ||
480 | evlist__for_each(rep->session->evlist, pos) | ||
569 | nr_samples += pos->hists.nr_entries; | 481 | nr_samples += pos->hists.nr_entries; |
570 | 482 | ||
571 | ui_progress__init(&prog, nr_samples, "Merging related events..."); | 483 | ui_progress__init(&prog, nr_samples, "Merging related events..."); |
572 | 484 | /* | |
485 | * Count total number of samples, will be used to check if this | ||
486 | * session had any. | ||
487 | */ | ||
573 | nr_samples = 0; | 488 | nr_samples = 0; |
574 | list_for_each_entry(pos, &session->evlist->entries, node) { | 489 | |
490 | evlist__for_each(rep->session->evlist, pos) { | ||
575 | struct hists *hists = &pos->hists; | 491 | struct hists *hists = &pos->hists; |
576 | 492 | ||
577 | if (pos->idx == 0) | 493 | if (pos->idx == 0) |
@@ -589,8 +505,57 @@ static int __cmd_report(struct perf_report *rep) | |||
589 | hists__link(leader_hists, hists); | 505 | hists__link(leader_hists, hists); |
590 | } | 506 | } |
591 | } | 507 | } |
508 | |||
592 | ui_progress__finish(); | 509 | ui_progress__finish(); |
593 | 510 | ||
511 | return nr_samples; | ||
512 | } | ||
513 | |||
514 | static int __cmd_report(struct report *rep) | ||
515 | { | ||
516 | int ret; | ||
517 | u64 nr_samples; | ||
518 | struct perf_session *session = rep->session; | ||
519 | struct perf_evsel *pos; | ||
520 | struct perf_data_file *file = session->file; | ||
521 | |||
522 | signal(SIGINT, sig_handler); | ||
523 | |||
524 | if (rep->cpu_list) { | ||
525 | ret = perf_session__cpu_bitmap(session, rep->cpu_list, | ||
526 | rep->cpu_bitmap); | ||
527 | if (ret) | ||
528 | return ret; | ||
529 | } | ||
530 | |||
531 | if (rep->show_threads) | ||
532 | perf_read_values_init(&rep->show_threads_values); | ||
533 | |||
534 | ret = report__setup_sample_type(rep); | ||
535 | if (ret) | ||
536 | return ret; | ||
537 | |||
538 | ret = perf_session__process_events(session, &rep->tool); | ||
539 | if (ret) | ||
540 | return ret; | ||
541 | |||
542 | report__warn_kptr_restrict(rep); | ||
543 | |||
544 | if (use_browser == 0) { | ||
545 | if (verbose > 3) | ||
546 | perf_session__fprintf(session, stdout); | ||
547 | |||
548 | if (verbose > 2) | ||
549 | perf_session__fprintf_dsos(session, stdout); | ||
550 | |||
551 | if (dump_trace) { | ||
552 | perf_session__fprintf_nr_events(session, stdout); | ||
553 | return 0; | ||
554 | } | ||
555 | } | ||
556 | |||
557 | nr_samples = report__collapse_hists(rep); | ||
558 | |||
594 | if (session_done()) | 559 | if (session_done()) |
595 | return 0; | 560 | return 0; |
596 | 561 | ||
@@ -599,47 +564,16 @@ static int __cmd_report(struct perf_report *rep) | |||
599 | return 0; | 564 | return 0; |
600 | } | 565 | } |
601 | 566 | ||
602 | list_for_each_entry(pos, &session->evlist->entries, node) | 567 | evlist__for_each(session->evlist, pos) |
603 | hists__output_resort(&pos->hists); | 568 | hists__output_resort(&pos->hists); |
604 | 569 | ||
605 | if (use_browser > 0) { | 570 | return report__browse_hists(rep); |
606 | if (use_browser == 1) { | ||
607 | ret = perf_evlist__tui_browse_hists(session->evlist, | ||
608 | help, NULL, | ||
609 | rep->min_percent, | ||
610 | &session->header.env); | ||
611 | /* | ||
612 | * Usually "ret" is the last pressed key, and we only | ||
613 | * care if the key notifies us to switch data file. | ||
614 | */ | ||
615 | if (ret != K_SWITCH_INPUT_DATA) | ||
616 | ret = 0; | ||
617 | |||
618 | } else if (use_browser == 2) { | ||
619 | int (*hist_browser)(struct perf_evlist *, | ||
620 | const char *, | ||
621 | struct hist_browser_timer *, | ||
622 | float min_pcnt); | ||
623 | |||
624 | hist_browser = dlsym(perf_gtk_handle, | ||
625 | "perf_evlist__gtk_browse_hists"); | ||
626 | if (hist_browser == NULL) { | ||
627 | ui__error("GTK browser not found!\n"); | ||
628 | return ret; | ||
629 | } | ||
630 | hist_browser(session->evlist, help, NULL, | ||
631 | rep->min_percent); | ||
632 | } | ||
633 | } else | ||
634 | perf_evlist__tty_browse_hists(session->evlist, rep, help); | ||
635 | |||
636 | return ret; | ||
637 | } | 571 | } |
638 | 572 | ||
639 | static int | 573 | static int |
640 | parse_callchain_opt(const struct option *opt, const char *arg, int unset) | 574 | parse_callchain_opt(const struct option *opt, const char *arg, int unset) |
641 | { | 575 | { |
642 | struct perf_report *rep = (struct perf_report *)opt->value; | 576 | struct report *rep = (struct report *)opt->value; |
643 | char *tok, *tok2; | 577 | char *tok, *tok2; |
644 | char *endptr; | 578 | char *endptr; |
645 | 579 | ||
@@ -721,7 +655,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) | |||
721 | return -1; | 655 | return -1; |
722 | setup: | 656 | setup: |
723 | if (callchain_register_param(&callchain_param) < 0) { | 657 | if (callchain_register_param(&callchain_param) < 0) { |
724 | fprintf(stderr, "Can't register callchain params\n"); | 658 | pr_err("Can't register callchain params\n"); |
725 | return -1; | 659 | return -1; |
726 | } | 660 | } |
727 | return 0; | 661 | return 0; |
@@ -759,7 +693,7 @@ static int | |||
759 | parse_percent_limit(const struct option *opt, const char *str, | 693 | parse_percent_limit(const struct option *opt, const char *str, |
760 | int unset __maybe_unused) | 694 | int unset __maybe_unused) |
761 | { | 695 | { |
762 | struct perf_report *rep = opt->value; | 696 | struct report *rep = opt->value; |
763 | 697 | ||
764 | rep->min_percent = strtof(str, NULL); | 698 | rep->min_percent = strtof(str, NULL); |
765 | return 0; | 699 | return 0; |
@@ -777,7 +711,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
777 | "perf report [<options>]", | 711 | "perf report [<options>]", |
778 | NULL | 712 | NULL |
779 | }; | 713 | }; |
780 | struct perf_report report = { | 714 | struct report report = { |
781 | .tool = { | 715 | .tool = { |
782 | .sample = process_sample_event, | 716 | .sample = process_sample_event, |
783 | .mmap = perf_event__process_mmap, | 717 | .mmap = perf_event__process_mmap, |
@@ -820,6 +754,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
820 | OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"), | 754 | OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"), |
821 | OPT_BOOLEAN(0, "stdio", &report.use_stdio, | 755 | OPT_BOOLEAN(0, "stdio", &report.use_stdio, |
822 | "Use the stdio interface"), | 756 | "Use the stdio interface"), |
757 | OPT_BOOLEAN(0, "header", &report.header, "Show data header."), | ||
758 | OPT_BOOLEAN(0, "header-only", &report.header_only, | ||
759 | "Show only data header."), | ||
823 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", | 760 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", |
824 | "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," | 761 | "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," |
825 | " dso_to, dso_from, symbol_to, symbol_from, mispredict," | 762 | " dso_to, dso_from, symbol_to, symbol_from, mispredict," |
@@ -890,7 +827,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
890 | .mode = PERF_DATA_MODE_READ, | 827 | .mode = PERF_DATA_MODE_READ, |
891 | }; | 828 | }; |
892 | 829 | ||
893 | perf_config(perf_report_config, &report); | 830 | perf_config(report__config, &report); |
894 | 831 | ||
895 | argc = parse_options(argc, argv, options, report_usage, 0); | 832 | argc = parse_options(argc, argv, options, report_usage, 0); |
896 | 833 | ||
@@ -940,7 +877,7 @@ repeat: | |||
940 | } | 877 | } |
941 | if (report.mem_mode) { | 878 | if (report.mem_mode) { |
942 | if (sort__mode == SORT_MODE__BRANCH) { | 879 | if (sort__mode == SORT_MODE__BRANCH) { |
943 | fprintf(stderr, "branch and mem mode incompatible\n"); | 880 | pr_err("branch and mem mode incompatible\n"); |
944 | goto error; | 881 | goto error; |
945 | } | 882 | } |
946 | sort__mode = SORT_MODE__MEMORY; | 883 | sort__mode = SORT_MODE__MEMORY; |
@@ -963,6 +900,10 @@ repeat: | |||
963 | goto error; | 900 | goto error; |
964 | } | 901 | } |
965 | 902 | ||
903 | /* Force tty output for header output. */ | ||
904 | if (report.header || report.header_only) | ||
905 | use_browser = 0; | ||
906 | |||
966 | if (strcmp(input_name, "-") != 0) | 907 | if (strcmp(input_name, "-") != 0) |
967 | setup_browser(true); | 908 | setup_browser(true); |
968 | else { | 909 | else { |
@@ -970,6 +911,16 @@ repeat: | |||
970 | perf_hpp__init(); | 911 | perf_hpp__init(); |
971 | } | 912 | } |
972 | 913 | ||
914 | if (report.header || report.header_only) { | ||
915 | perf_session__fprintf_info(session, stdout, | ||
916 | report.show_full_info); | ||
917 | if (report.header_only) | ||
918 | return 0; | ||
919 | } else if (use_browser == 0) { | ||
920 | fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n", | ||
921 | stdout); | ||
922 | } | ||
923 | |||
973 | /* | 924 | /* |
974 | * Only in the TUI browser we are doing integrated annotation, | 925 | * Only in the TUI browser we are doing integrated annotation, |
975 | * so don't allocate extra space that won't be used in the stdio | 926 | * so don't allocate extra space that won't be used in the stdio |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 0f3c65518a2c..6a76a07b6789 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -469,7 +469,7 @@ static void *thread_func(void *ctx) | |||
469 | char comm2[22]; | 469 | char comm2[22]; |
470 | int fd; | 470 | int fd; |
471 | 471 | ||
472 | free(parms); | 472 | zfree(&parms); |
473 | 473 | ||
474 | sprintf(comm2, ":%s", this_task->comm); | 474 | sprintf(comm2, ":%s", this_task->comm); |
475 | prctl(PR_SET_NAME, comm2); | 475 | prctl(PR_SET_NAME, comm2); |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index baf17989a216..9e9c91f5b7fa 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -43,6 +43,7 @@ enum perf_output_field { | |||
43 | PERF_OUTPUT_DSO = 1U << 9, | 43 | PERF_OUTPUT_DSO = 1U << 9, |
44 | PERF_OUTPUT_ADDR = 1U << 10, | 44 | PERF_OUTPUT_ADDR = 1U << 10, |
45 | PERF_OUTPUT_SYMOFFSET = 1U << 11, | 45 | PERF_OUTPUT_SYMOFFSET = 1U << 11, |
46 | PERF_OUTPUT_SRCLINE = 1U << 12, | ||
46 | }; | 47 | }; |
47 | 48 | ||
48 | struct output_option { | 49 | struct output_option { |
@@ -61,6 +62,7 @@ struct output_option { | |||
61 | {.str = "dso", .field = PERF_OUTPUT_DSO}, | 62 | {.str = "dso", .field = PERF_OUTPUT_DSO}, |
62 | {.str = "addr", .field = PERF_OUTPUT_ADDR}, | 63 | {.str = "addr", .field = PERF_OUTPUT_ADDR}, |
63 | {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, | 64 | {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, |
65 | {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, | ||
64 | }; | 66 | }; |
65 | 67 | ||
66 | /* default set to maintain compatibility with current format */ | 68 | /* default set to maintain compatibility with current format */ |
@@ -210,6 +212,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, | |||
210 | "to DSO.\n"); | 212 | "to DSO.\n"); |
211 | return -EINVAL; | 213 | return -EINVAL; |
212 | } | 214 | } |
215 | if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { | ||
216 | pr_err("Display of source line number requested but sample IP is not\n" | ||
217 | "selected. Hence, no address to lookup the source line number.\n"); | ||
218 | return -EINVAL; | ||
219 | } | ||
213 | 220 | ||
214 | if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && | 221 | if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && |
215 | perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", | 222 | perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", |
@@ -245,6 +252,9 @@ static void set_print_ip_opts(struct perf_event_attr *attr) | |||
245 | 252 | ||
246 | if (PRINT_FIELD(SYMOFFSET)) | 253 | if (PRINT_FIELD(SYMOFFSET)) |
247 | output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; | 254 | output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; |
255 | |||
256 | if (PRINT_FIELD(SRCLINE)) | ||
257 | output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE; | ||
248 | } | 258 | } |
249 | 259 | ||
250 | /* | 260 | /* |
@@ -280,6 +290,30 @@ static int perf_session__check_output_opt(struct perf_session *session) | |||
280 | set_print_ip_opts(&evsel->attr); | 290 | set_print_ip_opts(&evsel->attr); |
281 | } | 291 | } |
282 | 292 | ||
293 | /* | ||
294 | * set default for tracepoints to print symbols only | ||
295 | * if callchains are present | ||
296 | */ | ||
297 | if (symbol_conf.use_callchain && | ||
298 | !output[PERF_TYPE_TRACEPOINT].user_set) { | ||
299 | struct perf_event_attr *attr; | ||
300 | |||
301 | j = PERF_TYPE_TRACEPOINT; | ||
302 | evsel = perf_session__find_first_evtype(session, j); | ||
303 | if (evsel == NULL) | ||
304 | goto out; | ||
305 | |||
306 | attr = &evsel->attr; | ||
307 | |||
308 | if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { | ||
309 | output[j].fields |= PERF_OUTPUT_IP; | ||
310 | output[j].fields |= PERF_OUTPUT_SYM; | ||
311 | output[j].fields |= PERF_OUTPUT_DSO; | ||
312 | set_print_ip_opts(attr); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | out: | ||
283 | return 0; | 317 | return 0; |
284 | } | 318 | } |
285 | 319 | ||
@@ -288,7 +322,6 @@ static void print_sample_start(struct perf_sample *sample, | |||
288 | struct perf_evsel *evsel) | 322 | struct perf_evsel *evsel) |
289 | { | 323 | { |
290 | struct perf_event_attr *attr = &evsel->attr; | 324 | struct perf_event_attr *attr = &evsel->attr; |
291 | const char *evname = NULL; | ||
292 | unsigned long secs; | 325 | unsigned long secs; |
293 | unsigned long usecs; | 326 | unsigned long usecs; |
294 | unsigned long long nsecs; | 327 | unsigned long long nsecs; |
@@ -323,11 +356,6 @@ static void print_sample_start(struct perf_sample *sample, | |||
323 | usecs = nsecs / NSECS_PER_USEC; | 356 | usecs = nsecs / NSECS_PER_USEC; |
324 | printf("%5lu.%06lu: ", secs, usecs); | 357 | printf("%5lu.%06lu: ", secs, usecs); |
325 | } | 358 | } |
326 | |||
327 | if (PRINT_FIELD(EVNAME)) { | ||
328 | evname = perf_evsel__name(evsel); | ||
329 | printf("%s: ", evname ? evname : "[unknown]"); | ||
330 | } | ||
331 | } | 359 | } |
332 | 360 | ||
333 | static bool is_bts_event(struct perf_event_attr *attr) | 361 | static bool is_bts_event(struct perf_event_attr *attr) |
@@ -395,8 +423,8 @@ static void print_sample_addr(union perf_event *event, | |||
395 | static void print_sample_bts(union perf_event *event, | 423 | static void print_sample_bts(union perf_event *event, |
396 | struct perf_sample *sample, | 424 | struct perf_sample *sample, |
397 | struct perf_evsel *evsel, | 425 | struct perf_evsel *evsel, |
398 | struct machine *machine, | 426 | struct thread *thread, |
399 | struct thread *thread) | 427 | struct addr_location *al) |
400 | { | 428 | { |
401 | struct perf_event_attr *attr = &evsel->attr; | 429 | struct perf_event_attr *attr = &evsel->attr; |
402 | 430 | ||
@@ -406,7 +434,7 @@ static void print_sample_bts(union perf_event *event, | |||
406 | printf(" "); | 434 | printf(" "); |
407 | else | 435 | else |
408 | printf("\n"); | 436 | printf("\n"); |
409 | perf_evsel__print_ip(evsel, event, sample, machine, | 437 | perf_evsel__print_ip(evsel, sample, al, |
410 | output[attr->type].print_ip_opts, | 438 | output[attr->type].print_ip_opts, |
411 | PERF_MAX_STACK_DEPTH); | 439 | PERF_MAX_STACK_DEPTH); |
412 | } | 440 | } |
@@ -417,15 +445,14 @@ static void print_sample_bts(union perf_event *event, | |||
417 | if (PRINT_FIELD(ADDR) || | 445 | if (PRINT_FIELD(ADDR) || |
418 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && | 446 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && |
419 | !output[attr->type].user_set)) | 447 | !output[attr->type].user_set)) |
420 | print_sample_addr(event, sample, machine, thread, attr); | 448 | print_sample_addr(event, sample, al->machine, thread, attr); |
421 | 449 | ||
422 | printf("\n"); | 450 | printf("\n"); |
423 | } | 451 | } |
424 | 452 | ||
425 | static void process_event(union perf_event *event, struct perf_sample *sample, | 453 | static void process_event(union perf_event *event, struct perf_sample *sample, |
426 | struct perf_evsel *evsel, struct machine *machine, | 454 | struct perf_evsel *evsel, struct thread *thread, |
427 | struct thread *thread, | 455 | struct addr_location *al) |
428 | struct addr_location *al __maybe_unused) | ||
429 | { | 456 | { |
430 | struct perf_event_attr *attr = &evsel->attr; | 457 | struct perf_event_attr *attr = &evsel->attr; |
431 | 458 | ||
@@ -434,8 +461,13 @@ static void process_event(union perf_event *event, struct perf_sample *sample, | |||
434 | 461 | ||
435 | print_sample_start(sample, thread, evsel); | 462 | print_sample_start(sample, thread, evsel); |
436 | 463 | ||
464 | if (PRINT_FIELD(EVNAME)) { | ||
465 | const char *evname = perf_evsel__name(evsel); | ||
466 | printf("%s: ", evname ? evname : "[unknown]"); | ||
467 | } | ||
468 | |||
437 | if (is_bts_event(attr)) { | 469 | if (is_bts_event(attr)) { |
438 | print_sample_bts(event, sample, evsel, machine, thread); | 470 | print_sample_bts(event, sample, evsel, thread, al); |
439 | return; | 471 | return; |
440 | } | 472 | } |
441 | 473 | ||
@@ -443,7 +475,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample, | |||
443 | event_format__print(evsel->tp_format, sample->cpu, | 475 | event_format__print(evsel->tp_format, sample->cpu, |
444 | sample->raw_data, sample->raw_size); | 476 | sample->raw_data, sample->raw_size); |
445 | if (PRINT_FIELD(ADDR)) | 477 | if (PRINT_FIELD(ADDR)) |
446 | print_sample_addr(event, sample, machine, thread, attr); | 478 | print_sample_addr(event, sample, al->machine, thread, attr); |
447 | 479 | ||
448 | if (PRINT_FIELD(IP)) { | 480 | if (PRINT_FIELD(IP)) { |
449 | if (!symbol_conf.use_callchain) | 481 | if (!symbol_conf.use_callchain) |
@@ -451,7 +483,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample, | |||
451 | else | 483 | else |
452 | printf("\n"); | 484 | printf("\n"); |
453 | 485 | ||
454 | perf_evsel__print_ip(evsel, event, sample, machine, | 486 | perf_evsel__print_ip(evsel, sample, al, |
455 | output[attr->type].print_ip_opts, | 487 | output[attr->type].print_ip_opts, |
456 | PERF_MAX_STACK_DEPTH); | 488 | PERF_MAX_STACK_DEPTH); |
457 | } | 489 | } |
@@ -540,7 +572,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, | |||
540 | if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) | 572 | if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) |
541 | return 0; | 573 | return 0; |
542 | 574 | ||
543 | scripting_ops->process_event(event, sample, evsel, machine, thread, &al); | 575 | scripting_ops->process_event(event, sample, evsel, thread, &al); |
544 | 576 | ||
545 | evsel->hists.stats.total_period += sample->period; | 577 | evsel->hists.stats.total_period += sample->period; |
546 | return 0; | 578 | return 0; |
@@ -549,6 +581,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, | |||
549 | struct perf_script { | 581 | struct perf_script { |
550 | struct perf_tool tool; | 582 | struct perf_tool tool; |
551 | struct perf_session *session; | 583 | struct perf_session *session; |
584 | bool show_task_events; | ||
585 | bool show_mmap_events; | ||
552 | }; | 586 | }; |
553 | 587 | ||
554 | static int process_attr(struct perf_tool *tool, union perf_event *event, | 588 | static int process_attr(struct perf_tool *tool, union perf_event *event, |
@@ -569,7 +603,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, | |||
569 | if (evsel->attr.type >= PERF_TYPE_MAX) | 603 | if (evsel->attr.type >= PERF_TYPE_MAX) |
570 | return 0; | 604 | return 0; |
571 | 605 | ||
572 | list_for_each_entry(pos, &evlist->entries, node) { | 606 | evlist__for_each(evlist, pos) { |
573 | if (pos->attr.type == evsel->attr.type && pos != evsel) | 607 | if (pos->attr.type == evsel->attr.type && pos != evsel) |
574 | return 0; | 608 | return 0; |
575 | } | 609 | } |
@@ -579,6 +613,163 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, | |||
579 | return perf_evsel__check_attr(evsel, scr->session); | 613 | return perf_evsel__check_attr(evsel, scr->session); |
580 | } | 614 | } |
581 | 615 | ||
616 | static int process_comm_event(struct perf_tool *tool, | ||
617 | union perf_event *event, | ||
618 | struct perf_sample *sample, | ||
619 | struct machine *machine) | ||
620 | { | ||
621 | struct thread *thread; | ||
622 | struct perf_script *script = container_of(tool, struct perf_script, tool); | ||
623 | struct perf_session *session = script->session; | ||
624 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | ||
625 | int ret = -1; | ||
626 | |||
627 | thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid); | ||
628 | if (thread == NULL) { | ||
629 | pr_debug("problem processing COMM event, skipping it.\n"); | ||
630 | return -1; | ||
631 | } | ||
632 | |||
633 | if (perf_event__process_comm(tool, event, sample, machine) < 0) | ||
634 | goto out; | ||
635 | |||
636 | if (!evsel->attr.sample_id_all) { | ||
637 | sample->cpu = 0; | ||
638 | sample->time = 0; | ||
639 | sample->tid = event->comm.tid; | ||
640 | sample->pid = event->comm.pid; | ||
641 | } | ||
642 | print_sample_start(sample, thread, evsel); | ||
643 | perf_event__fprintf(event, stdout); | ||
644 | ret = 0; | ||
645 | |||
646 | out: | ||
647 | return ret; | ||
648 | } | ||
649 | |||
650 | static int process_fork_event(struct perf_tool *tool, | ||
651 | union perf_event *event, | ||
652 | struct perf_sample *sample, | ||
653 | struct machine *machine) | ||
654 | { | ||
655 | struct thread *thread; | ||
656 | struct perf_script *script = container_of(tool, struct perf_script, tool); | ||
657 | struct perf_session *session = script->session; | ||
658 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | ||
659 | |||
660 | if (perf_event__process_fork(tool, event, sample, machine) < 0) | ||
661 | return -1; | ||
662 | |||
663 | thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); | ||
664 | if (thread == NULL) { | ||
665 | pr_debug("problem processing FORK event, skipping it.\n"); | ||
666 | return -1; | ||
667 | } | ||
668 | |||
669 | if (!evsel->attr.sample_id_all) { | ||
670 | sample->cpu = 0; | ||
671 | sample->time = event->fork.time; | ||
672 | sample->tid = event->fork.tid; | ||
673 | sample->pid = event->fork.pid; | ||
674 | } | ||
675 | print_sample_start(sample, thread, evsel); | ||
676 | perf_event__fprintf(event, stdout); | ||
677 | |||
678 | return 0; | ||
679 | } | ||
680 | static int process_exit_event(struct perf_tool *tool, | ||
681 | union perf_event *event, | ||
682 | struct perf_sample *sample, | ||
683 | struct machine *machine) | ||
684 | { | ||
685 | struct thread *thread; | ||
686 | struct perf_script *script = container_of(tool, struct perf_script, tool); | ||
687 | struct perf_session *session = script->session; | ||
688 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | ||
689 | |||
690 | thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); | ||
691 | if (thread == NULL) { | ||
692 | pr_debug("problem processing EXIT event, skipping it.\n"); | ||
693 | return -1; | ||
694 | } | ||
695 | |||
696 | if (!evsel->attr.sample_id_all) { | ||
697 | sample->cpu = 0; | ||
698 | sample->time = 0; | ||
699 | sample->tid = event->comm.tid; | ||
700 | sample->pid = event->comm.pid; | ||
701 | } | ||
702 | print_sample_start(sample, thread, evsel); | ||
703 | perf_event__fprintf(event, stdout); | ||
704 | |||
705 | if (perf_event__process_exit(tool, event, sample, machine) < 0) | ||
706 | return -1; | ||
707 | |||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int process_mmap_event(struct perf_tool *tool, | ||
712 | union perf_event *event, | ||
713 | struct perf_sample *sample, | ||
714 | struct machine *machine) | ||
715 | { | ||
716 | struct thread *thread; | ||
717 | struct perf_script *script = container_of(tool, struct perf_script, tool); | ||
718 | struct perf_session *session = script->session; | ||
719 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | ||
720 | |||
721 | if (perf_event__process_mmap(tool, event, sample, machine) < 0) | ||
722 | return -1; | ||
723 | |||
724 | thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid); | ||
725 | if (thread == NULL) { | ||
726 | pr_debug("problem processing MMAP event, skipping it.\n"); | ||
727 | return -1; | ||
728 | } | ||
729 | |||
730 | if (!evsel->attr.sample_id_all) { | ||
731 | sample->cpu = 0; | ||
732 | sample->time = 0; | ||
733 | sample->tid = event->mmap.tid; | ||
734 | sample->pid = event->mmap.pid; | ||
735 | } | ||
736 | print_sample_start(sample, thread, evsel); | ||
737 | perf_event__fprintf(event, stdout); | ||
738 | |||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | static int process_mmap2_event(struct perf_tool *tool, | ||
743 | union perf_event *event, | ||
744 | struct perf_sample *sample, | ||
745 | struct machine *machine) | ||
746 | { | ||
747 | struct thread *thread; | ||
748 | struct perf_script *script = container_of(tool, struct perf_script, tool); | ||
749 | struct perf_session *session = script->session; | ||
750 | struct perf_evsel *evsel = perf_evlist__first(session->evlist); | ||
751 | |||
752 | if (perf_event__process_mmap2(tool, event, sample, machine) < 0) | ||
753 | return -1; | ||
754 | |||
755 | thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid); | ||
756 | if (thread == NULL) { | ||
757 | pr_debug("problem processing MMAP2 event, skipping it.\n"); | ||
758 | return -1; | ||
759 | } | ||
760 | |||
761 | if (!evsel->attr.sample_id_all) { | ||
762 | sample->cpu = 0; | ||
763 | sample->time = 0; | ||
764 | sample->tid = event->mmap2.tid; | ||
765 | sample->pid = event->mmap2.pid; | ||
766 | } | ||
767 | print_sample_start(sample, thread, evsel); | ||
768 | perf_event__fprintf(event, stdout); | ||
769 | |||
770 | return 0; | ||
771 | } | ||
772 | |||
582 | static void sig_handler(int sig __maybe_unused) | 773 | static void sig_handler(int sig __maybe_unused) |
583 | { | 774 | { |
584 | session_done = 1; | 775 | session_done = 1; |
@@ -590,6 +781,17 @@ static int __cmd_script(struct perf_script *script) | |||
590 | 781 | ||
591 | signal(SIGINT, sig_handler); | 782 | signal(SIGINT, sig_handler); |
592 | 783 | ||
784 | /* override event processing functions */ | ||
785 | if (script->show_task_events) { | ||
786 | script->tool.comm = process_comm_event; | ||
787 | script->tool.fork = process_fork_event; | ||
788 | script->tool.exit = process_exit_event; | ||
789 | } | ||
790 | if (script->show_mmap_events) { | ||
791 | script->tool.mmap = process_mmap_event; | ||
792 | script->tool.mmap2 = process_mmap2_event; | ||
793 | } | ||
794 | |||
593 | ret = perf_session__process_events(script->session, &script->tool); | 795 | ret = perf_session__process_events(script->session, &script->tool); |
594 | 796 | ||
595 | if (debug_mode) | 797 | if (debug_mode) |
@@ -900,9 +1102,9 @@ static struct script_desc *script_desc__new(const char *name) | |||
900 | 1102 | ||
901 | static void script_desc__delete(struct script_desc *s) | 1103 | static void script_desc__delete(struct script_desc *s) |
902 | { | 1104 | { |
903 | free(s->name); | 1105 | zfree(&s->name); |
904 | free(s->half_liner); | 1106 | zfree(&s->half_liner); |
905 | free(s->args); | 1107 | zfree(&s->args); |
906 | free(s); | 1108 | free(s); |
907 | } | 1109 | } |
908 | 1110 | ||
@@ -1107,8 +1309,7 @@ static int check_ev_match(char *dir_name, char *scriptname, | |||
1107 | snprintf(evname, len + 1, "%s", p); | 1309 | snprintf(evname, len + 1, "%s", p); |
1108 | 1310 | ||
1109 | match = 0; | 1311 | match = 0; |
1110 | list_for_each_entry(pos, | 1312 | evlist__for_each(session->evlist, pos) { |
1111 | &session->evlist->entries, node) { | ||
1112 | if (!strcmp(perf_evsel__name(pos), evname)) { | 1313 | if (!strcmp(perf_evsel__name(pos), evname)) { |
1113 | match = 1; | 1314 | match = 1; |
1114 | break; | 1315 | break; |
@@ -1290,6 +1491,8 @@ static int have_cmd(int argc, const char **argv) | |||
1290 | int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | 1491 | int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) |
1291 | { | 1492 | { |
1292 | bool show_full_info = false; | 1493 | bool show_full_info = false; |
1494 | bool header = false; | ||
1495 | bool header_only = false; | ||
1293 | char *rec_script_path = NULL; | 1496 | char *rec_script_path = NULL; |
1294 | char *rep_script_path = NULL; | 1497 | char *rep_script_path = NULL; |
1295 | struct perf_session *session; | 1498 | struct perf_session *session; |
@@ -1328,6 +1531,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1328 | OPT_STRING('i', "input", &input_name, "file", "input file name"), | 1531 | OPT_STRING('i', "input", &input_name, "file", "input file name"), |
1329 | OPT_BOOLEAN('d', "debug-mode", &debug_mode, | 1532 | OPT_BOOLEAN('d', "debug-mode", &debug_mode, |
1330 | "do various checks like samples ordering and lost events"), | 1533 | "do various checks like samples ordering and lost events"), |
1534 | OPT_BOOLEAN(0, "header", &header, "Show data header."), | ||
1535 | OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."), | ||
1331 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | 1536 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, |
1332 | "file", "vmlinux pathname"), | 1537 | "file", "vmlinux pathname"), |
1333 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, | 1538 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, |
@@ -1352,6 +1557,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1352 | "display extended information from perf.data file"), | 1557 | "display extended information from perf.data file"), |
1353 | OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, | 1558 | OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, |
1354 | "Show the path of [kernel.kallsyms]"), | 1559 | "Show the path of [kernel.kallsyms]"), |
1560 | OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events, | ||
1561 | "Show the fork/comm/exit events"), | ||
1562 | OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events, | ||
1563 | "Show the mmap events"), | ||
1355 | OPT_END() | 1564 | OPT_END() |
1356 | }; | 1565 | }; |
1357 | const char * const script_usage[] = { | 1566 | const char * const script_usage[] = { |
@@ -1540,6 +1749,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1540 | if (session == NULL) | 1749 | if (session == NULL) |
1541 | return -ENOMEM; | 1750 | return -ENOMEM; |
1542 | 1751 | ||
1752 | if (header || header_only) { | ||
1753 | perf_session__fprintf_info(session, stdout, show_full_info); | ||
1754 | if (header_only) | ||
1755 | return 0; | ||
1756 | } | ||
1757 | |||
1543 | script.session = session; | 1758 | script.session = session; |
1544 | 1759 | ||
1545 | if (cpu_list) { | 1760 | if (cpu_list) { |
@@ -1547,9 +1762,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1547 | return -1; | 1762 | return -1; |
1548 | } | 1763 | } |
1549 | 1764 | ||
1550 | if (!script_name && !generate_script_lang) | ||
1551 | perf_session__fprintf_info(session, stdout, show_full_info); | ||
1552 | |||
1553 | if (!no_callchain) | 1765 | if (!no_callchain) |
1554 | symbol_conf.use_callchain = true; | 1766 | symbol_conf.use_callchain = true; |
1555 | else | 1767 | else |
@@ -1588,7 +1800,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1588 | return -1; | 1800 | return -1; |
1589 | } | 1801 | } |
1590 | 1802 | ||
1591 | err = scripting_ops->generate_script(session->pevent, | 1803 | err = scripting_ops->generate_script(session->tevent.pevent, |
1592 | "perf-script"); | 1804 | "perf-script"); |
1593 | goto out; | 1805 | goto out; |
1594 | } | 1806 | } |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ee0d565f83e3..8b0e1c9234d9 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -138,6 +138,7 @@ static const char *post_cmd = NULL; | |||
138 | static bool sync_run = false; | 138 | static bool sync_run = false; |
139 | static unsigned int interval = 0; | 139 | static unsigned int interval = 0; |
140 | static unsigned int initial_delay = 0; | 140 | static unsigned int initial_delay = 0; |
141 | static unsigned int unit_width = 4; /* strlen("unit") */ | ||
141 | static bool forever = false; | 142 | static bool forever = false; |
142 | static struct timespec ref_time; | 143 | static struct timespec ref_time; |
143 | static struct cpu_map *aggr_map; | 144 | static struct cpu_map *aggr_map; |
@@ -184,8 +185,7 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) | |||
184 | 185 | ||
185 | static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) | 186 | static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) |
186 | { | 187 | { |
187 | free(evsel->priv); | 188 | zfree(&evsel->priv); |
188 | evsel->priv = NULL; | ||
189 | } | 189 | } |
190 | 190 | ||
191 | static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) | 191 | static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) |
@@ -207,15 +207,14 @@ static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) | |||
207 | 207 | ||
208 | static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) | 208 | static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) |
209 | { | 209 | { |
210 | free(evsel->prev_raw_counts); | 210 | zfree(&evsel->prev_raw_counts); |
211 | evsel->prev_raw_counts = NULL; | ||
212 | } | 211 | } |
213 | 212 | ||
214 | static void perf_evlist__free_stats(struct perf_evlist *evlist) | 213 | static void perf_evlist__free_stats(struct perf_evlist *evlist) |
215 | { | 214 | { |
216 | struct perf_evsel *evsel; | 215 | struct perf_evsel *evsel; |
217 | 216 | ||
218 | list_for_each_entry(evsel, &evlist->entries, node) { | 217 | evlist__for_each(evlist, evsel) { |
219 | perf_evsel__free_stat_priv(evsel); | 218 | perf_evsel__free_stat_priv(evsel); |
220 | perf_evsel__free_counts(evsel); | 219 | perf_evsel__free_counts(evsel); |
221 | perf_evsel__free_prev_raw_counts(evsel); | 220 | perf_evsel__free_prev_raw_counts(evsel); |
@@ -226,7 +225,7 @@ static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) | |||
226 | { | 225 | { |
227 | struct perf_evsel *evsel; | 226 | struct perf_evsel *evsel; |
228 | 227 | ||
229 | list_for_each_entry(evsel, &evlist->entries, node) { | 228 | evlist__for_each(evlist, evsel) { |
230 | if (perf_evsel__alloc_stat_priv(evsel) < 0 || | 229 | if (perf_evsel__alloc_stat_priv(evsel) < 0 || |
231 | perf_evsel__alloc_counts(evsel, perf_evsel__nr_cpus(evsel)) < 0 || | 230 | perf_evsel__alloc_counts(evsel, perf_evsel__nr_cpus(evsel)) < 0 || |
232 | (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel) < 0)) | 231 | (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel) < 0)) |
@@ -260,7 +259,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist) | |||
260 | { | 259 | { |
261 | struct perf_evsel *evsel; | 260 | struct perf_evsel *evsel; |
262 | 261 | ||
263 | list_for_each_entry(evsel, &evlist->entries, node) { | 262 | evlist__for_each(evlist, evsel) { |
264 | perf_evsel__reset_stat_priv(evsel); | 263 | perf_evsel__reset_stat_priv(evsel); |
265 | perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel)); | 264 | perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel)); |
266 | } | 265 | } |
@@ -327,13 +326,13 @@ static struct perf_evsel *nth_evsel(int n) | |||
327 | 326 | ||
328 | /* Assumes this only called when evsel_list does not change anymore. */ | 327 | /* Assumes this only called when evsel_list does not change anymore. */ |
329 | if (!array) { | 328 | if (!array) { |
330 | list_for_each_entry(ev, &evsel_list->entries, node) | 329 | evlist__for_each(evsel_list, ev) |
331 | array_len++; | 330 | array_len++; |
332 | array = malloc(array_len * sizeof(void *)); | 331 | array = malloc(array_len * sizeof(void *)); |
333 | if (!array) | 332 | if (!array) |
334 | exit(ENOMEM); | 333 | exit(ENOMEM); |
335 | j = 0; | 334 | j = 0; |
336 | list_for_each_entry(ev, &evsel_list->entries, node) | 335 | evlist__for_each(evsel_list, ev) |
337 | array[j++] = ev; | 336 | array[j++] = ev; |
338 | } | 337 | } |
339 | if (n < array_len) | 338 | if (n < array_len) |
@@ -441,13 +440,13 @@ static void print_interval(void) | |||
441 | char prefix[64]; | 440 | char prefix[64]; |
442 | 441 | ||
443 | if (aggr_mode == AGGR_GLOBAL) { | 442 | if (aggr_mode == AGGR_GLOBAL) { |
444 | list_for_each_entry(counter, &evsel_list->entries, node) { | 443 | evlist__for_each(evsel_list, counter) { |
445 | ps = counter->priv; | 444 | ps = counter->priv; |
446 | memset(ps->res_stats, 0, sizeof(ps->res_stats)); | 445 | memset(ps->res_stats, 0, sizeof(ps->res_stats)); |
447 | read_counter_aggr(counter); | 446 | read_counter_aggr(counter); |
448 | } | 447 | } |
449 | } else { | 448 | } else { |
450 | list_for_each_entry(counter, &evsel_list->entries, node) { | 449 | evlist__for_each(evsel_list, counter) { |
451 | ps = counter->priv; | 450 | ps = counter->priv; |
452 | memset(ps->res_stats, 0, sizeof(ps->res_stats)); | 451 | memset(ps->res_stats, 0, sizeof(ps->res_stats)); |
453 | read_counter(counter); | 452 | read_counter(counter); |
@@ -461,17 +460,17 @@ static void print_interval(void) | |||
461 | if (num_print_interval == 0 && !csv_output) { | 460 | if (num_print_interval == 0 && !csv_output) { |
462 | switch (aggr_mode) { | 461 | switch (aggr_mode) { |
463 | case AGGR_SOCKET: | 462 | case AGGR_SOCKET: |
464 | fprintf(output, "# time socket cpus counts events\n"); | 463 | fprintf(output, "# time socket cpus counts %*s events\n", unit_width, "unit"); |
465 | break; | 464 | break; |
466 | case AGGR_CORE: | 465 | case AGGR_CORE: |
467 | fprintf(output, "# time core cpus counts events\n"); | 466 | fprintf(output, "# time core cpus counts %*s events\n", unit_width, "unit"); |
468 | break; | 467 | break; |
469 | case AGGR_NONE: | 468 | case AGGR_NONE: |
470 | fprintf(output, "# time CPU counts events\n"); | 469 | fprintf(output, "# time CPU counts %*s events\n", unit_width, "unit"); |
471 | break; | 470 | break; |
472 | case AGGR_GLOBAL: | 471 | case AGGR_GLOBAL: |
473 | default: | 472 | default: |
474 | fprintf(output, "# time counts events\n"); | 473 | fprintf(output, "# time counts %*s events\n", unit_width, "unit"); |
475 | } | 474 | } |
476 | } | 475 | } |
477 | 476 | ||
@@ -484,12 +483,12 @@ static void print_interval(void) | |||
484 | print_aggr(prefix); | 483 | print_aggr(prefix); |
485 | break; | 484 | break; |
486 | case AGGR_NONE: | 485 | case AGGR_NONE: |
487 | list_for_each_entry(counter, &evsel_list->entries, node) | 486 | evlist__for_each(evsel_list, counter) |
488 | print_counter(counter, prefix); | 487 | print_counter(counter, prefix); |
489 | break; | 488 | break; |
490 | case AGGR_GLOBAL: | 489 | case AGGR_GLOBAL: |
491 | default: | 490 | default: |
492 | list_for_each_entry(counter, &evsel_list->entries, node) | 491 | evlist__for_each(evsel_list, counter) |
493 | print_counter_aggr(counter, prefix); | 492 | print_counter_aggr(counter, prefix); |
494 | } | 493 | } |
495 | 494 | ||
@@ -505,17 +504,31 @@ static void handle_initial_delay(void) | |||
505 | nthreads = thread_map__nr(evsel_list->threads); | 504 | nthreads = thread_map__nr(evsel_list->threads); |
506 | 505 | ||
507 | usleep(initial_delay * 1000); | 506 | usleep(initial_delay * 1000); |
508 | list_for_each_entry(counter, &evsel_list->entries, node) | 507 | evlist__for_each(evsel_list, counter) |
509 | perf_evsel__enable(counter, ncpus, nthreads); | 508 | perf_evsel__enable(counter, ncpus, nthreads); |
510 | } | 509 | } |
511 | } | 510 | } |
512 | 511 | ||
512 | static volatile int workload_exec_errno; | ||
513 | |||
514 | /* | ||
515 | * perf_evlist__prepare_workload will send a SIGUSR1 | ||
516 | * if the fork fails, since we asked by setting its | ||
517 | * want_signal to true. | ||
518 | */ | ||
519 | static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info, | ||
520 | void *ucontext __maybe_unused) | ||
521 | { | ||
522 | workload_exec_errno = info->si_value.sival_int; | ||
523 | } | ||
524 | |||
513 | static int __run_perf_stat(int argc, const char **argv) | 525 | static int __run_perf_stat(int argc, const char **argv) |
514 | { | 526 | { |
515 | char msg[512]; | 527 | char msg[512]; |
516 | unsigned long long t0, t1; | 528 | unsigned long long t0, t1; |
517 | struct perf_evsel *counter; | 529 | struct perf_evsel *counter; |
518 | struct timespec ts; | 530 | struct timespec ts; |
531 | size_t l; | ||
519 | int status = 0; | 532 | int status = 0; |
520 | const bool forks = (argc > 0); | 533 | const bool forks = (argc > 0); |
521 | 534 | ||
@@ -528,8 +541,8 @@ static int __run_perf_stat(int argc, const char **argv) | |||
528 | } | 541 | } |
529 | 542 | ||
530 | if (forks) { | 543 | if (forks) { |
531 | if (perf_evlist__prepare_workload(evsel_list, &target, argv, | 544 | if (perf_evlist__prepare_workload(evsel_list, &target, argv, false, |
532 | false, false) < 0) { | 545 | workload_exec_failed_signal) < 0) { |
533 | perror("failed to prepare workload"); | 546 | perror("failed to prepare workload"); |
534 | return -1; | 547 | return -1; |
535 | } | 548 | } |
@@ -539,7 +552,7 @@ static int __run_perf_stat(int argc, const char **argv) | |||
539 | if (group) | 552 | if (group) |
540 | perf_evlist__set_leader(evsel_list); | 553 | perf_evlist__set_leader(evsel_list); |
541 | 554 | ||
542 | list_for_each_entry(counter, &evsel_list->entries, node) { | 555 | evlist__for_each(evsel_list, counter) { |
543 | if (create_perf_stat_counter(counter) < 0) { | 556 | if (create_perf_stat_counter(counter) < 0) { |
544 | /* | 557 | /* |
545 | * PPC returns ENXIO for HW counters until 2.6.37 | 558 | * PPC returns ENXIO for HW counters until 2.6.37 |
@@ -565,6 +578,10 @@ static int __run_perf_stat(int argc, const char **argv) | |||
565 | return -1; | 578 | return -1; |
566 | } | 579 | } |
567 | counter->supported = true; | 580 | counter->supported = true; |
581 | |||
582 | l = strlen(counter->unit); | ||
583 | if (l > unit_width) | ||
584 | unit_width = l; | ||
568 | } | 585 | } |
569 | 586 | ||
570 | if (perf_evlist__apply_filters(evsel_list)) { | 587 | if (perf_evlist__apply_filters(evsel_list)) { |
@@ -590,6 +607,13 @@ static int __run_perf_stat(int argc, const char **argv) | |||
590 | } | 607 | } |
591 | } | 608 | } |
592 | wait(&status); | 609 | wait(&status); |
610 | |||
611 | if (workload_exec_errno) { | ||
612 | const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); | ||
613 | pr_err("Workload failed: %s\n", emsg); | ||
614 | return -1; | ||
615 | } | ||
616 | |||
593 | if (WIFSIGNALED(status)) | 617 | if (WIFSIGNALED(status)) |
594 | psignal(WTERMSIG(status), argv[0]); | 618 | psignal(WTERMSIG(status), argv[0]); |
595 | } else { | 619 | } else { |
@@ -606,13 +630,13 @@ static int __run_perf_stat(int argc, const char **argv) | |||
606 | update_stats(&walltime_nsecs_stats, t1 - t0); | 630 | update_stats(&walltime_nsecs_stats, t1 - t0); |
607 | 631 | ||
608 | if (aggr_mode == AGGR_GLOBAL) { | 632 | if (aggr_mode == AGGR_GLOBAL) { |
609 | list_for_each_entry(counter, &evsel_list->entries, node) { | 633 | evlist__for_each(evsel_list, counter) { |
610 | read_counter_aggr(counter); | 634 | read_counter_aggr(counter); |
611 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), | 635 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), |
612 | thread_map__nr(evsel_list->threads)); | 636 | thread_map__nr(evsel_list->threads)); |
613 | } | 637 | } |
614 | } else { | 638 | } else { |
615 | list_for_each_entry(counter, &evsel_list->entries, node) { | 639 | evlist__for_each(evsel_list, counter) { |
616 | read_counter(counter); | 640 | read_counter(counter); |
617 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); | 641 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); |
618 | } | 642 | } |
@@ -621,7 +645,7 @@ static int __run_perf_stat(int argc, const char **argv) | |||
621 | return WEXITSTATUS(status); | 645 | return WEXITSTATUS(status); |
622 | } | 646 | } |
623 | 647 | ||
624 | static int run_perf_stat(int argc __maybe_unused, const char **argv) | 648 | static int run_perf_stat(int argc, const char **argv) |
625 | { | 649 | { |
626 | int ret; | 650 | int ret; |
627 | 651 | ||
@@ -704,14 +728,25 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) | |||
704 | static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) | 728 | static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) |
705 | { | 729 | { |
706 | double msecs = avg / 1e6; | 730 | double msecs = avg / 1e6; |
707 | const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s"; | 731 | const char *fmt_v, *fmt_n; |
708 | char name[25]; | 732 | char name[25]; |
709 | 733 | ||
734 | fmt_v = csv_output ? "%.6f%s" : "%18.6f%s"; | ||
735 | fmt_n = csv_output ? "%s" : "%-25s"; | ||
736 | |||
710 | aggr_printout(evsel, cpu, nr); | 737 | aggr_printout(evsel, cpu, nr); |
711 | 738 | ||
712 | scnprintf(name, sizeof(name), "%s%s", | 739 | scnprintf(name, sizeof(name), "%s%s", |
713 | perf_evsel__name(evsel), csv_output ? "" : " (msec)"); | 740 | perf_evsel__name(evsel), csv_output ? "" : " (msec)"); |
714 | fprintf(output, fmt, msecs, csv_sep, name); | 741 | |
742 | fprintf(output, fmt_v, msecs, csv_sep); | ||
743 | |||
744 | if (csv_output) | ||
745 | fprintf(output, "%s%s", evsel->unit, csv_sep); | ||
746 | else | ||
747 | fprintf(output, "%-*s%s", unit_width, evsel->unit, csv_sep); | ||
748 | |||
749 | fprintf(output, fmt_n, name); | ||
715 | 750 | ||
716 | if (evsel->cgrp) | 751 | if (evsel->cgrp) |
717 | fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); | 752 | fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); |
@@ -908,21 +943,31 @@ static void print_ll_cache_misses(int cpu, | |||
908 | static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) | 943 | static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) |
909 | { | 944 | { |
910 | double total, ratio = 0.0, total2; | 945 | double total, ratio = 0.0, total2; |
946 | double sc = evsel->scale; | ||
911 | const char *fmt; | 947 | const char *fmt; |
912 | 948 | ||
913 | if (csv_output) | 949 | if (csv_output) { |
914 | fmt = "%.0f%s%s"; | 950 | fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; |
915 | else if (big_num) | 951 | } else { |
916 | fmt = "%'18.0f%s%-25s"; | 952 | if (big_num) |
917 | else | 953 | fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s"; |
918 | fmt = "%18.0f%s%-25s"; | 954 | else |
955 | fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s"; | ||
956 | } | ||
919 | 957 | ||
920 | aggr_printout(evsel, cpu, nr); | 958 | aggr_printout(evsel, cpu, nr); |
921 | 959 | ||
922 | if (aggr_mode == AGGR_GLOBAL) | 960 | if (aggr_mode == AGGR_GLOBAL) |
923 | cpu = 0; | 961 | cpu = 0; |
924 | 962 | ||
925 | fprintf(output, fmt, avg, csv_sep, perf_evsel__name(evsel)); | 963 | fprintf(output, fmt, avg, csv_sep); |
964 | |||
965 | if (evsel->unit) | ||
966 | fprintf(output, "%-*s%s", | ||
967 | csv_output ? 0 : unit_width, | ||
968 | evsel->unit, csv_sep); | ||
969 | |||
970 | fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel)); | ||
926 | 971 | ||
927 | if (evsel->cgrp) | 972 | if (evsel->cgrp) |
928 | fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); | 973 | fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); |
@@ -941,7 +986,10 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) | |||
941 | 986 | ||
942 | if (total && avg) { | 987 | if (total && avg) { |
943 | ratio = total / avg; | 988 | ratio = total / avg; |
944 | fprintf(output, "\n # %5.2f stalled cycles per insn", ratio); | 989 | fprintf(output, "\n"); |
990 | if (aggr_mode == AGGR_NONE) | ||
991 | fprintf(output, " "); | ||
992 | fprintf(output, " # %5.2f stalled cycles per insn", ratio); | ||
945 | } | 993 | } |
946 | 994 | ||
947 | } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && | 995 | } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && |
@@ -1061,6 +1109,7 @@ static void print_aggr(char *prefix) | |||
1061 | { | 1109 | { |
1062 | struct perf_evsel *counter; | 1110 | struct perf_evsel *counter; |
1063 | int cpu, cpu2, s, s2, id, nr; | 1111 | int cpu, cpu2, s, s2, id, nr; |
1112 | double uval; | ||
1064 | u64 ena, run, val; | 1113 | u64 ena, run, val; |
1065 | 1114 | ||
1066 | if (!(aggr_map || aggr_get_id)) | 1115 | if (!(aggr_map || aggr_get_id)) |
@@ -1068,7 +1117,7 @@ static void print_aggr(char *prefix) | |||
1068 | 1117 | ||
1069 | for (s = 0; s < aggr_map->nr; s++) { | 1118 | for (s = 0; s < aggr_map->nr; s++) { |
1070 | id = aggr_map->map[s]; | 1119 | id = aggr_map->map[s]; |
1071 | list_for_each_entry(counter, &evsel_list->entries, node) { | 1120 | evlist__for_each(evsel_list, counter) { |
1072 | val = ena = run = 0; | 1121 | val = ena = run = 0; |
1073 | nr = 0; | 1122 | nr = 0; |
1074 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { | 1123 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { |
@@ -1087,11 +1136,17 @@ static void print_aggr(char *prefix) | |||
1087 | if (run == 0 || ena == 0) { | 1136 | if (run == 0 || ena == 0) { |
1088 | aggr_printout(counter, id, nr); | 1137 | aggr_printout(counter, id, nr); |
1089 | 1138 | ||
1090 | fprintf(output, "%*s%s%*s", | 1139 | fprintf(output, "%*s%s", |
1091 | csv_output ? 0 : 18, | 1140 | csv_output ? 0 : 18, |
1092 | counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, | 1141 | counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, |
1093 | csv_sep, | 1142 | csv_sep); |
1094 | csv_output ? 0 : -24, | 1143 | |
1144 | fprintf(output, "%-*s%s", | ||
1145 | csv_output ? 0 : unit_width, | ||
1146 | counter->unit, csv_sep); | ||
1147 | |||
1148 | fprintf(output, "%*s", | ||
1149 | csv_output ? 0 : -25, | ||
1095 | perf_evsel__name(counter)); | 1150 | perf_evsel__name(counter)); |
1096 | 1151 | ||
1097 | if (counter->cgrp) | 1152 | if (counter->cgrp) |
@@ -1101,11 +1156,12 @@ static void print_aggr(char *prefix) | |||
1101 | fputc('\n', output); | 1156 | fputc('\n', output); |
1102 | continue; | 1157 | continue; |
1103 | } | 1158 | } |
1159 | uval = val * counter->scale; | ||
1104 | 1160 | ||
1105 | if (nsec_counter(counter)) | 1161 | if (nsec_counter(counter)) |
1106 | nsec_printout(id, nr, counter, val); | 1162 | nsec_printout(id, nr, counter, uval); |
1107 | else | 1163 | else |
1108 | abs_printout(id, nr, counter, val); | 1164 | abs_printout(id, nr, counter, uval); |
1109 | 1165 | ||
1110 | if (!csv_output) { | 1166 | if (!csv_output) { |
1111 | print_noise(counter, 1.0); | 1167 | print_noise(counter, 1.0); |
@@ -1128,16 +1184,21 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix) | |||
1128 | struct perf_stat *ps = counter->priv; | 1184 | struct perf_stat *ps = counter->priv; |
1129 | double avg = avg_stats(&ps->res_stats[0]); | 1185 | double avg = avg_stats(&ps->res_stats[0]); |
1130 | int scaled = counter->counts->scaled; | 1186 | int scaled = counter->counts->scaled; |
1187 | double uval; | ||
1131 | 1188 | ||
1132 | if (prefix) | 1189 | if (prefix) |
1133 | fprintf(output, "%s", prefix); | 1190 | fprintf(output, "%s", prefix); |
1134 | 1191 | ||
1135 | if (scaled == -1) { | 1192 | if (scaled == -1) { |
1136 | fprintf(output, "%*s%s%*s", | 1193 | fprintf(output, "%*s%s", |
1137 | csv_output ? 0 : 18, | 1194 | csv_output ? 0 : 18, |
1138 | counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, | 1195 | counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, |
1139 | csv_sep, | 1196 | csv_sep); |
1140 | csv_output ? 0 : -24, | 1197 | fprintf(output, "%-*s%s", |
1198 | csv_output ? 0 : unit_width, | ||
1199 | counter->unit, csv_sep); | ||
1200 | fprintf(output, "%*s", | ||
1201 | csv_output ? 0 : -25, | ||
1141 | perf_evsel__name(counter)); | 1202 | perf_evsel__name(counter)); |
1142 | 1203 | ||
1143 | if (counter->cgrp) | 1204 | if (counter->cgrp) |
@@ -1147,10 +1208,12 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix) | |||
1147 | return; | 1208 | return; |
1148 | } | 1209 | } |
1149 | 1210 | ||
1211 | uval = avg * counter->scale; | ||
1212 | |||
1150 | if (nsec_counter(counter)) | 1213 | if (nsec_counter(counter)) |
1151 | nsec_printout(-1, 0, counter, avg); | 1214 | nsec_printout(-1, 0, counter, uval); |
1152 | else | 1215 | else |
1153 | abs_printout(-1, 0, counter, avg); | 1216 | abs_printout(-1, 0, counter, uval); |
1154 | 1217 | ||
1155 | print_noise(counter, avg); | 1218 | print_noise(counter, avg); |
1156 | 1219 | ||
@@ -1177,6 +1240,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix) | |||
1177 | static void print_counter(struct perf_evsel *counter, char *prefix) | 1240 | static void print_counter(struct perf_evsel *counter, char *prefix) |
1178 | { | 1241 | { |
1179 | u64 ena, run, val; | 1242 | u64 ena, run, val; |
1243 | double uval; | ||
1180 | int cpu; | 1244 | int cpu; |
1181 | 1245 | ||
1182 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { | 1246 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { |
@@ -1188,14 +1252,20 @@ static void print_counter(struct perf_evsel *counter, char *prefix) | |||
1188 | fprintf(output, "%s", prefix); | 1252 | fprintf(output, "%s", prefix); |
1189 | 1253 | ||
1190 | if (run == 0 || ena == 0) { | 1254 | if (run == 0 || ena == 0) { |
1191 | fprintf(output, "CPU%*d%s%*s%s%*s", | 1255 | fprintf(output, "CPU%*d%s%*s%s", |
1192 | csv_output ? 0 : -4, | 1256 | csv_output ? 0 : -4, |
1193 | perf_evsel__cpus(counter)->map[cpu], csv_sep, | 1257 | perf_evsel__cpus(counter)->map[cpu], csv_sep, |
1194 | csv_output ? 0 : 18, | 1258 | csv_output ? 0 : 18, |
1195 | counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, | 1259 | counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, |
1196 | csv_sep, | 1260 | csv_sep); |
1197 | csv_output ? 0 : -24, | 1261 | |
1198 | perf_evsel__name(counter)); | 1262 | fprintf(output, "%-*s%s", |
1263 | csv_output ? 0 : unit_width, | ||
1264 | counter->unit, csv_sep); | ||
1265 | |||
1266 | fprintf(output, "%*s", | ||
1267 | csv_output ? 0 : -25, | ||
1268 | perf_evsel__name(counter)); | ||
1199 | 1269 | ||
1200 | if (counter->cgrp) | 1270 | if (counter->cgrp) |
1201 | fprintf(output, "%s%s", | 1271 | fprintf(output, "%s%s", |
@@ -1205,10 +1275,12 @@ static void print_counter(struct perf_evsel *counter, char *prefix) | |||
1205 | continue; | 1275 | continue; |
1206 | } | 1276 | } |
1207 | 1277 | ||
1278 | uval = val * counter->scale; | ||
1279 | |||
1208 | if (nsec_counter(counter)) | 1280 | if (nsec_counter(counter)) |
1209 | nsec_printout(cpu, 0, counter, val); | 1281 | nsec_printout(cpu, 0, counter, uval); |
1210 | else | 1282 | else |
1211 | abs_printout(cpu, 0, counter, val); | 1283 | abs_printout(cpu, 0, counter, uval); |
1212 | 1284 | ||
1213 | if (!csv_output) { | 1285 | if (!csv_output) { |
1214 | print_noise(counter, 1.0); | 1286 | print_noise(counter, 1.0); |
@@ -1256,11 +1328,11 @@ static void print_stat(int argc, const char **argv) | |||
1256 | print_aggr(NULL); | 1328 | print_aggr(NULL); |
1257 | break; | 1329 | break; |
1258 | case AGGR_GLOBAL: | 1330 | case AGGR_GLOBAL: |
1259 | list_for_each_entry(counter, &evsel_list->entries, node) | 1331 | evlist__for_each(evsel_list, counter) |
1260 | print_counter_aggr(counter, NULL); | 1332 | print_counter_aggr(counter, NULL); |
1261 | break; | 1333 | break; |
1262 | case AGGR_NONE: | 1334 | case AGGR_NONE: |
1263 | list_for_each_entry(counter, &evsel_list->entries, node) | 1335 | evlist__for_each(evsel_list, counter) |
1264 | print_counter(counter, NULL); | 1336 | print_counter(counter, NULL); |
1265 | break; | 1337 | break; |
1266 | default: | 1338 | default: |
@@ -1710,14 +1782,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1710 | if (interval && interval < 100) { | 1782 | if (interval && interval < 100) { |
1711 | pr_err("print interval must be >= 100ms\n"); | 1783 | pr_err("print interval must be >= 100ms\n"); |
1712 | parse_options_usage(stat_usage, options, "I", 1); | 1784 | parse_options_usage(stat_usage, options, "I", 1); |
1713 | goto out_free_maps; | 1785 | goto out; |
1714 | } | 1786 | } |
1715 | 1787 | ||
1716 | if (perf_evlist__alloc_stats(evsel_list, interval)) | 1788 | if (perf_evlist__alloc_stats(evsel_list, interval)) |
1717 | goto out_free_maps; | 1789 | goto out; |
1718 | 1790 | ||
1719 | if (perf_stat_init_aggr_mode()) | 1791 | if (perf_stat_init_aggr_mode()) |
1720 | goto out_free_maps; | 1792 | goto out; |
1721 | 1793 | ||
1722 | /* | 1794 | /* |
1723 | * We dont want to block the signals - that would cause | 1795 | * We dont want to block the signals - that would cause |
@@ -1749,8 +1821,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1749 | print_stat(argc, argv); | 1821 | print_stat(argc, argv); |
1750 | 1822 | ||
1751 | perf_evlist__free_stats(evsel_list); | 1823 | perf_evlist__free_stats(evsel_list); |
1752 | out_free_maps: | ||
1753 | perf_evlist__delete_maps(evsel_list); | ||
1754 | out: | 1824 | out: |
1755 | perf_evlist__delete(evsel_list); | 1825 | perf_evlist__delete(evsel_list); |
1756 | return status; | 1826 | return status; |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 41c9bde2fb67..652af0b66a62 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -41,25 +41,29 @@ | |||
41 | #define SUPPORT_OLD_POWER_EVENTS 1 | 41 | #define SUPPORT_OLD_POWER_EVENTS 1 |
42 | #define PWR_EVENT_EXIT -1 | 42 | #define PWR_EVENT_EXIT -1 |
43 | 43 | ||
44 | |||
45 | static unsigned int numcpus; | ||
46 | static u64 min_freq; /* Lowest CPU frequency seen */ | ||
47 | static u64 max_freq; /* Highest CPU frequency seen */ | ||
48 | static u64 turbo_frequency; | ||
49 | |||
50 | static u64 first_time, last_time; | ||
51 | |||
52 | static bool power_only; | ||
53 | |||
54 | |||
55 | struct per_pid; | 44 | struct per_pid; |
56 | struct per_pidcomm; | ||
57 | |||
58 | struct cpu_sample; | ||
59 | struct power_event; | 45 | struct power_event; |
60 | struct wake_event; | 46 | struct wake_event; |
61 | 47 | ||
62 | struct sample_wrapper; | 48 | struct timechart { |
49 | struct perf_tool tool; | ||
50 | struct per_pid *all_data; | ||
51 | struct power_event *power_events; | ||
52 | struct wake_event *wake_events; | ||
53 | int proc_num; | ||
54 | unsigned int numcpus; | ||
55 | u64 min_freq, /* Lowest CPU frequency seen */ | ||
56 | max_freq, /* Highest CPU frequency seen */ | ||
57 | turbo_frequency, | ||
58 | first_time, last_time; | ||
59 | bool power_only, | ||
60 | tasks_only, | ||
61 | with_backtrace, | ||
62 | topology; | ||
63 | }; | ||
64 | |||
65 | struct per_pidcomm; | ||
66 | struct cpu_sample; | ||
63 | 67 | ||
64 | /* | 68 | /* |
65 | * Datastructure layout: | 69 | * Datastructure layout: |
@@ -124,10 +128,9 @@ struct cpu_sample { | |||
124 | u64 end_time; | 128 | u64 end_time; |
125 | int type; | 129 | int type; |
126 | int cpu; | 130 | int cpu; |
131 | const char *backtrace; | ||
127 | }; | 132 | }; |
128 | 133 | ||
129 | static struct per_pid *all_data; | ||
130 | |||
131 | #define CSTATE 1 | 134 | #define CSTATE 1 |
132 | #define PSTATE 2 | 135 | #define PSTATE 2 |
133 | 136 | ||
@@ -145,12 +148,9 @@ struct wake_event { | |||
145 | int waker; | 148 | int waker; |
146 | int wakee; | 149 | int wakee; |
147 | u64 time; | 150 | u64 time; |
151 | const char *backtrace; | ||
148 | }; | 152 | }; |
149 | 153 | ||
150 | static struct power_event *power_events; | ||
151 | static struct wake_event *wake_events; | ||
152 | |||
153 | struct process_filter; | ||
154 | struct process_filter { | 154 | struct process_filter { |
155 | char *name; | 155 | char *name; |
156 | int pid; | 156 | int pid; |
@@ -160,9 +160,9 @@ struct process_filter { | |||
160 | static struct process_filter *process_filter; | 160 | static struct process_filter *process_filter; |
161 | 161 | ||
162 | 162 | ||
163 | static struct per_pid *find_create_pid(int pid) | 163 | static struct per_pid *find_create_pid(struct timechart *tchart, int pid) |
164 | { | 164 | { |
165 | struct per_pid *cursor = all_data; | 165 | struct per_pid *cursor = tchart->all_data; |
166 | 166 | ||
167 | while (cursor) { | 167 | while (cursor) { |
168 | if (cursor->pid == pid) | 168 | if (cursor->pid == pid) |
@@ -172,16 +172,16 @@ static struct per_pid *find_create_pid(int pid) | |||
172 | cursor = zalloc(sizeof(*cursor)); | 172 | cursor = zalloc(sizeof(*cursor)); |
173 | assert(cursor != NULL); | 173 | assert(cursor != NULL); |
174 | cursor->pid = pid; | 174 | cursor->pid = pid; |
175 | cursor->next = all_data; | 175 | cursor->next = tchart->all_data; |
176 | all_data = cursor; | 176 | tchart->all_data = cursor; |
177 | return cursor; | 177 | return cursor; |
178 | } | 178 | } |
179 | 179 | ||
180 | static void pid_set_comm(int pid, char *comm) | 180 | static void pid_set_comm(struct timechart *tchart, int pid, char *comm) |
181 | { | 181 | { |
182 | struct per_pid *p; | 182 | struct per_pid *p; |
183 | struct per_pidcomm *c; | 183 | struct per_pidcomm *c; |
184 | p = find_create_pid(pid); | 184 | p = find_create_pid(tchart, pid); |
185 | c = p->all; | 185 | c = p->all; |
186 | while (c) { | 186 | while (c) { |
187 | if (c->comm && strcmp(c->comm, comm) == 0) { | 187 | if (c->comm && strcmp(c->comm, comm) == 0) { |
@@ -203,14 +203,14 @@ static void pid_set_comm(int pid, char *comm) | |||
203 | p->all = c; | 203 | p->all = c; |
204 | } | 204 | } |
205 | 205 | ||
206 | static void pid_fork(int pid, int ppid, u64 timestamp) | 206 | static void pid_fork(struct timechart *tchart, int pid, int ppid, u64 timestamp) |
207 | { | 207 | { |
208 | struct per_pid *p, *pp; | 208 | struct per_pid *p, *pp; |
209 | p = find_create_pid(pid); | 209 | p = find_create_pid(tchart, pid); |
210 | pp = find_create_pid(ppid); | 210 | pp = find_create_pid(tchart, ppid); |
211 | p->ppid = ppid; | 211 | p->ppid = ppid; |
212 | if (pp->current && pp->current->comm && !p->current) | 212 | if (pp->current && pp->current->comm && !p->current) |
213 | pid_set_comm(pid, pp->current->comm); | 213 | pid_set_comm(tchart, pid, pp->current->comm); |
214 | 214 | ||
215 | p->start_time = timestamp; | 215 | p->start_time = timestamp; |
216 | if (p->current) { | 216 | if (p->current) { |
@@ -219,23 +219,24 @@ static void pid_fork(int pid, int ppid, u64 timestamp) | |||
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | static void pid_exit(int pid, u64 timestamp) | 222 | static void pid_exit(struct timechart *tchart, int pid, u64 timestamp) |
223 | { | 223 | { |
224 | struct per_pid *p; | 224 | struct per_pid *p; |
225 | p = find_create_pid(pid); | 225 | p = find_create_pid(tchart, pid); |
226 | p->end_time = timestamp; | 226 | p->end_time = timestamp; |
227 | if (p->current) | 227 | if (p->current) |
228 | p->current->end_time = timestamp; | 228 | p->current->end_time = timestamp; |
229 | } | 229 | } |
230 | 230 | ||
231 | static void | 231 | static void pid_put_sample(struct timechart *tchart, int pid, int type, |
232 | pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end) | 232 | unsigned int cpu, u64 start, u64 end, |
233 | const char *backtrace) | ||
233 | { | 234 | { |
234 | struct per_pid *p; | 235 | struct per_pid *p; |
235 | struct per_pidcomm *c; | 236 | struct per_pidcomm *c; |
236 | struct cpu_sample *sample; | 237 | struct cpu_sample *sample; |
237 | 238 | ||
238 | p = find_create_pid(pid); | 239 | p = find_create_pid(tchart, pid); |
239 | c = p->current; | 240 | c = p->current; |
240 | if (!c) { | 241 | if (!c) { |
241 | c = zalloc(sizeof(*c)); | 242 | c = zalloc(sizeof(*c)); |
@@ -252,6 +253,7 @@ pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end) | |||
252 | sample->type = type; | 253 | sample->type = type; |
253 | sample->next = c->samples; | 254 | sample->next = c->samples; |
254 | sample->cpu = cpu; | 255 | sample->cpu = cpu; |
256 | sample->backtrace = backtrace; | ||
255 | c->samples = sample; | 257 | c->samples = sample; |
256 | 258 | ||
257 | if (sample->type == TYPE_RUNNING && end > start && start > 0) { | 259 | if (sample->type == TYPE_RUNNING && end > start && start > 0) { |
@@ -272,84 +274,47 @@ static int cpus_cstate_state[MAX_CPUS]; | |||
272 | static u64 cpus_pstate_start_times[MAX_CPUS]; | 274 | static u64 cpus_pstate_start_times[MAX_CPUS]; |
273 | static u64 cpus_pstate_state[MAX_CPUS]; | 275 | static u64 cpus_pstate_state[MAX_CPUS]; |
274 | 276 | ||
275 | static int process_comm_event(struct perf_tool *tool __maybe_unused, | 277 | static int process_comm_event(struct perf_tool *tool, |
276 | union perf_event *event, | 278 | union perf_event *event, |
277 | struct perf_sample *sample __maybe_unused, | 279 | struct perf_sample *sample __maybe_unused, |
278 | struct machine *machine __maybe_unused) | 280 | struct machine *machine __maybe_unused) |
279 | { | 281 | { |
280 | pid_set_comm(event->comm.tid, event->comm.comm); | 282 | struct timechart *tchart = container_of(tool, struct timechart, tool); |
283 | pid_set_comm(tchart, event->comm.tid, event->comm.comm); | ||
281 | return 0; | 284 | return 0; |
282 | } | 285 | } |
283 | 286 | ||
284 | static int process_fork_event(struct perf_tool *tool __maybe_unused, | 287 | static int process_fork_event(struct perf_tool *tool, |
285 | union perf_event *event, | 288 | union perf_event *event, |
286 | struct perf_sample *sample __maybe_unused, | 289 | struct perf_sample *sample __maybe_unused, |
287 | struct machine *machine __maybe_unused) | 290 | struct machine *machine __maybe_unused) |
288 | { | 291 | { |
289 | pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); | 292 | struct timechart *tchart = container_of(tool, struct timechart, tool); |
293 | pid_fork(tchart, event->fork.pid, event->fork.ppid, event->fork.time); | ||
290 | return 0; | 294 | return 0; |
291 | } | 295 | } |
292 | 296 | ||
293 | static int process_exit_event(struct perf_tool *tool __maybe_unused, | 297 | static int process_exit_event(struct perf_tool *tool, |
294 | union perf_event *event, | 298 | union perf_event *event, |
295 | struct perf_sample *sample __maybe_unused, | 299 | struct perf_sample *sample __maybe_unused, |
296 | struct machine *machine __maybe_unused) | 300 | struct machine *machine __maybe_unused) |
297 | { | 301 | { |
298 | pid_exit(event->fork.pid, event->fork.time); | 302 | struct timechart *tchart = container_of(tool, struct timechart, tool); |
303 | pid_exit(tchart, event->fork.pid, event->fork.time); | ||
299 | return 0; | 304 | return 0; |
300 | } | 305 | } |
301 | 306 | ||
302 | struct trace_entry { | ||
303 | unsigned short type; | ||
304 | unsigned char flags; | ||
305 | unsigned char preempt_count; | ||
306 | int pid; | ||
307 | int lock_depth; | ||
308 | }; | ||
309 | |||
310 | #ifdef SUPPORT_OLD_POWER_EVENTS | 307 | #ifdef SUPPORT_OLD_POWER_EVENTS |
311 | static int use_old_power_events; | 308 | static int use_old_power_events; |
312 | struct power_entry_old { | ||
313 | struct trace_entry te; | ||
314 | u64 type; | ||
315 | u64 value; | ||
316 | u64 cpu_id; | ||
317 | }; | ||
318 | #endif | 309 | #endif |
319 | 310 | ||
320 | struct power_processor_entry { | ||
321 | struct trace_entry te; | ||
322 | u32 state; | ||
323 | u32 cpu_id; | ||
324 | }; | ||
325 | |||
326 | #define TASK_COMM_LEN 16 | ||
327 | struct wakeup_entry { | ||
328 | struct trace_entry te; | ||
329 | char comm[TASK_COMM_LEN]; | ||
330 | int pid; | ||
331 | int prio; | ||
332 | int success; | ||
333 | }; | ||
334 | |||
335 | struct sched_switch { | ||
336 | struct trace_entry te; | ||
337 | char prev_comm[TASK_COMM_LEN]; | ||
338 | int prev_pid; | ||
339 | int prev_prio; | ||
340 | long prev_state; /* Arjan weeps. */ | ||
341 | char next_comm[TASK_COMM_LEN]; | ||
342 | int next_pid; | ||
343 | int next_prio; | ||
344 | }; | ||
345 | |||
346 | static void c_state_start(int cpu, u64 timestamp, int state) | 311 | static void c_state_start(int cpu, u64 timestamp, int state) |
347 | { | 312 | { |
348 | cpus_cstate_start_times[cpu] = timestamp; | 313 | cpus_cstate_start_times[cpu] = timestamp; |
349 | cpus_cstate_state[cpu] = state; | 314 | cpus_cstate_state[cpu] = state; |
350 | } | 315 | } |
351 | 316 | ||
352 | static void c_state_end(int cpu, u64 timestamp) | 317 | static void c_state_end(struct timechart *tchart, int cpu, u64 timestamp) |
353 | { | 318 | { |
354 | struct power_event *pwr = zalloc(sizeof(*pwr)); | 319 | struct power_event *pwr = zalloc(sizeof(*pwr)); |
355 | 320 | ||
@@ -361,12 +326,12 @@ static void c_state_end(int cpu, u64 timestamp) | |||
361 | pwr->end_time = timestamp; | 326 | pwr->end_time = timestamp; |
362 | pwr->cpu = cpu; | 327 | pwr->cpu = cpu; |
363 | pwr->type = CSTATE; | 328 | pwr->type = CSTATE; |
364 | pwr->next = power_events; | 329 | pwr->next = tchart->power_events; |
365 | 330 | ||
366 | power_events = pwr; | 331 | tchart->power_events = pwr; |
367 | } | 332 | } |
368 | 333 | ||
369 | static void p_state_change(int cpu, u64 timestamp, u64 new_freq) | 334 | static void p_state_change(struct timechart *tchart, int cpu, u64 timestamp, u64 new_freq) |
370 | { | 335 | { |
371 | struct power_event *pwr; | 336 | struct power_event *pwr; |
372 | 337 | ||
@@ -382,73 +347,78 @@ static void p_state_change(int cpu, u64 timestamp, u64 new_freq) | |||
382 | pwr->end_time = timestamp; | 347 | pwr->end_time = timestamp; |
383 | pwr->cpu = cpu; | 348 | pwr->cpu = cpu; |
384 | pwr->type = PSTATE; | 349 | pwr->type = PSTATE; |
385 | pwr->next = power_events; | 350 | pwr->next = tchart->power_events; |
386 | 351 | ||
387 | if (!pwr->start_time) | 352 | if (!pwr->start_time) |
388 | pwr->start_time = first_time; | 353 | pwr->start_time = tchart->first_time; |
389 | 354 | ||
390 | power_events = pwr; | 355 | tchart->power_events = pwr; |
391 | 356 | ||
392 | cpus_pstate_state[cpu] = new_freq; | 357 | cpus_pstate_state[cpu] = new_freq; |
393 | cpus_pstate_start_times[cpu] = timestamp; | 358 | cpus_pstate_start_times[cpu] = timestamp; |
394 | 359 | ||
395 | if ((u64)new_freq > max_freq) | 360 | if ((u64)new_freq > tchart->max_freq) |
396 | max_freq = new_freq; | 361 | tchart->max_freq = new_freq; |
397 | 362 | ||
398 | if (new_freq < min_freq || min_freq == 0) | 363 | if (new_freq < tchart->min_freq || tchart->min_freq == 0) |
399 | min_freq = new_freq; | 364 | tchart->min_freq = new_freq; |
400 | 365 | ||
401 | if (new_freq == max_freq - 1000) | 366 | if (new_freq == tchart->max_freq - 1000) |
402 | turbo_frequency = max_freq; | 367 | tchart->turbo_frequency = tchart->max_freq; |
403 | } | 368 | } |
404 | 369 | ||
405 | static void | 370 | static void sched_wakeup(struct timechart *tchart, int cpu, u64 timestamp, |
406 | sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te) | 371 | int waker, int wakee, u8 flags, const char *backtrace) |
407 | { | 372 | { |
408 | struct per_pid *p; | 373 | struct per_pid *p; |
409 | struct wakeup_entry *wake = (void *)te; | ||
410 | struct wake_event *we = zalloc(sizeof(*we)); | 374 | struct wake_event *we = zalloc(sizeof(*we)); |
411 | 375 | ||
412 | if (!we) | 376 | if (!we) |
413 | return; | 377 | return; |
414 | 378 | ||
415 | we->time = timestamp; | 379 | we->time = timestamp; |
416 | we->waker = pid; | 380 | we->waker = waker; |
381 | we->backtrace = backtrace; | ||
417 | 382 | ||
418 | if ((te->flags & TRACE_FLAG_HARDIRQ) || (te->flags & TRACE_FLAG_SOFTIRQ)) | 383 | if ((flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) |
419 | we->waker = -1; | 384 | we->waker = -1; |
420 | 385 | ||
421 | we->wakee = wake->pid; | 386 | we->wakee = wakee; |
422 | we->next = wake_events; | 387 | we->next = tchart->wake_events; |
423 | wake_events = we; | 388 | tchart->wake_events = we; |
424 | p = find_create_pid(we->wakee); | 389 | p = find_create_pid(tchart, we->wakee); |
425 | 390 | ||
426 | if (p && p->current && p->current->state == TYPE_NONE) { | 391 | if (p && p->current && p->current->state == TYPE_NONE) { |
427 | p->current->state_since = timestamp; | 392 | p->current->state_since = timestamp; |
428 | p->current->state = TYPE_WAITING; | 393 | p->current->state = TYPE_WAITING; |
429 | } | 394 | } |
430 | if (p && p->current && p->current->state == TYPE_BLOCKED) { | 395 | if (p && p->current && p->current->state == TYPE_BLOCKED) { |
431 | pid_put_sample(p->pid, p->current->state, cpu, p->current->state_since, timestamp); | 396 | pid_put_sample(tchart, p->pid, p->current->state, cpu, |
397 | p->current->state_since, timestamp, NULL); | ||
432 | p->current->state_since = timestamp; | 398 | p->current->state_since = timestamp; |
433 | p->current->state = TYPE_WAITING; | 399 | p->current->state = TYPE_WAITING; |
434 | } | 400 | } |
435 | } | 401 | } |
436 | 402 | ||
437 | static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) | 403 | static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp, |
404 | int prev_pid, int next_pid, u64 prev_state, | ||
405 | const char *backtrace) | ||
438 | { | 406 | { |
439 | struct per_pid *p = NULL, *prev_p; | 407 | struct per_pid *p = NULL, *prev_p; |
440 | struct sched_switch *sw = (void *)te; | ||
441 | |||
442 | 408 | ||
443 | prev_p = find_create_pid(sw->prev_pid); | 409 | prev_p = find_create_pid(tchart, prev_pid); |
444 | 410 | ||
445 | p = find_create_pid(sw->next_pid); | 411 | p = find_create_pid(tchart, next_pid); |
446 | 412 | ||
447 | if (prev_p->current && prev_p->current->state != TYPE_NONE) | 413 | if (prev_p->current && prev_p->current->state != TYPE_NONE) |
448 | pid_put_sample(sw->prev_pid, TYPE_RUNNING, cpu, prev_p->current->state_since, timestamp); | 414 | pid_put_sample(tchart, prev_pid, TYPE_RUNNING, cpu, |
415 | prev_p->current->state_since, timestamp, | ||
416 | backtrace); | ||
449 | if (p && p->current) { | 417 | if (p && p->current) { |
450 | if (p->current->state != TYPE_NONE) | 418 | if (p->current->state != TYPE_NONE) |
451 | pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp); | 419 | pid_put_sample(tchart, next_pid, p->current->state, cpu, |
420 | p->current->state_since, timestamp, | ||
421 | backtrace); | ||
452 | 422 | ||
453 | p->current->state_since = timestamp; | 423 | p->current->state_since = timestamp; |
454 | p->current->state = TYPE_RUNNING; | 424 | p->current->state = TYPE_RUNNING; |
@@ -457,109 +427,211 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) | |||
457 | if (prev_p->current) { | 427 | if (prev_p->current) { |
458 | prev_p->current->state = TYPE_NONE; | 428 | prev_p->current->state = TYPE_NONE; |
459 | prev_p->current->state_since = timestamp; | 429 | prev_p->current->state_since = timestamp; |
460 | if (sw->prev_state & 2) | 430 | if (prev_state & 2) |
461 | prev_p->current->state = TYPE_BLOCKED; | 431 | prev_p->current->state = TYPE_BLOCKED; |
462 | if (sw->prev_state == 0) | 432 | if (prev_state == 0) |
463 | prev_p->current->state = TYPE_WAITING; | 433 | prev_p->current->state = TYPE_WAITING; |
464 | } | 434 | } |
465 | } | 435 | } |
466 | 436 | ||
467 | typedef int (*tracepoint_handler)(struct perf_evsel *evsel, | 437 | static const char *cat_backtrace(union perf_event *event, |
468 | struct perf_sample *sample); | 438 | struct perf_sample *sample, |
439 | struct machine *machine) | ||
440 | { | ||
441 | struct addr_location al; | ||
442 | unsigned int i; | ||
443 | char *p = NULL; | ||
444 | size_t p_len; | ||
445 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
446 | struct addr_location tal; | ||
447 | struct ip_callchain *chain = sample->callchain; | ||
448 | FILE *f = open_memstream(&p, &p_len); | ||
449 | |||
450 | if (!f) { | ||
451 | perror("open_memstream error"); | ||
452 | return NULL; | ||
453 | } | ||
454 | |||
455 | if (!chain) | ||
456 | goto exit; | ||
469 | 457 | ||
470 | static int process_sample_event(struct perf_tool *tool __maybe_unused, | 458 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { |
471 | union perf_event *event __maybe_unused, | 459 | fprintf(stderr, "problem processing %d event, skipping it.\n", |
460 | event->header.type); | ||
461 | goto exit; | ||
462 | } | ||
463 | |||
464 | for (i = 0; i < chain->nr; i++) { | ||
465 | u64 ip; | ||
466 | |||
467 | if (callchain_param.order == ORDER_CALLEE) | ||
468 | ip = chain->ips[i]; | ||
469 | else | ||
470 | ip = chain->ips[chain->nr - i - 1]; | ||
471 | |||
472 | if (ip >= PERF_CONTEXT_MAX) { | ||
473 | switch (ip) { | ||
474 | case PERF_CONTEXT_HV: | ||
475 | cpumode = PERF_RECORD_MISC_HYPERVISOR; | ||
476 | break; | ||
477 | case PERF_CONTEXT_KERNEL: | ||
478 | cpumode = PERF_RECORD_MISC_KERNEL; | ||
479 | break; | ||
480 | case PERF_CONTEXT_USER: | ||
481 | cpumode = PERF_RECORD_MISC_USER; | ||
482 | break; | ||
483 | default: | ||
484 | pr_debug("invalid callchain context: " | ||
485 | "%"PRId64"\n", (s64) ip); | ||
486 | |||
487 | /* | ||
488 | * It seems the callchain is corrupted. | ||
489 | * Discard all. | ||
490 | */ | ||
491 | zfree(&p); | ||
492 | goto exit; | ||
493 | } | ||
494 | continue; | ||
495 | } | ||
496 | |||
497 | tal.filtered = false; | ||
498 | thread__find_addr_location(al.thread, machine, cpumode, | ||
499 | MAP__FUNCTION, ip, &tal); | ||
500 | |||
501 | if (tal.sym) | ||
502 | fprintf(f, "..... %016" PRIx64 " %s\n", ip, | ||
503 | tal.sym->name); | ||
504 | else | ||
505 | fprintf(f, "..... %016" PRIx64 "\n", ip); | ||
506 | } | ||
507 | |||
508 | exit: | ||
509 | fclose(f); | ||
510 | |||
511 | return p; | ||
512 | } | ||
513 | |||
514 | typedef int (*tracepoint_handler)(struct timechart *tchart, | ||
515 | struct perf_evsel *evsel, | ||
516 | struct perf_sample *sample, | ||
517 | const char *backtrace); | ||
518 | |||
519 | static int process_sample_event(struct perf_tool *tool, | ||
520 | union perf_event *event, | ||
472 | struct perf_sample *sample, | 521 | struct perf_sample *sample, |
473 | struct perf_evsel *evsel, | 522 | struct perf_evsel *evsel, |
474 | struct machine *machine __maybe_unused) | 523 | struct machine *machine) |
475 | { | 524 | { |
525 | struct timechart *tchart = container_of(tool, struct timechart, tool); | ||
526 | |||
476 | if (evsel->attr.sample_type & PERF_SAMPLE_TIME) { | 527 | if (evsel->attr.sample_type & PERF_SAMPLE_TIME) { |
477 | if (!first_time || first_time > sample->time) | 528 | if (!tchart->first_time || tchart->first_time > sample->time) |
478 | first_time = sample->time; | 529 | tchart->first_time = sample->time; |
479 | if (last_time < sample->time) | 530 | if (tchart->last_time < sample->time) |
480 | last_time = sample->time; | 531 | tchart->last_time = sample->time; |
481 | } | 532 | } |
482 | 533 | ||
483 | if (sample->cpu > numcpus) | ||
484 | numcpus = sample->cpu; | ||
485 | |||
486 | if (evsel->handler != NULL) { | 534 | if (evsel->handler != NULL) { |
487 | tracepoint_handler f = evsel->handler; | 535 | tracepoint_handler f = evsel->handler; |
488 | return f(evsel, sample); | 536 | return f(tchart, evsel, sample, |
537 | cat_backtrace(event, sample, machine)); | ||
489 | } | 538 | } |
490 | 539 | ||
491 | return 0; | 540 | return 0; |
492 | } | 541 | } |
493 | 542 | ||
494 | static int | 543 | static int |
495 | process_sample_cpu_idle(struct perf_evsel *evsel __maybe_unused, | 544 | process_sample_cpu_idle(struct timechart *tchart __maybe_unused, |
496 | struct perf_sample *sample) | 545 | struct perf_evsel *evsel, |
546 | struct perf_sample *sample, | ||
547 | const char *backtrace __maybe_unused) | ||
497 | { | 548 | { |
498 | struct power_processor_entry *ppe = sample->raw_data; | 549 | u32 state = perf_evsel__intval(evsel, sample, "state"); |
550 | u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id"); | ||
499 | 551 | ||
500 | if (ppe->state == (u32) PWR_EVENT_EXIT) | 552 | if (state == (u32)PWR_EVENT_EXIT) |
501 | c_state_end(ppe->cpu_id, sample->time); | 553 | c_state_end(tchart, cpu_id, sample->time); |
502 | else | 554 | else |
503 | c_state_start(ppe->cpu_id, sample->time, ppe->state); | 555 | c_state_start(cpu_id, sample->time, state); |
504 | return 0; | 556 | return 0; |
505 | } | 557 | } |
506 | 558 | ||
507 | static int | 559 | static int |
508 | process_sample_cpu_frequency(struct perf_evsel *evsel __maybe_unused, | 560 | process_sample_cpu_frequency(struct timechart *tchart, |
509 | struct perf_sample *sample) | 561 | struct perf_evsel *evsel, |
562 | struct perf_sample *sample, | ||
563 | const char *backtrace __maybe_unused) | ||
510 | { | 564 | { |
511 | struct power_processor_entry *ppe = sample->raw_data; | 565 | u32 state = perf_evsel__intval(evsel, sample, "state"); |
566 | u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id"); | ||
512 | 567 | ||
513 | p_state_change(ppe->cpu_id, sample->time, ppe->state); | 568 | p_state_change(tchart, cpu_id, sample->time, state); |
514 | return 0; | 569 | return 0; |
515 | } | 570 | } |
516 | 571 | ||
517 | static int | 572 | static int |
518 | process_sample_sched_wakeup(struct perf_evsel *evsel __maybe_unused, | 573 | process_sample_sched_wakeup(struct timechart *tchart, |
519 | struct perf_sample *sample) | 574 | struct perf_evsel *evsel, |
575 | struct perf_sample *sample, | ||
576 | const char *backtrace) | ||
520 | { | 577 | { |
521 | struct trace_entry *te = sample->raw_data; | 578 | u8 flags = perf_evsel__intval(evsel, sample, "common_flags"); |
579 | int waker = perf_evsel__intval(evsel, sample, "common_pid"); | ||
580 | int wakee = perf_evsel__intval(evsel, sample, "pid"); | ||
522 | 581 | ||
523 | sched_wakeup(sample->cpu, sample->time, sample->pid, te); | 582 | sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace); |
524 | return 0; | 583 | return 0; |
525 | } | 584 | } |
526 | 585 | ||
527 | static int | 586 | static int |
528 | process_sample_sched_switch(struct perf_evsel *evsel __maybe_unused, | 587 | process_sample_sched_switch(struct timechart *tchart, |
529 | struct perf_sample *sample) | 588 | struct perf_evsel *evsel, |
589 | struct perf_sample *sample, | ||
590 | const char *backtrace) | ||
530 | { | 591 | { |
531 | struct trace_entry *te = sample->raw_data; | 592 | int prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"); |
593 | int next_pid = perf_evsel__intval(evsel, sample, "next_pid"); | ||
594 | u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); | ||
532 | 595 | ||
533 | sched_switch(sample->cpu, sample->time, te); | 596 | sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid, |
597 | prev_state, backtrace); | ||
534 | return 0; | 598 | return 0; |
535 | } | 599 | } |
536 | 600 | ||
537 | #ifdef SUPPORT_OLD_POWER_EVENTS | 601 | #ifdef SUPPORT_OLD_POWER_EVENTS |
538 | static int | 602 | static int |
539 | process_sample_power_start(struct perf_evsel *evsel __maybe_unused, | 603 | process_sample_power_start(struct timechart *tchart __maybe_unused, |
540 | struct perf_sample *sample) | 604 | struct perf_evsel *evsel, |
605 | struct perf_sample *sample, | ||
606 | const char *backtrace __maybe_unused) | ||
541 | { | 607 | { |
542 | struct power_entry_old *peo = sample->raw_data; | 608 | u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id"); |
609 | u64 value = perf_evsel__intval(evsel, sample, "value"); | ||
543 | 610 | ||
544 | c_state_start(peo->cpu_id, sample->time, peo->value); | 611 | c_state_start(cpu_id, sample->time, value); |
545 | return 0; | 612 | return 0; |
546 | } | 613 | } |
547 | 614 | ||
548 | static int | 615 | static int |
549 | process_sample_power_end(struct perf_evsel *evsel __maybe_unused, | 616 | process_sample_power_end(struct timechart *tchart, |
550 | struct perf_sample *sample) | 617 | struct perf_evsel *evsel __maybe_unused, |
618 | struct perf_sample *sample, | ||
619 | const char *backtrace __maybe_unused) | ||
551 | { | 620 | { |
552 | c_state_end(sample->cpu, sample->time); | 621 | c_state_end(tchart, sample->cpu, sample->time); |
553 | return 0; | 622 | return 0; |
554 | } | 623 | } |
555 | 624 | ||
556 | static int | 625 | static int |
557 | process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused, | 626 | process_sample_power_frequency(struct timechart *tchart, |
558 | struct perf_sample *sample) | 627 | struct perf_evsel *evsel, |
628 | struct perf_sample *sample, | ||
629 | const char *backtrace __maybe_unused) | ||
559 | { | 630 | { |
560 | struct power_entry_old *peo = sample->raw_data; | 631 | u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id"); |
632 | u64 value = perf_evsel__intval(evsel, sample, "value"); | ||
561 | 633 | ||
562 | p_state_change(peo->cpu_id, sample->time, peo->value); | 634 | p_state_change(tchart, cpu_id, sample->time, value); |
563 | return 0; | 635 | return 0; |
564 | } | 636 | } |
565 | #endif /* SUPPORT_OLD_POWER_EVENTS */ | 637 | #endif /* SUPPORT_OLD_POWER_EVENTS */ |
@@ -568,12 +640,12 @@ process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused, | |||
568 | * After the last sample we need to wrap up the current C/P state | 640 | * After the last sample we need to wrap up the current C/P state |
569 | * and close out each CPU for these. | 641 | * and close out each CPU for these. |
570 | */ | 642 | */ |
571 | static void end_sample_processing(void) | 643 | static void end_sample_processing(struct timechart *tchart) |
572 | { | 644 | { |
573 | u64 cpu; | 645 | u64 cpu; |
574 | struct power_event *pwr; | 646 | struct power_event *pwr; |
575 | 647 | ||
576 | for (cpu = 0; cpu <= numcpus; cpu++) { | 648 | for (cpu = 0; cpu <= tchart->numcpus; cpu++) { |
577 | /* C state */ | 649 | /* C state */ |
578 | #if 0 | 650 | #if 0 |
579 | pwr = zalloc(sizeof(*pwr)); | 651 | pwr = zalloc(sizeof(*pwr)); |
@@ -582,12 +654,12 @@ static void end_sample_processing(void) | |||
582 | 654 | ||
583 | pwr->state = cpus_cstate_state[cpu]; | 655 | pwr->state = cpus_cstate_state[cpu]; |
584 | pwr->start_time = cpus_cstate_start_times[cpu]; | 656 | pwr->start_time = cpus_cstate_start_times[cpu]; |
585 | pwr->end_time = last_time; | 657 | pwr->end_time = tchart->last_time; |
586 | pwr->cpu = cpu; | 658 | pwr->cpu = cpu; |
587 | pwr->type = CSTATE; | 659 | pwr->type = CSTATE; |
588 | pwr->next = power_events; | 660 | pwr->next = tchart->power_events; |
589 | 661 | ||
590 | power_events = pwr; | 662 | tchart->power_events = pwr; |
591 | #endif | 663 | #endif |
592 | /* P state */ | 664 | /* P state */ |
593 | 665 | ||
@@ -597,32 +669,32 @@ static void end_sample_processing(void) | |||
597 | 669 | ||
598 | pwr->state = cpus_pstate_state[cpu]; | 670 | pwr->state = cpus_pstate_state[cpu]; |
599 | pwr->start_time = cpus_pstate_start_times[cpu]; | 671 | pwr->start_time = cpus_pstate_start_times[cpu]; |
600 | pwr->end_time = last_time; | 672 | pwr->end_time = tchart->last_time; |
601 | pwr->cpu = cpu; | 673 | pwr->cpu = cpu; |
602 | pwr->type = PSTATE; | 674 | pwr->type = PSTATE; |
603 | pwr->next = power_events; | 675 | pwr->next = tchart->power_events; |
604 | 676 | ||
605 | if (!pwr->start_time) | 677 | if (!pwr->start_time) |
606 | pwr->start_time = first_time; | 678 | pwr->start_time = tchart->first_time; |
607 | if (!pwr->state) | 679 | if (!pwr->state) |
608 | pwr->state = min_freq; | 680 | pwr->state = tchart->min_freq; |
609 | power_events = pwr; | 681 | tchart->power_events = pwr; |
610 | } | 682 | } |
611 | } | 683 | } |
612 | 684 | ||
613 | /* | 685 | /* |
614 | * Sort the pid datastructure | 686 | * Sort the pid datastructure |
615 | */ | 687 | */ |
616 | static void sort_pids(void) | 688 | static void sort_pids(struct timechart *tchart) |
617 | { | 689 | { |
618 | struct per_pid *new_list, *p, *cursor, *prev; | 690 | struct per_pid *new_list, *p, *cursor, *prev; |
619 | /* sort by ppid first, then by pid, lowest to highest */ | 691 | /* sort by ppid first, then by pid, lowest to highest */ |
620 | 692 | ||
621 | new_list = NULL; | 693 | new_list = NULL; |
622 | 694 | ||
623 | while (all_data) { | 695 | while (tchart->all_data) { |
624 | p = all_data; | 696 | p = tchart->all_data; |
625 | all_data = p->next; | 697 | tchart->all_data = p->next; |
626 | p->next = NULL; | 698 | p->next = NULL; |
627 | 699 | ||
628 | if (new_list == NULL) { | 700 | if (new_list == NULL) { |
@@ -655,14 +727,14 @@ static void sort_pids(void) | |||
655 | prev->next = p; | 727 | prev->next = p; |
656 | } | 728 | } |
657 | } | 729 | } |
658 | all_data = new_list; | 730 | tchart->all_data = new_list; |
659 | } | 731 | } |
660 | 732 | ||
661 | 733 | ||
662 | static void draw_c_p_states(void) | 734 | static void draw_c_p_states(struct timechart *tchart) |
663 | { | 735 | { |
664 | struct power_event *pwr; | 736 | struct power_event *pwr; |
665 | pwr = power_events; | 737 | pwr = tchart->power_events; |
666 | 738 | ||
667 | /* | 739 | /* |
668 | * two pass drawing so that the P state bars are on top of the C state blocks | 740 | * two pass drawing so that the P state bars are on top of the C state blocks |
@@ -673,30 +745,30 @@ static void draw_c_p_states(void) | |||
673 | pwr = pwr->next; | 745 | pwr = pwr->next; |
674 | } | 746 | } |
675 | 747 | ||
676 | pwr = power_events; | 748 | pwr = tchart->power_events; |
677 | while (pwr) { | 749 | while (pwr) { |
678 | if (pwr->type == PSTATE) { | 750 | if (pwr->type == PSTATE) { |
679 | if (!pwr->state) | 751 | if (!pwr->state) |
680 | pwr->state = min_freq; | 752 | pwr->state = tchart->min_freq; |
681 | svg_pstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state); | 753 | svg_pstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state); |
682 | } | 754 | } |
683 | pwr = pwr->next; | 755 | pwr = pwr->next; |
684 | } | 756 | } |
685 | } | 757 | } |
686 | 758 | ||
687 | static void draw_wakeups(void) | 759 | static void draw_wakeups(struct timechart *tchart) |
688 | { | 760 | { |
689 | struct wake_event *we; | 761 | struct wake_event *we; |
690 | struct per_pid *p; | 762 | struct per_pid *p; |
691 | struct per_pidcomm *c; | 763 | struct per_pidcomm *c; |
692 | 764 | ||
693 | we = wake_events; | 765 | we = tchart->wake_events; |
694 | while (we) { | 766 | while (we) { |
695 | int from = 0, to = 0; | 767 | int from = 0, to = 0; |
696 | char *task_from = NULL, *task_to = NULL; | 768 | char *task_from = NULL, *task_to = NULL; |
697 | 769 | ||
698 | /* locate the column of the waker and wakee */ | 770 | /* locate the column of the waker and wakee */ |
699 | p = all_data; | 771 | p = tchart->all_data; |
700 | while (p) { | 772 | while (p) { |
701 | if (p->pid == we->waker || p->pid == we->wakee) { | 773 | if (p->pid == we->waker || p->pid == we->wakee) { |
702 | c = p->all; | 774 | c = p->all; |
@@ -739,11 +811,12 @@ static void draw_wakeups(void) | |||
739 | } | 811 | } |
740 | 812 | ||
741 | if (we->waker == -1) | 813 | if (we->waker == -1) |
742 | svg_interrupt(we->time, to); | 814 | svg_interrupt(we->time, to, we->backtrace); |
743 | else if (from && to && abs(from - to) == 1) | 815 | else if (from && to && abs(from - to) == 1) |
744 | svg_wakeline(we->time, from, to); | 816 | svg_wakeline(we->time, from, to, we->backtrace); |
745 | else | 817 | else |
746 | svg_partial_wakeline(we->time, from, task_from, to, task_to); | 818 | svg_partial_wakeline(we->time, from, task_from, to, |
819 | task_to, we->backtrace); | ||
747 | we = we->next; | 820 | we = we->next; |
748 | 821 | ||
749 | free(task_from); | 822 | free(task_from); |
@@ -751,19 +824,25 @@ static void draw_wakeups(void) | |||
751 | } | 824 | } |
752 | } | 825 | } |
753 | 826 | ||
754 | static void draw_cpu_usage(void) | 827 | static void draw_cpu_usage(struct timechart *tchart) |
755 | { | 828 | { |
756 | struct per_pid *p; | 829 | struct per_pid *p; |
757 | struct per_pidcomm *c; | 830 | struct per_pidcomm *c; |
758 | struct cpu_sample *sample; | 831 | struct cpu_sample *sample; |
759 | p = all_data; | 832 | p = tchart->all_data; |
760 | while (p) { | 833 | while (p) { |
761 | c = p->all; | 834 | c = p->all; |
762 | while (c) { | 835 | while (c) { |
763 | sample = c->samples; | 836 | sample = c->samples; |
764 | while (sample) { | 837 | while (sample) { |
765 | if (sample->type == TYPE_RUNNING) | 838 | if (sample->type == TYPE_RUNNING) { |
766 | svg_process(sample->cpu, sample->start_time, sample->end_time, "sample", c->comm); | 839 | svg_process(sample->cpu, |
840 | sample->start_time, | ||
841 | sample->end_time, | ||
842 | p->pid, | ||
843 | c->comm, | ||
844 | sample->backtrace); | ||
845 | } | ||
767 | 846 | ||
768 | sample = sample->next; | 847 | sample = sample->next; |
769 | } | 848 | } |
@@ -773,16 +852,16 @@ static void draw_cpu_usage(void) | |||
773 | } | 852 | } |
774 | } | 853 | } |
775 | 854 | ||
776 | static void draw_process_bars(void) | 855 | static void draw_process_bars(struct timechart *tchart) |
777 | { | 856 | { |
778 | struct per_pid *p; | 857 | struct per_pid *p; |
779 | struct per_pidcomm *c; | 858 | struct per_pidcomm *c; |
780 | struct cpu_sample *sample; | 859 | struct cpu_sample *sample; |
781 | int Y = 0; | 860 | int Y = 0; |
782 | 861 | ||
783 | Y = 2 * numcpus + 2; | 862 | Y = 2 * tchart->numcpus + 2; |
784 | 863 | ||
785 | p = all_data; | 864 | p = tchart->all_data; |
786 | while (p) { | 865 | while (p) { |
787 | c = p->all; | 866 | c = p->all; |
788 | while (c) { | 867 | while (c) { |
@@ -796,11 +875,20 @@ static void draw_process_bars(void) | |||
796 | sample = c->samples; | 875 | sample = c->samples; |
797 | while (sample) { | 876 | while (sample) { |
798 | if (sample->type == TYPE_RUNNING) | 877 | if (sample->type == TYPE_RUNNING) |
799 | svg_sample(Y, sample->cpu, sample->start_time, sample->end_time); | 878 | svg_running(Y, sample->cpu, |
879 | sample->start_time, | ||
880 | sample->end_time, | ||
881 | sample->backtrace); | ||
800 | if (sample->type == TYPE_BLOCKED) | 882 | if (sample->type == TYPE_BLOCKED) |
801 | svg_box(Y, sample->start_time, sample->end_time, "blocked"); | 883 | svg_blocked(Y, sample->cpu, |
884 | sample->start_time, | ||
885 | sample->end_time, | ||
886 | sample->backtrace); | ||
802 | if (sample->type == TYPE_WAITING) | 887 | if (sample->type == TYPE_WAITING) |
803 | svg_waiting(Y, sample->start_time, sample->end_time); | 888 | svg_waiting(Y, sample->cpu, |
889 | sample->start_time, | ||
890 | sample->end_time, | ||
891 | sample->backtrace); | ||
804 | sample = sample->next; | 892 | sample = sample->next; |
805 | } | 893 | } |
806 | 894 | ||
@@ -853,21 +941,21 @@ static int passes_filter(struct per_pid *p, struct per_pidcomm *c) | |||
853 | return 0; | 941 | return 0; |
854 | } | 942 | } |
855 | 943 | ||
856 | static int determine_display_tasks_filtered(void) | 944 | static int determine_display_tasks_filtered(struct timechart *tchart) |
857 | { | 945 | { |
858 | struct per_pid *p; | 946 | struct per_pid *p; |
859 | struct per_pidcomm *c; | 947 | struct per_pidcomm *c; |
860 | int count = 0; | 948 | int count = 0; |
861 | 949 | ||
862 | p = all_data; | 950 | p = tchart->all_data; |
863 | while (p) { | 951 | while (p) { |
864 | p->display = 0; | 952 | p->display = 0; |
865 | if (p->start_time == 1) | 953 | if (p->start_time == 1) |
866 | p->start_time = first_time; | 954 | p->start_time = tchart->first_time; |
867 | 955 | ||
868 | /* no exit marker, task kept running to the end */ | 956 | /* no exit marker, task kept running to the end */ |
869 | if (p->end_time == 0) | 957 | if (p->end_time == 0) |
870 | p->end_time = last_time; | 958 | p->end_time = tchart->last_time; |
871 | 959 | ||
872 | c = p->all; | 960 | c = p->all; |
873 | 961 | ||
@@ -875,7 +963,7 @@ static int determine_display_tasks_filtered(void) | |||
875 | c->display = 0; | 963 | c->display = 0; |
876 | 964 | ||
877 | if (c->start_time == 1) | 965 | if (c->start_time == 1) |
878 | c->start_time = first_time; | 966 | c->start_time = tchart->first_time; |
879 | 967 | ||
880 | if (passes_filter(p, c)) { | 968 | if (passes_filter(p, c)) { |
881 | c->display = 1; | 969 | c->display = 1; |
@@ -884,7 +972,7 @@ static int determine_display_tasks_filtered(void) | |||
884 | } | 972 | } |
885 | 973 | ||
886 | if (c->end_time == 0) | 974 | if (c->end_time == 0) |
887 | c->end_time = last_time; | 975 | c->end_time = tchart->last_time; |
888 | 976 | ||
889 | c = c->next; | 977 | c = c->next; |
890 | } | 978 | } |
@@ -893,25 +981,25 @@ static int determine_display_tasks_filtered(void) | |||
893 | return count; | 981 | return count; |
894 | } | 982 | } |
895 | 983 | ||
896 | static int determine_display_tasks(u64 threshold) | 984 | static int determine_display_tasks(struct timechart *tchart, u64 threshold) |
897 | { | 985 | { |
898 | struct per_pid *p; | 986 | struct per_pid *p; |
899 | struct per_pidcomm *c; | 987 | struct per_pidcomm *c; |
900 | int count = 0; | 988 | int count = 0; |
901 | 989 | ||
902 | if (process_filter) | 990 | if (process_filter) |
903 | return determine_display_tasks_filtered(); | 991 | return determine_display_tasks_filtered(tchart); |
904 | 992 | ||
905 | p = all_data; | 993 | p = tchart->all_data; |
906 | while (p) { | 994 | while (p) { |
907 | p->display = 0; | 995 | p->display = 0; |
908 | if (p->start_time == 1) | 996 | if (p->start_time == 1) |
909 | p->start_time = first_time; | 997 | p->start_time = tchart->first_time; |
910 | 998 | ||
911 | /* no exit marker, task kept running to the end */ | 999 | /* no exit marker, task kept running to the end */ |
912 | if (p->end_time == 0) | 1000 | if (p->end_time == 0) |
913 | p->end_time = last_time; | 1001 | p->end_time = tchart->last_time; |
914 | if (p->total_time >= threshold && !power_only) | 1002 | if (p->total_time >= threshold) |
915 | p->display = 1; | 1003 | p->display = 1; |
916 | 1004 | ||
917 | c = p->all; | 1005 | c = p->all; |
@@ -920,15 +1008,15 @@ static int determine_display_tasks(u64 threshold) | |||
920 | c->display = 0; | 1008 | c->display = 0; |
921 | 1009 | ||
922 | if (c->start_time == 1) | 1010 | if (c->start_time == 1) |
923 | c->start_time = first_time; | 1011 | c->start_time = tchart->first_time; |
924 | 1012 | ||
925 | if (c->total_time >= threshold && !power_only) { | 1013 | if (c->total_time >= threshold) { |
926 | c->display = 1; | 1014 | c->display = 1; |
927 | count++; | 1015 | count++; |
928 | } | 1016 | } |
929 | 1017 | ||
930 | if (c->end_time == 0) | 1018 | if (c->end_time == 0) |
931 | c->end_time = last_time; | 1019 | c->end_time = tchart->last_time; |
932 | 1020 | ||
933 | c = c->next; | 1021 | c = c->next; |
934 | } | 1022 | } |
@@ -941,45 +1029,74 @@ static int determine_display_tasks(u64 threshold) | |||
941 | 1029 | ||
942 | #define TIME_THRESH 10000000 | 1030 | #define TIME_THRESH 10000000 |
943 | 1031 | ||
944 | static void write_svg_file(const char *filename) | 1032 | static void write_svg_file(struct timechart *tchart, const char *filename) |
945 | { | 1033 | { |
946 | u64 i; | 1034 | u64 i; |
947 | int count; | 1035 | int count; |
1036 | int thresh = TIME_THRESH; | ||
948 | 1037 | ||
949 | numcpus++; | 1038 | if (tchart->power_only) |
950 | 1039 | tchart->proc_num = 0; | |
951 | 1040 | ||
952 | count = determine_display_tasks(TIME_THRESH); | 1041 | /* We'd like to show at least proc_num tasks; |
1042 | * be less picky if we have fewer */ | ||
1043 | do { | ||
1044 | count = determine_display_tasks(tchart, thresh); | ||
1045 | thresh /= 10; | ||
1046 | } while (!process_filter && thresh && count < tchart->proc_num); | ||
953 | 1047 | ||
954 | /* We'd like to show at least 15 tasks; be less picky if we have fewer */ | 1048 | open_svg(filename, tchart->numcpus, count, tchart->first_time, tchart->last_time); |
955 | if (count < 15) | ||
956 | count = determine_display_tasks(TIME_THRESH / 10); | ||
957 | |||
958 | open_svg(filename, numcpus, count, first_time, last_time); | ||
959 | 1049 | ||
960 | svg_time_grid(); | 1050 | svg_time_grid(); |
961 | svg_legenda(); | 1051 | svg_legenda(); |
962 | 1052 | ||
963 | for (i = 0; i < numcpus; i++) | 1053 | for (i = 0; i < tchart->numcpus; i++) |
964 | svg_cpu_box(i, max_freq, turbo_frequency); | 1054 | svg_cpu_box(i, tchart->max_freq, tchart->turbo_frequency); |
965 | 1055 | ||
966 | draw_cpu_usage(); | 1056 | draw_cpu_usage(tchart); |
967 | draw_process_bars(); | 1057 | if (tchart->proc_num) |
968 | draw_c_p_states(); | 1058 | draw_process_bars(tchart); |
969 | draw_wakeups(); | 1059 | if (!tchart->tasks_only) |
1060 | draw_c_p_states(tchart); | ||
1061 | if (tchart->proc_num) | ||
1062 | draw_wakeups(tchart); | ||
970 | 1063 | ||
971 | svg_close(); | 1064 | svg_close(); |
972 | } | 1065 | } |
973 | 1066 | ||
974 | static int __cmd_timechart(const char *output_name) | 1067 | static int process_header(struct perf_file_section *section __maybe_unused, |
1068 | struct perf_header *ph, | ||
1069 | int feat, | ||
1070 | int fd __maybe_unused, | ||
1071 | void *data) | ||
1072 | { | ||
1073 | struct timechart *tchart = data; | ||
1074 | |||
1075 | switch (feat) { | ||
1076 | case HEADER_NRCPUS: | ||
1077 | tchart->numcpus = ph->env.nr_cpus_avail; | ||
1078 | break; | ||
1079 | |||
1080 | case HEADER_CPU_TOPOLOGY: | ||
1081 | if (!tchart->topology) | ||
1082 | break; | ||
1083 | |||
1084 | if (svg_build_topology_map(ph->env.sibling_cores, | ||
1085 | ph->env.nr_sibling_cores, | ||
1086 | ph->env.sibling_threads, | ||
1087 | ph->env.nr_sibling_threads)) | ||
1088 | fprintf(stderr, "problem building topology\n"); | ||
1089 | break; | ||
1090 | |||
1091 | default: | ||
1092 | break; | ||
1093 | } | ||
1094 | |||
1095 | return 0; | ||
1096 | } | ||
1097 | |||
1098 | static int __cmd_timechart(struct timechart *tchart, const char *output_name) | ||
975 | { | 1099 | { |
976 | struct perf_tool perf_timechart = { | ||
977 | .comm = process_comm_event, | ||
978 | .fork = process_fork_event, | ||
979 | .exit = process_exit_event, | ||
980 | .sample = process_sample_event, | ||
981 | .ordered_samples = true, | ||
982 | }; | ||
983 | const struct perf_evsel_str_handler power_tracepoints[] = { | 1100 | const struct perf_evsel_str_handler power_tracepoints[] = { |
984 | { "power:cpu_idle", process_sample_cpu_idle }, | 1101 | { "power:cpu_idle", process_sample_cpu_idle }, |
985 | { "power:cpu_frequency", process_sample_cpu_frequency }, | 1102 | { "power:cpu_frequency", process_sample_cpu_frequency }, |
@@ -997,12 +1114,17 @@ static int __cmd_timechart(const char *output_name) | |||
997 | }; | 1114 | }; |
998 | 1115 | ||
999 | struct perf_session *session = perf_session__new(&file, false, | 1116 | struct perf_session *session = perf_session__new(&file, false, |
1000 | &perf_timechart); | 1117 | &tchart->tool); |
1001 | int ret = -EINVAL; | 1118 | int ret = -EINVAL; |
1002 | 1119 | ||
1003 | if (session == NULL) | 1120 | if (session == NULL) |
1004 | return -ENOMEM; | 1121 | return -ENOMEM; |
1005 | 1122 | ||
1123 | (void)perf_header__process_sections(&session->header, | ||
1124 | perf_data_file__fd(session->file), | ||
1125 | tchart, | ||
1126 | process_header); | ||
1127 | |||
1006 | if (!perf_session__has_traces(session, "timechart record")) | 1128 | if (!perf_session__has_traces(session, "timechart record")) |
1007 | goto out_delete; | 1129 | goto out_delete; |
1008 | 1130 | ||
@@ -1012,69 +1134,111 @@ static int __cmd_timechart(const char *output_name) | |||
1012 | goto out_delete; | 1134 | goto out_delete; |
1013 | } | 1135 | } |
1014 | 1136 | ||
1015 | ret = perf_session__process_events(session, &perf_timechart); | 1137 | ret = perf_session__process_events(session, &tchart->tool); |
1016 | if (ret) | 1138 | if (ret) |
1017 | goto out_delete; | 1139 | goto out_delete; |
1018 | 1140 | ||
1019 | end_sample_processing(); | 1141 | end_sample_processing(tchart); |
1020 | 1142 | ||
1021 | sort_pids(); | 1143 | sort_pids(tchart); |
1022 | 1144 | ||
1023 | write_svg_file(output_name); | 1145 | write_svg_file(tchart, output_name); |
1024 | 1146 | ||
1025 | pr_info("Written %2.1f seconds of trace to %s.\n", | 1147 | pr_info("Written %2.1f seconds of trace to %s.\n", |
1026 | (last_time - first_time) / 1000000000.0, output_name); | 1148 | (tchart->last_time - tchart->first_time) / 1000000000.0, output_name); |
1027 | out_delete: | 1149 | out_delete: |
1028 | perf_session__delete(session); | 1150 | perf_session__delete(session); |
1029 | return ret; | 1151 | return ret; |
1030 | } | 1152 | } |
1031 | 1153 | ||
1032 | static int __cmd_record(int argc, const char **argv) | 1154 | static int timechart__record(struct timechart *tchart, int argc, const char **argv) |
1033 | { | 1155 | { |
1034 | #ifdef SUPPORT_OLD_POWER_EVENTS | 1156 | unsigned int rec_argc, i, j; |
1035 | const char * const record_old_args[] = { | 1157 | const char **rec_argv; |
1158 | const char **p; | ||
1159 | unsigned int record_elems; | ||
1160 | |||
1161 | const char * const common_args[] = { | ||
1036 | "record", "-a", "-R", "-c", "1", | 1162 | "record", "-a", "-R", "-c", "1", |
1163 | }; | ||
1164 | unsigned int common_args_nr = ARRAY_SIZE(common_args); | ||
1165 | |||
1166 | const char * const backtrace_args[] = { | ||
1167 | "-g", | ||
1168 | }; | ||
1169 | unsigned int backtrace_args_no = ARRAY_SIZE(backtrace_args); | ||
1170 | |||
1171 | const char * const power_args[] = { | ||
1172 | "-e", "power:cpu_frequency", | ||
1173 | "-e", "power:cpu_idle", | ||
1174 | }; | ||
1175 | unsigned int power_args_nr = ARRAY_SIZE(power_args); | ||
1176 | |||
1177 | const char * const old_power_args[] = { | ||
1178 | #ifdef SUPPORT_OLD_POWER_EVENTS | ||
1037 | "-e", "power:power_start", | 1179 | "-e", "power:power_start", |
1038 | "-e", "power:power_end", | 1180 | "-e", "power:power_end", |
1039 | "-e", "power:power_frequency", | 1181 | "-e", "power:power_frequency", |
1040 | "-e", "sched:sched_wakeup", | ||
1041 | "-e", "sched:sched_switch", | ||
1042 | }; | ||
1043 | #endif | 1182 | #endif |
1044 | const char * const record_new_args[] = { | 1183 | }; |
1045 | "record", "-a", "-R", "-c", "1", | 1184 | unsigned int old_power_args_nr = ARRAY_SIZE(old_power_args); |
1046 | "-e", "power:cpu_frequency", | 1185 | |
1047 | "-e", "power:cpu_idle", | 1186 | const char * const tasks_args[] = { |
1048 | "-e", "sched:sched_wakeup", | 1187 | "-e", "sched:sched_wakeup", |
1049 | "-e", "sched:sched_switch", | 1188 | "-e", "sched:sched_switch", |
1050 | }; | 1189 | }; |
1051 | unsigned int rec_argc, i, j; | 1190 | unsigned int tasks_args_nr = ARRAY_SIZE(tasks_args); |
1052 | const char **rec_argv; | ||
1053 | const char * const *record_args = record_new_args; | ||
1054 | unsigned int record_elems = ARRAY_SIZE(record_new_args); | ||
1055 | 1191 | ||
1056 | #ifdef SUPPORT_OLD_POWER_EVENTS | 1192 | #ifdef SUPPORT_OLD_POWER_EVENTS |
1057 | if (!is_valid_tracepoint("power:cpu_idle") && | 1193 | if (!is_valid_tracepoint("power:cpu_idle") && |
1058 | is_valid_tracepoint("power:power_start")) { | 1194 | is_valid_tracepoint("power:power_start")) { |
1059 | use_old_power_events = 1; | 1195 | use_old_power_events = 1; |
1060 | record_args = record_old_args; | 1196 | power_args_nr = 0; |
1061 | record_elems = ARRAY_SIZE(record_old_args); | 1197 | } else { |
1198 | old_power_args_nr = 0; | ||
1062 | } | 1199 | } |
1063 | #endif | 1200 | #endif |
1064 | 1201 | ||
1065 | rec_argc = record_elems + argc - 1; | 1202 | if (tchart->power_only) |
1203 | tasks_args_nr = 0; | ||
1204 | |||
1205 | if (tchart->tasks_only) { | ||
1206 | power_args_nr = 0; | ||
1207 | old_power_args_nr = 0; | ||
1208 | } | ||
1209 | |||
1210 | if (!tchart->with_backtrace) | ||
1211 | backtrace_args_no = 0; | ||
1212 | |||
1213 | record_elems = common_args_nr + tasks_args_nr + | ||
1214 | power_args_nr + old_power_args_nr + backtrace_args_no; | ||
1215 | |||
1216 | rec_argc = record_elems + argc; | ||
1066 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 1217 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
1067 | 1218 | ||
1068 | if (rec_argv == NULL) | 1219 | if (rec_argv == NULL) |
1069 | return -ENOMEM; | 1220 | return -ENOMEM; |
1070 | 1221 | ||
1071 | for (i = 0; i < record_elems; i++) | 1222 | p = rec_argv; |
1072 | rec_argv[i] = strdup(record_args[i]); | 1223 | for (i = 0; i < common_args_nr; i++) |
1224 | *p++ = strdup(common_args[i]); | ||
1225 | |||
1226 | for (i = 0; i < backtrace_args_no; i++) | ||
1227 | *p++ = strdup(backtrace_args[i]); | ||
1228 | |||
1229 | for (i = 0; i < tasks_args_nr; i++) | ||
1230 | *p++ = strdup(tasks_args[i]); | ||
1231 | |||
1232 | for (i = 0; i < power_args_nr; i++) | ||
1233 | *p++ = strdup(power_args[i]); | ||
1073 | 1234 | ||
1074 | for (j = 1; j < (unsigned int)argc; j++, i++) | 1235 | for (i = 0; i < old_power_args_nr; i++) |
1075 | rec_argv[i] = argv[j]; | 1236 | *p++ = strdup(old_power_args[i]); |
1076 | 1237 | ||
1077 | return cmd_record(i, rec_argv, NULL); | 1238 | for (j = 1; j < (unsigned int)argc; j++) |
1239 | *p++ = argv[j]; | ||
1240 | |||
1241 | return cmd_record(rec_argc, rec_argv, NULL); | ||
1078 | } | 1242 | } |
1079 | 1243 | ||
1080 | static int | 1244 | static int |
@@ -1086,20 +1250,56 @@ parse_process(const struct option *opt __maybe_unused, const char *arg, | |||
1086 | return 0; | 1250 | return 0; |
1087 | } | 1251 | } |
1088 | 1252 | ||
1253 | static int | ||
1254 | parse_highlight(const struct option *opt __maybe_unused, const char *arg, | ||
1255 | int __maybe_unused unset) | ||
1256 | { | ||
1257 | unsigned long duration = strtoul(arg, NULL, 0); | ||
1258 | |||
1259 | if (svg_highlight || svg_highlight_name) | ||
1260 | return -1; | ||
1261 | |||
1262 | if (duration) | ||
1263 | svg_highlight = duration; | ||
1264 | else | ||
1265 | svg_highlight_name = strdup(arg); | ||
1266 | |||
1267 | return 0; | ||
1268 | } | ||
1269 | |||
1089 | int cmd_timechart(int argc, const char **argv, | 1270 | int cmd_timechart(int argc, const char **argv, |
1090 | const char *prefix __maybe_unused) | 1271 | const char *prefix __maybe_unused) |
1091 | { | 1272 | { |
1273 | struct timechart tchart = { | ||
1274 | .tool = { | ||
1275 | .comm = process_comm_event, | ||
1276 | .fork = process_fork_event, | ||
1277 | .exit = process_exit_event, | ||
1278 | .sample = process_sample_event, | ||
1279 | .ordered_samples = true, | ||
1280 | }, | ||
1281 | .proc_num = 15, | ||
1282 | }; | ||
1092 | const char *output_name = "output.svg"; | 1283 | const char *output_name = "output.svg"; |
1093 | const struct option options[] = { | 1284 | const struct option timechart_options[] = { |
1094 | OPT_STRING('i', "input", &input_name, "file", "input file name"), | 1285 | OPT_STRING('i', "input", &input_name, "file", "input file name"), |
1095 | OPT_STRING('o', "output", &output_name, "file", "output file name"), | 1286 | OPT_STRING('o', "output", &output_name, "file", "output file name"), |
1096 | OPT_INTEGER('w', "width", &svg_page_width, "page width"), | 1287 | OPT_INTEGER('w', "width", &svg_page_width, "page width"), |
1097 | OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"), | 1288 | OPT_CALLBACK(0, "highlight", NULL, "duration or task name", |
1289 | "highlight tasks. Pass duration in ns or process name.", | ||
1290 | parse_highlight), | ||
1291 | OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), | ||
1292 | OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, | ||
1293 | "output processes data only"), | ||
1098 | OPT_CALLBACK('p', "process", NULL, "process", | 1294 | OPT_CALLBACK('p', "process", NULL, "process", |
1099 | "process selector. Pass a pid or process name.", | 1295 | "process selector. Pass a pid or process name.", |
1100 | parse_process), | 1296 | parse_process), |
1101 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 1297 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", |
1102 | "Look for files with symbols relative to this directory"), | 1298 | "Look for files with symbols relative to this directory"), |
1299 | OPT_INTEGER('n', "proc-num", &tchart.proc_num, | ||
1300 | "min. number of tasks to print"), | ||
1301 | OPT_BOOLEAN('t', "topology", &tchart.topology, | ||
1302 | "sort CPUs according to topology"), | ||
1103 | OPT_END() | 1303 | OPT_END() |
1104 | }; | 1304 | }; |
1105 | const char * const timechart_usage[] = { | 1305 | const char * const timechart_usage[] = { |
@@ -1107,17 +1307,41 @@ int cmd_timechart(int argc, const char **argv, | |||
1107 | NULL | 1307 | NULL |
1108 | }; | 1308 | }; |
1109 | 1309 | ||
1110 | argc = parse_options(argc, argv, options, timechart_usage, | 1310 | const struct option record_options[] = { |
1311 | OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), | ||
1312 | OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, | ||
1313 | "output processes data only"), | ||
1314 | OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"), | ||
1315 | OPT_END() | ||
1316 | }; | ||
1317 | const char * const record_usage[] = { | ||
1318 | "perf timechart record [<options>]", | ||
1319 | NULL | ||
1320 | }; | ||
1321 | argc = parse_options(argc, argv, timechart_options, timechart_usage, | ||
1111 | PARSE_OPT_STOP_AT_NON_OPTION); | 1322 | PARSE_OPT_STOP_AT_NON_OPTION); |
1112 | 1323 | ||
1324 | if (tchart.power_only && tchart.tasks_only) { | ||
1325 | pr_err("-P and -T options cannot be used at the same time.\n"); | ||
1326 | return -1; | ||
1327 | } | ||
1328 | |||
1113 | symbol__init(); | 1329 | symbol__init(); |
1114 | 1330 | ||
1115 | if (argc && !strncmp(argv[0], "rec", 3)) | 1331 | if (argc && !strncmp(argv[0], "rec", 3)) { |
1116 | return __cmd_record(argc, argv); | 1332 | argc = parse_options(argc, argv, record_options, record_usage, |
1117 | else if (argc) | 1333 | PARSE_OPT_STOP_AT_NON_OPTION); |
1118 | usage_with_options(timechart_usage, options); | 1334 | |
1335 | if (tchart.power_only && tchart.tasks_only) { | ||
1336 | pr_err("-P and -T options cannot be used at the same time.\n"); | ||
1337 | return -1; | ||
1338 | } | ||
1339 | |||
1340 | return timechart__record(&tchart, argc, argv); | ||
1341 | } else if (argc) | ||
1342 | usage_with_options(timechart_usage, timechart_options); | ||
1119 | 1343 | ||
1120 | setup_pager(); | 1344 | setup_pager(); |
1121 | 1345 | ||
1122 | return __cmd_timechart(output_name); | 1346 | return __cmd_timechart(&tchart, output_name); |
1123 | } | 1347 | } |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 71e6402729a8..76cd510d34d0 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -189,21 +189,18 @@ static void perf_top__record_precise_ip(struct perf_top *top, | |||
189 | if (pthread_mutex_trylock(¬es->lock)) | 189 | if (pthread_mutex_trylock(¬es->lock)) |
190 | return; | 190 | return; |
191 | 191 | ||
192 | if (notes->src == NULL && symbol__alloc_hist(sym) < 0) { | ||
193 | pthread_mutex_unlock(¬es->lock); | ||
194 | pr_err("Not enough memory for annotating '%s' symbol!\n", | ||
195 | sym->name); | ||
196 | sleep(1); | ||
197 | return; | ||
198 | } | ||
199 | |||
200 | ip = he->ms.map->map_ip(he->ms.map, ip); | 192 | ip = he->ms.map->map_ip(he->ms.map, ip); |
201 | err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip); | 193 | err = hist_entry__inc_addr_samples(he, counter, ip); |
202 | 194 | ||
203 | pthread_mutex_unlock(¬es->lock); | 195 | pthread_mutex_unlock(¬es->lock); |
204 | 196 | ||
205 | if (err == -ERANGE && !he->ms.map->erange_warned) | 197 | if (err == -ERANGE && !he->ms.map->erange_warned) |
206 | ui__warn_map_erange(he->ms.map, sym, ip); | 198 | ui__warn_map_erange(he->ms.map, sym, ip); |
199 | else if (err == -ENOMEM) { | ||
200 | pr_err("Not enough memory for annotating '%s' symbol!\n", | ||
201 | sym->name); | ||
202 | sleep(1); | ||
203 | } | ||
207 | } | 204 | } |
208 | 205 | ||
209 | static void perf_top__show_details(struct perf_top *top) | 206 | static void perf_top__show_details(struct perf_top *top) |
@@ -485,7 +482,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) | |||
485 | 482 | ||
486 | fprintf(stderr, "\nAvailable events:"); | 483 | fprintf(stderr, "\nAvailable events:"); |
487 | 484 | ||
488 | list_for_each_entry(top->sym_evsel, &top->evlist->entries, node) | 485 | evlist__for_each(top->evlist, top->sym_evsel) |
489 | fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel)); | 486 | fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel)); |
490 | 487 | ||
491 | prompt_integer(&counter, "Enter details event counter"); | 488 | prompt_integer(&counter, "Enter details event counter"); |
@@ -496,7 +493,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) | |||
496 | sleep(1); | 493 | sleep(1); |
497 | break; | 494 | break; |
498 | } | 495 | } |
499 | list_for_each_entry(top->sym_evsel, &top->evlist->entries, node) | 496 | evlist__for_each(top->evlist, top->sym_evsel) |
500 | if (top->sym_evsel->idx == counter) | 497 | if (top->sym_evsel->idx == counter) |
501 | break; | 498 | break; |
502 | } else | 499 | } else |
@@ -578,7 +575,7 @@ static void *display_thread_tui(void *arg) | |||
578 | * Zooming in/out UIDs. For now juse use whatever the user passed | 575 | * Zooming in/out UIDs. For now juse use whatever the user passed |
579 | * via --uid. | 576 | * via --uid. |
580 | */ | 577 | */ |
581 | list_for_each_entry(pos, &top->evlist->entries, node) | 578 | evlist__for_each(top->evlist, pos) |
582 | pos->hists.uid_filter_str = top->record_opts.target.uid_str; | 579 | pos->hists.uid_filter_str = top->record_opts.target.uid_str; |
583 | 580 | ||
584 | perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, | 581 | perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, |
@@ -634,26 +631,9 @@ repeat: | |||
634 | return NULL; | 631 | return NULL; |
635 | } | 632 | } |
636 | 633 | ||
637 | /* Tag samples to be skipped. */ | ||
638 | static const char *skip_symbols[] = { | ||
639 | "intel_idle", | ||
640 | "default_idle", | ||
641 | "native_safe_halt", | ||
642 | "cpu_idle", | ||
643 | "enter_idle", | ||
644 | "exit_idle", | ||
645 | "mwait_idle", | ||
646 | "mwait_idle_with_hints", | ||
647 | "poll_idle", | ||
648 | "ppc64_runlatch_off", | ||
649 | "pseries_dedicated_idle_sleep", | ||
650 | NULL | ||
651 | }; | ||
652 | |||
653 | static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) | 634 | static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) |
654 | { | 635 | { |
655 | const char *name = sym->name; | 636 | const char *name = sym->name; |
656 | int i; | ||
657 | 637 | ||
658 | /* | 638 | /* |
659 | * ppc64 uses function descriptors and appends a '.' to the | 639 | * ppc64 uses function descriptors and appends a '.' to the |
@@ -671,12 +651,8 @@ static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) | |||
671 | strstr(name, "_text_end")) | 651 | strstr(name, "_text_end")) |
672 | return 1; | 652 | return 1; |
673 | 653 | ||
674 | for (i = 0; skip_symbols[i]; i++) { | 654 | if (symbol__is_idle(sym)) |
675 | if (!strcmp(skip_symbols[i], name)) { | 655 | sym->ignore = true; |
676 | sym->ignore = true; | ||
677 | break; | ||
678 | } | ||
679 | } | ||
680 | 656 | ||
681 | return 0; | 657 | return 0; |
682 | } | 658 | } |
@@ -767,15 +743,10 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
767 | if (al.sym == NULL || !al.sym->ignore) { | 743 | if (al.sym == NULL || !al.sym->ignore) { |
768 | struct hist_entry *he; | 744 | struct hist_entry *he; |
769 | 745 | ||
770 | if ((sort__has_parent || symbol_conf.use_callchain) && | 746 | err = sample__resolve_callchain(sample, &parent, evsel, &al, |
771 | sample->callchain) { | 747 | top->max_stack); |
772 | err = machine__resolve_callchain(machine, evsel, | 748 | if (err) |
773 | al.thread, sample, | 749 | return; |
774 | &parent, &al, | ||
775 | top->max_stack); | ||
776 | if (err) | ||
777 | return; | ||
778 | } | ||
779 | 750 | ||
780 | he = perf_evsel__add_hist_entry(evsel, &al, sample); | 751 | he = perf_evsel__add_hist_entry(evsel, &al, sample); |
781 | if (he == NULL) { | 752 | if (he == NULL) { |
@@ -783,12 +754,9 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
783 | return; | 754 | return; |
784 | } | 755 | } |
785 | 756 | ||
786 | if (symbol_conf.use_callchain) { | 757 | err = hist_entry__append_callchain(he, sample); |
787 | err = callchain_append(he->callchain, &callchain_cursor, | 758 | if (err) |
788 | sample->period); | 759 | return; |
789 | if (err) | ||
790 | return; | ||
791 | } | ||
792 | 760 | ||
793 | if (sort__has_sym) | 761 | if (sort__has_sym) |
794 | perf_top__record_precise_ip(top, he, evsel->idx, ip); | 762 | perf_top__record_precise_ip(top, he, evsel->idx, ip); |
@@ -878,11 +846,11 @@ static int perf_top__start_counters(struct perf_top *top) | |||
878 | char msg[512]; | 846 | char msg[512]; |
879 | struct perf_evsel *counter; | 847 | struct perf_evsel *counter; |
880 | struct perf_evlist *evlist = top->evlist; | 848 | struct perf_evlist *evlist = top->evlist; |
881 | struct perf_record_opts *opts = &top->record_opts; | 849 | struct record_opts *opts = &top->record_opts; |
882 | 850 | ||
883 | perf_evlist__config(evlist, opts); | 851 | perf_evlist__config(evlist, opts); |
884 | 852 | ||
885 | list_for_each_entry(counter, &evlist->entries, node) { | 853 | evlist__for_each(evlist, counter) { |
886 | try_again: | 854 | try_again: |
887 | if (perf_evsel__open(counter, top->evlist->cpus, | 855 | if (perf_evsel__open(counter, top->evlist->cpus, |
888 | top->evlist->threads) < 0) { | 856 | top->evlist->threads) < 0) { |
@@ -930,7 +898,7 @@ static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused) | |||
930 | 898 | ||
931 | static int __cmd_top(struct perf_top *top) | 899 | static int __cmd_top(struct perf_top *top) |
932 | { | 900 | { |
933 | struct perf_record_opts *opts = &top->record_opts; | 901 | struct record_opts *opts = &top->record_opts; |
934 | pthread_t thread; | 902 | pthread_t thread; |
935 | int ret; | 903 | int ret; |
936 | 904 | ||
@@ -1052,7 +1020,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1052 | .max_stack = PERF_MAX_STACK_DEPTH, | 1020 | .max_stack = PERF_MAX_STACK_DEPTH, |
1053 | .sym_pcnt_filter = 5, | 1021 | .sym_pcnt_filter = 5, |
1054 | }; | 1022 | }; |
1055 | struct perf_record_opts *opts = &top.record_opts; | 1023 | struct record_opts *opts = &top.record_opts; |
1056 | struct target *target = &opts->target; | 1024 | struct target *target = &opts->target; |
1057 | const struct option options[] = { | 1025 | const struct option options[] = { |
1058 | OPT_CALLBACK('e', "event", &top.evlist, "event", | 1026 | OPT_CALLBACK('e', "event", &top.evlist, "event", |
@@ -1084,7 +1052,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1084 | "dump the symbol table used for profiling"), | 1052 | "dump the symbol table used for profiling"), |
1085 | OPT_INTEGER('f', "count-filter", &top.count_filter, | 1053 | OPT_INTEGER('f', "count-filter", &top.count_filter, |
1086 | "only display functions with more events than this"), | 1054 | "only display functions with more events than this"), |
1087 | OPT_BOOLEAN('g', "group", &opts->group, | 1055 | OPT_BOOLEAN(0, "group", &opts->group, |
1088 | "put the counters into a counter group"), | 1056 | "put the counters into a counter group"), |
1089 | OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit, | 1057 | OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit, |
1090 | "child tasks do not inherit counters"), | 1058 | "child tasks do not inherit counters"), |
@@ -1105,7 +1073,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1105 | " abort, in_tx, transaction"), | 1073 | " abort, in_tx, transaction"), |
1106 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, | 1074 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, |
1107 | "Show a column with the number of samples"), | 1075 | "Show a column with the number of samples"), |
1108 | OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts, | 1076 | OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, |
1109 | NULL, "enables call-graph recording", | 1077 | NULL, "enables call-graph recording", |
1110 | &callchain_opt), | 1078 | &callchain_opt), |
1111 | OPT_CALLBACK(0, "call-graph", &top.record_opts, | 1079 | OPT_CALLBACK(0, "call-graph", &top.record_opts, |
@@ -1195,7 +1163,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1195 | if (!top.evlist->nr_entries && | 1163 | if (!top.evlist->nr_entries && |
1196 | perf_evlist__add_default(top.evlist) < 0) { | 1164 | perf_evlist__add_default(top.evlist) < 0) { |
1197 | ui__error("Not enough memory for event selector list\n"); | 1165 | ui__error("Not enough memory for event selector list\n"); |
1198 | goto out_delete_maps; | 1166 | goto out_delete_evlist; |
1199 | } | 1167 | } |
1200 | 1168 | ||
1201 | symbol_conf.nr_events = top.evlist->nr_entries; | 1169 | symbol_conf.nr_events = top.evlist->nr_entries; |
@@ -1203,9 +1171,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1203 | if (top.delay_secs < 1) | 1171 | if (top.delay_secs < 1) |
1204 | top.delay_secs = 1; | 1172 | top.delay_secs = 1; |
1205 | 1173 | ||
1206 | if (perf_record_opts__config(opts)) { | 1174 | if (record_opts__config(opts)) { |
1207 | status = -EINVAL; | 1175 | status = -EINVAL; |
1208 | goto out_delete_maps; | 1176 | goto out_delete_evlist; |
1209 | } | 1177 | } |
1210 | 1178 | ||
1211 | top.sym_evsel = perf_evlist__first(top.evlist); | 1179 | top.sym_evsel = perf_evlist__first(top.evlist); |
@@ -1230,8 +1198,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1230 | 1198 | ||
1231 | status = __cmd_top(&top); | 1199 | status = __cmd_top(&top); |
1232 | 1200 | ||
1233 | out_delete_maps: | ||
1234 | perf_evlist__delete_maps(top.evlist); | ||
1235 | out_delete_evlist: | 1201 | out_delete_evlist: |
1236 | perf_evlist__delete(top.evlist); | 1202 | perf_evlist__delete(top.evlist); |
1237 | 1203 | ||
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8be17fc462ba..896f27047ed6 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include "util/intlist.h" | 11 | #include "util/intlist.h" |
12 | #include "util/thread_map.h" | 12 | #include "util/thread_map.h" |
13 | #include "util/stat.h" | 13 | #include "util/stat.h" |
14 | #include "trace-event.h" | ||
15 | #include "util/parse-events.h" | ||
14 | 16 | ||
15 | #include <libaudit.h> | 17 | #include <libaudit.h> |
16 | #include <stdlib.h> | 18 | #include <stdlib.h> |
@@ -144,8 +146,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel, | |||
144 | 146 | ||
145 | static void perf_evsel__delete_priv(struct perf_evsel *evsel) | 147 | static void perf_evsel__delete_priv(struct perf_evsel *evsel) |
146 | { | 148 | { |
147 | free(evsel->priv); | 149 | zfree(&evsel->priv); |
148 | evsel->priv = NULL; | ||
149 | perf_evsel__delete(evsel); | 150 | perf_evsel__delete(evsel); |
150 | } | 151 | } |
151 | 152 | ||
@@ -163,8 +164,7 @@ static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler) | |||
163 | return -ENOMEM; | 164 | return -ENOMEM; |
164 | 165 | ||
165 | out_delete: | 166 | out_delete: |
166 | free(evsel->priv); | 167 | zfree(&evsel->priv); |
167 | evsel->priv = NULL; | ||
168 | return -ENOENT; | 168 | return -ENOENT; |
169 | } | 169 | } |
170 | 170 | ||
@@ -172,6 +172,10 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void | |||
172 | { | 172 | { |
173 | struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); | 173 | struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); |
174 | 174 | ||
175 | /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */ | ||
176 | if (evsel == NULL) | ||
177 | evsel = perf_evsel__newtp("syscalls", direction); | ||
178 | |||
175 | if (evsel) { | 179 | if (evsel) { |
176 | if (perf_evsel__init_syscall_tp(evsel, handler)) | 180 | if (perf_evsel__init_syscall_tp(evsel, handler)) |
177 | goto out_delete; | 181 | goto out_delete; |
@@ -1153,29 +1157,30 @@ struct trace { | |||
1153 | int max; | 1157 | int max; |
1154 | struct syscall *table; | 1158 | struct syscall *table; |
1155 | } syscalls; | 1159 | } syscalls; |
1156 | struct perf_record_opts opts; | 1160 | struct record_opts opts; |
1157 | struct machine *host; | 1161 | struct machine *host; |
1158 | u64 base_time; | 1162 | u64 base_time; |
1159 | bool full_time; | ||
1160 | FILE *output; | 1163 | FILE *output; |
1161 | unsigned long nr_events; | 1164 | unsigned long nr_events; |
1162 | struct strlist *ev_qualifier; | 1165 | struct strlist *ev_qualifier; |
1163 | bool not_ev_qualifier; | ||
1164 | bool live; | ||
1165 | const char *last_vfs_getname; | 1166 | const char *last_vfs_getname; |
1166 | struct intlist *tid_list; | 1167 | struct intlist *tid_list; |
1167 | struct intlist *pid_list; | 1168 | struct intlist *pid_list; |
1169 | double duration_filter; | ||
1170 | double runtime_ms; | ||
1171 | struct { | ||
1172 | u64 vfs_getname, | ||
1173 | proc_getname; | ||
1174 | } stats; | ||
1175 | bool not_ev_qualifier; | ||
1176 | bool live; | ||
1177 | bool full_time; | ||
1168 | bool sched; | 1178 | bool sched; |
1169 | bool multiple_threads; | 1179 | bool multiple_threads; |
1170 | bool summary; | 1180 | bool summary; |
1171 | bool summary_only; | 1181 | bool summary_only; |
1172 | bool show_comm; | 1182 | bool show_comm; |
1173 | bool show_tool_stats; | 1183 | bool show_tool_stats; |
1174 | double duration_filter; | ||
1175 | double runtime_ms; | ||
1176 | struct { | ||
1177 | u64 vfs_getname, proc_getname; | ||
1178 | } stats; | ||
1179 | }; | 1184 | }; |
1180 | 1185 | ||
1181 | static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) | 1186 | static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) |
@@ -1272,10 +1277,8 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size, | |||
1272 | size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); | 1277 | size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); |
1273 | struct thread_trace *ttrace = arg->thread->priv; | 1278 | struct thread_trace *ttrace = arg->thread->priv; |
1274 | 1279 | ||
1275 | if (ttrace && fd >= 0 && fd <= ttrace->paths.max) { | 1280 | if (ttrace && fd >= 0 && fd <= ttrace->paths.max) |
1276 | free(ttrace->paths.table[fd]); | 1281 | zfree(&ttrace->paths.table[fd]); |
1277 | ttrace->paths.table[fd] = NULL; | ||
1278 | } | ||
1279 | 1282 | ||
1280 | return printed; | 1283 | return printed; |
1281 | } | 1284 | } |
@@ -1430,11 +1433,11 @@ static int trace__read_syscall_info(struct trace *trace, int id) | |||
1430 | sc->fmt = syscall_fmt__find(sc->name); | 1433 | sc->fmt = syscall_fmt__find(sc->name); |
1431 | 1434 | ||
1432 | snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); | 1435 | snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); |
1433 | sc->tp_format = event_format__new("syscalls", tp_name); | 1436 | sc->tp_format = trace_event__tp_format("syscalls", tp_name); |
1434 | 1437 | ||
1435 | if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) { | 1438 | if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) { |
1436 | snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); | 1439 | snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); |
1437 | sc->tp_format = event_format__new("syscalls", tp_name); | 1440 | sc->tp_format = trace_event__tp_format("syscalls", tp_name); |
1438 | } | 1441 | } |
1439 | 1442 | ||
1440 | if (sc->tp_format == NULL) | 1443 | if (sc->tp_format == NULL) |
@@ -1764,8 +1767,10 @@ static int trace__process_sample(struct perf_tool *tool, | |||
1764 | if (!trace->full_time && trace->base_time == 0) | 1767 | if (!trace->full_time && trace->base_time == 0) |
1765 | trace->base_time = sample->time; | 1768 | trace->base_time = sample->time; |
1766 | 1769 | ||
1767 | if (handler) | 1770 | if (handler) { |
1771 | ++trace->nr_events; | ||
1768 | handler(trace, evsel, sample); | 1772 | handler(trace, evsel, sample); |
1773 | } | ||
1769 | 1774 | ||
1770 | return err; | 1775 | return err; |
1771 | } | 1776 | } |
@@ -1800,10 +1805,11 @@ static int trace__record(int argc, const char **argv) | |||
1800 | "-R", | 1805 | "-R", |
1801 | "-m", "1024", | 1806 | "-m", "1024", |
1802 | "-c", "1", | 1807 | "-c", "1", |
1803 | "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit", | 1808 | "-e", |
1804 | }; | 1809 | }; |
1805 | 1810 | ||
1806 | rec_argc = ARRAY_SIZE(record_args) + argc; | 1811 | /* +1 is for the event string below */ |
1812 | rec_argc = ARRAY_SIZE(record_args) + 1 + argc; | ||
1807 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 1813 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
1808 | 1814 | ||
1809 | if (rec_argv == NULL) | 1815 | if (rec_argv == NULL) |
@@ -1812,6 +1818,17 @@ static int trace__record(int argc, const char **argv) | |||
1812 | for (i = 0; i < ARRAY_SIZE(record_args); i++) | 1818 | for (i = 0; i < ARRAY_SIZE(record_args); i++) |
1813 | rec_argv[i] = record_args[i]; | 1819 | rec_argv[i] = record_args[i]; |
1814 | 1820 | ||
1821 | /* event string may be different for older kernels - e.g., RHEL6 */ | ||
1822 | if (is_valid_tracepoint("raw_syscalls:sys_enter")) | ||
1823 | rec_argv[i] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit"; | ||
1824 | else if (is_valid_tracepoint("syscalls:sys_enter")) | ||
1825 | rec_argv[i] = "syscalls:sys_enter,syscalls:sys_exit"; | ||
1826 | else { | ||
1827 | pr_err("Neither raw_syscalls nor syscalls events exist.\n"); | ||
1828 | return -1; | ||
1829 | } | ||
1830 | i++; | ||
1831 | |||
1815 | for (j = 0; j < (unsigned int)argc; j++, i++) | 1832 | for (j = 0; j < (unsigned int)argc; j++, i++) |
1816 | rec_argv[i] = argv[j]; | 1833 | rec_argv[i] = argv[j]; |
1817 | 1834 | ||
@@ -1869,7 +1886,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
1869 | err = trace__symbols_init(trace, evlist); | 1886 | err = trace__symbols_init(trace, evlist); |
1870 | if (err < 0) { | 1887 | if (err < 0) { |
1871 | fprintf(trace->output, "Problems initializing symbol libraries!\n"); | 1888 | fprintf(trace->output, "Problems initializing symbol libraries!\n"); |
1872 | goto out_delete_maps; | 1889 | goto out_delete_evlist; |
1873 | } | 1890 | } |
1874 | 1891 | ||
1875 | perf_evlist__config(evlist, &trace->opts); | 1892 | perf_evlist__config(evlist, &trace->opts); |
@@ -1879,10 +1896,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
1879 | 1896 | ||
1880 | if (forks) { | 1897 | if (forks) { |
1881 | err = perf_evlist__prepare_workload(evlist, &trace->opts.target, | 1898 | err = perf_evlist__prepare_workload(evlist, &trace->opts.target, |
1882 | argv, false, false); | 1899 | argv, false, NULL); |
1883 | if (err < 0) { | 1900 | if (err < 0) { |
1884 | fprintf(trace->output, "Couldn't run the workload!\n"); | 1901 | fprintf(trace->output, "Couldn't run the workload!\n"); |
1885 | goto out_delete_maps; | 1902 | goto out_delete_evlist; |
1886 | } | 1903 | } |
1887 | } | 1904 | } |
1888 | 1905 | ||
@@ -1890,10 +1907,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
1890 | if (err < 0) | 1907 | if (err < 0) |
1891 | goto out_error_open; | 1908 | goto out_error_open; |
1892 | 1909 | ||
1893 | err = perf_evlist__mmap(evlist, UINT_MAX, false); | 1910 | err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); |
1894 | if (err < 0) { | 1911 | if (err < 0) { |
1895 | fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); | 1912 | fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); |
1896 | goto out_close_evlist; | 1913 | goto out_delete_evlist; |
1897 | } | 1914 | } |
1898 | 1915 | ||
1899 | perf_evlist__enable(evlist); | 1916 | perf_evlist__enable(evlist); |
@@ -1977,11 +1994,6 @@ out_disable: | |||
1977 | } | 1994 | } |
1978 | } | 1995 | } |
1979 | 1996 | ||
1980 | perf_evlist__munmap(evlist); | ||
1981 | out_close_evlist: | ||
1982 | perf_evlist__close(evlist); | ||
1983 | out_delete_maps: | ||
1984 | perf_evlist__delete_maps(evlist); | ||
1985 | out_delete_evlist: | 1997 | out_delete_evlist: |
1986 | perf_evlist__delete(evlist); | 1998 | perf_evlist__delete(evlist); |
1987 | out: | 1999 | out: |
@@ -2047,6 +2059,10 @@ static int trace__replay(struct trace *trace) | |||
2047 | 2059 | ||
2048 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, | 2060 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, |
2049 | "raw_syscalls:sys_enter"); | 2061 | "raw_syscalls:sys_enter"); |
2062 | /* older kernels have syscalls tp versus raw_syscalls */ | ||
2063 | if (evsel == NULL) | ||
2064 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, | ||
2065 | "syscalls:sys_enter"); | ||
2050 | if (evsel == NULL) { | 2066 | if (evsel == NULL) { |
2051 | pr_err("Data file does not have raw_syscalls:sys_enter event\n"); | 2067 | pr_err("Data file does not have raw_syscalls:sys_enter event\n"); |
2052 | goto out; | 2068 | goto out; |
@@ -2060,6 +2076,9 @@ static int trace__replay(struct trace *trace) | |||
2060 | 2076 | ||
2061 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, | 2077 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, |
2062 | "raw_syscalls:sys_exit"); | 2078 | "raw_syscalls:sys_exit"); |
2079 | if (evsel == NULL) | ||
2080 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, | ||
2081 | "syscalls:sys_exit"); | ||
2063 | if (evsel == NULL) { | 2082 | if (evsel == NULL) { |
2064 | pr_err("Data file does not have raw_syscalls:sys_exit event\n"); | 2083 | pr_err("Data file does not have raw_syscalls:sys_exit event\n"); |
2065 | goto out; | 2084 | goto out; |
@@ -2158,7 +2177,6 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv) | |||
2158 | size_t printed = data->printed; | 2177 | size_t printed = data->printed; |
2159 | struct trace *trace = data->trace; | 2178 | struct trace *trace = data->trace; |
2160 | struct thread_trace *ttrace = thread->priv; | 2179 | struct thread_trace *ttrace = thread->priv; |
2161 | const char *color; | ||
2162 | double ratio; | 2180 | double ratio; |
2163 | 2181 | ||
2164 | if (ttrace == NULL) | 2182 | if (ttrace == NULL) |
@@ -2166,17 +2184,9 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv) | |||
2166 | 2184 | ||
2167 | ratio = (double)ttrace->nr_events / trace->nr_events * 100.0; | 2185 | ratio = (double)ttrace->nr_events / trace->nr_events * 100.0; |
2168 | 2186 | ||
2169 | color = PERF_COLOR_NORMAL; | 2187 | printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid); |
2170 | if (ratio > 50.0) | ||
2171 | color = PERF_COLOR_RED; | ||
2172 | else if (ratio > 25.0) | ||
2173 | color = PERF_COLOR_GREEN; | ||
2174 | else if (ratio > 5.0) | ||
2175 | color = PERF_COLOR_YELLOW; | ||
2176 | |||
2177 | printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid); | ||
2178 | printed += fprintf(fp, "%lu events, ", ttrace->nr_events); | 2188 | printed += fprintf(fp, "%lu events, ", ttrace->nr_events); |
2179 | printed += color_fprintf(fp, color, "%.1f%%", ratio); | 2189 | printed += fprintf(fp, "%.1f%%", ratio); |
2180 | printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); | 2190 | printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); |
2181 | printed += thread__dump_stats(ttrace, trace, fp); | 2191 | printed += thread__dump_stats(ttrace, trace, fp); |
2182 | 2192 | ||
@@ -2248,7 +2258,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2248 | }, | 2258 | }, |
2249 | .user_freq = UINT_MAX, | 2259 | .user_freq = UINT_MAX, |
2250 | .user_interval = ULLONG_MAX, | 2260 | .user_interval = ULLONG_MAX, |
2251 | .no_delay = true, | 2261 | .no_buffering = true, |
2252 | .mmap_pages = 1024, | 2262 | .mmap_pages = 1024, |
2253 | }, | 2263 | }, |
2254 | .output = stdout, | 2264 | .output = stdout, |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index f7d11a811c74..d604e50fc167 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -1,28 +1,26 @@ | |||
1 | uname_M := $(shell uname -m 2>/dev/null || echo not) | ||
2 | 1 | ||
3 | ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | 2 | ifeq ($(src-perf),) |
4 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | 3 | src-perf := $(srctree)/tools/perf |
5 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | 4 | endif |
6 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ | ||
7 | -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) | ||
8 | NO_PERF_REGS := 1 | ||
9 | CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS) | ||
10 | 5 | ||
11 | # Additional ARCH settings for x86 | 6 | ifeq ($(obj-perf),) |
12 | ifeq ($(ARCH),i386) | 7 | obj-perf := $(OUTPUT) |
13 | override ARCH := x86 | ||
14 | NO_PERF_REGS := 0 | ||
15 | LIBUNWIND_LIBS = -lunwind -lunwind-x86 | ||
16 | endif | 8 | endif |
17 | 9 | ||
18 | ifeq ($(ARCH),x86_64) | 10 | ifneq ($(obj-perf),) |
19 | override ARCH := x86 | 11 | obj-perf := $(abspath $(obj-perf))/ |
20 | IS_X86_64 := 0 | 12 | endif |
21 | ifeq (, $(findstring m32,$(CFLAGS))) | 13 | |
22 | IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) | 14 | LIB_INCLUDE := $(srctree)/tools/lib/ |
23 | endif | 15 | CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS) |
16 | |||
17 | include $(src-perf)/config/Makefile.arch | ||
18 | |||
19 | NO_PERF_REGS := 1 | ||
20 | |||
21 | # Additional ARCH settings for x86 | ||
22 | ifeq ($(ARCH),x86) | ||
24 | ifeq (${IS_X86_64}, 1) | 23 | ifeq (${IS_X86_64}, 1) |
25 | RAW_ARCH := x86_64 | ||
26 | CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT | 24 | CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT |
27 | ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S | 25 | ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S |
28 | LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 | 26 | LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 |
@@ -36,24 +34,31 @@ ifeq ($(ARCH),arm) | |||
36 | LIBUNWIND_LIBS = -lunwind -lunwind-arm | 34 | LIBUNWIND_LIBS = -lunwind -lunwind-arm |
37 | endif | 35 | endif |
38 | 36 | ||
39 | ifeq ($(NO_PERF_REGS),0) | 37 | ifeq ($(LIBUNWIND_LIBS),) |
40 | CFLAGS += -DHAVE_PERF_REGS_SUPPORT | 38 | NO_LIBUNWIND := 1 |
41 | endif | 39 | else |
42 | 40 | # | |
43 | ifeq ($(src-perf),) | 41 | # For linking with debug library, run like: |
44 | src-perf := $(srctree)/tools/perf | 42 | # |
45 | endif | 43 | # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ |
44 | # | ||
45 | ifdef LIBUNWIND_DIR | ||
46 | LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include | ||
47 | LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib | ||
48 | endif | ||
49 | LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS) | ||
46 | 50 | ||
47 | ifeq ($(obj-perf),) | 51 | # Set per-feature check compilation flags |
48 | obj-perf := $(OUTPUT) | 52 | FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) |
53 | FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) | ||
54 | FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) | ||
55 | FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) | ||
49 | endif | 56 | endif |
50 | 57 | ||
51 | ifneq ($(obj-perf),) | 58 | ifeq ($(NO_PERF_REGS),0) |
52 | obj-perf := $(abspath $(obj-perf))/ | 59 | CFLAGS += -DHAVE_PERF_REGS_SUPPORT |
53 | endif | 60 | endif |
54 | 61 | ||
55 | LIB_INCLUDE := $(srctree)/tools/lib/ | ||
56 | |||
57 | # include ARCH specific config | 62 | # include ARCH specific config |
58 | -include $(src-perf)/arch/$(ARCH)/Makefile | 63 | -include $(src-perf)/arch/$(ARCH)/Makefile |
59 | 64 | ||
@@ -102,7 +107,7 @@ endif | |||
102 | 107 | ||
103 | feature_check = $(eval $(feature_check_code)) | 108 | feature_check = $(eval $(feature_check_code)) |
104 | define feature_check_code | 109 | define feature_check_code |
105 | feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0) | 110 | feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) |
106 | endef | 111 | endef |
107 | 112 | ||
108 | feature_set = $(eval $(feature_set_code)) | 113 | feature_set = $(eval $(feature_set_code)) |
@@ -141,16 +146,26 @@ CORE_FEATURE_TESTS = \ | |||
141 | libslang \ | 146 | libslang \ |
142 | libunwind \ | 147 | libunwind \ |
143 | on-exit \ | 148 | on-exit \ |
144 | stackprotector \ | ||
145 | stackprotector-all \ | 149 | stackprotector-all \ |
146 | timerfd | 150 | timerfd |
147 | 151 | ||
152 | # Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. | ||
153 | # If in the future we need per-feature checks/flags for features not | ||
154 | # mentioned in this list we need to refactor this ;-). | ||
155 | set_test_all_flags = $(eval $(set_test_all_flags_code)) | ||
156 | define set_test_all_flags_code | ||
157 | FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1)) | ||
158 | FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1)) | ||
159 | endef | ||
160 | |||
161 | $(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat))) | ||
162 | |||
148 | # | 163 | # |
149 | # So here we detect whether test-all was rebuilt, to be able | 164 | # So here we detect whether test-all was rebuilt, to be able |
150 | # to skip the print-out of the long features list if the file | 165 | # to skip the print-out of the long features list if the file |
151 | # existed before and after it was built: | 166 | # existed before and after it was built: |
152 | # | 167 | # |
153 | ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all),) | 168 | ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),) |
154 | test-all-failed := 1 | 169 | test-all-failed := 1 |
155 | else | 170 | else |
156 | test-all-failed := 0 | 171 | test-all-failed := 0 |
@@ -180,7 +195,7 @@ ifeq ($(feature-all), 1) | |||
180 | # | 195 | # |
181 | $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat))) | 196 | $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat))) |
182 | else | 197 | else |
183 | $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1) | 198 | $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(CORE_FEATURE_TESTS)) >/dev/null 2>&1) |
184 | $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat))) | 199 | $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat))) |
185 | endif | 200 | endif |
186 | 201 | ||
@@ -209,10 +224,6 @@ ifeq ($(feature-stackprotector-all), 1) | |||
209 | CFLAGS += -fstack-protector-all | 224 | CFLAGS += -fstack-protector-all |
210 | endif | 225 | endif |
211 | 226 | ||
212 | ifeq ($(feature-stackprotector), 1) | ||
213 | CFLAGS += -Wstack-protector | ||
214 | endif | ||
215 | |||
216 | ifeq ($(DEBUG),0) | 227 | ifeq ($(DEBUG),0) |
217 | ifeq ($(feature-fortify-source), 1) | 228 | ifeq ($(feature-fortify-source), 1) |
218 | CFLAGS += -D_FORTIFY_SOURCE=2 | 229 | CFLAGS += -D_FORTIFY_SOURCE=2 |
@@ -221,6 +232,7 @@ endif | |||
221 | 232 | ||
222 | CFLAGS += -I$(src-perf)/util/include | 233 | CFLAGS += -I$(src-perf)/util/include |
223 | CFLAGS += -I$(src-perf)/arch/$(ARCH)/include | 234 | CFLAGS += -I$(src-perf)/arch/$(ARCH)/include |
235 | CFLAGS += -I$(srctree)/tools/include/ | ||
224 | CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi | 236 | CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi |
225 | CFLAGS += -I$(srctree)/arch/$(ARCH)/include | 237 | CFLAGS += -I$(srctree)/arch/$(ARCH)/include |
226 | CFLAGS += -I$(srctree)/include/uapi | 238 | CFLAGS += -I$(srctree)/include/uapi |
@@ -310,21 +322,7 @@ ifndef NO_LIBELF | |||
310 | endif # NO_DWARF | 322 | endif # NO_DWARF |
311 | endif # NO_LIBELF | 323 | endif # NO_LIBELF |
312 | 324 | ||
313 | ifeq ($(LIBUNWIND_LIBS),) | ||
314 | NO_LIBUNWIND := 1 | ||
315 | endif | ||
316 | |||
317 | ifndef NO_LIBUNWIND | 325 | ifndef NO_LIBUNWIND |
318 | # | ||
319 | # For linking with debug library, run like: | ||
320 | # | ||
321 | # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ | ||
322 | # | ||
323 | ifdef LIBUNWIND_DIR | ||
324 | LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include | ||
325 | LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib | ||
326 | endif | ||
327 | |||
328 | ifneq ($(feature-libunwind), 1) | 326 | ifneq ($(feature-libunwind), 1) |
329 | msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1); | 327 | msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1); |
330 | NO_LIBUNWIND := 1 | 328 | NO_LIBUNWIND := 1 |
@@ -339,14 +337,12 @@ ifndef NO_LIBUNWIND | |||
339 | # non-ARM has no dwarf_find_debug_frame() function: | 337 | # non-ARM has no dwarf_find_debug_frame() function: |
340 | CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME | 338 | CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME |
341 | endif | 339 | endif |
342 | endif | ||
343 | endif | ||
344 | 340 | ||
345 | ifndef NO_LIBUNWIND | 341 | CFLAGS += -DHAVE_LIBUNWIND_SUPPORT |
346 | CFLAGS += -DHAVE_LIBUNWIND_SUPPORT | 342 | EXTLIBS += $(LIBUNWIND_LIBS) |
347 | EXTLIBS += $(LIBUNWIND_LIBS) | 343 | CFLAGS += $(LIBUNWIND_CFLAGS) |
348 | CFLAGS += $(LIBUNWIND_CFLAGS) | 344 | LDFLAGS += $(LIBUNWIND_LDFLAGS) |
349 | LDFLAGS += $(LIBUNWIND_LDFLAGS) | 345 | endif # ifneq ($(feature-libunwind), 1) |
350 | endif | 346 | endif |
351 | 347 | ||
352 | ifndef NO_LIBAUDIT | 348 | ifndef NO_LIBAUDIT |
@@ -376,7 +372,7 @@ ifndef NO_SLANG | |||
376 | endif | 372 | endif |
377 | 373 | ||
378 | ifndef NO_GTK2 | 374 | ifndef NO_GTK2 |
379 | FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) | 375 | FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) |
380 | ifneq ($(feature-gtk2), 1) | 376 | ifneq ($(feature-gtk2), 1) |
381 | msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); | 377 | msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); |
382 | NO_GTK2 := 1 | 378 | NO_GTK2 := 1 |
@@ -385,8 +381,8 @@ ifndef NO_GTK2 | |||
385 | GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT | 381 | GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT |
386 | endif | 382 | endif |
387 | CFLAGS += -DHAVE_GTK2_SUPPORT | 383 | CFLAGS += -DHAVE_GTK2_SUPPORT |
388 | GTK_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) | 384 | GTK_CFLAGS += $(shell $(PKG_CONFIG) --cflags gtk+-2.0 2>/dev/null) |
389 | GTK_LIBS := $(shell pkg-config --libs gtk+-2.0 2>/dev/null) | 385 | GTK_LIBS := $(shell $(PKG_CONFIG) --libs gtk+-2.0 2>/dev/null) |
390 | EXTLIBS += -ldl | 386 | EXTLIBS += -ldl |
391 | endif | 387 | endif |
392 | endif | 388 | endif |
@@ -533,7 +529,7 @@ endif | |||
533 | 529 | ||
534 | ifndef NO_LIBNUMA | 530 | ifndef NO_LIBNUMA |
535 | ifeq ($(feature-libnuma), 0) | 531 | ifeq ($(feature-libnuma), 0) |
536 | msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev); | 532 | msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numactl-devel/libnuma-devel/libnuma-dev); |
537 | NO_LIBNUMA := 1 | 533 | NO_LIBNUMA := 1 |
538 | else | 534 | else |
539 | CFLAGS += -DHAVE_LIBNUMA_SUPPORT | 535 | CFLAGS += -DHAVE_LIBNUMA_SUPPORT |
@@ -598,3 +594,11 @@ else | |||
598 | perfexec_instdir = $(prefix)/$(perfexecdir) | 594 | perfexec_instdir = $(prefix)/$(perfexecdir) |
599 | endif | 595 | endif |
600 | perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) | 596 | perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) |
597 | |||
598 | # If we install to $(HOME) we keep the traceevent default: | ||
599 | # $(HOME)/.traceevent/plugins | ||
600 | # Otherwise we install plugins into the global $(libdir). | ||
601 | ifdef DESTDIR | ||
602 | plugindir=$(libdir)/traceevent/plugins | ||
603 | plugindir_SQ= $(subst ','\'',$(prefix)/$(plugindir)) | ||
604 | endif | ||
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch new file mode 100644 index 000000000000..fef8ae922800 --- /dev/null +++ b/tools/perf/config/Makefile.arch | |||
@@ -0,0 +1,22 @@ | |||
1 | |||
2 | uname_M := $(shell uname -m 2>/dev/null || echo not) | ||
3 | |||
4 | ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | ||
5 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | ||
6 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | ||
7 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ | ||
8 | -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) | ||
9 | |||
10 | # Additional ARCH settings for x86 | ||
11 | ifeq ($(ARCH),i386) | ||
12 | override ARCH := x86 | ||
13 | endif | ||
14 | |||
15 | ifeq ($(ARCH),x86_64) | ||
16 | override ARCH := x86 | ||
17 | IS_X86_64 := 0 | ||
18 | ifeq (, $(findstring m32,$(CFLAGS))) | ||
19 | IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) | ||
20 | RAW_ARCH := x86_64 | ||
21 | endif | ||
22 | endif | ||
diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore new file mode 100644 index 000000000000..80f3da0c3515 --- /dev/null +++ b/tools/perf/config/feature-checks/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | *.d | ||
2 | *.bin | ||
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile index 87e790017c69..12e551346fa6 100644 --- a/tools/perf/config/feature-checks/Makefile +++ b/tools/perf/config/feature-checks/Makefile | |||
@@ -1,95 +1,92 @@ | |||
1 | 1 | ||
2 | FILES= \ | 2 | FILES= \ |
3 | test-all \ | 3 | test-all.bin \ |
4 | test-backtrace \ | 4 | test-backtrace.bin \ |
5 | test-bionic \ | 5 | test-bionic.bin \ |
6 | test-dwarf \ | 6 | test-dwarf.bin \ |
7 | test-fortify-source \ | 7 | test-fortify-source.bin \ |
8 | test-glibc \ | 8 | test-glibc.bin \ |
9 | test-gtk2 \ | 9 | test-gtk2.bin \ |
10 | test-gtk2-infobar \ | 10 | test-gtk2-infobar.bin \ |
11 | test-hello \ | 11 | test-hello.bin \ |
12 | test-libaudit \ | 12 | test-libaudit.bin \ |
13 | test-libbfd \ | 13 | test-libbfd.bin \ |
14 | test-liberty \ | 14 | test-liberty.bin \ |
15 | test-liberty-z \ | 15 | test-liberty-z.bin \ |
16 | test-cplus-demangle \ | 16 | test-cplus-demangle.bin \ |
17 | test-libelf \ | 17 | test-libelf.bin \ |
18 | test-libelf-getphdrnum \ | 18 | test-libelf-getphdrnum.bin \ |
19 | test-libelf-mmap \ | 19 | test-libelf-mmap.bin \ |
20 | test-libnuma \ | 20 | test-libnuma.bin \ |
21 | test-libperl \ | 21 | test-libperl.bin \ |
22 | test-libpython \ | 22 | test-libpython.bin \ |
23 | test-libpython-version \ | 23 | test-libpython-version.bin \ |
24 | test-libslang \ | 24 | test-libslang.bin \ |
25 | test-libunwind \ | 25 | test-libunwind.bin \ |
26 | test-libunwind-debug-frame \ | 26 | test-libunwind-debug-frame.bin \ |
27 | test-on-exit \ | 27 | test-on-exit.bin \ |
28 | test-stackprotector-all \ | 28 | test-stackprotector-all.bin \ |
29 | test-stackprotector \ | 29 | test-timerfd.bin |
30 | test-timerfd | 30 | |
31 | 31 | CC := $(CROSS_COMPILE)gcc -MD | |
32 | CC := $(CC) -MD | 32 | PKG_CONFIG := $(CROSS_COMPILE)pkg-config |
33 | 33 | ||
34 | all: $(FILES) | 34 | all: $(FILES) |
35 | 35 | ||
36 | BUILD = $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUTPUT)$@ $@.c | 36 | BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) |
37 | 37 | ||
38 | ############################### | 38 | ############################### |
39 | 39 | ||
40 | test-all: | 40 | test-all.bin: |
41 | $(BUILD) -Werror -fstack-protector -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl | 41 | $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl |
42 | 42 | ||
43 | test-hello: | 43 | test-hello.bin: |
44 | $(BUILD) | 44 | $(BUILD) |
45 | 45 | ||
46 | test-stackprotector-all: | 46 | test-stackprotector-all.bin: |
47 | $(BUILD) -Werror -fstack-protector-all | 47 | $(BUILD) -Werror -fstack-protector-all |
48 | 48 | ||
49 | test-stackprotector: | 49 | test-fortify-source.bin: |
50 | $(BUILD) -Werror -fstack-protector -Wstack-protector | ||
51 | |||
52 | test-fortify-source: | ||
53 | $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2 | 50 | $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2 |
54 | 51 | ||
55 | test-bionic: | 52 | test-bionic.bin: |
56 | $(BUILD) | 53 | $(BUILD) |
57 | 54 | ||
58 | test-libelf: | 55 | test-libelf.bin: |
59 | $(BUILD) -lelf | 56 | $(BUILD) -lelf |
60 | 57 | ||
61 | test-glibc: | 58 | test-glibc.bin: |
62 | $(BUILD) | 59 | $(BUILD) |
63 | 60 | ||
64 | test-dwarf: | 61 | test-dwarf.bin: |
65 | $(BUILD) -ldw | 62 | $(BUILD) -ldw |
66 | 63 | ||
67 | test-libelf-mmap: | 64 | test-libelf-mmap.bin: |
68 | $(BUILD) -lelf | 65 | $(BUILD) -lelf |
69 | 66 | ||
70 | test-libelf-getphdrnum: | 67 | test-libelf-getphdrnum.bin: |
71 | $(BUILD) -lelf | 68 | $(BUILD) -lelf |
72 | 69 | ||
73 | test-libnuma: | 70 | test-libnuma.bin: |
74 | $(BUILD) -lnuma | 71 | $(BUILD) -lnuma |
75 | 72 | ||
76 | test-libunwind: | 73 | test-libunwind.bin: |
77 | $(BUILD) $(LIBUNWIND_LIBS) -lelf | 74 | $(BUILD) -lelf |
78 | 75 | ||
79 | test-libunwind-debug-frame: | 76 | test-libunwind-debug-frame.bin: |
80 | $(BUILD) $(LIBUNWIND_LIBS) -lelf | 77 | $(BUILD) -lelf |
81 | 78 | ||
82 | test-libaudit: | 79 | test-libaudit.bin: |
83 | $(BUILD) -laudit | 80 | $(BUILD) -laudit |
84 | 81 | ||
85 | test-libslang: | 82 | test-libslang.bin: |
86 | $(BUILD) -I/usr/include/slang -lslang | 83 | $(BUILD) -I/usr/include/slang -lslang |
87 | 84 | ||
88 | test-gtk2: | 85 | test-gtk2.bin: |
89 | $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) | 86 | $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) |
90 | 87 | ||
91 | test-gtk2-infobar: | 88 | test-gtk2-infobar.bin: |
92 | $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) | 89 | $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) |
93 | 90 | ||
94 | grep-libs = $(filter -l%,$(1)) | 91 | grep-libs = $(filter -l%,$(1)) |
95 | strip-libs = $(filter-out -l%,$(1)) | 92 | strip-libs = $(filter-out -l%,$(1)) |
@@ -100,7 +97,7 @@ PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) | |||
100 | PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` | 97 | PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` |
101 | FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) | 98 | FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) |
102 | 99 | ||
103 | test-libperl: | 100 | test-libperl.bin: |
104 | $(BUILD) $(FLAGS_PERL_EMBED) | 101 | $(BUILD) $(FLAGS_PERL_EMBED) |
105 | 102 | ||
106 | override PYTHON := python | 103 | override PYTHON := python |
@@ -117,31 +114,31 @@ PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) | |||
117 | PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) | 114 | PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) |
118 | FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) | 115 | FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) |
119 | 116 | ||
120 | test-libpython: | 117 | test-libpython.bin: |
121 | $(BUILD) $(FLAGS_PYTHON_EMBED) | 118 | $(BUILD) $(FLAGS_PYTHON_EMBED) |
122 | 119 | ||
123 | test-libpython-version: | 120 | test-libpython-version.bin: |
124 | $(BUILD) $(FLAGS_PYTHON_EMBED) | 121 | $(BUILD) $(FLAGS_PYTHON_EMBED) |
125 | 122 | ||
126 | test-libbfd: | 123 | test-libbfd.bin: |
127 | $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl | 124 | $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl |
128 | 125 | ||
129 | test-liberty: | 126 | test-liberty.bin: |
130 | $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty | 127 | $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty |
131 | 128 | ||
132 | test-liberty-z: | 129 | test-liberty-z.bin: |
133 | $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz | 130 | $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz |
134 | 131 | ||
135 | test-cplus-demangle: | 132 | test-cplus-demangle.bin: |
136 | $(BUILD) -liberty | 133 | $(BUILD) -liberty |
137 | 134 | ||
138 | test-on-exit: | 135 | test-on-exit.bin: |
139 | $(BUILD) | 136 | $(BUILD) |
140 | 137 | ||
141 | test-backtrace: | 138 | test-backtrace.bin: |
142 | $(BUILD) | 139 | $(BUILD) |
143 | 140 | ||
144 | test-timerfd: | 141 | test-timerfd.bin: |
145 | $(BUILD) | 142 | $(BUILD) |
146 | 143 | ||
147 | -include *.d | 144 | -include *.d |
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c index 59e7a705e146..9b8a544155bb 100644 --- a/tools/perf/config/feature-checks/test-all.c +++ b/tools/perf/config/feature-checks/test-all.c | |||
@@ -85,6 +85,10 @@ | |||
85 | # include "test-timerfd.c" | 85 | # include "test-timerfd.c" |
86 | #undef main | 86 | #undef main |
87 | 87 | ||
88 | #define main main_test_stackprotector_all | ||
89 | # include "test-stackprotector-all.c" | ||
90 | #undef main | ||
91 | |||
88 | int main(int argc, char *argv[]) | 92 | int main(int argc, char *argv[]) |
89 | { | 93 | { |
90 | main_test_libpython(); | 94 | main_test_libpython(); |
@@ -106,6 +110,7 @@ int main(int argc, char *argv[]) | |||
106 | main_test_backtrace(); | 110 | main_test_backtrace(); |
107 | main_test_libnuma(); | 111 | main_test_libnuma(); |
108 | main_test_timerfd(); | 112 | main_test_timerfd(); |
113 | main_test_stackprotector_all(); | ||
109 | 114 | ||
110 | return 0; | 115 | return 0; |
111 | } | 116 | } |
diff --git a/tools/perf/config/feature-checks/test-stackprotector.c b/tools/perf/config/feature-checks/test-stackprotector.c deleted file mode 100644 index c9f398d87868..000000000000 --- a/tools/perf/config/feature-checks/test-stackprotector.c +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #include <stdio.h> | ||
2 | |||
3 | int main(void) | ||
4 | { | ||
5 | return puts("hi"); | ||
6 | } | ||
diff --git a/tools/perf/config/feature-checks/test-volatile-register-var.c b/tools/perf/config/feature-checks/test-volatile-register-var.c deleted file mode 100644 index c9f398d87868..000000000000 --- a/tools/perf/config/feature-checks/test-volatile-register-var.c +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #include <stdio.h> | ||
2 | |||
3 | int main(void) | ||
4 | { | ||
5 | return puts("hi"); | ||
6 | } | ||
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak index f168debc5be2..4d985e0f03f5 100644 --- a/tools/perf/config/utilities.mak +++ b/tools/perf/config/utilities.mak | |||
@@ -178,10 +178,3 @@ endef | |||
178 | _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) | 178 | _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) |
179 | _gea_warn = $(warning The path '$(1)' is not executable.) | 179 | _gea_warn = $(warning The path '$(1)' is not executable.) |
180 | _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) | 180 | _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) |
181 | |||
182 | ifneq ($(findstring $(MAKEFLAGS),s),s) | ||
183 | ifneq ($(V),1) | ||
184 | QUIET_CLEAN = @printf ' CLEAN %s\n' $1; | ||
185 | QUIET_INSTALL = @printf ' INSTALL %s\n' $1; | ||
186 | endif | ||
187 | endif | ||
diff --git a/tools/perf/bash_completion b/tools/perf/perf-completion.sh index 62e157db2e2b..496e2abb5482 100644 --- a/tools/perf/bash_completion +++ b/tools/perf/perf-completion.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | # perf completion | 1 | # perf bash and zsh completion |
2 | 2 | ||
3 | # Taken from git.git's completion script. | 3 | # Taken from git.git's completion script. |
4 | __my_reassemble_comp_words_by_ref() | 4 | __my_reassemble_comp_words_by_ref() |
@@ -89,37 +89,117 @@ __ltrim_colon_completions() | |||
89 | fi | 89 | fi |
90 | } | 90 | } |
91 | 91 | ||
92 | type perf &>/dev/null && | 92 | __perfcomp () |
93 | _perf() | ||
94 | { | 93 | { |
95 | local cur words cword prev cmd | 94 | COMPREPLY=( $( compgen -W "$1" -- "$2" ) ) |
95 | } | ||
96 | 96 | ||
97 | COMPREPLY=() | 97 | __perfcomp_colon () |
98 | _get_comp_words_by_ref -n =: cur words cword prev | 98 | { |
99 | __perfcomp "$1" "$2" | ||
100 | __ltrim_colon_completions $cur | ||
101 | } | ||
102 | |||
103 | __perf_main () | ||
104 | { | ||
105 | local cmd | ||
99 | 106 | ||
100 | cmd=${words[0]} | 107 | cmd=${words[0]} |
108 | COMPREPLY=() | ||
101 | 109 | ||
102 | # List perf subcommands or long options | 110 | # List perf subcommands or long options |
103 | if [ $cword -eq 1 ]; then | 111 | if [ $cword -eq 1 ]; then |
104 | if [[ $cur == --* ]]; then | 112 | if [[ $cur == --* ]]; then |
105 | COMPREPLY=( $( compgen -W '--help --version \ | 113 | __perfcomp '--help --version \ |
106 | --exec-path --html-path --paginate --no-pager \ | 114 | --exec-path --html-path --paginate --no-pager \ |
107 | --perf-dir --work-tree --debugfs-dir' -- "$cur" ) ) | 115 | --perf-dir --work-tree --debugfs-dir' -- "$cur" |
108 | else | 116 | else |
109 | cmds=$($cmd --list-cmds) | 117 | cmds=$($cmd --list-cmds) |
110 | COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) | 118 | __perfcomp "$cmds" "$cur" |
111 | fi | 119 | fi |
112 | # List possible events for -e option | 120 | # List possible events for -e option |
113 | elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then | 121 | elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then |
114 | evts=$($cmd list --raw-dump) | 122 | evts=$($cmd list --raw-dump) |
115 | COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) ) | 123 | __perfcomp_colon "$evts" "$cur" |
116 | __ltrim_colon_completions $cur | 124 | # List subcommands for 'perf kvm' |
125 | elif [[ $prev == "kvm" ]]; then | ||
126 | subcmds="top record report diff buildid-list stat" | ||
127 | __perfcomp_colon "$subcmds" "$cur" | ||
117 | # List long option names | 128 | # List long option names |
118 | elif [[ $cur == --* ]]; then | 129 | elif [[ $cur == --* ]]; then |
119 | subcmd=${words[1]} | 130 | subcmd=${words[1]} |
120 | opts=$($cmd $subcmd --list-opts) | 131 | opts=$($cmd $subcmd --list-opts) |
121 | COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) ) | 132 | __perfcomp "$opts" "$cur" |
122 | fi | 133 | fi |
134 | } | ||
135 | |||
136 | if [[ -n ${ZSH_VERSION-} ]]; then | ||
137 | autoload -U +X compinit && compinit | ||
138 | |||
139 | __perfcomp () | ||
140 | { | ||
141 | emulate -L zsh | ||
142 | |||
143 | local c IFS=$' \t\n' | ||
144 | local -a array | ||
145 | |||
146 | for c in ${=1}; do | ||
147 | case $c in | ||
148 | --*=*|*.) ;; | ||
149 | *) c="$c " ;; | ||
150 | esac | ||
151 | array[${#array[@]}+1]="$c" | ||
152 | done | ||
153 | |||
154 | compset -P '*[=:]' | ||
155 | compadd -Q -S '' -a -- array && _ret=0 | ||
156 | } | ||
157 | |||
158 | __perfcomp_colon () | ||
159 | { | ||
160 | emulate -L zsh | ||
161 | |||
162 | local cur_="${2-$cur}" | ||
163 | local c IFS=$' \t\n' | ||
164 | local -a array | ||
165 | |||
166 | if [[ "$cur_" == *:* ]]; then | ||
167 | local colon_word=${cur_%"${cur_##*:}"} | ||
168 | fi | ||
169 | |||
170 | for c in ${=1}; do | ||
171 | case $c in | ||
172 | --*=*|*.) ;; | ||
173 | *) c="$c " ;; | ||
174 | esac | ||
175 | array[$#array+1]=${c#"$colon_word"} | ||
176 | done | ||
177 | |||
178 | compset -P '*[=:]' | ||
179 | compadd -Q -S '' -a -- array && _ret=0 | ||
180 | } | ||
181 | |||
182 | _perf () | ||
183 | { | ||
184 | local _ret=1 cur cword prev | ||
185 | cur=${words[CURRENT]} | ||
186 | prev=${words[CURRENT-1]} | ||
187 | let cword=CURRENT-1 | ||
188 | emulate ksh -c __perf_main | ||
189 | let _ret && _default && _ret=0 | ||
190 | return _ret | ||
191 | } | ||
192 | |||
193 | compdef _perf perf | ||
194 | return | ||
195 | fi | ||
196 | |||
197 | type perf &>/dev/null && | ||
198 | _perf() | ||
199 | { | ||
200 | local cur words cword prev | ||
201 | _get_comp_words_by_ref -n =: cur words cword prev | ||
202 | __perf_main | ||
123 | } && | 203 | } && |
124 | 204 | ||
125 | complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \ | 205 | complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \ |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 8b38b4e80ec2..431798a4110d 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include "util/quote.h" | 13 | #include "util/quote.h" |
14 | #include "util/run-command.h" | 14 | #include "util/run-command.h" |
15 | #include "util/parse-events.h" | 15 | #include "util/parse-events.h" |
16 | #include <lk/debugfs.h> | 16 | #include <api/fs/debugfs.h> |
17 | #include <pthread.h> | 17 | #include <pthread.h> |
18 | 18 | ||
19 | const char perf_usage_string[] = | 19 | const char perf_usage_string[] = |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index b079304bd53d..3c2f213e979d 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -247,13 +247,14 @@ enum perf_call_graph_mode { | |||
247 | CALLCHAIN_DWARF | 247 | CALLCHAIN_DWARF |
248 | }; | 248 | }; |
249 | 249 | ||
250 | struct perf_record_opts { | 250 | struct record_opts { |
251 | struct target target; | 251 | struct target target; |
252 | int call_graph; | 252 | int call_graph; |
253 | bool group; | 253 | bool group; |
254 | bool inherit_stat; | 254 | bool inherit_stat; |
255 | bool no_delay; | 255 | bool no_buffering; |
256 | bool no_inherit; | 256 | bool no_inherit; |
257 | bool no_inherit_set; | ||
257 | bool no_samples; | 258 | bool no_samples; |
258 | bool raw_samples; | 259 | bool raw_samples; |
259 | bool sample_address; | 260 | bool sample_address; |
@@ -268,6 +269,7 @@ struct perf_record_opts { | |||
268 | u64 user_interval; | 269 | u64 user_interval; |
269 | u16 stack_dump_size; | 270 | u16 stack_dump_size; |
270 | bool sample_transaction; | 271 | bool sample_transaction; |
272 | unsigned initial_delay; | ||
271 | }; | 273 | }; |
272 | 274 | ||
273 | #endif | 275 | #endif |
diff --git a/tools/perf/tests/attr/test-record-no-inherit b/tools/perf/tests/attr/test-record-no-inherit index 9079a25cd643..44edcb2edcd5 100644 --- a/tools/perf/tests/attr/test-record-no-inherit +++ b/tools/perf/tests/attr/test-record-no-inherit | |||
@@ -3,5 +3,5 @@ command = record | |||
3 | args = -i kill >/dev/null 2>&1 | 3 | args = -i kill >/dev/null 2>&1 |
4 | 4 | ||
5 | [event:base-record] | 5 | [event:base-record] |
6 | sample_type=259 | 6 | sample_type=263 |
7 | inherit=0 | 7 | inherit=0 |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 85d4919dd623..653a8fe2db95 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -391,7 +391,7 @@ static int do_test_code_reading(bool try_kcore) | |||
391 | struct machines machines; | 391 | struct machines machines; |
392 | struct machine *machine; | 392 | struct machine *machine; |
393 | struct thread *thread; | 393 | struct thread *thread; |
394 | struct perf_record_opts opts = { | 394 | struct record_opts opts = { |
395 | .mmap_pages = UINT_MAX, | 395 | .mmap_pages = UINT_MAX, |
396 | .user_freq = UINT_MAX, | 396 | .user_freq = UINT_MAX, |
397 | .user_interval = ULLONG_MAX, | 397 | .user_interval = ULLONG_MAX, |
@@ -540,14 +540,11 @@ static int do_test_code_reading(bool try_kcore) | |||
540 | err = TEST_CODE_READING_OK; | 540 | err = TEST_CODE_READING_OK; |
541 | out_err: | 541 | out_err: |
542 | if (evlist) { | 542 | if (evlist) { |
543 | perf_evlist__munmap(evlist); | ||
544 | perf_evlist__close(evlist); | ||
545 | perf_evlist__delete(evlist); | 543 | perf_evlist__delete(evlist); |
546 | } | 544 | } else { |
547 | if (cpus) | ||
548 | cpu_map__delete(cpus); | 545 | cpu_map__delete(cpus); |
549 | if (threads) | ||
550 | thread_map__delete(threads); | 546 | thread_map__delete(threads); |
547 | } | ||
551 | machines__destroy_kernel_maps(&machines); | 548 | machines__destroy_kernel_maps(&machines); |
552 | machine__delete_threads(machine); | 549 | machine__delete_threads(machine); |
553 | machines__exit(&machines); | 550 | machines__exit(&machines); |
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c index 0197bda9c461..465cdbc345cf 100644 --- a/tools/perf/tests/evsel-roundtrip-name.c +++ b/tools/perf/tests/evsel-roundtrip-name.c | |||
@@ -79,7 +79,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names) | |||
79 | } | 79 | } |
80 | 80 | ||
81 | err = 0; | 81 | err = 0; |
82 | list_for_each_entry(evsel, &evlist->entries, node) { | 82 | evlist__for_each(evlist, evsel) { |
83 | if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { | 83 | if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { |
84 | --err; | 84 | --err; |
85 | pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); | 85 | pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); |
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 173bf42cc03e..2b6519e0e36f 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c | |||
@@ -208,7 +208,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
208 | * However the second evsel also has a collapsed entry for | 208 | * However the second evsel also has a collapsed entry for |
209 | * "bash [libc] malloc" so total 9 entries will be in the tree. | 209 | * "bash [libc] malloc" so total 9 entries will be in the tree. |
210 | */ | 210 | */ |
211 | list_for_each_entry(evsel, &evlist->entries, node) { | 211 | evlist__for_each(evlist, evsel) { |
212 | for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { | 212 | for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { |
213 | const union perf_event event = { | 213 | const union perf_event event = { |
214 | .header = { | 214 | .header = { |
@@ -466,7 +466,7 @@ int test__hists_link(void) | |||
466 | if (err < 0) | 466 | if (err < 0) |
467 | goto out; | 467 | goto out; |
468 | 468 | ||
469 | list_for_each_entry(evsel, &evlist->entries, node) { | 469 | evlist__for_each(evlist, evsel) { |
470 | hists__collapse_resort(&evsel->hists, NULL); | 470 | hists__collapse_resort(&evsel->hists, NULL); |
471 | 471 | ||
472 | if (verbose > 2) | 472 | if (verbose > 2) |
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 376c35608534..497957f269d8 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c | |||
@@ -51,7 +51,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm) | |||
51 | */ | 51 | */ |
52 | int test__keep_tracking(void) | 52 | int test__keep_tracking(void) |
53 | { | 53 | { |
54 | struct perf_record_opts opts = { | 54 | struct record_opts opts = { |
55 | .mmap_pages = UINT_MAX, | 55 | .mmap_pages = UINT_MAX, |
56 | .user_freq = UINT_MAX, | 56 | .user_freq = UINT_MAX, |
57 | .user_interval = ULLONG_MAX, | 57 | .user_interval = ULLONG_MAX, |
@@ -142,14 +142,11 @@ int test__keep_tracking(void) | |||
142 | out_err: | 142 | out_err: |
143 | if (evlist) { | 143 | if (evlist) { |
144 | perf_evlist__disable(evlist); | 144 | perf_evlist__disable(evlist); |
145 | perf_evlist__munmap(evlist); | ||
146 | perf_evlist__close(evlist); | ||
147 | perf_evlist__delete(evlist); | 145 | perf_evlist__delete(evlist); |
148 | } | 146 | } else { |
149 | if (cpus) | ||
150 | cpu_map__delete(cpus); | 147 | cpu_map__delete(cpus); |
151 | if (threads) | ||
152 | thread_map__delete(threads); | 148 | thread_map__delete(threads); |
149 | } | ||
153 | 150 | ||
154 | return err; | 151 | return err; |
155 | } | 152 | } |
diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 2ca0abf1b2b6..00544b8b644b 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make | |||
@@ -1,6 +1,16 @@ | |||
1 | PERF := . | 1 | PERF := . |
2 | MK := Makefile | 2 | MK := Makefile |
3 | 3 | ||
4 | include config/Makefile.arch | ||
5 | |||
6 | # FIXME looks like x86 is the only arch running tests ;-) | ||
7 | # we need some IS_(32/64) flag to make this generic | ||
8 | ifeq ($(IS_X86_64),1) | ||
9 | lib = lib64 | ||
10 | else | ||
11 | lib = lib | ||
12 | endif | ||
13 | |||
4 | has = $(shell which $1 2>/dev/null) | 14 | has = $(shell which $1 2>/dev/null) |
5 | 15 | ||
6 | # standard single make variable specified | 16 | # standard single make variable specified |
@@ -106,10 +116,36 @@ test_make_python_perf_so := test -f $(PERF)/python/perf.so | |||
106 | test_make_perf_o := test -f $(PERF)/perf.o | 116 | test_make_perf_o := test -f $(PERF)/perf.o |
107 | test_make_util_map_o := test -f $(PERF)/util/map.o | 117 | test_make_util_map_o := test -f $(PERF)/util/map.o |
108 | 118 | ||
109 | test_make_install := test -x $$TMP_DEST/bin/perf | 119 | define test_dest_files |
110 | test_make_install_O := $(test_make_install) | 120 | for file in $(1); do \ |
111 | test_make_install_bin := $(test_make_install) | 121 | if [ ! -x $$TMP_DEST/$$file ]; then \ |
112 | test_make_install_bin_O := $(test_make_install) | 122 | echo " failed to find: $$file"; \ |
123 | fi \ | ||
124 | done | ||
125 | endef | ||
126 | |||
127 | installed_files_bin := bin/perf | ||
128 | installed_files_bin += etc/bash_completion.d/perf | ||
129 | installed_files_bin += libexec/perf-core/perf-archive | ||
130 | |||
131 | installed_files_plugins := $(lib)/traceevent/plugins/plugin_cfg80211.so | ||
132 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_scsi.so | ||
133 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_xen.so | ||
134 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_function.so | ||
135 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_sched_switch.so | ||
136 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_mac80211.so | ||
137 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_kvm.so | ||
138 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_kmem.so | ||
139 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_hrtimer.so | ||
140 | installed_files_plugins += $(lib)/traceevent/plugins/plugin_jbd2.so | ||
141 | |||
142 | installed_files_all := $(installed_files_bin) | ||
143 | installed_files_all += $(installed_files_plugins) | ||
144 | |||
145 | test_make_install := $(call test_dest_files,$(installed_files_all)) | ||
146 | test_make_install_O := $(call test_dest_files,$(installed_files_all)) | ||
147 | test_make_install_bin := $(call test_dest_files,$(installed_files_bin)) | ||
148 | test_make_install_bin_O := $(call test_dest_files,$(installed_files_bin)) | ||
113 | 149 | ||
114 | # FIXME nothing gets installed | 150 | # FIXME nothing gets installed |
115 | test_make_install_man := test -f $$TMP_DEST/share/man/man1/perf.1 | 151 | test_make_install_man := test -f $$TMP_DEST/share/man/man1/perf.1 |
@@ -162,7 +198,7 @@ $(run): | |||
162 | cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \ | 198 | cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \ |
163 | echo "- $@: $$cmd" && echo $$cmd > $@ && \ | 199 | echo "- $@: $$cmd" && echo $$cmd > $@ && \ |
164 | ( eval $$cmd ) >> $@ 2>&1; \ | 200 | ( eval $$cmd ) >> $@ 2>&1; \ |
165 | echo " test: $(call test,$@)"; \ | 201 | echo " test: $(call test,$@)" >> $@ 2>&1; \ |
166 | $(call test,$@) && \ | 202 | $(call test,$@) && \ |
167 | rm -f $@ \ | 203 | rm -f $@ \ |
168 | rm -rf $$TMP_DEST | 204 | rm -rf $$TMP_DEST |
@@ -174,16 +210,22 @@ $(run_O): | |||
174 | cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ | 210 | cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ |
175 | echo "- $@: $$cmd" && echo $$cmd > $@ && \ | 211 | echo "- $@: $$cmd" && echo $$cmd > $@ && \ |
176 | ( eval $$cmd ) >> $@ 2>&1 && \ | 212 | ( eval $$cmd ) >> $@ 2>&1 && \ |
177 | echo " test: $(call test_O,$@)"; \ | 213 | echo " test: $(call test_O,$@)" >> $@ 2>&1; \ |
178 | $(call test_O,$@) && \ | 214 | $(call test_O,$@) && \ |
179 | rm -f $@ && \ | 215 | rm -f $@ && \ |
180 | rm -rf $$TMP_O \ | 216 | rm -rf $$TMP_O \ |
181 | rm -rf $$TMP_DEST | 217 | rm -rf $$TMP_DEST |
182 | 218 | ||
183 | all: $(run) $(run_O) | 219 | tarpkg: |
220 | @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \ | ||
221 | echo "- $@: $$cmd" && echo $$cmd > $@ && \ | ||
222 | ( eval $$cmd ) >> $@ 2>&1 | ||
223 | |||
224 | |||
225 | all: $(run) $(run_O) tarpkg | ||
184 | @echo OK | 226 | @echo OK |
185 | 227 | ||
186 | out: $(run_O) | 228 | out: $(run_O) |
187 | @echo OK | 229 | @echo OK |
188 | 230 | ||
189 | .PHONY: all $(run) $(run_O) clean | 231 | .PHONY: all $(run) $(run_O) tarpkg clean |
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index d64ab79c6d35..142263492f6f 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c | |||
@@ -68,7 +68,7 @@ int test__basic_mmap(void) | |||
68 | evsels[i] = perf_evsel__newtp("syscalls", name); | 68 | evsels[i] = perf_evsel__newtp("syscalls", name); |
69 | if (evsels[i] == NULL) { | 69 | if (evsels[i] == NULL) { |
70 | pr_debug("perf_evsel__new\n"); | 70 | pr_debug("perf_evsel__new\n"); |
71 | goto out_free_evlist; | 71 | goto out_delete_evlist; |
72 | } | 72 | } |
73 | 73 | ||
74 | evsels[i]->attr.wakeup_events = 1; | 74 | evsels[i]->attr.wakeup_events = 1; |
@@ -80,7 +80,7 @@ int test__basic_mmap(void) | |||
80 | pr_debug("failed to open counter: %s, " | 80 | pr_debug("failed to open counter: %s, " |
81 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | 81 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", |
82 | strerror(errno)); | 82 | strerror(errno)); |
83 | goto out_close_fd; | 83 | goto out_delete_evlist; |
84 | } | 84 | } |
85 | 85 | ||
86 | nr_events[i] = 0; | 86 | nr_events[i] = 0; |
@@ -90,7 +90,7 @@ int test__basic_mmap(void) | |||
90 | if (perf_evlist__mmap(evlist, 128, true) < 0) { | 90 | if (perf_evlist__mmap(evlist, 128, true) < 0) { |
91 | pr_debug("failed to mmap events: %d (%s)\n", errno, | 91 | pr_debug("failed to mmap events: %d (%s)\n", errno, |
92 | strerror(errno)); | 92 | strerror(errno)); |
93 | goto out_close_fd; | 93 | goto out_delete_evlist; |
94 | } | 94 | } |
95 | 95 | ||
96 | for (i = 0; i < nsyscalls; ++i) | 96 | for (i = 0; i < nsyscalls; ++i) |
@@ -105,13 +105,13 @@ int test__basic_mmap(void) | |||
105 | if (event->header.type != PERF_RECORD_SAMPLE) { | 105 | if (event->header.type != PERF_RECORD_SAMPLE) { |
106 | pr_debug("unexpected %s event\n", | 106 | pr_debug("unexpected %s event\n", |
107 | perf_event__name(event->header.type)); | 107 | perf_event__name(event->header.type)); |
108 | goto out_munmap; | 108 | goto out_delete_evlist; |
109 | } | 109 | } |
110 | 110 | ||
111 | err = perf_evlist__parse_sample(evlist, event, &sample); | 111 | err = perf_evlist__parse_sample(evlist, event, &sample); |
112 | if (err) { | 112 | if (err) { |
113 | pr_err("Can't parse sample, err = %d\n", err); | 113 | pr_err("Can't parse sample, err = %d\n", err); |
114 | goto out_munmap; | 114 | goto out_delete_evlist; |
115 | } | 115 | } |
116 | 116 | ||
117 | err = -1; | 117 | err = -1; |
@@ -119,30 +119,27 @@ int test__basic_mmap(void) | |||
119 | if (evsel == NULL) { | 119 | if (evsel == NULL) { |
120 | pr_debug("event with id %" PRIu64 | 120 | pr_debug("event with id %" PRIu64 |
121 | " doesn't map to an evsel\n", sample.id); | 121 | " doesn't map to an evsel\n", sample.id); |
122 | goto out_munmap; | 122 | goto out_delete_evlist; |
123 | } | 123 | } |
124 | nr_events[evsel->idx]++; | 124 | nr_events[evsel->idx]++; |
125 | perf_evlist__mmap_consume(evlist, 0); | 125 | perf_evlist__mmap_consume(evlist, 0); |
126 | } | 126 | } |
127 | 127 | ||
128 | err = 0; | 128 | err = 0; |
129 | list_for_each_entry(evsel, &evlist->entries, node) { | 129 | evlist__for_each(evlist, evsel) { |
130 | if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { | 130 | if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { |
131 | pr_debug("expected %d %s events, got %d\n", | 131 | pr_debug("expected %d %s events, got %d\n", |
132 | expected_nr_events[evsel->idx], | 132 | expected_nr_events[evsel->idx], |
133 | perf_evsel__name(evsel), nr_events[evsel->idx]); | 133 | perf_evsel__name(evsel), nr_events[evsel->idx]); |
134 | err = -1; | 134 | err = -1; |
135 | goto out_munmap; | 135 | goto out_delete_evlist; |
136 | } | 136 | } |
137 | } | 137 | } |
138 | 138 | ||
139 | out_munmap: | 139 | out_delete_evlist: |
140 | perf_evlist__munmap(evlist); | ||
141 | out_close_fd: | ||
142 | for (i = 0; i < nsyscalls; ++i) | ||
143 | perf_evsel__close_fd(evsels[i], 1, threads->nr); | ||
144 | out_free_evlist: | ||
145 | perf_evlist__delete(evlist); | 140 | perf_evlist__delete(evlist); |
141 | cpus = NULL; | ||
142 | threads = NULL; | ||
146 | out_free_cpus: | 143 | out_free_cpus: |
147 | cpu_map__delete(cpus); | 144 | cpu_map__delete(cpus); |
148 | out_free_threads: | 145 | out_free_threads: |
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c index 41cc0badb74b..c505ef2af245 100644 --- a/tools/perf/tests/open-syscall-tp-fields.c +++ b/tools/perf/tests/open-syscall-tp-fields.c | |||
@@ -6,15 +6,15 @@ | |||
6 | 6 | ||
7 | int test__syscall_open_tp_fields(void) | 7 | int test__syscall_open_tp_fields(void) |
8 | { | 8 | { |
9 | struct perf_record_opts opts = { | 9 | struct record_opts opts = { |
10 | .target = { | 10 | .target = { |
11 | .uid = UINT_MAX, | 11 | .uid = UINT_MAX, |
12 | .uses_mmap = true, | 12 | .uses_mmap = true, |
13 | }, | 13 | }, |
14 | .no_delay = true, | 14 | .no_buffering = true, |
15 | .freq = 1, | 15 | .freq = 1, |
16 | .mmap_pages = 256, | 16 | .mmap_pages = 256, |
17 | .raw_samples = true, | 17 | .raw_samples = true, |
18 | }; | 18 | }; |
19 | const char *filename = "/etc/passwd"; | 19 | const char *filename = "/etc/passwd"; |
20 | int flags = O_RDONLY | O_DIRECTORY; | 20 | int flags = O_RDONLY | O_DIRECTORY; |
@@ -48,13 +48,13 @@ int test__syscall_open_tp_fields(void) | |||
48 | err = perf_evlist__open(evlist); | 48 | err = perf_evlist__open(evlist); |
49 | if (err < 0) { | 49 | if (err < 0) { |
50 | pr_debug("perf_evlist__open: %s\n", strerror(errno)); | 50 | pr_debug("perf_evlist__open: %s\n", strerror(errno)); |
51 | goto out_delete_maps; | 51 | goto out_delete_evlist; |
52 | } | 52 | } |
53 | 53 | ||
54 | err = perf_evlist__mmap(evlist, UINT_MAX, false); | 54 | err = perf_evlist__mmap(evlist, UINT_MAX, false); |
55 | if (err < 0) { | 55 | if (err < 0) { |
56 | pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); | 56 | pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); |
57 | goto out_close_evlist; | 57 | goto out_delete_evlist; |
58 | } | 58 | } |
59 | 59 | ||
60 | perf_evlist__enable(evlist); | 60 | perf_evlist__enable(evlist); |
@@ -85,7 +85,7 @@ int test__syscall_open_tp_fields(void) | |||
85 | err = perf_evsel__parse_sample(evsel, event, &sample); | 85 | err = perf_evsel__parse_sample(evsel, event, &sample); |
86 | if (err) { | 86 | if (err) { |
87 | pr_err("Can't parse sample, err = %d\n", err); | 87 | pr_err("Can't parse sample, err = %d\n", err); |
88 | goto out_munmap; | 88 | goto out_delete_evlist; |
89 | } | 89 | } |
90 | 90 | ||
91 | tp_flags = perf_evsel__intval(evsel, &sample, "flags"); | 91 | tp_flags = perf_evsel__intval(evsel, &sample, "flags"); |
@@ -93,7 +93,7 @@ int test__syscall_open_tp_fields(void) | |||
93 | if (flags != tp_flags) { | 93 | if (flags != tp_flags) { |
94 | pr_debug("%s: Expected flags=%#x, got %#x\n", | 94 | pr_debug("%s: Expected flags=%#x, got %#x\n", |
95 | __func__, flags, tp_flags); | 95 | __func__, flags, tp_flags); |
96 | goto out_munmap; | 96 | goto out_delete_evlist; |
97 | } | 97 | } |
98 | 98 | ||
99 | goto out_ok; | 99 | goto out_ok; |
@@ -105,17 +105,11 @@ int test__syscall_open_tp_fields(void) | |||
105 | 105 | ||
106 | if (++nr_polls > 5) { | 106 | if (++nr_polls > 5) { |
107 | pr_debug("%s: no events!\n", __func__); | 107 | pr_debug("%s: no events!\n", __func__); |
108 | goto out_munmap; | 108 | goto out_delete_evlist; |
109 | } | 109 | } |
110 | } | 110 | } |
111 | out_ok: | 111 | out_ok: |
112 | err = 0; | 112 | err = 0; |
113 | out_munmap: | ||
114 | perf_evlist__munmap(evlist); | ||
115 | out_close_evlist: | ||
116 | perf_evlist__close(evlist); | ||
117 | out_delete_maps: | ||
118 | perf_evlist__delete_maps(evlist); | ||
119 | out_delete_evlist: | 113 | out_delete_evlist: |
120 | perf_evlist__delete(evlist); | 114 | perf_evlist__delete(evlist); |
121 | out: | 115 | out: |
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 3cbd10496087..4db0ae617d70 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c | |||
@@ -3,7 +3,7 @@ | |||
3 | #include "evsel.h" | 3 | #include "evsel.h" |
4 | #include "evlist.h" | 4 | #include "evlist.h" |
5 | #include "fs.h" | 5 | #include "fs.h" |
6 | #include <lk/debugfs.h> | 6 | #include <api/fs/debugfs.h> |
7 | #include "tests.h" | 7 | #include "tests.h" |
8 | #include <linux/hw_breakpoint.h> | 8 | #include <linux/hw_breakpoint.h> |
9 | 9 | ||
@@ -30,7 +30,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) | |||
30 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); | 30 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); |
31 | TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); | 31 | TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); |
32 | 32 | ||
33 | list_for_each_entry(evsel, &evlist->entries, node) { | 33 | evlist__for_each(evlist, evsel) { |
34 | TEST_ASSERT_VAL("wrong type", | 34 | TEST_ASSERT_VAL("wrong type", |
35 | PERF_TYPE_TRACEPOINT == evsel->attr.type); | 35 | PERF_TYPE_TRACEPOINT == evsel->attr.type); |
36 | TEST_ASSERT_VAL("wrong sample_type", | 36 | TEST_ASSERT_VAL("wrong sample_type", |
@@ -201,7 +201,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist) | |||
201 | 201 | ||
202 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); | 202 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); |
203 | 203 | ||
204 | list_for_each_entry(evsel, &evlist->entries, node) { | 204 | evlist__for_each(evlist, evsel) { |
205 | TEST_ASSERT_VAL("wrong exclude_user", | 205 | TEST_ASSERT_VAL("wrong exclude_user", |
206 | !evsel->attr.exclude_user); | 206 | !evsel->attr.exclude_user); |
207 | TEST_ASSERT_VAL("wrong exclude_kernel", | 207 | TEST_ASSERT_VAL("wrong exclude_kernel", |
@@ -1385,10 +1385,10 @@ static int test_event(struct evlist_test *e) | |||
1385 | if (ret) { | 1385 | if (ret) { |
1386 | pr_debug("failed to parse event '%s', err %d\n", | 1386 | pr_debug("failed to parse event '%s', err %d\n", |
1387 | e->name, ret); | 1387 | e->name, ret); |
1388 | return ret; | 1388 | } else { |
1389 | ret = e->check(evlist); | ||
1389 | } | 1390 | } |
1390 | 1391 | ||
1391 | ret = e->check(evlist); | ||
1392 | perf_evlist__delete(evlist); | 1392 | perf_evlist__delete(evlist); |
1393 | 1393 | ||
1394 | return ret; | 1394 | return ret; |
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 93a62b06c3af..aca1a83dd13a 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c | |||
@@ -34,14 +34,14 @@ realloc: | |||
34 | 34 | ||
35 | int test__PERF_RECORD(void) | 35 | int test__PERF_RECORD(void) |
36 | { | 36 | { |
37 | struct perf_record_opts opts = { | 37 | struct record_opts opts = { |
38 | .target = { | 38 | .target = { |
39 | .uid = UINT_MAX, | 39 | .uid = UINT_MAX, |
40 | .uses_mmap = true, | 40 | .uses_mmap = true, |
41 | }, | 41 | }, |
42 | .no_delay = true, | 42 | .no_buffering = true, |
43 | .freq = 10, | 43 | .freq = 10, |
44 | .mmap_pages = 256, | 44 | .mmap_pages = 256, |
45 | }; | 45 | }; |
46 | cpu_set_t cpu_mask; | 46 | cpu_set_t cpu_mask; |
47 | size_t cpu_mask_size = sizeof(cpu_mask); | 47 | size_t cpu_mask_size = sizeof(cpu_mask); |
@@ -83,11 +83,10 @@ int test__PERF_RECORD(void) | |||
83 | * so that we have time to open the evlist (calling sys_perf_event_open | 83 | * so that we have time to open the evlist (calling sys_perf_event_open |
84 | * on all the fds) and then mmap them. | 84 | * on all the fds) and then mmap them. |
85 | */ | 85 | */ |
86 | err = perf_evlist__prepare_workload(evlist, &opts.target, argv, | 86 | err = perf_evlist__prepare_workload(evlist, &opts.target, argv, false, NULL); |
87 | false, false); | ||
88 | if (err < 0) { | 87 | if (err < 0) { |
89 | pr_debug("Couldn't run the workload!\n"); | 88 | pr_debug("Couldn't run the workload!\n"); |
90 | goto out_delete_maps; | 89 | goto out_delete_evlist; |
91 | } | 90 | } |
92 | 91 | ||
93 | /* | 92 | /* |
@@ -102,7 +101,7 @@ int test__PERF_RECORD(void) | |||
102 | err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); | 101 | err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); |
103 | if (err < 0) { | 102 | if (err < 0) { |
104 | pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); | 103 | pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); |
105 | goto out_delete_maps; | 104 | goto out_delete_evlist; |
106 | } | 105 | } |
107 | 106 | ||
108 | cpu = err; | 107 | cpu = err; |
@@ -112,7 +111,7 @@ int test__PERF_RECORD(void) | |||
112 | */ | 111 | */ |
113 | if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { | 112 | if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { |
114 | pr_debug("sched_setaffinity: %s\n", strerror(errno)); | 113 | pr_debug("sched_setaffinity: %s\n", strerror(errno)); |
115 | goto out_delete_maps; | 114 | goto out_delete_evlist; |
116 | } | 115 | } |
117 | 116 | ||
118 | /* | 117 | /* |
@@ -122,7 +121,7 @@ int test__PERF_RECORD(void) | |||
122 | err = perf_evlist__open(evlist); | 121 | err = perf_evlist__open(evlist); |
123 | if (err < 0) { | 122 | if (err < 0) { |
124 | pr_debug("perf_evlist__open: %s\n", strerror(errno)); | 123 | pr_debug("perf_evlist__open: %s\n", strerror(errno)); |
125 | goto out_delete_maps; | 124 | goto out_delete_evlist; |
126 | } | 125 | } |
127 | 126 | ||
128 | /* | 127 | /* |
@@ -133,7 +132,7 @@ int test__PERF_RECORD(void) | |||
133 | err = perf_evlist__mmap(evlist, opts.mmap_pages, false); | 132 | err = perf_evlist__mmap(evlist, opts.mmap_pages, false); |
134 | if (err < 0) { | 133 | if (err < 0) { |
135 | pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); | 134 | pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); |
136 | goto out_close_evlist; | 135 | goto out_delete_evlist; |
137 | } | 136 | } |
138 | 137 | ||
139 | /* | 138 | /* |
@@ -166,7 +165,7 @@ int test__PERF_RECORD(void) | |||
166 | if (verbose) | 165 | if (verbose) |
167 | perf_event__fprintf(event, stderr); | 166 | perf_event__fprintf(event, stderr); |
168 | pr_debug("Couldn't parse sample\n"); | 167 | pr_debug("Couldn't parse sample\n"); |
169 | goto out_err; | 168 | goto out_delete_evlist; |
170 | } | 169 | } |
171 | 170 | ||
172 | if (verbose) { | 171 | if (verbose) { |
@@ -303,12 +302,6 @@ found_exit: | |||
303 | pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]"); | 302 | pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]"); |
304 | ++errs; | 303 | ++errs; |
305 | } | 304 | } |
306 | out_err: | ||
307 | perf_evlist__munmap(evlist); | ||
308 | out_close_evlist: | ||
309 | perf_evlist__close(evlist); | ||
310 | out_delete_maps: | ||
311 | perf_evlist__delete_maps(evlist); | ||
312 | out_delete_evlist: | 305 | out_delete_evlist: |
313 | perf_evlist__delete(evlist); | 306 | perf_evlist__delete(evlist); |
314 | out: | 307 | out: |
diff --git a/tools/perf/tests/perf-targz-src-pkg b/tools/perf/tests/perf-targz-src-pkg new file mode 100755 index 000000000000..238aa3927c71 --- /dev/null +++ b/tools/perf/tests/perf-targz-src-pkg | |||
@@ -0,0 +1,21 @@ | |||
1 | #!/bin/sh | ||
2 | # Test one of the main kernel Makefile targets to generate a perf sources tarball | ||
3 | # suitable for build outside the full kernel sources. | ||
4 | # | ||
5 | # This is to test that the tools/perf/MANIFEST file lists all the files needed to | ||
6 | # be in such tarball, which sometimes gets broken when we move files around, | ||
7 | # like when we made some files that were in tools/perf/ available to other tools/ | ||
8 | # codebases by moving it to tools/include/, etc. | ||
9 | |||
10 | PERF=$1 | ||
11 | cd ${PERF}/../.. | ||
12 | make perf-targz-src-pkg > /dev/null | ||
13 | TARBALL=$(ls -rt perf-*.tar.gz) | ||
14 | TMP_DEST=$(mktemp -d) | ||
15 | tar xf ${TARBALL} -C $TMP_DEST | ||
16 | rm -f ${TARBALL} | ||
17 | cd - > /dev/null | ||
18 | make -C $TMP_DEST/perf*/tools/perf > /dev/null 2>&1 | ||
19 | RC=$? | ||
20 | rm -rf ${TMP_DEST} | ||
21 | exit $RC | ||
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c index 4ca1b938f6a6..47146d388dbf 100644 --- a/tools/perf/tests/perf-time-to-tsc.c +++ b/tools/perf/tests/perf-time-to-tsc.c | |||
@@ -46,7 +46,7 @@ static u64 rdtsc(void) | |||
46 | */ | 46 | */ |
47 | int test__perf_time_to_tsc(void) | 47 | int test__perf_time_to_tsc(void) |
48 | { | 48 | { |
49 | struct perf_record_opts opts = { | 49 | struct record_opts opts = { |
50 | .mmap_pages = UINT_MAX, | 50 | .mmap_pages = UINT_MAX, |
51 | .user_freq = UINT_MAX, | 51 | .user_freq = UINT_MAX, |
52 | .user_interval = ULLONG_MAX, | 52 | .user_interval = ULLONG_MAX, |
@@ -166,14 +166,8 @@ next_event: | |||
166 | out_err: | 166 | out_err: |
167 | if (evlist) { | 167 | if (evlist) { |
168 | perf_evlist__disable(evlist); | 168 | perf_evlist__disable(evlist); |
169 | perf_evlist__munmap(evlist); | ||
170 | perf_evlist__close(evlist); | ||
171 | perf_evlist__delete(evlist); | 169 | perf_evlist__delete(evlist); |
172 | } | 170 | } |
173 | if (cpus) | ||
174 | cpu_map__delete(cpus); | ||
175 | if (threads) | ||
176 | thread_map__delete(threads); | ||
177 | 171 | ||
178 | return err; | 172 | return err; |
179 | } | 173 | } |
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 6664a7cd828c..983d6b8562a8 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c | |||
@@ -45,7 +45,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
45 | evsel = perf_evsel__new(&attr); | 45 | evsel = perf_evsel__new(&attr); |
46 | if (evsel == NULL) { | 46 | if (evsel == NULL) { |
47 | pr_debug("perf_evsel__new\n"); | 47 | pr_debug("perf_evsel__new\n"); |
48 | goto out_free_evlist; | 48 | goto out_delete_evlist; |
49 | } | 49 | } |
50 | perf_evlist__add(evlist, evsel); | 50 | perf_evlist__add(evlist, evsel); |
51 | 51 | ||
@@ -54,7 +54,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
54 | if (!evlist->cpus || !evlist->threads) { | 54 | if (!evlist->cpus || !evlist->threads) { |
55 | err = -ENOMEM; | 55 | err = -ENOMEM; |
56 | pr_debug("Not enough memory to create thread/cpu maps\n"); | 56 | pr_debug("Not enough memory to create thread/cpu maps\n"); |
57 | goto out_delete_maps; | 57 | goto out_delete_evlist; |
58 | } | 58 | } |
59 | 59 | ||
60 | if (perf_evlist__open(evlist)) { | 60 | if (perf_evlist__open(evlist)) { |
@@ -63,14 +63,14 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
63 | err = -errno; | 63 | err = -errno; |
64 | pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", | 64 | pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", |
65 | strerror(errno), knob, (u64)attr.sample_freq); | 65 | strerror(errno), knob, (u64)attr.sample_freq); |
66 | goto out_delete_maps; | 66 | goto out_delete_evlist; |
67 | } | 67 | } |
68 | 68 | ||
69 | err = perf_evlist__mmap(evlist, 128, true); | 69 | err = perf_evlist__mmap(evlist, 128, true); |
70 | if (err < 0) { | 70 | if (err < 0) { |
71 | pr_debug("failed to mmap event: %d (%s)\n", errno, | 71 | pr_debug("failed to mmap event: %d (%s)\n", errno, |
72 | strerror(errno)); | 72 | strerror(errno)); |
73 | goto out_close_evlist; | 73 | goto out_delete_evlist; |
74 | } | 74 | } |
75 | 75 | ||
76 | perf_evlist__enable(evlist); | 76 | perf_evlist__enable(evlist); |
@@ -90,7 +90,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
90 | err = perf_evlist__parse_sample(evlist, event, &sample); | 90 | err = perf_evlist__parse_sample(evlist, event, &sample); |
91 | if (err < 0) { | 91 | if (err < 0) { |
92 | pr_debug("Error during parse sample\n"); | 92 | pr_debug("Error during parse sample\n"); |
93 | goto out_unmap_evlist; | 93 | goto out_delete_evlist; |
94 | } | 94 | } |
95 | 95 | ||
96 | total_periods += sample.period; | 96 | total_periods += sample.period; |
@@ -105,13 +105,7 @@ next_event: | |||
105 | err = -1; | 105 | err = -1; |
106 | } | 106 | } |
107 | 107 | ||
108 | out_unmap_evlist: | 108 | out_delete_evlist: |
109 | perf_evlist__munmap(evlist); | ||
110 | out_close_evlist: | ||
111 | perf_evlist__close(evlist); | ||
112 | out_delete_maps: | ||
113 | perf_evlist__delete_maps(evlist); | ||
114 | out_free_evlist: | ||
115 | perf_evlist__delete(evlist); | 109 | perf_evlist__delete(evlist); |
116 | return err; | 110 | return err; |
117 | } | 111 | } |
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index d09ab579119e..5ff3db318f12 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c | |||
@@ -9,12 +9,21 @@ | |||
9 | static int exited; | 9 | static int exited; |
10 | static int nr_exit; | 10 | static int nr_exit; |
11 | 11 | ||
12 | static void sig_handler(int sig) | 12 | static void sig_handler(int sig __maybe_unused) |
13 | { | 13 | { |
14 | exited = 1; | 14 | exited = 1; |
15 | } | ||
15 | 16 | ||
16 | if (sig == SIGUSR1) | 17 | /* |
17 | nr_exit = -1; | 18 | * perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since |
19 | * we asked by setting its exec_error to this handler. | ||
20 | */ | ||
21 | static void workload_exec_failed_signal(int signo __maybe_unused, | ||
22 | siginfo_t *info __maybe_unused, | ||
23 | void *ucontext __maybe_unused) | ||
24 | { | ||
25 | exited = 1; | ||
26 | nr_exit = -1; | ||
18 | } | 27 | } |
19 | 28 | ||
20 | /* | 29 | /* |
@@ -35,7 +44,6 @@ int test__task_exit(void) | |||
35 | const char *argv[] = { "true", NULL }; | 44 | const char *argv[] = { "true", NULL }; |
36 | 45 | ||
37 | signal(SIGCHLD, sig_handler); | 46 | signal(SIGCHLD, sig_handler); |
38 | signal(SIGUSR1, sig_handler); | ||
39 | 47 | ||
40 | evlist = perf_evlist__new_default(); | 48 | evlist = perf_evlist__new_default(); |
41 | if (evlist == NULL) { | 49 | if (evlist == NULL) { |
@@ -54,13 +62,14 @@ int test__task_exit(void) | |||
54 | if (!evlist->cpus || !evlist->threads) { | 62 | if (!evlist->cpus || !evlist->threads) { |
55 | err = -ENOMEM; | 63 | err = -ENOMEM; |
56 | pr_debug("Not enough memory to create thread/cpu maps\n"); | 64 | pr_debug("Not enough memory to create thread/cpu maps\n"); |
57 | goto out_delete_maps; | 65 | goto out_delete_evlist; |
58 | } | 66 | } |
59 | 67 | ||
60 | err = perf_evlist__prepare_workload(evlist, &target, argv, false, true); | 68 | err = perf_evlist__prepare_workload(evlist, &target, argv, false, |
69 | workload_exec_failed_signal); | ||
61 | if (err < 0) { | 70 | if (err < 0) { |
62 | pr_debug("Couldn't run the workload!\n"); | 71 | pr_debug("Couldn't run the workload!\n"); |
63 | goto out_delete_maps; | 72 | goto out_delete_evlist; |
64 | } | 73 | } |
65 | 74 | ||
66 | evsel = perf_evlist__first(evlist); | 75 | evsel = perf_evlist__first(evlist); |
@@ -74,13 +83,13 @@ int test__task_exit(void) | |||
74 | err = perf_evlist__open(evlist); | 83 | err = perf_evlist__open(evlist); |
75 | if (err < 0) { | 84 | if (err < 0) { |
76 | pr_debug("Couldn't open the evlist: %s\n", strerror(-err)); | 85 | pr_debug("Couldn't open the evlist: %s\n", strerror(-err)); |
77 | goto out_delete_maps; | 86 | goto out_delete_evlist; |
78 | } | 87 | } |
79 | 88 | ||
80 | if (perf_evlist__mmap(evlist, 128, true) < 0) { | 89 | if (perf_evlist__mmap(evlist, 128, true) < 0) { |
81 | pr_debug("failed to mmap events: %d (%s)\n", errno, | 90 | pr_debug("failed to mmap events: %d (%s)\n", errno, |
82 | strerror(errno)); | 91 | strerror(errno)); |
83 | goto out_close_evlist; | 92 | goto out_delete_evlist; |
84 | } | 93 | } |
85 | 94 | ||
86 | perf_evlist__start_workload(evlist); | 95 | perf_evlist__start_workload(evlist); |
@@ -103,11 +112,7 @@ retry: | |||
103 | err = -1; | 112 | err = -1; |
104 | } | 113 | } |
105 | 114 | ||
106 | perf_evlist__munmap(evlist); | 115 | out_delete_evlist: |
107 | out_close_evlist: | ||
108 | perf_evlist__close(evlist); | ||
109 | out_delete_maps: | ||
110 | perf_evlist__delete_maps(evlist); | ||
111 | perf_evlist__delete(evlist); | 116 | perf_evlist__delete(evlist); |
112 | return err; | 117 | return err; |
113 | } | 118 | } |
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index cbaa7af45513..d11541d4d7d7 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c | |||
@@ -256,8 +256,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title, | |||
256 | __ui_browser__show_title(browser, title); | 256 | __ui_browser__show_title(browser, title); |
257 | 257 | ||
258 | browser->title = title; | 258 | browser->title = title; |
259 | free(browser->helpline); | 259 | zfree(&browser->helpline); |
260 | browser->helpline = NULL; | ||
261 | 260 | ||
262 | va_start(ap, helpline); | 261 | va_start(ap, helpline); |
263 | err = vasprintf(&browser->helpline, helpline, ap); | 262 | err = vasprintf(&browser->helpline, helpline, ap); |
@@ -268,12 +267,11 @@ int ui_browser__show(struct ui_browser *browser, const char *title, | |||
268 | return err ? 0 : -1; | 267 | return err ? 0 : -1; |
269 | } | 268 | } |
270 | 269 | ||
271 | void ui_browser__hide(struct ui_browser *browser __maybe_unused) | 270 | void ui_browser__hide(struct ui_browser *browser) |
272 | { | 271 | { |
273 | pthread_mutex_lock(&ui__lock); | 272 | pthread_mutex_lock(&ui__lock); |
274 | ui_helpline__pop(); | 273 | ui_helpline__pop(); |
275 | free(browser->helpline); | 274 | zfree(&browser->helpline); |
276 | browser->helpline = NULL; | ||
277 | pthread_mutex_unlock(&ui__lock); | 275 | pthread_mutex_unlock(&ui__lock); |
278 | } | 276 | } |
279 | 277 | ||
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index 7d45d2f53601..118cca29dd26 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h | |||
@@ -59,6 +59,8 @@ int ui_browser__help_window(struct ui_browser *browser, const char *text); | |||
59 | bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text); | 59 | bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text); |
60 | int ui_browser__input_window(const char *title, const char *text, char *input, | 60 | int ui_browser__input_window(const char *title, const char *text, char *input, |
61 | const char *exit_msg, int delay_sec); | 61 | const char *exit_msg, int delay_sec); |
62 | struct perf_session_env; | ||
63 | int tui__header_window(struct perf_session_env *env); | ||
62 | 64 | ||
63 | void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence); | 65 | void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence); |
64 | unsigned int ui_browser__argv_refresh(struct ui_browser *browser); | 66 | unsigned int ui_browser__argv_refresh(struct ui_browser *browser); |
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c new file mode 100644 index 000000000000..89c16b988618 --- /dev/null +++ b/tools/perf/ui/browsers/header.c | |||
@@ -0,0 +1,127 @@ | |||
1 | #include "util/cache.h" | ||
2 | #include "util/debug.h" | ||
3 | #include "ui/browser.h" | ||
4 | #include "ui/ui.h" | ||
5 | #include "ui/util.h" | ||
6 | #include "ui/libslang.h" | ||
7 | #include "util/header.h" | ||
8 | #include "util/session.h" | ||
9 | |||
10 | static void ui_browser__argv_write(struct ui_browser *browser, | ||
11 | void *entry, int row) | ||
12 | { | ||
13 | char **arg = entry; | ||
14 | char *str = *arg; | ||
15 | char empty[] = " "; | ||
16 | bool current_entry = ui_browser__is_current_entry(browser, row); | ||
17 | unsigned long offset = (unsigned long)browser->priv; | ||
18 | |||
19 | if (offset >= strlen(str)) | ||
20 | str = empty; | ||
21 | else | ||
22 | str = str + offset; | ||
23 | |||
24 | ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : | ||
25 | HE_COLORSET_NORMAL); | ||
26 | |||
27 | slsmg_write_nstring(str, browser->width); | ||
28 | } | ||
29 | |||
30 | static int list_menu__run(struct ui_browser *menu) | ||
31 | { | ||
32 | int key; | ||
33 | unsigned long offset; | ||
34 | const char help[] = | ||
35 | "h/?/F1 Show this window\n" | ||
36 | "UP/DOWN/PGUP\n" | ||
37 | "PGDN/SPACE\n" | ||
38 | "LEFT/RIGHT Navigate\n" | ||
39 | "q/ESC/CTRL+C Exit browser"; | ||
40 | |||
41 | if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0) | ||
42 | return -1; | ||
43 | |||
44 | while (1) { | ||
45 | key = ui_browser__run(menu, 0); | ||
46 | |||
47 | switch (key) { | ||
48 | case K_RIGHT: | ||
49 | offset = (unsigned long)menu->priv; | ||
50 | offset += 10; | ||
51 | menu->priv = (void *)offset; | ||
52 | continue; | ||
53 | case K_LEFT: | ||
54 | offset = (unsigned long)menu->priv; | ||
55 | if (offset >= 10) | ||
56 | offset -= 10; | ||
57 | menu->priv = (void *)offset; | ||
58 | continue; | ||
59 | case K_F1: | ||
60 | case 'h': | ||
61 | case '?': | ||
62 | ui_browser__help_window(menu, help); | ||
63 | continue; | ||
64 | case K_ESC: | ||
65 | case 'q': | ||
66 | case CTRL('c'): | ||
67 | key = -1; | ||
68 | break; | ||
69 | default: | ||
70 | continue; | ||
71 | } | ||
72 | |||
73 | break; | ||
74 | } | ||
75 | |||
76 | ui_browser__hide(menu); | ||
77 | return key; | ||
78 | } | ||
79 | |||
80 | static int ui__list_menu(int argc, char * const argv[]) | ||
81 | { | ||
82 | struct ui_browser menu = { | ||
83 | .entries = (void *)argv, | ||
84 | .refresh = ui_browser__argv_refresh, | ||
85 | .seek = ui_browser__argv_seek, | ||
86 | .write = ui_browser__argv_write, | ||
87 | .nr_entries = argc, | ||
88 | }; | ||
89 | |||
90 | return list_menu__run(&menu); | ||
91 | } | ||
92 | |||
93 | int tui__header_window(struct perf_session_env *env) | ||
94 | { | ||
95 | int i, argc = 0; | ||
96 | char **argv; | ||
97 | struct perf_session *session; | ||
98 | char *ptr, *pos; | ||
99 | size_t size; | ||
100 | FILE *fp = open_memstream(&ptr, &size); | ||
101 | |||
102 | session = container_of(env, struct perf_session, header.env); | ||
103 | perf_header__fprintf_info(session, fp, true); | ||
104 | fclose(fp); | ||
105 | |||
106 | for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++) | ||
107 | argc++; | ||
108 | |||
109 | argv = calloc(argc + 1, sizeof(*argv)); | ||
110 | if (argv == NULL) | ||
111 | goto out; | ||
112 | |||
113 | argv[0] = pos = ptr; | ||
114 | for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) { | ||
115 | *pos++ = '\0'; | ||
116 | argv[i] = pos; | ||
117 | } | ||
118 | |||
119 | BUG_ON(i != argc + 1); | ||
120 | |||
121 | ui__list_menu(argc, argv); | ||
122 | |||
123 | out: | ||
124 | free(argv); | ||
125 | free(ptr); | ||
126 | return 0; | ||
127 | } | ||
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a440e03cd8c2..b720b92eba6e 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -1267,10 +1267,8 @@ static inline void free_popup_options(char **options, int n) | |||
1267 | { | 1267 | { |
1268 | int i; | 1268 | int i; |
1269 | 1269 | ||
1270 | for (i = 0; i < n; ++i) { | 1270 | for (i = 0; i < n; ++i) |
1271 | free(options[i]); | 1271 | zfree(&options[i]); |
1272 | options[i] = NULL; | ||
1273 | } | ||
1274 | } | 1272 | } |
1275 | 1273 | ||
1276 | /* Check whether the browser is for 'top' or 'report' */ | 1274 | /* Check whether the browser is for 'top' or 'report' */ |
@@ -1329,7 +1327,7 @@ static int switch_data_file(void) | |||
1329 | 1327 | ||
1330 | abs_path[nr_options] = strdup(path); | 1328 | abs_path[nr_options] = strdup(path); |
1331 | if (!abs_path[nr_options]) { | 1329 | if (!abs_path[nr_options]) { |
1332 | free(options[nr_options]); | 1330 | zfree(&options[nr_options]); |
1333 | ui__warning("Can't search all data files due to memory shortage.\n"); | 1331 | ui__warning("Can't search all data files due to memory shortage.\n"); |
1334 | fclose(file); | 1332 | fclose(file); |
1335 | break; | 1333 | break; |
@@ -1400,6 +1398,36 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1400 | char script_opt[64]; | 1398 | char script_opt[64]; |
1401 | int delay_secs = hbt ? hbt->refresh : 0; | 1399 | int delay_secs = hbt ? hbt->refresh : 0; |
1402 | 1400 | ||
1401 | #define HIST_BROWSER_HELP_COMMON \ | ||
1402 | "h/?/F1 Show this window\n" \ | ||
1403 | "UP/DOWN/PGUP\n" \ | ||
1404 | "PGDN/SPACE Navigate\n" \ | ||
1405 | "q/ESC/CTRL+C Exit browser\n\n" \ | ||
1406 | "For multiple event sessions:\n\n" \ | ||
1407 | "TAB/UNTAB Switch events\n\n" \ | ||
1408 | "For symbolic views (--sort has sym):\n\n" \ | ||
1409 | "-> Zoom into DSO/Threads & Annotate current symbol\n" \ | ||
1410 | "<- Zoom out\n" \ | ||
1411 | "a Annotate current symbol\n" \ | ||
1412 | "C Collapse all callchains\n" \ | ||
1413 | "d Zoom into current DSO\n" \ | ||
1414 | "E Expand all callchains\n" \ | ||
1415 | |||
1416 | /* help messages are sorted by lexical order of the hotkey */ | ||
1417 | const char report_help[] = HIST_BROWSER_HELP_COMMON | ||
1418 | "i Show header information\n" | ||
1419 | "P Print histograms to perf.hist.N\n" | ||
1420 | "r Run available scripts\n" | ||
1421 | "s Switch to another data file in PWD\n" | ||
1422 | "t Zoom into current Thread\n" | ||
1423 | "V Verbose (DSO names in callchains, etc)\n" | ||
1424 | "/ Filter symbol by name"; | ||
1425 | const char top_help[] = HIST_BROWSER_HELP_COMMON | ||
1426 | "P Print histograms to perf.hist.N\n" | ||
1427 | "t Zoom into current Thread\n" | ||
1428 | "V Verbose (DSO names in callchains, etc)\n" | ||
1429 | "/ Filter symbol by name"; | ||
1430 | |||
1403 | if (browser == NULL) | 1431 | if (browser == NULL) |
1404 | return -1; | 1432 | return -1; |
1405 | 1433 | ||
@@ -1484,29 +1512,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1484 | if (is_report_browser(hbt)) | 1512 | if (is_report_browser(hbt)) |
1485 | goto do_data_switch; | 1513 | goto do_data_switch; |
1486 | continue; | 1514 | continue; |
1515 | case 'i': | ||
1516 | /* env->arch is NULL for live-mode (i.e. perf top) */ | ||
1517 | if (env->arch) | ||
1518 | tui__header_window(env); | ||
1519 | continue; | ||
1487 | case K_F1: | 1520 | case K_F1: |
1488 | case 'h': | 1521 | case 'h': |
1489 | case '?': | 1522 | case '?': |
1490 | ui_browser__help_window(&browser->b, | 1523 | ui_browser__help_window(&browser->b, |
1491 | "h/?/F1 Show this window\n" | 1524 | is_report_browser(hbt) ? report_help : top_help); |
1492 | "UP/DOWN/PGUP\n" | ||
1493 | "PGDN/SPACE Navigate\n" | ||
1494 | "q/ESC/CTRL+C Exit browser\n\n" | ||
1495 | "For multiple event sessions:\n\n" | ||
1496 | "TAB/UNTAB Switch events\n\n" | ||
1497 | "For symbolic views (--sort has sym):\n\n" | ||
1498 | "-> Zoom into DSO/Threads & Annotate current symbol\n" | ||
1499 | "<- Zoom out\n" | ||
1500 | "a Annotate current symbol\n" | ||
1501 | "C Collapse all callchains\n" | ||
1502 | "E Expand all callchains\n" | ||
1503 | "d Zoom into current DSO\n" | ||
1504 | "t Zoom into current Thread\n" | ||
1505 | "r Run available scripts('perf report' only)\n" | ||
1506 | "s Switch to another data file in PWD ('perf report' only)\n" | ||
1507 | "P Print histograms to perf.hist.N\n" | ||
1508 | "V Verbose (DSO names in callchains, etc)\n" | ||
1509 | "/ Filter symbol by name"); | ||
1510 | continue; | 1525 | continue; |
1511 | case K_ENTER: | 1526 | case K_ENTER: |
1512 | case K_RIGHT: | 1527 | case K_RIGHT: |
@@ -1923,7 +1938,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, | |||
1923 | 1938 | ||
1924 | ui_helpline__push("Press ESC to exit"); | 1939 | ui_helpline__push("Press ESC to exit"); |
1925 | 1940 | ||
1926 | list_for_each_entry(pos, &evlist->entries, node) { | 1941 | evlist__for_each(evlist, pos) { |
1927 | const char *ev_name = perf_evsel__name(pos); | 1942 | const char *ev_name = perf_evsel__name(pos); |
1928 | size_t line_len = strlen(ev_name) + 7; | 1943 | size_t line_len = strlen(ev_name) + 7; |
1929 | 1944 | ||
@@ -1955,9 +1970,10 @@ single_entry: | |||
1955 | struct perf_evsel *pos; | 1970 | struct perf_evsel *pos; |
1956 | 1971 | ||
1957 | nr_entries = 0; | 1972 | nr_entries = 0; |
1958 | list_for_each_entry(pos, &evlist->entries, node) | 1973 | evlist__for_each(evlist, pos) { |
1959 | if (perf_evsel__is_group_leader(pos)) | 1974 | if (perf_evsel__is_group_leader(pos)) |
1960 | nr_entries++; | 1975 | nr_entries++; |
1976 | } | ||
1961 | 1977 | ||
1962 | if (nr_entries == 1) | 1978 | if (nr_entries == 1) |
1963 | goto single_entry; | 1979 | goto single_entry; |
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c index d63c68ea02a8..402d2bd30b09 100644 --- a/tools/perf/ui/browsers/scripts.c +++ b/tools/perf/ui/browsers/scripts.c | |||
@@ -173,8 +173,7 @@ int script_browse(const char *script_opt) | |||
173 | if (script.b.width > AVERAGE_LINE_LEN) | 173 | if (script.b.width > AVERAGE_LINE_LEN) |
174 | script.b.width = AVERAGE_LINE_LEN; | 174 | script.b.width = AVERAGE_LINE_LEN; |
175 | 175 | ||
176 | if (line) | 176 | free(line); |
177 | free(line); | ||
178 | pclose(fp); | 177 | pclose(fp); |
179 | 178 | ||
180 | script.nr_lines = nr_entries; | 179 | script.nr_lines = nr_entries; |
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 2ca66cc1160f..5b95c44f3435 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c | |||
@@ -375,7 +375,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, | |||
375 | 375 | ||
376 | gtk_container_add(GTK_CONTAINER(window), vbox); | 376 | gtk_container_add(GTK_CONTAINER(window), vbox); |
377 | 377 | ||
378 | list_for_each_entry(pos, &evlist->entries, node) { | 378 | evlist__for_each(evlist, pos) { |
379 | struct hists *hists = &pos->hists; | 379 | struct hists *hists = &pos->hists; |
380 | const char *evname = perf_evsel__name(pos); | 380 | const char *evname = perf_evsel__name(pos); |
381 | GtkWidget *scrolled_window; | 381 | GtkWidget *scrolled_window; |
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index 696c1fbe4248..52e7fc48af9f 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c | |||
@@ -23,8 +23,7 @@ int perf_gtk__deactivate_context(struct perf_gtk_context **ctx) | |||
23 | if (!perf_gtk__is_active_context(*ctx)) | 23 | if (!perf_gtk__is_active_context(*ctx)) |
24 | return -1; | 24 | return -1; |
25 | 25 | ||
26 | free(*ctx); | 26 | zfree(ctx); |
27 | *ctx = NULL; | ||
28 | return 0; | 27 | return 0; |
29 | } | 28 | } |
30 | 29 | ||
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index c244cb524ef2..831fbb77d1ff 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -510,7 +510,7 @@ print_entries: | |||
510 | 510 | ||
511 | free(line); | 511 | free(line); |
512 | out: | 512 | out: |
513 | free(rem_sq_bracket); | 513 | zfree(&rem_sq_bracket); |
514 | 514 | ||
515 | return ret; | 515 | return ret; |
516 | } | 516 | } |
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c index 092902e30cee..bf890f72fe80 100644 --- a/tools/perf/ui/tui/util.c +++ b/tools/perf/ui/tui/util.c | |||
@@ -92,6 +92,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input, | |||
92 | t = sep + 1; | 92 | t = sep + 1; |
93 | } | 93 | } |
94 | 94 | ||
95 | pthread_mutex_lock(&ui__lock); | ||
96 | |||
95 | max_len += 2; | 97 | max_len += 2; |
96 | nr_lines += 8; | 98 | nr_lines += 8; |
97 | y = SLtt_Screen_Rows / 2 - nr_lines / 2; | 99 | y = SLtt_Screen_Rows / 2 - nr_lines / 2; |
@@ -120,13 +122,19 @@ int ui_browser__input_window(const char *title, const char *text, char *input, | |||
120 | SLsmg_write_nstring((char *)exit_msg, max_len); | 122 | SLsmg_write_nstring((char *)exit_msg, max_len); |
121 | SLsmg_refresh(); | 123 | SLsmg_refresh(); |
122 | 124 | ||
125 | pthread_mutex_unlock(&ui__lock); | ||
126 | |||
123 | x += 2; | 127 | x += 2; |
124 | len = 0; | 128 | len = 0; |
125 | key = ui__getch(delay_secs); | 129 | key = ui__getch(delay_secs); |
126 | while (key != K_TIMER && key != K_ENTER && key != K_ESC) { | 130 | while (key != K_TIMER && key != K_ENTER && key != K_ESC) { |
131 | pthread_mutex_lock(&ui__lock); | ||
132 | |||
127 | if (key == K_BKSPC) { | 133 | if (key == K_BKSPC) { |
128 | if (len == 0) | 134 | if (len == 0) { |
135 | pthread_mutex_unlock(&ui__lock); | ||
129 | goto next_key; | 136 | goto next_key; |
137 | } | ||
130 | SLsmg_gotorc(y, x + --len); | 138 | SLsmg_gotorc(y, x + --len); |
131 | SLsmg_write_char(' '); | 139 | SLsmg_write_char(' '); |
132 | } else { | 140 | } else { |
@@ -136,6 +144,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input, | |||
136 | } | 144 | } |
137 | SLsmg_refresh(); | 145 | SLsmg_refresh(); |
138 | 146 | ||
147 | pthread_mutex_unlock(&ui__lock); | ||
148 | |||
139 | /* XXX more graceful overflow handling needed */ | 149 | /* XXX more graceful overflow handling needed */ |
140 | if (len == sizeof(buf) - 1) { | 150 | if (len == sizeof(buf) - 1) { |
141 | ui_helpline__push("maximum size of symbol name reached!"); | 151 | ui_helpline__push("maximum size of symbol name reached!"); |
@@ -174,6 +184,8 @@ int ui__question_window(const char *title, const char *text, | |||
174 | t = sep + 1; | 184 | t = sep + 1; |
175 | } | 185 | } |
176 | 186 | ||
187 | pthread_mutex_lock(&ui__lock); | ||
188 | |||
177 | max_len += 2; | 189 | max_len += 2; |
178 | nr_lines += 4; | 190 | nr_lines += 4; |
179 | y = SLtt_Screen_Rows / 2 - nr_lines / 2, | 191 | y = SLtt_Screen_Rows / 2 - nr_lines / 2, |
@@ -195,6 +207,9 @@ int ui__question_window(const char *title, const char *text, | |||
195 | SLsmg_gotorc(y + nr_lines - 1, x); | 207 | SLsmg_gotorc(y + nr_lines - 1, x); |
196 | SLsmg_write_nstring((char *)exit_msg, max_len); | 208 | SLsmg_write_nstring((char *)exit_msg, max_len); |
197 | SLsmg_refresh(); | 209 | SLsmg_refresh(); |
210 | |||
211 | pthread_mutex_unlock(&ui__lock); | ||
212 | |||
198 | return ui__getch(delay_secs); | 213 | return ui__getch(delay_secs); |
199 | } | 214 | } |
200 | 215 | ||
@@ -215,9 +230,7 @@ static int __ui__warning(const char *title, const char *format, va_list args) | |||
215 | if (vasprintf(&s, format, args) > 0) { | 230 | if (vasprintf(&s, format, args) > 0) { |
216 | int key; | 231 | int key; |
217 | 232 | ||
218 | pthread_mutex_lock(&ui__lock); | ||
219 | key = ui__question_window(title, s, "Press any key...", 0); | 233 | key = ui__question_window(title, s, "Press any key...", 0); |
220 | pthread_mutex_unlock(&ui__lock); | ||
221 | free(s); | 234 | free(s); |
222 | return key; | 235 | return key; |
223 | } | 236 | } |
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c index e6d134773d0a..c0b43ee40d95 100644 --- a/tools/perf/util/alias.c +++ b/tools/perf/util/alias.c | |||
@@ -55,8 +55,7 @@ int split_cmdline(char *cmdline, const char ***argv) | |||
55 | src++; | 55 | src++; |
56 | c = cmdline[src]; | 56 | c = cmdline[src]; |
57 | if (!c) { | 57 | if (!c) { |
58 | free(*argv); | 58 | zfree(argv); |
59 | *argv = NULL; | ||
60 | return error("cmdline ends with \\"); | 59 | return error("cmdline ends with \\"); |
61 | } | 60 | } |
62 | } | 61 | } |
@@ -68,8 +67,7 @@ int split_cmdline(char *cmdline, const char ***argv) | |||
68 | cmdline[dst] = 0; | 67 | cmdline[dst] = 0; |
69 | 68 | ||
70 | if (quoted) { | 69 | if (quoted) { |
71 | free(*argv); | 70 | zfree(argv); |
72 | *argv = NULL; | ||
73 | return error("unclosed quote"); | 71 | return error("unclosed quote"); |
74 | } | 72 | } |
75 | 73 | ||
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index cf6242c92ee2..469eb679fb9d 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -26,10 +26,10 @@ static int disasm_line__parse(char *line, char **namep, char **rawp); | |||
26 | 26 | ||
27 | static void ins__delete(struct ins_operands *ops) | 27 | static void ins__delete(struct ins_operands *ops) |
28 | { | 28 | { |
29 | free(ops->source.raw); | 29 | zfree(&ops->source.raw); |
30 | free(ops->source.name); | 30 | zfree(&ops->source.name); |
31 | free(ops->target.raw); | 31 | zfree(&ops->target.raw); |
32 | free(ops->target.name); | 32 | zfree(&ops->target.name); |
33 | } | 33 | } |
34 | 34 | ||
35 | static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, | 35 | static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, |
@@ -185,8 +185,7 @@ static int lock__parse(struct ins_operands *ops) | |||
185 | return 0; | 185 | return 0; |
186 | 186 | ||
187 | out_free_ops: | 187 | out_free_ops: |
188 | free(ops->locked.ops); | 188 | zfree(&ops->locked.ops); |
189 | ops->locked.ops = NULL; | ||
190 | return 0; | 189 | return 0; |
191 | } | 190 | } |
192 | 191 | ||
@@ -205,9 +204,9 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size, | |||
205 | 204 | ||
206 | static void lock__delete(struct ins_operands *ops) | 205 | static void lock__delete(struct ins_operands *ops) |
207 | { | 206 | { |
208 | free(ops->locked.ops); | 207 | zfree(&ops->locked.ops); |
209 | free(ops->target.raw); | 208 | zfree(&ops->target.raw); |
210 | free(ops->target.name); | 209 | zfree(&ops->target.name); |
211 | } | 210 | } |
212 | 211 | ||
213 | static struct ins_ops lock_ops = { | 212 | static struct ins_ops lock_ops = { |
@@ -256,8 +255,7 @@ static int mov__parse(struct ins_operands *ops) | |||
256 | return 0; | 255 | return 0; |
257 | 256 | ||
258 | out_free_source: | 257 | out_free_source: |
259 | free(ops->source.raw); | 258 | zfree(&ops->source.raw); |
260 | ops->source.raw = NULL; | ||
261 | return -1; | 259 | return -1; |
262 | } | 260 | } |
263 | 261 | ||
@@ -464,17 +462,12 @@ void symbol__annotate_zero_histograms(struct symbol *sym) | |||
464 | pthread_mutex_unlock(¬es->lock); | 462 | pthread_mutex_unlock(¬es->lock); |
465 | } | 463 | } |
466 | 464 | ||
467 | int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | 465 | static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, |
468 | int evidx, u64 addr) | 466 | struct annotation *notes, int evidx, u64 addr) |
469 | { | 467 | { |
470 | unsigned offset; | 468 | unsigned offset; |
471 | struct annotation *notes; | ||
472 | struct sym_hist *h; | 469 | struct sym_hist *h; |
473 | 470 | ||
474 | notes = symbol__annotation(sym); | ||
475 | if (notes->src == NULL) | ||
476 | return -ENOMEM; | ||
477 | |||
478 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); | 471 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); |
479 | 472 | ||
480 | if (addr < sym->start || addr > sym->end) | 473 | if (addr < sym->start || addr > sym->end) |
@@ -491,6 +484,33 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | |||
491 | return 0; | 484 | return 0; |
492 | } | 485 | } |
493 | 486 | ||
487 | static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | ||
488 | int evidx, u64 addr) | ||
489 | { | ||
490 | struct annotation *notes; | ||
491 | |||
492 | if (sym == NULL || use_browser != 1 || !sort__has_sym) | ||
493 | return 0; | ||
494 | |||
495 | notes = symbol__annotation(sym); | ||
496 | if (notes->src == NULL) { | ||
497 | if (symbol__alloc_hist(sym) < 0) | ||
498 | return -ENOMEM; | ||
499 | } | ||
500 | |||
501 | return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); | ||
502 | } | ||
503 | |||
504 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx) | ||
505 | { | ||
506 | return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr); | ||
507 | } | ||
508 | |||
509 | int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) | ||
510 | { | ||
511 | return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); | ||
512 | } | ||
513 | |||
494 | static void disasm_line__init_ins(struct disasm_line *dl) | 514 | static void disasm_line__init_ins(struct disasm_line *dl) |
495 | { | 515 | { |
496 | dl->ins = ins__find(dl->name); | 516 | dl->ins = ins__find(dl->name); |
@@ -538,8 +558,7 @@ static int disasm_line__parse(char *line, char **namep, char **rawp) | |||
538 | return 0; | 558 | return 0; |
539 | 559 | ||
540 | out_free_name: | 560 | out_free_name: |
541 | free(*namep); | 561 | zfree(namep); |
542 | *namep = NULL; | ||
543 | return -1; | 562 | return -1; |
544 | } | 563 | } |
545 | 564 | ||
@@ -564,7 +583,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs | |||
564 | return dl; | 583 | return dl; |
565 | 584 | ||
566 | out_free_line: | 585 | out_free_line: |
567 | free(dl->line); | 586 | zfree(&dl->line); |
568 | out_delete: | 587 | out_delete: |
569 | free(dl); | 588 | free(dl); |
570 | return NULL; | 589 | return NULL; |
@@ -572,8 +591,8 @@ out_delete: | |||
572 | 591 | ||
573 | void disasm_line__free(struct disasm_line *dl) | 592 | void disasm_line__free(struct disasm_line *dl) |
574 | { | 593 | { |
575 | free(dl->line); | 594 | zfree(&dl->line); |
576 | free(dl->name); | 595 | zfree(&dl->name); |
577 | if (dl->ins && dl->ins->ops->free) | 596 | if (dl->ins && dl->ins->ops->free) |
578 | dl->ins->ops->free(&dl->ops); | 597 | dl->ins->ops->free(&dl->ops); |
579 | else | 598 | else |
@@ -900,7 +919,7 @@ fallback: | |||
900 | * cache, or is just a kallsyms file, well, lets hope that this | 919 | * cache, or is just a kallsyms file, well, lets hope that this |
901 | * DSO is the same as when 'perf record' ran. | 920 | * DSO is the same as when 'perf record' ran. |
902 | */ | 921 | */ |
903 | filename = dso->long_name; | 922 | filename = (char *)dso->long_name; |
904 | snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", | 923 | snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", |
905 | symbol_conf.symfs, filename); | 924 | symbol_conf.symfs, filename); |
906 | free_filename = false; | 925 | free_filename = false; |
@@ -1091,8 +1110,7 @@ static void symbol__free_source_line(struct symbol *sym, int len) | |||
1091 | src_line = (void *)src_line + sizeof_src_line; | 1110 | src_line = (void *)src_line + sizeof_src_line; |
1092 | } | 1111 | } |
1093 | 1112 | ||
1094 | free(notes->src->lines); | 1113 | zfree(¬es->src->lines); |
1095 | notes->src->lines = NULL; | ||
1096 | } | 1114 | } |
1097 | 1115 | ||
1098 | /* Get the filename:line for the colored entries */ | 1116 | /* Get the filename:line for the colored entries */ |
@@ -1376,3 +1394,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, | |||
1376 | 1394 | ||
1377 | return 0; | 1395 | return 0; |
1378 | } | 1396 | } |
1397 | |||
1398 | int hist_entry__annotate(struct hist_entry *he, size_t privsize) | ||
1399 | { | ||
1400 | return symbol__annotate(he->ms.sym, he->ms.map, privsize); | ||
1401 | } | ||
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 834b7b57b788..b2aef59d6bb2 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
@@ -132,12 +132,17 @@ static inline struct annotation *symbol__annotation(struct symbol *sym) | |||
132 | return &a->annotation; | 132 | return &a->annotation; |
133 | } | 133 | } |
134 | 134 | ||
135 | int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | 135 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); |
136 | int evidx, u64 addr); | 136 | |
137 | int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); | ||
138 | |||
137 | int symbol__alloc_hist(struct symbol *sym); | 139 | int symbol__alloc_hist(struct symbol *sym); |
138 | void symbol__annotate_zero_histograms(struct symbol *sym); | 140 | void symbol__annotate_zero_histograms(struct symbol *sym); |
139 | 141 | ||
140 | int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); | 142 | int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); |
143 | |||
144 | int hist_entry__annotate(struct hist_entry *he, size_t privsize); | ||
145 | |||
141 | int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); | 146 | int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); |
142 | int symbol__annotate_printf(struct symbol *sym, struct map *map, | 147 | int symbol__annotate_printf(struct symbol *sym, struct map *map, |
143 | struct perf_evsel *evsel, bool full_paths, | 148 | struct perf_evsel *evsel, bool full_paths, |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index a92770c98cc7..6baabe63182b 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -89,7 +89,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf) | |||
89 | return raw - build_id; | 89 | return raw - build_id; |
90 | } | 90 | } |
91 | 91 | ||
92 | char *dso__build_id_filename(struct dso *dso, char *bf, size_t size) | 92 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) |
93 | { | 93 | { |
94 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 94 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
95 | 95 | ||
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 929f28a7c14d..845ef865eced 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h | |||
@@ -10,7 +10,7 @@ extern struct perf_tool build_id__mark_dso_hit_ops; | |||
10 | struct dso; | 10 | struct dso; |
11 | 11 | ||
12 | int build_id__sprintf(const u8 *build_id, int len, char *bf); | 12 | int build_id__sprintf(const u8 *build_id, int len, char *bf); |
13 | char *dso__build_id_filename(struct dso *dso, char *bf, size_t size); | 13 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); |
14 | 14 | ||
15 | int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, | 15 | int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, |
16 | struct perf_sample *sample, struct perf_evsel *evsel, | 16 | struct perf_sample *sample, struct perf_evsel *evsel, |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index e3970e3eaacf..8d9db454f1a9 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -15,8 +15,12 @@ | |||
15 | #include <errno.h> | 15 | #include <errno.h> |
16 | #include <math.h> | 16 | #include <math.h> |
17 | 17 | ||
18 | #include "asm/bug.h" | ||
19 | |||
18 | #include "hist.h" | 20 | #include "hist.h" |
19 | #include "util.h" | 21 | #include "util.h" |
22 | #include "sort.h" | ||
23 | #include "machine.h" | ||
20 | #include "callchain.h" | 24 | #include "callchain.h" |
21 | 25 | ||
22 | __thread struct callchain_cursor callchain_cursor; | 26 | __thread struct callchain_cursor callchain_cursor; |
@@ -356,19 +360,14 @@ append_chain_children(struct callchain_node *root, | |||
356 | /* lookup in childrens */ | 360 | /* lookup in childrens */ |
357 | while (*p) { | 361 | while (*p) { |
358 | s64 ret; | 362 | s64 ret; |
359 | struct callchain_list *cnode; | ||
360 | 363 | ||
361 | parent = *p; | 364 | parent = *p; |
362 | rnode = rb_entry(parent, struct callchain_node, rb_node_in); | 365 | rnode = rb_entry(parent, struct callchain_node, rb_node_in); |
363 | cnode = list_first_entry(&rnode->val, struct callchain_list, | ||
364 | list); | ||
365 | 366 | ||
366 | /* just check first entry */ | 367 | /* If at least first entry matches, rely to children */ |
367 | ret = match_chain(node, cnode); | 368 | ret = append_chain(rnode, cursor, period); |
368 | if (ret == 0) { | 369 | if (ret == 0) |
369 | append_chain(rnode, cursor, period); | ||
370 | goto inc_children_hit; | 370 | goto inc_children_hit; |
371 | } | ||
372 | 371 | ||
373 | if (ret < 0) | 372 | if (ret < 0) |
374 | p = &parent->rb_left; | 373 | p = &parent->rb_left; |
@@ -389,11 +388,11 @@ append_chain(struct callchain_node *root, | |||
389 | struct callchain_cursor *cursor, | 388 | struct callchain_cursor *cursor, |
390 | u64 period) | 389 | u64 period) |
391 | { | 390 | { |
392 | struct callchain_cursor_node *curr_snap = cursor->curr; | ||
393 | struct callchain_list *cnode; | 391 | struct callchain_list *cnode; |
394 | u64 start = cursor->pos; | 392 | u64 start = cursor->pos; |
395 | bool found = false; | 393 | bool found = false; |
396 | u64 matches; | 394 | u64 matches; |
395 | int cmp = 0; | ||
397 | 396 | ||
398 | /* | 397 | /* |
399 | * Lookup in the current node | 398 | * Lookup in the current node |
@@ -408,7 +407,8 @@ append_chain(struct callchain_node *root, | |||
408 | if (!node) | 407 | if (!node) |
409 | break; | 408 | break; |
410 | 409 | ||
411 | if (match_chain(node, cnode) != 0) | 410 | cmp = match_chain(node, cnode); |
411 | if (cmp) | ||
412 | break; | 412 | break; |
413 | 413 | ||
414 | found = true; | 414 | found = true; |
@@ -418,9 +418,8 @@ append_chain(struct callchain_node *root, | |||
418 | 418 | ||
419 | /* matches not, relay no the parent */ | 419 | /* matches not, relay no the parent */ |
420 | if (!found) { | 420 | if (!found) { |
421 | cursor->curr = curr_snap; | 421 | WARN_ONCE(!cmp, "Chain comparison error\n"); |
422 | cursor->pos = start; | 422 | return cmp; |
423 | return -1; | ||
424 | } | 423 | } |
425 | 424 | ||
426 | matches = cursor->pos - start; | 425 | matches = cursor->pos - start; |
@@ -531,3 +530,24 @@ int callchain_cursor_append(struct callchain_cursor *cursor, | |||
531 | 530 | ||
532 | return 0; | 531 | return 0; |
533 | } | 532 | } |
533 | |||
534 | int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, | ||
535 | struct perf_evsel *evsel, struct addr_location *al, | ||
536 | int max_stack) | ||
537 | { | ||
538 | if (sample->callchain == NULL) | ||
539 | return 0; | ||
540 | |||
541 | if (symbol_conf.use_callchain || sort__has_parent) { | ||
542 | return machine__resolve_callchain(al->machine, evsel, al->thread, | ||
543 | sample, parent, al, max_stack); | ||
544 | } | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) | ||
549 | { | ||
550 | if (!symbol_conf.use_callchain) | ||
551 | return 0; | ||
552 | return callchain_append(he->callchain, &callchain_cursor, sample->period); | ||
553 | } | ||
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 4f7f989876ec..8ad97e9b119f 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -145,10 +145,16 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | struct option; | 147 | struct option; |
148 | struct hist_entry; | ||
148 | 149 | ||
149 | int record_parse_callchain(const char *arg, struct perf_record_opts *opts); | 150 | int record_parse_callchain(const char *arg, struct record_opts *opts); |
150 | int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); | 151 | int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); |
151 | int record_callchain_opt(const struct option *opt, const char *arg, int unset); | 152 | int record_callchain_opt(const struct option *opt, const char *arg, int unset); |
152 | 153 | ||
154 | int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, | ||
155 | struct perf_evsel *evsel, struct addr_location *al, | ||
156 | int max_stack); | ||
157 | int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample); | ||
158 | |||
153 | extern const char record_callchain_help[]; | 159 | extern const char record_callchain_help[]; |
154 | #endif /* __PERF_CALLCHAIN_H */ | 160 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 96bbda1ddb83..88f7be399432 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c | |||
@@ -81,7 +81,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str) | |||
81 | /* | 81 | /* |
82 | * check if cgrp is already defined, if so we reuse it | 82 | * check if cgrp is already defined, if so we reuse it |
83 | */ | 83 | */ |
84 | list_for_each_entry(counter, &evlist->entries, node) { | 84 | evlist__for_each(evlist, counter) { |
85 | cgrp = counter->cgrp; | 85 | cgrp = counter->cgrp; |
86 | if (!cgrp) | 86 | if (!cgrp) |
87 | continue; | 87 | continue; |
@@ -110,7 +110,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str) | |||
110 | * if add cgroup N, then need to find event N | 110 | * if add cgroup N, then need to find event N |
111 | */ | 111 | */ |
112 | n = 0; | 112 | n = 0; |
113 | list_for_each_entry(counter, &evlist->entries, node) { | 113 | evlist__for_each(evlist, counter) { |
114 | if (n == nr_cgroups) | 114 | if (n == nr_cgroups) |
115 | goto found; | 115 | goto found; |
116 | n++; | 116 | n++; |
@@ -133,7 +133,7 @@ void close_cgroup(struct cgroup_sel *cgrp) | |||
133 | /* XXX: not reentrant */ | 133 | /* XXX: not reentrant */ |
134 | if (--cgrp->refcnt == 0) { | 134 | if (--cgrp->refcnt == 0) { |
135 | close(cgrp->fd); | 135 | close(cgrp->fd); |
136 | free(cgrp->name); | 136 | zfree(&cgrp->name); |
137 | free(cgrp); | 137 | free(cgrp); |
138 | } | 138 | } |
139 | } | 139 | } |
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 66e44a5019d5..87b8672eb413 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include "cache.h" | 2 | #include "cache.h" |
3 | #include "color.h" | 3 | #include "color.h" |
4 | #include <math.h> | ||
4 | 5 | ||
5 | int perf_use_color_default = -1; | 6 | int perf_use_color_default = -1; |
6 | 7 | ||
@@ -298,10 +299,10 @@ const char *get_percent_color(double percent) | |||
298 | * entries in green - and keep the low overhead places | 299 | * entries in green - and keep the low overhead places |
299 | * normal: | 300 | * normal: |
300 | */ | 301 | */ |
301 | if (percent >= MIN_RED) | 302 | if (fabs(percent) >= MIN_RED) |
302 | color = PERF_COLOR_RED; | 303 | color = PERF_COLOR_RED; |
303 | else { | 304 | else { |
304 | if (percent > MIN_GREEN) | 305 | if (fabs(percent) > MIN_GREEN) |
305 | color = PERF_COLOR_GREEN; | 306 | color = PERF_COLOR_GREEN; |
306 | } | 307 | } |
307 | return color; | 308 | return color; |
@@ -318,15 +319,19 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent) | |||
318 | return r; | 319 | return r; |
319 | } | 320 | } |
320 | 321 | ||
322 | int value_color_snprintf(char *bf, size_t size, const char *fmt, double value) | ||
323 | { | ||
324 | const char *color = get_percent_color(value); | ||
325 | return color_snprintf(bf, size, color, fmt, value); | ||
326 | } | ||
327 | |||
321 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) | 328 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) |
322 | { | 329 | { |
323 | va_list args; | 330 | va_list args; |
324 | double percent; | 331 | double percent; |
325 | const char *color; | ||
326 | 332 | ||
327 | va_start(args, fmt); | 333 | va_start(args, fmt); |
328 | percent = va_arg(args, double); | 334 | percent = va_arg(args, double); |
329 | va_end(args); | 335 | va_end(args); |
330 | color = get_percent_color(percent); | 336 | return value_color_snprintf(bf, size, fmt, percent); |
331 | return color_snprintf(bf, size, color, fmt, percent); | ||
332 | } | 337 | } |
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index fced3840e99c..7ff30a62a132 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h | |||
@@ -39,6 +39,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); | |||
39 | int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); | 39 | int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); |
40 | int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); | 40 | int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); |
41 | int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); | 41 | int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); |
42 | int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); | ||
42 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); | 43 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); |
43 | int percent_color_fprintf(FILE *fp, const char *fmt, double percent); | 44 | int percent_color_fprintf(FILE *fp, const char *fmt, double percent); |
44 | const char *get_percent_color(double percent); | 45 | const char *get_percent_color(double percent); |
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c index ee0df0e24cdb..f9e777629e21 100644 --- a/tools/perf/util/comm.c +++ b/tools/perf/util/comm.c | |||
@@ -21,7 +21,7 @@ static void comm_str__put(struct comm_str *cs) | |||
21 | { | 21 | { |
22 | if (!--cs->ref) { | 22 | if (!--cs->ref) { |
23 | rb_erase(&cs->rb_node, &comm_str_root); | 23 | rb_erase(&cs->rb_node, &comm_str_root); |
24 | free(cs->str); | 24 | zfree(&cs->str); |
25 | free(cs); | 25 | free(cs); |
26 | } | 26 | } |
27 | } | 27 | } |
@@ -94,19 +94,20 @@ struct comm *comm__new(const char *str, u64 timestamp) | |||
94 | return comm; | 94 | return comm; |
95 | } | 95 | } |
96 | 96 | ||
97 | void comm__override(struct comm *comm, const char *str, u64 timestamp) | 97 | int comm__override(struct comm *comm, const char *str, u64 timestamp) |
98 | { | 98 | { |
99 | struct comm_str *old = comm->comm_str; | 99 | struct comm_str *new, *old = comm->comm_str; |
100 | 100 | ||
101 | comm->comm_str = comm_str__findnew(str, &comm_str_root); | 101 | new = comm_str__findnew(str, &comm_str_root); |
102 | if (!comm->comm_str) { | 102 | if (!new) |
103 | comm->comm_str = old; | 103 | return -ENOMEM; |
104 | return; | ||
105 | } | ||
106 | 104 | ||
107 | comm->start = timestamp; | 105 | comm_str__get(new); |
108 | comm_str__get(comm->comm_str); | ||
109 | comm_str__put(old); | 106 | comm_str__put(old); |
107 | comm->comm_str = new; | ||
108 | comm->start = timestamp; | ||
109 | |||
110 | return 0; | ||
110 | } | 111 | } |
111 | 112 | ||
112 | void comm__free(struct comm *comm) | 113 | void comm__free(struct comm *comm) |
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h index 7a86e5656710..fac5bd51befc 100644 --- a/tools/perf/util/comm.h +++ b/tools/perf/util/comm.h | |||
@@ -16,6 +16,6 @@ struct comm { | |||
16 | void comm__free(struct comm *comm); | 16 | void comm__free(struct comm *comm); |
17 | struct comm *comm__new(const char *str, u64 timestamp); | 17 | struct comm *comm__new(const char *str, u64 timestamp); |
18 | const char *comm__str(const struct comm *comm); | 18 | const char *comm__str(const struct comm *comm); |
19 | void comm__override(struct comm *comm, const char *str, u64 timestamp); | 19 | int comm__override(struct comm *comm, const char *str, u64 timestamp); |
20 | 20 | ||
21 | #endif /* __PERF_COMM_H */ | 21 | #endif /* __PERF_COMM_H */ |
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index 7d09faf85cf1..1fbcd8bdc11b 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c | |||
@@ -118,3 +118,9 @@ void perf_data_file__close(struct perf_data_file *file) | |||
118 | { | 118 | { |
119 | close(file->fd); | 119 | close(file->fd); |
120 | } | 120 | } |
121 | |||
122 | ssize_t perf_data_file__write(struct perf_data_file *file, | ||
123 | void *buf, size_t size) | ||
124 | { | ||
125 | return writen(file->fd, buf, size); | ||
126 | } | ||
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h index 8c2df80152a5..2b15d0c95c7f 100644 --- a/tools/perf/util/data.h +++ b/tools/perf/util/data.h | |||
@@ -9,12 +9,12 @@ enum perf_data_mode { | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | struct perf_data_file { | 11 | struct perf_data_file { |
12 | const char *path; | 12 | const char *path; |
13 | int fd; | 13 | int fd; |
14 | bool is_pipe; | 14 | bool is_pipe; |
15 | bool force; | 15 | bool force; |
16 | unsigned long size; | 16 | unsigned long size; |
17 | enum perf_data_mode mode; | 17 | enum perf_data_mode mode; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | static inline bool perf_data_file__is_read(struct perf_data_file *file) | 20 | static inline bool perf_data_file__is_read(struct perf_data_file *file) |
@@ -44,5 +44,7 @@ static inline unsigned long perf_data_file__size(struct perf_data_file *file) | |||
44 | 44 | ||
45 | int perf_data_file__open(struct perf_data_file *file); | 45 | int perf_data_file__open(struct perf_data_file *file); |
46 | void perf_data_file__close(struct perf_data_file *file); | 46 | void perf_data_file__close(struct perf_data_file *file); |
47 | ssize_t perf_data_file__write(struct perf_data_file *file, | ||
48 | void *buf, size_t size); | ||
47 | 49 | ||
48 | #endif /* __PERF_DATA_H */ | 50 | #endif /* __PERF_DATA_H */ |
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 399e74c34c1a..299b55586502 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c | |||
@@ -16,23 +16,46 @@ | |||
16 | int verbose; | 16 | int verbose; |
17 | bool dump_trace = false, quiet = false; | 17 | bool dump_trace = false, quiet = false; |
18 | 18 | ||
19 | int eprintf(int level, const char *fmt, ...) | 19 | static int _eprintf(int level, const char *fmt, va_list args) |
20 | { | 20 | { |
21 | va_list args; | ||
22 | int ret = 0; | 21 | int ret = 0; |
23 | 22 | ||
24 | if (verbose >= level) { | 23 | if (verbose >= level) { |
25 | va_start(args, fmt); | ||
26 | if (use_browser >= 1) | 24 | if (use_browser >= 1) |
27 | ui_helpline__vshow(fmt, args); | 25 | ui_helpline__vshow(fmt, args); |
28 | else | 26 | else |
29 | ret = vfprintf(stderr, fmt, args); | 27 | ret = vfprintf(stderr, fmt, args); |
30 | va_end(args); | ||
31 | } | 28 | } |
32 | 29 | ||
33 | return ret; | 30 | return ret; |
34 | } | 31 | } |
35 | 32 | ||
33 | int eprintf(int level, const char *fmt, ...) | ||
34 | { | ||
35 | va_list args; | ||
36 | int ret; | ||
37 | |||
38 | va_start(args, fmt); | ||
39 | ret = _eprintf(level, fmt, args); | ||
40 | va_end(args); | ||
41 | |||
42 | return ret; | ||
43 | } | ||
44 | |||
45 | /* | ||
46 | * Overloading libtraceevent standard info print | ||
47 | * function, display with -v in perf. | ||
48 | */ | ||
49 | void pr_stat(const char *fmt, ...) | ||
50 | { | ||
51 | va_list args; | ||
52 | |||
53 | va_start(args, fmt); | ||
54 | _eprintf(1, fmt, args); | ||
55 | va_end(args); | ||
56 | eprintf(1, "\n"); | ||
57 | } | ||
58 | |||
36 | int dump_printf(const char *fmt, ...) | 59 | int dump_printf(const char *fmt, ...) |
37 | { | 60 | { |
38 | va_list args; | 61 | va_list args; |
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index efbd98805ad0..443694c36b03 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h | |||
@@ -17,4 +17,6 @@ void trace_event(union perf_event *event); | |||
17 | int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); | 17 | int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); |
18 | int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); | 18 | int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); |
19 | 19 | ||
20 | void pr_stat(const char *fmt, ...); | ||
21 | |||
20 | #endif /* __PERF_DEBUG_H */ | 22 | #endif /* __PERF_DEBUG_H */ |
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index af4c687cc49b..4045d086d9d9 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
@@ -28,8 +28,9 @@ char dso__symtab_origin(const struct dso *dso) | |||
28 | return origin[dso->symtab_type]; | 28 | return origin[dso->symtab_type]; |
29 | } | 29 | } |
30 | 30 | ||
31 | int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | 31 | int dso__read_binary_type_filename(const struct dso *dso, |
32 | char *root_dir, char *file, size_t size) | 32 | enum dso_binary_type type, |
33 | char *root_dir, char *filename, size_t size) | ||
33 | { | 34 | { |
34 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 35 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
35 | int ret = 0; | 36 | int ret = 0; |
@@ -38,36 +39,36 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
38 | case DSO_BINARY_TYPE__DEBUGLINK: { | 39 | case DSO_BINARY_TYPE__DEBUGLINK: { |
39 | char *debuglink; | 40 | char *debuglink; |
40 | 41 | ||
41 | strncpy(file, dso->long_name, size); | 42 | strncpy(filename, dso->long_name, size); |
42 | debuglink = file + dso->long_name_len; | 43 | debuglink = filename + dso->long_name_len; |
43 | while (debuglink != file && *debuglink != '/') | 44 | while (debuglink != filename && *debuglink != '/') |
44 | debuglink--; | 45 | debuglink--; |
45 | if (*debuglink == '/') | 46 | if (*debuglink == '/') |
46 | debuglink++; | 47 | debuglink++; |
47 | filename__read_debuglink(dso->long_name, debuglink, | 48 | filename__read_debuglink(dso->long_name, debuglink, |
48 | size - (debuglink - file)); | 49 | size - (debuglink - filename)); |
49 | } | 50 | } |
50 | break; | 51 | break; |
51 | case DSO_BINARY_TYPE__BUILD_ID_CACHE: | 52 | case DSO_BINARY_TYPE__BUILD_ID_CACHE: |
52 | /* skip the locally configured cache if a symfs is given */ | 53 | /* skip the locally configured cache if a symfs is given */ |
53 | if (symbol_conf.symfs[0] || | 54 | if (symbol_conf.symfs[0] || |
54 | (dso__build_id_filename(dso, file, size) == NULL)) | 55 | (dso__build_id_filename(dso, filename, size) == NULL)) |
55 | ret = -1; | 56 | ret = -1; |
56 | break; | 57 | break; |
57 | 58 | ||
58 | case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: | 59 | case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: |
59 | snprintf(file, size, "%s/usr/lib/debug%s.debug", | 60 | snprintf(filename, size, "%s/usr/lib/debug%s.debug", |
60 | symbol_conf.symfs, dso->long_name); | 61 | symbol_conf.symfs, dso->long_name); |
61 | break; | 62 | break; |
62 | 63 | ||
63 | case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: | 64 | case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: |
64 | snprintf(file, size, "%s/usr/lib/debug%s", | 65 | snprintf(filename, size, "%s/usr/lib/debug%s", |
65 | symbol_conf.symfs, dso->long_name); | 66 | symbol_conf.symfs, dso->long_name); |
66 | break; | 67 | break; |
67 | 68 | ||
68 | case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: | 69 | case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: |
69 | { | 70 | { |
70 | char *last_slash; | 71 | const char *last_slash; |
71 | size_t len; | 72 | size_t len; |
72 | size_t dir_size; | 73 | size_t dir_size; |
73 | 74 | ||
@@ -75,14 +76,14 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
75 | while (last_slash != dso->long_name && *last_slash != '/') | 76 | while (last_slash != dso->long_name && *last_slash != '/') |
76 | last_slash--; | 77 | last_slash--; |
77 | 78 | ||
78 | len = scnprintf(file, size, "%s", symbol_conf.symfs); | 79 | len = scnprintf(filename, size, "%s", symbol_conf.symfs); |
79 | dir_size = last_slash - dso->long_name + 2; | 80 | dir_size = last_slash - dso->long_name + 2; |
80 | if (dir_size > (size - len)) { | 81 | if (dir_size > (size - len)) { |
81 | ret = -1; | 82 | ret = -1; |
82 | break; | 83 | break; |
83 | } | 84 | } |
84 | len += scnprintf(file + len, dir_size, "%s", dso->long_name); | 85 | len += scnprintf(filename + len, dir_size, "%s", dso->long_name); |
85 | len += scnprintf(file + len , size - len, ".debug%s", | 86 | len += scnprintf(filename + len , size - len, ".debug%s", |
86 | last_slash); | 87 | last_slash); |
87 | break; | 88 | break; |
88 | } | 89 | } |
@@ -96,7 +97,7 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
96 | build_id__sprintf(dso->build_id, | 97 | build_id__sprintf(dso->build_id, |
97 | sizeof(dso->build_id), | 98 | sizeof(dso->build_id), |
98 | build_id_hex); | 99 | build_id_hex); |
99 | snprintf(file, size, | 100 | snprintf(filename, size, |
100 | "%s/usr/lib/debug/.build-id/%.2s/%s.debug", | 101 | "%s/usr/lib/debug/.build-id/%.2s/%s.debug", |
101 | symbol_conf.symfs, build_id_hex, build_id_hex + 2); | 102 | symbol_conf.symfs, build_id_hex, build_id_hex + 2); |
102 | break; | 103 | break; |
@@ -104,23 +105,23 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
104 | case DSO_BINARY_TYPE__VMLINUX: | 105 | case DSO_BINARY_TYPE__VMLINUX: |
105 | case DSO_BINARY_TYPE__GUEST_VMLINUX: | 106 | case DSO_BINARY_TYPE__GUEST_VMLINUX: |
106 | case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: | 107 | case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: |
107 | snprintf(file, size, "%s%s", | 108 | snprintf(filename, size, "%s%s", |
108 | symbol_conf.symfs, dso->long_name); | 109 | symbol_conf.symfs, dso->long_name); |
109 | break; | 110 | break; |
110 | 111 | ||
111 | case DSO_BINARY_TYPE__GUEST_KMODULE: | 112 | case DSO_BINARY_TYPE__GUEST_KMODULE: |
112 | snprintf(file, size, "%s%s%s", symbol_conf.symfs, | 113 | snprintf(filename, size, "%s%s%s", symbol_conf.symfs, |
113 | root_dir, dso->long_name); | 114 | root_dir, dso->long_name); |
114 | break; | 115 | break; |
115 | 116 | ||
116 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: | 117 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: |
117 | snprintf(file, size, "%s%s", symbol_conf.symfs, | 118 | snprintf(filename, size, "%s%s", symbol_conf.symfs, |
118 | dso->long_name); | 119 | dso->long_name); |
119 | break; | 120 | break; |
120 | 121 | ||
121 | case DSO_BINARY_TYPE__KCORE: | 122 | case DSO_BINARY_TYPE__KCORE: |
122 | case DSO_BINARY_TYPE__GUEST_KCORE: | 123 | case DSO_BINARY_TYPE__GUEST_KCORE: |
123 | snprintf(file, size, "%s", dso->long_name); | 124 | snprintf(filename, size, "%s", dso->long_name); |
124 | break; | 125 | break; |
125 | 126 | ||
126 | default: | 127 | default: |
@@ -137,19 +138,18 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
137 | 138 | ||
138 | static int open_dso(struct dso *dso, struct machine *machine) | 139 | static int open_dso(struct dso *dso, struct machine *machine) |
139 | { | 140 | { |
140 | char *root_dir = (char *) ""; | ||
141 | char *name; | ||
142 | int fd; | 141 | int fd; |
142 | char *root_dir = (char *)""; | ||
143 | char *name = malloc(PATH_MAX); | ||
143 | 144 | ||
144 | name = malloc(PATH_MAX); | ||
145 | if (!name) | 145 | if (!name) |
146 | return -ENOMEM; | 146 | return -ENOMEM; |
147 | 147 | ||
148 | if (machine) | 148 | if (machine) |
149 | root_dir = machine->root_dir; | 149 | root_dir = machine->root_dir; |
150 | 150 | ||
151 | if (dso__binary_type_file(dso, dso->data_type, | 151 | if (dso__read_binary_type_filename(dso, dso->binary_type, |
152 | root_dir, name, PATH_MAX)) { | 152 | root_dir, name, PATH_MAX)) { |
153 | free(name); | 153 | free(name); |
154 | return -EINVAL; | 154 | return -EINVAL; |
155 | } | 155 | } |
@@ -161,26 +161,26 @@ static int open_dso(struct dso *dso, struct machine *machine) | |||
161 | 161 | ||
162 | int dso__data_fd(struct dso *dso, struct machine *machine) | 162 | int dso__data_fd(struct dso *dso, struct machine *machine) |
163 | { | 163 | { |
164 | static enum dso_binary_type binary_type_data[] = { | 164 | enum dso_binary_type binary_type_data[] = { |
165 | DSO_BINARY_TYPE__BUILD_ID_CACHE, | 165 | DSO_BINARY_TYPE__BUILD_ID_CACHE, |
166 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, | 166 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, |
167 | DSO_BINARY_TYPE__NOT_FOUND, | 167 | DSO_BINARY_TYPE__NOT_FOUND, |
168 | }; | 168 | }; |
169 | int i = 0; | 169 | int i = 0; |
170 | 170 | ||
171 | if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND) | 171 | if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) |
172 | return open_dso(dso, machine); | 172 | return open_dso(dso, machine); |
173 | 173 | ||
174 | do { | 174 | do { |
175 | int fd; | 175 | int fd; |
176 | 176 | ||
177 | dso->data_type = binary_type_data[i++]; | 177 | dso->binary_type = binary_type_data[i++]; |
178 | 178 | ||
179 | fd = open_dso(dso, machine); | 179 | fd = open_dso(dso, machine); |
180 | if (fd >= 0) | 180 | if (fd >= 0) |
181 | return fd; | 181 | return fd; |
182 | 182 | ||
183 | } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND); | 183 | } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND); |
184 | 184 | ||
185 | return -EINVAL; | 185 | return -EINVAL; |
186 | } | 186 | } |
@@ -200,11 +200,10 @@ dso_cache__free(struct rb_root *root) | |||
200 | } | 200 | } |
201 | } | 201 | } |
202 | 202 | ||
203 | static struct dso_cache* | 203 | static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset) |
204 | dso_cache__find(struct rb_root *root, u64 offset) | ||
205 | { | 204 | { |
206 | struct rb_node **p = &root->rb_node; | 205 | struct rb_node * const *p = &root->rb_node; |
207 | struct rb_node *parent = NULL; | 206 | const struct rb_node *parent = NULL; |
208 | struct dso_cache *cache; | 207 | struct dso_cache *cache; |
209 | 208 | ||
210 | while (*p != NULL) { | 209 | while (*p != NULL) { |
@@ -379,32 +378,63 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name, | |||
379 | * processing we had no idea this was the kernel dso. | 378 | * processing we had no idea this was the kernel dso. |
380 | */ | 379 | */ |
381 | if (dso != NULL) { | 380 | if (dso != NULL) { |
382 | dso__set_short_name(dso, short_name); | 381 | dso__set_short_name(dso, short_name, false); |
383 | dso->kernel = dso_type; | 382 | dso->kernel = dso_type; |
384 | } | 383 | } |
385 | 384 | ||
386 | return dso; | 385 | return dso; |
387 | } | 386 | } |
388 | 387 | ||
389 | void dso__set_long_name(struct dso *dso, char *name) | 388 | void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) |
390 | { | 389 | { |
391 | if (name == NULL) | 390 | if (name == NULL) |
392 | return; | 391 | return; |
393 | dso->long_name = name; | 392 | |
394 | dso->long_name_len = strlen(name); | 393 | if (dso->long_name_allocated) |
394 | free((char *)dso->long_name); | ||
395 | |||
396 | dso->long_name = name; | ||
397 | dso->long_name_len = strlen(name); | ||
398 | dso->long_name_allocated = name_allocated; | ||
395 | } | 399 | } |
396 | 400 | ||
397 | void dso__set_short_name(struct dso *dso, const char *name) | 401 | void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated) |
398 | { | 402 | { |
399 | if (name == NULL) | 403 | if (name == NULL) |
400 | return; | 404 | return; |
401 | dso->short_name = name; | 405 | |
402 | dso->short_name_len = strlen(name); | 406 | if (dso->short_name_allocated) |
407 | free((char *)dso->short_name); | ||
408 | |||
409 | dso->short_name = name; | ||
410 | dso->short_name_len = strlen(name); | ||
411 | dso->short_name_allocated = name_allocated; | ||
403 | } | 412 | } |
404 | 413 | ||
405 | static void dso__set_basename(struct dso *dso) | 414 | static void dso__set_basename(struct dso *dso) |
406 | { | 415 | { |
407 | dso__set_short_name(dso, basename(dso->long_name)); | 416 | /* |
417 | * basename() may modify path buffer, so we must pass | ||
418 | * a copy. | ||
419 | */ | ||
420 | char *base, *lname = strdup(dso->long_name); | ||
421 | |||
422 | if (!lname) | ||
423 | return; | ||
424 | |||
425 | /* | ||
426 | * basename() may return a pointer to internal | ||
427 | * storage which is reused in subsequent calls | ||
428 | * so copy the result. | ||
429 | */ | ||
430 | base = strdup(basename(lname)); | ||
431 | |||
432 | free(lname); | ||
433 | |||
434 | if (!base) | ||
435 | return; | ||
436 | |||
437 | dso__set_short_name(dso, base, true); | ||
408 | } | 438 | } |
409 | 439 | ||
410 | int dso__name_len(const struct dso *dso) | 440 | int dso__name_len(const struct dso *dso) |
@@ -439,18 +469,19 @@ struct dso *dso__new(const char *name) | |||
439 | if (dso != NULL) { | 469 | if (dso != NULL) { |
440 | int i; | 470 | int i; |
441 | strcpy(dso->name, name); | 471 | strcpy(dso->name, name); |
442 | dso__set_long_name(dso, dso->name); | 472 | dso__set_long_name(dso, dso->name, false); |
443 | dso__set_short_name(dso, dso->name); | 473 | dso__set_short_name(dso, dso->name, false); |
444 | for (i = 0; i < MAP__NR_TYPES; ++i) | 474 | for (i = 0; i < MAP__NR_TYPES; ++i) |
445 | dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; | 475 | dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; |
446 | dso->cache = RB_ROOT; | 476 | dso->cache = RB_ROOT; |
447 | dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; | 477 | dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; |
448 | dso->data_type = DSO_BINARY_TYPE__NOT_FOUND; | 478 | dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND; |
449 | dso->loaded = 0; | 479 | dso->loaded = 0; |
450 | dso->rel = 0; | 480 | dso->rel = 0; |
451 | dso->sorted_by_name = 0; | 481 | dso->sorted_by_name = 0; |
452 | dso->has_build_id = 0; | 482 | dso->has_build_id = 0; |
453 | dso->has_srcline = 1; | 483 | dso->has_srcline = 1; |
484 | dso->a2l_fails = 1; | ||
454 | dso->kernel = DSO_TYPE_USER; | 485 | dso->kernel = DSO_TYPE_USER; |
455 | dso->needs_swap = DSO_SWAP__UNSET; | 486 | dso->needs_swap = DSO_SWAP__UNSET; |
456 | INIT_LIST_HEAD(&dso->node); | 487 | INIT_LIST_HEAD(&dso->node); |
@@ -464,11 +495,20 @@ void dso__delete(struct dso *dso) | |||
464 | int i; | 495 | int i; |
465 | for (i = 0; i < MAP__NR_TYPES; ++i) | 496 | for (i = 0; i < MAP__NR_TYPES; ++i) |
466 | symbols__delete(&dso->symbols[i]); | 497 | symbols__delete(&dso->symbols[i]); |
467 | if (dso->sname_alloc) | 498 | |
468 | free((char *)dso->short_name); | 499 | if (dso->short_name_allocated) { |
469 | if (dso->lname_alloc) | 500 | zfree((char **)&dso->short_name); |
470 | free(dso->long_name); | 501 | dso->short_name_allocated = false; |
502 | } | ||
503 | |||
504 | if (dso->long_name_allocated) { | ||
505 | zfree((char **)&dso->long_name); | ||
506 | dso->long_name_allocated = false; | ||
507 | } | ||
508 | |||
471 | dso_cache__free(&dso->cache); | 509 | dso_cache__free(&dso->cache); |
510 | dso__free_a2l(dso); | ||
511 | zfree(&dso->symsrc_filename); | ||
472 | free(dso); | 512 | free(dso); |
473 | } | 513 | } |
474 | 514 | ||
@@ -543,7 +583,7 @@ void dsos__add(struct list_head *head, struct dso *dso) | |||
543 | list_add_tail(&dso->node, head); | 583 | list_add_tail(&dso->node, head); |
544 | } | 584 | } |
545 | 585 | ||
546 | struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short) | 586 | struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short) |
547 | { | 587 | { |
548 | struct dso *pos; | 588 | struct dso *pos; |
549 | 589 | ||
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 9ac666abbe7e..cd7d6f078cdd 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -77,23 +77,26 @@ struct dso { | |||
77 | struct rb_root symbols[MAP__NR_TYPES]; | 77 | struct rb_root symbols[MAP__NR_TYPES]; |
78 | struct rb_root symbol_names[MAP__NR_TYPES]; | 78 | struct rb_root symbol_names[MAP__NR_TYPES]; |
79 | struct rb_root cache; | 79 | struct rb_root cache; |
80 | void *a2l; | ||
81 | char *symsrc_filename; | ||
82 | unsigned int a2l_fails; | ||
80 | enum dso_kernel_type kernel; | 83 | enum dso_kernel_type kernel; |
81 | enum dso_swap_type needs_swap; | 84 | enum dso_swap_type needs_swap; |
82 | enum dso_binary_type symtab_type; | 85 | enum dso_binary_type symtab_type; |
83 | enum dso_binary_type data_type; | 86 | enum dso_binary_type binary_type; |
84 | u8 adjust_symbols:1; | 87 | u8 adjust_symbols:1; |
85 | u8 has_build_id:1; | 88 | u8 has_build_id:1; |
86 | u8 has_srcline:1; | 89 | u8 has_srcline:1; |
87 | u8 hit:1; | 90 | u8 hit:1; |
88 | u8 annotate_warned:1; | 91 | u8 annotate_warned:1; |
89 | u8 sname_alloc:1; | 92 | u8 short_name_allocated:1; |
90 | u8 lname_alloc:1; | 93 | u8 long_name_allocated:1; |
91 | u8 sorted_by_name; | 94 | u8 sorted_by_name; |
92 | u8 loaded; | 95 | u8 loaded; |
93 | u8 rel; | 96 | u8 rel; |
94 | u8 build_id[BUILD_ID_SIZE]; | 97 | u8 build_id[BUILD_ID_SIZE]; |
95 | const char *short_name; | 98 | const char *short_name; |
96 | char *long_name; | 99 | const char *long_name; |
97 | u16 long_name_len; | 100 | u16 long_name_len; |
98 | u16 short_name_len; | 101 | u16 short_name_len; |
99 | char name[0]; | 102 | char name[0]; |
@@ -107,8 +110,8 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type) | |||
107 | struct dso *dso__new(const char *name); | 110 | struct dso *dso__new(const char *name); |
108 | void dso__delete(struct dso *dso); | 111 | void dso__delete(struct dso *dso); |
109 | 112 | ||
110 | void dso__set_short_name(struct dso *dso, const char *name); | 113 | void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated); |
111 | void dso__set_long_name(struct dso *dso, char *name); | 114 | void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated); |
112 | 115 | ||
113 | int dso__name_len(const struct dso *dso); | 116 | int dso__name_len(const struct dso *dso); |
114 | 117 | ||
@@ -125,8 +128,8 @@ void dso__read_running_kernel_build_id(struct dso *dso, | |||
125 | int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); | 128 | int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); |
126 | 129 | ||
127 | char dso__symtab_origin(const struct dso *dso); | 130 | char dso__symtab_origin(const struct dso *dso); |
128 | int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | 131 | int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, |
129 | char *root_dir, char *file, size_t size); | 132 | char *root_dir, char *filename, size_t size); |
130 | 133 | ||
131 | int dso__data_fd(struct dso *dso, struct machine *machine); | 134 | int dso__data_fd(struct dso *dso, struct machine *machine); |
132 | ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, | 135 | ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, |
@@ -140,7 +143,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name, | |||
140 | const char *short_name, int dso_type); | 143 | const char *short_name, int dso_type); |
141 | 144 | ||
142 | void dsos__add(struct list_head *head, struct dso *dso); | 145 | void dsos__add(struct list_head *head, struct dso *dso); |
143 | struct dso *dsos__find(struct list_head *head, const char *name, | 146 | struct dso *dsos__find(const struct list_head *head, const char *name, |
144 | bool cmp_short); | 147 | bool cmp_short); |
145 | struct dso *__dsos__findnew(struct list_head *head, const char *name); | 148 | struct dso *__dsos__findnew(struct list_head *head, const char *name); |
146 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits); | 149 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits); |
@@ -156,14 +159,16 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); | |||
156 | 159 | ||
157 | static inline bool dso__is_vmlinux(struct dso *dso) | 160 | static inline bool dso__is_vmlinux(struct dso *dso) |
158 | { | 161 | { |
159 | return dso->data_type == DSO_BINARY_TYPE__VMLINUX || | 162 | return dso->binary_type == DSO_BINARY_TYPE__VMLINUX || |
160 | dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX; | 163 | dso->binary_type == DSO_BINARY_TYPE__GUEST_VMLINUX; |
161 | } | 164 | } |
162 | 165 | ||
163 | static inline bool dso__is_kcore(struct dso *dso) | 166 | static inline bool dso__is_kcore(struct dso *dso) |
164 | { | 167 | { |
165 | return dso->data_type == DSO_BINARY_TYPE__KCORE || | 168 | return dso->binary_type == DSO_BINARY_TYPE__KCORE || |
166 | dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE; | 169 | dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE; |
167 | } | 170 | } |
168 | 171 | ||
172 | void dso__free_a2l(struct dso *dso); | ||
173 | |||
169 | #endif /* __PERF_DSO */ | 174 | #endif /* __PERF_DSO */ |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index bb788c109fe6..1fc1c2f04772 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "strlist.h" | 7 | #include "strlist.h" |
8 | #include "thread.h" | 8 | #include "thread.h" |
9 | #include "thread_map.h" | 9 | #include "thread_map.h" |
10 | #include "symbol/kallsyms.h" | ||
10 | 11 | ||
11 | static const char *perf_event__names[] = { | 12 | static const char *perf_event__names[] = { |
12 | [0] = "TOTAL", | 13 | [0] = "TOTAL", |
@@ -105,8 +106,12 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | |||
105 | 106 | ||
106 | memset(&event->comm, 0, sizeof(event->comm)); | 107 | memset(&event->comm, 0, sizeof(event->comm)); |
107 | 108 | ||
108 | tgid = perf_event__get_comm_tgid(pid, event->comm.comm, | 109 | if (machine__is_host(machine)) |
109 | sizeof(event->comm.comm)); | 110 | tgid = perf_event__get_comm_tgid(pid, event->comm.comm, |
111 | sizeof(event->comm.comm)); | ||
112 | else | ||
113 | tgid = machine->pid; | ||
114 | |||
110 | if (tgid < 0) | 115 | if (tgid < 0) |
111 | goto out; | 116 | goto out; |
112 | 117 | ||
@@ -128,7 +133,11 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | |||
128 | goto out; | 133 | goto out; |
129 | } | 134 | } |
130 | 135 | ||
131 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); | 136 | if (machine__is_default_guest(machine)) |
137 | return 0; | ||
138 | |||
139 | snprintf(filename, sizeof(filename), "%s/proc/%d/task", | ||
140 | machine->root_dir, pid); | ||
132 | 141 | ||
133 | tasks = opendir(filename); | 142 | tasks = opendir(filename); |
134 | if (tasks == NULL) { | 143 | if (tasks == NULL) { |
@@ -166,18 +175,22 @@ out: | |||
166 | return tgid; | 175 | return tgid; |
167 | } | 176 | } |
168 | 177 | ||
169 | static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | 178 | int perf_event__synthesize_mmap_events(struct perf_tool *tool, |
170 | union perf_event *event, | 179 | union perf_event *event, |
171 | pid_t pid, pid_t tgid, | 180 | pid_t pid, pid_t tgid, |
172 | perf_event__handler_t process, | 181 | perf_event__handler_t process, |
173 | struct machine *machine, | 182 | struct machine *machine, |
174 | bool mmap_data) | 183 | bool mmap_data) |
175 | { | 184 | { |
176 | char filename[PATH_MAX]; | 185 | char filename[PATH_MAX]; |
177 | FILE *fp; | 186 | FILE *fp; |
178 | int rc = 0; | 187 | int rc = 0; |
179 | 188 | ||
180 | snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); | 189 | if (machine__is_default_guest(machine)) |
190 | return 0; | ||
191 | |||
192 | snprintf(filename, sizeof(filename), "%s/proc/%d/maps", | ||
193 | machine->root_dir, pid); | ||
181 | 194 | ||
182 | fp = fopen(filename, "r"); | 195 | fp = fopen(filename, "r"); |
183 | if (fp == NULL) { | 196 | if (fp == NULL) { |
@@ -217,7 +230,10 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
217 | /* | 230 | /* |
218 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c | 231 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c |
219 | */ | 232 | */ |
220 | event->header.misc = PERF_RECORD_MISC_USER; | 233 | if (machine__is_host(machine)) |
234 | event->header.misc = PERF_RECORD_MISC_USER; | ||
235 | else | ||
236 | event->header.misc = PERF_RECORD_MISC_GUEST_USER; | ||
221 | 237 | ||
222 | if (prot[2] != 'x') { | 238 | if (prot[2] != 'x') { |
223 | if (!mmap_data || prot[0] != 'r') | 239 | if (!mmap_data || prot[0] != 'r') |
@@ -386,6 +402,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, | |||
386 | struct machine *machine, bool mmap_data) | 402 | struct machine *machine, bool mmap_data) |
387 | { | 403 | { |
388 | DIR *proc; | 404 | DIR *proc; |
405 | char proc_path[PATH_MAX]; | ||
389 | struct dirent dirent, *next; | 406 | struct dirent dirent, *next; |
390 | union perf_event *comm_event, *mmap_event; | 407 | union perf_event *comm_event, *mmap_event; |
391 | int err = -1; | 408 | int err = -1; |
@@ -398,7 +415,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool, | |||
398 | if (mmap_event == NULL) | 415 | if (mmap_event == NULL) |
399 | goto out_free_comm; | 416 | goto out_free_comm; |
400 | 417 | ||
401 | proc = opendir("/proc"); | 418 | if (machine__is_default_guest(machine)) |
419 | return 0; | ||
420 | |||
421 | snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); | ||
422 | proc = opendir(proc_path); | ||
423 | |||
402 | if (proc == NULL) | 424 | if (proc == NULL) |
403 | goto out_free_mmap; | 425 | goto out_free_mmap; |
404 | 426 | ||
@@ -637,6 +659,7 @@ void thread__find_addr_map(struct thread *thread, | |||
637 | struct map_groups *mg = &thread->mg; | 659 | struct map_groups *mg = &thread->mg; |
638 | bool load_map = false; | 660 | bool load_map = false; |
639 | 661 | ||
662 | al->machine = machine; | ||
640 | al->thread = thread; | 663 | al->thread = thread; |
641 | al->addr = addr; | 664 | al->addr = addr; |
642 | al->cpumode = cpumode; | 665 | al->cpumode = cpumode; |
@@ -657,15 +680,10 @@ void thread__find_addr_map(struct thread *thread, | |||
657 | al->level = 'g'; | 680 | al->level = 'g'; |
658 | mg = &machine->kmaps; | 681 | mg = &machine->kmaps; |
659 | load_map = true; | 682 | load_map = true; |
683 | } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) { | ||
684 | al->level = 'u'; | ||
660 | } else { | 685 | } else { |
661 | /* | 686 | al->level = 'H'; |
662 | * 'u' means guest os user space. | ||
663 | * TODO: We don't support guest user space. Might support late. | ||
664 | */ | ||
665 | if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) | ||
666 | al->level = 'u'; | ||
667 | else | ||
668 | al->level = 'H'; | ||
669 | al->map = NULL; | 687 | al->map = NULL; |
670 | 688 | ||
671 | if ((cpumode == PERF_RECORD_MISC_GUEST_USER || | 689 | if ((cpumode == PERF_RECORD_MISC_GUEST_USER || |
@@ -732,8 +750,7 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
732 | if (thread == NULL) | 750 | if (thread == NULL) |
733 | return -1; | 751 | return -1; |
734 | 752 | ||
735 | if (symbol_conf.comm_list && | 753 | if (thread__is_filtered(thread)) |
736 | !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) | ||
737 | goto out_filtered; | 754 | goto out_filtered; |
738 | 755 | ||
739 | dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); | 756 | dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 30fec9901e44..faf6e219be21 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -266,6 +266,13 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
266 | const struct perf_sample *sample, | 266 | const struct perf_sample *sample, |
267 | bool swapped); | 267 | bool swapped); |
268 | 268 | ||
269 | int perf_event__synthesize_mmap_events(struct perf_tool *tool, | ||
270 | union perf_event *event, | ||
271 | pid_t pid, pid_t tgid, | ||
272 | perf_event__handler_t process, | ||
273 | struct machine *machine, | ||
274 | bool mmap_data); | ||
275 | |||
269 | size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); | 276 | size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); |
270 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); | 277 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); |
271 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); | 278 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index bbc746aa5716..40bd2c04df8a 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Released under the GPL v2. (and only v2, not any later version) | 7 | * Released under the GPL v2. (and only v2, not any later version) |
8 | */ | 8 | */ |
9 | #include "util.h" | 9 | #include "util.h" |
10 | #include <lk/debugfs.h> | 10 | #include <api/fs/debugfs.h> |
11 | #include <poll.h> | 11 | #include <poll.h> |
12 | #include "cpumap.h" | 12 | #include "cpumap.h" |
13 | #include "thread_map.h" | 13 | #include "thread_map.h" |
@@ -81,7 +81,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist) | |||
81 | { | 81 | { |
82 | struct perf_evsel *evsel; | 82 | struct perf_evsel *evsel; |
83 | 83 | ||
84 | list_for_each_entry(evsel, &evlist->entries, node) | 84 | evlist__for_each(evlist, evsel) |
85 | perf_evsel__calc_id_pos(evsel); | 85 | perf_evsel__calc_id_pos(evsel); |
86 | 86 | ||
87 | perf_evlist__set_id_pos(evlist); | 87 | perf_evlist__set_id_pos(evlist); |
@@ -91,7 +91,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist) | |||
91 | { | 91 | { |
92 | struct perf_evsel *pos, *n; | 92 | struct perf_evsel *pos, *n; |
93 | 93 | ||
94 | list_for_each_entry_safe(pos, n, &evlist->entries, node) { | 94 | evlist__for_each_safe(evlist, n, pos) { |
95 | list_del_init(&pos->node); | 95 | list_del_init(&pos->node); |
96 | perf_evsel__delete(pos); | 96 | perf_evsel__delete(pos); |
97 | } | 97 | } |
@@ -101,14 +101,18 @@ static void perf_evlist__purge(struct perf_evlist *evlist) | |||
101 | 101 | ||
102 | void perf_evlist__exit(struct perf_evlist *evlist) | 102 | void perf_evlist__exit(struct perf_evlist *evlist) |
103 | { | 103 | { |
104 | free(evlist->mmap); | 104 | zfree(&evlist->mmap); |
105 | free(evlist->pollfd); | 105 | zfree(&evlist->pollfd); |
106 | evlist->mmap = NULL; | ||
107 | evlist->pollfd = NULL; | ||
108 | } | 106 | } |
109 | 107 | ||
110 | void perf_evlist__delete(struct perf_evlist *evlist) | 108 | void perf_evlist__delete(struct perf_evlist *evlist) |
111 | { | 109 | { |
110 | perf_evlist__munmap(evlist); | ||
111 | perf_evlist__close(evlist); | ||
112 | cpu_map__delete(evlist->cpus); | ||
113 | thread_map__delete(evlist->threads); | ||
114 | evlist->cpus = NULL; | ||
115 | evlist->threads = NULL; | ||
112 | perf_evlist__purge(evlist); | 116 | perf_evlist__purge(evlist); |
113 | perf_evlist__exit(evlist); | 117 | perf_evlist__exit(evlist); |
114 | free(evlist); | 118 | free(evlist); |
@@ -144,7 +148,7 @@ void __perf_evlist__set_leader(struct list_head *list) | |||
144 | 148 | ||
145 | leader->nr_members = evsel->idx - leader->idx + 1; | 149 | leader->nr_members = evsel->idx - leader->idx + 1; |
146 | 150 | ||
147 | list_for_each_entry(evsel, list, node) { | 151 | __evlist__for_each(list, evsel) { |
148 | evsel->leader = leader; | 152 | evsel->leader = leader; |
149 | } | 153 | } |
150 | } | 154 | } |
@@ -203,7 +207,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, | |||
203 | return 0; | 207 | return 0; |
204 | 208 | ||
205 | out_delete_partial_list: | 209 | out_delete_partial_list: |
206 | list_for_each_entry_safe(evsel, n, &head, node) | 210 | __evlist__for_each_safe(&head, n, evsel) |
207 | perf_evsel__delete(evsel); | 211 | perf_evsel__delete(evsel); |
208 | return -1; | 212 | return -1; |
209 | } | 213 | } |
@@ -224,7 +228,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) | |||
224 | { | 228 | { |
225 | struct perf_evsel *evsel; | 229 | struct perf_evsel *evsel; |
226 | 230 | ||
227 | list_for_each_entry(evsel, &evlist->entries, node) { | 231 | evlist__for_each(evlist, evsel) { |
228 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT && | 232 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT && |
229 | (int)evsel->attr.config == id) | 233 | (int)evsel->attr.config == id) |
230 | return evsel; | 234 | return evsel; |
@@ -239,7 +243,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, | |||
239 | { | 243 | { |
240 | struct perf_evsel *evsel; | 244 | struct perf_evsel *evsel; |
241 | 245 | ||
242 | list_for_each_entry(evsel, &evlist->entries, node) { | 246 | evlist__for_each(evlist, evsel) { |
243 | if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && | 247 | if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && |
244 | (strcmp(evsel->name, name) == 0)) | 248 | (strcmp(evsel->name, name) == 0)) |
245 | return evsel; | 249 | return evsel; |
@@ -269,7 +273,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) | |||
269 | int nr_threads = thread_map__nr(evlist->threads); | 273 | int nr_threads = thread_map__nr(evlist->threads); |
270 | 274 | ||
271 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 275 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
272 | list_for_each_entry(pos, &evlist->entries, node) { | 276 | evlist__for_each(evlist, pos) { |
273 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 277 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
274 | continue; | 278 | continue; |
275 | for (thread = 0; thread < nr_threads; thread++) | 279 | for (thread = 0; thread < nr_threads; thread++) |
@@ -287,7 +291,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) | |||
287 | int nr_threads = thread_map__nr(evlist->threads); | 291 | int nr_threads = thread_map__nr(evlist->threads); |
288 | 292 | ||
289 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 293 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
290 | list_for_each_entry(pos, &evlist->entries, node) { | 294 | evlist__for_each(evlist, pos) { |
291 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 295 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
292 | continue; | 296 | continue; |
293 | for (thread = 0; thread < nr_threads; thread++) | 297 | for (thread = 0; thread < nr_threads; thread++) |
@@ -584,11 +588,13 @@ void perf_evlist__munmap(struct perf_evlist *evlist) | |||
584 | { | 588 | { |
585 | int i; | 589 | int i; |
586 | 590 | ||
591 | if (evlist->mmap == NULL) | ||
592 | return; | ||
593 | |||
587 | for (i = 0; i < evlist->nr_mmaps; i++) | 594 | for (i = 0; i < evlist->nr_mmaps; i++) |
588 | __perf_evlist__munmap(evlist, i); | 595 | __perf_evlist__munmap(evlist, i); |
589 | 596 | ||
590 | free(evlist->mmap); | 597 | zfree(&evlist->mmap); |
591 | evlist->mmap = NULL; | ||
592 | } | 598 | } |
593 | 599 | ||
594 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | 600 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) |
@@ -624,7 +630,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
624 | { | 630 | { |
625 | struct perf_evsel *evsel; | 631 | struct perf_evsel *evsel; |
626 | 632 | ||
627 | list_for_each_entry(evsel, &evlist->entries, node) { | 633 | evlist__for_each(evlist, evsel) { |
628 | int fd = FD(evsel, cpu, thread); | 634 | int fd = FD(evsel, cpu, thread); |
629 | 635 | ||
630 | if (*output == -1) { | 636 | if (*output == -1) { |
@@ -732,11 +738,13 @@ static long parse_pages_arg(const char *str, unsigned long min, | |||
732 | return -EINVAL; | 738 | return -EINVAL; |
733 | } | 739 | } |
734 | 740 | ||
735 | if ((pages == 0) && (min == 0)) { | 741 | if (pages == 0 && min == 0) { |
736 | /* leave number of pages at 0 */ | 742 | /* leave number of pages at 0 */ |
737 | } else if (pages < (1UL << 31) && !is_power_of_2(pages)) { | 743 | } else if (!is_power_of_2(pages)) { |
738 | /* round pages up to next power of 2 */ | 744 | /* round pages up to next power of 2 */ |
739 | pages = next_pow2(pages); | 745 | pages = next_pow2_l(pages); |
746 | if (!pages) | ||
747 | return -EINVAL; | ||
740 | pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", | 748 | pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", |
741 | pages * page_size, pages); | 749 | pages * page_size, pages); |
742 | } | 750 | } |
@@ -754,7 +762,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, | |||
754 | unsigned long max = UINT_MAX; | 762 | unsigned long max = UINT_MAX; |
755 | long pages; | 763 | long pages; |
756 | 764 | ||
757 | if (max < SIZE_MAX / page_size) | 765 | if (max > SIZE_MAX / page_size) |
758 | max = SIZE_MAX / page_size; | 766 | max = SIZE_MAX / page_size; |
759 | 767 | ||
760 | pages = parse_pages_arg(str, 1, max); | 768 | pages = parse_pages_arg(str, 1, max); |
@@ -798,7 +806,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, | |||
798 | pr_debug("mmap size %zuB\n", evlist->mmap_len); | 806 | pr_debug("mmap size %zuB\n", evlist->mmap_len); |
799 | mask = evlist->mmap_len - page_size - 1; | 807 | mask = evlist->mmap_len - page_size - 1; |
800 | 808 | ||
801 | list_for_each_entry(evsel, &evlist->entries, node) { | 809 | evlist__for_each(evlist, evsel) { |
802 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 810 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
803 | evsel->sample_id == NULL && | 811 | evsel->sample_id == NULL && |
804 | perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) | 812 | perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) |
@@ -819,11 +827,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) | |||
819 | if (evlist->threads == NULL) | 827 | if (evlist->threads == NULL) |
820 | return -1; | 828 | return -1; |
821 | 829 | ||
822 | if (target->force_per_cpu) | 830 | if (target__uses_dummy_map(target)) |
823 | evlist->cpus = cpu_map__new(target->cpu_list); | ||
824 | else if (target__has_task(target)) | ||
825 | evlist->cpus = cpu_map__dummy_new(); | ||
826 | else if (!target__has_cpu(target) && !target->uses_mmap) | ||
827 | evlist->cpus = cpu_map__dummy_new(); | 831 | evlist->cpus = cpu_map__dummy_new(); |
828 | else | 832 | else |
829 | evlist->cpus = cpu_map__new(target->cpu_list); | 833 | evlist->cpus = cpu_map__new(target->cpu_list); |
@@ -838,14 +842,6 @@ out_delete_threads: | |||
838 | return -1; | 842 | return -1; |
839 | } | 843 | } |
840 | 844 | ||
841 | void perf_evlist__delete_maps(struct perf_evlist *evlist) | ||
842 | { | ||
843 | cpu_map__delete(evlist->cpus); | ||
844 | thread_map__delete(evlist->threads); | ||
845 | evlist->cpus = NULL; | ||
846 | evlist->threads = NULL; | ||
847 | } | ||
848 | |||
849 | int perf_evlist__apply_filters(struct perf_evlist *evlist) | 845 | int perf_evlist__apply_filters(struct perf_evlist *evlist) |
850 | { | 846 | { |
851 | struct perf_evsel *evsel; | 847 | struct perf_evsel *evsel; |
@@ -853,7 +849,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist) | |||
853 | const int ncpus = cpu_map__nr(evlist->cpus), | 849 | const int ncpus = cpu_map__nr(evlist->cpus), |
854 | nthreads = thread_map__nr(evlist->threads); | 850 | nthreads = thread_map__nr(evlist->threads); |
855 | 851 | ||
856 | list_for_each_entry(evsel, &evlist->entries, node) { | 852 | evlist__for_each(evlist, evsel) { |
857 | if (evsel->filter == NULL) | 853 | if (evsel->filter == NULL) |
858 | continue; | 854 | continue; |
859 | 855 | ||
@@ -872,7 +868,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) | |||
872 | const int ncpus = cpu_map__nr(evlist->cpus), | 868 | const int ncpus = cpu_map__nr(evlist->cpus), |
873 | nthreads = thread_map__nr(evlist->threads); | 869 | nthreads = thread_map__nr(evlist->threads); |
874 | 870 | ||
875 | list_for_each_entry(evsel, &evlist->entries, node) { | 871 | evlist__for_each(evlist, evsel) { |
876 | err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); | 872 | err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); |
877 | if (err) | 873 | if (err) |
878 | break; | 874 | break; |
@@ -891,7 +887,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) | |||
891 | if (evlist->id_pos < 0 || evlist->is_pos < 0) | 887 | if (evlist->id_pos < 0 || evlist->is_pos < 0) |
892 | return false; | 888 | return false; |
893 | 889 | ||
894 | list_for_each_entry(pos, &evlist->entries, node) { | 890 | evlist__for_each(evlist, pos) { |
895 | if (pos->id_pos != evlist->id_pos || | 891 | if (pos->id_pos != evlist->id_pos || |
896 | pos->is_pos != evlist->is_pos) | 892 | pos->is_pos != evlist->is_pos) |
897 | return false; | 893 | return false; |
@@ -907,7 +903,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) | |||
907 | if (evlist->combined_sample_type) | 903 | if (evlist->combined_sample_type) |
908 | return evlist->combined_sample_type; | 904 | return evlist->combined_sample_type; |
909 | 905 | ||
910 | list_for_each_entry(evsel, &evlist->entries, node) | 906 | evlist__for_each(evlist, evsel) |
911 | evlist->combined_sample_type |= evsel->attr.sample_type; | 907 | evlist->combined_sample_type |= evsel->attr.sample_type; |
912 | 908 | ||
913 | return evlist->combined_sample_type; | 909 | return evlist->combined_sample_type; |
@@ -925,7 +921,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist) | |||
925 | u64 read_format = first->attr.read_format; | 921 | u64 read_format = first->attr.read_format; |
926 | u64 sample_type = first->attr.sample_type; | 922 | u64 sample_type = first->attr.sample_type; |
927 | 923 | ||
928 | list_for_each_entry_continue(pos, &evlist->entries, node) { | 924 | evlist__for_each(evlist, pos) { |
929 | if (read_format != pos->attr.read_format) | 925 | if (read_format != pos->attr.read_format) |
930 | return false; | 926 | return false; |
931 | } | 927 | } |
@@ -982,7 +978,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) | |||
982 | { | 978 | { |
983 | struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; | 979 | struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; |
984 | 980 | ||
985 | list_for_each_entry_continue(pos, &evlist->entries, node) { | 981 | evlist__for_each_continue(evlist, pos) { |
986 | if (first->attr.sample_id_all != pos->attr.sample_id_all) | 982 | if (first->attr.sample_id_all != pos->attr.sample_id_all) |
987 | return false; | 983 | return false; |
988 | } | 984 | } |
@@ -1008,7 +1004,7 @@ void perf_evlist__close(struct perf_evlist *evlist) | |||
1008 | int ncpus = cpu_map__nr(evlist->cpus); | 1004 | int ncpus = cpu_map__nr(evlist->cpus); |
1009 | int nthreads = thread_map__nr(evlist->threads); | 1005 | int nthreads = thread_map__nr(evlist->threads); |
1010 | 1006 | ||
1011 | list_for_each_entry_reverse(evsel, &evlist->entries, node) | 1007 | evlist__for_each_reverse(evlist, evsel) |
1012 | perf_evsel__close(evsel, ncpus, nthreads); | 1008 | perf_evsel__close(evsel, ncpus, nthreads); |
1013 | } | 1009 | } |
1014 | 1010 | ||
@@ -1019,7 +1015,7 @@ int perf_evlist__open(struct perf_evlist *evlist) | |||
1019 | 1015 | ||
1020 | perf_evlist__update_id_pos(evlist); | 1016 | perf_evlist__update_id_pos(evlist); |
1021 | 1017 | ||
1022 | list_for_each_entry(evsel, &evlist->entries, node) { | 1018 | evlist__for_each(evlist, evsel) { |
1023 | err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); | 1019 | err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); |
1024 | if (err < 0) | 1020 | if (err < 0) |
1025 | goto out_err; | 1021 | goto out_err; |
@@ -1034,7 +1030,7 @@ out_err: | |||
1034 | 1030 | ||
1035 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, | 1031 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, |
1036 | const char *argv[], bool pipe_output, | 1032 | const char *argv[], bool pipe_output, |
1037 | bool want_signal) | 1033 | void (*exec_error)(int signo, siginfo_t *info, void *ucontext)) |
1038 | { | 1034 | { |
1039 | int child_ready_pipe[2], go_pipe[2]; | 1035 | int child_ready_pipe[2], go_pipe[2]; |
1040 | char bf; | 1036 | char bf; |
@@ -1078,12 +1074,25 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar | |||
1078 | 1074 | ||
1079 | execvp(argv[0], (char **)argv); | 1075 | execvp(argv[0], (char **)argv); |
1080 | 1076 | ||
1081 | perror(argv[0]); | 1077 | if (exec_error) { |
1082 | if (want_signal) | 1078 | union sigval val; |
1083 | kill(getppid(), SIGUSR1); | 1079 | |
1080 | val.sival_int = errno; | ||
1081 | if (sigqueue(getppid(), SIGUSR1, val)) | ||
1082 | perror(argv[0]); | ||
1083 | } else | ||
1084 | perror(argv[0]); | ||
1084 | exit(-1); | 1085 | exit(-1); |
1085 | } | 1086 | } |
1086 | 1087 | ||
1088 | if (exec_error) { | ||
1089 | struct sigaction act = { | ||
1090 | .sa_flags = SA_SIGINFO, | ||
1091 | .sa_sigaction = exec_error, | ||
1092 | }; | ||
1093 | sigaction(SIGUSR1, &act, NULL); | ||
1094 | } | ||
1095 | |||
1087 | if (target__none(target)) | 1096 | if (target__none(target)) |
1088 | evlist->threads->map[0] = evlist->workload.pid; | 1097 | evlist->threads->map[0] = evlist->workload.pid; |
1089 | 1098 | ||
@@ -1145,7 +1154,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) | |||
1145 | struct perf_evsel *evsel; | 1154 | struct perf_evsel *evsel; |
1146 | size_t printed = 0; | 1155 | size_t printed = 0; |
1147 | 1156 | ||
1148 | list_for_each_entry(evsel, &evlist->entries, node) { | 1157 | evlist__for_each(evlist, evsel) { |
1149 | printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", | 1158 | printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", |
1150 | perf_evsel__name(evsel)); | 1159 | perf_evsel__name(evsel)); |
1151 | } | 1160 | } |
@@ -1193,8 +1202,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, | |||
1193 | "Error:\t%s.\n" | 1202 | "Error:\t%s.\n" |
1194 | "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); | 1203 | "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); |
1195 | 1204 | ||
1196 | if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value)) | 1205 | value = perf_event_paranoid(); |
1197 | break; | ||
1198 | 1206 | ||
1199 | printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); | 1207 | printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); |
1200 | 1208 | ||
@@ -1215,3 +1223,20 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, | |||
1215 | 1223 | ||
1216 | return 0; | 1224 | return 0; |
1217 | } | 1225 | } |
1226 | |||
1227 | void perf_evlist__to_front(struct perf_evlist *evlist, | ||
1228 | struct perf_evsel *move_evsel) | ||
1229 | { | ||
1230 | struct perf_evsel *evsel, *n; | ||
1231 | LIST_HEAD(move); | ||
1232 | |||
1233 | if (move_evsel == perf_evlist__first(evlist)) | ||
1234 | return; | ||
1235 | |||
1236 | evlist__for_each_safe(evlist, n, evsel) { | ||
1237 | if (evsel->leader == move_evsel->leader) | ||
1238 | list_move_tail(&evsel->node, &move); | ||
1239 | } | ||
1240 | |||
1241 | list_splice(&move, &evlist->entries); | ||
1242 | } | ||
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 649d6ea98a84..f5173cd63693 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -12,7 +12,7 @@ | |||
12 | struct pollfd; | 12 | struct pollfd; |
13 | struct thread_map; | 13 | struct thread_map; |
14 | struct cpu_map; | 14 | struct cpu_map; |
15 | struct perf_record_opts; | 15 | struct record_opts; |
16 | 16 | ||
17 | #define PERF_EVLIST__HLIST_BITS 8 | 17 | #define PERF_EVLIST__HLIST_BITS 8 |
18 | #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) | 18 | #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) |
@@ -97,14 +97,14 @@ void perf_evlist__close(struct perf_evlist *evlist); | |||
97 | 97 | ||
98 | void perf_evlist__set_id_pos(struct perf_evlist *evlist); | 98 | void perf_evlist__set_id_pos(struct perf_evlist *evlist); |
99 | bool perf_can_sample_identifier(void); | 99 | bool perf_can_sample_identifier(void); |
100 | void perf_evlist__config(struct perf_evlist *evlist, | 100 | void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts); |
101 | struct perf_record_opts *opts); | 101 | int record_opts__config(struct record_opts *opts); |
102 | int perf_record_opts__config(struct perf_record_opts *opts); | ||
103 | 102 | ||
104 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, | 103 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, |
105 | struct target *target, | 104 | struct target *target, |
106 | const char *argv[], bool pipe_output, | 105 | const char *argv[], bool pipe_output, |
107 | bool want_signal); | 106 | void (*exec_error)(int signo, siginfo_t *info, |
107 | void *ucontext)); | ||
108 | int perf_evlist__start_workload(struct perf_evlist *evlist); | 108 | int perf_evlist__start_workload(struct perf_evlist *evlist); |
109 | 109 | ||
110 | int perf_evlist__parse_mmap_pages(const struct option *opt, | 110 | int perf_evlist__parse_mmap_pages(const struct option *opt, |
@@ -135,7 +135,6 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist, | |||
135 | } | 135 | } |
136 | 136 | ||
137 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); | 137 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); |
138 | void perf_evlist__delete_maps(struct perf_evlist *evlist); | ||
139 | int perf_evlist__apply_filters(struct perf_evlist *evlist); | 138 | int perf_evlist__apply_filters(struct perf_evlist *evlist); |
140 | 139 | ||
141 | void __perf_evlist__set_leader(struct list_head *list); | 140 | void __perf_evlist__set_leader(struct list_head *list); |
@@ -193,4 +192,74 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md, | |||
193 | pc->data_tail = tail; | 192 | pc->data_tail = tail; |
194 | } | 193 | } |
195 | 194 | ||
195 | bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str); | ||
196 | void perf_evlist__to_front(struct perf_evlist *evlist, | ||
197 | struct perf_evsel *move_evsel); | ||
198 | |||
199 | /** | ||
200 | * __evlist__for_each - iterate thru all the evsels | ||
201 | * @list: list_head instance to iterate | ||
202 | * @evsel: struct evsel iterator | ||
203 | */ | ||
204 | #define __evlist__for_each(list, evsel) \ | ||
205 | list_for_each_entry(evsel, list, node) | ||
206 | |||
207 | /** | ||
208 | * evlist__for_each - iterate thru all the evsels | ||
209 | * @evlist: evlist instance to iterate | ||
210 | * @evsel: struct evsel iterator | ||
211 | */ | ||
212 | #define evlist__for_each(evlist, evsel) \ | ||
213 | __evlist__for_each(&(evlist)->entries, evsel) | ||
214 | |||
215 | /** | ||
216 | * __evlist__for_each_continue - continue iteration thru all the evsels | ||
217 | * @list: list_head instance to iterate | ||
218 | * @evsel: struct evsel iterator | ||
219 | */ | ||
220 | #define __evlist__for_each_continue(list, evsel) \ | ||
221 | list_for_each_entry_continue(evsel, list, node) | ||
222 | |||
223 | /** | ||
224 | * evlist__for_each_continue - continue iteration thru all the evsels | ||
225 | * @evlist: evlist instance to iterate | ||
226 | * @evsel: struct evsel iterator | ||
227 | */ | ||
228 | #define evlist__for_each_continue(evlist, evsel) \ | ||
229 | __evlist__for_each_continue(&(evlist)->entries, evsel) | ||
230 | |||
231 | /** | ||
232 | * __evlist__for_each_reverse - iterate thru all the evsels in reverse order | ||
233 | * @list: list_head instance to iterate | ||
234 | * @evsel: struct evsel iterator | ||
235 | */ | ||
236 | #define __evlist__for_each_reverse(list, evsel) \ | ||
237 | list_for_each_entry_reverse(evsel, list, node) | ||
238 | |||
239 | /** | ||
240 | * evlist__for_each_reverse - iterate thru all the evsels in reverse order | ||
241 | * @evlist: evlist instance to iterate | ||
242 | * @evsel: struct evsel iterator | ||
243 | */ | ||
244 | #define evlist__for_each_reverse(evlist, evsel) \ | ||
245 | __evlist__for_each_reverse(&(evlist)->entries, evsel) | ||
246 | |||
247 | /** | ||
248 | * __evlist__for_each_safe - safely iterate thru all the evsels | ||
249 | * @list: list_head instance to iterate | ||
250 | * @tmp: struct evsel temp iterator | ||
251 | * @evsel: struct evsel iterator | ||
252 | */ | ||
253 | #define __evlist__for_each_safe(list, tmp, evsel) \ | ||
254 | list_for_each_entry_safe(evsel, tmp, list, node) | ||
255 | |||
256 | /** | ||
257 | * evlist__for_each_safe - safely iterate thru all the evsels | ||
258 | * @evlist: evlist instance to iterate | ||
259 | * @evsel: struct evsel iterator | ||
260 | * @tmp: struct evsel temp iterator | ||
261 | */ | ||
262 | #define evlist__for_each_safe(evlist, tmp, evsel) \ | ||
263 | __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) | ||
264 | |||
196 | #endif /* __PERF_EVLIST_H */ | 265 | #endif /* __PERF_EVLIST_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 46dd4c2a41ce..22e18a26b7e6 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | #include <byteswap.h> | 10 | #include <byteswap.h> |
11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
12 | #include <lk/debugfs.h> | 12 | #include <api/fs/debugfs.h> |
13 | #include <traceevent/event-parse.h> | 13 | #include <traceevent/event-parse.h> |
14 | #include <linux/hw_breakpoint.h> | 14 | #include <linux/hw_breakpoint.h> |
15 | #include <linux/perf_event.h> | 15 | #include <linux/perf_event.h> |
@@ -23,6 +23,7 @@ | |||
23 | #include "target.h" | 23 | #include "target.h" |
24 | #include "perf_regs.h" | 24 | #include "perf_regs.h" |
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include "trace-event.h" | ||
26 | 27 | ||
27 | static struct { | 28 | static struct { |
28 | bool sample_id_all; | 29 | bool sample_id_all; |
@@ -162,6 +163,8 @@ void perf_evsel__init(struct perf_evsel *evsel, | |||
162 | evsel->idx = idx; | 163 | evsel->idx = idx; |
163 | evsel->attr = *attr; | 164 | evsel->attr = *attr; |
164 | evsel->leader = evsel; | 165 | evsel->leader = evsel; |
166 | evsel->unit = ""; | ||
167 | evsel->scale = 1.0; | ||
165 | INIT_LIST_HEAD(&evsel->node); | 168 | INIT_LIST_HEAD(&evsel->node); |
166 | hists__init(&evsel->hists); | 169 | hists__init(&evsel->hists); |
167 | evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); | 170 | evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); |
@@ -178,47 +181,6 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) | |||
178 | return evsel; | 181 | return evsel; |
179 | } | 182 | } |
180 | 183 | ||
181 | struct event_format *event_format__new(const char *sys, const char *name) | ||
182 | { | ||
183 | int fd, n; | ||
184 | char *filename; | ||
185 | void *bf = NULL, *nbf; | ||
186 | size_t size = 0, alloc_size = 0; | ||
187 | struct event_format *format = NULL; | ||
188 | |||
189 | if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0) | ||
190 | goto out; | ||
191 | |||
192 | fd = open(filename, O_RDONLY); | ||
193 | if (fd < 0) | ||
194 | goto out_free_filename; | ||
195 | |||
196 | do { | ||
197 | if (size == alloc_size) { | ||
198 | alloc_size += BUFSIZ; | ||
199 | nbf = realloc(bf, alloc_size); | ||
200 | if (nbf == NULL) | ||
201 | goto out_free_bf; | ||
202 | bf = nbf; | ||
203 | } | ||
204 | |||
205 | n = read(fd, bf + size, alloc_size - size); | ||
206 | if (n < 0) | ||
207 | goto out_free_bf; | ||
208 | size += n; | ||
209 | } while (n > 0); | ||
210 | |||
211 | pevent_parse_format(&format, bf, size, sys); | ||
212 | |||
213 | out_free_bf: | ||
214 | free(bf); | ||
215 | close(fd); | ||
216 | out_free_filename: | ||
217 | free(filename); | ||
218 | out: | ||
219 | return format; | ||
220 | } | ||
221 | |||
222 | struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) | 184 | struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) |
223 | { | 185 | { |
224 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); | 186 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); |
@@ -233,7 +195,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int | |||
233 | if (asprintf(&evsel->name, "%s:%s", sys, name) < 0) | 195 | if (asprintf(&evsel->name, "%s:%s", sys, name) < 0) |
234 | goto out_free; | 196 | goto out_free; |
235 | 197 | ||
236 | evsel->tp_format = event_format__new(sys, name); | 198 | evsel->tp_format = trace_event__tp_format(sys, name); |
237 | if (evsel->tp_format == NULL) | 199 | if (evsel->tp_format == NULL) |
238 | goto out_free; | 200 | goto out_free; |
239 | 201 | ||
@@ -246,7 +208,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int | |||
246 | return evsel; | 208 | return evsel; |
247 | 209 | ||
248 | out_free: | 210 | out_free: |
249 | free(evsel->name); | 211 | zfree(&evsel->name); |
250 | free(evsel); | 212 | free(evsel); |
251 | return NULL; | 213 | return NULL; |
252 | } | 214 | } |
@@ -566,12 +528,12 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) | |||
566 | * enable/disable events specifically, as there's no | 528 | * enable/disable events specifically, as there's no |
567 | * initial traced exec call. | 529 | * initial traced exec call. |
568 | */ | 530 | */ |
569 | void perf_evsel__config(struct perf_evsel *evsel, | 531 | void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) |
570 | struct perf_record_opts *opts) | ||
571 | { | 532 | { |
572 | struct perf_evsel *leader = evsel->leader; | 533 | struct perf_evsel *leader = evsel->leader; |
573 | struct perf_event_attr *attr = &evsel->attr; | 534 | struct perf_event_attr *attr = &evsel->attr; |
574 | int track = !evsel->idx; /* only the first counter needs these */ | 535 | int track = !evsel->idx; /* only the first counter needs these */ |
536 | bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; | ||
575 | 537 | ||
576 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; | 538 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; |
577 | attr->inherit = !opts->no_inherit; | 539 | attr->inherit = !opts->no_inherit; |
@@ -645,7 +607,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
645 | } | 607 | } |
646 | } | 608 | } |
647 | 609 | ||
648 | if (target__has_cpu(&opts->target) || opts->target.force_per_cpu) | 610 | if (target__has_cpu(&opts->target)) |
649 | perf_evsel__set_sample_bit(evsel, CPU); | 611 | perf_evsel__set_sample_bit(evsel, CPU); |
650 | 612 | ||
651 | if (opts->period) | 613 | if (opts->period) |
@@ -653,7 +615,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
653 | 615 | ||
654 | if (!perf_missing_features.sample_id_all && | 616 | if (!perf_missing_features.sample_id_all && |
655 | (opts->sample_time || !opts->no_inherit || | 617 | (opts->sample_time || !opts->no_inherit || |
656 | target__has_cpu(&opts->target) || opts->target.force_per_cpu)) | 618 | target__has_cpu(&opts->target) || per_cpu)) |
657 | perf_evsel__set_sample_bit(evsel, TIME); | 619 | perf_evsel__set_sample_bit(evsel, TIME); |
658 | 620 | ||
659 | if (opts->raw_samples) { | 621 | if (opts->raw_samples) { |
@@ -665,7 +627,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
665 | if (opts->sample_address) | 627 | if (opts->sample_address) |
666 | perf_evsel__set_sample_bit(evsel, DATA_SRC); | 628 | perf_evsel__set_sample_bit(evsel, DATA_SRC); |
667 | 629 | ||
668 | if (opts->no_delay) { | 630 | if (opts->no_buffering) { |
669 | attr->watermark = 0; | 631 | attr->watermark = 0; |
670 | attr->wakeup_events = 1; | 632 | attr->wakeup_events = 1; |
671 | } | 633 | } |
@@ -696,7 +658,8 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
696 | * Setting enable_on_exec for independent events and | 658 | * Setting enable_on_exec for independent events and |
697 | * group leaders for traced executed by perf. | 659 | * group leaders for traced executed by perf. |
698 | */ | 660 | */ |
699 | if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel)) | 661 | if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel) && |
662 | !opts->initial_delay) | ||
700 | attr->enable_on_exec = 1; | 663 | attr->enable_on_exec = 1; |
701 | } | 664 | } |
702 | 665 | ||
@@ -788,8 +751,7 @@ void perf_evsel__free_id(struct perf_evsel *evsel) | |||
788 | { | 751 | { |
789 | xyarray__delete(evsel->sample_id); | 752 | xyarray__delete(evsel->sample_id); |
790 | evsel->sample_id = NULL; | 753 | evsel->sample_id = NULL; |
791 | free(evsel->id); | 754 | zfree(&evsel->id); |
792 | evsel->id = NULL; | ||
793 | } | 755 | } |
794 | 756 | ||
795 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 757 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
@@ -805,7 +767,7 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | |||
805 | 767 | ||
806 | void perf_evsel__free_counts(struct perf_evsel *evsel) | 768 | void perf_evsel__free_counts(struct perf_evsel *evsel) |
807 | { | 769 | { |
808 | free(evsel->counts); | 770 | zfree(&evsel->counts); |
809 | } | 771 | } |
810 | 772 | ||
811 | void perf_evsel__exit(struct perf_evsel *evsel) | 773 | void perf_evsel__exit(struct perf_evsel *evsel) |
@@ -819,10 +781,10 @@ void perf_evsel__delete(struct perf_evsel *evsel) | |||
819 | { | 781 | { |
820 | perf_evsel__exit(evsel); | 782 | perf_evsel__exit(evsel); |
821 | close_cgroup(evsel->cgrp); | 783 | close_cgroup(evsel->cgrp); |
822 | free(evsel->group_name); | 784 | zfree(&evsel->group_name); |
823 | if (evsel->tp_format) | 785 | if (evsel->tp_format) |
824 | pevent_free_format(evsel->tp_format); | 786 | pevent_free_format(evsel->tp_format); |
825 | free(evsel->name); | 787 | zfree(&evsel->name); |
826 | free(evsel); | 788 | free(evsel); |
827 | } | 789 | } |
828 | 790 | ||
@@ -1998,8 +1960,7 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err, | |||
1998 | evsel->attr.type = PERF_TYPE_SOFTWARE; | 1960 | evsel->attr.type = PERF_TYPE_SOFTWARE; |
1999 | evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; | 1961 | evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; |
2000 | 1962 | ||
2001 | free(evsel->name); | 1963 | zfree(&evsel->name); |
2002 | evsel->name = NULL; | ||
2003 | return true; | 1964 | return true; |
2004 | } | 1965 | } |
2005 | 1966 | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1ea7c92e6e33..f1b325665aae 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -68,6 +68,8 @@ struct perf_evsel { | |||
68 | u32 ids; | 68 | u32 ids; |
69 | struct hists hists; | 69 | struct hists hists; |
70 | char *name; | 70 | char *name; |
71 | double scale; | ||
72 | const char *unit; | ||
71 | struct event_format *tp_format; | 73 | struct event_format *tp_format; |
72 | union { | 74 | union { |
73 | void *priv; | 75 | void *priv; |
@@ -94,7 +96,7 @@ struct perf_evsel { | |||
94 | struct cpu_map; | 96 | struct cpu_map; |
95 | struct thread_map; | 97 | struct thread_map; |
96 | struct perf_evlist; | 98 | struct perf_evlist; |
97 | struct perf_record_opts; | 99 | struct record_opts; |
98 | 100 | ||
99 | struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); | 101 | struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); |
100 | 102 | ||
@@ -118,7 +120,7 @@ void perf_evsel__exit(struct perf_evsel *evsel); | |||
118 | void perf_evsel__delete(struct perf_evsel *evsel); | 120 | void perf_evsel__delete(struct perf_evsel *evsel); |
119 | 121 | ||
120 | void perf_evsel__config(struct perf_evsel *evsel, | 122 | void perf_evsel__config(struct perf_evsel *evsel, |
121 | struct perf_record_opts *opts); | 123 | struct record_opts *opts); |
122 | 124 | ||
123 | int __perf_evsel__sample_size(u64 sample_type); | 125 | int __perf_evsel__sample_size(u64 sample_type); |
124 | void perf_evsel__calc_id_pos(struct perf_evsel *evsel); | 126 | void perf_evsel__calc_id_pos(struct perf_evsel *evsel); |
@@ -138,6 +140,7 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX]; | |||
138 | int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, | 140 | int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, |
139 | char *bf, size_t size); | 141 | char *bf, size_t size); |
140 | const char *perf_evsel__name(struct perf_evsel *evsel); | 142 | const char *perf_evsel__name(struct perf_evsel *evsel); |
143 | |||
141 | const char *perf_evsel__group_name(struct perf_evsel *evsel); | 144 | const char *perf_evsel__group_name(struct perf_evsel *evsel); |
142 | int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); | 145 | int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); |
143 | 146 | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 1cd035708931..bb3e0ede6183 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -177,7 +177,7 @@ perf_header__set_cmdline(int argc, const char **argv) | |||
177 | continue; \ | 177 | continue; \ |
178 | else | 178 | else |
179 | 179 | ||
180 | static int write_buildid(char *name, size_t name_len, u8 *build_id, | 180 | static int write_buildid(const char *name, size_t name_len, u8 *build_id, |
181 | pid_t pid, u16 misc, int fd) | 181 | pid_t pid, u16 misc, int fd) |
182 | { | 182 | { |
183 | int err; | 183 | int err; |
@@ -209,7 +209,7 @@ static int __dsos__write_buildid_table(struct list_head *head, | |||
209 | 209 | ||
210 | dsos__for_each_with_build_id(pos, head) { | 210 | dsos__for_each_with_build_id(pos, head) { |
211 | int err; | 211 | int err; |
212 | char *name; | 212 | const char *name; |
213 | size_t name_len; | 213 | size_t name_len; |
214 | 214 | ||
215 | if (!pos->hit) | 215 | if (!pos->hit) |
@@ -387,7 +387,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine, | |||
387 | { | 387 | { |
388 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; | 388 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; |
389 | bool is_vdso = is_vdso_map(dso->short_name); | 389 | bool is_vdso = is_vdso_map(dso->short_name); |
390 | char *name = dso->long_name; | 390 | const char *name = dso->long_name; |
391 | char nm[PATH_MAX]; | 391 | char nm[PATH_MAX]; |
392 | 392 | ||
393 | if (dso__is_kcore(dso)) { | 393 | if (dso__is_kcore(dso)) { |
@@ -643,8 +643,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused, | |||
643 | if (ret < 0) | 643 | if (ret < 0) |
644 | return ret; | 644 | return ret; |
645 | 645 | ||
646 | list_for_each_entry(evsel, &evlist->entries, node) { | 646 | evlist__for_each(evlist, evsel) { |
647 | |||
648 | ret = do_write(fd, &evsel->attr, sz); | 647 | ret = do_write(fd, &evsel->attr, sz); |
649 | if (ret < 0) | 648 | if (ret < 0) |
650 | return ret; | 649 | return ret; |
@@ -800,10 +799,10 @@ static void free_cpu_topo(struct cpu_topo *tp) | |||
800 | return; | 799 | return; |
801 | 800 | ||
802 | for (i = 0 ; i < tp->core_sib; i++) | 801 | for (i = 0 ; i < tp->core_sib; i++) |
803 | free(tp->core_siblings[i]); | 802 | zfree(&tp->core_siblings[i]); |
804 | 803 | ||
805 | for (i = 0 ; i < tp->thread_sib; i++) | 804 | for (i = 0 ; i < tp->thread_sib; i++) |
806 | free(tp->thread_siblings[i]); | 805 | zfree(&tp->thread_siblings[i]); |
807 | 806 | ||
808 | free(tp); | 807 | free(tp); |
809 | } | 808 | } |
@@ -1092,7 +1091,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused, | |||
1092 | if (ret < 0) | 1091 | if (ret < 0) |
1093 | return ret; | 1092 | return ret; |
1094 | 1093 | ||
1095 | list_for_each_entry(evsel, &evlist->entries, node) { | 1094 | evlist__for_each(evlist, evsel) { |
1096 | if (perf_evsel__is_group_leader(evsel) && | 1095 | if (perf_evsel__is_group_leader(evsel) && |
1097 | evsel->nr_members > 1) { | 1096 | evsel->nr_members > 1) { |
1098 | const char *name = evsel->group_name ?: "{anon_group}"; | 1097 | const char *name = evsel->group_name ?: "{anon_group}"; |
@@ -1232,10 +1231,8 @@ static void free_event_desc(struct perf_evsel *events) | |||
1232 | return; | 1231 | return; |
1233 | 1232 | ||
1234 | for (evsel = events; evsel->attr.size; evsel++) { | 1233 | for (evsel = events; evsel->attr.size; evsel++) { |
1235 | if (evsel->name) | 1234 | zfree(&evsel->name); |
1236 | free(evsel->name); | 1235 | zfree(&evsel->id); |
1237 | if (evsel->id) | ||
1238 | free(evsel->id); | ||
1239 | } | 1236 | } |
1240 | 1237 | ||
1241 | free(events); | 1238 | free(events); |
@@ -1326,8 +1323,7 @@ read_event_desc(struct perf_header *ph, int fd) | |||
1326 | } | 1323 | } |
1327 | } | 1324 | } |
1328 | out: | 1325 | out: |
1329 | if (buf) | 1326 | free(buf); |
1330 | free(buf); | ||
1331 | return events; | 1327 | return events; |
1332 | error: | 1328 | error: |
1333 | if (events) | 1329 | if (events) |
@@ -1490,7 +1486,7 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, | |||
1490 | 1486 | ||
1491 | session = container_of(ph, struct perf_session, header); | 1487 | session = container_of(ph, struct perf_session, header); |
1492 | 1488 | ||
1493 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 1489 | evlist__for_each(session->evlist, evsel) { |
1494 | if (perf_evsel__is_group_leader(evsel) && | 1490 | if (perf_evsel__is_group_leader(evsel) && |
1495 | evsel->nr_members > 1) { | 1491 | evsel->nr_members > 1) { |
1496 | fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", | 1492 | fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", |
@@ -1709,7 +1705,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, | |||
1709 | struct perf_header *ph, int fd, | 1705 | struct perf_header *ph, int fd, |
1710 | void *data __maybe_unused) | 1706 | void *data __maybe_unused) |
1711 | { | 1707 | { |
1712 | size_t ret; | 1708 | ssize_t ret; |
1713 | u32 nr; | 1709 | u32 nr; |
1714 | 1710 | ||
1715 | ret = readn(fd, &nr, sizeof(nr)); | 1711 | ret = readn(fd, &nr, sizeof(nr)); |
@@ -1753,7 +1749,7 @@ static int process_total_mem(struct perf_file_section *section __maybe_unused, | |||
1753 | void *data __maybe_unused) | 1749 | void *data __maybe_unused) |
1754 | { | 1750 | { |
1755 | uint64_t mem; | 1751 | uint64_t mem; |
1756 | size_t ret; | 1752 | ssize_t ret; |
1757 | 1753 | ||
1758 | ret = readn(fd, &mem, sizeof(mem)); | 1754 | ret = readn(fd, &mem, sizeof(mem)); |
1759 | if (ret != sizeof(mem)) | 1755 | if (ret != sizeof(mem)) |
@@ -1771,7 +1767,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) | |||
1771 | { | 1767 | { |
1772 | struct perf_evsel *evsel; | 1768 | struct perf_evsel *evsel; |
1773 | 1769 | ||
1774 | list_for_each_entry(evsel, &evlist->entries, node) { | 1770 | evlist__for_each(evlist, evsel) { |
1775 | if (evsel->idx == idx) | 1771 | if (evsel->idx == idx) |
1776 | return evsel; | 1772 | return evsel; |
1777 | } | 1773 | } |
@@ -1822,7 +1818,7 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused, | |||
1822 | struct perf_header *ph, int fd, | 1818 | struct perf_header *ph, int fd, |
1823 | void *data __maybe_unused) | 1819 | void *data __maybe_unused) |
1824 | { | 1820 | { |
1825 | size_t ret; | 1821 | ssize_t ret; |
1826 | char *str; | 1822 | char *str; |
1827 | u32 nr, i; | 1823 | u32 nr, i; |
1828 | struct strbuf sb; | 1824 | struct strbuf sb; |
@@ -1858,7 +1854,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused | |||
1858 | struct perf_header *ph, int fd, | 1854 | struct perf_header *ph, int fd, |
1859 | void *data __maybe_unused) | 1855 | void *data __maybe_unused) |
1860 | { | 1856 | { |
1861 | size_t ret; | 1857 | ssize_t ret; |
1862 | u32 nr, i; | 1858 | u32 nr, i; |
1863 | char *str; | 1859 | char *str; |
1864 | struct strbuf sb; | 1860 | struct strbuf sb; |
@@ -1914,7 +1910,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse | |||
1914 | struct perf_header *ph, int fd, | 1910 | struct perf_header *ph, int fd, |
1915 | void *data __maybe_unused) | 1911 | void *data __maybe_unused) |
1916 | { | 1912 | { |
1917 | size_t ret; | 1913 | ssize_t ret; |
1918 | u32 nr, node, i; | 1914 | u32 nr, node, i; |
1919 | char *str; | 1915 | char *str; |
1920 | uint64_t mem_total, mem_free; | 1916 | uint64_t mem_total, mem_free; |
@@ -1974,7 +1970,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused | |||
1974 | struct perf_header *ph, int fd, | 1970 | struct perf_header *ph, int fd, |
1975 | void *data __maybe_unused) | 1971 | void *data __maybe_unused) |
1976 | { | 1972 | { |
1977 | size_t ret; | 1973 | ssize_t ret; |
1978 | char *name; | 1974 | char *name; |
1979 | u32 pmu_num; | 1975 | u32 pmu_num; |
1980 | u32 type; | 1976 | u32 type; |
@@ -2074,7 +2070,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused, | |||
2074 | session->evlist->nr_groups = nr_groups; | 2070 | session->evlist->nr_groups = nr_groups; |
2075 | 2071 | ||
2076 | i = nr = 0; | 2072 | i = nr = 0; |
2077 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 2073 | evlist__for_each(session->evlist, evsel) { |
2078 | if (evsel->idx == (int) desc[i].leader_idx) { | 2074 | if (evsel->idx == (int) desc[i].leader_idx) { |
2079 | evsel->leader = evsel; | 2075 | evsel->leader = evsel; |
2080 | /* {anon_group} is a dummy name */ | 2076 | /* {anon_group} is a dummy name */ |
@@ -2108,7 +2104,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused, | |||
2108 | ret = 0; | 2104 | ret = 0; |
2109 | out_free: | 2105 | out_free: |
2110 | for (i = 0; i < nr_groups; i++) | 2106 | for (i = 0; i < nr_groups; i++) |
2111 | free(desc[i].name); | 2107 | zfree(&desc[i].name); |
2112 | free(desc); | 2108 | free(desc); |
2113 | 2109 | ||
2114 | return ret; | 2110 | return ret; |
@@ -2301,7 +2297,7 @@ int perf_session__write_header(struct perf_session *session, | |||
2301 | 2297 | ||
2302 | lseek(fd, sizeof(f_header), SEEK_SET); | 2298 | lseek(fd, sizeof(f_header), SEEK_SET); |
2303 | 2299 | ||
2304 | list_for_each_entry(evsel, &evlist->entries, node) { | 2300 | evlist__for_each(session->evlist, evsel) { |
2305 | evsel->id_offset = lseek(fd, 0, SEEK_CUR); | 2301 | evsel->id_offset = lseek(fd, 0, SEEK_CUR); |
2306 | err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); | 2302 | err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); |
2307 | if (err < 0) { | 2303 | if (err < 0) { |
@@ -2312,7 +2308,7 @@ int perf_session__write_header(struct perf_session *session, | |||
2312 | 2308 | ||
2313 | attr_offset = lseek(fd, 0, SEEK_CUR); | 2309 | attr_offset = lseek(fd, 0, SEEK_CUR); |
2314 | 2310 | ||
2315 | list_for_each_entry(evsel, &evlist->entries, node) { | 2311 | evlist__for_each(evlist, evsel) { |
2316 | f_attr = (struct perf_file_attr){ | 2312 | f_attr = (struct perf_file_attr){ |
2317 | .attr = evsel->attr, | 2313 | .attr = evsel->attr, |
2318 | .ids = { | 2314 | .ids = { |
@@ -2327,7 +2323,8 @@ int perf_session__write_header(struct perf_session *session, | |||
2327 | } | 2323 | } |
2328 | } | 2324 | } |
2329 | 2325 | ||
2330 | header->data_offset = lseek(fd, 0, SEEK_CUR); | 2326 | if (!header->data_offset) |
2327 | header->data_offset = lseek(fd, 0, SEEK_CUR); | ||
2331 | header->feat_offset = header->data_offset + header->data_size; | 2328 | header->feat_offset = header->data_offset + header->data_size; |
2332 | 2329 | ||
2333 | if (at_exit) { | 2330 | if (at_exit) { |
@@ -2534,7 +2531,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz, | |||
2534 | int perf_file_header__read(struct perf_file_header *header, | 2531 | int perf_file_header__read(struct perf_file_header *header, |
2535 | struct perf_header *ph, int fd) | 2532 | struct perf_header *ph, int fd) |
2536 | { | 2533 | { |
2537 | int ret; | 2534 | ssize_t ret; |
2538 | 2535 | ||
2539 | lseek(fd, 0, SEEK_SET); | 2536 | lseek(fd, 0, SEEK_SET); |
2540 | 2537 | ||
@@ -2628,7 +2625,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, | |||
2628 | struct perf_header *ph, int fd, | 2625 | struct perf_header *ph, int fd, |
2629 | bool repipe) | 2626 | bool repipe) |
2630 | { | 2627 | { |
2631 | int ret; | 2628 | ssize_t ret; |
2632 | 2629 | ||
2633 | ret = readn(fd, header, sizeof(*header)); | 2630 | ret = readn(fd, header, sizeof(*header)); |
2634 | if (ret <= 0) | 2631 | if (ret <= 0) |
@@ -2669,7 +2666,7 @@ static int read_attr(int fd, struct perf_header *ph, | |||
2669 | struct perf_event_attr *attr = &f_attr->attr; | 2666 | struct perf_event_attr *attr = &f_attr->attr; |
2670 | size_t sz, left; | 2667 | size_t sz, left; |
2671 | size_t our_sz = sizeof(f_attr->attr); | 2668 | size_t our_sz = sizeof(f_attr->attr); |
2672 | int ret; | 2669 | ssize_t ret; |
2673 | 2670 | ||
2674 | memset(f_attr, 0, sizeof(*f_attr)); | 2671 | memset(f_attr, 0, sizeof(*f_attr)); |
2675 | 2672 | ||
@@ -2744,7 +2741,7 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, | |||
2744 | { | 2741 | { |
2745 | struct perf_evsel *pos; | 2742 | struct perf_evsel *pos; |
2746 | 2743 | ||
2747 | list_for_each_entry(pos, &evlist->entries, node) { | 2744 | evlist__for_each(evlist, pos) { |
2748 | if (pos->attr.type == PERF_TYPE_TRACEPOINT && | 2745 | if (pos->attr.type == PERF_TYPE_TRACEPOINT && |
2749 | perf_evsel__prepare_tracepoint_event(pos, pevent)) | 2746 | perf_evsel__prepare_tracepoint_event(pos, pevent)) |
2750 | return -1; | 2747 | return -1; |
@@ -2834,11 +2831,11 @@ int perf_session__read_header(struct perf_session *session) | |||
2834 | 2831 | ||
2835 | symbol_conf.nr_events = nr_attrs; | 2832 | symbol_conf.nr_events = nr_attrs; |
2836 | 2833 | ||
2837 | perf_header__process_sections(header, fd, &session->pevent, | 2834 | perf_header__process_sections(header, fd, &session->tevent, |
2838 | perf_file_section__process); | 2835 | perf_file_section__process); |
2839 | 2836 | ||
2840 | if (perf_evlist__prepare_tracepoint_events(session->evlist, | 2837 | if (perf_evlist__prepare_tracepoint_events(session->evlist, |
2841 | session->pevent)) | 2838 | session->tevent.pevent)) |
2842 | goto out_delete_evlist; | 2839 | goto out_delete_evlist; |
2843 | 2840 | ||
2844 | return 0; | 2841 | return 0; |
@@ -2892,7 +2889,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, | |||
2892 | struct perf_evsel *evsel; | 2889 | struct perf_evsel *evsel; |
2893 | int err = 0; | 2890 | int err = 0; |
2894 | 2891 | ||
2895 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 2892 | evlist__for_each(session->evlist, evsel) { |
2896 | err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, | 2893 | err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, |
2897 | evsel->id, process); | 2894 | evsel->id, process); |
2898 | if (err) { | 2895 | if (err) { |
@@ -3003,7 +3000,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, | |||
3003 | lseek(fd, offset + sizeof(struct tracing_data_event), | 3000 | lseek(fd, offset + sizeof(struct tracing_data_event), |
3004 | SEEK_SET); | 3001 | SEEK_SET); |
3005 | 3002 | ||
3006 | size_read = trace_report(fd, &session->pevent, | 3003 | size_read = trace_report(fd, &session->tevent, |
3007 | session->repipe); | 3004 | session->repipe); |
3008 | padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; | 3005 | padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; |
3009 | 3006 | ||
@@ -3025,7 +3022,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, | |||
3025 | } | 3022 | } |
3026 | 3023 | ||
3027 | perf_evlist__prepare_tracepoint_events(session->evlist, | 3024 | perf_evlist__prepare_tracepoint_events(session->evlist, |
3028 | session->pevent); | 3025 | session->tevent.pevent); |
3029 | 3026 | ||
3030 | return size_read + padding; | 3027 | return size_read + padding; |
3031 | } | 3028 | } |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 307c9aed972e..a2d047bdf4ef 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -77,16 +77,16 @@ struct perf_session_env { | |||
77 | unsigned long long total_mem; | 77 | unsigned long long total_mem; |
78 | 78 | ||
79 | int nr_cmdline; | 79 | int nr_cmdline; |
80 | char *cmdline; | ||
81 | int nr_sibling_cores; | 80 | int nr_sibling_cores; |
82 | char *sibling_cores; | ||
83 | int nr_sibling_threads; | 81 | int nr_sibling_threads; |
84 | char *sibling_threads; | ||
85 | int nr_numa_nodes; | 82 | int nr_numa_nodes; |
86 | char *numa_nodes; | ||
87 | int nr_pmu_mappings; | 83 | int nr_pmu_mappings; |
88 | char *pmu_mappings; | ||
89 | int nr_groups; | 84 | int nr_groups; |
85 | char *cmdline; | ||
86 | char *sibling_cores; | ||
87 | char *sibling_threads; | ||
88 | char *numa_nodes; | ||
89 | char *pmu_mappings; | ||
90 | }; | 90 | }; |
91 | 91 | ||
92 | struct perf_header { | 92 | struct perf_header { |
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 8b1f6e891b8a..86c37c472263 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c | |||
@@ -22,8 +22,8 @@ static void clean_cmdnames(struct cmdnames *cmds) | |||
22 | unsigned int i; | 22 | unsigned int i; |
23 | 23 | ||
24 | for (i = 0; i < cmds->cnt; ++i) | 24 | for (i = 0; i < cmds->cnt; ++i) |
25 | free(cmds->names[i]); | 25 | zfree(&cmds->names[i]); |
26 | free(cmds->names); | 26 | zfree(&cmds->names); |
27 | cmds->cnt = 0; | 27 | cmds->cnt = 0; |
28 | cmds->alloc = 0; | 28 | cmds->alloc = 0; |
29 | } | 29 | } |
@@ -263,9 +263,8 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) | |||
263 | 263 | ||
264 | for (i = 0; i < old->cnt; i++) | 264 | for (i = 0; i < old->cnt; i++) |
265 | cmds->names[cmds->cnt++] = old->names[i]; | 265 | cmds->names[cmds->cnt++] = old->names[i]; |
266 | free(old->names); | 266 | zfree(&old->names); |
267 | old->cnt = 0; | 267 | old->cnt = 0; |
268 | old->names = NULL; | ||
269 | } | 268 | } |
270 | 269 | ||
271 | const char *help_unknown_cmd(const char *cmd) | 270 | const char *help_unknown_cmd(const char *cmd) |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 822903eaa201..e4e6249b87d4 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #include "annotate.h" | ||
2 | #include "util.h" | 1 | #include "util.h" |
3 | #include "build-id.h" | 2 | #include "build-id.h" |
4 | #include "hist.h" | 3 | #include "hist.h" |
@@ -182,21 +181,21 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows) | |||
182 | } | 181 | } |
183 | } | 182 | } |
184 | 183 | ||
185 | static void hist_entry__add_cpumode_period(struct hist_entry *he, | 184 | static void he_stat__add_cpumode_period(struct he_stat *he_stat, |
186 | unsigned int cpumode, u64 period) | 185 | unsigned int cpumode, u64 period) |
187 | { | 186 | { |
188 | switch (cpumode) { | 187 | switch (cpumode) { |
189 | case PERF_RECORD_MISC_KERNEL: | 188 | case PERF_RECORD_MISC_KERNEL: |
190 | he->stat.period_sys += period; | 189 | he_stat->period_sys += period; |
191 | break; | 190 | break; |
192 | case PERF_RECORD_MISC_USER: | 191 | case PERF_RECORD_MISC_USER: |
193 | he->stat.period_us += period; | 192 | he_stat->period_us += period; |
194 | break; | 193 | break; |
195 | case PERF_RECORD_MISC_GUEST_KERNEL: | 194 | case PERF_RECORD_MISC_GUEST_KERNEL: |
196 | he->stat.period_guest_sys += period; | 195 | he_stat->period_guest_sys += period; |
197 | break; | 196 | break; |
198 | case PERF_RECORD_MISC_GUEST_USER: | 197 | case PERF_RECORD_MISC_GUEST_USER: |
199 | he->stat.period_guest_us += period; | 198 | he_stat->period_guest_us += period; |
200 | break; | 199 | break; |
201 | default: | 200 | default: |
202 | break; | 201 | break; |
@@ -223,10 +222,10 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) | |||
223 | dest->weight += src->weight; | 222 | dest->weight += src->weight; |
224 | } | 223 | } |
225 | 224 | ||
226 | static void hist_entry__decay(struct hist_entry *he) | 225 | static void he_stat__decay(struct he_stat *he_stat) |
227 | { | 226 | { |
228 | he->stat.period = (he->stat.period * 7) / 8; | 227 | he_stat->period = (he_stat->period * 7) / 8; |
229 | he->stat.nr_events = (he->stat.nr_events * 7) / 8; | 228 | he_stat->nr_events = (he_stat->nr_events * 7) / 8; |
230 | /* XXX need decay for weight too? */ | 229 | /* XXX need decay for weight too? */ |
231 | } | 230 | } |
232 | 231 | ||
@@ -237,7 +236,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) | |||
237 | if (prev_period == 0) | 236 | if (prev_period == 0) |
238 | return true; | 237 | return true; |
239 | 238 | ||
240 | hist_entry__decay(he); | 239 | he_stat__decay(&he->stat); |
241 | 240 | ||
242 | if (!he->filtered) | 241 | if (!he->filtered) |
243 | hists->stats.total_period -= prev_period - he->stat.period; | 242 | hists->stats.total_period -= prev_period - he->stat.period; |
@@ -342,15 +341,15 @@ static u8 symbol__parent_filter(const struct symbol *parent) | |||
342 | } | 341 | } |
343 | 342 | ||
344 | static struct hist_entry *add_hist_entry(struct hists *hists, | 343 | static struct hist_entry *add_hist_entry(struct hists *hists, |
345 | struct hist_entry *entry, | 344 | struct hist_entry *entry, |
346 | struct addr_location *al, | 345 | struct addr_location *al) |
347 | u64 period, | ||
348 | u64 weight) | ||
349 | { | 346 | { |
350 | struct rb_node **p; | 347 | struct rb_node **p; |
351 | struct rb_node *parent = NULL; | 348 | struct rb_node *parent = NULL; |
352 | struct hist_entry *he; | 349 | struct hist_entry *he; |
353 | int64_t cmp; | 350 | int64_t cmp; |
351 | u64 period = entry->stat.period; | ||
352 | u64 weight = entry->stat.weight; | ||
354 | 353 | ||
355 | p = &hists->entries_in->rb_node; | 354 | p = &hists->entries_in->rb_node; |
356 | 355 | ||
@@ -373,7 +372,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, | |||
373 | * This mem info was allocated from machine__resolve_mem | 372 | * This mem info was allocated from machine__resolve_mem |
374 | * and will not be used anymore. | 373 | * and will not be used anymore. |
375 | */ | 374 | */ |
376 | free(entry->mem_info); | 375 | zfree(&entry->mem_info); |
377 | 376 | ||
378 | /* If the map of an existing hist_entry has | 377 | /* If the map of an existing hist_entry has |
379 | * become out-of-date due to an exec() or | 378 | * become out-of-date due to an exec() or |
@@ -403,7 +402,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, | |||
403 | rb_link_node(&he->rb_node_in, parent, p); | 402 | rb_link_node(&he->rb_node_in, parent, p); |
404 | rb_insert_color(&he->rb_node_in, hists->entries_in); | 403 | rb_insert_color(&he->rb_node_in, hists->entries_in); |
405 | out: | 404 | out: |
406 | hist_entry__add_cpumode_period(he, al->cpumode, period); | 405 | he_stat__add_cpumode_period(&he->stat, al->cpumode, period); |
407 | return he; | 406 | return he; |
408 | } | 407 | } |
409 | 408 | ||
@@ -437,7 +436,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists, | |||
437 | .transaction = transaction, | 436 | .transaction = transaction, |
438 | }; | 437 | }; |
439 | 438 | ||
440 | return add_hist_entry(hists, &entry, al, period, weight); | 439 | return add_hist_entry(hists, &entry, al); |
441 | } | 440 | } |
442 | 441 | ||
443 | int64_t | 442 | int64_t |
@@ -476,8 +475,8 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) | |||
476 | 475 | ||
477 | void hist_entry__free(struct hist_entry *he) | 476 | void hist_entry__free(struct hist_entry *he) |
478 | { | 477 | { |
479 | free(he->branch_info); | 478 | zfree(&he->branch_info); |
480 | free(he->mem_info); | 479 | zfree(&he->mem_info); |
481 | free_srcline(he->srcline); | 480 | free_srcline(he->srcline); |
482 | free(he); | 481 | free(he); |
483 | } | 482 | } |
@@ -807,16 +806,6 @@ void hists__filter_by_symbol(struct hists *hists) | |||
807 | } | 806 | } |
808 | } | 807 | } |
809 | 808 | ||
810 | int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) | ||
811 | { | ||
812 | return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); | ||
813 | } | ||
814 | |||
815 | int hist_entry__annotate(struct hist_entry *he, size_t privsize) | ||
816 | { | ||
817 | return symbol__annotate(he->ms.sym, he->ms.map, privsize); | ||
818 | } | ||
819 | |||
820 | void events_stats__inc(struct events_stats *stats, u32 type) | 809 | void events_stats__inc(struct events_stats *stats, u32 type) |
821 | { | 810 | { |
822 | ++stats->nr_events[0]; | 811 | ++stats->nr_events[0]; |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b621347a1585..a59743fa3ef7 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -111,9 +111,6 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); | |||
111 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | 111 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, |
112 | int max_cols, float min_pcnt, FILE *fp); | 112 | int max_cols, float min_pcnt, FILE *fp); |
113 | 113 | ||
114 | int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); | ||
115 | int hist_entry__annotate(struct hist_entry *he, size_t privsize); | ||
116 | |||
117 | void hists__filter_by_dso(struct hists *hists); | 114 | void hists__filter_by_dso(struct hists *hists); |
118 | void hists__filter_by_thread(struct hists *hists); | 115 | void hists__filter_by_thread(struct hists *hists); |
119 | void hists__filter_by_symbol(struct hists *hists); | 116 | void hists__filter_by_symbol(struct hists *hists); |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 84cdb072ac83..ded74590b92f 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "strlist.h" | 9 | #include "strlist.h" |
10 | #include "thread.h" | 10 | #include "thread.h" |
11 | #include <stdbool.h> | 11 | #include <stdbool.h> |
12 | #include <symbol/kallsyms.h> | ||
12 | #include "unwind.h" | 13 | #include "unwind.h" |
13 | 14 | ||
14 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | 15 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid) |
@@ -26,6 +27,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | |||
26 | machine->pid = pid; | 27 | machine->pid = pid; |
27 | 28 | ||
28 | machine->symbol_filter = NULL; | 29 | machine->symbol_filter = NULL; |
30 | machine->id_hdr_size = 0; | ||
29 | 31 | ||
30 | machine->root_dir = strdup(root_dir); | 32 | machine->root_dir = strdup(root_dir); |
31 | if (machine->root_dir == NULL) | 33 | if (machine->root_dir == NULL) |
@@ -101,8 +103,7 @@ void machine__exit(struct machine *machine) | |||
101 | map_groups__exit(&machine->kmaps); | 103 | map_groups__exit(&machine->kmaps); |
102 | dsos__delete(&machine->user_dsos); | 104 | dsos__delete(&machine->user_dsos); |
103 | dsos__delete(&machine->kernel_dsos); | 105 | dsos__delete(&machine->kernel_dsos); |
104 | free(machine->root_dir); | 106 | zfree(&machine->root_dir); |
105 | machine->root_dir = NULL; | ||
106 | } | 107 | } |
107 | 108 | ||
108 | void machine__delete(struct machine *machine) | 109 | void machine__delete(struct machine *machine) |
@@ -502,15 +503,11 @@ static u64 machine__get_kernel_start_addr(struct machine *machine) | |||
502 | char path[PATH_MAX]; | 503 | char path[PATH_MAX]; |
503 | struct process_args args; | 504 | struct process_args args; |
504 | 505 | ||
505 | if (machine__is_host(machine)) { | 506 | if (machine__is_default_guest(machine)) |
506 | filename = "/proc/kallsyms"; | 507 | filename = (char *)symbol_conf.default_guest_kallsyms; |
507 | } else { | 508 | else { |
508 | if (machine__is_default_guest(machine)) | 509 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); |
509 | filename = (char *)symbol_conf.default_guest_kallsyms; | 510 | filename = path; |
510 | else { | ||
511 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); | ||
512 | filename = path; | ||
513 | } | ||
514 | } | 511 | } |
515 | 512 | ||
516 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) | 513 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) |
@@ -565,11 +562,10 @@ void machine__destroy_kernel_maps(struct machine *machine) | |||
565 | * on one of them. | 562 | * on one of them. |
566 | */ | 563 | */ |
567 | if (type == MAP__FUNCTION) { | 564 | if (type == MAP__FUNCTION) { |
568 | free((char *)kmap->ref_reloc_sym->name); | 565 | zfree((char **)&kmap->ref_reloc_sym->name); |
569 | kmap->ref_reloc_sym->name = NULL; | 566 | zfree(&kmap->ref_reloc_sym); |
570 | free(kmap->ref_reloc_sym); | 567 | } else |
571 | } | 568 | kmap->ref_reloc_sym = NULL; |
572 | kmap->ref_reloc_sym = NULL; | ||
573 | } | 569 | } |
574 | 570 | ||
575 | map__delete(machine->vmlinux_maps[type]); | 571 | map__delete(machine->vmlinux_maps[type]); |
@@ -767,8 +763,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg, | |||
767 | ret = -1; | 763 | ret = -1; |
768 | goto out; | 764 | goto out; |
769 | } | 765 | } |
770 | dso__set_long_name(map->dso, long_name); | 766 | dso__set_long_name(map->dso, long_name, true); |
771 | map->dso->lname_alloc = 1; | ||
772 | dso__kernel_module_get_build_id(map->dso, ""); | 767 | dso__kernel_module_get_build_id(map->dso, ""); |
773 | } | 768 | } |
774 | } | 769 | } |
@@ -939,8 +934,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
939 | if (name == NULL) | 934 | if (name == NULL) |
940 | goto out_problem; | 935 | goto out_problem; |
941 | 936 | ||
942 | map->dso->short_name = name; | 937 | dso__set_short_name(map->dso, name, true); |
943 | map->dso->sname_alloc = 1; | ||
944 | map->end = map->start + event->mmap.len; | 938 | map->end = map->start + event->mmap.len; |
945 | } else if (is_kernel_mmap) { | 939 | } else if (is_kernel_mmap) { |
946 | const char *symbol_name = (event->mmap.filename + | 940 | const char *symbol_name = (event->mmap.filename + |
@@ -1320,8 +1314,6 @@ static int machine__resolve_callchain_sample(struct machine *machine, | |||
1320 | *root_al = al; | 1314 | *root_al = al; |
1321 | callchain_cursor_reset(&callchain_cursor); | 1315 | callchain_cursor_reset(&callchain_cursor); |
1322 | } | 1316 | } |
1323 | if (!symbol_conf.use_callchain) | ||
1324 | break; | ||
1325 | } | 1317 | } |
1326 | 1318 | ||
1327 | err = callchain_cursor_append(&callchain_cursor, | 1319 | err = callchain_cursor_append(&callchain_cursor, |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index ef5bc913ca7a..9b9bd719aa19 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "strlist.h" | 11 | #include "strlist.h" |
12 | #include "vdso.h" | 12 | #include "vdso.h" |
13 | #include "build-id.h" | 13 | #include "build-id.h" |
14 | #include "util.h" | ||
14 | #include <linux/string.h> | 15 | #include <linux/string.h> |
15 | 16 | ||
16 | const char *map_type__name[MAP__NR_TYPES] = { | 17 | const char *map_type__name[MAP__NR_TYPES] = { |
@@ -252,6 +253,22 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp) | |||
252 | return fprintf(fp, "%s", dsoname); | 253 | return fprintf(fp, "%s", dsoname); |
253 | } | 254 | } |
254 | 255 | ||
256 | int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, | ||
257 | FILE *fp) | ||
258 | { | ||
259 | char *srcline; | ||
260 | int ret = 0; | ||
261 | |||
262 | if (map && map->dso) { | ||
263 | srcline = get_srcline(map->dso, | ||
264 | map__rip_2objdump(map, addr)); | ||
265 | if (srcline != SRCLINE_UNKNOWN) | ||
266 | ret = fprintf(fp, "%s%s", prefix, srcline); | ||
267 | free_srcline(srcline); | ||
268 | } | ||
269 | return ret; | ||
270 | } | ||
271 | |||
255 | /** | 272 | /** |
256 | * map__rip_2objdump - convert symbol start address to objdump address. | 273 | * map__rip_2objdump - convert symbol start address to objdump address. |
257 | * @map: memory map | 274 | * @map: memory map |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index e4e259c3ba16..18068c6b71c1 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -103,6 +103,8 @@ struct map *map__clone(struct map *map); | |||
103 | int map__overlap(struct map *l, struct map *r); | 103 | int map__overlap(struct map *l, struct map *r); |
104 | size_t map__fprintf(struct map *map, FILE *fp); | 104 | size_t map__fprintf(struct map *map, FILE *fp); |
105 | size_t map__fprintf_dsoname(struct map *map, FILE *fp); | 105 | size_t map__fprintf_dsoname(struct map *map, FILE *fp); |
106 | int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, | ||
107 | FILE *fp); | ||
106 | 108 | ||
107 | int map__load(struct map *map, symbol_filter_t filter); | 109 | int map__load(struct map *map, symbol_filter_t filter); |
108 | struct symbol *map__find_symbol(struct map *map, | 110 | struct symbol *map__find_symbol(struct map *map, |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6de6f89c2a61..a7f1b6a91fdd 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include "symbol.h" | 10 | #include "symbol.h" |
11 | #include "cache.h" | 11 | #include "cache.h" |
12 | #include "header.h" | 12 | #include "header.h" |
13 | #include <lk/debugfs.h> | 13 | #include <api/fs/debugfs.h> |
14 | #include "parse-events-bison.h" | 14 | #include "parse-events-bison.h" |
15 | #define YY_EXTRA_TYPE int | 15 | #define YY_EXTRA_TYPE int |
16 | #include "parse-events-flex.h" | 16 | #include "parse-events-flex.h" |
@@ -204,7 +204,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) | |||
204 | } | 204 | } |
205 | path->name = malloc(MAX_EVENT_LENGTH); | 205 | path->name = malloc(MAX_EVENT_LENGTH); |
206 | if (!path->name) { | 206 | if (!path->name) { |
207 | free(path->system); | 207 | zfree(&path->system); |
208 | free(path); | 208 | free(path); |
209 | return NULL; | 209 | return NULL; |
210 | } | 210 | } |
@@ -236,8 +236,8 @@ struct tracepoint_path *tracepoint_name_to_path(const char *name) | |||
236 | path->name = strdup(str+1); | 236 | path->name = strdup(str+1); |
237 | 237 | ||
238 | if (path->system == NULL || path->name == NULL) { | 238 | if (path->system == NULL || path->name == NULL) { |
239 | free(path->system); | 239 | zfree(&path->system); |
240 | free(path->name); | 240 | zfree(&path->name); |
241 | free(path); | 241 | free(path); |
242 | path = NULL; | 242 | path = NULL; |
243 | } | 243 | } |
@@ -269,9 +269,10 @@ const char *event_type(int type) | |||
269 | 269 | ||
270 | 270 | ||
271 | 271 | ||
272 | static int __add_event(struct list_head *list, int *idx, | 272 | static struct perf_evsel * |
273 | struct perf_event_attr *attr, | 273 | __add_event(struct list_head *list, int *idx, |
274 | char *name, struct cpu_map *cpus) | 274 | struct perf_event_attr *attr, |
275 | char *name, struct cpu_map *cpus) | ||
275 | { | 276 | { |
276 | struct perf_evsel *evsel; | 277 | struct perf_evsel *evsel; |
277 | 278 | ||
@@ -279,19 +280,19 @@ static int __add_event(struct list_head *list, int *idx, | |||
279 | 280 | ||
280 | evsel = perf_evsel__new_idx(attr, (*idx)++); | 281 | evsel = perf_evsel__new_idx(attr, (*idx)++); |
281 | if (!evsel) | 282 | if (!evsel) |
282 | return -ENOMEM; | 283 | return NULL; |
283 | 284 | ||
284 | evsel->cpus = cpus; | 285 | evsel->cpus = cpus; |
285 | if (name) | 286 | if (name) |
286 | evsel->name = strdup(name); | 287 | evsel->name = strdup(name); |
287 | list_add_tail(&evsel->node, list); | 288 | list_add_tail(&evsel->node, list); |
288 | return 0; | 289 | return evsel; |
289 | } | 290 | } |
290 | 291 | ||
291 | static int add_event(struct list_head *list, int *idx, | 292 | static int add_event(struct list_head *list, int *idx, |
292 | struct perf_event_attr *attr, char *name) | 293 | struct perf_event_attr *attr, char *name) |
293 | { | 294 | { |
294 | return __add_event(list, idx, attr, name, NULL); | 295 | return __add_event(list, idx, attr, name, NULL) ? 0 : -ENOMEM; |
295 | } | 296 | } |
296 | 297 | ||
297 | static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) | 298 | static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) |
@@ -633,6 +634,9 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
633 | { | 634 | { |
634 | struct perf_event_attr attr; | 635 | struct perf_event_attr attr; |
635 | struct perf_pmu *pmu; | 636 | struct perf_pmu *pmu; |
637 | struct perf_evsel *evsel; | ||
638 | char *unit; | ||
639 | double scale; | ||
636 | 640 | ||
637 | pmu = perf_pmu__find(name); | 641 | pmu = perf_pmu__find(name); |
638 | if (!pmu) | 642 | if (!pmu) |
@@ -640,7 +644,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
640 | 644 | ||
641 | memset(&attr, 0, sizeof(attr)); | 645 | memset(&attr, 0, sizeof(attr)); |
642 | 646 | ||
643 | if (perf_pmu__check_alias(pmu, head_config)) | 647 | if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) |
644 | return -EINVAL; | 648 | return -EINVAL; |
645 | 649 | ||
646 | /* | 650 | /* |
@@ -652,8 +656,14 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
652 | if (perf_pmu__config(pmu, &attr, head_config)) | 656 | if (perf_pmu__config(pmu, &attr, head_config)) |
653 | return -EINVAL; | 657 | return -EINVAL; |
654 | 658 | ||
655 | return __add_event(list, idx, &attr, pmu_event_name(head_config), | 659 | evsel = __add_event(list, idx, &attr, pmu_event_name(head_config), |
656 | pmu->cpus); | 660 | pmu->cpus); |
661 | if (evsel) { | ||
662 | evsel->unit = unit; | ||
663 | evsel->scale = scale; | ||
664 | } | ||
665 | |||
666 | return evsel ? 0 : -ENOMEM; | ||
657 | } | 667 | } |
658 | 668 | ||
659 | int parse_events__modifier_group(struct list_head *list, | 669 | int parse_events__modifier_group(struct list_head *list, |
@@ -810,8 +820,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) | |||
810 | if (!add && get_event_modifier(&mod, str, NULL)) | 820 | if (!add && get_event_modifier(&mod, str, NULL)) |
811 | return -EINVAL; | 821 | return -EINVAL; |
812 | 822 | ||
813 | list_for_each_entry(evsel, list, node) { | 823 | __evlist__for_each(list, evsel) { |
814 | |||
815 | if (add && get_event_modifier(&mod, str, evsel)) | 824 | if (add && get_event_modifier(&mod, str, evsel)) |
816 | return -EINVAL; | 825 | return -EINVAL; |
817 | 826 | ||
@@ -835,7 +844,7 @@ int parse_events_name(struct list_head *list, char *name) | |||
835 | { | 844 | { |
836 | struct perf_evsel *evsel; | 845 | struct perf_evsel *evsel; |
837 | 846 | ||
838 | list_for_each_entry(evsel, list, node) { | 847 | __evlist__for_each(list, evsel) { |
839 | if (!evsel->name) | 848 | if (!evsel->name) |
840 | evsel->name = strdup(name); | 849 | evsel->name = strdup(name); |
841 | } | 850 | } |
@@ -907,7 +916,7 @@ int parse_events_terms(struct list_head *terms, const char *str) | |||
907 | ret = parse_events__scanner(str, &data, PE_START_TERMS); | 916 | ret = parse_events__scanner(str, &data, PE_START_TERMS); |
908 | if (!ret) { | 917 | if (!ret) { |
909 | list_splice(data.terms, terms); | 918 | list_splice(data.terms, terms); |
910 | free(data.terms); | 919 | zfree(&data.terms); |
911 | return 0; | 920 | return 0; |
912 | } | 921 | } |
913 | 922 | ||
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 31f404a032a9..d22e3f8017dc 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
@@ -78,6 +78,8 @@ static int get_value(struct parse_opt_ctx_t *p, | |||
78 | 78 | ||
79 | case OPTION_BOOLEAN: | 79 | case OPTION_BOOLEAN: |
80 | *(bool *)opt->value = unset ? false : true; | 80 | *(bool *)opt->value = unset ? false : true; |
81 | if (opt->set) | ||
82 | *(bool *)opt->set = true; | ||
81 | return 0; | 83 | return 0; |
82 | 84 | ||
83 | case OPTION_INCR: | 85 | case OPTION_INCR: |
@@ -224,6 +226,24 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, | |||
224 | return 0; | 226 | return 0; |
225 | } | 227 | } |
226 | if (!rest) { | 228 | if (!rest) { |
229 | if (!prefixcmp(options->long_name, "no-")) { | ||
230 | /* | ||
231 | * The long name itself starts with "no-", so | ||
232 | * accept the option without "no-" so that users | ||
233 | * do not have to enter "no-no-" to get the | ||
234 | * negation. | ||
235 | */ | ||
236 | rest = skip_prefix(arg, options->long_name + 3); | ||
237 | if (rest) { | ||
238 | flags |= OPT_UNSET; | ||
239 | goto match; | ||
240 | } | ||
241 | /* Abbreviated case */ | ||
242 | if (!prefixcmp(options->long_name + 3, arg)) { | ||
243 | flags |= OPT_UNSET; | ||
244 | goto is_abbreviated; | ||
245 | } | ||
246 | } | ||
227 | /* abbreviated? */ | 247 | /* abbreviated? */ |
228 | if (!strncmp(options->long_name, arg, arg_end - arg)) { | 248 | if (!strncmp(options->long_name, arg, arg_end - arg)) { |
229 | is_abbreviated: | 249 | is_abbreviated: |
@@ -259,6 +279,7 @@ is_abbreviated: | |||
259 | if (!rest) | 279 | if (!rest) |
260 | continue; | 280 | continue; |
261 | } | 281 | } |
282 | match: | ||
262 | if (*rest) { | 283 | if (*rest) { |
263 | if (*rest != '=') | 284 | if (*rest != '=') |
264 | continue; | 285 | continue; |
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index b0241e28eaf7..cbf0149cf221 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h | |||
@@ -82,6 +82,9 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset); | |||
82 | * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in | 82 | * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in |
83 | * the value when met. | 83 | * the value when met. |
84 | * CALLBACKS can use it like they want. | 84 | * CALLBACKS can use it like they want. |
85 | * | ||
86 | * `set`:: | ||
87 | * whether an option was set by the user | ||
85 | */ | 88 | */ |
86 | struct option { | 89 | struct option { |
87 | enum parse_opt_type type; | 90 | enum parse_opt_type type; |
@@ -94,6 +97,7 @@ struct option { | |||
94 | int flags; | 97 | int flags; |
95 | parse_opt_cb *callback; | 98 | parse_opt_cb *callback; |
96 | intptr_t defval; | 99 | intptr_t defval; |
100 | bool *set; | ||
97 | }; | 101 | }; |
98 | 102 | ||
99 | #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) | 103 | #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) |
@@ -103,6 +107,10 @@ struct option { | |||
103 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } | 107 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } |
104 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } | 108 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } |
105 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } | 109 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } |
110 | #define OPT_BOOLEAN_SET(s, l, v, os, h) \ | ||
111 | { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ | ||
112 | .value = check_vtype(v, bool *), .help = (h), \ | ||
113 | .set = check_vtype(os, bool *)} | ||
106 | #define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } | 114 | #define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } |
107 | #define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } | 115 | #define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } |
108 | #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } | 116 | #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index c232d8dd410b..d9cab4d27192 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -1,19 +1,23 @@ | |||
1 | #include <linux/list.h> | 1 | #include <linux/list.h> |
2 | #include <sys/types.h> | 2 | #include <sys/types.h> |
3 | #include <sys/stat.h> | ||
4 | #include <unistd.h> | 3 | #include <unistd.h> |
5 | #include <stdio.h> | 4 | #include <stdio.h> |
6 | #include <dirent.h> | 5 | #include <dirent.h> |
7 | #include "fs.h" | 6 | #include "fs.h" |
7 | #include <locale.h> | ||
8 | #include "util.h" | 8 | #include "util.h" |
9 | #include "pmu.h" | 9 | #include "pmu.h" |
10 | #include "parse-events.h" | 10 | #include "parse-events.h" |
11 | #include "cpumap.h" | 11 | #include "cpumap.h" |
12 | 12 | ||
13 | #define UNIT_MAX_LEN 31 /* max length for event unit name */ | ||
14 | |||
13 | struct perf_pmu_alias { | 15 | struct perf_pmu_alias { |
14 | char *name; | 16 | char *name; |
15 | struct list_head terms; | 17 | struct list_head terms; |
16 | struct list_head list; | 18 | struct list_head list; |
19 | char unit[UNIT_MAX_LEN+1]; | ||
20 | double scale; | ||
17 | }; | 21 | }; |
18 | 22 | ||
19 | struct perf_pmu_format { | 23 | struct perf_pmu_format { |
@@ -94,7 +98,80 @@ static int pmu_format(const char *name, struct list_head *format) | |||
94 | return 0; | 98 | return 0; |
95 | } | 99 | } |
96 | 100 | ||
97 | static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) | 101 | static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name) |
102 | { | ||
103 | struct stat st; | ||
104 | ssize_t sret; | ||
105 | char scale[128]; | ||
106 | int fd, ret = -1; | ||
107 | char path[PATH_MAX]; | ||
108 | char *lc; | ||
109 | |||
110 | snprintf(path, PATH_MAX, "%s/%s.scale", dir, name); | ||
111 | |||
112 | fd = open(path, O_RDONLY); | ||
113 | if (fd == -1) | ||
114 | return -1; | ||
115 | |||
116 | if (fstat(fd, &st) < 0) | ||
117 | goto error; | ||
118 | |||
119 | sret = read(fd, scale, sizeof(scale)-1); | ||
120 | if (sret < 0) | ||
121 | goto error; | ||
122 | |||
123 | scale[sret] = '\0'; | ||
124 | /* | ||
125 | * save current locale | ||
126 | */ | ||
127 | lc = setlocale(LC_NUMERIC, NULL); | ||
128 | |||
129 | /* | ||
130 | * force to C locale to ensure kernel | ||
131 | * scale string is converted correctly. | ||
132 | * kernel uses default C locale. | ||
133 | */ | ||
134 | setlocale(LC_NUMERIC, "C"); | ||
135 | |||
136 | alias->scale = strtod(scale, NULL); | ||
137 | |||
138 | /* restore locale */ | ||
139 | setlocale(LC_NUMERIC, lc); | ||
140 | |||
141 | ret = 0; | ||
142 | error: | ||
143 | close(fd); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name) | ||
148 | { | ||
149 | char path[PATH_MAX]; | ||
150 | ssize_t sret; | ||
151 | int fd; | ||
152 | |||
153 | snprintf(path, PATH_MAX, "%s/%s.unit", dir, name); | ||
154 | |||
155 | fd = open(path, O_RDONLY); | ||
156 | if (fd == -1) | ||
157 | return -1; | ||
158 | |||
159 | sret = read(fd, alias->unit, UNIT_MAX_LEN); | ||
160 | if (sret < 0) | ||
161 | goto error; | ||
162 | |||
163 | close(fd); | ||
164 | |||
165 | alias->unit[sret] = '\0'; | ||
166 | |||
167 | return 0; | ||
168 | error: | ||
169 | close(fd); | ||
170 | alias->unit[0] = '\0'; | ||
171 | return -1; | ||
172 | } | ||
173 | |||
174 | static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) | ||
98 | { | 175 | { |
99 | struct perf_pmu_alias *alias; | 176 | struct perf_pmu_alias *alias; |
100 | char buf[256]; | 177 | char buf[256]; |
@@ -110,6 +187,9 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) | |||
110 | return -ENOMEM; | 187 | return -ENOMEM; |
111 | 188 | ||
112 | INIT_LIST_HEAD(&alias->terms); | 189 | INIT_LIST_HEAD(&alias->terms); |
190 | alias->scale = 1.0; | ||
191 | alias->unit[0] = '\0'; | ||
192 | |||
113 | ret = parse_events_terms(&alias->terms, buf); | 193 | ret = parse_events_terms(&alias->terms, buf); |
114 | if (ret) { | 194 | if (ret) { |
115 | free(alias); | 195 | free(alias); |
@@ -117,7 +197,14 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) | |||
117 | } | 197 | } |
118 | 198 | ||
119 | alias->name = strdup(name); | 199 | alias->name = strdup(name); |
200 | /* | ||
201 | * load unit name and scale if available | ||
202 | */ | ||
203 | perf_pmu__parse_unit(alias, dir, name); | ||
204 | perf_pmu__parse_scale(alias, dir, name); | ||
205 | |||
120 | list_add_tail(&alias->list, list); | 206 | list_add_tail(&alias->list, list); |
207 | |||
121 | return 0; | 208 | return 0; |
122 | } | 209 | } |
123 | 210 | ||
@@ -129,6 +216,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head) | |||
129 | { | 216 | { |
130 | struct dirent *evt_ent; | 217 | struct dirent *evt_ent; |
131 | DIR *event_dir; | 218 | DIR *event_dir; |
219 | size_t len; | ||
132 | int ret = 0; | 220 | int ret = 0; |
133 | 221 | ||
134 | event_dir = opendir(dir); | 222 | event_dir = opendir(dir); |
@@ -143,13 +231,24 @@ static int pmu_aliases_parse(char *dir, struct list_head *head) | |||
143 | if (!strcmp(name, ".") || !strcmp(name, "..")) | 231 | if (!strcmp(name, ".") || !strcmp(name, "..")) |
144 | continue; | 232 | continue; |
145 | 233 | ||
234 | /* | ||
235 | * skip .unit and .scale info files | ||
236 | * parsed in perf_pmu__new_alias() | ||
237 | */ | ||
238 | len = strlen(name); | ||
239 | if (len > 5 && !strcmp(name + len - 5, ".unit")) | ||
240 | continue; | ||
241 | if (len > 6 && !strcmp(name + len - 6, ".scale")) | ||
242 | continue; | ||
243 | |||
146 | snprintf(path, PATH_MAX, "%s/%s", dir, name); | 244 | snprintf(path, PATH_MAX, "%s/%s", dir, name); |
147 | 245 | ||
148 | ret = -EINVAL; | 246 | ret = -EINVAL; |
149 | file = fopen(path, "r"); | 247 | file = fopen(path, "r"); |
150 | if (!file) | 248 | if (!file) |
151 | break; | 249 | break; |
152 | ret = perf_pmu__new_alias(head, name, file); | 250 | |
251 | ret = perf_pmu__new_alias(head, dir, name, file); | ||
153 | fclose(file); | 252 | fclose(file); |
154 | } | 253 | } |
155 | 254 | ||
@@ -406,7 +505,7 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value) | |||
406 | 505 | ||
407 | /* | 506 | /* |
408 | * Setup one of config[12] attr members based on the | 507 | * Setup one of config[12] attr members based on the |
409 | * user input data - temr parameter. | 508 | * user input data - term parameter. |
410 | */ | 509 | */ |
411 | static int pmu_config_term(struct list_head *formats, | 510 | static int pmu_config_term(struct list_head *formats, |
412 | struct perf_event_attr *attr, | 511 | struct perf_event_attr *attr, |
@@ -508,16 +607,42 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, | |||
508 | return NULL; | 607 | return NULL; |
509 | } | 608 | } |
510 | 609 | ||
610 | |||
611 | static int check_unit_scale(struct perf_pmu_alias *alias, | ||
612 | char **unit, double *scale) | ||
613 | { | ||
614 | /* | ||
615 | * Only one term in event definition can | ||
616 | * define unit and scale, fail if there's | ||
617 | * more than one. | ||
618 | */ | ||
619 | if ((*unit && alias->unit) || | ||
620 | (*scale && alias->scale)) | ||
621 | return -EINVAL; | ||
622 | |||
623 | if (alias->unit) | ||
624 | *unit = alias->unit; | ||
625 | |||
626 | if (alias->scale) | ||
627 | *scale = alias->scale; | ||
628 | |||
629 | return 0; | ||
630 | } | ||
631 | |||
511 | /* | 632 | /* |
512 | * Find alias in the terms list and replace it with the terms | 633 | * Find alias in the terms list and replace it with the terms |
513 | * defined for the alias | 634 | * defined for the alias |
514 | */ | 635 | */ |
515 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) | 636 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, |
637 | char **unit, double *scale) | ||
516 | { | 638 | { |
517 | struct parse_events_term *term, *h; | 639 | struct parse_events_term *term, *h; |
518 | struct perf_pmu_alias *alias; | 640 | struct perf_pmu_alias *alias; |
519 | int ret; | 641 | int ret; |
520 | 642 | ||
643 | *unit = NULL; | ||
644 | *scale = 0; | ||
645 | |||
521 | list_for_each_entry_safe(term, h, head_terms, list) { | 646 | list_for_each_entry_safe(term, h, head_terms, list) { |
522 | alias = pmu_find_alias(pmu, term); | 647 | alias = pmu_find_alias(pmu, term); |
523 | if (!alias) | 648 | if (!alias) |
@@ -525,6 +650,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) | |||
525 | ret = pmu_alias_terms(alias, &term->list); | 650 | ret = pmu_alias_terms(alias, &term->list); |
526 | if (ret) | 651 | if (ret) |
527 | return ret; | 652 | return ret; |
653 | |||
654 | ret = check_unit_scale(alias, unit, scale); | ||
655 | if (ret) | ||
656 | return ret; | ||
657 | |||
528 | list_del(&term->list); | 658 | list_del(&term->list); |
529 | free(term); | 659 | free(term); |
530 | } | 660 | } |
@@ -625,7 +755,7 @@ void print_pmu_events(const char *event_glob, bool name_only) | |||
625 | continue; | 755 | continue; |
626 | } | 756 | } |
627 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); | 757 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); |
628 | free(aliases[j]); | 758 | zfree(&aliases[j]); |
629 | printed++; | 759 | printed++; |
630 | } | 760 | } |
631 | if (printed) | 761 | if (printed) |
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 1179b26f244a..9183380e2038 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h | |||
@@ -28,7 +28,8 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, | |||
28 | int perf_pmu__config_terms(struct list_head *formats, | 28 | int perf_pmu__config_terms(struct list_head *formats, |
29 | struct perf_event_attr *attr, | 29 | struct perf_event_attr *attr, |
30 | struct list_head *head_terms); | 30 | struct list_head *head_terms); |
31 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms); | 31 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, |
32 | char **unit, double *scale); | ||
32 | struct list_head *perf_pmu__alias(struct perf_pmu *pmu, | 33 | struct list_head *perf_pmu__alias(struct perf_pmu *pmu, |
33 | struct list_head *head_terms); | 34 | struct list_head *head_terms); |
34 | int perf_pmu_wrap(void); | 35 | int perf_pmu_wrap(void); |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 9c6989ca2bea..a8a9b6cd93a8 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include "color.h" | 40 | #include "color.h" |
41 | #include "symbol.h" | 41 | #include "symbol.h" |
42 | #include "thread.h" | 42 | #include "thread.h" |
43 | #include <lk/debugfs.h> | 43 | #include <api/fs/debugfs.h> |
44 | #include "trace-event.h" /* For __maybe_unused */ | 44 | #include "trace-event.h" /* For __maybe_unused */ |
45 | #include "probe-event.h" | 45 | #include "probe-event.h" |
46 | #include "probe-finder.h" | 46 | #include "probe-finder.h" |
@@ -72,6 +72,7 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) | |||
72 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); | 72 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); |
73 | static int convert_name_to_addr(struct perf_probe_event *pev, | 73 | static int convert_name_to_addr(struct perf_probe_event *pev, |
74 | const char *exec); | 74 | const char *exec); |
75 | static void clear_probe_trace_event(struct probe_trace_event *tev); | ||
75 | static struct machine machine; | 76 | static struct machine machine; |
76 | 77 | ||
77 | /* Initialize symbol maps and path of vmlinux/modules */ | 78 | /* Initialize symbol maps and path of vmlinux/modules */ |
@@ -154,7 +155,7 @@ static struct dso *kernel_get_module_dso(const char *module) | |||
154 | 155 | ||
155 | vmlinux_name = symbol_conf.vmlinux_name; | 156 | vmlinux_name = symbol_conf.vmlinux_name; |
156 | if (vmlinux_name) { | 157 | if (vmlinux_name) { |
157 | if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0) | 158 | if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0) |
158 | return NULL; | 159 | return NULL; |
159 | } else { | 160 | } else { |
160 | if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { | 161 | if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { |
@@ -186,6 +187,37 @@ static int init_user_exec(void) | |||
186 | return ret; | 187 | return ret; |
187 | } | 188 | } |
188 | 189 | ||
190 | static int convert_exec_to_group(const char *exec, char **result) | ||
191 | { | ||
192 | char *ptr1, *ptr2, *exec_copy; | ||
193 | char buf[64]; | ||
194 | int ret; | ||
195 | |||
196 | exec_copy = strdup(exec); | ||
197 | if (!exec_copy) | ||
198 | return -ENOMEM; | ||
199 | |||
200 | ptr1 = basename(exec_copy); | ||
201 | if (!ptr1) { | ||
202 | ret = -EINVAL; | ||
203 | goto out; | ||
204 | } | ||
205 | |||
206 | ptr2 = strpbrk(ptr1, "-._"); | ||
207 | if (ptr2) | ||
208 | *ptr2 = '\0'; | ||
209 | ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); | ||
210 | if (ret < 0) | ||
211 | goto out; | ||
212 | |||
213 | *result = strdup(buf); | ||
214 | ret = *result ? 0 : -ENOMEM; | ||
215 | |||
216 | out: | ||
217 | free(exec_copy); | ||
218 | return ret; | ||
219 | } | ||
220 | |||
189 | static int convert_to_perf_probe_point(struct probe_trace_point *tp, | 221 | static int convert_to_perf_probe_point(struct probe_trace_point *tp, |
190 | struct perf_probe_point *pp) | 222 | struct perf_probe_point *pp) |
191 | { | 223 | { |
@@ -261,6 +293,68 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, | |||
261 | return 0; | 293 | return 0; |
262 | } | 294 | } |
263 | 295 | ||
296 | static int get_text_start_address(const char *exec, unsigned long *address) | ||
297 | { | ||
298 | Elf *elf; | ||
299 | GElf_Ehdr ehdr; | ||
300 | GElf_Shdr shdr; | ||
301 | int fd, ret = -ENOENT; | ||
302 | |||
303 | fd = open(exec, O_RDONLY); | ||
304 | if (fd < 0) | ||
305 | return -errno; | ||
306 | |||
307 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
308 | if (elf == NULL) | ||
309 | return -EINVAL; | ||
310 | |||
311 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
312 | goto out; | ||
313 | |||
314 | if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL)) | ||
315 | goto out; | ||
316 | |||
317 | *address = shdr.sh_addr - shdr.sh_offset; | ||
318 | ret = 0; | ||
319 | out: | ||
320 | elf_end(elf); | ||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, | ||
325 | int ntevs, const char *exec) | ||
326 | { | ||
327 | int i, ret = 0; | ||
328 | unsigned long offset, stext = 0; | ||
329 | char buf[32]; | ||
330 | |||
331 | if (!exec) | ||
332 | return 0; | ||
333 | |||
334 | ret = get_text_start_address(exec, &stext); | ||
335 | if (ret < 0) | ||
336 | return ret; | ||
337 | |||
338 | for (i = 0; i < ntevs && ret >= 0; i++) { | ||
339 | offset = tevs[i].point.address - stext; | ||
340 | offset += tevs[i].point.offset; | ||
341 | tevs[i].point.offset = 0; | ||
342 | zfree(&tevs[i].point.symbol); | ||
343 | ret = e_snprintf(buf, 32, "0x%lx", offset); | ||
344 | if (ret < 0) | ||
345 | break; | ||
346 | tevs[i].point.module = strdup(exec); | ||
347 | tevs[i].point.symbol = strdup(buf); | ||
348 | if (!tevs[i].point.symbol || !tevs[i].point.module) { | ||
349 | ret = -ENOMEM; | ||
350 | break; | ||
351 | } | ||
352 | tevs[i].uprobes = true; | ||
353 | } | ||
354 | |||
355 | return ret; | ||
356 | } | ||
357 | |||
264 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | 358 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, |
265 | int ntevs, const char *module) | 359 | int ntevs, const char *module) |
266 | { | 360 | { |
@@ -290,12 +384,18 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | |||
290 | } | 384 | } |
291 | } | 385 | } |
292 | 386 | ||
293 | if (tmp) | 387 | free(tmp); |
294 | free(tmp); | ||
295 | |||
296 | return ret; | 388 | return ret; |
297 | } | 389 | } |
298 | 390 | ||
391 | static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) | ||
392 | { | ||
393 | int i; | ||
394 | |||
395 | for (i = 0; i < ntevs; i++) | ||
396 | clear_probe_trace_event(tevs + i); | ||
397 | } | ||
398 | |||
299 | /* Try to find perf_probe_event with debuginfo */ | 399 | /* Try to find perf_probe_event with debuginfo */ |
300 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | 400 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, |
301 | struct probe_trace_event **tevs, | 401 | struct probe_trace_event **tevs, |
@@ -305,15 +405,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
305 | struct debuginfo *dinfo; | 405 | struct debuginfo *dinfo; |
306 | int ntevs, ret = 0; | 406 | int ntevs, ret = 0; |
307 | 407 | ||
308 | if (pev->uprobes) { | ||
309 | if (need_dwarf) { | ||
310 | pr_warning("Debuginfo-analysis is not yet supported" | ||
311 | " with -x/--exec option.\n"); | ||
312 | return -ENOSYS; | ||
313 | } | ||
314 | return convert_name_to_addr(pev, target); | ||
315 | } | ||
316 | |||
317 | dinfo = open_debuginfo(target); | 408 | dinfo = open_debuginfo(target); |
318 | 409 | ||
319 | if (!dinfo) { | 410 | if (!dinfo) { |
@@ -332,9 +423,18 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
332 | 423 | ||
333 | if (ntevs > 0) { /* Succeeded to find trace events */ | 424 | if (ntevs > 0) { /* Succeeded to find trace events */ |
334 | pr_debug("find %d probe_trace_events.\n", ntevs); | 425 | pr_debug("find %d probe_trace_events.\n", ntevs); |
335 | if (target) | 426 | if (target) { |
336 | ret = add_module_to_probe_trace_events(*tevs, ntevs, | 427 | if (pev->uprobes) |
337 | target); | 428 | ret = add_exec_to_probe_trace_events(*tevs, |
429 | ntevs, target); | ||
430 | else | ||
431 | ret = add_module_to_probe_trace_events(*tevs, | ||
432 | ntevs, target); | ||
433 | } | ||
434 | if (ret < 0) { | ||
435 | clear_probe_trace_events(*tevs, ntevs); | ||
436 | zfree(tevs); | ||
437 | } | ||
338 | return ret < 0 ? ret : ntevs; | 438 | return ret < 0 ? ret : ntevs; |
339 | } | 439 | } |
340 | 440 | ||
@@ -401,15 +501,13 @@ static int get_real_path(const char *raw_path, const char *comp_dir, | |||
401 | case EFAULT: | 501 | case EFAULT: |
402 | raw_path = strchr(++raw_path, '/'); | 502 | raw_path = strchr(++raw_path, '/'); |
403 | if (!raw_path) { | 503 | if (!raw_path) { |
404 | free(*new_path); | 504 | zfree(new_path); |
405 | *new_path = NULL; | ||
406 | return -ENOENT; | 505 | return -ENOENT; |
407 | } | 506 | } |
408 | continue; | 507 | continue; |
409 | 508 | ||
410 | default: | 509 | default: |
411 | free(*new_path); | 510 | zfree(new_path); |
412 | *new_path = NULL; | ||
413 | return -errno; | 511 | return -errno; |
414 | } | 512 | } |
415 | } | 513 | } |
@@ -580,7 +678,7 @@ static int show_available_vars_at(struct debuginfo *dinfo, | |||
580 | */ | 678 | */ |
581 | fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, | 679 | fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, |
582 | vl->point.offset); | 680 | vl->point.offset); |
583 | free(vl->point.symbol); | 681 | zfree(&vl->point.symbol); |
584 | nvars = 0; | 682 | nvars = 0; |
585 | if (vl->vars) { | 683 | if (vl->vars) { |
586 | strlist__for_each(node, vl->vars) { | 684 | strlist__for_each(node, vl->vars) { |
@@ -647,16 +745,14 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, | |||
647 | 745 | ||
648 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | 746 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, |
649 | struct probe_trace_event **tevs __maybe_unused, | 747 | struct probe_trace_event **tevs __maybe_unused, |
650 | int max_tevs __maybe_unused, const char *target) | 748 | int max_tevs __maybe_unused, |
749 | const char *target __maybe_unused) | ||
651 | { | 750 | { |
652 | if (perf_probe_event_need_dwarf(pev)) { | 751 | if (perf_probe_event_need_dwarf(pev)) { |
653 | pr_warning("Debuginfo-analysis is not supported.\n"); | 752 | pr_warning("Debuginfo-analysis is not supported.\n"); |
654 | return -ENOSYS; | 753 | return -ENOSYS; |
655 | } | 754 | } |
656 | 755 | ||
657 | if (pev->uprobes) | ||
658 | return convert_name_to_addr(pev, target); | ||
659 | |||
660 | return 0; | 756 | return 0; |
661 | } | 757 | } |
662 | 758 | ||
@@ -678,6 +774,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused, | |||
678 | } | 774 | } |
679 | #endif | 775 | #endif |
680 | 776 | ||
777 | void line_range__clear(struct line_range *lr) | ||
778 | { | ||
779 | struct line_node *ln; | ||
780 | |||
781 | free(lr->function); | ||
782 | free(lr->file); | ||
783 | free(lr->path); | ||
784 | free(lr->comp_dir); | ||
785 | while (!list_empty(&lr->line_list)) { | ||
786 | ln = list_first_entry(&lr->line_list, struct line_node, list); | ||
787 | list_del(&ln->list); | ||
788 | free(ln); | ||
789 | } | ||
790 | memset(lr, 0, sizeof(*lr)); | ||
791 | } | ||
792 | |||
793 | void line_range__init(struct line_range *lr) | ||
794 | { | ||
795 | memset(lr, 0, sizeof(*lr)); | ||
796 | INIT_LIST_HEAD(&lr->line_list); | ||
797 | } | ||
798 | |||
681 | static int parse_line_num(char **ptr, int *val, const char *what) | 799 | static int parse_line_num(char **ptr, int *val, const char *what) |
682 | { | 800 | { |
683 | const char *start = *ptr; | 801 | const char *start = *ptr; |
@@ -1278,8 +1396,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) | |||
1278 | error: | 1396 | error: |
1279 | pr_debug("Failed to synthesize perf probe point: %s\n", | 1397 | pr_debug("Failed to synthesize perf probe point: %s\n", |
1280 | strerror(-ret)); | 1398 | strerror(-ret)); |
1281 | if (buf) | 1399 | free(buf); |
1282 | free(buf); | ||
1283 | return NULL; | 1400 | return NULL; |
1284 | } | 1401 | } |
1285 | 1402 | ||
@@ -1480,34 +1597,25 @@ void clear_perf_probe_event(struct perf_probe_event *pev) | |||
1480 | struct perf_probe_arg_field *field, *next; | 1597 | struct perf_probe_arg_field *field, *next; |
1481 | int i; | 1598 | int i; |
1482 | 1599 | ||
1483 | if (pev->event) | 1600 | free(pev->event); |
1484 | free(pev->event); | 1601 | free(pev->group); |
1485 | if (pev->group) | 1602 | free(pp->file); |
1486 | free(pev->group); | 1603 | free(pp->function); |
1487 | if (pp->file) | 1604 | free(pp->lazy_line); |
1488 | free(pp->file); | 1605 | |
1489 | if (pp->function) | ||
1490 | free(pp->function); | ||
1491 | if (pp->lazy_line) | ||
1492 | free(pp->lazy_line); | ||
1493 | for (i = 0; i < pev->nargs; i++) { | 1606 | for (i = 0; i < pev->nargs; i++) { |
1494 | if (pev->args[i].name) | 1607 | free(pev->args[i].name); |
1495 | free(pev->args[i].name); | 1608 | free(pev->args[i].var); |
1496 | if (pev->args[i].var) | 1609 | free(pev->args[i].type); |
1497 | free(pev->args[i].var); | ||
1498 | if (pev->args[i].type) | ||
1499 | free(pev->args[i].type); | ||
1500 | field = pev->args[i].field; | 1610 | field = pev->args[i].field; |
1501 | while (field) { | 1611 | while (field) { |
1502 | next = field->next; | 1612 | next = field->next; |
1503 | if (field->name) | 1613 | zfree(&field->name); |
1504 | free(field->name); | ||
1505 | free(field); | 1614 | free(field); |
1506 | field = next; | 1615 | field = next; |
1507 | } | 1616 | } |
1508 | } | 1617 | } |
1509 | if (pev->args) | 1618 | free(pev->args); |
1510 | free(pev->args); | ||
1511 | memset(pev, 0, sizeof(*pev)); | 1619 | memset(pev, 0, sizeof(*pev)); |
1512 | } | 1620 | } |
1513 | 1621 | ||
@@ -1516,21 +1624,14 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) | |||
1516 | struct probe_trace_arg_ref *ref, *next; | 1624 | struct probe_trace_arg_ref *ref, *next; |
1517 | int i; | 1625 | int i; |
1518 | 1626 | ||
1519 | if (tev->event) | 1627 | free(tev->event); |
1520 | free(tev->event); | 1628 | free(tev->group); |
1521 | if (tev->group) | 1629 | free(tev->point.symbol); |
1522 | free(tev->group); | 1630 | free(tev->point.module); |
1523 | if (tev->point.symbol) | ||
1524 | free(tev->point.symbol); | ||
1525 | if (tev->point.module) | ||
1526 | free(tev->point.module); | ||
1527 | for (i = 0; i < tev->nargs; i++) { | 1631 | for (i = 0; i < tev->nargs; i++) { |
1528 | if (tev->args[i].name) | 1632 | free(tev->args[i].name); |
1529 | free(tev->args[i].name); | 1633 | free(tev->args[i].value); |
1530 | if (tev->args[i].value) | 1634 | free(tev->args[i].type); |
1531 | free(tev->args[i].value); | ||
1532 | if (tev->args[i].type) | ||
1533 | free(tev->args[i].type); | ||
1534 | ref = tev->args[i].ref; | 1635 | ref = tev->args[i].ref; |
1535 | while (ref) { | 1636 | while (ref) { |
1536 | next = ref->next; | 1637 | next = ref->next; |
@@ -1538,8 +1639,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) | |||
1538 | ref = next; | 1639 | ref = next; |
1539 | } | 1640 | } |
1540 | } | 1641 | } |
1541 | if (tev->args) | 1642 | free(tev->args); |
1542 | free(tev->args); | ||
1543 | memset(tev, 0, sizeof(*tev)); | 1643 | memset(tev, 0, sizeof(*tev)); |
1544 | } | 1644 | } |
1545 | 1645 | ||
@@ -1913,14 +2013,29 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
1913 | int max_tevs, const char *target) | 2013 | int max_tevs, const char *target) |
1914 | { | 2014 | { |
1915 | struct symbol *sym; | 2015 | struct symbol *sym; |
1916 | int ret = 0, i; | 2016 | int ret, i; |
1917 | struct probe_trace_event *tev; | 2017 | struct probe_trace_event *tev; |
1918 | 2018 | ||
2019 | if (pev->uprobes && !pev->group) { | ||
2020 | /* Replace group name if not given */ | ||
2021 | ret = convert_exec_to_group(target, &pev->group); | ||
2022 | if (ret != 0) { | ||
2023 | pr_warning("Failed to make a group name.\n"); | ||
2024 | return ret; | ||
2025 | } | ||
2026 | } | ||
2027 | |||
1919 | /* Convert perf_probe_event with debuginfo */ | 2028 | /* Convert perf_probe_event with debuginfo */ |
1920 | ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); | 2029 | ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); |
1921 | if (ret != 0) | 2030 | if (ret != 0) |
1922 | return ret; /* Found in debuginfo or got an error */ | 2031 | return ret; /* Found in debuginfo or got an error */ |
1923 | 2032 | ||
2033 | if (pev->uprobes) { | ||
2034 | ret = convert_name_to_addr(pev, target); | ||
2035 | if (ret < 0) | ||
2036 | return ret; | ||
2037 | } | ||
2038 | |||
1924 | /* Allocate trace event buffer */ | 2039 | /* Allocate trace event buffer */ |
1925 | tev = *tevs = zalloc(sizeof(struct probe_trace_event)); | 2040 | tev = *tevs = zalloc(sizeof(struct probe_trace_event)); |
1926 | if (tev == NULL) | 2041 | if (tev == NULL) |
@@ -2056,7 +2171,7 @@ end: | |||
2056 | for (i = 0; i < npevs; i++) { | 2171 | for (i = 0; i < npevs; i++) { |
2057 | for (j = 0; j < pkgs[i].ntevs; j++) | 2172 | for (j = 0; j < pkgs[i].ntevs; j++) |
2058 | clear_probe_trace_event(&pkgs[i].tevs[j]); | 2173 | clear_probe_trace_event(&pkgs[i].tevs[j]); |
2059 | free(pkgs[i].tevs); | 2174 | zfree(&pkgs[i].tevs); |
2060 | } | 2175 | } |
2061 | free(pkgs); | 2176 | free(pkgs); |
2062 | 2177 | ||
@@ -2281,7 +2396,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) | |||
2281 | struct perf_probe_point *pp = &pev->point; | 2396 | struct perf_probe_point *pp = &pev->point; |
2282 | struct symbol *sym; | 2397 | struct symbol *sym; |
2283 | struct map *map = NULL; | 2398 | struct map *map = NULL; |
2284 | char *function = NULL, *name = NULL; | 2399 | char *function = NULL; |
2285 | int ret = -EINVAL; | 2400 | int ret = -EINVAL; |
2286 | unsigned long long vaddr = 0; | 2401 | unsigned long long vaddr = 0; |
2287 | 2402 | ||
@@ -2297,12 +2412,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) | |||
2297 | goto out; | 2412 | goto out; |
2298 | } | 2413 | } |
2299 | 2414 | ||
2300 | name = realpath(exec, NULL); | 2415 | map = dso__new_map(exec); |
2301 | if (!name) { | ||
2302 | pr_warning("Cannot find realpath for %s.\n", exec); | ||
2303 | goto out; | ||
2304 | } | ||
2305 | map = dso__new_map(name); | ||
2306 | if (!map) { | 2416 | if (!map) { |
2307 | pr_warning("Cannot find appropriate DSO for %s.\n", exec); | 2417 | pr_warning("Cannot find appropriate DSO for %s.\n", exec); |
2308 | goto out; | 2418 | goto out; |
@@ -2367,7 +2477,5 @@ out: | |||
2367 | } | 2477 | } |
2368 | if (function) | 2478 | if (function) |
2369 | free(function); | 2479 | free(function); |
2370 | if (name) | ||
2371 | free(name); | ||
2372 | return ret; | 2480 | return ret; |
2373 | } | 2481 | } |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index f9f3de8b4220..fcaf7273e85a 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -12,6 +12,7 @@ struct probe_trace_point { | |||
12 | char *symbol; /* Base symbol */ | 12 | char *symbol; /* Base symbol */ |
13 | char *module; /* Module name */ | 13 | char *module; /* Module name */ |
14 | unsigned long offset; /* Offset from symbol */ | 14 | unsigned long offset; /* Offset from symbol */ |
15 | unsigned long address; /* Actual address of the trace point */ | ||
15 | bool retprobe; /* Return probe flag */ | 16 | bool retprobe; /* Return probe flag */ |
16 | }; | 17 | }; |
17 | 18 | ||
@@ -119,6 +120,12 @@ extern void clear_perf_probe_event(struct perf_probe_event *pev); | |||
119 | /* Command string to line-range */ | 120 | /* Command string to line-range */ |
120 | extern int parse_line_range_desc(const char *cmd, struct line_range *lr); | 121 | extern int parse_line_range_desc(const char *cmd, struct line_range *lr); |
121 | 122 | ||
123 | /* Release line range members */ | ||
124 | extern void line_range__clear(struct line_range *lr); | ||
125 | |||
126 | /* Initialize line range */ | ||
127 | extern void line_range__init(struct line_range *lr); | ||
128 | |||
122 | /* Internal use: Return kernel/module path */ | 129 | /* Internal use: Return kernel/module path */ |
123 | extern const char *kernel_get_module_path(const char *module); | 130 | extern const char *kernel_get_module_path(const char *module); |
124 | 131 | ||
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index ffb657ffd327..061edb162b5b 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -226,10 +226,8 @@ struct debuginfo *debuginfo__new(const char *path) | |||
226 | if (!dbg) | 226 | if (!dbg) |
227 | return NULL; | 227 | return NULL; |
228 | 228 | ||
229 | if (debuginfo__init_offline_dwarf(dbg, path) < 0) { | 229 | if (debuginfo__init_offline_dwarf(dbg, path) < 0) |
230 | free(dbg); | 230 | zfree(&dbg); |
231 | dbg = NULL; | ||
232 | } | ||
233 | 231 | ||
234 | return dbg; | 232 | return dbg; |
235 | } | 233 | } |
@@ -241,10 +239,8 @@ struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) | |||
241 | if (!dbg) | 239 | if (!dbg) |
242 | return NULL; | 240 | return NULL; |
243 | 241 | ||
244 | if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) { | 242 | if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) |
245 | free(dbg); | 243 | zfree(&dbg); |
246 | dbg = NULL; | ||
247 | } | ||
248 | 244 | ||
249 | return dbg; | 245 | return dbg; |
250 | } | 246 | } |
@@ -729,6 +725,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | |||
729 | return -ENOENT; | 725 | return -ENOENT; |
730 | } | 726 | } |
731 | tp->offset = (unsigned long)(paddr - sym.st_value); | 727 | tp->offset = (unsigned long)(paddr - sym.st_value); |
728 | tp->address = (unsigned long)paddr; | ||
732 | tp->symbol = strdup(symbol); | 729 | tp->symbol = strdup(symbol); |
733 | if (!tp->symbol) | 730 | if (!tp->symbol) |
734 | return -ENOMEM; | 731 | return -ENOMEM; |
@@ -1301,8 +1298,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, | |||
1301 | 1298 | ||
1302 | ret = debuginfo__find_probes(dbg, &tf.pf); | 1299 | ret = debuginfo__find_probes(dbg, &tf.pf); |
1303 | if (ret < 0) { | 1300 | if (ret < 0) { |
1304 | free(*tevs); | 1301 | zfree(tevs); |
1305 | *tevs = NULL; | ||
1306 | return ret; | 1302 | return ret; |
1307 | } | 1303 | } |
1308 | 1304 | ||
@@ -1413,13 +1409,10 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, | |||
1413 | if (ret < 0) { | 1409 | if (ret < 0) { |
1414 | /* Free vlist for error */ | 1410 | /* Free vlist for error */ |
1415 | while (af.nvls--) { | 1411 | while (af.nvls--) { |
1416 | if (af.vls[af.nvls].point.symbol) | 1412 | zfree(&af.vls[af.nvls].point.symbol); |
1417 | free(af.vls[af.nvls].point.symbol); | 1413 | strlist__delete(af.vls[af.nvls].vars); |
1418 | if (af.vls[af.nvls].vars) | ||
1419 | strlist__delete(af.vls[af.nvls].vars); | ||
1420 | } | 1414 | } |
1421 | free(af.vls); | 1415 | zfree(vls); |
1422 | *vls = NULL; | ||
1423 | return ret; | 1416 | return ret; |
1424 | } | 1417 | } |
1425 | 1418 | ||
@@ -1523,10 +1516,7 @@ post: | |||
1523 | if (fname) { | 1516 | if (fname) { |
1524 | ppt->file = strdup(fname); | 1517 | ppt->file = strdup(fname); |
1525 | if (ppt->file == NULL) { | 1518 | if (ppt->file == NULL) { |
1526 | if (ppt->function) { | 1519 | zfree(&ppt->function); |
1527 | free(ppt->function); | ||
1528 | ppt->function = NULL; | ||
1529 | } | ||
1530 | ret = -ENOMEM; | 1520 | ret = -ENOMEM; |
1531 | goto end; | 1521 | goto end; |
1532 | } | 1522 | } |
@@ -1580,8 +1570,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) | |||
1580 | else | 1570 | else |
1581 | ret = 0; /* Lines are not found */ | 1571 | ret = 0; /* Lines are not found */ |
1582 | else { | 1572 | else { |
1583 | free(lf->lr->path); | 1573 | zfree(&lf->lr->path); |
1584 | lf->lr->path = NULL; | ||
1585 | } | 1574 | } |
1586 | return ret; | 1575 | return ret; |
1587 | } | 1576 | } |
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 239036fb2b2c..595bfc73d2ed 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources | |||
@@ -18,4 +18,5 @@ util/cgroup.c | |||
18 | util/rblist.c | 18 | util/rblist.c |
19 | util/strlist.c | 19 | util/strlist.c |
20 | util/fs.c | 20 | util/fs.c |
21 | util/trace-event.c | ||
21 | ../../lib/rbtree.c | 22 | ../../lib/rbtree.c |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 4bf8ace7f511..122669c18ff4 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
@@ -908,9 +908,10 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) | |||
908 | if (i >= pevlist->evlist.nr_entries) | 908 | if (i >= pevlist->evlist.nr_entries) |
909 | return NULL; | 909 | return NULL; |
910 | 910 | ||
911 | list_for_each_entry(pos, &pevlist->evlist.entries, node) | 911 | evlist__for_each(&pevlist->evlist, pos) { |
912 | if (i-- == 0) | 912 | if (i-- == 0) |
913 | break; | 913 | break; |
914 | } | ||
914 | 915 | ||
915 | return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel)); | 916 | return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel)); |
916 | } | 917 | } |
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index c8845b107f60..373762501dad 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
@@ -74,8 +74,7 @@ bool perf_can_sample_identifier(void) | |||
74 | return perf_probe_api(perf_probe_sample_identifier); | 74 | return perf_probe_api(perf_probe_sample_identifier); |
75 | } | 75 | } |
76 | 76 | ||
77 | void perf_evlist__config(struct perf_evlist *evlist, | 77 | void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) |
78 | struct perf_record_opts *opts) | ||
79 | { | 78 | { |
80 | struct perf_evsel *evsel; | 79 | struct perf_evsel *evsel; |
81 | bool use_sample_identifier = false; | 80 | bool use_sample_identifier = false; |
@@ -90,19 +89,19 @@ void perf_evlist__config(struct perf_evlist *evlist, | |||
90 | if (evlist->cpus->map[0] < 0) | 89 | if (evlist->cpus->map[0] < 0) |
91 | opts->no_inherit = true; | 90 | opts->no_inherit = true; |
92 | 91 | ||
93 | list_for_each_entry(evsel, &evlist->entries, node) | 92 | evlist__for_each(evlist, evsel) |
94 | perf_evsel__config(evsel, opts); | 93 | perf_evsel__config(evsel, opts); |
95 | 94 | ||
96 | if (evlist->nr_entries > 1) { | 95 | if (evlist->nr_entries > 1) { |
97 | struct perf_evsel *first = perf_evlist__first(evlist); | 96 | struct perf_evsel *first = perf_evlist__first(evlist); |
98 | 97 | ||
99 | list_for_each_entry(evsel, &evlist->entries, node) { | 98 | evlist__for_each(evlist, evsel) { |
100 | if (evsel->attr.sample_type == first->attr.sample_type) | 99 | if (evsel->attr.sample_type == first->attr.sample_type) |
101 | continue; | 100 | continue; |
102 | use_sample_identifier = perf_can_sample_identifier(); | 101 | use_sample_identifier = perf_can_sample_identifier(); |
103 | break; | 102 | break; |
104 | } | 103 | } |
105 | list_for_each_entry(evsel, &evlist->entries, node) | 104 | evlist__for_each(evlist, evsel) |
106 | perf_evsel__set_sample_id(evsel, use_sample_identifier); | 105 | perf_evsel__set_sample_id(evsel, use_sample_identifier); |
107 | } | 106 | } |
108 | 107 | ||
@@ -123,7 +122,7 @@ static int get_max_rate(unsigned int *rate) | |||
123 | return filename__read_int(path, (int *) rate); | 122 | return filename__read_int(path, (int *) rate); |
124 | } | 123 | } |
125 | 124 | ||
126 | static int perf_record_opts__config_freq(struct perf_record_opts *opts) | 125 | static int record_opts__config_freq(struct record_opts *opts) |
127 | { | 126 | { |
128 | bool user_freq = opts->user_freq != UINT_MAX; | 127 | bool user_freq = opts->user_freq != UINT_MAX; |
129 | unsigned int max_rate; | 128 | unsigned int max_rate; |
@@ -173,7 +172,44 @@ static int perf_record_opts__config_freq(struct perf_record_opts *opts) | |||
173 | return 0; | 172 | return 0; |
174 | } | 173 | } |
175 | 174 | ||
176 | int perf_record_opts__config(struct perf_record_opts *opts) | 175 | int record_opts__config(struct record_opts *opts) |
177 | { | 176 | { |
178 | return perf_record_opts__config_freq(opts); | 177 | return record_opts__config_freq(opts); |
178 | } | ||
179 | |||
180 | bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) | ||
181 | { | ||
182 | struct perf_evlist *temp_evlist; | ||
183 | struct perf_evsel *evsel; | ||
184 | int err, fd, cpu; | ||
185 | bool ret = false; | ||
186 | |||
187 | temp_evlist = perf_evlist__new(); | ||
188 | if (!temp_evlist) | ||
189 | return false; | ||
190 | |||
191 | err = parse_events(temp_evlist, str); | ||
192 | if (err) | ||
193 | goto out_delete; | ||
194 | |||
195 | evsel = perf_evlist__last(temp_evlist); | ||
196 | |||
197 | if (!evlist || cpu_map__empty(evlist->cpus)) { | ||
198 | struct cpu_map *cpus = cpu_map__new(NULL); | ||
199 | |||
200 | cpu = cpus ? cpus->map[0] : 0; | ||
201 | cpu_map__delete(cpus); | ||
202 | } else { | ||
203 | cpu = evlist->cpus->map[0]; | ||
204 | } | ||
205 | |||
206 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0); | ||
207 | if (fd >= 0) { | ||
208 | close(fd); | ||
209 | ret = true; | ||
210 | } | ||
211 | |||
212 | out_delete: | ||
213 | perf_evlist__delete(temp_evlist); | ||
214 | return ret; | ||
179 | } | 215 | } |
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index d5e5969f6fea..e108207c5de0 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
@@ -194,8 +194,7 @@ static void define_event_symbols(struct event_format *event, | |||
194 | zero_flag_atom = 0; | 194 | zero_flag_atom = 0; |
195 | break; | 195 | break; |
196 | case PRINT_FIELD: | 196 | case PRINT_FIELD: |
197 | if (cur_field_name) | 197 | free(cur_field_name); |
198 | free(cur_field_name); | ||
199 | cur_field_name = strdup(args->field.name); | 198 | cur_field_name = strdup(args->field.name); |
200 | break; | 199 | break; |
201 | case PRINT_FLAGS: | 200 | case PRINT_FLAGS: |
@@ -257,12 +256,9 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | |||
257 | return event; | 256 | return event; |
258 | } | 257 | } |
259 | 258 | ||
260 | static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, | 259 | static void perl_process_tracepoint(struct perf_sample *sample, |
261 | struct perf_sample *sample, | ||
262 | struct perf_evsel *evsel, | 260 | struct perf_evsel *evsel, |
263 | struct machine *machine __maybe_unused, | 261 | struct thread *thread) |
264 | struct thread *thread, | ||
265 | struct addr_location *al) | ||
266 | { | 262 | { |
267 | struct format_field *field; | 263 | struct format_field *field; |
268 | static char handler[256]; | 264 | static char handler[256]; |
@@ -349,10 +345,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, | |||
349 | 345 | ||
350 | static void perl_process_event_generic(union perf_event *event, | 346 | static void perl_process_event_generic(union perf_event *event, |
351 | struct perf_sample *sample, | 347 | struct perf_sample *sample, |
352 | struct perf_evsel *evsel, | 348 | struct perf_evsel *evsel) |
353 | struct machine *machine __maybe_unused, | ||
354 | struct thread *thread __maybe_unused, | ||
355 | struct addr_location *al __maybe_unused) | ||
356 | { | 349 | { |
357 | dSP; | 350 | dSP; |
358 | 351 | ||
@@ -377,12 +370,11 @@ static void perl_process_event_generic(union perf_event *event, | |||
377 | static void perl_process_event(union perf_event *event, | 370 | static void perl_process_event(union perf_event *event, |
378 | struct perf_sample *sample, | 371 | struct perf_sample *sample, |
379 | struct perf_evsel *evsel, | 372 | struct perf_evsel *evsel, |
380 | struct machine *machine, | ||
381 | struct thread *thread, | 373 | struct thread *thread, |
382 | struct addr_location *al) | 374 | struct addr_location *al __maybe_unused) |
383 | { | 375 | { |
384 | perl_process_tracepoint(event, sample, evsel, machine, thread, al); | 376 | perl_process_tracepoint(sample, evsel, thread); |
385 | perl_process_event_generic(event, sample, evsel, machine, thread, al); | 377 | perl_process_event_generic(event, sample, evsel); |
386 | } | 378 | } |
387 | 379 | ||
388 | static void run_start_sub(void) | 380 | static void run_start_sub(void) |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 53c20e7fd900..cd9774df3750 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -161,8 +161,7 @@ static void define_event_symbols(struct event_format *event, | |||
161 | zero_flag_atom = 0; | 161 | zero_flag_atom = 0; |
162 | break; | 162 | break; |
163 | case PRINT_FIELD: | 163 | case PRINT_FIELD: |
164 | if (cur_field_name) | 164 | free(cur_field_name); |
165 | free(cur_field_name); | ||
166 | cur_field_name = strdup(args->field.name); | 165 | cur_field_name = strdup(args->field.name); |
167 | break; | 166 | break; |
168 | case PRINT_FLAGS: | 167 | case PRINT_FLAGS: |
@@ -231,13 +230,10 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | |||
231 | return event; | 230 | return event; |
232 | } | 231 | } |
233 | 232 | ||
234 | static void python_process_tracepoint(union perf_event *perf_event | 233 | static void python_process_tracepoint(struct perf_sample *sample, |
235 | __maybe_unused, | 234 | struct perf_evsel *evsel, |
236 | struct perf_sample *sample, | 235 | struct thread *thread, |
237 | struct perf_evsel *evsel, | 236 | struct addr_location *al) |
238 | struct machine *machine __maybe_unused, | ||
239 | struct thread *thread, | ||
240 | struct addr_location *al) | ||
241 | { | 237 | { |
242 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; | 238 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; |
243 | static char handler_name[256]; | 239 | static char handler_name[256]; |
@@ -351,11 +347,8 @@ static void python_process_tracepoint(union perf_event *perf_event | |||
351 | Py_DECREF(t); | 347 | Py_DECREF(t); |
352 | } | 348 | } |
353 | 349 | ||
354 | static void python_process_general_event(union perf_event *perf_event | 350 | static void python_process_general_event(struct perf_sample *sample, |
355 | __maybe_unused, | ||
356 | struct perf_sample *sample, | ||
357 | struct perf_evsel *evsel, | 351 | struct perf_evsel *evsel, |
358 | struct machine *machine __maybe_unused, | ||
359 | struct thread *thread, | 352 | struct thread *thread, |
360 | struct addr_location *al) | 353 | struct addr_location *al) |
361 | { | 354 | { |
@@ -411,22 +404,19 @@ exit: | |||
411 | Py_DECREF(t); | 404 | Py_DECREF(t); |
412 | } | 405 | } |
413 | 406 | ||
414 | static void python_process_event(union perf_event *perf_event, | 407 | static void python_process_event(union perf_event *event __maybe_unused, |
415 | struct perf_sample *sample, | 408 | struct perf_sample *sample, |
416 | struct perf_evsel *evsel, | 409 | struct perf_evsel *evsel, |
417 | struct machine *machine, | ||
418 | struct thread *thread, | 410 | struct thread *thread, |
419 | struct addr_location *al) | 411 | struct addr_location *al) |
420 | { | 412 | { |
421 | switch (evsel->attr.type) { | 413 | switch (evsel->attr.type) { |
422 | case PERF_TYPE_TRACEPOINT: | 414 | case PERF_TYPE_TRACEPOINT: |
423 | python_process_tracepoint(perf_event, sample, evsel, | 415 | python_process_tracepoint(sample, evsel, thread, al); |
424 | machine, thread, al); | ||
425 | break; | 416 | break; |
426 | /* Reserve for future process_hw/sw/raw APIs */ | 417 | /* Reserve for future process_hw/sw/raw APIs */ |
427 | default: | 418 | default: |
428 | python_process_general_event(perf_event, sample, evsel, | 419 | python_process_general_event(sample, evsel, thread, al); |
429 | machine, thread, al); | ||
430 | } | 420 | } |
431 | } | 421 | } |
432 | 422 | ||
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f36d24a02445..7acc03e8f3b2 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -132,18 +132,18 @@ static void perf_session__delete_threads(struct perf_session *session) | |||
132 | 132 | ||
133 | static void perf_session_env__delete(struct perf_session_env *env) | 133 | static void perf_session_env__delete(struct perf_session_env *env) |
134 | { | 134 | { |
135 | free(env->hostname); | 135 | zfree(&env->hostname); |
136 | free(env->os_release); | 136 | zfree(&env->os_release); |
137 | free(env->version); | 137 | zfree(&env->version); |
138 | free(env->arch); | 138 | zfree(&env->arch); |
139 | free(env->cpu_desc); | 139 | zfree(&env->cpu_desc); |
140 | free(env->cpuid); | 140 | zfree(&env->cpuid); |
141 | 141 | ||
142 | free(env->cmdline); | 142 | zfree(&env->cmdline); |
143 | free(env->sibling_cores); | 143 | zfree(&env->sibling_cores); |
144 | free(env->sibling_threads); | 144 | zfree(&env->sibling_threads); |
145 | free(env->numa_nodes); | 145 | zfree(&env->numa_nodes); |
146 | free(env->pmu_mappings); | 146 | zfree(&env->pmu_mappings); |
147 | } | 147 | } |
148 | 148 | ||
149 | void perf_session__delete(struct perf_session *session) | 149 | void perf_session__delete(struct perf_session *session) |
@@ -247,27 +247,6 @@ void perf_tool__fill_defaults(struct perf_tool *tool) | |||
247 | } | 247 | } |
248 | } | 248 | } |
249 | 249 | ||
250 | void mem_bswap_32(void *src, int byte_size) | ||
251 | { | ||
252 | u32 *m = src; | ||
253 | while (byte_size > 0) { | ||
254 | *m = bswap_32(*m); | ||
255 | byte_size -= sizeof(u32); | ||
256 | ++m; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | void mem_bswap_64(void *src, int byte_size) | ||
261 | { | ||
262 | u64 *m = src; | ||
263 | |||
264 | while (byte_size > 0) { | ||
265 | *m = bswap_64(*m); | ||
266 | byte_size -= sizeof(u64); | ||
267 | ++m; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | static void swap_sample_id_all(union perf_event *event, void *data) | 250 | static void swap_sample_id_all(union perf_event *event, void *data) |
272 | { | 251 | { |
273 | void *end = (void *) event + event->header.size; | 252 | void *end = (void *) event + event->header.size; |
@@ -851,6 +830,7 @@ static struct machine * | |||
851 | struct perf_sample *sample) | 830 | struct perf_sample *sample) |
852 | { | 831 | { |
853 | const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 832 | const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
833 | struct machine *machine; | ||
854 | 834 | ||
855 | if (perf_guest && | 835 | if (perf_guest && |
856 | ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || | 836 | ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || |
@@ -863,7 +843,11 @@ static struct machine * | |||
863 | else | 843 | else |
864 | pid = sample->pid; | 844 | pid = sample->pid; |
865 | 845 | ||
866 | return perf_session__findnew_machine(session, pid); | 846 | machine = perf_session__find_machine(session, pid); |
847 | if (!machine) | ||
848 | machine = perf_session__findnew_machine(session, | ||
849 | DEFAULT_GUEST_KERNEL_ID); | ||
850 | return machine; | ||
867 | } | 851 | } |
868 | 852 | ||
869 | return &session->machines.host; | 853 | return &session->machines.host; |
@@ -1158,7 +1142,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session, | |||
1158 | void *buf = NULL; | 1142 | void *buf = NULL; |
1159 | int skip = 0; | 1143 | int skip = 0; |
1160 | u64 head; | 1144 | u64 head; |
1161 | int err; | 1145 | ssize_t err; |
1162 | void *p; | 1146 | void *p; |
1163 | 1147 | ||
1164 | perf_tool__fill_defaults(tool); | 1148 | perf_tool__fill_defaults(tool); |
@@ -1400,7 +1384,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg) | |||
1400 | { | 1384 | { |
1401 | struct perf_evsel *evsel; | 1385 | struct perf_evsel *evsel; |
1402 | 1386 | ||
1403 | list_for_each_entry(evsel, &session->evlist->entries, node) { | 1387 | evlist__for_each(session->evlist, evsel) { |
1404 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT) | 1388 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT) |
1405 | return true; | 1389 | return true; |
1406 | } | 1390 | } |
@@ -1458,7 +1442,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) | |||
1458 | 1442 | ||
1459 | ret += events_stats__fprintf(&session->stats, fp); | 1443 | ret += events_stats__fprintf(&session->stats, fp); |
1460 | 1444 | ||
1461 | list_for_each_entry(pos, &session->evlist->entries, node) { | 1445 | evlist__for_each(session->evlist, pos) { |
1462 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); | 1446 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); |
1463 | ret += events_stats__fprintf(&pos->hists.stats, fp); | 1447 | ret += events_stats__fprintf(&pos->hists.stats, fp); |
1464 | } | 1448 | } |
@@ -1480,35 +1464,30 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | |||
1480 | { | 1464 | { |
1481 | struct perf_evsel *pos; | 1465 | struct perf_evsel *pos; |
1482 | 1466 | ||
1483 | list_for_each_entry(pos, &session->evlist->entries, node) { | 1467 | evlist__for_each(session->evlist, pos) { |
1484 | if (pos->attr.type == type) | 1468 | if (pos->attr.type == type) |
1485 | return pos; | 1469 | return pos; |
1486 | } | 1470 | } |
1487 | return NULL; | 1471 | return NULL; |
1488 | } | 1472 | } |
1489 | 1473 | ||
1490 | void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | 1474 | void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, |
1491 | struct perf_sample *sample, struct machine *machine, | 1475 | struct addr_location *al, |
1492 | unsigned int print_opts, unsigned int stack_depth) | 1476 | unsigned int print_opts, unsigned int stack_depth) |
1493 | { | 1477 | { |
1494 | struct addr_location al; | ||
1495 | struct callchain_cursor_node *node; | 1478 | struct callchain_cursor_node *node; |
1496 | int print_ip = print_opts & PRINT_IP_OPT_IP; | 1479 | int print_ip = print_opts & PRINT_IP_OPT_IP; |
1497 | int print_sym = print_opts & PRINT_IP_OPT_SYM; | 1480 | int print_sym = print_opts & PRINT_IP_OPT_SYM; |
1498 | int print_dso = print_opts & PRINT_IP_OPT_DSO; | 1481 | int print_dso = print_opts & PRINT_IP_OPT_DSO; |
1499 | int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; | 1482 | int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; |
1500 | int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; | 1483 | int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; |
1484 | int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; | ||
1501 | char s = print_oneline ? ' ' : '\t'; | 1485 | char s = print_oneline ? ' ' : '\t'; |
1502 | 1486 | ||
1503 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | ||
1504 | error("problem processing %d event, skipping it.\n", | ||
1505 | event->header.type); | ||
1506 | return; | ||
1507 | } | ||
1508 | |||
1509 | if (symbol_conf.use_callchain && sample->callchain) { | 1487 | if (symbol_conf.use_callchain && sample->callchain) { |
1488 | struct addr_location node_al; | ||
1510 | 1489 | ||
1511 | if (machine__resolve_callchain(machine, evsel, al.thread, | 1490 | if (machine__resolve_callchain(al->machine, evsel, al->thread, |
1512 | sample, NULL, NULL, | 1491 | sample, NULL, NULL, |
1513 | PERF_MAX_STACK_DEPTH) != 0) { | 1492 | PERF_MAX_STACK_DEPTH) != 0) { |
1514 | if (verbose) | 1493 | if (verbose) |
@@ -1517,20 +1496,31 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | |||
1517 | } | 1496 | } |
1518 | callchain_cursor_commit(&callchain_cursor); | 1497 | callchain_cursor_commit(&callchain_cursor); |
1519 | 1498 | ||
1499 | if (print_symoffset) | ||
1500 | node_al = *al; | ||
1501 | |||
1520 | while (stack_depth) { | 1502 | while (stack_depth) { |
1503 | u64 addr = 0; | ||
1504 | |||
1521 | node = callchain_cursor_current(&callchain_cursor); | 1505 | node = callchain_cursor_current(&callchain_cursor); |
1522 | if (!node) | 1506 | if (!node) |
1523 | break; | 1507 | break; |
1524 | 1508 | ||
1509 | if (node->sym && node->sym->ignore) | ||
1510 | goto next; | ||
1511 | |||
1525 | if (print_ip) | 1512 | if (print_ip) |
1526 | printf("%c%16" PRIx64, s, node->ip); | 1513 | printf("%c%16" PRIx64, s, node->ip); |
1527 | 1514 | ||
1515 | if (node->map) | ||
1516 | addr = node->map->map_ip(node->map, node->ip); | ||
1517 | |||
1528 | if (print_sym) { | 1518 | if (print_sym) { |
1529 | printf(" "); | 1519 | printf(" "); |
1530 | if (print_symoffset) { | 1520 | if (print_symoffset) { |
1531 | al.addr = node->ip; | 1521 | node_al.addr = addr; |
1532 | al.map = node->map; | 1522 | node_al.map = node->map; |
1533 | symbol__fprintf_symname_offs(node->sym, &al, stdout); | 1523 | symbol__fprintf_symname_offs(node->sym, &node_al, stdout); |
1534 | } else | 1524 | } else |
1535 | symbol__fprintf_symname(node->sym, stdout); | 1525 | symbol__fprintf_symname(node->sym, stdout); |
1536 | } | 1526 | } |
@@ -1541,32 +1531,42 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | |||
1541 | printf(")"); | 1531 | printf(")"); |
1542 | } | 1532 | } |
1543 | 1533 | ||
1534 | if (print_srcline) | ||
1535 | map__fprintf_srcline(node->map, addr, "\n ", | ||
1536 | stdout); | ||
1537 | |||
1544 | if (!print_oneline) | 1538 | if (!print_oneline) |
1545 | printf("\n"); | 1539 | printf("\n"); |
1546 | 1540 | ||
1547 | callchain_cursor_advance(&callchain_cursor); | ||
1548 | |||
1549 | stack_depth--; | 1541 | stack_depth--; |
1542 | next: | ||
1543 | callchain_cursor_advance(&callchain_cursor); | ||
1550 | } | 1544 | } |
1551 | 1545 | ||
1552 | } else { | 1546 | } else { |
1547 | if (al->sym && al->sym->ignore) | ||
1548 | return; | ||
1549 | |||
1553 | if (print_ip) | 1550 | if (print_ip) |
1554 | printf("%16" PRIx64, sample->ip); | 1551 | printf("%16" PRIx64, sample->ip); |
1555 | 1552 | ||
1556 | if (print_sym) { | 1553 | if (print_sym) { |
1557 | printf(" "); | 1554 | printf(" "); |
1558 | if (print_symoffset) | 1555 | if (print_symoffset) |
1559 | symbol__fprintf_symname_offs(al.sym, &al, | 1556 | symbol__fprintf_symname_offs(al->sym, al, |
1560 | stdout); | 1557 | stdout); |
1561 | else | 1558 | else |
1562 | symbol__fprintf_symname(al.sym, stdout); | 1559 | symbol__fprintf_symname(al->sym, stdout); |
1563 | } | 1560 | } |
1564 | 1561 | ||
1565 | if (print_dso) { | 1562 | if (print_dso) { |
1566 | printf(" ("); | 1563 | printf(" ("); |
1567 | map__fprintf_dsoname(al.map, stdout); | 1564 | map__fprintf_dsoname(al->map, stdout); |
1568 | printf(")"); | 1565 | printf(")"); |
1569 | } | 1566 | } |
1567 | |||
1568 | if (print_srcline) | ||
1569 | map__fprintf_srcline(al->map, al->addr, "\n ", stdout); | ||
1570 | } | 1570 | } |
1571 | } | 1571 | } |
1572 | 1572 | ||
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 50f640958f0f..3140f8ae6148 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef __PERF_SESSION_H | 1 | #ifndef __PERF_SESSION_H |
2 | #define __PERF_SESSION_H | 2 | #define __PERF_SESSION_H |
3 | 3 | ||
4 | #include "trace-event.h" | ||
4 | #include "hist.h" | 5 | #include "hist.h" |
5 | #include "event.h" | 6 | #include "event.h" |
6 | #include "header.h" | 7 | #include "header.h" |
@@ -32,7 +33,7 @@ struct perf_session { | |||
32 | struct perf_header header; | 33 | struct perf_header header; |
33 | struct machines machines; | 34 | struct machines machines; |
34 | struct perf_evlist *evlist; | 35 | struct perf_evlist *evlist; |
35 | struct pevent *pevent; | 36 | struct trace_event tevent; |
36 | struct events_stats stats; | 37 | struct events_stats stats; |
37 | bool repipe; | 38 | bool repipe; |
38 | struct ordered_samples ordered_samples; | 39 | struct ordered_samples ordered_samples; |
@@ -44,6 +45,7 @@ struct perf_session { | |||
44 | #define PRINT_IP_OPT_DSO (1<<2) | 45 | #define PRINT_IP_OPT_DSO (1<<2) |
45 | #define PRINT_IP_OPT_SYMOFFSET (1<<3) | 46 | #define PRINT_IP_OPT_SYMOFFSET (1<<3) |
46 | #define PRINT_IP_OPT_ONELINE (1<<4) | 47 | #define PRINT_IP_OPT_ONELINE (1<<4) |
48 | #define PRINT_IP_OPT_SRCLINE (1<<5) | ||
47 | 49 | ||
48 | struct perf_tool; | 50 | struct perf_tool; |
49 | 51 | ||
@@ -72,8 +74,6 @@ int perf_session__resolve_callchain(struct perf_session *session, | |||
72 | 74 | ||
73 | bool perf_session__has_traces(struct perf_session *session, const char *msg); | 75 | bool perf_session__has_traces(struct perf_session *session, const char *msg); |
74 | 76 | ||
75 | void mem_bswap_64(void *src, int byte_size); | ||
76 | void mem_bswap_32(void *src, int byte_size); | ||
77 | void perf_event__attr_swap(struct perf_event_attr *attr); | 77 | void perf_event__attr_swap(struct perf_event_attr *attr); |
78 | 78 | ||
79 | int perf_session__create_kernel_maps(struct perf_session *session); | 79 | int perf_session__create_kernel_maps(struct perf_session *session); |
@@ -105,8 +105,8 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); | |||
105 | struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | 105 | struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, |
106 | unsigned int type); | 106 | unsigned int type); |
107 | 107 | ||
108 | void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | 108 | void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, |
109 | struct perf_sample *sample, struct machine *machine, | 109 | struct addr_location *al, |
110 | unsigned int print_opts, unsigned int stack_depth); | 110 | unsigned int print_opts, unsigned int stack_depth); |
111 | 111 | ||
112 | int perf_session__cpu_bitmap(struct perf_session *session, | 112 | int perf_session__cpu_bitmap(struct perf_session *session, |
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index 58ea5ca6c255..d0aee4b9dfd4 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py | |||
@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' | |||
25 | build_lib = getenv('PYTHON_EXTBUILD_LIB') | 25 | build_lib = getenv('PYTHON_EXTBUILD_LIB') |
26 | build_tmp = getenv('PYTHON_EXTBUILD_TMP') | 26 | build_tmp = getenv('PYTHON_EXTBUILD_TMP') |
27 | libtraceevent = getenv('LIBTRACEEVENT') | 27 | libtraceevent = getenv('LIBTRACEEVENT') |
28 | liblk = getenv('LIBLK') | 28 | libapikfs = getenv('LIBAPIKFS') |
29 | 29 | ||
30 | ext_sources = [f.strip() for f in file('util/python-ext-sources') | 30 | ext_sources = [f.strip() for f in file('util/python-ext-sources') |
31 | if len(f.strip()) > 0 and f[0] != '#'] | 31 | if len(f.strip()) > 0 and f[0] != '#'] |
@@ -34,7 +34,7 @@ perf = Extension('perf', | |||
34 | sources = ext_sources, | 34 | sources = ext_sources, |
35 | include_dirs = ['util/include'], | 35 | include_dirs = ['util/include'], |
36 | extra_compile_args = cflags, | 36 | extra_compile_args = cflags, |
37 | extra_objects = [libtraceevent, liblk], | 37 | extra_objects = [libtraceevent, libapikfs], |
38 | ) | 38 | ) |
39 | 39 | ||
40 | setup(name='perf', | 40 | setup(name='perf', |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b0bb1f4494a..635cd8f8b22e 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -13,6 +13,7 @@ int have_ignore_callees = 0; | |||
13 | int sort__need_collapse = 0; | 13 | int sort__need_collapse = 0; |
14 | int sort__has_parent = 0; | 14 | int sort__has_parent = 0; |
15 | int sort__has_sym = 0; | 15 | int sort__has_sym = 0; |
16 | int sort__has_dso = 0; | ||
16 | enum sort_mode sort__mode = SORT_MODE__NORMAL; | 17 | enum sort_mode sort__mode = SORT_MODE__NORMAL; |
17 | 18 | ||
18 | enum sort_type sort__first_dimension; | 19 | enum sort_type sort__first_dimension; |
@@ -161,6 +162,11 @@ struct sort_entry sort_dso = { | |||
161 | 162 | ||
162 | /* --sort symbol */ | 163 | /* --sort symbol */ |
163 | 164 | ||
165 | static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip) | ||
166 | { | ||
167 | return (int64_t)(right_ip - left_ip); | ||
168 | } | ||
169 | |||
164 | static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) | 170 | static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) |
165 | { | 171 | { |
166 | u64 ip_l, ip_r; | 172 | u64 ip_l, ip_r; |
@@ -183,15 +189,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) | |||
183 | int64_t ret; | 189 | int64_t ret; |
184 | 190 | ||
185 | if (!left->ms.sym && !right->ms.sym) | 191 | if (!left->ms.sym && !right->ms.sym) |
186 | return right->level - left->level; | 192 | return _sort__addr_cmp(left->ip, right->ip); |
187 | 193 | ||
188 | /* | 194 | /* |
189 | * comparing symbol address alone is not enough since it's a | 195 | * comparing symbol address alone is not enough since it's a |
190 | * relative address within a dso. | 196 | * relative address within a dso. |
191 | */ | 197 | */ |
192 | ret = sort__dso_cmp(left, right); | 198 | if (!sort__has_dso) { |
193 | if (ret != 0) | 199 | ret = sort__dso_cmp(left, right); |
194 | return ret; | 200 | if (ret != 0) |
201 | return ret; | ||
202 | } | ||
195 | 203 | ||
196 | return _sort__sym_cmp(left->ms.sym, right->ms.sym); | 204 | return _sort__sym_cmp(left->ms.sym, right->ms.sym); |
197 | } | 205 | } |
@@ -372,7 +380,7 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right) | |||
372 | struct addr_map_symbol *from_r = &right->branch_info->from; | 380 | struct addr_map_symbol *from_r = &right->branch_info->from; |
373 | 381 | ||
374 | if (!from_l->sym && !from_r->sym) | 382 | if (!from_l->sym && !from_r->sym) |
375 | return right->level - left->level; | 383 | return _sort__addr_cmp(from_l->addr, from_r->addr); |
376 | 384 | ||
377 | return _sort__sym_cmp(from_l->sym, from_r->sym); | 385 | return _sort__sym_cmp(from_l->sym, from_r->sym); |
378 | } | 386 | } |
@@ -384,7 +392,7 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) | |||
384 | struct addr_map_symbol *to_r = &right->branch_info->to; | 392 | struct addr_map_symbol *to_r = &right->branch_info->to; |
385 | 393 | ||
386 | if (!to_l->sym && !to_r->sym) | 394 | if (!to_l->sym && !to_r->sym) |
387 | return right->level - left->level; | 395 | return _sort__addr_cmp(to_l->addr, to_r->addr); |
388 | 396 | ||
389 | return _sort__sym_cmp(to_l->sym, to_r->sym); | 397 | return _sort__sym_cmp(to_l->sym, to_r->sym); |
390 | } | 398 | } |
@@ -1056,6 +1064,8 @@ int sort_dimension__add(const char *tok) | |||
1056 | sort__has_parent = 1; | 1064 | sort__has_parent = 1; |
1057 | } else if (sd->entry == &sort_sym) { | 1065 | } else if (sd->entry == &sort_sym) { |
1058 | sort__has_sym = 1; | 1066 | sort__has_sym = 1; |
1067 | } else if (sd->entry == &sort_dso) { | ||
1068 | sort__has_dso = 1; | ||
1059 | } | 1069 | } |
1060 | 1070 | ||
1061 | __sort_dimension__add(sd, i); | 1071 | __sort_dimension__add(sd, i); |
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index d11aefbc4b8d..f3e4bc5fe5d2 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c | |||
@@ -129,7 +129,7 @@ static struct a2l_data *addr2line_init(const char *path) | |||
129 | 129 | ||
130 | out: | 130 | out: |
131 | if (a2l) { | 131 | if (a2l) { |
132 | free((void *)a2l->input); | 132 | zfree((char **)&a2l->input); |
133 | free(a2l); | 133 | free(a2l); |
134 | } | 134 | } |
135 | bfd_close(abfd); | 135 | bfd_close(abfd); |
@@ -140,24 +140,30 @@ static void addr2line_cleanup(struct a2l_data *a2l) | |||
140 | { | 140 | { |
141 | if (a2l->abfd) | 141 | if (a2l->abfd) |
142 | bfd_close(a2l->abfd); | 142 | bfd_close(a2l->abfd); |
143 | free((void *)a2l->input); | 143 | zfree((char **)&a2l->input); |
144 | free(a2l->syms); | 144 | zfree(&a2l->syms); |
145 | free(a2l); | 145 | free(a2l); |
146 | } | 146 | } |
147 | 147 | ||
148 | static int addr2line(const char *dso_name, unsigned long addr, | 148 | static int addr2line(const char *dso_name, unsigned long addr, |
149 | char **file, unsigned int *line) | 149 | char **file, unsigned int *line, struct dso *dso) |
150 | { | 150 | { |
151 | int ret = 0; | 151 | int ret = 0; |
152 | struct a2l_data *a2l; | 152 | struct a2l_data *a2l = dso->a2l; |
153 | |||
154 | if (!a2l) { | ||
155 | dso->a2l = addr2line_init(dso_name); | ||
156 | a2l = dso->a2l; | ||
157 | } | ||
153 | 158 | ||
154 | a2l = addr2line_init(dso_name); | ||
155 | if (a2l == NULL) { | 159 | if (a2l == NULL) { |
156 | pr_warning("addr2line_init failed for %s\n", dso_name); | 160 | pr_warning("addr2line_init failed for %s\n", dso_name); |
157 | return 0; | 161 | return 0; |
158 | } | 162 | } |
159 | 163 | ||
160 | a2l->addr = addr; | 164 | a2l->addr = addr; |
165 | a2l->found = false; | ||
166 | |||
161 | bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); | 167 | bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); |
162 | 168 | ||
163 | if (a2l->found && a2l->filename) { | 169 | if (a2l->found && a2l->filename) { |
@@ -168,14 +174,26 @@ static int addr2line(const char *dso_name, unsigned long addr, | |||
168 | ret = 1; | 174 | ret = 1; |
169 | } | 175 | } |
170 | 176 | ||
171 | addr2line_cleanup(a2l); | ||
172 | return ret; | 177 | return ret; |
173 | } | 178 | } |
174 | 179 | ||
180 | void dso__free_a2l(struct dso *dso) | ||
181 | { | ||
182 | struct a2l_data *a2l = dso->a2l; | ||
183 | |||
184 | if (!a2l) | ||
185 | return; | ||
186 | |||
187 | addr2line_cleanup(a2l); | ||
188 | |||
189 | dso->a2l = NULL; | ||
190 | } | ||
191 | |||
175 | #else /* HAVE_LIBBFD_SUPPORT */ | 192 | #else /* HAVE_LIBBFD_SUPPORT */ |
176 | 193 | ||
177 | static int addr2line(const char *dso_name, unsigned long addr, | 194 | static int addr2line(const char *dso_name, unsigned long addr, |
178 | char **file, unsigned int *line_nr) | 195 | char **file, unsigned int *line_nr, |
196 | struct dso *dso __maybe_unused) | ||
179 | { | 197 | { |
180 | FILE *fp; | 198 | FILE *fp; |
181 | char cmd[PATH_MAX]; | 199 | char cmd[PATH_MAX]; |
@@ -219,42 +237,58 @@ out: | |||
219 | pclose(fp); | 237 | pclose(fp); |
220 | return ret; | 238 | return ret; |
221 | } | 239 | } |
240 | |||
241 | void dso__free_a2l(struct dso *dso __maybe_unused) | ||
242 | { | ||
243 | } | ||
244 | |||
222 | #endif /* HAVE_LIBBFD_SUPPORT */ | 245 | #endif /* HAVE_LIBBFD_SUPPORT */ |
223 | 246 | ||
247 | /* | ||
248 | * Number of addr2line failures (without success) before disabling it for that | ||
249 | * dso. | ||
250 | */ | ||
251 | #define A2L_FAIL_LIMIT 123 | ||
252 | |||
224 | char *get_srcline(struct dso *dso, unsigned long addr) | 253 | char *get_srcline(struct dso *dso, unsigned long addr) |
225 | { | 254 | { |
226 | char *file = NULL; | 255 | char *file = NULL; |
227 | unsigned line = 0; | 256 | unsigned line = 0; |
228 | char *srcline; | 257 | char *srcline; |
229 | char *dso_name = dso->long_name; | 258 | const char *dso_name; |
230 | size_t size; | ||
231 | 259 | ||
232 | if (!dso->has_srcline) | 260 | if (!dso->has_srcline) |
233 | return SRCLINE_UNKNOWN; | 261 | return SRCLINE_UNKNOWN; |
234 | 262 | ||
263 | if (dso->symsrc_filename) | ||
264 | dso_name = dso->symsrc_filename; | ||
265 | else | ||
266 | dso_name = dso->long_name; | ||
267 | |||
235 | if (dso_name[0] == '[') | 268 | if (dso_name[0] == '[') |
236 | goto out; | 269 | goto out; |
237 | 270 | ||
238 | if (!strncmp(dso_name, "/tmp/perf-", 10)) | 271 | if (!strncmp(dso_name, "/tmp/perf-", 10)) |
239 | goto out; | 272 | goto out; |
240 | 273 | ||
241 | if (!addr2line(dso_name, addr, &file, &line)) | 274 | if (!addr2line(dso_name, addr, &file, &line, dso)) |
242 | goto out; | 275 | goto out; |
243 | 276 | ||
244 | /* just calculate actual length */ | 277 | if (asprintf(&srcline, "%s:%u", file, line) < 0) { |
245 | size = snprintf(NULL, 0, "%s:%u", file, line) + 1; | 278 | free(file); |
279 | goto out; | ||
280 | } | ||
246 | 281 | ||
247 | srcline = malloc(size); | 282 | dso->a2l_fails = 0; |
248 | if (srcline) | ||
249 | snprintf(srcline, size, "%s:%u", file, line); | ||
250 | else | ||
251 | srcline = SRCLINE_UNKNOWN; | ||
252 | 283 | ||
253 | free(file); | 284 | free(file); |
254 | return srcline; | 285 | return srcline; |
255 | 286 | ||
256 | out: | 287 | out: |
257 | dso->has_srcline = 0; | 288 | if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) { |
289 | dso->has_srcline = 0; | ||
290 | dso__free_a2l(dso); | ||
291 | } | ||
258 | return SRCLINE_UNKNOWN; | 292 | return SRCLINE_UNKNOWN; |
259 | } | 293 | } |
260 | 294 | ||
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index cfa906882e2c..4abe23550c73 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c | |||
@@ -28,7 +28,7 @@ void strbuf_init(struct strbuf *sb, ssize_t hint) | |||
28 | void strbuf_release(struct strbuf *sb) | 28 | void strbuf_release(struct strbuf *sb) |
29 | { | 29 | { |
30 | if (sb->alloc) { | 30 | if (sb->alloc) { |
31 | free(sb->buf); | 31 | zfree(&sb->buf); |
32 | strbuf_init(sb, 0); | 32 | strbuf_init(sb, 0); |
33 | } | 33 | } |
34 | } | 34 | } |
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c index 3edd0538161f..79a757a2a15c 100644 --- a/tools/perf/util/strfilter.c +++ b/tools/perf/util/strfilter.c | |||
@@ -14,7 +14,7 @@ static void strfilter_node__delete(struct strfilter_node *node) | |||
14 | { | 14 | { |
15 | if (node) { | 15 | if (node) { |
16 | if (node->p && !is_operator(*node->p)) | 16 | if (node->p && !is_operator(*node->p)) |
17 | free((char *)node->p); | 17 | zfree((char **)&node->p); |
18 | strfilter_node__delete(node->l); | 18 | strfilter_node__delete(node->l); |
19 | strfilter_node__delete(node->r); | 19 | strfilter_node__delete(node->r); |
20 | free(node); | 20 | free(node); |
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index f0b0c008c507..2553e5b55b89 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c | |||
@@ -128,7 +128,7 @@ void argv_free(char **argv) | |||
128 | { | 128 | { |
129 | char **p; | 129 | char **p; |
130 | for (p = argv; *p; p++) | 130 | for (p = argv; *p; p++) |
131 | free(*p); | 131 | zfree(p); |
132 | 132 | ||
133 | free(argv); | 133 | free(argv); |
134 | } | 134 | } |
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c index eabdce0a2daa..71f9d102b96f 100644 --- a/tools/perf/util/strlist.c +++ b/tools/perf/util/strlist.c | |||
@@ -5,6 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "strlist.h" | 7 | #include "strlist.h" |
8 | #include "util.h" | ||
8 | #include <errno.h> | 9 | #include <errno.h> |
9 | #include <stdio.h> | 10 | #include <stdio.h> |
10 | #include <stdlib.h> | 11 | #include <stdlib.h> |
@@ -38,7 +39,7 @@ out_delete: | |||
38 | static void str_node__delete(struct str_node *snode, bool dupstr) | 39 | static void str_node__delete(struct str_node *snode, bool dupstr) |
39 | { | 40 | { |
40 | if (dupstr) | 41 | if (dupstr) |
41 | free((void *)snode->s); | 42 | zfree((char **)&snode->s); |
42 | free(snode); | 43 | free(snode); |
43 | } | 44 | } |
44 | 45 | ||
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 96c866045d60..43262b83c541 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c | |||
@@ -17,8 +17,12 @@ | |||
17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
18 | #include <unistd.h> | 18 | #include <unistd.h> |
19 | #include <string.h> | 19 | #include <string.h> |
20 | #include <linux/bitops.h> | ||
20 | 21 | ||
22 | #include "perf.h" | ||
21 | #include "svghelper.h" | 23 | #include "svghelper.h" |
24 | #include "util.h" | ||
25 | #include "cpumap.h" | ||
22 | 26 | ||
23 | static u64 first_time, last_time; | 27 | static u64 first_time, last_time; |
24 | static u64 turbo_frequency, max_freq; | 28 | static u64 turbo_frequency, max_freq; |
@@ -28,6 +32,8 @@ static u64 turbo_frequency, max_freq; | |||
28 | #define SLOT_HEIGHT 25.0 | 32 | #define SLOT_HEIGHT 25.0 |
29 | 33 | ||
30 | int svg_page_width = 1000; | 34 | int svg_page_width = 1000; |
35 | u64 svg_highlight; | ||
36 | const char *svg_highlight_name; | ||
31 | 37 | ||
32 | #define MIN_TEXT_SIZE 0.01 | 38 | #define MIN_TEXT_SIZE 0.01 |
33 | 39 | ||
@@ -39,9 +45,14 @@ static double cpu2slot(int cpu) | |||
39 | return 2 * cpu + 1; | 45 | return 2 * cpu + 1; |
40 | } | 46 | } |
41 | 47 | ||
48 | static int *topology_map; | ||
49 | |||
42 | static double cpu2y(int cpu) | 50 | static double cpu2y(int cpu) |
43 | { | 51 | { |
44 | return cpu2slot(cpu) * SLOT_MULT; | 52 | if (topology_map) |
53 | return cpu2slot(topology_map[cpu]) * SLOT_MULT; | ||
54 | else | ||
55 | return cpu2slot(cpu) * SLOT_MULT; | ||
45 | } | 56 | } |
46 | 57 | ||
47 | static double time2pixels(u64 __time) | 58 | static double time2pixels(u64 __time) |
@@ -95,6 +106,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end) | |||
95 | 106 | ||
96 | total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; | 107 | total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; |
97 | fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); | 108 | fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); |
109 | fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); | ||
98 | fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); | 110 | fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); |
99 | 111 | ||
100 | fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); | 112 | fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); |
@@ -103,6 +115,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end) | |||
103 | fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); | 115 | fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); |
104 | fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 116 | fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
105 | fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 117 | fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
118 | fprintf(svgfile, " rect.sample_hi{ fill:rgb(255,128, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | ||
106 | fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 119 | fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
107 | fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 120 | fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
108 | fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 121 | fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
@@ -128,14 +141,42 @@ void svg_box(int Yslot, u64 start, u64 end, const char *type) | |||
128 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); | 141 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); |
129 | } | 142 | } |
130 | 143 | ||
131 | void svg_sample(int Yslot, int cpu, u64 start, u64 end) | 144 | static char *time_to_string(u64 duration); |
145 | void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) | ||
146 | { | ||
147 | if (!svgfile) | ||
148 | return; | ||
149 | |||
150 | fprintf(svgfile, "<g>\n"); | ||
151 | fprintf(svgfile, "<title>#%d blocked %s</title>\n", cpu, | ||
152 | time_to_string(end - start)); | ||
153 | if (backtrace) | ||
154 | fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace); | ||
155 | svg_box(Yslot, start, end, "blocked"); | ||
156 | fprintf(svgfile, "</g>\n"); | ||
157 | } | ||
158 | |||
159 | void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) | ||
132 | { | 160 | { |
133 | double text_size; | 161 | double text_size; |
162 | const char *type; | ||
163 | |||
134 | if (!svgfile) | 164 | if (!svgfile) |
135 | return; | 165 | return; |
136 | 166 | ||
137 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n", | 167 | if (svg_highlight && end - start > svg_highlight) |
138 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT); | 168 | type = "sample_hi"; |
169 | else | ||
170 | type = "sample"; | ||
171 | fprintf(svgfile, "<g>\n"); | ||
172 | |||
173 | fprintf(svgfile, "<title>#%d running %s</title>\n", | ||
174 | cpu, time_to_string(end - start)); | ||
175 | if (backtrace) | ||
176 | fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); | ||
177 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n", | ||
178 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, | ||
179 | type); | ||
139 | 180 | ||
140 | text_size = (time2pixels(end)-time2pixels(start)); | 181 | text_size = (time2pixels(end)-time2pixels(start)); |
141 | if (cpu > 9) | 182 | if (cpu > 9) |
@@ -148,6 +189,7 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end) | |||
148 | fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n", | 189 | fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n", |
149 | time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); | 190 | time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); |
150 | 191 | ||
192 | fprintf(svgfile, "</g>\n"); | ||
151 | } | 193 | } |
152 | 194 | ||
153 | static char *time_to_string(u64 duration) | 195 | static char *time_to_string(u64 duration) |
@@ -168,7 +210,7 @@ static char *time_to_string(u64 duration) | |||
168 | return text; | 210 | return text; |
169 | } | 211 | } |
170 | 212 | ||
171 | void svg_waiting(int Yslot, u64 start, u64 end) | 213 | void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) |
172 | { | 214 | { |
173 | char *text; | 215 | char *text; |
174 | const char *style; | 216 | const char *style; |
@@ -192,6 +234,9 @@ void svg_waiting(int Yslot, u64 start, u64 end) | |||
192 | font_size = round_text_size(font_size); | 234 | font_size = round_text_size(font_size); |
193 | 235 | ||
194 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT); | 236 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT); |
237 | fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start)); | ||
238 | if (backtrace) | ||
239 | fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace); | ||
195 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", | 240 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", |
196 | time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style); | 241 | time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style); |
197 | if (font_size > MIN_TEXT_SIZE) | 242 | if (font_size > MIN_TEXT_SIZE) |
@@ -242,28 +287,42 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq) | |||
242 | max_freq = __max_freq; | 287 | max_freq = __max_freq; |
243 | turbo_frequency = __turbo_freq; | 288 | turbo_frequency = __turbo_freq; |
244 | 289 | ||
290 | fprintf(svgfile, "<g>\n"); | ||
291 | |||
245 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n", | 292 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n", |
246 | time2pixels(first_time), | 293 | time2pixels(first_time), |
247 | time2pixels(last_time)-time2pixels(first_time), | 294 | time2pixels(last_time)-time2pixels(first_time), |
248 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); | 295 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); |
249 | 296 | ||
250 | sprintf(cpu_string, "CPU %i", (int)cpu+1); | 297 | sprintf(cpu_string, "CPU %i", (int)cpu); |
251 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", | 298 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", |
252 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); | 299 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); |
253 | 300 | ||
254 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n", | 301 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n", |
255 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model()); | 302 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model()); |
303 | |||
304 | fprintf(svgfile, "</g>\n"); | ||
256 | } | 305 | } |
257 | 306 | ||
258 | void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name) | 307 | void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace) |
259 | { | 308 | { |
260 | double width; | 309 | double width; |
310 | const char *type; | ||
261 | 311 | ||
262 | if (!svgfile) | 312 | if (!svgfile) |
263 | return; | 313 | return; |
264 | 314 | ||
315 | if (svg_highlight && end - start >= svg_highlight) | ||
316 | type = "sample_hi"; | ||
317 | else if (svg_highlight_name && strstr(name, svg_highlight_name)) | ||
318 | type = "sample_hi"; | ||
319 | else | ||
320 | type = "sample"; | ||
265 | 321 | ||
266 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); | 322 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); |
323 | fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start)); | ||
324 | if (backtrace) | ||
325 | fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); | ||
267 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", | 326 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", |
268 | time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); | 327 | time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); |
269 | width = time2pixels(end)-time2pixels(start); | 328 | width = time2pixels(end)-time2pixels(start); |
@@ -288,6 +347,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type) | |||
288 | return; | 347 | return; |
289 | 348 | ||
290 | 349 | ||
350 | fprintf(svgfile, "<g>\n"); | ||
351 | |||
291 | if (type > 6) | 352 | if (type > 6) |
292 | type = 6; | 353 | type = 6; |
293 | sprintf(style, "c%i", type); | 354 | sprintf(style, "c%i", type); |
@@ -306,6 +367,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type) | |||
306 | if (width > MIN_TEXT_SIZE) | 367 | if (width > MIN_TEXT_SIZE) |
307 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n", | 368 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n", |
308 | time2pixels(start), cpu2y(cpu)+width, width, type); | 369 | time2pixels(start), cpu2y(cpu)+width, width, type); |
370 | |||
371 | fprintf(svgfile, "</g>\n"); | ||
309 | } | 372 | } |
310 | 373 | ||
311 | static char *HzToHuman(unsigned long hz) | 374 | static char *HzToHuman(unsigned long hz) |
@@ -339,6 +402,8 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq) | |||
339 | if (!svgfile) | 402 | if (!svgfile) |
340 | return; | 403 | return; |
341 | 404 | ||
405 | fprintf(svgfile, "<g>\n"); | ||
406 | |||
342 | if (max_freq) | 407 | if (max_freq) |
343 | height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT); | 408 | height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT); |
344 | height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; | 409 | height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; |
@@ -347,10 +412,11 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq) | |||
347 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n", | 412 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n", |
348 | time2pixels(start), height+0.9, HzToHuman(freq)); | 413 | time2pixels(start), height+0.9, HzToHuman(freq)); |
349 | 414 | ||
415 | fprintf(svgfile, "</g>\n"); | ||
350 | } | 416 | } |
351 | 417 | ||
352 | 418 | ||
353 | void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2) | 419 | void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace) |
354 | { | 420 | { |
355 | double height; | 421 | double height; |
356 | 422 | ||
@@ -358,6 +424,15 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc | |||
358 | return; | 424 | return; |
359 | 425 | ||
360 | 426 | ||
427 | fprintf(svgfile, "<g>\n"); | ||
428 | |||
429 | fprintf(svgfile, "<title>%s wakes up %s</title>\n", | ||
430 | desc1 ? desc1 : "?", | ||
431 | desc2 ? desc2 : "?"); | ||
432 | |||
433 | if (backtrace) | ||
434 | fprintf(svgfile, "<desc>%s</desc>\n", backtrace); | ||
435 | |||
361 | if (row1 < row2) { | 436 | if (row1 < row2) { |
362 | if (row1) { | 437 | if (row1) { |
363 | fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", | 438 | fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", |
@@ -395,9 +470,11 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc | |||
395 | if (row1) | 470 | if (row1) |
396 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", | 471 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", |
397 | time2pixels(start), height); | 472 | time2pixels(start), height); |
473 | |||
474 | fprintf(svgfile, "</g>\n"); | ||
398 | } | 475 | } |
399 | 476 | ||
400 | void svg_wakeline(u64 start, int row1, int row2) | 477 | void svg_wakeline(u64 start, int row1, int row2, const char *backtrace) |
401 | { | 478 | { |
402 | double height; | 479 | double height; |
403 | 480 | ||
@@ -405,6 +482,11 @@ void svg_wakeline(u64 start, int row1, int row2) | |||
405 | return; | 482 | return; |
406 | 483 | ||
407 | 484 | ||
485 | fprintf(svgfile, "<g>\n"); | ||
486 | |||
487 | if (backtrace) | ||
488 | fprintf(svgfile, "<desc>%s</desc>\n", backtrace); | ||
489 | |||
408 | if (row1 < row2) | 490 | if (row1 < row2) |
409 | fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", | 491 | fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", |
410 | time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT); | 492 | time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT); |
@@ -417,17 +499,28 @@ void svg_wakeline(u64 start, int row1, int row2) | |||
417 | height += SLOT_HEIGHT; | 499 | height += SLOT_HEIGHT; |
418 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", | 500 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", |
419 | time2pixels(start), height); | 501 | time2pixels(start), height); |
502 | |||
503 | fprintf(svgfile, "</g>\n"); | ||
420 | } | 504 | } |
421 | 505 | ||
422 | void svg_interrupt(u64 start, int row) | 506 | void svg_interrupt(u64 start, int row, const char *backtrace) |
423 | { | 507 | { |
424 | if (!svgfile) | 508 | if (!svgfile) |
425 | return; | 509 | return; |
426 | 510 | ||
511 | fprintf(svgfile, "<g>\n"); | ||
512 | |||
513 | fprintf(svgfile, "<title>Wakeup from interrupt</title>\n"); | ||
514 | |||
515 | if (backtrace) | ||
516 | fprintf(svgfile, "<desc>%s</desc>\n", backtrace); | ||
517 | |||
427 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", | 518 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", |
428 | time2pixels(start), row * SLOT_MULT); | 519 | time2pixels(start), row * SLOT_MULT); |
429 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", | 520 | fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", |
430 | time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT); | 521 | time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT); |
522 | |||
523 | fprintf(svgfile, "</g>\n"); | ||
431 | } | 524 | } |
432 | 525 | ||
433 | void svg_text(int Yslot, u64 start, const char *text) | 526 | void svg_text(int Yslot, u64 start, const char *text) |
@@ -455,6 +548,7 @@ void svg_legenda(void) | |||
455 | if (!svgfile) | 548 | if (!svgfile) |
456 | return; | 549 | return; |
457 | 550 | ||
551 | fprintf(svgfile, "<g>\n"); | ||
458 | svg_legenda_box(0, "Running", "sample"); | 552 | svg_legenda_box(0, "Running", "sample"); |
459 | svg_legenda_box(100, "Idle","c1"); | 553 | svg_legenda_box(100, "Idle","c1"); |
460 | svg_legenda_box(200, "Deeper Idle", "c3"); | 554 | svg_legenda_box(200, "Deeper Idle", "c3"); |
@@ -462,6 +556,7 @@ void svg_legenda(void) | |||
462 | svg_legenda_box(550, "Sleeping", "process2"); | 556 | svg_legenda_box(550, "Sleeping", "process2"); |
463 | svg_legenda_box(650, "Waiting for cpu", "waiting"); | 557 | svg_legenda_box(650, "Waiting for cpu", "waiting"); |
464 | svg_legenda_box(800, "Blocked on IO", "blocked"); | 558 | svg_legenda_box(800, "Blocked on IO", "blocked"); |
559 | fprintf(svgfile, "</g>\n"); | ||
465 | } | 560 | } |
466 | 561 | ||
467 | void svg_time_grid(void) | 562 | void svg_time_grid(void) |
@@ -499,3 +594,123 @@ void svg_close(void) | |||
499 | svgfile = NULL; | 594 | svgfile = NULL; |
500 | } | 595 | } |
501 | } | 596 | } |
597 | |||
598 | #define cpumask_bits(maskp) ((maskp)->bits) | ||
599 | typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t; | ||
600 | |||
601 | struct topology { | ||
602 | cpumask_t *sib_core; | ||
603 | int sib_core_nr; | ||
604 | cpumask_t *sib_thr; | ||
605 | int sib_thr_nr; | ||
606 | }; | ||
607 | |||
608 | static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos) | ||
609 | { | ||
610 | int i; | ||
611 | int thr; | ||
612 | |||
613 | for (i = 0; i < t->sib_thr_nr; i++) { | ||
614 | if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i]))) | ||
615 | continue; | ||
616 | |||
617 | for_each_set_bit(thr, | ||
618 | cpumask_bits(&t->sib_thr[i]), | ||
619 | MAX_NR_CPUS) | ||
620 | if (map[thr] == -1) | ||
621 | map[thr] = (*pos)++; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | static void scan_core_topology(int *map, struct topology *t) | ||
626 | { | ||
627 | int pos = 0; | ||
628 | int i; | ||
629 | int cpu; | ||
630 | |||
631 | for (i = 0; i < t->sib_core_nr; i++) | ||
632 | for_each_set_bit(cpu, | ||
633 | cpumask_bits(&t->sib_core[i]), | ||
634 | MAX_NR_CPUS) | ||
635 | scan_thread_topology(map, t, cpu, &pos); | ||
636 | } | ||
637 | |||
638 | static int str_to_bitmap(char *s, cpumask_t *b) | ||
639 | { | ||
640 | int i; | ||
641 | int ret = 0; | ||
642 | struct cpu_map *m; | ||
643 | int c; | ||
644 | |||
645 | m = cpu_map__new(s); | ||
646 | if (!m) | ||
647 | return -1; | ||
648 | |||
649 | for (i = 0; i < m->nr; i++) { | ||
650 | c = m->map[i]; | ||
651 | if (c >= MAX_NR_CPUS) { | ||
652 | ret = -1; | ||
653 | break; | ||
654 | } | ||
655 | |||
656 | set_bit(c, cpumask_bits(b)); | ||
657 | } | ||
658 | |||
659 | cpu_map__delete(m); | ||
660 | |||
661 | return ret; | ||
662 | } | ||
663 | |||
664 | int svg_build_topology_map(char *sib_core, int sib_core_nr, | ||
665 | char *sib_thr, int sib_thr_nr) | ||
666 | { | ||
667 | int i; | ||
668 | struct topology t; | ||
669 | |||
670 | t.sib_core_nr = sib_core_nr; | ||
671 | t.sib_thr_nr = sib_thr_nr; | ||
672 | t.sib_core = calloc(sib_core_nr, sizeof(cpumask_t)); | ||
673 | t.sib_thr = calloc(sib_thr_nr, sizeof(cpumask_t)); | ||
674 | |||
675 | if (!t.sib_core || !t.sib_thr) { | ||
676 | fprintf(stderr, "topology: no memory\n"); | ||
677 | goto exit; | ||
678 | } | ||
679 | |||
680 | for (i = 0; i < sib_core_nr; i++) { | ||
681 | if (str_to_bitmap(sib_core, &t.sib_core[i])) { | ||
682 | fprintf(stderr, "topology: can't parse siblings map\n"); | ||
683 | goto exit; | ||
684 | } | ||
685 | |||
686 | sib_core += strlen(sib_core) + 1; | ||
687 | } | ||
688 | |||
689 | for (i = 0; i < sib_thr_nr; i++) { | ||
690 | if (str_to_bitmap(sib_thr, &t.sib_thr[i])) { | ||
691 | fprintf(stderr, "topology: can't parse siblings map\n"); | ||
692 | goto exit; | ||
693 | } | ||
694 | |||
695 | sib_thr += strlen(sib_thr) + 1; | ||
696 | } | ||
697 | |||
698 | topology_map = malloc(sizeof(int) * MAX_NR_CPUS); | ||
699 | if (!topology_map) { | ||
700 | fprintf(stderr, "topology: no memory\n"); | ||
701 | goto exit; | ||
702 | } | ||
703 | |||
704 | for (i = 0; i < MAX_NR_CPUS; i++) | ||
705 | topology_map[i] = -1; | ||
706 | |||
707 | scan_core_topology(topology_map, &t); | ||
708 | |||
709 | return 0; | ||
710 | |||
711 | exit: | ||
712 | zfree(&t.sib_core); | ||
713 | zfree(&t.sib_thr); | ||
714 | |||
715 | return -1; | ||
716 | } | ||
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h index e0781989cc31..f7b4d6e699ea 100644 --- a/tools/perf/util/svghelper.h +++ b/tools/perf/util/svghelper.h | |||
@@ -5,24 +5,29 @@ | |||
5 | 5 | ||
6 | extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); | 6 | extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); |
7 | extern void svg_box(int Yslot, u64 start, u64 end, const char *type); | 7 | extern void svg_box(int Yslot, u64 start, u64 end, const char *type); |
8 | extern void svg_sample(int Yslot, int cpu, u64 start, u64 end); | 8 | extern void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); |
9 | extern void svg_waiting(int Yslot, u64 start, u64 end); | 9 | extern void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); |
10 | extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); | ||
10 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); | 11 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); |
11 | 12 | ||
12 | 13 | ||
13 | extern void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name); | 14 | extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace); |
14 | extern void svg_cstate(int cpu, u64 start, u64 end, int type); | 15 | extern void svg_cstate(int cpu, u64 start, u64 end, int type); |
15 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); | 16 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); |
16 | 17 | ||
17 | 18 | ||
18 | extern void svg_time_grid(void); | 19 | extern void svg_time_grid(void); |
19 | extern void svg_legenda(void); | 20 | extern void svg_legenda(void); |
20 | extern void svg_wakeline(u64 start, int row1, int row2); | 21 | extern void svg_wakeline(u64 start, int row1, int row2, const char *backtrace); |
21 | extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2); | 22 | extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace); |
22 | extern void svg_interrupt(u64 start, int row); | 23 | extern void svg_interrupt(u64 start, int row, const char *backtrace); |
23 | extern void svg_text(int Yslot, u64 start, const char *text); | 24 | extern void svg_text(int Yslot, u64 start, const char *text); |
24 | extern void svg_close(void); | 25 | extern void svg_close(void); |
26 | extern int svg_build_topology_map(char *sib_core, int sib_core_nr, | ||
27 | char *sib_thr, int sib_thr_nr); | ||
25 | 28 | ||
26 | extern int svg_page_width; | 29 | extern int svg_page_width; |
30 | extern u64 svg_highlight; | ||
31 | extern const char *svg_highlight_name; | ||
27 | 32 | ||
28 | #endif /* __PERF_SVGHELPER_H */ | 33 | #endif /* __PERF_SVGHELPER_H */ |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index eed0b96302af..759456728703 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <inttypes.h> | 6 | #include <inttypes.h> |
7 | 7 | ||
8 | #include "symbol.h" | 8 | #include "symbol.h" |
9 | #include <symbol/kallsyms.h> | ||
9 | #include "debug.h" | 10 | #include "debug.h" |
10 | 11 | ||
11 | #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT | 12 | #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT |
@@ -135,9 +136,8 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) | |||
135 | return -1; | 136 | return -1; |
136 | } | 137 | } |
137 | 138 | ||
138 | static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | 139 | Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, |
139 | GElf_Shdr *shp, const char *name, | 140 | GElf_Shdr *shp, const char *name, size_t *idx) |
140 | size_t *idx) | ||
141 | { | 141 | { |
142 | Elf_Scn *sec = NULL; | 142 | Elf_Scn *sec = NULL; |
143 | size_t cnt = 1; | 143 | size_t cnt = 1; |
@@ -553,7 +553,7 @@ bool symsrc__has_symtab(struct symsrc *ss) | |||
553 | 553 | ||
554 | void symsrc__destroy(struct symsrc *ss) | 554 | void symsrc__destroy(struct symsrc *ss) |
555 | { | 555 | { |
556 | free(ss->name); | 556 | zfree(&ss->name); |
557 | elf_end(ss->elf); | 557 | elf_end(ss->elf); |
558 | close(ss->fd); | 558 | close(ss->fd); |
559 | } | 559 | } |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 2d2dd0532b5a..bd15f490d04f 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include "symbol.h" | 1 | #include "symbol.h" |
2 | #include "util.h" | ||
2 | 3 | ||
3 | #include <stdio.h> | 4 | #include <stdio.h> |
4 | #include <fcntl.h> | 5 | #include <fcntl.h> |
@@ -253,6 +254,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused, | |||
253 | if (!ss->name) | 254 | if (!ss->name) |
254 | goto out_close; | 255 | goto out_close; |
255 | 256 | ||
257 | ss->fd = fd; | ||
256 | ss->type = type; | 258 | ss->type = type; |
257 | 259 | ||
258 | return 0; | 260 | return 0; |
@@ -274,7 +276,7 @@ bool symsrc__has_symtab(struct symsrc *ss __maybe_unused) | |||
274 | 276 | ||
275 | void symsrc__destroy(struct symsrc *ss) | 277 | void symsrc__destroy(struct symsrc *ss) |
276 | { | 278 | { |
277 | free(ss->name); | 279 | zfree(&ss->name); |
278 | close(ss->fd); | 280 | close(ss->fd); |
279 | } | 281 | } |
280 | 282 | ||
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index c0c36965fff0..39ce9adbaaf0 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -18,12 +18,9 @@ | |||
18 | 18 | ||
19 | #include <elf.h> | 19 | #include <elf.h> |
20 | #include <limits.h> | 20 | #include <limits.h> |
21 | #include <symbol/kallsyms.h> | ||
21 | #include <sys/utsname.h> | 22 | #include <sys/utsname.h> |
22 | 23 | ||
23 | #ifndef KSYM_NAME_LEN | ||
24 | #define KSYM_NAME_LEN 256 | ||
25 | #endif | ||
26 | |||
27 | static int dso__load_kernel_sym(struct dso *dso, struct map *map, | 24 | static int dso__load_kernel_sym(struct dso *dso, struct map *map, |
28 | symbol_filter_t filter); | 25 | symbol_filter_t filter); |
29 | static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | 26 | static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, |
@@ -446,62 +443,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso, | |||
446 | return ret; | 443 | return ret; |
447 | } | 444 | } |
448 | 445 | ||
449 | int kallsyms__parse(const char *filename, void *arg, | ||
450 | int (*process_symbol)(void *arg, const char *name, | ||
451 | char type, u64 start)) | ||
452 | { | ||
453 | char *line = NULL; | ||
454 | size_t n; | ||
455 | int err = -1; | ||
456 | FILE *file = fopen(filename, "r"); | ||
457 | |||
458 | if (file == NULL) | ||
459 | goto out_failure; | ||
460 | |||
461 | err = 0; | ||
462 | |||
463 | while (!feof(file)) { | ||
464 | u64 start; | ||
465 | int line_len, len; | ||
466 | char symbol_type; | ||
467 | char *symbol_name; | ||
468 | |||
469 | line_len = getline(&line, &n, file); | ||
470 | if (line_len < 0 || !line) | ||
471 | break; | ||
472 | |||
473 | line[--line_len] = '\0'; /* \n */ | ||
474 | |||
475 | len = hex2u64(line, &start); | ||
476 | |||
477 | len++; | ||
478 | if (len + 2 >= line_len) | ||
479 | continue; | ||
480 | |||
481 | symbol_type = line[len]; | ||
482 | len += 2; | ||
483 | symbol_name = line + len; | ||
484 | len = line_len - len; | ||
485 | |||
486 | if (len >= KSYM_NAME_LEN) { | ||
487 | err = -1; | ||
488 | break; | ||
489 | } | ||
490 | |||
491 | err = process_symbol(arg, symbol_name, | ||
492 | symbol_type, start); | ||
493 | if (err) | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | free(line); | ||
498 | fclose(file); | ||
499 | return err; | ||
500 | |||
501 | out_failure: | ||
502 | return -1; | ||
503 | } | ||
504 | |||
505 | int modules__parse(const char *filename, void *arg, | 446 | int modules__parse(const char *filename, void *arg, |
506 | int (*process_module)(void *arg, const char *name, | 447 | int (*process_module)(void *arg, const char *name, |
507 | u64 start)) | 448 | u64 start)) |
@@ -565,12 +506,34 @@ struct process_kallsyms_args { | |||
565 | struct dso *dso; | 506 | struct dso *dso; |
566 | }; | 507 | }; |
567 | 508 | ||
568 | static u8 kallsyms2elf_type(char type) | 509 | bool symbol__is_idle(struct symbol *sym) |
569 | { | 510 | { |
570 | if (type == 'W') | 511 | const char * const idle_symbols[] = { |
571 | return STB_WEAK; | 512 | "cpu_idle", |
513 | "intel_idle", | ||
514 | "default_idle", | ||
515 | "native_safe_halt", | ||
516 | "enter_idle", | ||
517 | "exit_idle", | ||
518 | "mwait_idle", | ||
519 | "mwait_idle_with_hints", | ||
520 | "poll_idle", | ||
521 | "ppc64_runlatch_off", | ||
522 | "pseries_dedicated_idle_sleep", | ||
523 | NULL | ||
524 | }; | ||
525 | |||
526 | int i; | ||
527 | |||
528 | if (!sym) | ||
529 | return false; | ||
530 | |||
531 | for (i = 0; idle_symbols[i]; i++) { | ||
532 | if (!strcmp(idle_symbols[i], sym->name)) | ||
533 | return true; | ||
534 | } | ||
572 | 535 | ||
573 | return isupper(type) ? STB_GLOBAL : STB_LOCAL; | 536 | return false; |
574 | } | 537 | } |
575 | 538 | ||
576 | static int map__process_kallsym_symbol(void *arg, const char *name, | 539 | static int map__process_kallsym_symbol(void *arg, const char *name, |
@@ -833,7 +796,7 @@ static void delete_modules(struct rb_root *modules) | |||
833 | mi = rb_entry(next, struct module_info, rb_node); | 796 | mi = rb_entry(next, struct module_info, rb_node); |
834 | next = rb_next(&mi->rb_node); | 797 | next = rb_next(&mi->rb_node); |
835 | rb_erase(&mi->rb_node, modules); | 798 | rb_erase(&mi->rb_node, modules); |
836 | free(mi->name); | 799 | zfree(&mi->name); |
837 | free(mi); | 800 | free(mi); |
838 | } | 801 | } |
839 | } | 802 | } |
@@ -1126,10 +1089,10 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
1126 | * dso__data_read_addr(). | 1089 | * dso__data_read_addr(). |
1127 | */ | 1090 | */ |
1128 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) | 1091 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
1129 | dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE; | 1092 | dso->binary_type = DSO_BINARY_TYPE__GUEST_KCORE; |
1130 | else | 1093 | else |
1131 | dso->data_type = DSO_BINARY_TYPE__KCORE; | 1094 | dso->binary_type = DSO_BINARY_TYPE__KCORE; |
1132 | dso__set_long_name(dso, strdup(kcore_filename)); | 1095 | dso__set_long_name(dso, strdup(kcore_filename), true); |
1133 | 1096 | ||
1134 | close(fd); | 1097 | close(fd); |
1135 | 1098 | ||
@@ -1295,8 +1258,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1295 | 1258 | ||
1296 | enum dso_binary_type symtab_type = binary_type_symtab[i]; | 1259 | enum dso_binary_type symtab_type = binary_type_symtab[i]; |
1297 | 1260 | ||
1298 | if (dso__binary_type_file(dso, symtab_type, | 1261 | if (dso__read_binary_type_filename(dso, symtab_type, |
1299 | root_dir, name, PATH_MAX)) | 1262 | root_dir, name, PATH_MAX)) |
1300 | continue; | 1263 | continue; |
1301 | 1264 | ||
1302 | /* Name is now the name of the next image to try */ | 1265 | /* Name is now the name of the next image to try */ |
@@ -1306,6 +1269,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1306 | if (!syms_ss && symsrc__has_symtab(ss)) { | 1269 | if (!syms_ss && symsrc__has_symtab(ss)) { |
1307 | syms_ss = ss; | 1270 | syms_ss = ss; |
1308 | next_slot = true; | 1271 | next_slot = true; |
1272 | if (!dso->symsrc_filename) | ||
1273 | dso->symsrc_filename = strdup(name); | ||
1309 | } | 1274 | } |
1310 | 1275 | ||
1311 | if (!runtime_ss && symsrc__possibly_runtime(ss)) { | 1276 | if (!runtime_ss && symsrc__possibly_runtime(ss)) { |
@@ -1376,7 +1341,8 @@ struct map *map_groups__find_by_name(struct map_groups *mg, | |||
1376 | } | 1341 | } |
1377 | 1342 | ||
1378 | int dso__load_vmlinux(struct dso *dso, struct map *map, | 1343 | int dso__load_vmlinux(struct dso *dso, struct map *map, |
1379 | const char *vmlinux, symbol_filter_t filter) | 1344 | const char *vmlinux, bool vmlinux_allocated, |
1345 | symbol_filter_t filter) | ||
1380 | { | 1346 | { |
1381 | int err = -1; | 1347 | int err = -1; |
1382 | struct symsrc ss; | 1348 | struct symsrc ss; |
@@ -1402,10 +1368,10 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, | |||
1402 | 1368 | ||
1403 | if (err > 0) { | 1369 | if (err > 0) { |
1404 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) | 1370 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
1405 | dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX; | 1371 | dso->binary_type = DSO_BINARY_TYPE__GUEST_VMLINUX; |
1406 | else | 1372 | else |
1407 | dso->data_type = DSO_BINARY_TYPE__VMLINUX; | 1373 | dso->binary_type = DSO_BINARY_TYPE__VMLINUX; |
1408 | dso__set_long_name(dso, (char *)vmlinux); | 1374 | dso__set_long_name(dso, vmlinux, vmlinux_allocated); |
1409 | dso__set_loaded(dso, map->type); | 1375 | dso__set_loaded(dso, map->type); |
1410 | pr_debug("Using %s for symbols\n", symfs_vmlinux); | 1376 | pr_debug("Using %s for symbols\n", symfs_vmlinux); |
1411 | } | 1377 | } |
@@ -1424,21 +1390,16 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
1424 | 1390 | ||
1425 | filename = dso__build_id_filename(dso, NULL, 0); | 1391 | filename = dso__build_id_filename(dso, NULL, 0); |
1426 | if (filename != NULL) { | 1392 | if (filename != NULL) { |
1427 | err = dso__load_vmlinux(dso, map, filename, filter); | 1393 | err = dso__load_vmlinux(dso, map, filename, true, filter); |
1428 | if (err > 0) { | 1394 | if (err > 0) |
1429 | dso->lname_alloc = 1; | ||
1430 | goto out; | 1395 | goto out; |
1431 | } | ||
1432 | free(filename); | 1396 | free(filename); |
1433 | } | 1397 | } |
1434 | 1398 | ||
1435 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | 1399 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { |
1436 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); | 1400 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); |
1437 | if (err > 0) { | 1401 | if (err > 0) |
1438 | dso__set_long_name(dso, strdup(vmlinux_path[i])); | ||
1439 | dso->lname_alloc = 1; | ||
1440 | break; | 1402 | break; |
1441 | } | ||
1442 | } | 1403 | } |
1443 | out: | 1404 | out: |
1444 | return err; | 1405 | return err; |
@@ -1496,14 +1457,15 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) | |||
1496 | 1457 | ||
1497 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | 1458 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); |
1498 | 1459 | ||
1460 | scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir, | ||
1461 | sbuild_id); | ||
1462 | |||
1499 | /* Use /proc/kallsyms if possible */ | 1463 | /* Use /proc/kallsyms if possible */ |
1500 | if (is_host) { | 1464 | if (is_host) { |
1501 | DIR *d; | 1465 | DIR *d; |
1502 | int fd; | 1466 | int fd; |
1503 | 1467 | ||
1504 | /* If no cached kcore go with /proc/kallsyms */ | 1468 | /* If no cached kcore go with /proc/kallsyms */ |
1505 | scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", | ||
1506 | buildid_dir, sbuild_id); | ||
1507 | d = opendir(path); | 1469 | d = opendir(path); |
1508 | if (!d) | 1470 | if (!d) |
1509 | goto proc_kallsyms; | 1471 | goto proc_kallsyms; |
@@ -1528,6 +1490,10 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) | |||
1528 | goto proc_kallsyms; | 1490 | goto proc_kallsyms; |
1529 | } | 1491 | } |
1530 | 1492 | ||
1493 | /* Find kallsyms in build-id cache with kcore */ | ||
1494 | if (!find_matching_kcore(map, path, sizeof(path))) | ||
1495 | return strdup(path); | ||
1496 | |||
1531 | scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", | 1497 | scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", |
1532 | buildid_dir, sbuild_id); | 1498 | buildid_dir, sbuild_id); |
1533 | 1499 | ||
@@ -1570,15 +1536,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, | |||
1570 | } | 1536 | } |
1571 | 1537 | ||
1572 | if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { | 1538 | if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { |
1573 | err = dso__load_vmlinux(dso, map, | 1539 | return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name, |
1574 | symbol_conf.vmlinux_name, filter); | 1540 | false, filter); |
1575 | if (err > 0) { | ||
1576 | dso__set_long_name(dso, | ||
1577 | strdup(symbol_conf.vmlinux_name)); | ||
1578 | dso->lname_alloc = 1; | ||
1579 | return err; | ||
1580 | } | ||
1581 | return err; | ||
1582 | } | 1541 | } |
1583 | 1542 | ||
1584 | if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { | 1543 | if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { |
@@ -1604,7 +1563,7 @@ do_kallsyms: | |||
1604 | free(kallsyms_allocated_filename); | 1563 | free(kallsyms_allocated_filename); |
1605 | 1564 | ||
1606 | if (err > 0 && !dso__is_kcore(dso)) { | 1565 | if (err > 0 && !dso__is_kcore(dso)) { |
1607 | dso__set_long_name(dso, strdup("[kernel.kallsyms]")); | 1566 | dso__set_long_name(dso, "[kernel.kallsyms]", false); |
1608 | map__fixup_start(map); | 1567 | map__fixup_start(map); |
1609 | map__fixup_end(map); | 1568 | map__fixup_end(map); |
1610 | } | 1569 | } |
@@ -1634,7 +1593,8 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | |||
1634 | */ | 1593 | */ |
1635 | if (symbol_conf.default_guest_vmlinux_name != NULL) { | 1594 | if (symbol_conf.default_guest_vmlinux_name != NULL) { |
1636 | err = dso__load_vmlinux(dso, map, | 1595 | err = dso__load_vmlinux(dso, map, |
1637 | symbol_conf.default_guest_vmlinux_name, filter); | 1596 | symbol_conf.default_guest_vmlinux_name, |
1597 | false, filter); | ||
1638 | return err; | 1598 | return err; |
1639 | } | 1599 | } |
1640 | 1600 | ||
@@ -1651,7 +1611,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | |||
1651 | pr_debug("Using %s for symbols\n", kallsyms_filename); | 1611 | pr_debug("Using %s for symbols\n", kallsyms_filename); |
1652 | if (err > 0 && !dso__is_kcore(dso)) { | 1612 | if (err > 0 && !dso__is_kcore(dso)) { |
1653 | machine__mmap_name(machine, path, sizeof(path)); | 1613 | machine__mmap_name(machine, path, sizeof(path)); |
1654 | dso__set_long_name(dso, strdup(path)); | 1614 | dso__set_long_name(dso, strdup(path), true); |
1655 | map__fixup_start(map); | 1615 | map__fixup_start(map); |
1656 | map__fixup_end(map); | 1616 | map__fixup_end(map); |
1657 | } | 1617 | } |
@@ -1661,13 +1621,10 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | |||
1661 | 1621 | ||
1662 | static void vmlinux_path__exit(void) | 1622 | static void vmlinux_path__exit(void) |
1663 | { | 1623 | { |
1664 | while (--vmlinux_path__nr_entries >= 0) { | 1624 | while (--vmlinux_path__nr_entries >= 0) |
1665 | free(vmlinux_path[vmlinux_path__nr_entries]); | 1625 | zfree(&vmlinux_path[vmlinux_path__nr_entries]); |
1666 | vmlinux_path[vmlinux_path__nr_entries] = NULL; | ||
1667 | } | ||
1668 | 1626 | ||
1669 | free(vmlinux_path); | 1627 | zfree(&vmlinux_path); |
1670 | vmlinux_path = NULL; | ||
1671 | } | 1628 | } |
1672 | 1629 | ||
1673 | static int vmlinux_path__init(void) | 1630 | static int vmlinux_path__init(void) |
@@ -1719,7 +1676,7 @@ out_fail: | |||
1719 | return -1; | 1676 | return -1; |
1720 | } | 1677 | } |
1721 | 1678 | ||
1722 | static int setup_list(struct strlist **list, const char *list_str, | 1679 | int setup_list(struct strlist **list, const char *list_str, |
1723 | const char *list_name) | 1680 | const char *list_name) |
1724 | { | 1681 | { |
1725 | if (list_str == NULL) | 1682 | if (list_str == NULL) |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 07de8fea2f48..fffe2888a1c7 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -52,6 +52,11 @@ static inline char *bfd_demangle(void __maybe_unused *v, | |||
52 | # define PERF_ELF_C_READ_MMAP ELF_C_READ | 52 | # define PERF_ELF_C_READ_MMAP ELF_C_READ |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | #ifdef HAVE_LIBELF_SUPPORT | ||
56 | extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | ||
57 | GElf_Shdr *shp, const char *name, size_t *idx); | ||
58 | #endif | ||
59 | |||
55 | #ifndef DMGL_PARAMS | 60 | #ifndef DMGL_PARAMS |
56 | #define DMGL_PARAMS (1 << 0) /* Include function args */ | 61 | #define DMGL_PARAMS (1 << 0) /* Include function args */ |
57 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ | 62 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ |
@@ -164,6 +169,7 @@ struct mem_info { | |||
164 | }; | 169 | }; |
165 | 170 | ||
166 | struct addr_location { | 171 | struct addr_location { |
172 | struct machine *machine; | ||
167 | struct thread *thread; | 173 | struct thread *thread; |
168 | struct map *map; | 174 | struct map *map; |
169 | struct symbol *sym; | 175 | struct symbol *sym; |
@@ -206,7 +212,8 @@ bool symsrc__possibly_runtime(struct symsrc *ss); | |||
206 | 212 | ||
207 | int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); | 213 | int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); |
208 | int dso__load_vmlinux(struct dso *dso, struct map *map, | 214 | int dso__load_vmlinux(struct dso *dso, struct map *map, |
209 | const char *vmlinux, symbol_filter_t filter); | 215 | const char *vmlinux, bool vmlinux_allocated, |
216 | symbol_filter_t filter); | ||
210 | int dso__load_vmlinux_path(struct dso *dso, struct map *map, | 217 | int dso__load_vmlinux_path(struct dso *dso, struct map *map, |
211 | symbol_filter_t filter); | 218 | symbol_filter_t filter); |
212 | int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, | 219 | int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, |
@@ -220,9 +227,6 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); | |||
220 | 227 | ||
221 | int filename__read_build_id(const char *filename, void *bf, size_t size); | 228 | int filename__read_build_id(const char *filename, void *bf, size_t size); |
222 | int sysfs__read_build_id(const char *filename, void *bf, size_t size); | 229 | int sysfs__read_build_id(const char *filename, void *bf, size_t size); |
223 | int kallsyms__parse(const char *filename, void *arg, | ||
224 | int (*process_symbol)(void *arg, const char *name, | ||
225 | char type, u64 start)); | ||
226 | int modules__parse(const char *filename, void *arg, | 230 | int modules__parse(const char *filename, void *arg, |
227 | int (*process_module)(void *arg, const char *name, | 231 | int (*process_module)(void *arg, const char *name, |
228 | u64 start)); | 232 | u64 start)); |
@@ -240,6 +244,7 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp); | |||
240 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); | 244 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); |
241 | bool symbol__restricted_filename(const char *filename, | 245 | bool symbol__restricted_filename(const char *filename, |
242 | const char *restricted_filename); | 246 | const char *restricted_filename); |
247 | bool symbol__is_idle(struct symbol *sym); | ||
243 | 248 | ||
244 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | 249 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, |
245 | struct symsrc *runtime_ss, symbol_filter_t filter, | 250 | struct symsrc *runtime_ss, symbol_filter_t filter, |
@@ -273,4 +278,7 @@ void kcore_extract__delete(struct kcore_extract *kce); | |||
273 | int kcore_copy(const char *from_dir, const char *to_dir); | 278 | int kcore_copy(const char *from_dir, const char *to_dir); |
274 | int compare_proc_modules(const char *from, const char *to); | 279 | int compare_proc_modules(const char *from, const char *to); |
275 | 280 | ||
281 | int setup_list(struct strlist **list, const char *list_str, | ||
282 | const char *list_name); | ||
283 | |||
276 | #endif /* __PERF_SYMBOL */ | 284 | #endif /* __PERF_SYMBOL */ |
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c index 3c778a07b7cc..e74c5963dc7a 100644 --- a/tools/perf/util/target.c +++ b/tools/perf/util/target.c | |||
@@ -55,6 +55,13 @@ enum target_errno target__validate(struct target *target) | |||
55 | ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; | 55 | ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; |
56 | } | 56 | } |
57 | 57 | ||
58 | /* THREAD and SYSTEM/CPU are mutually exclusive */ | ||
59 | if (target->per_thread && (target->system_wide || target->cpu_list)) { | ||
60 | target->per_thread = false; | ||
61 | if (ret == TARGET_ERRNO__SUCCESS) | ||
62 | ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD; | ||
63 | } | ||
64 | |||
58 | return ret; | 65 | return ret; |
59 | } | 66 | } |
60 | 67 | ||
@@ -100,6 +107,7 @@ static const char *target__error_str[] = { | |||
100 | "UID switch overriding CPU", | 107 | "UID switch overriding CPU", |
101 | "PID/TID switch overriding SYSTEM", | 108 | "PID/TID switch overriding SYSTEM", |
102 | "UID switch overriding SYSTEM", | 109 | "UID switch overriding SYSTEM", |
110 | "SYSTEM/CPU switch overriding PER-THREAD", | ||
103 | "Invalid User: %s", | 111 | "Invalid User: %s", |
104 | "Problems obtaining information for user %s", | 112 | "Problems obtaining information for user %s", |
105 | }; | 113 | }; |
@@ -131,7 +139,8 @@ int target__strerror(struct target *target, int errnum, | |||
131 | msg = target__error_str[idx]; | 139 | msg = target__error_str[idx]; |
132 | 140 | ||
133 | switch (errnum) { | 141 | switch (errnum) { |
134 | case TARGET_ERRNO__PID_OVERRIDE_CPU ... TARGET_ERRNO__UID_OVERRIDE_SYSTEM: | 142 | case TARGET_ERRNO__PID_OVERRIDE_CPU ... |
143 | TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD: | ||
135 | snprintf(buf, buflen, "%s", msg); | 144 | snprintf(buf, buflen, "%s", msg); |
136 | break; | 145 | break; |
137 | 146 | ||
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h index 2d0c50690892..7381b1ca4041 100644 --- a/tools/perf/util/target.h +++ b/tools/perf/util/target.h | |||
@@ -12,7 +12,8 @@ struct target { | |||
12 | uid_t uid; | 12 | uid_t uid; |
13 | bool system_wide; | 13 | bool system_wide; |
14 | bool uses_mmap; | 14 | bool uses_mmap; |
15 | bool force_per_cpu; | 15 | bool default_per_cpu; |
16 | bool per_thread; | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | enum target_errno { | 19 | enum target_errno { |
@@ -33,6 +34,7 @@ enum target_errno { | |||
33 | TARGET_ERRNO__UID_OVERRIDE_CPU, | 34 | TARGET_ERRNO__UID_OVERRIDE_CPU, |
34 | TARGET_ERRNO__PID_OVERRIDE_SYSTEM, | 35 | TARGET_ERRNO__PID_OVERRIDE_SYSTEM, |
35 | TARGET_ERRNO__UID_OVERRIDE_SYSTEM, | 36 | TARGET_ERRNO__UID_OVERRIDE_SYSTEM, |
37 | TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD, | ||
36 | 38 | ||
37 | /* for target__parse_uid() */ | 39 | /* for target__parse_uid() */ |
38 | TARGET_ERRNO__INVALID_UID, | 40 | TARGET_ERRNO__INVALID_UID, |
@@ -61,4 +63,17 @@ static inline bool target__none(struct target *target) | |||
61 | return !target__has_task(target) && !target__has_cpu(target); | 63 | return !target__has_task(target) && !target__has_cpu(target); |
62 | } | 64 | } |
63 | 65 | ||
66 | static inline bool target__uses_dummy_map(struct target *target) | ||
67 | { | ||
68 | bool use_dummy = false; | ||
69 | |||
70 | if (target->default_per_cpu) | ||
71 | use_dummy = target->per_thread ? true : false; | ||
72 | else if (target__has_task(target) || | ||
73 | (!target__has_cpu(target) && !target->uses_mmap)) | ||
74 | use_dummy = true; | ||
75 | |||
76 | return use_dummy; | ||
77 | } | ||
78 | |||
64 | #endif /* _PERF_TARGET_H */ | 79 | #endif /* _PERF_TARGET_H */ |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 49eaf1d7d89d..0358882c8910 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -66,10 +66,13 @@ struct comm *thread__comm(const struct thread *thread) | |||
66 | int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) | 66 | int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) |
67 | { | 67 | { |
68 | struct comm *new, *curr = thread__comm(thread); | 68 | struct comm *new, *curr = thread__comm(thread); |
69 | int err; | ||
69 | 70 | ||
70 | /* Override latest entry if it had no specific time coverage */ | 71 | /* Override latest entry if it had no specific time coverage */ |
71 | if (!curr->start) { | 72 | if (!curr->start) { |
72 | comm__override(curr, str, timestamp); | 73 | err = comm__override(curr, str, timestamp); |
74 | if (err) | ||
75 | return err; | ||
73 | } else { | 76 | } else { |
74 | new = comm__new(str, timestamp); | 77 | new = comm__new(str, timestamp); |
75 | if (!new) | 78 | if (!new) |
@@ -126,7 +129,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) | |||
126 | if (!comm) | 129 | if (!comm) |
127 | return -ENOMEM; | 130 | return -ENOMEM; |
128 | err = thread__set_comm(thread, comm, timestamp); | 131 | err = thread__set_comm(thread, comm, timestamp); |
129 | if (!err) | 132 | if (err) |
130 | return err; | 133 | return err; |
131 | thread->comm_set = true; | 134 | thread->comm_set = true; |
132 | } | 135 | } |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 897c1b2a750a..5b856bf942e1 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <sys/types.h> | 7 | #include <sys/types.h> |
8 | #include "symbol.h" | 8 | #include "symbol.h" |
9 | #include <strlist.h> | ||
9 | 10 | ||
10 | struct thread { | 11 | struct thread { |
11 | union { | 12 | union { |
@@ -66,4 +67,15 @@ static inline void thread__set_priv(struct thread *thread, void *p) | |||
66 | { | 67 | { |
67 | thread->priv = p; | 68 | thread->priv = p; |
68 | } | 69 | } |
70 | |||
71 | static inline bool thread__is_filtered(struct thread *thread) | ||
72 | { | ||
73 | if (symbol_conf.comm_list && | ||
74 | !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) { | ||
75 | return true; | ||
76 | } | ||
77 | |||
78 | return false; | ||
79 | } | ||
80 | |||
69 | #endif /* __PERF_THREAD_H */ | 81 | #endif /* __PERF_THREAD_H */ |
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 9b5f856cc280..5d3215912105 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "strlist.h" | 9 | #include "strlist.h" |
10 | #include <string.h> | 10 | #include <string.h> |
11 | #include "thread_map.h" | 11 | #include "thread_map.h" |
12 | #include "util.h" | ||
12 | 13 | ||
13 | /* Skip "." and ".." directories */ | 14 | /* Skip "." and ".." directories */ |
14 | static int filter(const struct dirent *dir) | 15 | static int filter(const struct dirent *dir) |
@@ -40,7 +41,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) | |||
40 | } | 41 | } |
41 | 42 | ||
42 | for (i=0; i<items; i++) | 43 | for (i=0; i<items; i++) |
43 | free(namelist[i]); | 44 | zfree(&namelist[i]); |
44 | free(namelist); | 45 | free(namelist); |
45 | 46 | ||
46 | return threads; | 47 | return threads; |
@@ -117,7 +118,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) | |||
117 | threads->map[threads->nr + i] = atoi(namelist[i]->d_name); | 118 | threads->map[threads->nr + i] = atoi(namelist[i]->d_name); |
118 | 119 | ||
119 | for (i = 0; i < items; i++) | 120 | for (i = 0; i < items; i++) |
120 | free(namelist[i]); | 121 | zfree(&namelist[i]); |
121 | free(namelist); | 122 | free(namelist); |
122 | 123 | ||
123 | threads->nr += items; | 124 | threads->nr += items; |
@@ -134,12 +135,11 @@ out_free_threads: | |||
134 | 135 | ||
135 | out_free_namelist: | 136 | out_free_namelist: |
136 | for (i = 0; i < items; i++) | 137 | for (i = 0; i < items; i++) |
137 | free(namelist[i]); | 138 | zfree(&namelist[i]); |
138 | free(namelist); | 139 | free(namelist); |
139 | 140 | ||
140 | out_free_closedir: | 141 | out_free_closedir: |
141 | free(threads); | 142 | zfree(&threads); |
142 | threads = NULL; | ||
143 | goto out_closedir; | 143 | goto out_closedir; |
144 | } | 144 | } |
145 | 145 | ||
@@ -194,7 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) | |||
194 | 194 | ||
195 | for (i = 0; i < items; i++) { | 195 | for (i = 0; i < items; i++) { |
196 | threads->map[j++] = atoi(namelist[i]->d_name); | 196 | threads->map[j++] = atoi(namelist[i]->d_name); |
197 | free(namelist[i]); | 197 | zfree(&namelist[i]); |
198 | } | 198 | } |
199 | threads->nr = total_tasks; | 199 | threads->nr = total_tasks; |
200 | free(namelist); | 200 | free(namelist); |
@@ -206,12 +206,11 @@ out: | |||
206 | 206 | ||
207 | out_free_namelist: | 207 | out_free_namelist: |
208 | for (i = 0; i < items; i++) | 208 | for (i = 0; i < items; i++) |
209 | free(namelist[i]); | 209 | zfree(&namelist[i]); |
210 | free(namelist); | 210 | free(namelist); |
211 | 211 | ||
212 | out_free_threads: | 212 | out_free_threads: |
213 | free(threads); | 213 | zfree(&threads); |
214 | threads = NULL; | ||
215 | goto out; | 214 | goto out; |
216 | } | 215 | } |
217 | 216 | ||
@@ -262,8 +261,7 @@ out: | |||
262 | return threads; | 261 | return threads; |
263 | 262 | ||
264 | out_free_threads: | 263 | out_free_threads: |
265 | free(threads); | 264 | zfree(&threads); |
266 | threads = NULL; | ||
267 | goto out; | 265 | goto out; |
268 | } | 266 | } |
269 | 267 | ||
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index ce793c7dd23c..8e517def925b 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c | |||
@@ -26,7 +26,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) | |||
26 | float samples_per_sec; | 26 | float samples_per_sec; |
27 | float ksamples_per_sec; | 27 | float ksamples_per_sec; |
28 | float esamples_percent; | 28 | float esamples_percent; |
29 | struct perf_record_opts *opts = &top->record_opts; | 29 | struct record_opts *opts = &top->record_opts; |
30 | struct target *target = &opts->target; | 30 | struct target *target = &opts->target; |
31 | size_t ret = 0; | 31 | size_t ret = 0; |
32 | 32 | ||
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 88cfeaff600b..dab14d0ad3d0 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h | |||
@@ -14,7 +14,7 @@ struct perf_session; | |||
14 | struct perf_top { | 14 | struct perf_top { |
15 | struct perf_tool tool; | 15 | struct perf_tool tool; |
16 | struct perf_evlist *evlist; | 16 | struct perf_evlist *evlist; |
17 | struct perf_record_opts record_opts; | 17 | struct record_opts record_opts; |
18 | /* | 18 | /* |
19 | * Symbols will be added here in perf_event__process_sample and will | 19 | * Symbols will be added here in perf_event__process_sample and will |
20 | * get out after decayed. | 20 | * get out after decayed. |
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index f3c9e551bd35..7e6fcfe8b438 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | #include "../perf.h" | 39 | #include "../perf.h" |
40 | #include "trace-event.h" | 40 | #include "trace-event.h" |
41 | #include <lk/debugfs.h> | 41 | #include <api/fs/debugfs.h> |
42 | #include "evsel.h" | 42 | #include "evsel.h" |
43 | 43 | ||
44 | #define VERSION "0.5" | 44 | #define VERSION "0.5" |
@@ -397,8 +397,8 @@ put_tracepoints_path(struct tracepoint_path *tps) | |||
397 | struct tracepoint_path *t = tps; | 397 | struct tracepoint_path *t = tps; |
398 | 398 | ||
399 | tps = tps->next; | 399 | tps = tps->next; |
400 | free(t->name); | 400 | zfree(&t->name); |
401 | free(t->system); | 401 | zfree(&t->system); |
402 | free(t); | 402 | free(t); |
403 | } | 403 | } |
404 | } | 404 | } |
@@ -562,10 +562,8 @@ out: | |||
562 | output_fd = fd; | 562 | output_fd = fd; |
563 | } | 563 | } |
564 | 564 | ||
565 | if (err) { | 565 | if (err) |
566 | free(tdata); | 566 | zfree(&tdata); |
567 | tdata = NULL; | ||
568 | } | ||
569 | 567 | ||
570 | put_tracepoints_path(tps); | 568 | put_tracepoints_path(tps); |
571 | return tdata; | 569 | return tdata; |
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 6681f71f2f95..e0d6d07f6848 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
@@ -28,19 +28,6 @@ | |||
28 | #include "util.h" | 28 | #include "util.h" |
29 | #include "trace-event.h" | 29 | #include "trace-event.h" |
30 | 30 | ||
31 | struct pevent *read_trace_init(int file_bigendian, int host_bigendian) | ||
32 | { | ||
33 | struct pevent *pevent = pevent_alloc(); | ||
34 | |||
35 | if (pevent != NULL) { | ||
36 | pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); | ||
37 | pevent_set_file_bigendian(pevent, file_bigendian); | ||
38 | pevent_set_host_bigendian(pevent, host_bigendian); | ||
39 | } | ||
40 | |||
41 | return pevent; | ||
42 | } | ||
43 | |||
44 | static int get_common_field(struct scripting_context *context, | 31 | static int get_common_field(struct scripting_context *context, |
45 | int *offset, int *size, const char *type) | 32 | int *offset, int *size, const char *type) |
46 | { | 33 | { |
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index f2112270c663..e113e180c48f 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c | |||
@@ -343,7 +343,7 @@ static int read_event_files(struct pevent *pevent) | |||
343 | return 0; | 343 | return 0; |
344 | } | 344 | } |
345 | 345 | ||
346 | ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) | 346 | ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe) |
347 | { | 347 | { |
348 | char buf[BUFSIZ]; | 348 | char buf[BUFSIZ]; |
349 | char test[] = { 23, 8, 68 }; | 349 | char test[] = { 23, 8, 68 }; |
@@ -356,11 +356,9 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) | |||
356 | int host_bigendian; | 356 | int host_bigendian; |
357 | int file_long_size; | 357 | int file_long_size; |
358 | int file_page_size; | 358 | int file_page_size; |
359 | struct pevent *pevent; | 359 | struct pevent *pevent = NULL; |
360 | int err; | 360 | int err; |
361 | 361 | ||
362 | *ppevent = NULL; | ||
363 | |||
364 | repipe = __repipe; | 362 | repipe = __repipe; |
365 | input_fd = fd; | 363 | input_fd = fd; |
366 | 364 | ||
@@ -390,12 +388,17 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) | |||
390 | file_bigendian = buf[0]; | 388 | file_bigendian = buf[0]; |
391 | host_bigendian = bigendian(); | 389 | host_bigendian = bigendian(); |
392 | 390 | ||
393 | pevent = read_trace_init(file_bigendian, host_bigendian); | 391 | if (trace_event__init(tevent)) { |
394 | if (pevent == NULL) { | 392 | pr_debug("trace_event__init failed"); |
395 | pr_debug("read_trace_init failed"); | ||
396 | goto out; | 393 | goto out; |
397 | } | 394 | } |
398 | 395 | ||
396 | pevent = tevent->pevent; | ||
397 | |||
398 | pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); | ||
399 | pevent_set_file_bigendian(pevent, file_bigendian); | ||
400 | pevent_set_host_bigendian(pevent, host_bigendian); | ||
401 | |||
399 | if (do_read(buf, 1) < 0) | 402 | if (do_read(buf, 1) < 0) |
400 | goto out; | 403 | goto out; |
401 | file_long_size = buf[0]; | 404 | file_long_size = buf[0]; |
@@ -432,11 +435,10 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) | |||
432 | pevent_print_printk(pevent); | 435 | pevent_print_printk(pevent); |
433 | } | 436 | } |
434 | 437 | ||
435 | *ppevent = pevent; | ||
436 | pevent = NULL; | 438 | pevent = NULL; |
437 | 439 | ||
438 | out: | 440 | out: |
439 | if (pevent) | 441 | if (pevent) |
440 | pevent_free(pevent); | 442 | trace_event__cleanup(tevent); |
441 | return size; | 443 | return size; |
442 | } | 444 | } |
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 95199e4eea97..57aaccc1692e 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c | |||
@@ -38,9 +38,8 @@ static int stop_script_unsupported(void) | |||
38 | static void process_event_unsupported(union perf_event *event __maybe_unused, | 38 | static void process_event_unsupported(union perf_event *event __maybe_unused, |
39 | struct perf_sample *sample __maybe_unused, | 39 | struct perf_sample *sample __maybe_unused, |
40 | struct perf_evsel *evsel __maybe_unused, | 40 | struct perf_evsel *evsel __maybe_unused, |
41 | struct machine *machine __maybe_unused, | ||
42 | struct thread *thread __maybe_unused, | 41 | struct thread *thread __maybe_unused, |
43 | struct addr_location *al __maybe_unused) | 42 | struct addr_location *al __maybe_unused) |
44 | { | 43 | { |
45 | } | 44 | } |
46 | 45 | ||
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c new file mode 100644 index 000000000000..6322d37164c5 --- /dev/null +++ b/tools/perf/util/trace-event.c | |||
@@ -0,0 +1,82 @@ | |||
1 | |||
2 | #include <stdio.h> | ||
3 | #include <unistd.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <errno.h> | ||
6 | #include <sys/types.h> | ||
7 | #include <sys/stat.h> | ||
8 | #include <fcntl.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <traceevent/event-parse.h> | ||
11 | #include "trace-event.h" | ||
12 | #include "util.h" | ||
13 | |||
14 | /* | ||
15 | * global trace_event object used by trace_event__tp_format | ||
16 | * | ||
17 | * TODO There's no cleanup call for this. Add some sort of | ||
18 | * __exit function support and call trace_event__cleanup | ||
19 | * there. | ||
20 | */ | ||
21 | static struct trace_event tevent; | ||
22 | |||
23 | int trace_event__init(struct trace_event *t) | ||
24 | { | ||
25 | struct pevent *pevent = pevent_alloc(); | ||
26 | |||
27 | if (pevent) { | ||
28 | t->plugin_list = traceevent_load_plugins(pevent); | ||
29 | t->pevent = pevent; | ||
30 | } | ||
31 | |||
32 | return pevent ? 0 : -1; | ||
33 | } | ||
34 | |||
35 | void trace_event__cleanup(struct trace_event *t) | ||
36 | { | ||
37 | traceevent_unload_plugins(t->plugin_list, t->pevent); | ||
38 | pevent_free(t->pevent); | ||
39 | } | ||
40 | |||
41 | static struct event_format* | ||
42 | tp_format(const char *sys, const char *name) | ||
43 | { | ||
44 | struct pevent *pevent = tevent.pevent; | ||
45 | struct event_format *event = NULL; | ||
46 | char path[PATH_MAX]; | ||
47 | size_t size; | ||
48 | char *data; | ||
49 | |||
50 | scnprintf(path, PATH_MAX, "%s/%s/%s/format", | ||
51 | tracing_events_path, sys, name); | ||
52 | |||
53 | if (filename__read_str(path, &data, &size)) | ||
54 | return NULL; | ||
55 | |||
56 | pevent_parse_format(pevent, &event, data, size, sys); | ||
57 | |||
58 | free(data); | ||
59 | return event; | ||
60 | } | ||
61 | |||
62 | struct event_format* | ||
63 | trace_event__tp_format(const char *sys, const char *name) | ||
64 | { | ||
65 | static bool initialized; | ||
66 | |||
67 | if (!initialized) { | ||
68 | int be = traceevent_host_bigendian(); | ||
69 | struct pevent *pevent; | ||
70 | |||
71 | if (trace_event__init(&tevent)) | ||
72 | return NULL; | ||
73 | |||
74 | pevent = tevent.pevent; | ||
75 | pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); | ||
76 | pevent_set_file_bigendian(pevent, be); | ||
77 | pevent_set_host_bigendian(pevent, be); | ||
78 | initialized = true; | ||
79 | } | ||
80 | |||
81 | return tp_format(sys, name); | ||
82 | } | ||
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 04df63114109..7b6d68688327 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
@@ -3,17 +3,26 @@ | |||
3 | 3 | ||
4 | #include <traceevent/event-parse.h> | 4 | #include <traceevent/event-parse.h> |
5 | #include "parse-events.h" | 5 | #include "parse-events.h" |
6 | #include "session.h" | ||
7 | 6 | ||
8 | struct machine; | 7 | struct machine; |
9 | struct perf_sample; | 8 | struct perf_sample; |
10 | union perf_event; | 9 | union perf_event; |
11 | struct perf_tool; | 10 | struct perf_tool; |
12 | struct thread; | 11 | struct thread; |
12 | struct plugin_list; | ||
13 | |||
14 | struct trace_event { | ||
15 | struct pevent *pevent; | ||
16 | struct plugin_list *plugin_list; | ||
17 | }; | ||
18 | |||
19 | int trace_event__init(struct trace_event *t); | ||
20 | void trace_event__cleanup(struct trace_event *t); | ||
21 | struct event_format* | ||
22 | trace_event__tp_format(const char *sys, const char *name); | ||
13 | 23 | ||
14 | int bigendian(void); | 24 | int bigendian(void); |
15 | 25 | ||
16 | struct pevent *read_trace_init(int file_bigendian, int host_bigendian); | ||
17 | void event_format__print(struct event_format *event, | 26 | void event_format__print(struct event_format *event, |
18 | int cpu, void *data, int size); | 27 | int cpu, void *data, int size); |
19 | 28 | ||
@@ -27,7 +36,7 @@ raw_field_value(struct event_format *event, const char *name, void *data); | |||
27 | void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); | 36 | void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); |
28 | void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); | 37 | void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); |
29 | 38 | ||
30 | ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); | 39 | ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); |
31 | 40 | ||
32 | struct event_format *trace_find_next_event(struct pevent *pevent, | 41 | struct event_format *trace_find_next_event(struct pevent *pevent, |
33 | struct event_format *event); | 42 | struct event_format *event); |
@@ -59,7 +68,6 @@ struct scripting_ops { | |||
59 | void (*process_event) (union perf_event *event, | 68 | void (*process_event) (union perf_event *event, |
60 | struct perf_sample *sample, | 69 | struct perf_sample *sample, |
61 | struct perf_evsel *evsel, | 70 | struct perf_evsel *evsel, |
62 | struct machine *machine, | ||
63 | struct thread *thread, | 71 | struct thread *thread, |
64 | struct addr_location *al); | 72 | struct addr_location *al); |
65 | int (*generate_script) (struct pevent *pevent, const char *outfile); | 73 | int (*generate_script) (struct pevent *pevent, const char *outfile); |
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c index 0efd5393de85..742f23bf35ff 100644 --- a/tools/perf/util/unwind.c +++ b/tools/perf/util/unwind.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "session.h" | 28 | #include "session.h" |
29 | #include "perf_regs.h" | 29 | #include "perf_regs.h" |
30 | #include "unwind.h" | 30 | #include "unwind.h" |
31 | #include "symbol.h" | ||
31 | #include "util.h" | 32 | #include "util.h" |
32 | 33 | ||
33 | extern int | 34 | extern int |
@@ -158,23 +159,6 @@ static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, | |||
158 | __v; \ | 159 | __v; \ |
159 | }) | 160 | }) |
160 | 161 | ||
161 | static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | ||
162 | GElf_Shdr *shp, const char *name) | ||
163 | { | ||
164 | Elf_Scn *sec = NULL; | ||
165 | |||
166 | while ((sec = elf_nextscn(elf, sec)) != NULL) { | ||
167 | char *str; | ||
168 | |||
169 | gelf_getshdr(sec, shp); | ||
170 | str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); | ||
171 | if (!strcmp(name, str)) | ||
172 | break; | ||
173 | } | ||
174 | |||
175 | return sec; | ||
176 | } | ||
177 | |||
178 | static u64 elf_section_offset(int fd, const char *name) | 162 | static u64 elf_section_offset(int fd, const char *name) |
179 | { | 163 | { |
180 | Elf *elf; | 164 | Elf *elf; |
@@ -190,7 +174,7 @@ static u64 elf_section_offset(int fd, const char *name) | |||
190 | if (gelf_getehdr(elf, &ehdr) == NULL) | 174 | if (gelf_getehdr(elf, &ehdr) == NULL) |
191 | break; | 175 | break; |
192 | 176 | ||
193 | if (!elf_section_by_name(elf, &ehdr, &shdr, name)) | 177 | if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL)) |
194 | break; | 178 | break; |
195 | 179 | ||
196 | offset = shdr.sh_offset; | 180 | offset = shdr.sh_offset; |
@@ -340,10 +324,10 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | |||
340 | /* Check the .debug_frame section for unwinding info */ | 324 | /* Check the .debug_frame section for unwinding info */ |
341 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | 325 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { |
342 | memset(&di, 0, sizeof(di)); | 326 | memset(&di, 0, sizeof(di)); |
343 | dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, | 327 | if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, |
344 | map->start, map->end); | 328 | map->start, map->end)) |
345 | return dwarf_search_unwind_table(as, ip, &di, pi, | 329 | return dwarf_search_unwind_table(as, ip, &di, pi, |
346 | need_unwind_info, arg); | 330 | need_unwind_info, arg); |
347 | } | 331 | } |
348 | #endif | 332 | #endif |
349 | 333 | ||
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 28a0a89c1f73..42ad667bb317 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -1,11 +1,17 @@ | |||
1 | #include "../perf.h" | 1 | #include "../perf.h" |
2 | #include "util.h" | 2 | #include "util.h" |
3 | #include "fs.h" | ||
3 | #include <sys/mman.h> | 4 | #include <sys/mman.h> |
4 | #ifdef HAVE_BACKTRACE_SUPPORT | 5 | #ifdef HAVE_BACKTRACE_SUPPORT |
5 | #include <execinfo.h> | 6 | #include <execinfo.h> |
6 | #endif | 7 | #endif |
7 | #include <stdio.h> | 8 | #include <stdio.h> |
8 | #include <stdlib.h> | 9 | #include <stdlib.h> |
10 | #include <string.h> | ||
11 | #include <errno.h> | ||
12 | #include <limits.h> | ||
13 | #include <byteswap.h> | ||
14 | #include <linux/kernel.h> | ||
9 | 15 | ||
10 | /* | 16 | /* |
11 | * XXX We need to find a better place for these things... | 17 | * XXX We need to find a better place for these things... |
@@ -151,21 +157,40 @@ unsigned long convert_unit(unsigned long value, char *unit) | |||
151 | return value; | 157 | return value; |
152 | } | 158 | } |
153 | 159 | ||
154 | int readn(int fd, void *buf, size_t n) | 160 | static ssize_t ion(bool is_read, int fd, void *buf, size_t n) |
155 | { | 161 | { |
156 | void *buf_start = buf; | 162 | void *buf_start = buf; |
163 | size_t left = n; | ||
157 | 164 | ||
158 | while (n) { | 165 | while (left) { |
159 | int ret = read(fd, buf, n); | 166 | ssize_t ret = is_read ? read(fd, buf, left) : |
167 | write(fd, buf, left); | ||
160 | 168 | ||
161 | if (ret <= 0) | 169 | if (ret <= 0) |
162 | return ret; | 170 | return ret; |
163 | 171 | ||
164 | n -= ret; | 172 | left -= ret; |
165 | buf += ret; | 173 | buf += ret; |
166 | } | 174 | } |
167 | 175 | ||
168 | return buf - buf_start; | 176 | BUG_ON((size_t)(buf - buf_start) != n); |
177 | return n; | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * Read exactly 'n' bytes or return an error. | ||
182 | */ | ||
183 | ssize_t readn(int fd, void *buf, size_t n) | ||
184 | { | ||
185 | return ion(true, fd, buf, n); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Write exactly 'n' bytes or return an error. | ||
190 | */ | ||
191 | ssize_t writen(int fd, void *buf, size_t n) | ||
192 | { | ||
193 | return ion(false, fd, buf, n); | ||
169 | } | 194 | } |
170 | 195 | ||
171 | size_t hex_width(u64 v) | 196 | size_t hex_width(u64 v) |
@@ -413,3 +438,102 @@ int filename__read_int(const char *filename, int *value) | |||
413 | close(fd); | 438 | close(fd); |
414 | return err; | 439 | return err; |
415 | } | 440 | } |
441 | |||
442 | int filename__read_str(const char *filename, char **buf, size_t *sizep) | ||
443 | { | ||
444 | size_t size = 0, alloc_size = 0; | ||
445 | void *bf = NULL, *nbf; | ||
446 | int fd, n, err = 0; | ||
447 | |||
448 | fd = open(filename, O_RDONLY); | ||
449 | if (fd < 0) | ||
450 | return -errno; | ||
451 | |||
452 | do { | ||
453 | if (size == alloc_size) { | ||
454 | alloc_size += BUFSIZ; | ||
455 | nbf = realloc(bf, alloc_size); | ||
456 | if (!nbf) { | ||
457 | err = -ENOMEM; | ||
458 | break; | ||
459 | } | ||
460 | |||
461 | bf = nbf; | ||
462 | } | ||
463 | |||
464 | n = read(fd, bf + size, alloc_size - size); | ||
465 | if (n < 0) { | ||
466 | if (size) { | ||
467 | pr_warning("read failed %d: %s\n", | ||
468 | errno, strerror(errno)); | ||
469 | err = 0; | ||
470 | } else | ||
471 | err = -errno; | ||
472 | |||
473 | break; | ||
474 | } | ||
475 | |||
476 | size += n; | ||
477 | } while (n > 0); | ||
478 | |||
479 | if (!err) { | ||
480 | *sizep = size; | ||
481 | *buf = bf; | ||
482 | } else | ||
483 | free(bf); | ||
484 | |||
485 | close(fd); | ||
486 | return err; | ||
487 | } | ||
488 | |||
489 | const char *get_filename_for_perf_kvm(void) | ||
490 | { | ||
491 | const char *filename; | ||
492 | |||
493 | if (perf_host && !perf_guest) | ||
494 | filename = strdup("perf.data.host"); | ||
495 | else if (!perf_host && perf_guest) | ||
496 | filename = strdup("perf.data.guest"); | ||
497 | else | ||
498 | filename = strdup("perf.data.kvm"); | ||
499 | |||
500 | return filename; | ||
501 | } | ||
502 | |||
503 | int perf_event_paranoid(void) | ||
504 | { | ||
505 | char path[PATH_MAX]; | ||
506 | const char *procfs = procfs__mountpoint(); | ||
507 | int value; | ||
508 | |||
509 | if (!procfs) | ||
510 | return INT_MAX; | ||
511 | |||
512 | scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs); | ||
513 | |||
514 | if (filename__read_int(path, &value)) | ||
515 | return INT_MAX; | ||
516 | |||
517 | return value; | ||
518 | } | ||
519 | |||
520 | void mem_bswap_32(void *src, int byte_size) | ||
521 | { | ||
522 | u32 *m = src; | ||
523 | while (byte_size > 0) { | ||
524 | *m = bswap_32(*m); | ||
525 | byte_size -= sizeof(u32); | ||
526 | ++m; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | void mem_bswap_64(void *src, int byte_size) | ||
531 | { | ||
532 | u64 *m = src; | ||
533 | |||
534 | while (byte_size > 0) { | ||
535 | *m = bswap_64(*m); | ||
536 | byte_size -= sizeof(u64); | ||
537 | ++m; | ||
538 | } | ||
539 | } | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index c8f362daba87..6995d66f225c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -71,8 +71,9 @@ | |||
71 | #include <linux/magic.h> | 71 | #include <linux/magic.h> |
72 | #include "types.h" | 72 | #include "types.h" |
73 | #include <sys/ttydefaults.h> | 73 | #include <sys/ttydefaults.h> |
74 | #include <lk/debugfs.h> | 74 | #include <api/fs/debugfs.h> |
75 | #include <termios.h> | 75 | #include <termios.h> |
76 | #include <linux/bitops.h> | ||
76 | 77 | ||
77 | extern const char *graph_line; | 78 | extern const char *graph_line; |
78 | extern const char *graph_dotted_line; | 79 | extern const char *graph_dotted_line; |
@@ -185,6 +186,8 @@ static inline void *zalloc(size_t size) | |||
185 | return calloc(1, size); | 186 | return calloc(1, size); |
186 | } | 187 | } |
187 | 188 | ||
189 | #define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) | ||
190 | |||
188 | static inline int has_extension(const char *filename, const char *ext) | 191 | static inline int has_extension(const char *filename, const char *ext) |
189 | { | 192 | { |
190 | size_t len = strlen(filename); | 193 | size_t len = strlen(filename); |
@@ -253,7 +256,8 @@ bool strlazymatch(const char *str, const char *pat); | |||
253 | int strtailcmp(const char *s1, const char *s2); | 256 | int strtailcmp(const char *s1, const char *s2); |
254 | char *strxfrchar(char *s, char from, char to); | 257 | char *strxfrchar(char *s, char from, char to); |
255 | unsigned long convert_unit(unsigned long value, char *unit); | 258 | unsigned long convert_unit(unsigned long value, char *unit); |
256 | int readn(int fd, void *buf, size_t size); | 259 | ssize_t readn(int fd, void *buf, size_t n); |
260 | ssize_t writen(int fd, void *buf, size_t n); | ||
257 | 261 | ||
258 | struct perf_event_attr; | 262 | struct perf_event_attr; |
259 | 263 | ||
@@ -280,6 +284,17 @@ static inline unsigned next_pow2(unsigned x) | |||
280 | return 1ULL << (32 - __builtin_clz(x - 1)); | 284 | return 1ULL << (32 - __builtin_clz(x - 1)); |
281 | } | 285 | } |
282 | 286 | ||
287 | static inline unsigned long next_pow2_l(unsigned long x) | ||
288 | { | ||
289 | #if BITS_PER_LONG == 64 | ||
290 | if (x <= (1UL << 31)) | ||
291 | return next_pow2(x); | ||
292 | return (unsigned long)next_pow2(x >> 32) << 32; | ||
293 | #else | ||
294 | return next_pow2(x); | ||
295 | #endif | ||
296 | } | ||
297 | |||
283 | size_t hex_width(u64 v); | 298 | size_t hex_width(u64 v); |
284 | int hex2u64(const char *ptr, u64 *val); | 299 | int hex2u64(const char *ptr, u64 *val); |
285 | 300 | ||
@@ -307,4 +322,11 @@ char *get_srcline(struct dso *dso, unsigned long addr); | |||
307 | void free_srcline(char *srcline); | 322 | void free_srcline(char *srcline); |
308 | 323 | ||
309 | int filename__read_int(const char *filename, int *value); | 324 | int filename__read_int(const char *filename, int *value); |
325 | int filename__read_str(const char *filename, char **buf, size_t *sizep); | ||
326 | int perf_event_paranoid(void); | ||
327 | |||
328 | void mem_bswap_64(void *src, int byte_size); | ||
329 | void mem_bswap_32(void *src, int byte_size); | ||
330 | |||
331 | const char *get_filename_for_perf_kvm(void); | ||
310 | #endif /* GIT_COMPAT_UTIL_H */ | 332 | #endif /* GIT_COMPAT_UTIL_H */ |
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c index 697c8b4e59cc..0fb3c1fcd3e6 100644 --- a/tools/perf/util/values.c +++ b/tools/perf/util/values.c | |||
@@ -31,14 +31,14 @@ void perf_read_values_destroy(struct perf_read_values *values) | |||
31 | return; | 31 | return; |
32 | 32 | ||
33 | for (i = 0; i < values->threads; i++) | 33 | for (i = 0; i < values->threads; i++) |
34 | free(values->value[i]); | 34 | zfree(&values->value[i]); |
35 | free(values->value); | 35 | zfree(&values->value); |
36 | free(values->pid); | 36 | zfree(&values->pid); |
37 | free(values->tid); | 37 | zfree(&values->tid); |
38 | free(values->counterrawid); | 38 | zfree(&values->counterrawid); |
39 | for (i = 0; i < values->counters; i++) | 39 | for (i = 0; i < values->counters; i++) |
40 | free(values->countername[i]); | 40 | zfree(&values->countername[i]); |
41 | free(values->countername); | 41 | zfree(&values->countername); |
42 | } | 42 | } |
43 | 43 | ||
44 | static void perf_read_values__enlarge_threads(struct perf_read_values *values) | 44 | static void perf_read_values__enlarge_threads(struct perf_read_values *values) |
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index 39159822d58f..0ddb3b8a89ec 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c | |||
@@ -103,7 +103,7 @@ struct dso *vdso__dso_findnew(struct list_head *head) | |||
103 | dso = dso__new(VDSO__MAP_NAME); | 103 | dso = dso__new(VDSO__MAP_NAME); |
104 | if (dso != NULL) { | 104 | if (dso != NULL) { |
105 | dsos__add(head, dso); | 105 | dsos__add(head, dso); |
106 | dso__set_long_name(dso, file); | 106 | dso__set_long_name(dso, file, false); |
107 | } | 107 | } |
108 | } | 108 | } |
109 | 109 | ||
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index ee76544deecb..8abbef164b4e 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include | |||
@@ -61,6 +61,7 @@ QUIET_SUBDIR1 = | |||
61 | ifneq ($(findstring $(MAKEFLAGS),s),s) | 61 | ifneq ($(findstring $(MAKEFLAGS),s),s) |
62 | ifneq ($(V),1) | 62 | ifneq ($(V),1) |
63 | QUIET_CC = @echo ' CC '$@; | 63 | QUIET_CC = @echo ' CC '$@; |
64 | QUIET_CC_FPIC = @echo ' CC FPIC '$@; | ||
64 | QUIET_AR = @echo ' AR '$@; | 65 | QUIET_AR = @echo ' AR '$@; |
65 | QUIET_LINK = @echo ' LINK '$@; | 66 | QUIET_LINK = @echo ' LINK '$@; |
66 | QUIET_MKDIR = @echo ' MKDIR '$@; | 67 | QUIET_MKDIR = @echo ' MKDIR '$@; |
@@ -76,5 +77,8 @@ ifneq ($(findstring $(MAKEFLAGS),s),s) | |||
76 | +@echo ' DESCEND '$(1); \ | 77 | +@echo ' DESCEND '$(1); \ |
77 | mkdir -p $(OUTPUT)$(1) && \ | 78 | mkdir -p $(OUTPUT)$(1) && \ |
78 | $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) | 79 | $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) |
80 | |||
81 | QUIET_CLEAN = @printf ' CLEAN %s\n' $1; | ||
82 | QUIET_INSTALL = @printf ' INSTALL %s\n' $1; | ||
79 | endif | 83 | endif |
80 | endif | 84 | endif |
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 999eab1bc64f..40631569a0fd 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl | |||
@@ -18,6 +18,7 @@ $| = 1; | |||
18 | my %opt; | 18 | my %opt; |
19 | my %repeat_tests; | 19 | my %repeat_tests; |
20 | my %repeats; | 20 | my %repeats; |
21 | my %evals; | ||
21 | 22 | ||
22 | #default opts | 23 | #default opts |
23 | my %default = ( | 24 | my %default = ( |
@@ -25,6 +26,7 @@ my %default = ( | |||
25 | "TEST_TYPE" => "build", | 26 | "TEST_TYPE" => "build", |
26 | "BUILD_TYPE" => "randconfig", | 27 | "BUILD_TYPE" => "randconfig", |
27 | "MAKE_CMD" => "make", | 28 | "MAKE_CMD" => "make", |
29 | "CLOSE_CONSOLE_SIGNAL" => "INT", | ||
28 | "TIMEOUT" => 120, | 30 | "TIMEOUT" => 120, |
29 | "TMP_DIR" => "/tmp/ktest/\${MACHINE}", | 31 | "TMP_DIR" => "/tmp/ktest/\${MACHINE}", |
30 | "SLEEP_TIME" => 60, # sleep time between tests | 32 | "SLEEP_TIME" => 60, # sleep time between tests |
@@ -39,6 +41,7 @@ my %default = ( | |||
39 | "CLEAR_LOG" => 0, | 41 | "CLEAR_LOG" => 0, |
40 | "BISECT_MANUAL" => 0, | 42 | "BISECT_MANUAL" => 0, |
41 | "BISECT_SKIP" => 1, | 43 | "BISECT_SKIP" => 1, |
44 | "BISECT_TRIES" => 1, | ||
42 | "MIN_CONFIG_TYPE" => "boot", | 45 | "MIN_CONFIG_TYPE" => "boot", |
43 | "SUCCESS_LINE" => "login:", | 46 | "SUCCESS_LINE" => "login:", |
44 | "DETECT_TRIPLE_FAULT" => 1, | 47 | "DETECT_TRIPLE_FAULT" => 1, |
@@ -137,6 +140,7 @@ my $bisect_bad_commit = ""; | |||
137 | my $reverse_bisect; | 140 | my $reverse_bisect; |
138 | my $bisect_manual; | 141 | my $bisect_manual; |
139 | my $bisect_skip; | 142 | my $bisect_skip; |
143 | my $bisect_tries; | ||
140 | my $config_bisect_good; | 144 | my $config_bisect_good; |
141 | my $bisect_ret_good; | 145 | my $bisect_ret_good; |
142 | my $bisect_ret_bad; | 146 | my $bisect_ret_bad; |
@@ -163,6 +167,7 @@ my $timeout; | |||
163 | my $booted_timeout; | 167 | my $booted_timeout; |
164 | my $detect_triplefault; | 168 | my $detect_triplefault; |
165 | my $console; | 169 | my $console; |
170 | my $close_console_signal; | ||
166 | my $reboot_success_line; | 171 | my $reboot_success_line; |
167 | my $success_line; | 172 | my $success_line; |
168 | my $stop_after_success; | 173 | my $stop_after_success; |
@@ -273,6 +278,7 @@ my %option_map = ( | |||
273 | "IGNORE_ERRORS" => \$ignore_errors, | 278 | "IGNORE_ERRORS" => \$ignore_errors, |
274 | "BISECT_MANUAL" => \$bisect_manual, | 279 | "BISECT_MANUAL" => \$bisect_manual, |
275 | "BISECT_SKIP" => \$bisect_skip, | 280 | "BISECT_SKIP" => \$bisect_skip, |
281 | "BISECT_TRIES" => \$bisect_tries, | ||
276 | "CONFIG_BISECT_GOOD" => \$config_bisect_good, | 282 | "CONFIG_BISECT_GOOD" => \$config_bisect_good, |
277 | "BISECT_RET_GOOD" => \$bisect_ret_good, | 283 | "BISECT_RET_GOOD" => \$bisect_ret_good, |
278 | "BISECT_RET_BAD" => \$bisect_ret_bad, | 284 | "BISECT_RET_BAD" => \$bisect_ret_bad, |
@@ -285,6 +291,7 @@ my %option_map = ( | |||
285 | "TIMEOUT" => \$timeout, | 291 | "TIMEOUT" => \$timeout, |
286 | "BOOTED_TIMEOUT" => \$booted_timeout, | 292 | "BOOTED_TIMEOUT" => \$booted_timeout, |
287 | "CONSOLE" => \$console, | 293 | "CONSOLE" => \$console, |
294 | "CLOSE_CONSOLE_SIGNAL" => \$close_console_signal, | ||
288 | "DETECT_TRIPLE_FAULT" => \$detect_triplefault, | 295 | "DETECT_TRIPLE_FAULT" => \$detect_triplefault, |
289 | "SUCCESS_LINE" => \$success_line, | 296 | "SUCCESS_LINE" => \$success_line, |
290 | "REBOOT_SUCCESS_LINE" => \$reboot_success_line, | 297 | "REBOOT_SUCCESS_LINE" => \$reboot_success_line, |
@@ -445,6 +452,27 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF" | |||
445 | EOF | 452 | EOF |
446 | ; | 453 | ; |
447 | 454 | ||
455 | sub _logit { | ||
456 | if (defined($opt{"LOG_FILE"})) { | ||
457 | open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; | ||
458 | print OUT @_; | ||
459 | close(OUT); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | sub logit { | ||
464 | if (defined($opt{"LOG_FILE"})) { | ||
465 | _logit @_; | ||
466 | } else { | ||
467 | print @_; | ||
468 | } | ||
469 | } | ||
470 | |||
471 | sub doprint { | ||
472 | print @_; | ||
473 | _logit @_; | ||
474 | } | ||
475 | |||
448 | sub read_prompt { | 476 | sub read_prompt { |
449 | my ($cancel, $prompt) = @_; | 477 | my ($cancel, $prompt) = @_; |
450 | 478 | ||
@@ -662,6 +690,22 @@ sub set_value { | |||
662 | } | 690 | } |
663 | } | 691 | } |
664 | 692 | ||
693 | sub set_eval { | ||
694 | my ($lvalue, $rvalue, $name) = @_; | ||
695 | |||
696 | my $prvalue = process_variables($rvalue); | ||
697 | my $arr; | ||
698 | |||
699 | if (defined($evals{$lvalue})) { | ||
700 | $arr = $evals{$lvalue}; | ||
701 | } else { | ||
702 | $arr = []; | ||
703 | $evals{$lvalue} = $arr; | ||
704 | } | ||
705 | |||
706 | push @{$arr}, $rvalue; | ||
707 | } | ||
708 | |||
665 | sub set_variable { | 709 | sub set_variable { |
666 | my ($lvalue, $rvalue) = @_; | 710 | my ($lvalue, $rvalue) = @_; |
667 | 711 | ||
@@ -947,6 +991,20 @@ sub __read_config { | |||
947 | $test_case = 1; | 991 | $test_case = 1; |
948 | } | 992 | } |
949 | 993 | ||
994 | } elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) { | ||
995 | |||
996 | next if ($skip); | ||
997 | |||
998 | my $lvalue = $1; | ||
999 | my $rvalue = $2; | ||
1000 | |||
1001 | if ($default || $lvalue =~ /\[\d+\]$/) { | ||
1002 | set_eval($lvalue, $rvalue, $name); | ||
1003 | } else { | ||
1004 | my $val = "$lvalue\[$test_num\]"; | ||
1005 | set_eval($val, $rvalue, $name); | ||
1006 | } | ||
1007 | |||
950 | } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { | 1008 | } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { |
951 | 1009 | ||
952 | next if ($skip); | 1010 | next if ($skip); |
@@ -1126,6 +1184,10 @@ sub __eval_option { | |||
1126 | } elsif (defined($opt{$var})) { | 1184 | } elsif (defined($opt{$var})) { |
1127 | $o = $opt{$var}; | 1185 | $o = $opt{$var}; |
1128 | $retval = "$retval$o"; | 1186 | $retval = "$retval$o"; |
1187 | } elsif ($var eq "KERNEL_VERSION" && defined($make)) { | ||
1188 | # special option KERNEL_VERSION uses kernel version | ||
1189 | get_version(); | ||
1190 | $retval = "$retval$version"; | ||
1129 | } else { | 1191 | } else { |
1130 | $retval = "$retval\$\{$var\}"; | 1192 | $retval = "$retval\$\{$var\}"; |
1131 | } | 1193 | } |
@@ -1140,6 +1202,33 @@ sub __eval_option { | |||
1140 | return $retval; | 1202 | return $retval; |
1141 | } | 1203 | } |
1142 | 1204 | ||
1205 | sub process_evals { | ||
1206 | my ($name, $option, $i) = @_; | ||
1207 | |||
1208 | my $option_name = "$name\[$i\]"; | ||
1209 | my $ev; | ||
1210 | |||
1211 | my $old_option = $option; | ||
1212 | |||
1213 | if (defined($evals{$option_name})) { | ||
1214 | $ev = $evals{$option_name}; | ||
1215 | } elsif (defined($evals{$name})) { | ||
1216 | $ev = $evals{$name}; | ||
1217 | } else { | ||
1218 | return $option; | ||
1219 | } | ||
1220 | |||
1221 | for my $e (@{$ev}) { | ||
1222 | eval "\$option =~ $e"; | ||
1223 | } | ||
1224 | |||
1225 | if ($option ne $old_option) { | ||
1226 | doprint("$name changed from '$old_option' to '$option'\n"); | ||
1227 | } | ||
1228 | |||
1229 | return $option; | ||
1230 | } | ||
1231 | |||
1143 | sub eval_option { | 1232 | sub eval_option { |
1144 | my ($name, $option, $i) = @_; | 1233 | my ($name, $option, $i) = @_; |
1145 | 1234 | ||
@@ -1160,28 +1249,9 @@ sub eval_option { | |||
1160 | $option = __eval_option($name, $option, $i); | 1249 | $option = __eval_option($name, $option, $i); |
1161 | } | 1250 | } |
1162 | 1251 | ||
1163 | return $option; | 1252 | $option = process_evals($name, $option, $i); |
1164 | } | ||
1165 | 1253 | ||
1166 | sub _logit { | 1254 | return $option; |
1167 | if (defined($opt{"LOG_FILE"})) { | ||
1168 | open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; | ||
1169 | print OUT @_; | ||
1170 | close(OUT); | ||
1171 | } | ||
1172 | } | ||
1173 | |||
1174 | sub logit { | ||
1175 | if (defined($opt{"LOG_FILE"})) { | ||
1176 | _logit @_; | ||
1177 | } else { | ||
1178 | print @_; | ||
1179 | } | ||
1180 | } | ||
1181 | |||
1182 | sub doprint { | ||
1183 | print @_; | ||
1184 | _logit @_; | ||
1185 | } | 1255 | } |
1186 | 1256 | ||
1187 | sub run_command; | 1257 | sub run_command; |
@@ -1296,7 +1366,7 @@ sub close_console { | |||
1296 | my ($fp, $pid) = @_; | 1366 | my ($fp, $pid) = @_; |
1297 | 1367 | ||
1298 | doprint "kill child process $pid\n"; | 1368 | doprint "kill child process $pid\n"; |
1299 | kill 2, $pid; | 1369 | kill $close_console_signal, $pid; |
1300 | 1370 | ||
1301 | print "closing!\n"; | 1371 | print "closing!\n"; |
1302 | close($fp); | 1372 | close($fp); |
@@ -2517,12 +2587,29 @@ sub run_bisect { | |||
2517 | $buildtype = "useconfig:$minconfig"; | 2587 | $buildtype = "useconfig:$minconfig"; |
2518 | } | 2588 | } |
2519 | 2589 | ||
2520 | my $ret = run_bisect_test $type, $buildtype; | 2590 | # If the user sets bisect_tries to less than 1, then no tries |
2591 | # is a success. | ||
2592 | my $ret = 1; | ||
2521 | 2593 | ||
2522 | if ($bisect_manual) { | 2594 | # Still let the user manually decide that though. |
2595 | if ($bisect_tries < 1 && $bisect_manual) { | ||
2523 | $ret = answer_bisect; | 2596 | $ret = answer_bisect; |
2524 | } | 2597 | } |
2525 | 2598 | ||
2599 | for (my $i = 0; $i < $bisect_tries; $i++) { | ||
2600 | if ($bisect_tries > 1) { | ||
2601 | my $t = $i + 1; | ||
2602 | doprint("Running bisect trial $t of $bisect_tries:\n"); | ||
2603 | } | ||
2604 | $ret = run_bisect_test $type, $buildtype; | ||
2605 | |||
2606 | if ($bisect_manual) { | ||
2607 | $ret = answer_bisect; | ||
2608 | } | ||
2609 | |||
2610 | last if (!$ret); | ||
2611 | } | ||
2612 | |||
2526 | # Are we looking for where it worked, not failed? | 2613 | # Are we looking for where it worked, not failed? |
2527 | if ($reverse_bisect && $ret >= 0) { | 2614 | if ($reverse_bisect && $ret >= 0) { |
2528 | $ret = !$ret; | 2615 | $ret = !$ret; |
@@ -3916,6 +4003,18 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { | |||
3916 | 4003 | ||
3917 | my $makecmd = set_test_option("MAKE_CMD", $i); | 4004 | my $makecmd = set_test_option("MAKE_CMD", $i); |
3918 | 4005 | ||
4006 | $outputdir = set_test_option("OUTPUT_DIR", $i); | ||
4007 | $builddir = set_test_option("BUILD_DIR", $i); | ||
4008 | |||
4009 | chdir $builddir || die "can't change directory to $builddir"; | ||
4010 | |||
4011 | if (!-d $outputdir) { | ||
4012 | mkpath($outputdir) or | ||
4013 | die "can't create $outputdir"; | ||
4014 | } | ||
4015 | |||
4016 | $make = "$makecmd O=$outputdir"; | ||
4017 | |||
3919 | # Load all the options into their mapped variable names | 4018 | # Load all the options into their mapped variable names |
3920 | foreach my $opt (keys %option_map) { | 4019 | foreach my $opt (keys %option_map) { |
3921 | ${$option_map{$opt}} = set_test_option($opt, $i); | 4020 | ${$option_map{$opt}} = set_test_option($opt, $i); |
@@ -3940,13 +4039,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { | |||
3940 | $start_minconfig = $minconfig; | 4039 | $start_minconfig = $minconfig; |
3941 | } | 4040 | } |
3942 | 4041 | ||
3943 | chdir $builddir || die "can't change directory to $builddir"; | 4042 | if (!-d $tmpdir) { |
3944 | 4043 | mkpath($tmpdir) or | |
3945 | foreach my $dir ($tmpdir, $outputdir) { | 4044 | die "can't create $tmpdir"; |
3946 | if (!-d $dir) { | ||
3947 | mkpath($dir) or | ||
3948 | die "can't create $dir"; | ||
3949 | } | ||
3950 | } | 4045 | } |
3951 | 4046 | ||
3952 | $ENV{"SSH_USER"} = $ssh_user; | 4047 | $ENV{"SSH_USER"} = $ssh_user; |
@@ -3955,7 +4050,6 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { | |||
3955 | $buildlog = "$tmpdir/buildlog-$machine"; | 4050 | $buildlog = "$tmpdir/buildlog-$machine"; |
3956 | $testlog = "$tmpdir/testlog-$machine"; | 4051 | $testlog = "$tmpdir/testlog-$machine"; |
3957 | $dmesg = "$tmpdir/dmesg-$machine"; | 4052 | $dmesg = "$tmpdir/dmesg-$machine"; |
3958 | $make = "$makecmd O=$outputdir"; | ||
3959 | $output_config = "$outputdir/.config"; | 4053 | $output_config = "$outputdir/.config"; |
3960 | 4054 | ||
3961 | if (!$buildonly) { | 4055 | if (!$buildonly) { |
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 0a290fb4cd5e..172eec4517fb 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf | |||
@@ -328,6 +328,13 @@ | |||
328 | # For a virtual machine with guest name "Guest". | 328 | # For a virtual machine with guest name "Guest". |
329 | #CONSOLE = virsh console Guest | 329 | #CONSOLE = virsh console Guest |
330 | 330 | ||
331 | # Signal to send to kill console. | ||
332 | # ktest.pl will create a child process to monitor the console. | ||
333 | # When the console is finished, ktest will kill the child process | ||
334 | # with this signal. | ||
335 | # (default INT) | ||
336 | #CLOSE_CONSOLE_SIGNAL = HUP | ||
337 | |||
331 | # Required version ending to differentiate the test | 338 | # Required version ending to differentiate the test |
332 | # from other linux builds on the system. | 339 | # from other linux builds on the system. |
333 | #LOCALVERSION = -test | 340 | #LOCALVERSION = -test |
@@ -1021,6 +1028,20 @@ | |||
1021 | # BISECT_BAD with BISECT_CHECK = good or | 1028 | # BISECT_BAD with BISECT_CHECK = good or |
1022 | # BISECT_CHECK = bad, respectively. | 1029 | # BISECT_CHECK = bad, respectively. |
1023 | # | 1030 | # |
1031 | # BISECT_TRIES = 5 (optional, default 1) | ||
1032 | # | ||
1033 | # For those cases that it takes several tries to hit a bug, | ||
1034 | # the BISECT_TRIES is useful. It is the number of times the | ||
1035 | # test is ran before it says the kernel is good. The first failure | ||
1036 | # will stop trying and mark the current SHA1 as bad. | ||
1037 | # | ||
1038 | # Note, as with all race bugs, there's no guarantee that if | ||
1039 | # it succeeds, it is really a good bisect. But it helps in case | ||
1040 | # the bug is some what reliable. | ||
1041 | # | ||
1042 | # You can set BISECT_TRIES to zero, and all tests will be considered | ||
1043 | # good, unless you also set BISECT_MANUAL. | ||
1044 | # | ||
1024 | # BISECT_RET_GOOD = 0 (optional, default undefined) | 1045 | # BISECT_RET_GOOD = 0 (optional, default undefined) |
1025 | # | 1046 | # |
1026 | # In case the specificed test returns something other than just | 1047 | # In case the specificed test returns something other than just |
diff --git a/tools/testing/selftests/rcutorture/.gitignore b/tools/testing/selftests/rcutorture/.gitignore new file mode 100644 index 000000000000..05838f6f2ebe --- /dev/null +++ b/tools/testing/selftests/rcutorture/.gitignore | |||
@@ -0,0 +1,6 @@ | |||
1 | initrd | ||
2 | linux-2.6 | ||
3 | b[0-9]* | ||
4 | rcu-test-image | ||
5 | res | ||
6 | *.swp | ||
diff --git a/tools/testing/selftests/rcutorture/bin/config2frag.sh b/tools/testing/selftests/rcutorture/bin/config2frag.sh new file mode 100644 index 000000000000..9f9ffcd427d3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/config2frag.sh | |||
@@ -0,0 +1,25 @@ | |||
1 | #!/bin/sh | ||
2 | # Usage: sh config2frag.sh < .config > configfrag | ||
3 | # | ||
4 | # Converts the "# CONFIG_XXX is not set" to "CONFIG_XXX=n" so that the | ||
5 | # resulting file becomes a legitimate Kconfig fragment. | ||
6 | # | ||
7 | # This program is free software; you can redistribute it and/or modify | ||
8 | # it under the terms of the GNU General Public License as published by | ||
9 | # the Free Software Foundation; either version 2 of the License, or | ||
10 | # (at your option) any later version. | ||
11 | # | ||
12 | # This program is distributed in the hope that it will be useful, | ||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | # GNU General Public License for more details. | ||
16 | # | ||
17 | # You should have received a copy of the GNU General Public License | ||
18 | # along with this program; if not, you can access it online at | ||
19 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
20 | # | ||
21 | # Copyright (C) IBM Corporation, 2013 | ||
22 | # | ||
23 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
24 | |||
25 | LANG=C sed -e 's/^# CONFIG_\([a-zA-Z0-9_]*\) is not set$/CONFIG_\1=n/' | ||
diff --git a/tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh b/tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh new file mode 100755 index 000000000000..43540f1828cc --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh | |||
@@ -0,0 +1,45 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Extract the number of CPUs expected from the specified Kconfig-file | ||
4 | # fragment by checking CONFIG_SMP and CONFIG_NR_CPUS. If the specified | ||
5 | # file gives no clue, base the number on the number of idle CPUs on | ||
6 | # the system. | ||
7 | # | ||
8 | # Usage: configNR_CPUS.sh config-frag | ||
9 | # | ||
10 | # This program is free software; you can redistribute it and/or modify | ||
11 | # it under the terms of the GNU General Public License as published by | ||
12 | # the Free Software Foundation; either version 2 of the License, or | ||
13 | # (at your option) any later version. | ||
14 | # | ||
15 | # This program is distributed in the hope that it will be useful, | ||
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | # GNU General Public License for more details. | ||
19 | # | ||
20 | # You should have received a copy of the GNU General Public License | ||
21 | # along with this program; if not, you can access it online at | ||
22 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
23 | # | ||
24 | # Copyright (C) IBM Corporation, 2013 | ||
25 | # | ||
26 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
27 | |||
28 | cf=$1 | ||
29 | if test ! -r $cf | ||
30 | then | ||
31 | echo Unreadable config fragment $cf 1>&2 | ||
32 | exit -1 | ||
33 | fi | ||
34 | if grep -q '^CONFIG_SMP=n$' $cf | ||
35 | then | ||
36 | echo 1 | ||
37 | exit 0 | ||
38 | fi | ||
39 | if grep -q '^CONFIG_NR_CPUS=' $cf | ||
40 | then | ||
41 | grep '^CONFIG_NR_CPUS=' $cf | | ||
42 | sed -e 's/^CONFIG_NR_CPUS=\([0-9]*\).*$/\1/' | ||
43 | exit 0 | ||
44 | fi | ||
45 | cpus2use.sh | ||
diff --git a/tools/testing/selftests/rcutorture/bin/configcheck.sh b/tools/testing/selftests/rcutorture/bin/configcheck.sh new file mode 100755 index 000000000000..d686537dd55c --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/configcheck.sh | |||
@@ -0,0 +1,54 @@ | |||
1 | #!/bin/sh | ||
2 | # Usage: sh configcheck.sh .config .config-template | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 2 of the License, or | ||
7 | # (at your option) any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program; if not, you can access it online at | ||
16 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
17 | # | ||
18 | # Copyright (C) IBM Corporation, 2011 | ||
19 | # | ||
20 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
21 | |||
22 | T=/tmp/abat-chk-config.sh.$$ | ||
23 | trap 'rm -rf $T' 0 | ||
24 | mkdir $T | ||
25 | |||
26 | cat $1 > $T/.config | ||
27 | |||
28 | cat $2 | sed -e 's/\(.*\)=n/# \1 is not set/' -e 's/^#CHECK#//' | | ||
29 | awk ' | ||
30 | BEGIN { | ||
31 | print "if grep -q \"" $0 "\" < '"$T/.config"'"; | ||
32 | print "then"; | ||
33 | print "\t:"; | ||
34 | print "else"; | ||
35 | if ($1 == "#") { | ||
36 | print "\tif grep -q \"" $2 "\" < '"$T/.config"'"; | ||
37 | print "\tthen"; | ||
38 | print "\t\tif test \"$firsttime\" = \"\"" | ||
39 | print "\t\tthen" | ||
40 | print "\t\t\tfirsttime=1" | ||
41 | print "\t\tfi" | ||
42 | print "\t\techo \":" $2 ": improperly set\""; | ||
43 | print "\telse"; | ||
44 | print "\t\t:"; | ||
45 | print "\tfi"; | ||
46 | } else { | ||
47 | print "\tif test \"$firsttime\" = \"\"" | ||
48 | print "\tthen" | ||
49 | print "\t\tfirsttime=1" | ||
50 | print "\tfi" | ||
51 | print "\techo \":" $0 ": improperly set\""; | ||
52 | } | ||
53 | print "fi"; | ||
54 | }' | sh | ||
diff --git a/tools/testing/selftests/rcutorture/bin/configinit.sh b/tools/testing/selftests/rcutorture/bin/configinit.sh new file mode 100755 index 000000000000..a1be6e62add1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/configinit.sh | |||
@@ -0,0 +1,74 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # sh configinit.sh config-spec-file [ build output dir ] | ||
4 | # | ||
5 | # Create a .config file from the spec file. Run from the kernel source tree. | ||
6 | # Exits with 0 if all went well, with 1 if all went well but the config | ||
7 | # did not match, and some other number for other failures. | ||
8 | # | ||
9 | # The first argument is the .config specification file, which contains | ||
10 | # desired settings, for example, "CONFIG_NO_HZ=y". For best results, | ||
11 | # this should be a full pathname. | ||
12 | # | ||
13 | # The second argument is a optional path to a build output directory, | ||
14 | # for example, "O=/tmp/foo". If this argument is omitted, the .config | ||
15 | # file will be generated directly in the current directory. | ||
16 | # | ||
17 | # This program is free software; you can redistribute it and/or modify | ||
18 | # it under the terms of the GNU General Public License as published by | ||
19 | # the Free Software Foundation; either version 2 of the License, or | ||
20 | # (at your option) any later version. | ||
21 | # | ||
22 | # This program is distributed in the hope that it will be useful, | ||
23 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | # GNU General Public License for more details. | ||
26 | # | ||
27 | # You should have received a copy of the GNU General Public License | ||
28 | # along with this program; if not, you can access it online at | ||
29 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
30 | # | ||
31 | # Copyright (C) IBM Corporation, 2013 | ||
32 | # | ||
33 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
34 | |||
35 | T=/tmp/configinit.sh.$$ | ||
36 | trap 'rm -rf $T' 0 | ||
37 | mkdir $T | ||
38 | |||
39 | # Capture config spec file. | ||
40 | |||
41 | c=$1 | ||
42 | buildloc=$2 | ||
43 | builddir= | ||
44 | if test -n $buildloc | ||
45 | then | ||
46 | if echo $buildloc | grep -q '^O=' | ||
47 | then | ||
48 | builddir=`echo $buildloc | sed -e 's/^O=//'` | ||
49 | if test ! -d $builddir | ||
50 | then | ||
51 | mkdir $builddir | ||
52 | fi | ||
53 | else | ||
54 | echo Bad build directory: \"$builddir\" | ||
55 | exit 2 | ||
56 | fi | ||
57 | fi | ||
58 | |||
59 | sed -e 's/^\(CONFIG[0-9A-Z_]*\)=.*$/grep -v "^# \1" |/' < $c > $T/u.sh | ||
60 | sed -e 's/^\(CONFIG[0-9A-Z_]*=\).*$/grep -v \1 |/' < $c >> $T/u.sh | ||
61 | grep '^grep' < $T/u.sh > $T/upd.sh | ||
62 | echo "cat - $c" >> $T/upd.sh | ||
63 | make mrproper | ||
64 | make $buildloc distclean > $builddir/Make.distclean 2>&1 | ||
65 | make $buildloc defconfig > $builddir/Make.defconfig.out 2>&1 | ||
66 | mv $builddir/.config $builddir/.config.sav | ||
67 | sh $T/upd.sh < $builddir/.config.sav > $builddir/.config | ||
68 | cp $builddir/.config $builddir/.config.new | ||
69 | yes '' | make $buildloc oldconfig > $builddir/Make.modconfig.out 2>&1 | ||
70 | |||
71 | # verify new config matches specification. | ||
72 | configcheck.sh $builddir/.config $c | ||
73 | |||
74 | exit 0 | ||
diff --git a/tools/testing/selftests/rcutorture/bin/cpus2use.sh b/tools/testing/selftests/rcutorture/bin/cpus2use.sh new file mode 100755 index 000000000000..abe14b7f36e9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/cpus2use.sh | |||
@@ -0,0 +1,41 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Get an estimate of how CPU-hoggy to be. | ||
4 | # | ||
5 | # Usage: cpus2use.sh | ||
6 | # | ||
7 | # This program is free software; you can redistribute it and/or modify | ||
8 | # it under the terms of the GNU General Public License as published by | ||
9 | # the Free Software Foundation; either version 2 of the License, or | ||
10 | # (at your option) any later version. | ||
11 | # | ||
12 | # This program is distributed in the hope that it will be useful, | ||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | # GNU General Public License for more details. | ||
16 | # | ||
17 | # You should have received a copy of the GNU General Public License | ||
18 | # along with this program; if not, you can access it online at | ||
19 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
20 | # | ||
21 | # Copyright (C) IBM Corporation, 2013 | ||
22 | # | ||
23 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
24 | |||
25 | ncpus=`grep '^processor' /proc/cpuinfo | wc -l` | ||
26 | idlecpus=`mpstat | tail -1 | \ | ||
27 | awk -v ncpus=$ncpus '{ print ncpus * ($7 + $12) / 100 }'` | ||
28 | awk -v ncpus=$ncpus -v idlecpus=$idlecpus < /dev/null ' | ||
29 | BEGIN { | ||
30 | cpus2use = idlecpus; | ||
31 | if (cpus2use < 1) | ||
32 | cpus2use = 1; | ||
33 | if (cpus2use < ncpus / 10) | ||
34 | cpus2use = ncpus / 10; | ||
35 | if (cpus2use == int(cpus2use)) | ||
36 | cpus2use = int(cpus2use) | ||
37 | else | ||
38 | cpus2use = int(cpus2use) + 1 | ||
39 | print cpus2use; | ||
40 | }' | ||
41 | |||
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh new file mode 100644 index 000000000000..587561d7c035 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/functions.sh | |||
@@ -0,0 +1,198 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Shell functions for the rest of the scripts. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, you can access it online at | ||
17 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
18 | # | ||
19 | # Copyright (C) IBM Corporation, 2013 | ||
20 | # | ||
21 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
22 | |||
23 | # bootparam_hotplug_cpu bootparam-string | ||
24 | # | ||
25 | # Returns 1 if the specified boot-parameter string tells rcutorture to | ||
26 | # test CPU-hotplug operations. | ||
27 | bootparam_hotplug_cpu () { | ||
28 | echo "$1" | grep -q "rcutorture\.onoff_" | ||
29 | } | ||
30 | |||
31 | # checkarg --argname argtype $# arg mustmatch cannotmatch | ||
32 | # | ||
33 | # Checks the specified argument "arg" against the mustmatch and cannotmatch | ||
34 | # patterns. | ||
35 | checkarg () { | ||
36 | if test $3 -le 1 | ||
37 | then | ||
38 | echo $1 needs argument $2 matching \"$5\" | ||
39 | usage | ||
40 | fi | ||
41 | if echo "$4" | grep -q -e "$5" | ||
42 | then | ||
43 | : | ||
44 | else | ||
45 | echo $1 $2 \"$4\" must match \"$5\" | ||
46 | usage | ||
47 | fi | ||
48 | if echo "$4" | grep -q -e "$6" | ||
49 | then | ||
50 | echo $1 $2 \"$4\" must not match \"$6\" | ||
51 | usage | ||
52 | fi | ||
53 | } | ||
54 | |||
55 | # configfrag_boot_params bootparam-string config-fragment-file | ||
56 | # | ||
57 | # Adds boot parameters from the .boot file, if any. | ||
58 | configfrag_boot_params () { | ||
59 | if test -r "$2.boot" | ||
60 | then | ||
61 | echo $1 `grep -v '^#' "$2.boot" | tr '\012' ' '` | ||
62 | else | ||
63 | echo $1 | ||
64 | fi | ||
65 | } | ||
66 | |||
67 | # configfrag_hotplug_cpu config-fragment-file | ||
68 | # | ||
69 | # Returns 1 if the config fragment specifies hotplug CPU. | ||
70 | configfrag_hotplug_cpu () { | ||
71 | if test ! -r "$1" | ||
72 | then | ||
73 | echo Unreadable config fragment "$1" 1>&2 | ||
74 | exit -1 | ||
75 | fi | ||
76 | grep -q '^CONFIG_HOTPLUG_CPU=y$' "$1" | ||
77 | } | ||
78 | |||
79 | # identify_qemu builddir | ||
80 | # | ||
81 | # Returns our best guess as to which qemu command is appropriate for | ||
82 | # the kernel at hand. Override with the RCU_QEMU_CMD environment variable. | ||
83 | identify_qemu () { | ||
84 | local u="`file "$1"`" | ||
85 | if test -n "$RCU_QEMU_CMD" | ||
86 | then | ||
87 | echo $RCU_QEMU_CMD | ||
88 | elif echo $u | grep -q x86-64 | ||
89 | then | ||
90 | echo qemu-system-x86_64 | ||
91 | elif echo $u | grep -q "Intel 80386" | ||
92 | then | ||
93 | echo qemu-system-i386 | ||
94 | elif uname -a | grep -q ppc64 | ||
95 | then | ||
96 | echo qemu-system-ppc64 | ||
97 | else | ||
98 | echo Cannot figure out what qemu command to use! 1>&2 | ||
99 | # Usually this will be one of /usr/bin/qemu-system-* | ||
100 | # Use RCU_QEMU_CMD environment variable or appropriate | ||
101 | # argument to top-level script. | ||
102 | exit 1 | ||
103 | fi | ||
104 | } | ||
105 | |||
106 | # identify_qemu_append qemu-cmd | ||
107 | # | ||
108 | # Output arguments for the qemu "-append" string based on CPU type | ||
109 | # and the RCU_QEMU_INTERACTIVE environment variable. | ||
110 | identify_qemu_append () { | ||
111 | case "$1" in | ||
112 | qemu-system-x86_64|qemu-system-i386) | ||
113 | echo noapic selinux=0 initcall_debug debug | ||
114 | ;; | ||
115 | esac | ||
116 | if test -n "$RCU_QEMU_INTERACTIVE" | ||
117 | then | ||
118 | echo root=/dev/sda | ||
119 | else | ||
120 | echo console=ttyS0 | ||
121 | fi | ||
122 | } | ||
123 | |||
124 | # identify_qemu_args qemu-cmd serial-file | ||
125 | # | ||
126 | # Output arguments for qemu arguments based on the RCU_QEMU_MAC | ||
127 | # and RCU_QEMU_INTERACTIVE environment variables. | ||
128 | identify_qemu_args () { | ||
129 | case "$1" in | ||
130 | qemu-system-x86_64|qemu-system-i386) | ||
131 | ;; | ||
132 | qemu-system-ppc64) | ||
133 | echo -enable-kvm -M pseries -cpu POWER7 -nodefaults | ||
134 | echo -device spapr-vscsi | ||
135 | if test -n "$RCU_QEMU_INTERACTIVE" -a -n "$RCU_QEMU_MAC" | ||
136 | then | ||
137 | echo -device spapr-vlan,netdev=net0,mac=$RCU_QEMU_MAC | ||
138 | echo -netdev bridge,br=br0,id=net0 | ||
139 | elif test -n "$RCU_QEMU_INTERACTIVE" | ||
140 | then | ||
141 | echo -net nic -net user | ||
142 | fi | ||
143 | ;; | ||
144 | esac | ||
145 | if test -n "$RCU_QEMU_INTERACTIVE" | ||
146 | then | ||
147 | echo -monitor stdio -serial pty -S | ||
148 | else | ||
149 | echo -serial file:$2 | ||
150 | fi | ||
151 | } | ||
152 | |||
153 | # identify_qemu_vcpus | ||
154 | # | ||
155 | # Returns the number of virtual CPUs available to the aggregate of the | ||
156 | # guest OSes. | ||
157 | identify_qemu_vcpus () { | ||
158 | lscpu | grep '^CPU(s):' | sed -e 's/CPU(s)://' | ||
159 | } | ||
160 | |||
161 | # print_bug | ||
162 | # | ||
163 | # Prints "BUG: " in red followed by remaining arguments | ||
164 | print_bug () { | ||
165 | printf '\033[031mBUG: \033[m' | ||
166 | echo $* | ||
167 | } | ||
168 | |||
169 | # print_warning | ||
170 | # | ||
171 | # Prints "WARNING: " in yellow followed by remaining arguments | ||
172 | print_warning () { | ||
173 | printf '\033[033mWARNING: \033[m' | ||
174 | echo $* | ||
175 | } | ||
176 | |||
177 | # specify_qemu_cpus qemu-cmd qemu-args #cpus | ||
178 | # | ||
179 | # Appends a string containing "-smp XXX" to qemu-args, unless the incoming | ||
180 | # qemu-args already contains "-smp". | ||
181 | specify_qemu_cpus () { | ||
182 | local nt; | ||
183 | |||
184 | if echo $2 | grep -q -e -smp | ||
185 | then | ||
186 | echo $2 | ||
187 | else | ||
188 | case "$1" in | ||
189 | qemu-system-x86_64|qemu-system-i386) | ||
190 | echo $2 -smp $3 | ||
191 | ;; | ||
192 | qemu-system-ppc64) | ||
193 | nt="`lscpu | grep '^NUMA node0' | sed -e 's/^[^,]*,\([0-9]*\),.*$/\1/'`" | ||
194 | echo $2 -smp cores=`expr \( $3 + $nt - 1 \) / $nt`,threads=$nt | ||
195 | ;; | ||
196 | esac | ||
197 | fi | ||
198 | } | ||
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-build.sh b/tools/testing/selftests/rcutorture/bin/kvm-build.sh new file mode 100755 index 000000000000..197901ec10bf --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-build.sh | |||
@@ -0,0 +1,71 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Build a kvm-ready Linux kernel from the tree in the current directory. | ||
4 | # | ||
5 | # Usage: sh kvm-build.sh config-template build-dir more-configs | ||
6 | # | ||
7 | # This program is free software; you can redistribute it and/or modify | ||
8 | # it under the terms of the GNU General Public License as published by | ||
9 | # the Free Software Foundation; either version 2 of the License, or | ||
10 | # (at your option) any later version. | ||
11 | # | ||
12 | # This program is distributed in the hope that it will be useful, | ||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | # GNU General Public License for more details. | ||
16 | # | ||
17 | # You should have received a copy of the GNU General Public License | ||
18 | # along with this program; if not, you can access it online at | ||
19 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
20 | # | ||
21 | # Copyright (C) IBM Corporation, 2011 | ||
22 | # | ||
23 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
24 | |||
25 | config_template=${1} | ||
26 | if test -z "$config_template" -o ! -f "$config_template" -o ! -r "$config_template" | ||
27 | then | ||
28 | echo "kvm-build.sh :$config_template: Not a readable file" | ||
29 | exit 1 | ||
30 | fi | ||
31 | builddir=${2} | ||
32 | if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir" | ||
33 | then | ||
34 | echo "kvm-build.sh :$builddir: Not a writable directory, cannot build into it" | ||
35 | exit 1 | ||
36 | fi | ||
37 | moreconfigs=${3} | ||
38 | if test -z "$moreconfigs" -o ! -r "$moreconfigs" | ||
39 | then | ||
40 | echo "kvm-build.sh :$moreconfigs: Not a readable file" | ||
41 | exit 1 | ||
42 | fi | ||
43 | |||
44 | T=/tmp/test-linux.sh.$$ | ||
45 | trap 'rm -rf $T' 0 | ||
46 | mkdir $T | ||
47 | |||
48 | cat ${config_template} | grep -v CONFIG_RCU_TORTURE_TEST > $T/config | ||
49 | cat << ___EOF___ >> $T/config | ||
50 | CONFIG_INITRAMFS_SOURCE="$RCU_INITRD" | ||
51 | CONFIG_VIRTIO_PCI=y | ||
52 | CONFIG_VIRTIO_CONSOLE=y | ||
53 | ___EOF___ | ||
54 | cat $moreconfigs >> $T/config | ||
55 | |||
56 | configinit.sh $T/config O=$builddir | ||
57 | retval=$? | ||
58 | if test $retval -gt 1 | ||
59 | then | ||
60 | exit 2 | ||
61 | fi | ||
62 | ncpus=`cpus2use.sh` | ||
63 | make O=$builddir -j$ncpus $RCU_KMAKE_ARG > $builddir/Make.out 2>&1 | ||
64 | retval=$? | ||
65 | if test $retval -ne 0 || grep "rcu[^/]*": < $builddir/Make.out | egrep -q "Stop|Error|error:|warning:" || egrep -q "Stop|Error|error:" < $builddir/Make.out | ||
66 | then | ||
67 | echo Kernel build error | ||
68 | egrep "Stop|Error|error:|warning:" < $builddir/Make.out | ||
69 | echo Run aborted. | ||
70 | exit 3 | ||
71 | fi | ||
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh new file mode 100755 index 000000000000..baef09f3469b --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh | |||
@@ -0,0 +1,44 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Given the results directories for previous KVM runs of rcutorture, | ||
4 | # check the build and console output for errors. Given a directory | ||
5 | # containing results directories, this recursively checks them all. | ||
6 | # | ||
7 | # Usage: sh kvm-recheck.sh resdir ... | ||
8 | # | ||
9 | # This program is free software; you can redistribute it and/or modify | ||
10 | # it under the terms of the GNU General Public License as published by | ||
11 | # the Free Software Foundation; either version 2 of the License, or | ||
12 | # (at your option) any later version. | ||
13 | # | ||
14 | # This program is distributed in the hope that it will be useful, | ||
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | # GNU General Public License for more details. | ||
18 | # | ||
19 | # You should have received a copy of the GNU General Public License | ||
20 | # along with this program; if not, you can access it online at | ||
21 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
22 | # | ||
23 | # Copyright (C) IBM Corporation, 2011 | ||
24 | # | ||
25 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
26 | |||
27 | PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH | ||
28 | for rd in "$@" | ||
29 | do | ||
30 | dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u` | ||
31 | for i in $dirs | ||
32 | do | ||
33 | configfile=`echo $i | sed -e 's/^.*\///'` | ||
34 | echo $configfile | ||
35 | configcheck.sh $i/.config $i/ConfigFragment | ||
36 | parse-build.sh $i/Make.out $configfile | ||
37 | parse-rcutorture.sh $i/console.log $configfile | ||
38 | parse-console.sh $i/console.log $configfile | ||
39 | if test -r $i/Warnings | ||
40 | then | ||
41 | cat $i/Warnings | ||
42 | fi | ||
43 | done | ||
44 | done | ||
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh new file mode 100755 index 000000000000..151b23788935 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh | |||
@@ -0,0 +1,192 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Run a kvm-based test of the specified tree on the specified configs. | ||
4 | # Fully automated run and error checking, no graphics console. | ||
5 | # | ||
6 | # Execute this in the source tree. Do not run it as a background task | ||
7 | # because qemu does not seem to like that much. | ||
8 | # | ||
9 | # Usage: sh kvm-test-1-rcu.sh config builddir resdir minutes qemu-args bootargs | ||
10 | # | ||
11 | # qemu-args defaults to "" -- you will want "-nographic" if running headless. | ||
12 | # bootargs defaults to "root=/dev/sda noapic selinux=0 console=ttyS0" | ||
13 | # "initcall_debug debug rcutorture.stat_interval=15" | ||
14 | # "rcutorture.shutdown_secs=$((minutes * 60))" | ||
15 | # "rcutorture.rcutorture_runnable=1" | ||
16 | # | ||
17 | # Anything you specify for either qemu-args or bootargs is appended to | ||
18 | # the default values. The "-smp" value is deduced from the contents of | ||
19 | # the config fragment. | ||
20 | # | ||
21 | # More sophisticated argument parsing is clearly needed. | ||
22 | # | ||
23 | # This program is free software; you can redistribute it and/or modify | ||
24 | # it under the terms of the GNU General Public License as published by | ||
25 | # the Free Software Foundation; either version 2 of the License, or | ||
26 | # (at your option) any later version. | ||
27 | # | ||
28 | # This program is distributed in the hope that it will be useful, | ||
29 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
30 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
31 | # GNU General Public License for more details. | ||
32 | # | ||
33 | # You should have received a copy of the GNU General Public License | ||
34 | # along with this program; if not, you can access it online at | ||
35 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
36 | # | ||
37 | # Copyright (C) IBM Corporation, 2011 | ||
38 | # | ||
39 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
40 | |||
41 | grace=120 | ||
42 | |||
43 | T=/tmp/kvm-test-1-rcu.sh.$$ | ||
44 | trap 'rm -rf $T' 0 | ||
45 | |||
46 | . $KVM/bin/functions.sh | ||
47 | . $KVPATH/ver_functions.sh | ||
48 | |||
49 | config_template=${1} | ||
50 | title=`echo $config_template | sed -e 's/^.*\///'` | ||
51 | builddir=${2} | ||
52 | if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir" | ||
53 | then | ||
54 | echo "kvm-test-1-rcu.sh :$builddir: Not a writable directory, cannot build into it" | ||
55 | exit 1 | ||
56 | fi | ||
57 | resdir=${3} | ||
58 | if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir" | ||
59 | then | ||
60 | echo "kvm-test-1-rcu.sh :$resdir: Not a writable directory, cannot build into it" | ||
61 | exit 1 | ||
62 | fi | ||
63 | cp $config_template $resdir/ConfigFragment | ||
64 | echo ' ---' `date`: Starting build | ||
65 | echo ' ---' Kconfig fragment at: $config_template >> $resdir/log | ||
66 | cat << '___EOF___' >> $T | ||
67 | CONFIG_RCU_TORTURE_TEST=y | ||
68 | ___EOF___ | ||
69 | # Optimizations below this point | ||
70 | # CONFIG_USB=n | ||
71 | # CONFIG_SECURITY=n | ||
72 | # CONFIG_NFS_FS=n | ||
73 | # CONFIG_SOUND=n | ||
74 | # CONFIG_INPUT_JOYSTICK=n | ||
75 | # CONFIG_INPUT_TABLET=n | ||
76 | # CONFIG_INPUT_TOUCHSCREEN=n | ||
77 | # CONFIG_INPUT_MISC=n | ||
78 | # CONFIG_INPUT_MOUSE=n | ||
79 | # # CONFIG_NET=n # disables console access, so accept the slower build. | ||
80 | # CONFIG_SCSI=n | ||
81 | # CONFIG_ATA=n | ||
82 | # CONFIG_FAT_FS=n | ||
83 | # CONFIG_MSDOS_FS=n | ||
84 | # CONFIG_VFAT_FS=n | ||
85 | # CONFIG_ISO9660_FS=n | ||
86 | # CONFIG_QUOTA=n | ||
87 | # CONFIG_HID=n | ||
88 | # CONFIG_CRYPTO=n | ||
89 | # CONFIG_PCCARD=n | ||
90 | # CONFIG_PCMCIA=n | ||
91 | # CONFIG_CARDBUS=n | ||
92 | # CONFIG_YENTA=n | ||
93 | if kvm-build.sh $config_template $builddir $T | ||
94 | then | ||
95 | cp $builddir/Make*.out $resdir | ||
96 | cp $builddir/.config $resdir | ||
97 | cp $builddir/arch/x86/boot/bzImage $resdir | ||
98 | parse-build.sh $resdir/Make.out $title | ||
99 | else | ||
100 | cp $builddir/Make*.out $resdir | ||
101 | echo Build failed, not running KVM, see $resdir. | ||
102 | exit 1 | ||
103 | fi | ||
104 | minutes=$4 | ||
105 | seconds=$(($minutes * 60)) | ||
106 | qemu_args=$5 | ||
107 | boot_args=$6 | ||
108 | |||
109 | cd $KVM | ||
110 | kstarttime=`awk 'BEGIN { print systime() }' < /dev/null` | ||
111 | echo ' ---' `date`: Starting kernel | ||
112 | |||
113 | # Determine the appropriate flavor of qemu command. | ||
114 | QEMU="`identify_qemu $builddir/vmlinux.o`" | ||
115 | |||
116 | # Generate -smp qemu argument. | ||
117 | cpu_count=`configNR_CPUS.sh $config_template` | ||
118 | vcpus=`identify_qemu_vcpus` | ||
119 | if test $cpu_count -gt $vcpus | ||
120 | then | ||
121 | echo CPU count limited from $cpu_count to $vcpus | ||
122 | touch $resdir/Warnings | ||
123 | echo CPU count limited from $cpu_count to $vcpus >> $resdir/Warnings | ||
124 | cpu_count=$vcpus | ||
125 | fi | ||
126 | qemu_args="`specify_qemu_cpus "$QEMU" "$qemu_args" "$cpu_count"`" | ||
127 | |||
128 | # Generate architecture-specific and interaction-specific qemu arguments | ||
129 | qemu_args="$qemu_args `identify_qemu_args "$QEMU" "$builddir/console.log"`" | ||
130 | |||
131 | # Generate qemu -append arguments | ||
132 | qemu_append="`identify_qemu_append "$QEMU"`" | ||
133 | |||
134 | # Pull in Kconfig-fragment boot parameters | ||
135 | boot_args="`configfrag_boot_params "$boot_args" "$config_template"`" | ||
136 | # Generate CPU-hotplug boot parameters | ||
137 | boot_args="`rcutorture_param_onoff "$boot_args" $builddir/.config`" | ||
138 | # Generate rcu_barrier() boot parameter | ||
139 | boot_args="`rcutorture_param_n_barrier_cbs "$boot_args"`" | ||
140 | # Pull in standard rcutorture boot arguments | ||
141 | boot_args="$boot_args rcutorture.stat_interval=15 rcutorture.shutdown_secs=$seconds rcutorture.rcutorture_runnable=1" | ||
142 | |||
143 | echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd | ||
144 | if test -n "$RCU_BUILDONLY" | ||
145 | then | ||
146 | echo Build-only run specified, boot/test omitted. | ||
147 | exit 0 | ||
148 | fi | ||
149 | $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append "$qemu_append $boot_args" & | ||
150 | qemu_pid=$! | ||
151 | commandcompleted=0 | ||
152 | echo Monitoring qemu job at pid $qemu_pid | ||
153 | for ((i=0;i<$seconds;i++)) | ||
154 | do | ||
155 | if kill -0 $qemu_pid > /dev/null 2>&1 | ||
156 | then | ||
157 | sleep 1 | ||
158 | else | ||
159 | commandcompleted=1 | ||
160 | kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` | ||
161 | if test $kruntime -lt $seconds | ||
162 | then | ||
163 | echo Completed in $kruntime vs. $seconds >> $resdir/Warnings 2>&1 | ||
164 | else | ||
165 | echo ' ---' `date`: Kernel done | ||
166 | fi | ||
167 | break | ||
168 | fi | ||
169 | done | ||
170 | if test $commandcompleted -eq 0 | ||
171 | then | ||
172 | echo Grace period for qemu job at pid $qemu_pid | ||
173 | for ((i=0;i<=$grace;i++)) | ||
174 | do | ||
175 | if kill -0 $qemu_pid > /dev/null 2>&1 | ||
176 | then | ||
177 | sleep 1 | ||
178 | else | ||
179 | break | ||
180 | fi | ||
181 | if test $i -eq $grace | ||
182 | then | ||
183 | kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }'` | ||
184 | echo "!!! Hang at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1 | ||
185 | kill -KILL $qemu_pid | ||
186 | fi | ||
187 | done | ||
188 | fi | ||
189 | |||
190 | cp $builddir/console.log $resdir | ||
191 | parse-rcutorture.sh $resdir/console.log $title | ||
192 | parse-console.sh $resdir/console.log $title | ||
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh new file mode 100644 index 000000000000..1b7923bf6a70 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/kvm.sh | |||
@@ -0,0 +1,210 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Run a series of 14 tests under KVM. These are not particularly | ||
4 | # well-selected or well-tuned, but are the current set. Run from the | ||
5 | # top level of the source tree. | ||
6 | # | ||
7 | # Edit the definitions below to set the locations of the various directories, | ||
8 | # as well as the test duration. | ||
9 | # | ||
10 | # Usage: sh kvm.sh [ options ] | ||
11 | # | ||
12 | # This program is free software; you can redistribute it and/or modify | ||
13 | # it under the terms of the GNU General Public License as published by | ||
14 | # the Free Software Foundation; either version 2 of the License, or | ||
15 | # (at your option) any later version. | ||
16 | # | ||
17 | # This program is distributed in the hope that it will be useful, | ||
18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | # GNU General Public License for more details. | ||
21 | # | ||
22 | # You should have received a copy of the GNU General Public License | ||
23 | # along with this program; if not, you can access it online at | ||
24 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
25 | # | ||
26 | # Copyright (C) IBM Corporation, 2011 | ||
27 | # | ||
28 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
29 | |||
30 | scriptname=$0 | ||
31 | args="$*" | ||
32 | |||
33 | dur=30 | ||
34 | KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM | ||
35 | PATH=${KVM}/bin:$PATH; export PATH | ||
36 | builddir="${KVM}/b1" | ||
37 | RCU_INITRD="$KVM/initrd"; export RCU_INITRD | ||
38 | RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG | ||
39 | resdir="" | ||
40 | configs="" | ||
41 | ds=`date +%Y.%m.%d-%H:%M:%S` | ||
42 | kversion="" | ||
43 | |||
44 | . functions.sh | ||
45 | |||
46 | usage () { | ||
47 | echo "Usage: $scriptname optional arguments:" | ||
48 | echo " --bootargs kernel-boot-arguments" | ||
49 | echo " --builddir absolute-pathname" | ||
50 | echo " --buildonly" | ||
51 | echo " --configs \"config-file list\"" | ||
52 | echo " --datestamp string" | ||
53 | echo " --duration minutes" | ||
54 | echo " --interactive" | ||
55 | echo " --kmake-arg kernel-make-arguments" | ||
56 | echo " --kversion vN.NN" | ||
57 | echo " --mac nn:nn:nn:nn:nn:nn" | ||
58 | echo " --no-initrd" | ||
59 | echo " --qemu-args qemu-system-..." | ||
60 | echo " --qemu-cmd qemu-system-..." | ||
61 | echo " --results absolute-pathname" | ||
62 | echo " --relbuilddir relative-pathname" | ||
63 | exit 1 | ||
64 | } | ||
65 | |||
66 | while test $# -gt 0 | ||
67 | do | ||
68 | case "$1" in | ||
69 | --bootargs) | ||
70 | checkarg --bootargs "(list of kernel boot arguments)" "$#" "$2" '.*' '^--' | ||
71 | RCU_BOOTARGS="$2" | ||
72 | shift | ||
73 | ;; | ||
74 | --builddir) | ||
75 | checkarg --builddir "(absolute pathname)" "$#" "$2" '^/' '^error' | ||
76 | builddir=$2 | ||
77 | gotbuilddir=1 | ||
78 | shift | ||
79 | ;; | ||
80 | --buildonly) | ||
81 | RCU_BUILDONLY=1; export RCU_BUILDONLY | ||
82 | ;; | ||
83 | --configs) | ||
84 | checkarg --configs "(list of config files)" "$#" "$2" '^[^/]*$' '^--' | ||
85 | configs="$2" | ||
86 | shift | ||
87 | ;; | ||
88 | --datestamp) | ||
89 | checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--' | ||
90 | ds=$2 | ||
91 | shift | ||
92 | ;; | ||
93 | --duration) | ||
94 | checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error' | ||
95 | dur=$2 | ||
96 | shift | ||
97 | ;; | ||
98 | --interactive) | ||
99 | RCU_QEMU_INTERACTIVE=1; export RCU_QEMU_INTERACTIVE | ||
100 | ;; | ||
101 | --kmake-arg) | ||
102 | checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$' | ||
103 | RCU_KMAKE_ARG="$2"; export RCU_KMAKE_ARG | ||
104 | shift | ||
105 | ;; | ||
106 | --kversion) | ||
107 | checkarg --kversion "(kernel version)" $# "$2" '^v[0-9.]*$' '^error' | ||
108 | kversion=$2 | ||
109 | shift | ||
110 | ;; | ||
111 | --mac) | ||
112 | checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error | ||
113 | RCU_QEMU_MAC=$2; export RCU_QEMU_MAC | ||
114 | shift | ||
115 | ;; | ||
116 | --no-initrd) | ||
117 | RCU_INITRD=""; export RCU_INITRD | ||
118 | ;; | ||
119 | --qemu-args) | ||
120 | checkarg --qemu-args "-qemu args" $# "$2" '^-' '^error' | ||
121 | RCU_QEMU_ARG="$2" | ||
122 | shift | ||
123 | ;; | ||
124 | --qemu-cmd) | ||
125 | checkarg --qemu-cmd "(qemu-system-...)" $# "$2" 'qemu-system-' '^--' | ||
126 | RCU_QEMU_CMD="$2"; export RCU_QEMU_CMD | ||
127 | shift | ||
128 | ;; | ||
129 | --relbuilddir) | ||
130 | checkarg --relbuilddir "(relative pathname)" "$#" "$2" '^[^/]*$' '^--' | ||
131 | relbuilddir=$2 | ||
132 | gotrelbuilddir=1 | ||
133 | builddir=${KVM}/${relbuilddir} | ||
134 | shift | ||
135 | ;; | ||
136 | --results) | ||
137 | checkarg --results "(absolute pathname)" "$#" "$2" '^/' '^error' | ||
138 | resdir=$2 | ||
139 | shift | ||
140 | ;; | ||
141 | *) | ||
142 | echo Unknown argument $1 | ||
143 | usage | ||
144 | ;; | ||
145 | esac | ||
146 | shift | ||
147 | done | ||
148 | |||
149 | CONFIGFRAG=${KVM}/configs; export CONFIGFRAG | ||
150 | KVPATH=${CONFIGFRAG}/$kversion; export KVPATH | ||
151 | |||
152 | if test -z "$configs" | ||
153 | then | ||
154 | configs="`cat $CONFIGFRAG/$kversion/CFLIST`" | ||
155 | fi | ||
156 | |||
157 | if test -z "$resdir" | ||
158 | then | ||
159 | resdir=$KVM/res | ||
160 | if ! test -e $resdir | ||
161 | then | ||
162 | mkdir $resdir || : | ||
163 | fi | ||
164 | else | ||
165 | if ! test -e $resdir | ||
166 | then | ||
167 | mkdir -p "$resdir" || : | ||
168 | fi | ||
169 | fi | ||
170 | mkdir $resdir/$ds | ||
171 | touch $resdir/$ds/log | ||
172 | echo $scriptname $args >> $resdir/$ds/log | ||
173 | |||
174 | pwd > $resdir/$ds/testid.txt | ||
175 | if test -d .git | ||
176 | then | ||
177 | git status >> $resdir/$ds/testid.txt | ||
178 | git rev-parse HEAD >> $resdir/$ds/testid.txt | ||
179 | fi | ||
180 | builddir=$KVM/b1 | ||
181 | if ! test -e $builddir | ||
182 | then | ||
183 | mkdir $builddir || : | ||
184 | fi | ||
185 | |||
186 | for CF in $configs | ||
187 | do | ||
188 | # Running TREE01 multiple times creates TREE01, TREE01.2, TREE01.3, ... | ||
189 | rd=$resdir/$ds/$CF | ||
190 | if test -d "${rd}" | ||
191 | then | ||
192 | n="`ls -d "${rd}"* | grep '\.[0-9]\+$' | | ||
193 | sed -e 's/^.*\.\([0-9]\+\)/\1/' | | ||
194 | sort -k1n | tail -1`" | ||
195 | if test -z "$n" | ||
196 | then | ||
197 | rd="${rd}.2" | ||
198 | else | ||
199 | n="`expr $n + 1`" | ||
200 | rd="${rd}.${n}" | ||
201 | fi | ||
202 | fi | ||
203 | mkdir "${rd}" | ||
204 | echo Results directory: $rd | ||
205 | kvm-test-1-rcu.sh $CONFIGFRAG/$kversion/$CF $builddir $rd $dur "-nographic $RCU_QEMU_ARG" "rcutorture.test_no_idle_hz=1 rcutorture.verbose=1 $RCU_BOOTARGS" | ||
206 | done | ||
207 | # Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier | ||
208 | |||
209 | echo " --- `date` Test summary:" | ||
210 | kvm-recheck.sh $resdir/$ds | ||
diff --git a/tools/testing/selftests/rcutorture/bin/parse-build.sh b/tools/testing/selftests/rcutorture/bin/parse-build.sh new file mode 100755 index 000000000000..543230951c38 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/parse-build.sh | |||
@@ -0,0 +1,57 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Check the build output from an rcutorture run for goodness. | ||
4 | # The "file" is a pathname on the local system, and "title" is | ||
5 | # a text string for error-message purposes. | ||
6 | # | ||
7 | # The file must contain kernel build output. | ||
8 | # | ||
9 | # Usage: | ||
10 | # sh parse-build.sh file title | ||
11 | # | ||
12 | # This program is free software; you can redistribute it and/or modify | ||
13 | # it under the terms of the GNU General Public License as published by | ||
14 | # the Free Software Foundation; either version 2 of the License, or | ||
15 | # (at your option) any later version. | ||
16 | # | ||
17 | # This program is distributed in the hope that it will be useful, | ||
18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | # GNU General Public License for more details. | ||
21 | # | ||
22 | # You should have received a copy of the GNU General Public License | ||
23 | # along with this program; if not, you can access it online at | ||
24 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
25 | # | ||
26 | # Copyright (C) IBM Corporation, 2011 | ||
27 | # | ||
28 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
29 | |||
30 | T=$1 | ||
31 | title=$2 | ||
32 | |||
33 | . functions.sh | ||
34 | |||
35 | if grep -q CC < $T | ||
36 | then | ||
37 | : | ||
38 | else | ||
39 | print_bug $title no build | ||
40 | exit 1 | ||
41 | fi | ||
42 | |||
43 | if grep -q "error:" < $T | ||
44 | then | ||
45 | print_bug $title build errors: | ||
46 | grep "error:" < $T | ||
47 | exit 2 | ||
48 | fi | ||
49 | exit 0 | ||
50 | |||
51 | if egrep -q "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T | ||
52 | then | ||
53 | print_warning $title build errors: | ||
54 | egrep "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T | ||
55 | exit 2 | ||
56 | fi | ||
57 | exit 0 | ||
diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh new file mode 100755 index 000000000000..4185d4cab32e --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh | |||
@@ -0,0 +1,41 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Check the console output from an rcutorture run for oopses. | ||
4 | # The "file" is a pathname on the local system, and "title" is | ||
5 | # a text string for error-message purposes. | ||
6 | # | ||
7 | # Usage: | ||
8 | # sh parse-console.sh file title | ||
9 | # | ||
10 | # This program is free software; you can redistribute it and/or modify | ||
11 | # it under the terms of the GNU General Public License as published by | ||
12 | # the Free Software Foundation; either version 2 of the License, or | ||
13 | # (at your option) any later version. | ||
14 | # | ||
15 | # This program is distributed in the hope that it will be useful, | ||
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | # GNU General Public License for more details. | ||
19 | # | ||
20 | # You should have received a copy of the GNU General Public License | ||
21 | # along with this program; if not, you can access it online at | ||
22 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
23 | # | ||
24 | # Copyright (C) IBM Corporation, 2011 | ||
25 | # | ||
26 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
27 | |||
28 | T=/tmp/abat-chk-badness.sh.$$ | ||
29 | trap 'rm -f $T' 0 | ||
30 | |||
31 | file="$1" | ||
32 | title="$2" | ||
33 | |||
34 | . functions.sh | ||
35 | |||
36 | egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T | ||
37 | if test -s $T | ||
38 | then | ||
39 | print_warning Assertion failure in $file $title | ||
40 | cat $T | ||
41 | fi | ||
diff --git a/tools/testing/selftests/rcutorture/bin/parse-rcutorture.sh b/tools/testing/selftests/rcutorture/bin/parse-rcutorture.sh new file mode 100755 index 000000000000..dd0a275d9796 --- /dev/null +++ b/tools/testing/selftests/rcutorture/bin/parse-rcutorture.sh | |||
@@ -0,0 +1,106 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Check the console output from an rcutorture run for goodness. | ||
4 | # The "file" is a pathname on the local system, and "title" is | ||
5 | # a text string for error-message purposes. | ||
6 | # | ||
7 | # The file must contain rcutorture output, but can be interspersed | ||
8 | # with other dmesg text. | ||
9 | # | ||
10 | # Usage: | ||
11 | # sh parse-rcutorture.sh file title | ||
12 | # | ||
13 | # This program is free software; you can redistribute it and/or modify | ||
14 | # it under the terms of the GNU General Public License as published by | ||
15 | # the Free Software Foundation; either version 2 of the License, or | ||
16 | # (at your option) any later version. | ||
17 | # | ||
18 | # This program is distributed in the hope that it will be useful, | ||
19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | # GNU General Public License for more details. | ||
22 | # | ||
23 | # You should have received a copy of the GNU General Public License | ||
24 | # along with this program; if not, you can access it online at | ||
25 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
26 | # | ||
27 | # Copyright (C) IBM Corporation, 2011 | ||
28 | # | ||
29 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
30 | |||
31 | T=/tmp/parse-rcutorture.sh.$$ | ||
32 | file="$1" | ||
33 | title="$2" | ||
34 | |||
35 | trap 'rm -f $T.seq' 0 | ||
36 | |||
37 | . functions.sh | ||
38 | |||
39 | # check for presence of rcutorture.txt file | ||
40 | |||
41 | if test -f "$file" -a -r "$file" | ||
42 | then | ||
43 | : | ||
44 | else | ||
45 | echo $title unreadable rcutorture.txt file: $file | ||
46 | exit 1 | ||
47 | fi | ||
48 | |||
49 | # check for abject failure | ||
50 | |||
51 | if grep -q FAILURE $file || grep -q -e '-torture.*!!!' $file | ||
52 | then | ||
53 | nerrs=`grep --binary-files=text '!!!' $file | tail -1 | awk '{for (i=NF-8;i<=NF;i++) sum+=$i; } END {print sum}'` | ||
54 | print_bug $title FAILURE, $nerrs instances | ||
55 | echo " " $url | ||
56 | exit | ||
57 | fi | ||
58 | |||
59 | grep --binary-files=text 'torture:.*ver:' $file | grep --binary-files=text -v '(null)' | sed -e 's/^(initramfs)[^]]*] //' -e 's/^\[[^]]*] //' | | ||
60 | awk ' | ||
61 | BEGIN { | ||
62 | ver = 0; | ||
63 | badseq = 0; | ||
64 | } | ||
65 | |||
66 | { | ||
67 | if (!badseq && ($5 + 0 != $5 || $5 <= ver)) { | ||
68 | badseqno1 = ver; | ||
69 | badseqno2 = $5; | ||
70 | badseqnr = NR; | ||
71 | badseq = 1; | ||
72 | } | ||
73 | ver = $5 | ||
74 | } | ||
75 | |||
76 | END { | ||
77 | if (badseq) { | ||
78 | if (badseqno1 == badseqno2 && badseqno2 == ver) | ||
79 | print "RCU GP HANG at " ver " rcutorture stat " badseqnr; | ||
80 | else | ||
81 | print "BAD SEQ " badseqno1 ":" badseqno2 " last:" ver " RCU version " badseqnr; | ||
82 | } | ||
83 | }' > $T.seq | ||
84 | |||
85 | if grep -q SUCCESS $file | ||
86 | then | ||
87 | if test -s $T.seq | ||
88 | then | ||
89 | print_warning $title $title `cat $T.seq` | ||
90 | echo " " $file | ||
91 | exit 2 | ||
92 | fi | ||
93 | else | ||
94 | if grep -q RCU_HOTPLUG $file | ||
95 | then | ||
96 | print_warning HOTPLUG FAILURES $title `cat $T.seq` | ||
97 | echo " " $file | ||
98 | exit 3 | ||
99 | fi | ||
100 | echo $title no success message, `grep --binary-files=text 'ver:' $file | wc -l` successful RCU version messages | ||
101 | if test -s $T.seq | ||
102 | then | ||
103 | print_warning $title `cat $T.seq` | ||
104 | fi | ||
105 | exit 2 | ||
106 | fi | ||
diff --git a/tools/testing/selftests/rcutorture/configs/CFLIST b/tools/testing/selftests/rcutorture/configs/CFLIST new file mode 100644 index 000000000000..cd3d29cb0a47 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/CFLIST | |||
@@ -0,0 +1,13 @@ | |||
1 | TREE01 | ||
2 | TREE02 | ||
3 | TREE03 | ||
4 | TREE04 | ||
5 | TREE05 | ||
6 | TREE06 | ||
7 | TREE07 | ||
8 | TREE08 | ||
9 | TREE09 | ||
10 | SRCU-N | ||
11 | SRCU-P | ||
12 | TINY01 | ||
13 | TINY02 | ||
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-N b/tools/testing/selftests/rcutorture/configs/SRCU-N new file mode 100644 index 000000000000..10a0e27f4c75 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/SRCU-N | |||
@@ -0,0 +1,8 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_SMP=y | ||
3 | CONFIG_NR_CPUS=8 | ||
4 | CONFIG_HOTPLUG_CPU=y | ||
5 | CONFIG_PREEMPT_NONE=y | ||
6 | CONFIG_PREEMPT_VOLUNTARY=n | ||
7 | CONFIG_PREEMPT=n | ||
8 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-N.boot b/tools/testing/selftests/rcutorture/configs/SRCU-N.boot new file mode 100644 index 000000000000..238bfe3bd0cc --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/SRCU-N.boot | |||
@@ -0,0 +1 @@ | |||
rcutorture.torture_type=srcu | |||
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-P b/tools/testing/selftests/rcutorture/configs/SRCU-P new file mode 100644 index 000000000000..6650e00c6d91 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/SRCU-P | |||
@@ -0,0 +1,8 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_SMP=y | ||
3 | CONFIG_NR_CPUS=8 | ||
4 | CONFIG_HOTPLUG_CPU=y | ||
5 | CONFIG_PREEMPT_NONE=n | ||
6 | CONFIG_PREEMPT_VOLUNTARY=n | ||
7 | CONFIG_PREEMPT=y | ||
8 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-P.boot b/tools/testing/selftests/rcutorture/configs/SRCU-P.boot new file mode 100644 index 000000000000..238bfe3bd0cc --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/SRCU-P.boot | |||
@@ -0,0 +1 @@ | |||
rcutorture.torture_type=srcu | |||
diff --git a/tools/testing/selftests/rcutorture/configs/TINY01 b/tools/testing/selftests/rcutorture/configs/TINY01 new file mode 100644 index 000000000000..0c2823f21712 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TINY01 | |||
@@ -0,0 +1,13 @@ | |||
1 | CONFIG_SMP=n | ||
2 | CONFIG_PREEMPT_NONE=y | ||
3 | CONFIG_PREEMPT_VOLUNTARY=n | ||
4 | CONFIG_PREEMPT=n | ||
5 | #CHECK#CONFIG_TINY_RCU=y | ||
6 | CONFIG_HZ_PERIODIC=n | ||
7 | CONFIG_NO_HZ_IDLE=y | ||
8 | CONFIG_NO_HZ_FULL=n | ||
9 | CONFIG_RCU_TRACE=n | ||
10 | CONFIG_DEBUG_LOCK_ALLOC=n | ||
11 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
12 | CONFIG_PREEMPT_COUNT=n | ||
13 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TINY02 b/tools/testing/selftests/rcutorture/configs/TINY02 new file mode 100644 index 000000000000..e5072d7528b6 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TINY02 | |||
@@ -0,0 +1,13 @@ | |||
1 | CONFIG_SMP=n | ||
2 | CONFIG_PREEMPT_NONE=y | ||
3 | CONFIG_PREEMPT_VOLUNTARY=n | ||
4 | CONFIG_PREEMPT=n | ||
5 | #CHECK#CONFIG_TINY_RCU=y | ||
6 | CONFIG_HZ_PERIODIC=y | ||
7 | CONFIG_NO_HZ_IDLE=n | ||
8 | CONFIG_NO_HZ_FULL=n | ||
9 | CONFIG_RCU_TRACE=y | ||
10 | CONFIG_DEBUG_LOCK_ALLOC=y | ||
11 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
12 | CONFIG_PREEMPT_COUNT=y | ||
13 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE01 b/tools/testing/selftests/rcutorture/configs/TREE01 new file mode 100644 index 000000000000..141119a00044 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE01 | |||
@@ -0,0 +1,23 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=8 | ||
3 | CONFIG_PREEMPT_NONE=n | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=y | ||
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=y | ||
9 | CONFIG_NO_HZ_FULL=n | ||
10 | CONFIG_RCU_FAST_NO_HZ=y | ||
11 | CONFIG_RCU_TRACE=y | ||
12 | CONFIG_HOTPLUG_CPU=y | ||
13 | CONFIG_RCU_FANOUT=8 | ||
14 | CONFIG_RCU_FANOUT_EXACT=n | ||
15 | CONFIG_RCU_NOCB_CPU=y | ||
16 | CONFIG_RCU_NOCB_CPU_ZERO=y | ||
17 | CONFIG_DEBUG_LOCK_ALLOC=n | ||
18 | CONFIG_PROVE_RCU_DELAY=n | ||
19 | CONFIG_RCU_CPU_STALL_INFO=n | ||
20 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
21 | CONFIG_RCU_BOOST=n | ||
22 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
23 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE01.boot b/tools/testing/selftests/rcutorture/configs/TREE01.boot new file mode 100644 index 000000000000..0fc8a3428938 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE01.boot | |||
@@ -0,0 +1 @@ | |||
rcutorture.torture_type=rcu_bh | |||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE02 b/tools/testing/selftests/rcutorture/configs/TREE02 new file mode 100644 index 000000000000..2d4d09608528 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE02 | |||
@@ -0,0 +1,26 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=8 | ||
3 | CONFIG_PREEMPT_NONE=n | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=y | ||
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=y | ||
9 | CONFIG_NO_HZ_FULL=n | ||
10 | CONFIG_RCU_FAST_NO_HZ=n | ||
11 | CONFIG_RCU_TRACE=n | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | CONFIG_SUSPEND=n | ||
14 | CONFIG_HIBERNATION=n | ||
15 | CONFIG_RCU_FANOUT=3 | ||
16 | CONFIG_RCU_FANOUT_LEAF=3 | ||
17 | CONFIG_RCU_FANOUT_EXACT=n | ||
18 | CONFIG_RCU_NOCB_CPU=n | ||
19 | CONFIG_DEBUG_LOCK_ALLOC=y | ||
20 | CONFIG_PROVE_LOCKING=n | ||
21 | CONFIG_PROVE_RCU_DELAY=n | ||
22 | CONFIG_RCU_CPU_STALL_INFO=n | ||
23 | CONFIG_RCU_CPU_STALL_VERBOSE=y | ||
24 | CONFIG_RCU_BOOST=n | ||
25 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
26 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE03 b/tools/testing/selftests/rcutorture/configs/TREE03 new file mode 100644 index 000000000000..a47de5be8a04 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE03 | |||
@@ -0,0 +1,23 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=8 | ||
3 | CONFIG_PREEMPT_NONE=n | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=y | ||
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=y | ||
8 | CONFIG_NO_HZ_IDLE=n | ||
9 | CONFIG_NO_HZ_FULL=n | ||
10 | CONFIG_RCU_TRACE=y | ||
11 | CONFIG_HOTPLUG_CPU=y | ||
12 | CONFIG_RCU_FANOUT=4 | ||
13 | CONFIG_RCU_FANOUT_LEAF=4 | ||
14 | CONFIG_RCU_FANOUT_EXACT=n | ||
15 | CONFIG_RCU_NOCB_CPU=n | ||
16 | CONFIG_DEBUG_LOCK_ALLOC=n | ||
17 | CONFIG_PROVE_RCU_DELAY=n | ||
18 | CONFIG_RCU_CPU_STALL_INFO=n | ||
19 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
20 | CONFIG_RCU_BOOST=y | ||
21 | CONFIG_RCU_BOOST_PRIO=2 | ||
22 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
23 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE04 b/tools/testing/selftests/rcutorture/configs/TREE04 new file mode 100644 index 000000000000..8d839b86a1d5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE04 | |||
@@ -0,0 +1,25 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=8 | ||
3 | CONFIG_PREEMPT_NONE=y | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=n | ||
6 | #CHECK#CONFIG_TREE_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=n | ||
9 | CONFIG_NO_HZ_FULL=y | ||
10 | CONFIG_NO_HZ_FULL_ALL=y | ||
11 | CONFIG_RCU_FAST_NO_HZ=y | ||
12 | CONFIG_RCU_TRACE=y | ||
13 | CONFIG_HOTPLUG_CPU=n | ||
14 | CONFIG_SUSPEND=n | ||
15 | CONFIG_HIBERNATION=n | ||
16 | CONFIG_RCU_FANOUT=2 | ||
17 | CONFIG_RCU_FANOUT_LEAF=2 | ||
18 | CONFIG_RCU_FANOUT_EXACT=n | ||
19 | CONFIG_RCU_NOCB_CPU=n | ||
20 | CONFIG_DEBUG_LOCK_ALLOC=n | ||
21 | CONFIG_PROVE_RCU_DELAY=n | ||
22 | CONFIG_RCU_CPU_STALL_INFO=y | ||
23 | CONFIG_RCU_CPU_STALL_VERBOSE=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
25 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE04.boot b/tools/testing/selftests/rcutorture/configs/TREE04.boot new file mode 100644 index 000000000000..0fc8a3428938 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE04.boot | |||
@@ -0,0 +1 @@ | |||
rcutorture.torture_type=rcu_bh | |||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE05 b/tools/testing/selftests/rcutorture/configs/TREE05 new file mode 100644 index 000000000000..b5ba72ea25cb --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE05 | |||
@@ -0,0 +1,25 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=8 | ||
3 | CONFIG_PREEMPT_NONE=y | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=n | ||
6 | #CHECK#CONFIG_TREE_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=y | ||
9 | CONFIG_NO_HZ_FULL=n | ||
10 | CONFIG_RCU_FAST_NO_HZ=n | ||
11 | CONFIG_RCU_TRACE=n | ||
12 | CONFIG_HOTPLUG_CPU=y | ||
13 | CONFIG_RCU_FANOUT=6 | ||
14 | CONFIG_RCU_FANOUT_LEAF=6 | ||
15 | CONFIG_RCU_FANOUT_EXACT=n | ||
16 | CONFIG_RCU_NOCB_CPU=y | ||
17 | CONFIG_RCU_NOCB_CPU_NONE=y | ||
18 | CONFIG_DEBUG_LOCK_ALLOC=y | ||
19 | CONFIG_PROVE_LOCKING=y | ||
20 | CONFIG_PROVE_RCU=y | ||
21 | CONFIG_PROVE_RCU_DELAY=y | ||
22 | CONFIG_RCU_CPU_STALL_INFO=n | ||
23 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
25 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE05.boot b/tools/testing/selftests/rcutorture/configs/TREE05.boot new file mode 100644 index 000000000000..3b42b8b033cd --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE05.boot | |||
@@ -0,0 +1 @@ | |||
rcutorture.torture_type=sched | |||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE06 b/tools/testing/selftests/rcutorture/configs/TREE06 new file mode 100644 index 000000000000..7c95ab48d29f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE06 | |||
@@ -0,0 +1,26 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=8 | ||
3 | CONFIG_PREEMPT_NONE=y | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=n | ||
6 | #CHECK#CONFIG_TREE_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=y | ||
9 | CONFIG_NO_HZ_FULL=n | ||
10 | CONFIG_RCU_FAST_NO_HZ=n | ||
11 | CONFIG_RCU_TRACE=n | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | CONFIG_SUSPEND=n | ||
14 | CONFIG_HIBERNATION=n | ||
15 | CONFIG_RCU_FANOUT=6 | ||
16 | CONFIG_RCU_FANOUT_LEAF=6 | ||
17 | CONFIG_RCU_FANOUT_EXACT=y | ||
18 | CONFIG_RCU_NOCB_CPU=n | ||
19 | CONFIG_DEBUG_LOCK_ALLOC=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_PROVE_RCU_DELAY=n | ||
23 | CONFIG_RCU_CPU_STALL_INFO=n | ||
24 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
25 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
26 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE07 b/tools/testing/selftests/rcutorture/configs/TREE07 new file mode 100644 index 000000000000..1467404bdec1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE07 | |||
@@ -0,0 +1,24 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=16 | ||
3 | CONFIG_PREEMPT_NONE=y | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=n | ||
6 | #CHECK#CONFIG_TREE_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=n | ||
9 | CONFIG_NO_HZ_FULL=y | ||
10 | CONFIG_NO_HZ_FULL_ALL=y | ||
11 | CONFIG_NO_HZ_FULL_SYSIDLE=y | ||
12 | CONFIG_RCU_FAST_NO_HZ=n | ||
13 | CONFIG_RCU_TRACE=y | ||
14 | CONFIG_HOTPLUG_CPU=y | ||
15 | CONFIG_RCU_FANOUT=2 | ||
16 | CONFIG_RCU_FANOUT_LEAF=2 | ||
17 | CONFIG_RCU_FANOUT_EXACT=n | ||
18 | CONFIG_RCU_NOCB_CPU=n | ||
19 | CONFIG_DEBUG_LOCK_ALLOC=n | ||
20 | CONFIG_PROVE_RCU_DELAY=n | ||
21 | CONFIG_RCU_CPU_STALL_INFO=y | ||
22 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
23 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
24 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE08 b/tools/testing/selftests/rcutorture/configs/TREE08 new file mode 100644 index 000000000000..7d097a61ac2a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE08 | |||
@@ -0,0 +1,26 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=16 | ||
3 | CONFIG_PREEMPT_NONE=n | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=y | ||
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=y | ||
9 | CONFIG_NO_HZ_FULL=n | ||
10 | CONFIG_RCU_FAST_NO_HZ=n | ||
11 | CONFIG_RCU_TRACE=n | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | CONFIG_SUSPEND=n | ||
14 | CONFIG_HIBERNATION=n | ||
15 | CONFIG_RCU_FANOUT=3 | ||
16 | CONFIG_RCU_FANOUT_EXACT=y | ||
17 | CONFIG_RCU_FANOUT_LEAF=2 | ||
18 | CONFIG_RCU_NOCB_CPU=y | ||
19 | CONFIG_RCU_NOCB_CPU_ALL=y | ||
20 | CONFIG_DEBUG_LOCK_ALLOC=n | ||
21 | CONFIG_PROVE_RCU_DELAY=n | ||
22 | CONFIG_RCU_CPU_STALL_INFO=n | ||
23 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
24 | CONFIG_RCU_BOOST=n | ||
25 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
26 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE08-T b/tools/testing/selftests/rcutorture/configs/TREE08-T new file mode 100644 index 000000000000..442c4e450ab3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE08-T | |||
@@ -0,0 +1,26 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=16 | ||
3 | CONFIG_PREEMPT_NONE=n | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=y | ||
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=y | ||
9 | CONFIG_NO_HZ_FULL=n | ||
10 | CONFIG_RCU_FAST_NO_HZ=n | ||
11 | CONFIG_RCU_TRACE=y | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | CONFIG_SUSPEND=n | ||
14 | CONFIG_HIBERNATION=n | ||
15 | CONFIG_RCU_FANOUT=3 | ||
16 | CONFIG_RCU_FANOUT_EXACT=y | ||
17 | CONFIG_RCU_FANOUT_LEAF=2 | ||
18 | CONFIG_RCU_NOCB_CPU=y | ||
19 | CONFIG_RCU_NOCB_CPU_ALL=y | ||
20 | CONFIG_DEBUG_LOCK_ALLOC=n | ||
21 | CONFIG_PROVE_RCU_DELAY=n | ||
22 | CONFIG_RCU_CPU_STALL_INFO=n | ||
23 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
24 | CONFIG_RCU_BOOST=n | ||
25 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
26 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/TREE09 b/tools/testing/selftests/rcutorture/configs/TREE09 new file mode 100644 index 000000000000..0d1ec0d3dfee --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/TREE09 | |||
@@ -0,0 +1,21 @@ | |||
1 | CONFIG_SMP=n | ||
2 | CONFIG_NR_CPUS=1 | ||
3 | CONFIG_PREEMPT_NONE=n | ||
4 | CONFIG_PREEMPT_VOLUNTARY=n | ||
5 | CONFIG_PREEMPT=y | ||
6 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
7 | CONFIG_HZ_PERIODIC=n | ||
8 | CONFIG_NO_HZ_IDLE=y | ||
9 | CONFIG_NO_HZ_FULL=n | ||
10 | CONFIG_RCU_TRACE=n | ||
11 | CONFIG_HOTPLUG_CPU=n | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_RCU_NOCB_CPU=n | ||
15 | CONFIG_DEBUG_LOCK_ALLOC=n | ||
16 | CONFIG_PROVE_RCU_DELAY=n | ||
17 | CONFIG_RCU_CPU_STALL_INFO=n | ||
18 | CONFIG_RCU_CPU_STALL_VERBOSE=n | ||
19 | CONFIG_RCU_BOOST=n | ||
20 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=n | ||
21 | CONFIG_PRINTK_TIME=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST new file mode 100644 index 000000000000..18223947bbcb --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST | |||
@@ -0,0 +1,14 @@ | |||
1 | P1-S-T-NH-SD-SMP-HP | ||
2 | P2-2-t-nh-sd-SMP-hp | ||
3 | P3-3-T-nh-SD-SMP-hp | ||
4 | P4-A-t-NH-sd-SMP-HP | ||
5 | P5-U-T-NH-sd-SMP-hp | ||
6 | N1-S-T-NH-SD-SMP-HP | ||
7 | N2-2-t-nh-sd-SMP-hp | ||
8 | N3-3-T-nh-SD-SMP-hp | ||
9 | N4-A-t-NH-sd-SMP-HP | ||
10 | N5-U-T-NH-sd-SMP-hp | ||
11 | PT1-nh | ||
12 | PT2-NH | ||
13 | NT1-nh | ||
14 | NT3-NH | ||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..d3ef873eb6e7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,18 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=8 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp new file mode 100644 index 000000000000..02e418572b1b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp new file mode 100644 index 000000000000..b3100f69c8cf --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP new file mode 100644 index 000000000000..c56b44530725 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP | |||
@@ -0,0 +1,18 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp new file mode 100644 index 000000000000..90d924fea9e9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=6 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh new file mode 100644 index 000000000000..023f312a931c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh | |||
@@ -0,0 +1,23 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TRACE=y | ||
3 | CONFIG_RCU_TORTURE_TEST=m | ||
4 | CONFIG_MODULE_UNLOAD=y | ||
5 | CONFIG_SUSPEND=n | ||
6 | CONFIG_HIBERNATION=n | ||
7 | # | ||
8 | CONFIG_SMP=n | ||
9 | # | ||
10 | CONFIG_HOTPLUG_CPU=n | ||
11 | # | ||
12 | CONFIG_NO_HZ=n | ||
13 | # | ||
14 | CONFIG_PREEMPT_NONE=y | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=n | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH new file mode 100644 index 000000000000..6fd0235dae73 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH | |||
@@ -0,0 +1,20 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=y | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=n | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..f72402d7c13d --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,19 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=8 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=n | ||
8 | CONFIG_HOTPLUG_CPU=y | ||
9 | CONFIG_PREEMPT_NONE=n | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=y | ||
12 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp new file mode 100644 index 000000000000..0f3b667d2a9f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp new file mode 100644 index 000000000000..b035e141bf2a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP new file mode 100644 index 000000000000..3ccf6a9447f5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_RT_MUTEXES=y | ||
15 | CONFIG_RCU_BOOST=y | ||
16 | CONFIG_RCU_BOOST_PRIO=2 | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp new file mode 100644 index 000000000000..ef624ce73d8e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp | |||
@@ -0,0 +1,28 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=6 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=y | ||
8 | CONFIG_HOTPLUG_CPU=n | ||
9 | CONFIG_SUSPEND=n | ||
10 | CONFIG_HIBERNATION=n | ||
11 | CONFIG_PREEMPT_NONE=n | ||
12 | CONFIG_PREEMPT_VOLUNTARY=n | ||
13 | CONFIG_PREEMPT=y | ||
14 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
15 | CONFIG_DEBUG_KERNEL=y | ||
16 | CONFIG_PROVE_RCU_DELAY=y | ||
17 | CONFIG_DEBUG_OBJECTS=y | ||
18 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
19 | CONFIG_RT_MUTEXES=y | ||
20 | CONFIG_RCU_BOOST=y | ||
21 | CONFIG_RCU_BOOST_PRIO=2 | ||
22 | CONFIG_RCU_TORTURE_TEST=m | ||
23 | CONFIG_MODULE_UNLOAD=y | ||
24 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
25 | CONFIG_IKCONFIG=y | ||
26 | CONFIG_IKCONFIG_PROC=y | ||
27 | CONFIG_PRINTK_TIME=y | ||
28 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh new file mode 100644 index 000000000000..e3361c3894a1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh | |||
@@ -0,0 +1,23 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_BOOST=y | ||
3 | CONFIG_RCU_BOOST_PRIO=2 | ||
4 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_RCU_TORTURE_TEST=m | ||
6 | CONFIG_MODULE_UNLOAD=y | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | # | ||
10 | CONFIG_SMP=n | ||
11 | # | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | # | ||
14 | CONFIG_NO_HZ=n | ||
15 | # | ||
16 | CONFIG_PREEMPT_NONE=n | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH new file mode 100644 index 000000000000..64abfc3b4d94 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=n | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh new file mode 100644 index 000000000000..e8052539af54 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh | |||
@@ -0,0 +1,35 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Kernel-version-dependent shell functions for the rest of the scripts. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, you can access it online at | ||
17 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
18 | # | ||
19 | # Copyright (C) IBM Corporation, 2013 | ||
20 | # | ||
21 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
22 | |||
23 | # rcutorture_param_n_barrier_cbs bootparam-string | ||
24 | # | ||
25 | # Adds n_barrier_cbs rcutorture module parameter to kernels having it. | ||
26 | rcutorture_param_n_barrier_cbs () { | ||
27 | echo $1 | ||
28 | } | ||
29 | |||
30 | # rcutorture_param_onoff bootparam-string config-file | ||
31 | # | ||
32 | # Adds onoff rcutorture module parameters to kernels having it. | ||
33 | rcutorture_param_onoff () { | ||
34 | echo $1 | ||
35 | } | ||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST new file mode 100644 index 000000000000..da4cbc668f2a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST | |||
@@ -0,0 +1,17 @@ | |||
1 | sysidleY.2013.06.19a | ||
2 | sysidleN.2013.06.19a | ||
3 | P1-S-T-NH-SD-SMP-HP | ||
4 | P2-2-t-nh-sd-SMP-hp | ||
5 | P3-3-T-nh-SD-SMP-hp | ||
6 | P4-A-t-NH-sd-SMP-HP | ||
7 | P5-U-T-NH-sd-SMP-hp | ||
8 | P6---t-nh-SD-smp-hp | ||
9 | N1-S-T-NH-SD-SMP-HP | ||
10 | N2-2-t-nh-sd-SMP-hp | ||
11 | N3-3-T-nh-SD-SMP-hp | ||
12 | N4-A-t-NH-sd-SMP-HP | ||
13 | N5-U-T-NH-sd-SMP-hp | ||
14 | PT1-nh | ||
15 | PT2-NH | ||
16 | NT1-nh | ||
17 | NT3-NH | ||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..d81e11d280aa --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,19 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_FAST_NO_HZ=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=8 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=n | ||
8 | CONFIG_HOTPLUG_CPU=y | ||
9 | CONFIG_PREEMPT_NONE=y | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=n | ||
12 | #CHECK#CONFIG_TREE_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp new file mode 100644 index 000000000000..02e418572b1b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp new file mode 100644 index 000000000000..b3100f69c8cf --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP new file mode 100644 index 000000000000..c56b44530725 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP | |||
@@ -0,0 +1,18 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp new file mode 100644 index 000000000000..90d924fea9e9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=6 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp new file mode 100644 index 000000000000..0ccc36d72738 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp | |||
@@ -0,0 +1,19 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_NR_CPUS=1 | ||
5 | CONFIG_RCU_FANOUT_EXACT=n | ||
6 | CONFIG_HOTPLUG_CPU=n | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | CONFIG_PREEMPT_NONE=y | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=n | ||
12 | #CHECK#CONFIG_TREE_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..3f640cf84973 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,26 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=2 | ||
7 | CONFIG_NR_CPUS=16 | ||
8 | CONFIG_RCU_FANOUT_EXACT=n | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_RCU_NOCB_CPU=y | ||
11 | CONFIG_RCU_NOCB_CPU_NONE=y | ||
12 | CONFIG_RCU_NOCB_CPU_ZERO=n | ||
13 | CONFIG_RCU_NOCB_CPU_ALL=n | ||
14 | CONFIG_SUSPEND=n | ||
15 | CONFIG_HIBERNATION=n | ||
16 | CONFIG_PREEMPT_NONE=y | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=n | ||
19 | #CHECK#CONFIG_TREE_RCU=y | ||
20 | CONFIG_RCU_TORTURE_TEST=m | ||
21 | CONFIG_MODULE_UNLOAD=y | ||
22 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
23 | CONFIG_IKCONFIG=y | ||
24 | CONFIG_IKCONFIG_PROC=y | ||
25 | CONFIG_PRINTK_TIME=y | ||
26 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..285da2dd8ac3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=14 | ||
7 | CONFIG_NR_CPUS=16 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh new file mode 100644 index 000000000000..023f312a931c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh | |||
@@ -0,0 +1,23 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TRACE=y | ||
3 | CONFIG_RCU_TORTURE_TEST=m | ||
4 | CONFIG_MODULE_UNLOAD=y | ||
5 | CONFIG_SUSPEND=n | ||
6 | CONFIG_HIBERNATION=n | ||
7 | # | ||
8 | CONFIG_SMP=n | ||
9 | # | ||
10 | CONFIG_HOTPLUG_CPU=n | ||
11 | # | ||
12 | CONFIG_NO_HZ=n | ||
13 | # | ||
14 | CONFIG_PREEMPT_NONE=y | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=n | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH new file mode 100644 index 000000000000..6fd0235dae73 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH | |||
@@ -0,0 +1,20 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=y | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=n | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..9647c44cf4b7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_RCU_FAST_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=8 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=n | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp new file mode 100644 index 000000000000..0f3b667d2a9f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp new file mode 100644 index 000000000000..b035e141bf2a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP new file mode 100644 index 000000000000..3ccf6a9447f5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_RT_MUTEXES=y | ||
15 | CONFIG_RCU_BOOST=y | ||
16 | CONFIG_RCU_BOOST_PRIO=2 | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp new file mode 100644 index 000000000000..ef624ce73d8e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp | |||
@@ -0,0 +1,28 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=6 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=y | ||
8 | CONFIG_HOTPLUG_CPU=n | ||
9 | CONFIG_SUSPEND=n | ||
10 | CONFIG_HIBERNATION=n | ||
11 | CONFIG_PREEMPT_NONE=n | ||
12 | CONFIG_PREEMPT_VOLUNTARY=n | ||
13 | CONFIG_PREEMPT=y | ||
14 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
15 | CONFIG_DEBUG_KERNEL=y | ||
16 | CONFIG_PROVE_RCU_DELAY=y | ||
17 | CONFIG_DEBUG_OBJECTS=y | ||
18 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
19 | CONFIG_RT_MUTEXES=y | ||
20 | CONFIG_RCU_BOOST=y | ||
21 | CONFIG_RCU_BOOST_PRIO=2 | ||
22 | CONFIG_RCU_TORTURE_TEST=m | ||
23 | CONFIG_MODULE_UNLOAD=y | ||
24 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
25 | CONFIG_IKCONFIG=y | ||
26 | CONFIG_IKCONFIG_PROC=y | ||
27 | CONFIG_PRINTK_TIME=y | ||
28 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp new file mode 100644 index 000000000000..f4c9175828bf --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp | |||
@@ -0,0 +1,18 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=n | ||
4 | CONFIG_RCU_FANOUT_EXACT=n | ||
5 | CONFIG_HOTPLUG_CPU=n | ||
6 | CONFIG_SUSPEND=n | ||
7 | CONFIG_HIBERNATION=n | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..77a8c5b75763 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,30 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=16 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_RCU_NOCB_CPU=y | ||
9 | CONFIG_RCU_NOCB_CPU_NONE=n | ||
10 | CONFIG_RCU_NOCB_CPU_ZERO=n | ||
11 | CONFIG_RCU_NOCB_CPU_ALL=y | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_PREEMPT_NONE=n | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=y | ||
17 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
18 | CONFIG_RCU_TORTURE_TEST=m | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_DEBUG_KERNEL=y | ||
23 | CONFIG_DEBUG_OBJECTS=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
25 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
26 | CONFIG_SLUB=y | ||
27 | CONFIG_IKCONFIG=y | ||
28 | CONFIG_IKCONFIG_PROC=y | ||
29 | CONFIG_PRINTK_TIME=y | ||
30 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all new file mode 100644 index 000000000000..0eecebc6e95f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all | |||
@@ -0,0 +1,30 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=16 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_RCU_NOCB_CPU=y | ||
9 | CONFIG_RCU_NOCB_CPU_NONE=y | ||
10 | CONFIG_RCU_NOCB_CPU_ZERO=n | ||
11 | CONFIG_RCU_NOCB_CPU_ALL=n | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_PREEMPT_NONE=n | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=y | ||
17 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
18 | CONFIG_RCU_TORTURE_TEST=m | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_DEBUG_KERNEL=y | ||
23 | CONFIG_DEBUG_OBJECTS=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
25 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
26 | CONFIG_SLUB=y | ||
27 | CONFIG_IKCONFIG=y | ||
28 | CONFIG_IKCONFIG_PROC=y | ||
29 | CONFIG_PRINTK_TIME=y | ||
30 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none new file mode 100644 index 000000000000..0eecebc6e95f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none | |||
@@ -0,0 +1,30 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=16 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_RCU_NOCB_CPU=y | ||
9 | CONFIG_RCU_NOCB_CPU_NONE=y | ||
10 | CONFIG_RCU_NOCB_CPU_ZERO=n | ||
11 | CONFIG_RCU_NOCB_CPU_ALL=n | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_PREEMPT_NONE=n | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=y | ||
17 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
18 | CONFIG_RCU_TORTURE_TEST=m | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_DEBUG_KERNEL=y | ||
23 | CONFIG_DEBUG_OBJECTS=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
25 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
26 | CONFIG_SLUB=y | ||
27 | CONFIG_IKCONFIG=y | ||
28 | CONFIG_IKCONFIG_PROC=y | ||
29 | CONFIG_PRINTK_TIME=y | ||
30 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp new file mode 100644 index 000000000000..588bc70420cd --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp | |||
@@ -0,0 +1,30 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=16 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_RCU_NOCB_CPU=y | ||
9 | CONFIG_RCU_NOCB_CPU_NONE=n | ||
10 | CONFIG_RCU_NOCB_CPU_ZERO=y | ||
11 | CONFIG_RCU_NOCB_CPU_ALL=n | ||
12 | CONFIG_SUSPEND=n | ||
13 | CONFIG_HIBERNATION=n | ||
14 | CONFIG_PREEMPT_NONE=n | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=y | ||
17 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
18 | CONFIG_RCU_TORTURE_TEST=m | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_PROVE_LOCKING=y | ||
21 | CONFIG_PROVE_RCU=y | ||
22 | CONFIG_DEBUG_KERNEL=y | ||
23 | CONFIG_DEBUG_OBJECTS=y | ||
24 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
25 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
26 | CONFIG_SLUB=y | ||
27 | CONFIG_IKCONFIG=y | ||
28 | CONFIG_IKCONFIG_PROC=y | ||
29 | CONFIG_PRINTK_TIME=y | ||
30 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh new file mode 100644 index 000000000000..e3361c3894a1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh | |||
@@ -0,0 +1,23 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_BOOST=y | ||
3 | CONFIG_RCU_BOOST_PRIO=2 | ||
4 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_RCU_TORTURE_TEST=m | ||
6 | CONFIG_MODULE_UNLOAD=y | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | # | ||
10 | CONFIG_SMP=n | ||
11 | # | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | # | ||
14 | CONFIG_NO_HZ=n | ||
15 | # | ||
16 | CONFIG_PREEMPT_NONE=n | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH new file mode 100644 index 000000000000..64abfc3b4d94 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=n | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST new file mode 100644 index 000000000000..18223947bbcb --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST | |||
@@ -0,0 +1,14 @@ | |||
1 | P1-S-T-NH-SD-SMP-HP | ||
2 | P2-2-t-nh-sd-SMP-hp | ||
3 | P3-3-T-nh-SD-SMP-hp | ||
4 | P4-A-t-NH-sd-SMP-HP | ||
5 | P5-U-T-NH-sd-SMP-hp | ||
6 | N1-S-T-NH-SD-SMP-HP | ||
7 | N2-2-t-nh-sd-SMP-hp | ||
8 | N3-3-T-nh-SD-SMP-hp | ||
9 | N4-A-t-NH-sd-SMP-HP | ||
10 | N5-U-T-NH-sd-SMP-hp | ||
11 | PT1-nh | ||
12 | PT2-NH | ||
13 | NT1-nh | ||
14 | NT3-NH | ||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..d81e11d280aa --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,19 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_FAST_NO_HZ=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=8 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=n | ||
8 | CONFIG_HOTPLUG_CPU=y | ||
9 | CONFIG_PREEMPT_NONE=y | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=n | ||
12 | #CHECK#CONFIG_TREE_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp new file mode 100644 index 000000000000..02e418572b1b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp new file mode 100644 index 000000000000..b3100f69c8cf --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP new file mode 100644 index 000000000000..c56b44530725 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP | |||
@@ -0,0 +1,18 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp new file mode 100644 index 000000000000..90d924fea9e9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=6 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh new file mode 100644 index 000000000000..023f312a931c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh | |||
@@ -0,0 +1,23 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TRACE=y | ||
3 | CONFIG_RCU_TORTURE_TEST=m | ||
4 | CONFIG_MODULE_UNLOAD=y | ||
5 | CONFIG_SUSPEND=n | ||
6 | CONFIG_HIBERNATION=n | ||
7 | # | ||
8 | CONFIG_SMP=n | ||
9 | # | ||
10 | CONFIG_HOTPLUG_CPU=n | ||
11 | # | ||
12 | CONFIG_NO_HZ=n | ||
13 | # | ||
14 | CONFIG_PREEMPT_NONE=y | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=n | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH new file mode 100644 index 000000000000..6fd0235dae73 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH | |||
@@ -0,0 +1,20 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=y | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=n | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..9647c44cf4b7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_RCU_FAST_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=8 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=n | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp new file mode 100644 index 000000000000..0f3b667d2a9f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp new file mode 100644 index 000000000000..b035e141bf2a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP new file mode 100644 index 000000000000..3ccf6a9447f5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_RT_MUTEXES=y | ||
15 | CONFIG_RCU_BOOST=y | ||
16 | CONFIG_RCU_BOOST_PRIO=2 | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp new file mode 100644 index 000000000000..ef624ce73d8e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp | |||
@@ -0,0 +1,28 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=6 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=y | ||
8 | CONFIG_HOTPLUG_CPU=n | ||
9 | CONFIG_SUSPEND=n | ||
10 | CONFIG_HIBERNATION=n | ||
11 | CONFIG_PREEMPT_NONE=n | ||
12 | CONFIG_PREEMPT_VOLUNTARY=n | ||
13 | CONFIG_PREEMPT=y | ||
14 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
15 | CONFIG_DEBUG_KERNEL=y | ||
16 | CONFIG_PROVE_RCU_DELAY=y | ||
17 | CONFIG_DEBUG_OBJECTS=y | ||
18 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
19 | CONFIG_RT_MUTEXES=y | ||
20 | CONFIG_RCU_BOOST=y | ||
21 | CONFIG_RCU_BOOST_PRIO=2 | ||
22 | CONFIG_RCU_TORTURE_TEST=m | ||
23 | CONFIG_MODULE_UNLOAD=y | ||
24 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
25 | CONFIG_IKCONFIG=y | ||
26 | CONFIG_IKCONFIG_PROC=y | ||
27 | CONFIG_PRINTK_TIME=y | ||
28 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh new file mode 100644 index 000000000000..e3361c3894a1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh | |||
@@ -0,0 +1,23 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_BOOST=y | ||
3 | CONFIG_RCU_BOOST_PRIO=2 | ||
4 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_RCU_TORTURE_TEST=m | ||
6 | CONFIG_MODULE_UNLOAD=y | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | # | ||
10 | CONFIG_SMP=n | ||
11 | # | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | # | ||
14 | CONFIG_NO_HZ=n | ||
15 | # | ||
16 | CONFIG_PREEMPT_NONE=n | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH new file mode 100644 index 000000000000..64abfc3b4d94 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=n | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh new file mode 100644 index 000000000000..c37432f3572c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh | |||
@@ -0,0 +1,41 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Kernel-version-dependent shell functions for the rest of the scripts. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, you can access it online at | ||
17 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
18 | # | ||
19 | # Copyright (C) IBM Corporation, 2013 | ||
20 | # | ||
21 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
22 | |||
23 | # rcutorture_param_n_barrier_cbs bootparam-string | ||
24 | # | ||
25 | # Adds n_barrier_cbs rcutorture module parameter to kernels having it. | ||
26 | rcutorture_param_n_barrier_cbs () { | ||
27 | echo $1 | ||
28 | } | ||
29 | |||
30 | # rcutorture_param_onoff bootparam-string config-file | ||
31 | # | ||
32 | # Adds onoff rcutorture module parameters to kernels having it. | ||
33 | rcutorture_param_onoff () { | ||
34 | if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" | ||
35 | then | ||
36 | echo CPU-hotplug kernel, adding rcutorture onoff. | ||
37 | echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 | ||
38 | else | ||
39 | echo $1 | ||
40 | fi | ||
41 | } | ||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST new file mode 100644 index 000000000000..18223947bbcb --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST | |||
@@ -0,0 +1,14 @@ | |||
1 | P1-S-T-NH-SD-SMP-HP | ||
2 | P2-2-t-nh-sd-SMP-hp | ||
3 | P3-3-T-nh-SD-SMP-hp | ||
4 | P4-A-t-NH-sd-SMP-HP | ||
5 | P5-U-T-NH-sd-SMP-hp | ||
6 | N1-S-T-NH-SD-SMP-HP | ||
7 | N2-2-t-nh-sd-SMP-hp | ||
8 | N3-3-T-nh-SD-SMP-hp | ||
9 | N4-A-t-NH-sd-SMP-HP | ||
10 | N5-U-T-NH-sd-SMP-hp | ||
11 | PT1-nh | ||
12 | PT2-NH | ||
13 | NT1-nh | ||
14 | NT3-NH | ||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..d81e11d280aa --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,19 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_FAST_NO_HZ=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=8 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=n | ||
8 | CONFIG_HOTPLUG_CPU=y | ||
9 | CONFIG_PREEMPT_NONE=y | ||
10 | CONFIG_PREEMPT_VOLUNTARY=n | ||
11 | CONFIG_PREEMPT=n | ||
12 | #CHECK#CONFIG_TREE_RCU=y | ||
13 | CONFIG_RCU_TORTURE_TEST=m | ||
14 | CONFIG_MODULE_UNLOAD=y | ||
15 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
16 | CONFIG_IKCONFIG=y | ||
17 | CONFIG_IKCONFIG_PROC=y | ||
18 | CONFIG_PRINTK_TIME=y | ||
19 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp new file mode 100644 index 000000000000..02e418572b1b --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp new file mode 100644 index 000000000000..b3100f69c8cf --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=y | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=n | ||
13 | #CHECK#CONFIG_TREE_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP new file mode 100644 index 000000000000..c56b44530725 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP | |||
@@ -0,0 +1,18 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=y | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=n | ||
11 | #CHECK#CONFIG_TREE_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
15 | CONFIG_IKCONFIG=y | ||
16 | CONFIG_IKCONFIG_PROC=y | ||
17 | CONFIG_PRINTK_TIME=y | ||
18 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp new file mode 100644 index 000000000000..90d924fea9e9 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_DEBUG_KERNEL=y | ||
3 | CONFIG_RCU_CPU_STALL_INFO=y | ||
4 | CONFIG_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=6 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=y | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | CONFIG_SUSPEND=n | ||
11 | CONFIG_HIBERNATION=n | ||
12 | CONFIG_PREEMPT_NONE=y | ||
13 | CONFIG_PREEMPT_VOLUNTARY=n | ||
14 | CONFIG_PREEMPT=n | ||
15 | #CHECK#CONFIG_TREE_RCU=y | ||
16 | CONFIG_RCU_TORTURE_TEST=m | ||
17 | CONFIG_MODULE_UNLOAD=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh new file mode 100644 index 000000000000..023f312a931c --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh | |||
@@ -0,0 +1,23 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TRACE=y | ||
3 | CONFIG_RCU_TORTURE_TEST=m | ||
4 | CONFIG_MODULE_UNLOAD=y | ||
5 | CONFIG_SUSPEND=n | ||
6 | CONFIG_HIBERNATION=n | ||
7 | # | ||
8 | CONFIG_SMP=n | ||
9 | # | ||
10 | CONFIG_HOTPLUG_CPU=n | ||
11 | # | ||
12 | CONFIG_NO_HZ=n | ||
13 | # | ||
14 | CONFIG_PREEMPT_NONE=y | ||
15 | CONFIG_PREEMPT_VOLUNTARY=n | ||
16 | CONFIG_PREEMPT=n | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH new file mode 100644 index 000000000000..6fd0235dae73 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH | |||
@@ -0,0 +1,20 @@ | |||
1 | #CHECK#CONFIG_TINY_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=y | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=n | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP new file mode 100644 index 000000000000..9647c44cf4b7 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_RCU_FAST_NO_HZ=y | ||
5 | CONFIG_SMP=y | ||
6 | CONFIG_RCU_FANOUT=8 | ||
7 | CONFIG_NR_CPUS=8 | ||
8 | CONFIG_RCU_FANOUT_EXACT=n | ||
9 | CONFIG_HOTPLUG_CPU=y | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp new file mode 100644 index 000000000000..0f3b667d2a9f --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=4 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp new file mode 100644 index 000000000000..b035e141bf2a --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp | |||
@@ -0,0 +1,20 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_NO_HZ=n | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=2 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=n | ||
8 | CONFIG_SUSPEND=n | ||
9 | CONFIG_HIBERNATION=n | ||
10 | CONFIG_PREEMPT_NONE=n | ||
11 | CONFIG_PREEMPT_VOLUNTARY=n | ||
12 | CONFIG_PREEMPT=y | ||
13 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
14 | CONFIG_RCU_TORTURE_TEST=m | ||
15 | CONFIG_MODULE_UNLOAD=y | ||
16 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
17 | CONFIG_IKCONFIG=y | ||
18 | CONFIG_IKCONFIG_PROC=y | ||
19 | CONFIG_PRINTK_TIME=y | ||
20 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP new file mode 100644 index 000000000000..3ccf6a9447f5 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_RCU_TRACE=n | ||
2 | CONFIG_NO_HZ=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_RCU_FANOUT=6 | ||
5 | CONFIG_NR_CPUS=8 | ||
6 | CONFIG_RCU_FANOUT_EXACT=n | ||
7 | CONFIG_HOTPLUG_CPU=y | ||
8 | CONFIG_PREEMPT_NONE=n | ||
9 | CONFIG_PREEMPT_VOLUNTARY=n | ||
10 | CONFIG_PREEMPT=y | ||
11 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
12 | CONFIG_RCU_TORTURE_TEST=m | ||
13 | CONFIG_MODULE_UNLOAD=y | ||
14 | CONFIG_RT_MUTEXES=y | ||
15 | CONFIG_RCU_BOOST=y | ||
16 | CONFIG_RCU_BOOST_PRIO=2 | ||
17 | CONFIG_PROVE_LOCKING=y | ||
18 | CONFIG_PROVE_RCU=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp new file mode 100644 index 000000000000..ef624ce73d8e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp | |||
@@ -0,0 +1,28 @@ | |||
1 | CONFIG_RCU_TRACE=y | ||
2 | CONFIG_RCU_CPU_STALL_INFO=y | ||
3 | CONFIG_NO_HZ=y | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_RCU_FANOUT=6 | ||
6 | CONFIG_NR_CPUS=8 | ||
7 | CONFIG_RCU_FANOUT_EXACT=y | ||
8 | CONFIG_HOTPLUG_CPU=n | ||
9 | CONFIG_SUSPEND=n | ||
10 | CONFIG_HIBERNATION=n | ||
11 | CONFIG_PREEMPT_NONE=n | ||
12 | CONFIG_PREEMPT_VOLUNTARY=n | ||
13 | CONFIG_PREEMPT=y | ||
14 | #CHECK#CONFIG_TREE_PREEMPT_RCU=y | ||
15 | CONFIG_DEBUG_KERNEL=y | ||
16 | CONFIG_PROVE_RCU_DELAY=y | ||
17 | CONFIG_DEBUG_OBJECTS=y | ||
18 | CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||
19 | CONFIG_RT_MUTEXES=y | ||
20 | CONFIG_RCU_BOOST=y | ||
21 | CONFIG_RCU_BOOST_PRIO=2 | ||
22 | CONFIG_RCU_TORTURE_TEST=m | ||
23 | CONFIG_MODULE_UNLOAD=y | ||
24 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
25 | CONFIG_IKCONFIG=y | ||
26 | CONFIG_IKCONFIG_PROC=y | ||
27 | CONFIG_PRINTK_TIME=y | ||
28 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh new file mode 100644 index 000000000000..e3361c3894a1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh | |||
@@ -0,0 +1,23 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_BOOST=y | ||
3 | CONFIG_RCU_BOOST_PRIO=2 | ||
4 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_RCU_TORTURE_TEST=m | ||
6 | CONFIG_MODULE_UNLOAD=y | ||
7 | CONFIG_SUSPEND=n | ||
8 | CONFIG_HIBERNATION=n | ||
9 | # | ||
10 | CONFIG_SMP=n | ||
11 | # | ||
12 | CONFIG_HOTPLUG_CPU=n | ||
13 | # | ||
14 | CONFIG_NO_HZ=n | ||
15 | # | ||
16 | CONFIG_PREEMPT_NONE=n | ||
17 | CONFIG_PREEMPT_VOLUNTARY=n | ||
18 | CONFIG_PREEMPT=y | ||
19 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
20 | CONFIG_IKCONFIG=y | ||
21 | CONFIG_IKCONFIG_PROC=y | ||
22 | CONFIG_PRINTK_TIME=y | ||
23 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH new file mode 100644 index 000000000000..64abfc3b4d94 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH | |||
@@ -0,0 +1,22 @@ | |||
1 | CONFIG_TINY_PREEMPT_RCU=y | ||
2 | CONFIG_RCU_TORTURE_TEST=m | ||
3 | CONFIG_MODULE_UNLOAD=y | ||
4 | CONFIG_SUSPEND=n | ||
5 | CONFIG_HIBERNATION=n | ||
6 | # | ||
7 | CONFIG_SMP=n | ||
8 | # | ||
9 | CONFIG_HOTPLUG_CPU=n | ||
10 | # | ||
11 | CONFIG_NO_HZ=y | ||
12 | # | ||
13 | CONFIG_PREEMPT_NONE=n | ||
14 | CONFIG_PREEMPT_VOLUNTARY=n | ||
15 | CONFIG_PREEMPT=y | ||
16 | CONFIG_PROVE_LOCKING=y | ||
17 | CONFIG_PROVE_RCU=y | ||
18 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
19 | CONFIG_IKCONFIG=y | ||
20 | CONFIG_IKCONFIG_PROC=y | ||
21 | CONFIG_PRINTK_TIME=y | ||
22 | |||
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh new file mode 100644 index 000000000000..6a5f13aab44d --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh | |||
@@ -0,0 +1,46 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Kernel-version-dependent shell functions for the rest of the scripts. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, you can access it online at | ||
17 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
18 | # | ||
19 | # Copyright (C) IBM Corporation, 2013 | ||
20 | # | ||
21 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
22 | |||
23 | # rcutorture_param_n_barrier_cbs bootparam-string | ||
24 | # | ||
25 | # Adds n_barrier_cbs rcutorture module parameter to kernels having it. | ||
26 | rcutorture_param_n_barrier_cbs () { | ||
27 | if echo $1 | grep -q "rcutorture\.n_barrier_cbs" | ||
28 | then | ||
29 | echo $1 | ||
30 | else | ||
31 | echo $1 rcutorture.n_barrier_cbs=4 | ||
32 | fi | ||
33 | } | ||
34 | |||
35 | # rcutorture_param_onoff bootparam-string config-file | ||
36 | # | ||
37 | # Adds onoff rcutorture module parameters to kernels having it. | ||
38 | rcutorture_param_onoff () { | ||
39 | if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" | ||
40 | then | ||
41 | echo CPU-hotplug kernel, adding rcutorture onoff. | ||
42 | echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 | ||
43 | else | ||
44 | echo $1 | ||
45 | fi | ||
46 | } | ||
diff --git a/tools/testing/selftests/rcutorture/configs/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/ver_functions.sh new file mode 100644 index 000000000000..5e40eadea777 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/ver_functions.sh | |||
@@ -0,0 +1,46 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Kernel-version-dependent shell functions for the rest of the scripts. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation; either version 2 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # This program is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with this program; if not, you can access it online at | ||
17 | # http://www.gnu.org/licenses/gpl-2.0.html. | ||
18 | # | ||
19 | # Copyright (C) IBM Corporation, 2013 | ||
20 | # | ||
21 | # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
22 | |||
23 | # rcutorture_param_n_barrier_cbs bootparam-string | ||
24 | # | ||
25 | # Adds n_barrier_cbs rcutorture module parameter to kernels having it. | ||
26 | rcutorture_param_n_barrier_cbs () { | ||
27 | if echo $1 | grep -q "rcutorture\.n_barrier_cbs" | ||
28 | then | ||
29 | echo $1 | ||
30 | else | ||
31 | echo $1 rcutorture.n_barrier_cbs=4 | ||
32 | fi | ||
33 | } | ||
34 | |||
35 | # rcutorture_param_onoff bootparam-string config-file | ||
36 | # | ||
37 | # Adds onoff rcutorture module parameters to kernels having it. | ||
38 | rcutorture_param_onoff () { | ||
39 | if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" | ||
40 | then | ||
41 | echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2 | ||
42 | echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 | ||
43 | else | ||
44 | echo $1 | ||
45 | fi | ||
46 | } | ||
diff --git a/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt new file mode 100644 index 000000000000..28db67b54e55 --- /dev/null +++ b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | This document gives a brief rationale for the TINY_RCU test cases. | ||
2 | |||
3 | |||
4 | Kconfig Parameters: | ||
5 | |||
6 | CONFIG_DEBUG_LOCK_ALLOC -- Do all three and none of the three. | ||
7 | CONFIG_PREEMPT_COUNT | ||
8 | CONFIG_RCU_TRACE | ||
9 | |||
10 | The theory here is that randconfig testing will hit the other six possible | ||
11 | combinations of these parameters. | ||
12 | |||
13 | |||
14 | Kconfig Parameters Ignored: | ||
15 | |||
16 | CONFIG_DEBUG_OBJECTS_RCU_HEAD | ||
17 | CONFIG_PROVE_RCU | ||
18 | |||
19 | In common code tested by TREE_RCU test cases. | ||
20 | |||
21 | CONFIG_NO_HZ_FULL_SYSIDLE | ||
22 | CONFIG_RCU_NOCB_CPU | ||
23 | CONFIG_RCU_USER_QS | ||
24 | |||
25 | Meaningless for TINY_RCU. | ||
26 | |||
27 | CONFIG_RCU_STALL_COMMON | ||
28 | CONFIG_RCU_TORTURE_TEST | ||
29 | |||
30 | Redundant with CONFIG_RCU_TRACE. | ||
31 | |||
32 | CONFIG_HOTPLUG_CPU | ||
33 | CONFIG_PREEMPT | ||
34 | CONFIG_PREEMPT_RCU | ||
35 | CONFIG_SMP | ||
36 | CONFIG_TINY_RCU | ||
37 | CONFIG_TREE_PREEMPT_RCU | ||
38 | CONFIG_TREE_RCU | ||
39 | |||
40 | All forced by CONFIG_TINY_RCU. | ||
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt new file mode 100644 index 000000000000..adbb76cffb49 --- /dev/null +++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt | |||
@@ -0,0 +1,95 @@ | |||
1 | This document gives a brief rationale for the TREE_RCU-related test | ||
2 | cases, a group that includes TREE_PREEMPT_RCU. | ||
3 | |||
4 | |||
5 | Kconfig Parameters: | ||
6 | |||
7 | CONFIG_DEBUG_LOCK_ALLOC -- Do three, covering CONFIG_PROVE_LOCKING & not. | ||
8 | CONFIG_DEBUG_OBJECTS_RCU_HEAD -- Do one. | ||
9 | CONFIG_HOTPLUG_CPU -- Do half. (Every second.) | ||
10 | CONFIG_HZ_PERIODIC -- Do one. | ||
11 | CONFIG_NO_HZ_IDLE -- Do those not otherwise specified. (Groups of two.) | ||
12 | CONFIG_NO_HZ_FULL -- Do two, one with CONFIG_NO_HZ_FULL_SYSIDLE. | ||
13 | CONFIG_NO_HZ_FULL_SYSIDLE -- Do one. | ||
14 | CONFIG_PREEMPT -- Do half. (First three and #8.) | ||
15 | CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not. | ||
16 | CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING. | ||
17 | CONFIG_PROVE_RCU_DELAY -- Do one. | ||
18 | CONFIG_RCU_BOOST -- one of TREE_PREEMPT_RCU. | ||
19 | CONFIG_RCU_BOOST_PRIO -- set to 2 for _BOOST testing. | ||
20 | CONFIG_RCU_CPU_STALL_INFO -- do one with and without _VERBOSE. | ||
21 | CONFIG_RCU_CPU_STALL_VERBOSE -- do one with and without _INFO. | ||
22 | CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others. | ||
23 | CONFIG_RCU_FANOUT_EXACT -- Do one. | ||
24 | CONFIG_RCU_FANOUT_LEAF -- Do one non-default. | ||
25 | CONFIG_RCU_FAST_NO_HZ -- Do one, but not with CONFIG_RCU_NOCB_CPU_ALL. | ||
26 | CONFIG_RCU_NOCB_CPU -- Do three, see below. | ||
27 | CONFIG_RCU_NOCB_CPU_ALL -- Do one. | ||
28 | CONFIG_RCU_NOCB_CPU_NONE -- Do one. | ||
29 | CONFIG_RCU_NOCB_CPU_ZERO -- Do one. | ||
30 | CONFIG_RCU_TRACE -- Do half. | ||
31 | CONFIG_SMP -- Need one !SMP for TREE_PREEMPT_RCU. | ||
32 | RCU-bh: Do one with PREEMPT and one with !PREEMPT. | ||
33 | RCU-sched: Do one with PREEMPT but not BOOST. | ||
34 | |||
35 | |||
36 | Hierarchy: | ||
37 | |||
38 | TREE01. CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=8, CONFIG_RCU_FANOUT_EXACT=n. | ||
39 | TREE02. CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=3, CONFIG_RCU_FANOUT_EXACT=n, | ||
40 | CONFIG_RCU_FANOUT_LEAF=3. | ||
41 | TREE03. CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=4, CONFIG_RCU_FANOUT_EXACT=n, | ||
42 | CONFIG_RCU_FANOUT_LEAF=4. | ||
43 | TREE04. CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=2, CONFIG_RCU_FANOUT_EXACT=n, | ||
44 | CONFIG_RCU_FANOUT_LEAF=2. | ||
45 | TREE05. CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=6, CONFIG_RCU_FANOUT_EXACT=n | ||
46 | CONFIG_RCU_FANOUT_LEAF=6. | ||
47 | TREE06. CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=6, CONFIG_RCU_FANOUT_EXACT=y | ||
48 | CONFIG_RCU_FANOUT_LEAF=6. | ||
49 | TREE07. CONFIG_NR_CPUS=16, CONFIG_RCU_FANOUT=2, CONFIG_RCU_FANOUT_EXACT=n, | ||
50 | CONFIG_RCU_FANOUT_LEAF=2. | ||
51 | TREE08. CONFIG_NR_CPUS=16, CONFIG_RCU_FANOUT=3, CONFIG_RCU_FANOUT_EXACT=y, | ||
52 | CONFIG_RCU_FANOUT_LEAF=2. | ||
53 | TREE09. CONFIG_NR_CPUS=1. | ||
54 | |||
55 | |||
56 | Kconfig Parameters Ignored: | ||
57 | |||
58 | CONFIG_64BIT | ||
59 | |||
60 | Used only to check CONFIG_RCU_FANOUT value, inspection suffices. | ||
61 | |||
62 | CONFIG_NO_HZ_FULL_SYSIDLE_SMALL | ||
63 | |||
64 | Defer until Frederic uses this. | ||
65 | |||
66 | CONFIG_PREEMPT_COUNT | ||
67 | CONFIG_PREEMPT_RCU | ||
68 | |||
69 | Redundant with CONFIG_PREEMPT, ignore. | ||
70 | |||
71 | CONFIG_RCU_BOOST_DELAY | ||
72 | |||
73 | Inspection suffices, ignore. | ||
74 | |||
75 | CONFIG_RCU_CPU_STALL_TIMEOUT | ||
76 | |||
77 | Inspection suffices, ignore. | ||
78 | |||
79 | CONFIG_RCU_STALL_COMMON | ||
80 | |||
81 | Implied by TREE_RCU and TREE_PREEMPT_RCU. | ||
82 | |||
83 | CONFIG_RCU_TORTURE_TEST | ||
84 | CONFIG_RCU_TORTURE_TEST_RUNNABLE | ||
85 | |||
86 | Always used in KVM testing. | ||
87 | |||
88 | CONFIG_RCU_USER_QS | ||
89 | |||
90 | Redundant with CONFIG_NO_HZ_FULL. | ||
91 | |||
92 | CONFIG_TREE_PREEMPT_RCU | ||
93 | CONFIG_TREE_RCU | ||
94 | |||
95 | These are controlled by CONFIG_PREEMPT. | ||
diff --git a/tools/testing/selftests/rcutorture/doc/initrd.txt b/tools/testing/selftests/rcutorture/doc/initrd.txt new file mode 100644 index 000000000000..49d134c25c04 --- /dev/null +++ b/tools/testing/selftests/rcutorture/doc/initrd.txt | |||
@@ -0,0 +1,90 @@ | |||
1 | This document describes one way to create the initrd directory hierarchy | ||
2 | in order to allow an initrd to be built into your kernel. The trick | ||
3 | here is to steal the initrd file used on your Linux laptop, Ubuntu in | ||
4 | this case. There are probably much better ways of doing this. | ||
5 | |||
6 | That said, here are the commands: | ||
7 | |||
8 | ------------------------------------------------------------------------ | ||
9 | zcat /initrd.img > /tmp/initrd.img.zcat | ||
10 | mkdir initrd | ||
11 | cd initrd | ||
12 | cpio -id < /tmp/initrd.img.zcat | ||
13 | ------------------------------------------------------------------------ | ||
14 | |||
15 | Interestingly enough, if you are running rcutorture, you don't really | ||
16 | need userspace in many cases. Running without userspace has the | ||
17 | advantage of allowing you to test your kernel independently of the | ||
18 | distro in place, the root-filesystem layout, and so on. To make this | ||
19 | happen, put the following script in the initrd's tree's "/init" file, | ||
20 | with 0755 mode. | ||
21 | |||
22 | ------------------------------------------------------------------------ | ||
23 | #!/bin/sh | ||
24 | |||
25 | [ -d /dev ] || mkdir -m 0755 /dev | ||
26 | [ -d /root ] || mkdir -m 0700 /root | ||
27 | [ -d /sys ] || mkdir /sys | ||
28 | [ -d /proc ] || mkdir /proc | ||
29 | [ -d /tmp ] || mkdir /tmp | ||
30 | mkdir -p /var/lock | ||
31 | mount -t sysfs -o nodev,noexec,nosuid sysfs /sys | ||
32 | mount -t proc -o nodev,noexec,nosuid proc /proc | ||
33 | # Some things don't work properly without /etc/mtab. | ||
34 | ln -sf /proc/mounts /etc/mtab | ||
35 | |||
36 | # Note that this only becomes /dev on the real filesystem if udev's scripts | ||
37 | # are used; which they will be, but it's worth pointing out | ||
38 | if ! mount -t devtmpfs -o mode=0755 udev /dev; then | ||
39 | echo "W: devtmpfs not available, falling back to tmpfs for /dev" | ||
40 | mount -t tmpfs -o mode=0755 udev /dev | ||
41 | [ -e /dev/console ] || mknod --mode=600 /dev/console c 5 1 | ||
42 | [ -e /dev/kmsg ] || mknod --mode=644 /dev/kmsg c 1 11 | ||
43 | [ -e /dev/null ] || mknod --mode=666 /dev/null c 1 3 | ||
44 | fi | ||
45 | |||
46 | mkdir /dev/pts | ||
47 | mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true | ||
48 | mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /run | ||
49 | mkdir /run/initramfs | ||
50 | # compatibility symlink for the pre-oneiric locations | ||
51 | ln -s /run/initramfs /dev/.initramfs | ||
52 | |||
53 | # Export relevant variables | ||
54 | export ROOT= | ||
55 | export ROOTDELAY= | ||
56 | export ROOTFLAGS= | ||
57 | export ROOTFSTYPE= | ||
58 | export IP= | ||
59 | export BOOT= | ||
60 | export BOOTIF= | ||
61 | export UBIMTD= | ||
62 | export break= | ||
63 | export init=/sbin/init | ||
64 | export quiet=n | ||
65 | export readonly=y | ||
66 | export rootmnt=/root | ||
67 | export debug= | ||
68 | export panic= | ||
69 | export blacklist= | ||
70 | export resume= | ||
71 | export resume_offset= | ||
72 | export recovery= | ||
73 | |||
74 | for i in /sys/devices/system/cpu/cpu*/online | ||
75 | do | ||
76 | case $i in | ||
77 | '/sys/devices/system/cpu/cpu0/online') | ||
78 | ;; | ||
79 | '/sys/devices/system/cpu/cpu*/online') | ||
80 | ;; | ||
81 | *) | ||
82 | echo 1 > $i | ||
83 | ;; | ||
84 | esac | ||
85 | done | ||
86 | |||
87 | while : | ||
88 | do | ||
89 | sleep 10 | ||
90 | done | ||
diff --git a/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt new file mode 100644 index 000000000000..66efb59a1bd1 --- /dev/null +++ b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt | |||
@@ -0,0 +1,42 @@ | |||
1 | This document describes one way to created the rcu-test-image file | ||
2 | that contains the filesystem used by the guest-OS kernel. There are | ||
3 | probably much better ways of doing this, and this filesystem could no | ||
4 | doubt be smaller. It is probably also possible to simply download | ||
5 | an appropriate image from any number of places. | ||
6 | |||
7 | That said, here are the commands: | ||
8 | |||
9 | ------------------------------------------------------------------------ | ||
10 | dd if=/dev/zero of=rcu-test-image bs=400M count=1 | ||
11 | mkfs.ext3 ./rcu-test-image | ||
12 | sudo mount -o loop ./rcu-test-image /mnt | ||
13 | |||
14 | # Replace "precise" below with your favorite Ubuntu release. | ||
15 | # Empirical evidence says this image will work for 64-bit, but... | ||
16 | # Note that debootstrap does take a few minutes to run. Or longer. | ||
17 | sudo debootstrap --verbose --arch i386 precise /mnt http://archive.ubuntu.com/ubuntu | ||
18 | cat << '___EOF___' | sudo dd of=/mnt/etc/fstab | ||
19 | # UNCONFIGURED FSTAB FOR BASE SYSTEM | ||
20 | # | ||
21 | /dev/vda / ext3 defaults 1 1 | ||
22 | dev /dev tmpfs rw 0 0 | ||
23 | tmpfs /dev/shm tmpfs defaults 0 0 | ||
24 | devpts /dev/pts devpts gid=5,mode=620 0 0 | ||
25 | sysfs /sys sysfs defaults 0 0 | ||
26 | proc /proc proc defaults 0 0 | ||
27 | ___EOF___ | ||
28 | sudo umount /mnt | ||
29 | ------------------------------------------------------------------------ | ||
30 | |||
31 | |||
32 | References: | ||
33 | |||
34 | http://sripathikodi.blogspot.com/2010/02/creating-kvm-bootable-fedora-system.html | ||
35 | https://help.ubuntu.com/community/KVM/CreateGuests | ||
36 | https://help.ubuntu.com/community/JeOSVMBuilder | ||
37 | http://wiki.libvirt.org/page/UbuntuKVMWalkthrough | ||
38 | http://www.moe.co.uk/2011/01/07/pci_add_option_rom-failed-to-find-romfile-pxe-rtl8139-bin/ -- "apt-get install kvm-pxe" | ||
39 | http://www.landley.net/writing/rootfs-howto.html | ||
40 | http://en.wikipedia.org/wiki/Initrd | ||
41 | http://en.wikipedia.org/wiki/Cpio | ||
42 | http://wiki.libvirt.org/page/UbuntuKVMWalkthrough | ||
diff --git a/tools/vm/Makefile b/tools/vm/Makefile index 24e9ddd93fa4..3d907dacf2ac 100644 --- a/tools/vm/Makefile +++ b/tools/vm/Makefile | |||
@@ -2,21 +2,21 @@ | |||
2 | # | 2 | # |
3 | TARGETS=page-types slabinfo | 3 | TARGETS=page-types slabinfo |
4 | 4 | ||
5 | LK_DIR = ../lib/lk | 5 | LIB_DIR = ../lib/api |
6 | LIBLK = $(LK_DIR)/liblk.a | 6 | LIBS = $(LIB_DIR)/libapikfs.a |
7 | 7 | ||
8 | CC = $(CROSS_COMPILE)gcc | 8 | CC = $(CROSS_COMPILE)gcc |
9 | CFLAGS = -Wall -Wextra -I../lib/ | 9 | CFLAGS = -Wall -Wextra -I../lib/ |
10 | LDFLAGS = $(LIBLK) | 10 | LDFLAGS = $(LIBS) |
11 | 11 | ||
12 | $(TARGETS): liblk | 12 | $(TARGETS): $(LIBS) |
13 | 13 | ||
14 | liblk: | 14 | $(LIBS): |
15 | make -C $(LK_DIR) | 15 | make -C $(LIB_DIR) |
16 | 16 | ||
17 | %: %.c | 17 | %: %.c |
18 | $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) | 18 | $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) |
19 | 19 | ||
20 | clean: | 20 | clean: |
21 | $(RM) page-types slabinfo | 21 | $(RM) page-types slabinfo |
22 | make -C ../lib/lk clean | 22 | make -C $(LIB_DIR) clean |
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c index d5e9d6d185c8..f9be24d9efac 100644 --- a/tools/vm/page-types.c +++ b/tools/vm/page-types.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <sys/statfs.h> | 36 | #include <sys/statfs.h> |
37 | #include "../../include/uapi/linux/magic.h" | 37 | #include "../../include/uapi/linux/magic.h" |
38 | #include "../../include/uapi/linux/kernel-page-flags.h" | 38 | #include "../../include/uapi/linux/kernel-page-flags.h" |
39 | #include <lk/debugfs.h> | 39 | #include <api/fs/debugfs.h> |
40 | 40 | ||
41 | #ifndef MAX_PATH | 41 | #ifndef MAX_PATH |
42 | # define MAX_PATH 256 | 42 | # define MAX_PATH 256 |