diff options
Diffstat (limited to 'arch/arm')
66 files changed, 3700 insertions, 2754 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 41266af5dfc8..fac6890b315d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -207,6 +207,9 @@ config ZONE_DMA | |||
207 | config NEED_DMA_MAP_STATE | 207 | config NEED_DMA_MAP_STATE |
208 | def_bool y | 208 | def_bool y |
209 | 209 | ||
210 | config ARCH_SUPPORTS_UPROBES | ||
211 | def_bool y | ||
212 | |||
210 | config ARCH_HAS_DMA_SET_COHERENT_MASK | 213 | config ARCH_HAS_DMA_SET_COHERENT_MASK |
211 | bool | 214 | bool |
212 | 215 | ||
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 6d1e43d46187..032030361bef 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile | |||
@@ -209,7 +209,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ | |||
209 | omap3-n900.dtb \ | 209 | omap3-n900.dtb \ |
210 | omap3-n9.dtb \ | 210 | omap3-n9.dtb \ |
211 | omap3-n950.dtb \ | 211 | omap3-n950.dtb \ |
212 | omap3-tobi.dtb \ | 212 | omap3-overo-tobi.dtb \ |
213 | omap3-overo-storm-tobi.dtb \ | ||
213 | omap3-gta04.dtb \ | 214 | omap3-gta04.dtb \ |
214 | omap3-igep0020.dtb \ | 215 | omap3-igep0020.dtb \ |
215 | omap3-igep0030.dtb \ | 216 | omap3-igep0030.dtb \ |
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index 4718ec4a4dbf..486880b74831 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts | |||
@@ -121,7 +121,7 @@ | |||
121 | ti,model = "AM335x-EVMSK"; | 121 | ti,model = "AM335x-EVMSK"; |
122 | ti,audio-codec = <&tlv320aic3106>; | 122 | ti,audio-codec = <&tlv320aic3106>; |
123 | ti,mcasp-controller = <&mcasp1>; | 123 | ti,mcasp-controller = <&mcasp1>; |
124 | ti,codec-clock-rate = <24576000>; | 124 | ti,codec-clock-rate = <24000000>; |
125 | ti,audio-routing = | 125 | ti,audio-routing = |
126 | "Headphone Jack", "HPLOUT", | 126 | "Headphone Jack", "HPLOUT", |
127 | "Headphone Jack", "HPROUT"; | 127 | "Headphone Jack", "HPROUT"; |
@@ -256,6 +256,12 @@ | |||
256 | >; | 256 | >; |
257 | }; | 257 | }; |
258 | 258 | ||
259 | mmc1_pins: pinmux_mmc1_pins { | ||
260 | pinctrl-single,pins = < | ||
261 | 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ | ||
262 | >; | ||
263 | }; | ||
264 | |||
259 | mcasp1_pins: mcasp1_pins { | 265 | mcasp1_pins: mcasp1_pins { |
260 | pinctrl-single,pins = < | 266 | pinctrl-single,pins = < |
261 | 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ | 267 | 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ |
@@ -456,6 +462,9 @@ | |||
456 | status = "okay"; | 462 | status = "okay"; |
457 | vmmc-supply = <&vmmc_reg>; | 463 | vmmc-supply = <&vmmc_reg>; |
458 | bus-width = <4>; | 464 | bus-width = <4>; |
465 | pinctrl-names = "default"; | ||
466 | pinctrl-0 = <&mmc1_pins>; | ||
467 | cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; | ||
459 | }; | 468 | }; |
460 | 469 | ||
461 | &sham { | 470 | &sham { |
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi index 66609684d41b..9480cf891f8c 100644 --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi | |||
@@ -23,6 +23,7 @@ | |||
23 | gpio0 = &gpio0; | 23 | gpio0 = &gpio0; |
24 | gpio1 = &gpio1; | 24 | gpio1 = &gpio1; |
25 | gpio2 = &gpio2; | 25 | gpio2 = &gpio2; |
26 | eth3 = ð3; | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | cpus { | 29 | cpus { |
@@ -291,7 +292,7 @@ | |||
291 | interrupts = <91>; | 292 | interrupts = <91>; |
292 | }; | 293 | }; |
293 | 294 | ||
294 | ethernet@34000 { | 295 | eth3: ethernet@34000 { |
295 | compatible = "marvell,armada-370-neta"; | 296 | compatible = "marvell,armada-370-neta"; |
296 | reg = <0x34000 0x4000>; | 297 | reg = <0x34000 0x4000>; |
297 | interrupts = <14>; | 298 | interrupts = <14>; |
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi index 2b76524f4aa7..187fd46b7b5e 100644 --- a/arch/arm/boot/dts/dove.dtsi +++ b/arch/arm/boot/dts/dove.dtsi | |||
@@ -379,15 +379,6 @@ | |||
379 | #clock-cells = <1>; | 379 | #clock-cells = <1>; |
380 | }; | 380 | }; |
381 | 381 | ||
382 | pmu_intc: pmu-interrupt-ctrl@d0050 { | ||
383 | compatible = "marvell,dove-pmu-intc"; | ||
384 | interrupt-controller; | ||
385 | #interrupt-cells = <1>; | ||
386 | reg = <0xd0050 0x8>; | ||
387 | interrupts = <33>; | ||
388 | marvell,#interrupts = <7>; | ||
389 | }; | ||
390 | |||
391 | pinctrl: pin-ctrl@d0200 { | 382 | pinctrl: pin-ctrl@d0200 { |
392 | compatible = "marvell,dove-pinctrl"; | 383 | compatible = "marvell,dove-pinctrl"; |
393 | reg = <0xd0200 0x10>; | 384 | reg = <0xd0200 0x10>; |
@@ -610,8 +601,6 @@ | |||
610 | rtc: real-time-clock@d8500 { | 601 | rtc: real-time-clock@d8500 { |
611 | compatible = "marvell,orion-rtc"; | 602 | compatible = "marvell,orion-rtc"; |
612 | reg = <0xd8500 0x20>; | 603 | reg = <0xd8500 0x20>; |
613 | interrupt-parent = <&pmu_intc>; | ||
614 | interrupts = <5>; | ||
615 | }; | 604 | }; |
616 | 605 | ||
617 | gpio2: gpio-ctrl@e8400 { | 606 | gpio2: gpio-ctrl@e8400 { |
diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts b/arch/arm/boot/dts/imx6dl-hummingboard.dts index fd8fc7cd53f3..5bfae54fb780 100644 --- a/arch/arm/boot/dts/imx6dl-hummingboard.dts +++ b/arch/arm/boot/dts/imx6dl-hummingboard.dts | |||
@@ -52,12 +52,6 @@ | |||
52 | }; | 52 | }; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | codec: spdif-transmitter { | ||
56 | compatible = "linux,spdif-dit"; | ||
57 | pinctrl-names = "default"; | ||
58 | pinctrl-0 = <&pinctrl_hummingboard_spdif>; | ||
59 | }; | ||
60 | |||
61 | sound-spdif { | 55 | sound-spdif { |
62 | compatible = "fsl,imx-audio-spdif"; | 56 | compatible = "fsl,imx-audio-spdif"; |
63 | model = "imx-spdif"; | 57 | model = "imx-spdif"; |
@@ -111,7 +105,7 @@ | |||
111 | }; | 105 | }; |
112 | 106 | ||
113 | pinctrl_hummingboard_spdif: hummingboard-spdif { | 107 | pinctrl_hummingboard_spdif: hummingboard-spdif { |
114 | fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0>; | 108 | fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>; |
115 | }; | 109 | }; |
116 | 110 | ||
117 | pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus { | 111 | pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus { |
@@ -142,6 +136,8 @@ | |||
142 | }; | 136 | }; |
143 | 137 | ||
144 | &spdif { | 138 | &spdif { |
139 | pinctrl-names = "default"; | ||
140 | pinctrl-0 = <&pinctrl_hummingboard_spdif>; | ||
145 | status = "okay"; | 141 | status = "okay"; |
146 | }; | 142 | }; |
147 | 143 | ||
diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi index 64daa3b311f6..c2a24888a276 100644 --- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | |||
@@ -46,12 +46,6 @@ | |||
46 | }; | 46 | }; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | codec: spdif-transmitter { | ||
50 | compatible = "linux,spdif-dit"; | ||
51 | pinctrl-names = "default"; | ||
52 | pinctrl-0 = <&pinctrl_cubox_i_spdif>; | ||
53 | }; | ||
54 | |||
55 | sound-spdif { | 49 | sound-spdif { |
56 | compatible = "fsl,imx-audio-spdif"; | 50 | compatible = "fsl,imx-audio-spdif"; |
57 | model = "imx-spdif"; | 51 | model = "imx-spdif"; |
@@ -89,7 +83,7 @@ | |||
89 | }; | 83 | }; |
90 | 84 | ||
91 | pinctrl_cubox_i_spdif: cubox-i-spdif { | 85 | pinctrl_cubox_i_spdif: cubox-i-spdif { |
92 | fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0>; | 86 | fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>; |
93 | }; | 87 | }; |
94 | 88 | ||
95 | pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus { | 89 | pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus { |
@@ -121,6 +115,8 @@ | |||
121 | }; | 115 | }; |
122 | 116 | ||
123 | &spdif { | 117 | &spdif { |
118 | pinctrl-names = "default"; | ||
119 | pinctrl-0 = <&pinctrl_cubox_i_spdif>; | ||
124 | status = "okay"; | 120 | status = "okay"; |
125 | }; | 121 | }; |
126 | 122 | ||
diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts index b9b55c95a566..c551e4af4d83 100644 --- a/arch/arm/boot/dts/omap3-gta04.dts +++ b/arch/arm/boot/dts/omap3-gta04.dts | |||
@@ -32,7 +32,7 @@ | |||
32 | aux-button { | 32 | aux-button { |
33 | label = "aux"; | 33 | label = "aux"; |
34 | linux,code = <169>; | 34 | linux,code = <169>; |
35 | gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; | 35 | gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; |
36 | gpio-key,wakeup; | 36 | gpio-key,wakeup; |
37 | }; | 37 | }; |
38 | }; | 38 | }; |
@@ -92,6 +92,8 @@ | |||
92 | bmp085@77 { | 92 | bmp085@77 { |
93 | compatible = "bosch,bmp085"; | 93 | compatible = "bosch,bmp085"; |
94 | reg = <0x77>; | 94 | reg = <0x77>; |
95 | interrupt-parent = <&gpio4>; | ||
96 | interrupts = <17 IRQ_TYPE_EDGE_RISING>; | ||
95 | }; | 97 | }; |
96 | 98 | ||
97 | /* leds */ | 99 | /* leds */ |
@@ -141,8 +143,8 @@ | |||
141 | pinctrl-names = "default"; | 143 | pinctrl-names = "default"; |
142 | pinctrl-0 = <&mmc1_pins>; | 144 | pinctrl-0 = <&mmc1_pins>; |
143 | vmmc-supply = <&vmmc1>; | 145 | vmmc-supply = <&vmmc1>; |
144 | vmmc_aux-supply = <&vsim>; | ||
145 | bus-width = <4>; | 146 | bus-width = <4>; |
147 | ti,non-removable; | ||
146 | }; | 148 | }; |
147 | 149 | ||
148 | &mmc2 { | 150 | &mmc2 { |
diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/omap3-n9.dts index 39828ce464ee..9938b5dc1909 100644 --- a/arch/arm/boot/dts/omap3-n9.dts +++ b/arch/arm/boot/dts/omap3-n9.dts | |||
@@ -14,5 +14,5 @@ | |||
14 | 14 | ||
15 | / { | 15 | / { |
16 | model = "Nokia N9"; | 16 | model = "Nokia N9"; |
17 | compatible = "nokia,omap3-n9", "ti,omap3"; | 17 | compatible = "nokia,omap3-n9", "ti,omap36xx", "ti,omap3"; |
18 | }; | 18 | }; |
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts index 6fc85f963530..0bf40c90faba 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/omap3-n900.dts | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2013 Pavel Machek <pavel@ucw.cz> | 2 | * Copyright (C) 2013 Pavel Machek <pavel@ucw.cz> |
3 | * Copyright 2013 Aaro Koskinen <aaro.koskinen@iki.fi> | 3 | * Copyright (C) 2013-2014 Aaro Koskinen <aaro.koskinen@iki.fi> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 (or later) as | 6 | * it under the terms of the GNU General Public License version 2 (or later) as |
@@ -13,7 +13,7 @@ | |||
13 | 13 | ||
14 | / { | 14 | / { |
15 | model = "Nokia N900"; | 15 | model = "Nokia N900"; |
16 | compatible = "nokia,omap3-n900", "ti,omap3"; | 16 | compatible = "nokia,omap3-n900", "ti,omap3430", "ti,omap3"; |
17 | 17 | ||
18 | cpus { | 18 | cpus { |
19 | cpu@0 { | 19 | cpu@0 { |
diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts index b076a526b999..261c5589bfa3 100644 --- a/arch/arm/boot/dts/omap3-n950.dts +++ b/arch/arm/boot/dts/omap3-n950.dts | |||
@@ -14,5 +14,5 @@ | |||
14 | 14 | ||
15 | / { | 15 | / { |
16 | model = "Nokia N950"; | 16 | model = "Nokia N950"; |
17 | compatible = "nokia,omap3-n950", "ti,omap3"; | 17 | compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3"; |
18 | }; | 18 | }; |
diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts new file mode 100644 index 000000000000..966b5c9cd96a --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group | ||
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 version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Tobi expansion board is manufactured by Gumstix Inc. | ||
11 | */ | ||
12 | |||
13 | /dts-v1/; | ||
14 | |||
15 | #include "omap36xx.dtsi" | ||
16 | #include "omap3-overo-tobi-common.dtsi" | ||
17 | |||
18 | / { | ||
19 | model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Tobi"; | ||
20 | compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; | ||
21 | }; | ||
22 | |||
diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi index 7e4ad2aec37a..4edc013a91c1 100644 --- a/arch/arm/boot/dts/omap3-tobi.dts +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | |||
@@ -13,9 +13,6 @@ | |||
13 | #include "omap3-overo.dtsi" | 13 | #include "omap3-overo.dtsi" |
14 | 14 | ||
15 | / { | 15 | / { |
16 | model = "TI OMAP3 Gumstix Overo on Tobi"; | ||
17 | compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"; | ||
18 | |||
19 | leds { | 16 | leds { |
20 | compatible = "gpio-leds"; | 17 | compatible = "gpio-leds"; |
21 | heartbeat { | 18 | heartbeat { |
diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi.dts new file mode 100644 index 000000000000..de5653e1b5ca --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-tobi.dts | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group | ||
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 version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Tobi expansion board is manufactured by Gumstix Inc. | ||
11 | */ | ||
12 | |||
13 | /dts-v1/; | ||
14 | |||
15 | #include "omap34xx.dtsi" | ||
16 | #include "omap3-overo-tobi-common.dtsi" | ||
17 | |||
18 | / { | ||
19 | model = "OMAP35xx Gumstix Overo on Tobi"; | ||
20 | compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3"; | ||
21 | }; | ||
22 | |||
diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi index a461d2fd1fb0..597099907f8e 100644 --- a/arch/arm/boot/dts/omap3-overo.dtsi +++ b/arch/arm/boot/dts/omap3-overo.dtsi | |||
@@ -9,9 +9,6 @@ | |||
9 | /* | 9 | /* |
10 | * The Gumstix Overo must be combined with an expansion board. | 10 | * The Gumstix Overo must be combined with an expansion board. |
11 | */ | 11 | */ |
12 | /dts-v1/; | ||
13 | |||
14 | #include "omap34xx.dtsi" | ||
15 | 12 | ||
16 | / { | 13 | / { |
17 | pwmleds { | 14 | pwmleds { |
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi index 389e987ec281..44ec401ec366 100644 --- a/arch/arm/boot/dts/tegra114.dtsi +++ b/arch/arm/boot/dts/tegra114.dtsi | |||
@@ -57,6 +57,8 @@ | |||
57 | resets = <&tegra_car 27>; | 57 | resets = <&tegra_car 27>; |
58 | reset-names = "dc"; | 58 | reset-names = "dc"; |
59 | 59 | ||
60 | nvidia,head = <0>; | ||
61 | |||
60 | rgb { | 62 | rgb { |
61 | status = "disabled"; | 63 | status = "disabled"; |
62 | }; | 64 | }; |
@@ -72,6 +74,8 @@ | |||
72 | resets = <&tegra_car 26>; | 74 | resets = <&tegra_car 26>; |
73 | reset-names = "dc"; | 75 | reset-names = "dc"; |
74 | 76 | ||
77 | nvidia,head = <1>; | ||
78 | |||
75 | rgb { | 79 | rgb { |
76 | status = "disabled"; | 80 | status = "disabled"; |
77 | }; | 81 | }; |
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 480ecda3416b..48d2a7f4d0c0 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi | |||
@@ -94,6 +94,8 @@ | |||
94 | resets = <&tegra_car 27>; | 94 | resets = <&tegra_car 27>; |
95 | reset-names = "dc"; | 95 | reset-names = "dc"; |
96 | 96 | ||
97 | nvidia,head = <0>; | ||
98 | |||
97 | rgb { | 99 | rgb { |
98 | status = "disabled"; | 100 | status = "disabled"; |
99 | }; | 101 | }; |
@@ -109,6 +111,8 @@ | |||
109 | resets = <&tegra_car 26>; | 111 | resets = <&tegra_car 26>; |
110 | reset-names = "dc"; | 112 | reset-names = "dc"; |
111 | 113 | ||
114 | nvidia,head = <1>; | ||
115 | |||
112 | rgb { | 116 | rgb { |
113 | status = "disabled"; | 117 | status = "disabled"; |
114 | }; | 118 | }; |
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index 9104224124ee..1e156d9d0506 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi | |||
@@ -28,7 +28,7 @@ | |||
28 | compatible = "nvidia,cardhu", "nvidia,tegra30"; | 28 | compatible = "nvidia,cardhu", "nvidia,tegra30"; |
29 | 29 | ||
30 | aliases { | 30 | aliases { |
31 | rtc0 = "/i2c@7000d000/tps6586x@34"; | 31 | rtc0 = "/i2c@7000d000/tps65911@2d"; |
32 | rtc1 = "/rtc@7000e000"; | 32 | rtc1 = "/rtc@7000e000"; |
33 | }; | 33 | }; |
34 | 34 | ||
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index ed8e7700b46d..19a84e933f4e 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi | |||
@@ -170,6 +170,8 @@ | |||
170 | resets = <&tegra_car 27>; | 170 | resets = <&tegra_car 27>; |
171 | reset-names = "dc"; | 171 | reset-names = "dc"; |
172 | 172 | ||
173 | nvidia,head = <0>; | ||
174 | |||
173 | rgb { | 175 | rgb { |
174 | status = "disabled"; | 176 | status = "disabled"; |
175 | }; | 177 | }; |
@@ -185,6 +187,8 @@ | |||
185 | resets = <&tegra_car 26>; | 187 | resets = <&tegra_car 26>; |
186 | reset-names = "dc"; | 188 | reset-names = "dc"; |
187 | 189 | ||
190 | nvidia,head = <1>; | ||
191 | |||
188 | rgb { | 192 | rgb { |
189 | status = "disabled"; | 193 | status = "disabled"; |
190 | }; | 194 | }; |
diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi deleted file mode 100644 index c843720bd3e5..000000000000 --- a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | |||
2 | / { | ||
3 | testcase-data { | ||
4 | interrupts { | ||
5 | #address-cells = <1>; | ||
6 | #size-cells = <1>; | ||
7 | test_intc0: intc0 { | ||
8 | interrupt-controller; | ||
9 | #interrupt-cells = <1>; | ||
10 | }; | ||
11 | |||
12 | test_intc1: intc1 { | ||
13 | interrupt-controller; | ||
14 | #interrupt-cells = <3>; | ||
15 | }; | ||
16 | |||
17 | test_intc2: intc2 { | ||
18 | interrupt-controller; | ||
19 | #interrupt-cells = <2>; | ||
20 | }; | ||
21 | |||
22 | test_intmap0: intmap0 { | ||
23 | #interrupt-cells = <1>; | ||
24 | #address-cells = <0>; | ||
25 | interrupt-map = <1 &test_intc0 9>, | ||
26 | <2 &test_intc1 10 11 12>, | ||
27 | <3 &test_intc2 13 14>, | ||
28 | <4 &test_intc2 15 16>; | ||
29 | }; | ||
30 | |||
31 | test_intmap1: intmap1 { | ||
32 | #interrupt-cells = <2>; | ||
33 | interrupt-map = <0x5000 1 2 &test_intc0 15>; | ||
34 | }; | ||
35 | |||
36 | interrupts0 { | ||
37 | interrupt-parent = <&test_intc0>; | ||
38 | interrupts = <1>, <2>, <3>, <4>; | ||
39 | }; | ||
40 | |||
41 | interrupts1 { | ||
42 | interrupt-parent = <&test_intmap0>; | ||
43 | interrupts = <1>, <2>, <3>, <4>; | ||
44 | }; | ||
45 | |||
46 | interrupts-extended0 { | ||
47 | reg = <0x5000 0x100>; | ||
48 | interrupts-extended = <&test_intc0 1>, | ||
49 | <&test_intc1 2 3 4>, | ||
50 | <&test_intc2 5 6>, | ||
51 | <&test_intmap0 1>, | ||
52 | <&test_intmap0 2>, | ||
53 | <&test_intmap0 3>, | ||
54 | <&test_intmap1 1 2>; | ||
55 | }; | ||
56 | }; | ||
57 | }; | ||
58 | }; | ||
diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/arch/arm/boot/dts/testcases/tests-phandle.dtsi deleted file mode 100644 index 0007d3cd7dc2..000000000000 --- a/arch/arm/boot/dts/testcases/tests-phandle.dtsi +++ /dev/null | |||
@@ -1,39 +0,0 @@ | |||
1 | |||
2 | / { | ||
3 | testcase-data { | ||
4 | phandle-tests { | ||
5 | provider0: provider0 { | ||
6 | #phandle-cells = <0>; | ||
7 | }; | ||
8 | |||
9 | provider1: provider1 { | ||
10 | #phandle-cells = <1>; | ||
11 | }; | ||
12 | |||
13 | provider2: provider2 { | ||
14 | #phandle-cells = <2>; | ||
15 | }; | ||
16 | |||
17 | provider3: provider3 { | ||
18 | #phandle-cells = <3>; | ||
19 | }; | ||
20 | |||
21 | consumer-a { | ||
22 | phandle-list = <&provider1 1>, | ||
23 | <&provider2 2 0>, | ||
24 | <0>, | ||
25 | <&provider3 4 4 3>, | ||
26 | <&provider2 5 100>, | ||
27 | <&provider0>, | ||
28 | <&provider1 7>; | ||
29 | phandle-list-names = "first", "second", "third"; | ||
30 | |||
31 | phandle-list-bad-phandle = <12345678 0 0>; | ||
32 | phandle-list-bad-args = <&provider2 1 0>, | ||
33 | <&provider3 0>; | ||
34 | empty-property; | ||
35 | unterminated-string = [40 41 42 43]; | ||
36 | }; | ||
37 | }; | ||
38 | }; | ||
39 | }; | ||
diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi deleted file mode 100644 index 3f123ecc9dd7..000000000000 --- a/arch/arm/boot/dts/testcases/tests.dtsi +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | /include/ "tests-phandle.dtsi" | ||
2 | /include/ "tests-interrupts.dtsi" | ||
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts index f43907c40c93..65f657711323 100644 --- a/arch/arm/boot/dts/versatile-pb.dts +++ b/arch/arm/boot/dts/versatile-pb.dts | |||
@@ -1,4 +1,4 @@ | |||
1 | /include/ "versatile-ab.dts" | 1 | #include <versatile-ab.dts> |
2 | 2 | ||
3 | / { | 3 | / { |
4 | model = "ARM Versatile PB"; | 4 | model = "ARM Versatile PB"; |
@@ -47,4 +47,4 @@ | |||
47 | }; | 47 | }; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | /include/ "testcases/tests.dtsi" | 50 | #include <testcases.dtsi> |
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index e9a49fe0284e..8b8b61685a34 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
@@ -212,6 +212,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, | |||
212 | static inline void __flush_icache_all(void) | 212 | static inline void __flush_icache_all(void) |
213 | { | 213 | { |
214 | __flush_icache_preferred(); | 214 | __flush_icache_preferred(); |
215 | dsb(); | ||
215 | } | 216 | } |
216 | 217 | ||
217 | /* | 218 | /* |
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index f82ec22eeb11..49fa0dfaad33 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #include <linux/ptrace.h> | 20 | #include <linux/ptrace.h> |
21 | #include <linux/percpu.h> | 21 | #include <linux/notifier.h> |
22 | 22 | ||
23 | #define __ARCH_WANT_KPROBES_INSN_SLOT | 23 | #define __ARCH_WANT_KPROBES_INSN_SLOT |
24 | #define MAX_INSN_SIZE 2 | 24 | #define MAX_INSN_SIZE 2 |
@@ -28,21 +28,10 @@ | |||
28 | #define kretprobe_blacklist_size 0 | 28 | #define kretprobe_blacklist_size 0 |
29 | 29 | ||
30 | typedef u32 kprobe_opcode_t; | 30 | typedef u32 kprobe_opcode_t; |
31 | |||
32 | struct kprobe; | 31 | struct kprobe; |
33 | typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); | 32 | #include <asm/probes.h> |
34 | typedef unsigned long (kprobe_check_cc)(unsigned long); | ||
35 | typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *); | ||
36 | typedef void (kprobe_insn_fn_t)(void); | ||
37 | 33 | ||
38 | /* Architecture specific copy of original instruction. */ | 34 | #define arch_specific_insn arch_probes_insn |
39 | struct arch_specific_insn { | ||
40 | kprobe_opcode_t *insn; | ||
41 | kprobe_insn_handler_t *insn_handler; | ||
42 | kprobe_check_cc *insn_check_cc; | ||
43 | kprobe_insn_singlestep_t *insn_singlestep; | ||
44 | kprobe_insn_fn_t *insn_fn; | ||
45 | }; | ||
46 | 35 | ||
47 | struct prev_kprobe { | 36 | struct prev_kprobe { |
48 | struct kprobe *kp; | 37 | struct kprobe *kp; |
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h index 03243f7eeddf..85c60adc8b60 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h | |||
@@ -120,13 +120,16 @@ | |||
120 | /* | 120 | /* |
121 | * 2nd stage PTE definitions for LPAE. | 121 | * 2nd stage PTE definitions for LPAE. |
122 | */ | 122 | */ |
123 | #define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */ | 123 | #define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x0) << 2) /* strongly ordered */ |
124 | #define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */ | 124 | #define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* normal inner write-through */ |
125 | #define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */ | 125 | #define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* normal inner write-back */ |
126 | #define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ | 126 | #define L_PTE_S2_MT_DEV_SHARED (_AT(pteval_t, 0x1) << 2) /* device */ |
127 | #define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ | 127 | #define L_PTE_S2_MT_MASK (_AT(pteval_t, 0xf) << 2) |
128 | 128 | ||
129 | #define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ | 129 | #define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ |
130 | #define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ | ||
131 | |||
132 | #define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ | ||
130 | 133 | ||
131 | /* | 134 | /* |
132 | * Hyp-mode PL2 PTE definitions for LPAE. | 135 | * Hyp-mode PL2 PTE definitions for LPAE. |
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h new file mode 100644 index 000000000000..806cfe622a9e --- /dev/null +++ b/arch/arm/include/asm/probes.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/probes.h | ||
3 | * | ||
4 | * Original contents copied from arch/arm/include/asm/kprobes.h | ||
5 | * which contains the following notice... | ||
6 | * | ||
7 | * Copyright (C) 2006, 2007 Motorola Inc. | ||
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 version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #ifndef _ASM_PROBES_H | ||
20 | #define _ASM_PROBES_H | ||
21 | |||
22 | typedef u32 probes_opcode_t; | ||
23 | |||
24 | struct arch_probes_insn; | ||
25 | typedef void (probes_insn_handler_t)(probes_opcode_t, | ||
26 | struct arch_probes_insn *, | ||
27 | struct pt_regs *); | ||
28 | typedef unsigned long (probes_check_cc)(unsigned long); | ||
29 | typedef void (probes_insn_singlestep_t)(probes_opcode_t, | ||
30 | struct arch_probes_insn *, | ||
31 | struct pt_regs *); | ||
32 | typedef void (probes_insn_fn_t)(void); | ||
33 | |||
34 | /* Architecture specific copy of original instruction. */ | ||
35 | struct arch_probes_insn { | ||
36 | probes_opcode_t *insn; | ||
37 | probes_insn_handler_t *insn_handler; | ||
38 | probes_check_cc *insn_check_cc; | ||
39 | probes_insn_singlestep_t *insn_singlestep; | ||
40 | probes_insn_fn_t *insn_fn; | ||
41 | }; | ||
42 | |||
43 | #endif | ||
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 627a03ebb987..c877654fe3bf 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h | |||
@@ -84,6 +84,12 @@ static inline long regs_return_value(struct pt_regs *regs) | |||
84 | 84 | ||
85 | #define instruction_pointer(regs) (regs)->ARM_pc | 85 | #define instruction_pointer(regs) (regs)->ARM_pc |
86 | 86 | ||
87 | static inline void instruction_pointer_set(struct pt_regs *regs, | ||
88 | unsigned long val) | ||
89 | { | ||
90 | instruction_pointer(regs) = val; | ||
91 | } | ||
92 | |||
87 | #ifdef CONFIG_SMP | 93 | #ifdef CONFIG_SMP |
88 | extern unsigned long profile_pc(struct pt_regs *regs); | 94 | extern unsigned long profile_pc(struct pt_regs *regs); |
89 | #else | 95 | #else |
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index ef3c6072aa45..ac4bfae26702 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h | |||
@@ -37,18 +37,9 @@ | |||
37 | 37 | ||
38 | static inline void dsb_sev(void) | 38 | static inline void dsb_sev(void) |
39 | { | 39 | { |
40 | #if __LINUX_ARM_ARCH__ >= 7 | 40 | |
41 | __asm__ __volatile__ ( | 41 | dsb(ishst); |
42 | "dsb ishst\n" | 42 | __asm__(SEV); |
43 | SEV | ||
44 | ); | ||
45 | #else | ||
46 | __asm__ __volatile__ ( | ||
47 | "mcr p15, 0, %0, c7, c10, 4\n" | ||
48 | SEV | ||
49 | : : "r" (0) | ||
50 | ); | ||
51 | #endif | ||
52 | } | 43 | } |
53 | 44 | ||
54 | /* | 45 | /* |
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 71a06b293489..f989d7c22dc5 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h | |||
@@ -153,6 +153,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, | |||
153 | #define TIF_SIGPENDING 0 | 153 | #define TIF_SIGPENDING 0 |
154 | #define TIF_NEED_RESCHED 1 | 154 | #define TIF_NEED_RESCHED 1 |
155 | #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ | 155 | #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ |
156 | #define TIF_UPROBE 7 | ||
156 | #define TIF_SYSCALL_TRACE 8 | 157 | #define TIF_SYSCALL_TRACE 8 |
157 | #define TIF_SYSCALL_AUDIT 9 | 158 | #define TIF_SYSCALL_AUDIT 9 |
158 | #define TIF_SYSCALL_TRACEPOINT 10 | 159 | #define TIF_SYSCALL_TRACEPOINT 10 |
@@ -165,6 +166,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, | |||
165 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | 166 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
166 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | 167 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
167 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | 168 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) |
169 | #define _TIF_UPROBE (1 << TIF_UPROBE) | ||
168 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | 170 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) |
169 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | 171 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) |
170 | #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) | 172 | #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) |
@@ -178,7 +180,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, | |||
178 | /* | 180 | /* |
179 | * Change these and you break ASM code in entry-common.S | 181 | * Change these and you break ASM code in entry-common.S |
180 | */ | 182 | */ |
181 | #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_RESUME) | 183 | #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ |
184 | _TIF_NOTIFY_RESUME | _TIF_UPROBE) | ||
182 | 185 | ||
183 | #endif /* __KERNEL__ */ | 186 | #endif /* __KERNEL__ */ |
184 | #endif /* __ASM_ARM_THREAD_INFO_H */ | 187 | #endif /* __ASM_ARM_THREAD_INFO_H */ |
diff --git a/arch/arm/include/asm/uprobes.h b/arch/arm/include/asm/uprobes.h new file mode 100644 index 000000000000..9472c20b7d49 --- /dev/null +++ b/arch/arm/include/asm/uprobes.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Rabin Vincent <rabin at rab.in> | ||
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 version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ASM_UPROBES_H | ||
10 | #define _ASM_UPROBES_H | ||
11 | |||
12 | #include <asm/probes.h> | ||
13 | #include <asm/opcodes.h> | ||
14 | |||
15 | typedef u32 uprobe_opcode_t; | ||
16 | |||
17 | #define MAX_UINSN_BYTES 4 | ||
18 | #define UPROBE_XOL_SLOT_BYTES 64 | ||
19 | |||
20 | #define UPROBE_SWBP_ARM_INSN 0xe7f001f9 | ||
21 | #define UPROBE_SS_ARM_INSN 0xe7f001fa | ||
22 | #define UPROBE_SWBP_INSN __opcode_to_mem_arm(UPROBE_SWBP_ARM_INSN) | ||
23 | #define UPROBE_SWBP_INSN_SIZE 4 | ||
24 | |||
25 | struct arch_uprobe_task { | ||
26 | u32 backup; | ||
27 | unsigned long saved_trap_no; | ||
28 | }; | ||
29 | |||
30 | struct arch_uprobe { | ||
31 | u8 insn[MAX_UINSN_BYTES]; | ||
32 | unsigned long ixol[2]; | ||
33 | uprobe_opcode_t bpinsn; | ||
34 | bool simulate; | ||
35 | u32 pcreg; | ||
36 | void (*prehandler)(struct arch_uprobe *auprobe, | ||
37 | struct arch_uprobe_task *autask, | ||
38 | struct pt_regs *regs); | ||
39 | void (*posthandler)(struct arch_uprobe *auprobe, | ||
40 | struct arch_uprobe_task *autask, | ||
41 | struct pt_regs *regs); | ||
42 | struct arch_probes_insn asi; | ||
43 | }; | ||
44 | |||
45 | #endif | ||
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index a30fc9be9e9e..a766bcbaf8ad 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -50,11 +50,12 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o | |||
50 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o | 50 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o |
51 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o | 51 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o |
52 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 52 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
53 | obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o patch.o | 53 | obj-$(CONFIG_UPROBES) += probes.o probes-arm.o uprobes.o uprobes-arm.o |
54 | obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o | ||
54 | ifdef CONFIG_THUMB2_KERNEL | 55 | ifdef CONFIG_THUMB2_KERNEL |
55 | obj-$(CONFIG_KPROBES) += kprobes-thumb.o | 56 | obj-$(CONFIG_KPROBES) += kprobes-thumb.o probes-thumb.o |
56 | else | 57 | else |
57 | obj-$(CONFIG_KPROBES) += kprobes-arm.o | 58 | obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-arm.o |
58 | endif | 59 | endif |
59 | obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o | 60 | obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o |
60 | test-kprobes-objs := kprobes-test.o | 61 | test-kprobes-objs := kprobes-test.o |
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 8a30c89da70e..ac300c60d656 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
@@ -60,13 +60,10 @@ | |||
60 | 60 | ||
61 | #include <linux/kernel.h> | 61 | #include <linux/kernel.h> |
62 | #include <linux/kprobes.h> | 62 | #include <linux/kprobes.h> |
63 | #include <linux/module.h> | 63 | #include <linux/ptrace.h> |
64 | 64 | ||
65 | #include "kprobes.h" | 65 | #include "kprobes.h" |
66 | 66 | #include "probes-arm.h" | |
67 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) | ||
68 | |||
69 | #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) | ||
70 | 67 | ||
71 | #if __LINUX_ARM_ARCH__ >= 6 | 68 | #if __LINUX_ARM_ARCH__ >= 6 |
72 | #define BLX(reg) "blx "reg" \n\t" | 69 | #define BLX(reg) "blx "reg" \n\t" |
@@ -75,92 +72,11 @@ | |||
75 | "mov pc, "reg" \n\t" | 72 | "mov pc, "reg" \n\t" |
76 | #endif | 73 | #endif |
77 | 74 | ||
78 | /* | ||
79 | * To avoid the complications of mimicing single-stepping on a | ||
80 | * processor without a Next-PC or a single-step mode, and to | ||
81 | * avoid having to deal with the side-effects of boosting, we | ||
82 | * simulate or emulate (almost) all ARM instructions. | ||
83 | * | ||
84 | * "Simulation" is where the instruction's behavior is duplicated in | ||
85 | * C code. "Emulation" is where the original instruction is rewritten | ||
86 | * and executed, often by altering its registers. | ||
87 | * | ||
88 | * By having all behavior of the kprobe'd instruction completed before | ||
89 | * returning from the kprobe_handler(), all locks (scheduler and | ||
90 | * interrupt) can safely be released. There is no need for secondary | ||
91 | * breakpoints, no race with MP or preemptable kernels, nor having to | ||
92 | * clean up resources counts at a later time impacting overall system | ||
93 | * performance. By rewriting the instruction, only the minimum registers | ||
94 | * need to be loaded and saved back optimizing performance. | ||
95 | * | ||
96 | * Calling the insnslot_*_rwflags version of a function doesn't hurt | ||
97 | * anything even when the CPSR flags aren't updated by the | ||
98 | * instruction. It's just a little slower in return for saving | ||
99 | * a little space by not having a duplicate function that doesn't | ||
100 | * update the flags. (The same optimization can be said for | ||
101 | * instructions that do or don't perform register writeback) | ||
102 | * Also, instructions can either read the flags, only write the | ||
103 | * flags, or read and write the flags. To save combinations | ||
104 | * rather than for sheer performance, flag functions just assume | ||
105 | * read and write of flags. | ||
106 | */ | ||
107 | |||
108 | static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) | ||
109 | { | ||
110 | kprobe_opcode_t insn = p->opcode; | ||
111 | long iaddr = (long)p->addr; | ||
112 | int disp = branch_displacement(insn); | ||
113 | |||
114 | if (insn & (1 << 24)) | ||
115 | regs->ARM_lr = iaddr + 4; | ||
116 | |||
117 | regs->ARM_pc = iaddr + 8 + disp; | ||
118 | } | ||
119 | |||
120 | static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) | ||
121 | { | ||
122 | kprobe_opcode_t insn = p->opcode; | ||
123 | long iaddr = (long)p->addr; | ||
124 | int disp = branch_displacement(insn); | ||
125 | |||
126 | regs->ARM_lr = iaddr + 4; | ||
127 | regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2); | ||
128 | regs->ARM_cpsr |= PSR_T_BIT; | ||
129 | } | ||
130 | |||
131 | static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) | ||
132 | { | ||
133 | kprobe_opcode_t insn = p->opcode; | ||
134 | int rm = insn & 0xf; | ||
135 | long rmv = regs->uregs[rm]; | ||
136 | |||
137 | if (insn & (1 << 5)) | ||
138 | regs->ARM_lr = (long)p->addr + 4; | ||
139 | |||
140 | regs->ARM_pc = rmv & ~0x1; | ||
141 | regs->ARM_cpsr &= ~PSR_T_BIT; | ||
142 | if (rmv & 0x1) | ||
143 | regs->ARM_cpsr |= PSR_T_BIT; | ||
144 | } | ||
145 | |||
146 | static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) | ||
147 | { | ||
148 | kprobe_opcode_t insn = p->opcode; | ||
149 | int rd = (insn >> 12) & 0xf; | ||
150 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ | ||
151 | regs->uregs[rd] = regs->ARM_cpsr & mask; | ||
152 | } | ||
153 | |||
154 | static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) | ||
155 | { | ||
156 | regs->uregs[12] = regs->uregs[13]; | ||
157 | } | ||
158 | |||
159 | static void __kprobes | 75 | static void __kprobes |
160 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | 76 | emulate_ldrdstrd(probes_opcode_t insn, |
77 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
161 | { | 78 | { |
162 | kprobe_opcode_t insn = p->opcode; | 79 | unsigned long pc = regs->ARM_pc + 4; |
163 | unsigned long pc = (unsigned long)p->addr + 8; | ||
164 | int rt = (insn >> 12) & 0xf; | 80 | int rt = (insn >> 12) & 0xf; |
165 | int rn = (insn >> 16) & 0xf; | 81 | int rn = (insn >> 16) & 0xf; |
166 | int rm = insn & 0xf; | 82 | int rm = insn & 0xf; |
@@ -175,7 +91,7 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
175 | BLX("%[fn]") | 91 | BLX("%[fn]") |
176 | : "=r" (rtv), "=r" (rt2v), "=r" (rnv) | 92 | : "=r" (rtv), "=r" (rt2v), "=r" (rnv) |
177 | : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), | 93 | : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), |
178 | [fn] "r" (p->ainsn.insn_fn) | 94 | [fn] "r" (asi->insn_fn) |
179 | : "lr", "memory", "cc" | 95 | : "lr", "memory", "cc" |
180 | ); | 96 | ); |
181 | 97 | ||
@@ -186,10 +102,10 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
186 | } | 102 | } |
187 | 103 | ||
188 | static void __kprobes | 104 | static void __kprobes |
189 | emulate_ldr(struct kprobe *p, struct pt_regs *regs) | 105 | emulate_ldr(probes_opcode_t insn, |
106 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
190 | { | 107 | { |
191 | kprobe_opcode_t insn = p->opcode; | 108 | unsigned long pc = regs->ARM_pc + 4; |
192 | unsigned long pc = (unsigned long)p->addr + 8; | ||
193 | int rt = (insn >> 12) & 0xf; | 109 | int rt = (insn >> 12) & 0xf; |
194 | int rn = (insn >> 16) & 0xf; | 110 | int rn = (insn >> 16) & 0xf; |
195 | int rm = insn & 0xf; | 111 | int rm = insn & 0xf; |
@@ -202,7 +118,7 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs) | |||
202 | __asm__ __volatile__ ( | 118 | __asm__ __volatile__ ( |
203 | BLX("%[fn]") | 119 | BLX("%[fn]") |
204 | : "=r" (rtv), "=r" (rnv) | 120 | : "=r" (rtv), "=r" (rnv) |
205 | : "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | 121 | : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) |
206 | : "lr", "memory", "cc" | 122 | : "lr", "memory", "cc" |
207 | ); | 123 | ); |
208 | 124 | ||
@@ -216,11 +132,11 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs) | |||
216 | } | 132 | } |
217 | 133 | ||
218 | static void __kprobes | 134 | static void __kprobes |
219 | emulate_str(struct kprobe *p, struct pt_regs *regs) | 135 | emulate_str(probes_opcode_t insn, |
136 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
220 | { | 137 | { |
221 | kprobe_opcode_t insn = p->opcode; | 138 | unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset; |
222 | unsigned long rtpc = (unsigned long)p->addr + str_pc_offset; | 139 | unsigned long rnpc = regs->ARM_pc + 4; |
223 | unsigned long rnpc = (unsigned long)p->addr + 8; | ||
224 | int rt = (insn >> 12) & 0xf; | 140 | int rt = (insn >> 12) & 0xf; |
225 | int rn = (insn >> 16) & 0xf; | 141 | int rn = (insn >> 16) & 0xf; |
226 | int rm = insn & 0xf; | 142 | int rm = insn & 0xf; |
@@ -234,7 +150,7 @@ emulate_str(struct kprobe *p, struct pt_regs *regs) | |||
234 | __asm__ __volatile__ ( | 150 | __asm__ __volatile__ ( |
235 | BLX("%[fn]") | 151 | BLX("%[fn]") |
236 | : "=r" (rnv) | 152 | : "=r" (rnv) |
237 | : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | 153 | : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) |
238 | : "lr", "memory", "cc" | 154 | : "lr", "memory", "cc" |
239 | ); | 155 | ); |
240 | 156 | ||
@@ -243,10 +159,10 @@ emulate_str(struct kprobe *p, struct pt_regs *regs) | |||
243 | } | 159 | } |
244 | 160 | ||
245 | static void __kprobes | 161 | static void __kprobes |
246 | emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | 162 | emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, |
163 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
247 | { | 164 | { |
248 | kprobe_opcode_t insn = p->opcode; | 165 | unsigned long pc = regs->ARM_pc + 4; |
249 | unsigned long pc = (unsigned long)p->addr + 8; | ||
250 | int rd = (insn >> 12) & 0xf; | 166 | int rd = (insn >> 12) & 0xf; |
251 | int rn = (insn >> 16) & 0xf; | 167 | int rn = (insn >> 16) & 0xf; |
252 | int rm = insn & 0xf; | 168 | int rm = insn & 0xf; |
@@ -266,7 +182,7 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
266 | "mrs %[cpsr], cpsr \n\t" | 182 | "mrs %[cpsr], cpsr \n\t" |
267 | : "=r" (rdv), [cpsr] "=r" (cpsr) | 183 | : "=r" (rdv), [cpsr] "=r" (cpsr) |
268 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), | 184 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), |
269 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 185 | "1" (cpsr), [fn] "r" (asi->insn_fn) |
270 | : "lr", "memory", "cc" | 186 | : "lr", "memory", "cc" |
271 | ); | 187 | ); |
272 | 188 | ||
@@ -278,9 +194,9 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
278 | } | 194 | } |
279 | 195 | ||
280 | static void __kprobes | 196 | static void __kprobes |
281 | emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 197 | emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn, |
198 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
282 | { | 199 | { |
283 | kprobe_opcode_t insn = p->opcode; | ||
284 | int rd = (insn >> 12) & 0xf; | 200 | int rd = (insn >> 12) & 0xf; |
285 | int rn = (insn >> 16) & 0xf; | 201 | int rn = (insn >> 16) & 0xf; |
286 | int rm = insn & 0xf; | 202 | int rm = insn & 0xf; |
@@ -296,7 +212,7 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
296 | "mrs %[cpsr], cpsr \n\t" | 212 | "mrs %[cpsr], cpsr \n\t" |
297 | : "=r" (rdv), [cpsr] "=r" (cpsr) | 213 | : "=r" (rdv), [cpsr] "=r" (cpsr) |
298 | : "0" (rdv), "r" (rnv), "r" (rmv), | 214 | : "0" (rdv), "r" (rnv), "r" (rmv), |
299 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 215 | "1" (cpsr), [fn] "r" (asi->insn_fn) |
300 | : "lr", "memory", "cc" | 216 | : "lr", "memory", "cc" |
301 | ); | 217 | ); |
302 | 218 | ||
@@ -305,9 +221,10 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
305 | } | 221 | } |
306 | 222 | ||
307 | static void __kprobes | 223 | static void __kprobes |
308 | emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 224 | emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn, |
225 | struct arch_probes_insn *asi, | ||
226 | struct pt_regs *regs) | ||
309 | { | 227 | { |
310 | kprobe_opcode_t insn = p->opcode; | ||
311 | int rd = (insn >> 16) & 0xf; | 228 | int rd = (insn >> 16) & 0xf; |
312 | int rn = (insn >> 12) & 0xf; | 229 | int rn = (insn >> 12) & 0xf; |
313 | int rm = insn & 0xf; | 230 | int rm = insn & 0xf; |
@@ -325,7 +242,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
325 | "mrs %[cpsr], cpsr \n\t" | 242 | "mrs %[cpsr], cpsr \n\t" |
326 | : "=r" (rdv), [cpsr] "=r" (cpsr) | 243 | : "=r" (rdv), [cpsr] "=r" (cpsr) |
327 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), | 244 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), |
328 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 245 | "1" (cpsr), [fn] "r" (asi->insn_fn) |
329 | : "lr", "memory", "cc" | 246 | : "lr", "memory", "cc" |
330 | ); | 247 | ); |
331 | 248 | ||
@@ -334,9 +251,9 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
334 | } | 251 | } |
335 | 252 | ||
336 | static void __kprobes | 253 | static void __kprobes |
337 | emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | 254 | emulate_rd12rm0_noflags_nopc(probes_opcode_t insn, |
255 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
338 | { | 256 | { |
339 | kprobe_opcode_t insn = p->opcode; | ||
340 | int rd = (insn >> 12) & 0xf; | 257 | int rd = (insn >> 12) & 0xf; |
341 | int rm = insn & 0xf; | 258 | int rm = insn & 0xf; |
342 | 259 | ||
@@ -346,7 +263,7 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
346 | __asm__ __volatile__ ( | 263 | __asm__ __volatile__ ( |
347 | BLX("%[fn]") | 264 | BLX("%[fn]") |
348 | : "=r" (rdv) | 265 | : "=r" (rdv) |
349 | : "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | 266 | : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn) |
350 | : "lr", "memory", "cc" | 267 | : "lr", "memory", "cc" |
351 | ); | 268 | ); |
352 | 269 | ||
@@ -354,9 +271,10 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
354 | } | 271 | } |
355 | 272 | ||
356 | static void __kprobes | 273 | static void __kprobes |
357 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 274 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, |
275 | struct arch_probes_insn *asi, | ||
276 | struct pt_regs *regs) | ||
358 | { | 277 | { |
359 | kprobe_opcode_t insn = p->opcode; | ||
360 | int rdlo = (insn >> 12) & 0xf; | 278 | int rdlo = (insn >> 12) & 0xf; |
361 | int rdhi = (insn >> 16) & 0xf; | 279 | int rdhi = (insn >> 16) & 0xf; |
362 | int rn = insn & 0xf; | 280 | int rn = insn & 0xf; |
@@ -374,7 +292,7 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
374 | "mrs %[cpsr], cpsr \n\t" | 292 | "mrs %[cpsr], cpsr \n\t" |
375 | : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) | 293 | : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) |
376 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), | 294 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), |
377 | "2" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 295 | "2" (cpsr), [fn] "r" (asi->insn_fn) |
378 | : "lr", "memory", "cc" | 296 | : "lr", "memory", "cc" |
379 | ); | 297 | ); |
380 | 298 | ||
@@ -383,623 +301,43 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
383 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 301 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
384 | } | 302 | } |
385 | 303 | ||
386 | /* | 304 | const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { |
387 | * For the instruction masking and comparisons in all the "space_*" | 305 | [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none}, |
388 | * functions below, Do _not_ rearrange the order of tests unless | 306 | [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, |
389 | * you're very, very sure of what you are doing. For the sake of | 307 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, |
390 | * efficiency, the masks for some tests sometimes assume other test | 308 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, |
391 | * have been done prior to them so the number of patterns to test | 309 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, |
392 | * for an instruction set can be as broad as possible to reduce the | 310 | [PROBES_MRS] = {.handler = simulate_mrs}, |
393 | * number of tests needed. | 311 | [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, |
394 | */ | 312 | [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc}, |
395 | 313 | [PROBES_SATURATING_ARITHMETIC] = { | |
396 | static const union decode_item arm_1111_table[] = { | 314 | .handler = emulate_rd12rn16rm0_rwflags_nopc}, |
397 | /* Unconditional instructions */ | 315 | [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, |
398 | 316 | [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, | |
399 | /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */ | 317 | [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, |
400 | /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */ | 318 | [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd}, |
401 | /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */ | 319 | [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr}, |
402 | /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */ | 320 | [PROBES_LOAD] = {.handler = emulate_ldr}, |
403 | DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop), | 321 | [PROBES_STORE_EXTRA] = {.handler = emulate_str}, |
404 | 322 | [PROBES_STORE] = {.handler = emulate_str}, | |
405 | /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */ | 323 | [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, |
406 | /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */ | 324 | [PROBES_DATA_PROCESSING_REG] = { |
407 | /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */ | 325 | .handler = emulate_rd12rn16rm0rs8_rwflags}, |
408 | /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */ | 326 | [PROBES_DATA_PROCESSING_IMM] = { |
409 | DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop), | 327 | .handler = emulate_rd12rn16rm0rs8_rwflags}, |
410 | 328 | [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc}, | |
411 | /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ | 329 | [PROBES_SEV] = {.handler = probes_emulate_none}, |
412 | DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1), | 330 | [PROBES_WFE] = {.handler = probes_simulate_nop}, |
413 | 331 | [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, | |
414 | /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */ | 332 | [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc}, |
415 | /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ | 333 | [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, |
416 | /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | 334 | [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, |
417 | /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | 335 | [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc}, |
418 | 336 | [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, | |
419 | /* Coprocessor instructions... */ | 337 | [PROBES_MUL_ADD_LONG] = { |
420 | /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | 338 | .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, |
421 | /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | 339 | [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, |
422 | /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | 340 | [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc}, |
423 | /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | 341 | [PROBES_BRANCH] = {.handler = simulate_bbl}, |
424 | /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | 342 | [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} |
425 | /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | ||
426 | /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | ||
427 | |||
428 | /* Other unallocated instructions... */ | ||
429 | DECODE_END | ||
430 | }; | ||
431 | |||
432 | static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = { | ||
433 | /* Miscellaneous instructions */ | ||
434 | |||
435 | /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ | ||
436 | DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs, | ||
437 | REGS(0, NOPC, 0, 0, 0)), | ||
438 | |||
439 | /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
440 | DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx), | ||
441 | |||
442 | /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
443 | DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx, | ||
444 | REGS(0, 0, 0, 0, NOPC)), | ||
445 | |||
446 | /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
447 | DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc, | ||
448 | REGS(0, NOPC, 0, 0, NOPC)), | ||
449 | |||
450 | /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */ | ||
451 | /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
452 | /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */ | ||
453 | /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
454 | DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc, | ||
455 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
456 | |||
457 | /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ | ||
458 | /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ | ||
459 | /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ | ||
460 | /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
461 | /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
462 | /* And unallocated instructions... */ | ||
463 | DECODE_END | ||
464 | }; | ||
465 | |||
466 | static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = { | ||
467 | /* Halfword multiply and multiply-accumulate */ | ||
468 | |||
469 | /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ | ||
470 | DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
471 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
472 | |||
473 | /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ | ||
474 | DECODE_OR (0x0ff000b0, 0x012000a0), | ||
475 | /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ | ||
476 | DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
477 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
478 | |||
479 | /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */ | ||
480 | DECODE_OR (0x0ff00090, 0x01000080), | ||
481 | /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */ | ||
482 | DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
483 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
484 | |||
485 | DECODE_END | ||
486 | }; | 343 | }; |
487 | |||
488 | static const union decode_item arm_cccc_0000_____1001_table[] = { | ||
489 | /* Multiply and multiply-accumulate */ | ||
490 | |||
491 | /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */ | ||
492 | /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
493 | DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
494 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
495 | |||
496 | /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
497 | /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
498 | DECODE_OR (0x0fe000f0, 0x00200090), | ||
499 | /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
500 | DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
501 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
502 | |||
503 | /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */ | ||
504 | DECODE_OR (0x0ff000f0, 0x00400090), | ||
505 | /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */ | ||
506 | /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */ | ||
507 | /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */ | ||
508 | /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */ | ||
509 | /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */ | ||
510 | /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */ | ||
511 | /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */ | ||
512 | /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */ | ||
513 | DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
514 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
515 | |||
516 | DECODE_END | ||
517 | }; | ||
518 | |||
519 | static const union decode_item arm_cccc_0001_____1001_table[] = { | ||
520 | /* Synchronization primitives */ | ||
521 | |||
522 | #if __LINUX_ARM_ARCH__ < 6 | ||
523 | /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ | ||
524 | /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ | ||
525 | DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, | ||
526 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
527 | #endif | ||
528 | /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ | ||
529 | /* And unallocated instructions... */ | ||
530 | DECODE_END | ||
531 | }; | ||
532 | |||
533 | static const union decode_item arm_cccc_000x_____1xx1_table[] = { | ||
534 | /* Extra load/store instructions */ | ||
535 | |||
536 | /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */ | ||
537 | /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */ | ||
538 | /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */ | ||
539 | /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */ | ||
540 | /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */ | ||
541 | DECODE_REJECT (0x0f200090, 0x00200090), | ||
542 | |||
543 | /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */ | ||
544 | DECODE_REJECT (0x0e10e0d0, 0x0000e0d0), | ||
545 | |||
546 | /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */ | ||
547 | /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */ | ||
548 | DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd, | ||
549 | REGS(NOPCWB, NOPCX, 0, 0, NOPC)), | ||
550 | |||
551 | /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */ | ||
552 | /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */ | ||
553 | DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd, | ||
554 | REGS(NOPCWB, NOPCX, 0, 0, 0)), | ||
555 | |||
556 | /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ | ||
557 | DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str, | ||
558 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | ||
559 | |||
560 | /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */ | ||
561 | /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */ | ||
562 | /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */ | ||
563 | DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr, | ||
564 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | ||
565 | |||
566 | /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ | ||
567 | DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str, | ||
568 | REGS(NOPCWB, NOPC, 0, 0, 0)), | ||
569 | |||
570 | /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */ | ||
571 | /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */ | ||
572 | /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */ | ||
573 | DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr, | ||
574 | REGS(NOPCWB, NOPC, 0, 0, 0)), | ||
575 | |||
576 | DECODE_END | ||
577 | }; | ||
578 | |||
579 | static const union decode_item arm_cccc_000x_table[] = { | ||
580 | /* Data-processing (register) */ | ||
581 | |||
582 | /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */ | ||
583 | DECODE_REJECT (0x0e10f000, 0x0010f000), | ||
584 | |||
585 | /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */ | ||
586 | DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp), | ||
587 | |||
588 | /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */ | ||
589 | /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */ | ||
590 | /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */ | ||
591 | /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */ | ||
592 | DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags, | ||
593 | REGS(ANY, 0, 0, 0, ANY)), | ||
594 | |||
595 | /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */ | ||
596 | /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */ | ||
597 | DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags, | ||
598 | REGS(0, ANY, 0, 0, ANY)), | ||
599 | |||
600 | /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */ | ||
601 | /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */ | ||
602 | /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */ | ||
603 | /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */ | ||
604 | /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */ | ||
605 | /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */ | ||
606 | /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */ | ||
607 | /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */ | ||
608 | /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */ | ||
609 | /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */ | ||
610 | DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags, | ||
611 | REGS(ANY, ANY, 0, 0, ANY)), | ||
612 | |||
613 | /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */ | ||
614 | /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */ | ||
615 | /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */ | ||
616 | /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */ | ||
617 | DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags, | ||
618 | REGS(ANY, 0, NOPC, 0, ANY)), | ||
619 | |||
620 | /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */ | ||
621 | /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */ | ||
622 | DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags, | ||
623 | REGS(0, ANY, NOPC, 0, ANY)), | ||
624 | |||
625 | /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */ | ||
626 | /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */ | ||
627 | /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */ | ||
628 | /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */ | ||
629 | /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */ | ||
630 | /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */ | ||
631 | /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */ | ||
632 | /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */ | ||
633 | /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */ | ||
634 | /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */ | ||
635 | DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, | ||
636 | REGS(ANY, ANY, NOPC, 0, ANY)), | ||
637 | |||
638 | DECODE_END | ||
639 | }; | ||
640 | |||
641 | static const union decode_item arm_cccc_001x_table[] = { | ||
642 | /* Data-processing (immediate) */ | ||
643 | |||
644 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ | ||
645 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
646 | DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc, | ||
647 | REGS(0, NOPC, 0, 0, 0)), | ||
648 | |||
649 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | ||
650 | DECODE_OR (0x0fff00ff, 0x03200001), | ||
651 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ | ||
652 | DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none), | ||
653 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ | ||
654 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ | ||
655 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ | ||
656 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop), | ||
657 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ | ||
658 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ | ||
659 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ | ||
660 | DECODE_REJECT (0x0fb00000, 0x03200000), | ||
661 | |||
662 | /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ | ||
663 | DECODE_REJECT (0x0e10f000, 0x0210f000), | ||
664 | |||
665 | /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */ | ||
666 | /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */ | ||
667 | /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
668 | /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */ | ||
669 | DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags, | ||
670 | REGS(ANY, 0, 0, 0, 0)), | ||
671 | |||
672 | /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */ | ||
673 | /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */ | ||
674 | DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags, | ||
675 | REGS(0, ANY, 0, 0, 0)), | ||
676 | |||
677 | /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */ | ||
678 | /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */ | ||
679 | /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */ | ||
680 | /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */ | ||
681 | /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */ | ||
682 | /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */ | ||
683 | /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */ | ||
684 | /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */ | ||
685 | /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */ | ||
686 | /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */ | ||
687 | DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags, | ||
688 | REGS(ANY, ANY, 0, 0, 0)), | ||
689 | |||
690 | DECODE_END | ||
691 | }; | ||
692 | |||
693 | static const union decode_item arm_cccc_0110_____xxx1_table[] = { | ||
694 | /* Media instructions */ | ||
695 | |||
696 | /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */ | ||
697 | DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc, | ||
698 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
699 | |||
700 | /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */ | ||
701 | /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */ | ||
702 | DECODE_OR(0x0fa00030, 0x06a00010), | ||
703 | /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */ | ||
704 | /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */ | ||
705 | DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc, | ||
706 | REGS(0, NOPC, 0, 0, NOPC)), | ||
707 | |||
708 | /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */ | ||
709 | /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */ | ||
710 | /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */ | ||
711 | /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */ | ||
712 | DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc, | ||
713 | REGS(0, NOPC, 0, 0, NOPC)), | ||
714 | |||
715 | /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */ | ||
716 | DECODE_REJECT (0x0fb00010, 0x06000010), | ||
717 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */ | ||
718 | DECODE_REJECT (0x0f8000f0, 0x060000b0), | ||
719 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */ | ||
720 | DECODE_REJECT (0x0f8000f0, 0x060000d0), | ||
721 | /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */ | ||
722 | /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */ | ||
723 | /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */ | ||
724 | /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */ | ||
725 | /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
726 | /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */ | ||
727 | /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
728 | /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
729 | /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
730 | /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
731 | /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
732 | /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */ | ||
733 | /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */ | ||
734 | /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */ | ||
735 | /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */ | ||
736 | /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */ | ||
737 | /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
738 | /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */ | ||
739 | /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */ | ||
740 | /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */ | ||
741 | /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */ | ||
742 | /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */ | ||
743 | /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */ | ||
744 | /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */ | ||
745 | /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
746 | /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */ | ||
747 | /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
748 | /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
749 | /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
750 | /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */ | ||
751 | /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */ | ||
752 | /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */ | ||
753 | /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */ | ||
754 | /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */ | ||
755 | /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */ | ||
756 | /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */ | ||
757 | DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc, | ||
758 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
759 | |||
760 | /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */ | ||
761 | /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */ | ||
762 | DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc, | ||
763 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
764 | |||
765 | /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */ | ||
766 | /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */ | ||
767 | DECODE_REJECT (0x0fb000f0, 0x06900070), | ||
768 | |||
769 | /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */ | ||
770 | /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */ | ||
771 | /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */ | ||
772 | /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */ | ||
773 | /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */ | ||
774 | /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */ | ||
775 | DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc, | ||
776 | REGS(0, NOPC, 0, 0, NOPC)), | ||
777 | |||
778 | /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */ | ||
779 | /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */ | ||
780 | /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */ | ||
781 | /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */ | ||
782 | /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */ | ||
783 | /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */ | ||
784 | DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc, | ||
785 | REGS(NOPCX, NOPC, 0, 0, NOPC)), | ||
786 | |||
787 | DECODE_END | ||
788 | }; | ||
789 | |||
790 | static const union decode_item arm_cccc_0111_____xxx1_table[] = { | ||
791 | /* Media instructions */ | ||
792 | |||
793 | /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */ | ||
794 | DECODE_REJECT (0x0ff000f0, 0x07f000f0), | ||
795 | |||
796 | /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */ | ||
797 | /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */ | ||
798 | DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
799 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
800 | |||
801 | /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */ | ||
802 | /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */ | ||
803 | DECODE_OR (0x0ff0f090, 0x0700f010), | ||
804 | /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */ | ||
805 | DECODE_OR (0x0ff0f0d0, 0x0750f010), | ||
806 | /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */ | ||
807 | DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
808 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
809 | |||
810 | /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */ | ||
811 | /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */ | ||
812 | DECODE_OR (0x0ff00090, 0x07000010), | ||
813 | /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */ | ||
814 | DECODE_OR (0x0ff000d0, 0x07500010), | ||
815 | /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */ | ||
816 | DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
817 | REGS(NOPC, NOPCX, NOPC, 0, NOPC)), | ||
818 | |||
819 | /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ | ||
820 | DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
821 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
822 | |||
823 | /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */ | ||
824 | /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */ | ||
825 | DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc, | ||
826 | REGS(0, NOPC, 0, 0, NOPC)), | ||
827 | |||
828 | /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ | ||
829 | DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc, | ||
830 | REGS(0, NOPC, 0, 0, 0)), | ||
831 | |||
832 | /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ | ||
833 | DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc, | ||
834 | REGS(0, NOPC, 0, 0, NOPCX)), | ||
835 | |||
836 | DECODE_END | ||
837 | }; | ||
838 | |||
839 | static const union decode_item arm_cccc_01xx_table[] = { | ||
840 | /* Load/store word and unsigned byte */ | ||
841 | |||
842 | /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */ | ||
843 | DECODE_REJECT (0x0c40f000, 0x0440f000), | ||
844 | |||
845 | /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */ | ||
846 | /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */ | ||
847 | /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */ | ||
848 | /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */ | ||
849 | DECODE_REJECT (0x0d200000, 0x04200000), | ||
850 | |||
851 | /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
852 | /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
853 | DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str, | ||
854 | REGS(NOPCWB, ANY, 0, 0, 0)), | ||
855 | |||
856 | /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
857 | /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
858 | DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr, | ||
859 | REGS(NOPCWB, ANY, 0, 0, 0)), | ||
860 | |||
861 | /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
862 | /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
863 | DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str, | ||
864 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | ||
865 | |||
866 | /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
867 | /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
868 | DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr, | ||
869 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | ||
870 | |||
871 | DECODE_END | ||
872 | }; | ||
873 | |||
874 | static const union decode_item arm_cccc_100x_table[] = { | ||
875 | /* Block data transfer instructions */ | ||
876 | |||
877 | /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
878 | /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
879 | DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm), | ||
880 | |||
881 | /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
882 | /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */ | ||
883 | /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */ | ||
884 | DECODE_END | ||
885 | }; | ||
886 | |||
887 | const union decode_item kprobe_decode_arm_table[] = { | ||
888 | /* | ||
889 | * Unconditional instructions | ||
890 | * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx | ||
891 | */ | ||
892 | DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table), | ||
893 | |||
894 | /* | ||
895 | * Miscellaneous instructions | ||
896 | * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx | ||
897 | */ | ||
898 | DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table), | ||
899 | |||
900 | /* | ||
901 | * Halfword multiply and multiply-accumulate | ||
902 | * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx | ||
903 | */ | ||
904 | DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table), | ||
905 | |||
906 | /* | ||
907 | * Multiply and multiply-accumulate | ||
908 | * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx | ||
909 | */ | ||
910 | DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table), | ||
911 | |||
912 | /* | ||
913 | * Synchronization primitives | ||
914 | * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx | ||
915 | */ | ||
916 | DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table), | ||
917 | |||
918 | /* | ||
919 | * Extra load/store instructions | ||
920 | * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx | ||
921 | */ | ||
922 | DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table), | ||
923 | |||
924 | /* | ||
925 | * Data-processing (register) | ||
926 | * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx | ||
927 | * Data-processing (register-shifted register) | ||
928 | * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx | ||
929 | */ | ||
930 | DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table), | ||
931 | |||
932 | /* | ||
933 | * Data-processing (immediate) | ||
934 | * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx | ||
935 | */ | ||
936 | DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table), | ||
937 | |||
938 | /* | ||
939 | * Media instructions | ||
940 | * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx | ||
941 | */ | ||
942 | DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table), | ||
943 | DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table), | ||
944 | |||
945 | /* | ||
946 | * Load/store word and unsigned byte | ||
947 | * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx | ||
948 | */ | ||
949 | DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table), | ||
950 | |||
951 | /* | ||
952 | * Block data transfer instructions | ||
953 | * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx | ||
954 | */ | ||
955 | DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table), | ||
956 | |||
957 | /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
958 | /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
959 | DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl), | ||
960 | |||
961 | /* | ||
962 | * Supervisor Call, and coprocessor instructions | ||
963 | */ | ||
964 | |||
965 | /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
966 | /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
967 | /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | ||
968 | /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | ||
969 | /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | ||
970 | /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | ||
971 | /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | ||
972 | /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
973 | DECODE_REJECT (0x0c000000, 0x0c000000), | ||
974 | |||
975 | DECODE_END | ||
976 | }; | ||
977 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE | ||
978 | EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); | ||
979 | #endif | ||
980 | |||
981 | static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) | ||
982 | { | ||
983 | regs->ARM_pc += 4; | ||
984 | p->ainsn.insn_handler(p, regs); | ||
985 | } | ||
986 | |||
987 | /* Return: | ||
988 | * INSN_REJECTED If instruction is one not allowed to kprobe, | ||
989 | * INSN_GOOD If instruction is supported and uses instruction slot, | ||
990 | * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. | ||
991 | * | ||
992 | * For instructions we don't want to kprobe (INSN_REJECTED return result): | ||
993 | * These are generally ones that modify the processor state making | ||
994 | * them "hard" to simulate such as switches processor modes or | ||
995 | * make accesses in alternate modes. Any of these could be simulated | ||
996 | * if the work was put into it, but low return considering they | ||
997 | * should also be very rare. | ||
998 | */ | ||
999 | enum kprobe_insn __kprobes | ||
1000 | arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | ||
1001 | { | ||
1002 | asi->insn_singlestep = arm_singlestep; | ||
1003 | asi->insn_check_cc = kprobe_condition_checks[insn>>28]; | ||
1004 | return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false); | ||
1005 | } | ||
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c index 18a76282970e..c311ed94ff1c 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/kernel/kprobes-common.c | |||
@@ -13,178 +13,14 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/kprobes.h> | 15 | #include <linux/kprobes.h> |
16 | #include <asm/system_info.h> | ||
17 | 16 | ||
18 | #include "kprobes.h" | 17 | #include "kprobes.h" |
19 | 18 | ||
20 | 19 | ||
21 | #ifndef find_str_pc_offset | 20 | static void __kprobes simulate_ldm1stm1(probes_opcode_t insn, |
22 | 21 | struct arch_probes_insn *asi, | |
23 | /* | 22 | struct pt_regs *regs) |
24 | * For STR and STM instructions, an ARM core may choose to use either | ||
25 | * a +8 or a +12 displacement from the current instruction's address. | ||
26 | * Whichever value is chosen for a given core, it must be the same for | ||
27 | * both instructions and may not change. This function measures it. | ||
28 | */ | ||
29 | |||
30 | int str_pc_offset; | ||
31 | |||
32 | void __init find_str_pc_offset(void) | ||
33 | { | ||
34 | int addr, scratch, ret; | ||
35 | |||
36 | __asm__ ( | ||
37 | "sub %[ret], pc, #4 \n\t" | ||
38 | "str pc, %[addr] \n\t" | ||
39 | "ldr %[scr], %[addr] \n\t" | ||
40 | "sub %[ret], %[scr], %[ret] \n\t" | ||
41 | : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr)); | ||
42 | |||
43 | str_pc_offset = ret; | ||
44 | } | ||
45 | |||
46 | #endif /* !find_str_pc_offset */ | ||
47 | |||
48 | |||
49 | #ifndef test_load_write_pc_interworking | ||
50 | |||
51 | bool load_write_pc_interworks; | ||
52 | |||
53 | void __init test_load_write_pc_interworking(void) | ||
54 | { | ||
55 | int arch = cpu_architecture(); | ||
56 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
57 | load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T; | ||
58 | } | ||
59 | |||
60 | #endif /* !test_load_write_pc_interworking */ | ||
61 | |||
62 | |||
63 | #ifndef test_alu_write_pc_interworking | ||
64 | |||
65 | bool alu_write_pc_interworks; | ||
66 | |||
67 | void __init test_alu_write_pc_interworking(void) | ||
68 | { | ||
69 | int arch = cpu_architecture(); | ||
70 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
71 | alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7; | ||
72 | } | ||
73 | |||
74 | #endif /* !test_alu_write_pc_interworking */ | ||
75 | |||
76 | |||
77 | void __init arm_kprobe_decode_init(void) | ||
78 | { | ||
79 | find_str_pc_offset(); | ||
80 | test_load_write_pc_interworking(); | ||
81 | test_alu_write_pc_interworking(); | ||
82 | } | ||
83 | |||
84 | |||
85 | static unsigned long __kprobes __check_eq(unsigned long cpsr) | ||
86 | { | ||
87 | return cpsr & PSR_Z_BIT; | ||
88 | } | ||
89 | |||
90 | static unsigned long __kprobes __check_ne(unsigned long cpsr) | ||
91 | { | ||
92 | return (~cpsr) & PSR_Z_BIT; | ||
93 | } | ||
94 | |||
95 | static unsigned long __kprobes __check_cs(unsigned long cpsr) | ||
96 | { | ||
97 | return cpsr & PSR_C_BIT; | ||
98 | } | ||
99 | |||
100 | static unsigned long __kprobes __check_cc(unsigned long cpsr) | ||
101 | { | ||
102 | return (~cpsr) & PSR_C_BIT; | ||
103 | } | ||
104 | |||
105 | static unsigned long __kprobes __check_mi(unsigned long cpsr) | ||
106 | { | ||
107 | return cpsr & PSR_N_BIT; | ||
108 | } | ||
109 | |||
110 | static unsigned long __kprobes __check_pl(unsigned long cpsr) | ||
111 | { | ||
112 | return (~cpsr) & PSR_N_BIT; | ||
113 | } | ||
114 | |||
115 | static unsigned long __kprobes __check_vs(unsigned long cpsr) | ||
116 | { | ||
117 | return cpsr & PSR_V_BIT; | ||
118 | } | ||
119 | |||
120 | static unsigned long __kprobes __check_vc(unsigned long cpsr) | ||
121 | { | ||
122 | return (~cpsr) & PSR_V_BIT; | ||
123 | } | ||
124 | |||
125 | static unsigned long __kprobes __check_hi(unsigned long cpsr) | ||
126 | { | ||
127 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
128 | return cpsr & PSR_C_BIT; | ||
129 | } | ||
130 | |||
131 | static unsigned long __kprobes __check_ls(unsigned long cpsr) | ||
132 | { | ||
133 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
134 | return (~cpsr) & PSR_C_BIT; | ||
135 | } | ||
136 | |||
137 | static unsigned long __kprobes __check_ge(unsigned long cpsr) | ||
138 | { | ||
139 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
140 | return (~cpsr) & PSR_N_BIT; | ||
141 | } | ||
142 | |||
143 | static unsigned long __kprobes __check_lt(unsigned long cpsr) | ||
144 | { | ||
145 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
146 | return cpsr & PSR_N_BIT; | ||
147 | } | ||
148 | |||
149 | static unsigned long __kprobes __check_gt(unsigned long cpsr) | ||
150 | { | ||
151 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
152 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
153 | return (~temp) & PSR_N_BIT; | ||
154 | } | ||
155 | |||
156 | static unsigned long __kprobes __check_le(unsigned long cpsr) | ||
157 | { | ||
158 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
159 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
160 | return temp & PSR_N_BIT; | ||
161 | } | ||
162 | |||
163 | static unsigned long __kprobes __check_al(unsigned long cpsr) | ||
164 | { | ||
165 | return true; | ||
166 | } | ||
167 | |||
168 | kprobe_check_cc * const kprobe_condition_checks[16] = { | ||
169 | &__check_eq, &__check_ne, &__check_cs, &__check_cc, | ||
170 | &__check_mi, &__check_pl, &__check_vs, &__check_vc, | ||
171 | &__check_hi, &__check_ls, &__check_ge, &__check_lt, | ||
172 | &__check_gt, &__check_le, &__check_al, &__check_al | ||
173 | }; | ||
174 | |||
175 | |||
176 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs) | ||
177 | { | ||
178 | } | ||
179 | |||
180 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs) | ||
181 | { | ||
182 | p->ainsn.insn_fn(); | ||
183 | } | ||
184 | |||
185 | static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) | ||
186 | { | 23 | { |
187 | kprobe_opcode_t insn = p->opcode; | ||
188 | int rn = (insn >> 16) & 0xf; | 24 | int rn = (insn >> 16) & 0xf; |
189 | int lbit = insn & (1 << 20); | 25 | int lbit = insn & (1 << 20); |
190 | int wbit = insn & (1 << 21); | 26 | int wbit = insn & (1 << 21); |
@@ -223,24 +59,31 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) | |||
223 | } | 59 | } |
224 | } | 60 | } |
225 | 61 | ||
226 | static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs) | 62 | static void __kprobes simulate_stm1_pc(probes_opcode_t insn, |
63 | struct arch_probes_insn *asi, | ||
64 | struct pt_regs *regs) | ||
227 | { | 65 | { |
228 | regs->ARM_pc = (long)p->addr + str_pc_offset; | 66 | unsigned long addr = regs->ARM_pc - 4; |
229 | simulate_ldm1stm1(p, regs); | 67 | |
230 | regs->ARM_pc = (long)p->addr + 4; | 68 | regs->ARM_pc = (long)addr + str_pc_offset; |
69 | simulate_ldm1stm1(insn, asi, regs); | ||
70 | regs->ARM_pc = (long)addr + 4; | ||
231 | } | 71 | } |
232 | 72 | ||
233 | static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs) | 73 | static void __kprobes simulate_ldm1_pc(probes_opcode_t insn, |
74 | struct arch_probes_insn *asi, | ||
75 | struct pt_regs *regs) | ||
234 | { | 76 | { |
235 | simulate_ldm1stm1(p, regs); | 77 | simulate_ldm1stm1(insn, asi, regs); |
236 | load_write_pc(regs->ARM_pc, regs); | 78 | load_write_pc(regs->ARM_pc, regs); |
237 | } | 79 | } |
238 | 80 | ||
239 | static void __kprobes | 81 | static void __kprobes |
240 | emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs) | 82 | emulate_generic_r0_12_noflags(probes_opcode_t insn, |
83 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
241 | { | 84 | { |
242 | register void *rregs asm("r1") = regs; | 85 | register void *rregs asm("r1") = regs; |
243 | register void *rfn asm("lr") = p->ainsn.insn_fn; | 86 | register void *rfn asm("lr") = asi->insn_fn; |
244 | 87 | ||
245 | __asm__ __volatile__ ( | 88 | __asm__ __volatile__ ( |
246 | "stmdb sp!, {%[regs], r11} \n\t" | 89 | "stmdb sp!, {%[regs], r11} \n\t" |
@@ -264,22 +107,27 @@ emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs) | |||
264 | } | 107 | } |
265 | 108 | ||
266 | static void __kprobes | 109 | static void __kprobes |
267 | emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs) | 110 | emulate_generic_r2_14_noflags(probes_opcode_t insn, |
111 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
268 | { | 112 | { |
269 | emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2)); | 113 | emulate_generic_r0_12_noflags(insn, asi, |
114 | (struct pt_regs *)(regs->uregs+2)); | ||
270 | } | 115 | } |
271 | 116 | ||
272 | static void __kprobes | 117 | static void __kprobes |
273 | emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs) | 118 | emulate_ldm_r3_15(probes_opcode_t insn, |
119 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
274 | { | 120 | { |
275 | emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3)); | 121 | emulate_generic_r0_12_noflags(insn, asi, |
122 | (struct pt_regs *)(regs->uregs+3)); | ||
276 | load_write_pc(regs->ARM_pc, regs); | 123 | load_write_pc(regs->ARM_pc, regs); |
277 | } | 124 | } |
278 | 125 | ||
279 | enum kprobe_insn __kprobes | 126 | enum probes_insn __kprobes |
280 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 127 | kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, |
128 | const struct decode_header *h) | ||
281 | { | 129 | { |
282 | kprobe_insn_handler_t *handler = 0; | 130 | probes_insn_handler_t *handler = 0; |
283 | unsigned reglist = insn & 0xffff; | 131 | unsigned reglist = insn & 0xffff; |
284 | int is_ldm = insn & 0x100000; | 132 | int is_ldm = insn & 0x100000; |
285 | int rn = (insn >> 16) & 0xf; | 133 | int rn = (insn >> 16) & 0xf; |
@@ -319,260 +167,3 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
319 | return INSN_GOOD_NO_SLOT; | 167 | return INSN_GOOD_NO_SLOT; |
320 | } | 168 | } |
321 | 169 | ||
322 | |||
323 | /* | ||
324 | * Prepare an instruction slot to receive an instruction for emulating. | ||
325 | * This is done by placing a subroutine return after the location where the | ||
326 | * instruction will be placed. We also modify ARM instructions to be | ||
327 | * unconditional as the condition code will already be checked before any | ||
328 | * emulation handler is called. | ||
329 | */ | ||
330 | static kprobe_opcode_t __kprobes | ||
331 | prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
332 | bool thumb) | ||
333 | { | ||
334 | #ifdef CONFIG_THUMB2_KERNEL | ||
335 | if (thumb) { | ||
336 | u16 *thumb_insn = (u16 *)asi->insn; | ||
337 | thumb_insn[1] = 0x4770; /* Thumb bx lr */ | ||
338 | thumb_insn[2] = 0x4770; /* Thumb bx lr */ | ||
339 | return insn; | ||
340 | } | ||
341 | asi->insn[1] = 0xe12fff1e; /* ARM bx lr */ | ||
342 | #else | ||
343 | asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */ | ||
344 | #endif | ||
345 | /* Make an ARM instruction unconditional */ | ||
346 | if (insn < 0xe0000000) | ||
347 | insn = (insn | 0xe0000000) & ~0x10000000; | ||
348 | return insn; | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * Write a (probably modified) instruction into the slot previously prepared by | ||
353 | * prepare_emulated_insn | ||
354 | */ | ||
355 | static void __kprobes | ||
356 | set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
357 | bool thumb) | ||
358 | { | ||
359 | #ifdef CONFIG_THUMB2_KERNEL | ||
360 | if (thumb) { | ||
361 | u16 *ip = (u16 *)asi->insn; | ||
362 | if (is_wide_instruction(insn)) | ||
363 | *ip++ = insn >> 16; | ||
364 | *ip++ = insn; | ||
365 | return; | ||
366 | } | ||
367 | #endif | ||
368 | asi->insn[0] = insn; | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | * When we modify the register numbers encoded in an instruction to be emulated, | ||
373 | * the new values come from this define. For ARM and 32-bit Thumb instructions | ||
374 | * this gives... | ||
375 | * | ||
376 | * bit position 16 12 8 4 0 | ||
377 | * ---------------+---+---+---+---+---+ | ||
378 | * register r2 r0 r1 -- r3 | ||
379 | */ | ||
380 | #define INSN_NEW_BITS 0x00020103 | ||
381 | |||
382 | /* Each nibble has same value as that at INSN_NEW_BITS bit 16 */ | ||
383 | #define INSN_SAMEAS16_BITS 0x22222222 | ||
384 | |||
385 | /* | ||
386 | * Validate and modify each of the registers encoded in an instruction. | ||
387 | * | ||
388 | * Each nibble in regs contains a value from enum decode_reg_type. For each | ||
389 | * non-zero value, the corresponding nibble in pinsn is validated and modified | ||
390 | * according to the type. | ||
391 | */ | ||
392 | static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs) | ||
393 | { | ||
394 | kprobe_opcode_t insn = *pinsn; | ||
395 | kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */ | ||
396 | |||
397 | for (; regs != 0; regs >>= 4, mask <<= 4) { | ||
398 | |||
399 | kprobe_opcode_t new_bits = INSN_NEW_BITS; | ||
400 | |||
401 | switch (regs & 0xf) { | ||
402 | |||
403 | case REG_TYPE_NONE: | ||
404 | /* Nibble not a register, skip to next */ | ||
405 | continue; | ||
406 | |||
407 | case REG_TYPE_ANY: | ||
408 | /* Any register is allowed */ | ||
409 | break; | ||
410 | |||
411 | case REG_TYPE_SAMEAS16: | ||
412 | /* Replace register with same as at bit position 16 */ | ||
413 | new_bits = INSN_SAMEAS16_BITS; | ||
414 | break; | ||
415 | |||
416 | case REG_TYPE_SP: | ||
417 | /* Only allow SP (R13) */ | ||
418 | if ((insn ^ 0xdddddddd) & mask) | ||
419 | goto reject; | ||
420 | break; | ||
421 | |||
422 | case REG_TYPE_PC: | ||
423 | /* Only allow PC (R15) */ | ||
424 | if ((insn ^ 0xffffffff) & mask) | ||
425 | goto reject; | ||
426 | break; | ||
427 | |||
428 | case REG_TYPE_NOSP: | ||
429 | /* Reject SP (R13) */ | ||
430 | if (((insn ^ 0xdddddddd) & mask) == 0) | ||
431 | goto reject; | ||
432 | break; | ||
433 | |||
434 | case REG_TYPE_NOSPPC: | ||
435 | case REG_TYPE_NOSPPCX: | ||
436 | /* Reject SP and PC (R13 and R15) */ | ||
437 | if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0) | ||
438 | goto reject; | ||
439 | break; | ||
440 | |||
441 | case REG_TYPE_NOPCWB: | ||
442 | if (!is_writeback(insn)) | ||
443 | break; /* No writeback, so any register is OK */ | ||
444 | /* fall through... */ | ||
445 | case REG_TYPE_NOPC: | ||
446 | case REG_TYPE_NOPCX: | ||
447 | /* Reject PC (R15) */ | ||
448 | if (((insn ^ 0xffffffff) & mask) == 0) | ||
449 | goto reject; | ||
450 | break; | ||
451 | } | ||
452 | |||
453 | /* Replace value of nibble with new register number... */ | ||
454 | insn &= ~mask; | ||
455 | insn |= new_bits & mask; | ||
456 | } | ||
457 | |||
458 | *pinsn = insn; | ||
459 | return true; | ||
460 | |||
461 | reject: | ||
462 | return false; | ||
463 | } | ||
464 | |||
465 | static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | ||
466 | [DECODE_TYPE_TABLE] = sizeof(struct decode_table), | ||
467 | [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), | ||
468 | [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), | ||
469 | [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), | ||
470 | [DECODE_TYPE_OR] = sizeof(struct decode_or), | ||
471 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) | ||
472 | }; | ||
473 | |||
474 | /* | ||
475 | * kprobe_decode_insn operates on data tables in order to decode an ARM | ||
476 | * architecture instruction onto which a kprobe has been placed. | ||
477 | * | ||
478 | * These instruction decoding tables are a concatenation of entries each | ||
479 | * of which consist of one of the following structs: | ||
480 | * | ||
481 | * decode_table | ||
482 | * decode_custom | ||
483 | * decode_simulate | ||
484 | * decode_emulate | ||
485 | * decode_or | ||
486 | * decode_reject | ||
487 | * | ||
488 | * Each of these starts with a struct decode_header which has the following | ||
489 | * fields: | ||
490 | * | ||
491 | * type_regs | ||
492 | * mask | ||
493 | * value | ||
494 | * | ||
495 | * The least significant DECODE_TYPE_BITS of type_regs contains a value | ||
496 | * from enum decode_type, this indicates which of the decode_* structs | ||
497 | * the entry contains. The value DECODE_TYPE_END indicates the end of the | ||
498 | * table. | ||
499 | * | ||
500 | * When the table is parsed, each entry is checked in turn to see if it | ||
501 | * matches the instruction to be decoded using the test: | ||
502 | * | ||
503 | * (insn & mask) == value | ||
504 | * | ||
505 | * If no match is found before the end of the table is reached then decoding | ||
506 | * fails with INSN_REJECTED. | ||
507 | * | ||
508 | * When a match is found, decode_regs() is called to validate and modify each | ||
509 | * of the registers encoded in the instruction; the data it uses to do this | ||
510 | * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding | ||
511 | * to fail with INSN_REJECTED. | ||
512 | * | ||
513 | * Once the instruction has passed the above tests, further processing | ||
514 | * depends on the type of the table entry's decode struct. | ||
515 | * | ||
516 | */ | ||
517 | int __kprobes | ||
518 | kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
519 | const union decode_item *table, bool thumb) | ||
520 | { | ||
521 | const struct decode_header *h = (struct decode_header *)table; | ||
522 | const struct decode_header *next; | ||
523 | bool matched = false; | ||
524 | |||
525 | insn = prepare_emulated_insn(insn, asi, thumb); | ||
526 | |||
527 | for (;; h = next) { | ||
528 | enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; | ||
529 | u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; | ||
530 | |||
531 | if (type == DECODE_TYPE_END) | ||
532 | return INSN_REJECTED; | ||
533 | |||
534 | next = (struct decode_header *) | ||
535 | ((uintptr_t)h + decode_struct_sizes[type]); | ||
536 | |||
537 | if (!matched && (insn & h->mask.bits) != h->value.bits) | ||
538 | continue; | ||
539 | |||
540 | if (!decode_regs(&insn, regs)) | ||
541 | return INSN_REJECTED; | ||
542 | |||
543 | switch (type) { | ||
544 | |||
545 | case DECODE_TYPE_TABLE: { | ||
546 | struct decode_table *d = (struct decode_table *)h; | ||
547 | next = (struct decode_header *)d->table.table; | ||
548 | break; | ||
549 | } | ||
550 | |||
551 | case DECODE_TYPE_CUSTOM: { | ||
552 | struct decode_custom *d = (struct decode_custom *)h; | ||
553 | return (*d->decoder.decoder)(insn, asi); | ||
554 | } | ||
555 | |||
556 | case DECODE_TYPE_SIMULATE: { | ||
557 | struct decode_simulate *d = (struct decode_simulate *)h; | ||
558 | asi->insn_handler = d->handler.handler; | ||
559 | return INSN_GOOD_NO_SLOT; | ||
560 | } | ||
561 | |||
562 | case DECODE_TYPE_EMULATE: { | ||
563 | struct decode_emulate *d = (struct decode_emulate *)h; | ||
564 | asi->insn_handler = d->handler.handler; | ||
565 | set_emulated_insn(insn, asi, thumb); | ||
566 | return INSN_GOOD; | ||
567 | } | ||
568 | |||
569 | case DECODE_TYPE_OR: | ||
570 | matched = true; | ||
571 | break; | ||
572 | |||
573 | case DECODE_TYPE_REJECT: | ||
574 | default: | ||
575 | return INSN_REJECTED; | ||
576 | } | ||
577 | } | ||
578 | } | ||
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c index 839312905067..87839de77e5f 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/kernel/kprobes-test-arm.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <asm/system_info.h> | ||
13 | 14 | ||
14 | #include "kprobes-test.h" | 15 | #include "kprobes-test.h" |
15 | 16 | ||
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c index 0cd63d080c7b..c2fd06b4c389 100644 --- a/arch/arm/kernel/kprobes-test.c +++ b/arch/arm/kernel/kprobes-test.c | |||
@@ -201,10 +201,14 @@ | |||
201 | #include <linux/module.h> | 201 | #include <linux/module.h> |
202 | #include <linux/slab.h> | 202 | #include <linux/slab.h> |
203 | #include <linux/kprobes.h> | 203 | #include <linux/kprobes.h> |
204 | 204 | #include <linux/errno.h> | |
205 | #include <linux/stddef.h> | ||
206 | #include <linux/bug.h> | ||
205 | #include <asm/opcodes.h> | 207 | #include <asm/opcodes.h> |
206 | 208 | ||
207 | #include "kprobes.h" | 209 | #include "kprobes.h" |
210 | #include "probes-arm.h" | ||
211 | #include "probes-thumb.h" | ||
208 | #include "kprobes-test.h" | 212 | #include "kprobes-test.h" |
209 | 213 | ||
210 | 214 | ||
@@ -1608,7 +1612,7 @@ static int __init run_all_tests(void) | |||
1608 | goto out; | 1612 | goto out; |
1609 | 1613 | ||
1610 | pr_info("ARM instruction simulation\n"); | 1614 | pr_info("ARM instruction simulation\n"); |
1611 | ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table); | 1615 | ret = run_test_cases(kprobe_arm_test_cases, probes_decode_arm_table); |
1612 | if (ret) | 1616 | if (ret) |
1613 | goto out; | 1617 | goto out; |
1614 | 1618 | ||
@@ -1631,13 +1635,13 @@ static int __init run_all_tests(void) | |||
1631 | 1635 | ||
1632 | pr_info("16-bit Thumb instruction simulation\n"); | 1636 | pr_info("16-bit Thumb instruction simulation\n"); |
1633 | ret = run_test_cases(kprobe_thumb16_test_cases, | 1637 | ret = run_test_cases(kprobe_thumb16_test_cases, |
1634 | kprobe_decode_thumb16_table); | 1638 | probes_decode_thumb16_table); |
1635 | if (ret) | 1639 | if (ret) |
1636 | goto out; | 1640 | goto out; |
1637 | 1641 | ||
1638 | pr_info("32-bit Thumb instruction simulation\n"); | 1642 | pr_info("32-bit Thumb instruction simulation\n"); |
1639 | ret = run_test_cases(kprobe_thumb32_test_cases, | 1643 | ret = run_test_cases(kprobe_thumb32_test_cases, |
1640 | kprobe_decode_thumb32_table); | 1644 | probes_decode_thumb32_table); |
1641 | if (ret) | 1645 | if (ret) |
1642 | goto out; | 1646 | goto out; |
1643 | #endif | 1647 | #endif |
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index 6123daf397a7..6619188619ae 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c | |||
@@ -8,41 +8,25 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/types.h> | ||
11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/ptrace.h> | ||
12 | #include <linux/kprobes.h> | 14 | #include <linux/kprobes.h> |
13 | #include <linux/module.h> | ||
14 | 15 | ||
15 | #include "kprobes.h" | 16 | #include "kprobes.h" |
17 | #include "probes-thumb.h" | ||
16 | 18 | ||
19 | /* These emulation encodings are functionally equivalent... */ | ||
20 | #define t32_emulate_rd8rn16rm0ra12_noflags \ | ||
21 | t32_emulate_rdlo12rdhi8rn16rm0_noflags | ||
17 | 22 | ||
18 | /* | 23 | /* t32 thumb actions */ |
19 | * True if current instruction is in an IT block. | ||
20 | */ | ||
21 | #define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000) | ||
22 | |||
23 | /* | ||
24 | * Return the condition code to check for the currently executing instruction. | ||
25 | * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if | ||
26 | * in_it_block returns true. | ||
27 | */ | ||
28 | #define current_cond(cpsr) ((cpsr >> 12) & 0xf) | ||
29 | |||
30 | /* | ||
31 | * Return the PC value for a probe in thumb code. | ||
32 | * This is the address of the probed instruction plus 4. | ||
33 | * We subtract one because the address will have bit zero set to indicate | ||
34 | * a pointer to thumb code. | ||
35 | */ | ||
36 | static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p) | ||
37 | { | ||
38 | return (unsigned long)p->addr - 1 + 4; | ||
39 | } | ||
40 | 24 | ||
41 | static void __kprobes | 25 | static void __kprobes |
42 | t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) | 26 | t32_simulate_table_branch(probes_opcode_t insn, |
27 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
43 | { | 28 | { |
44 | kprobe_opcode_t insn = p->opcode; | 29 | unsigned long pc = regs->ARM_pc; |
45 | unsigned long pc = thumb_probe_pc(p); | ||
46 | int rn = (insn >> 16) & 0xf; | 30 | int rn = (insn >> 16) & 0xf; |
47 | int rm = insn & 0xf; | 31 | int rm = insn & 0xf; |
48 | 32 | ||
@@ -59,19 +43,19 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) | |||
59 | } | 43 | } |
60 | 44 | ||
61 | static void __kprobes | 45 | static void __kprobes |
62 | t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs) | 46 | t32_simulate_mrs(probes_opcode_t insn, |
47 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
63 | { | 48 | { |
64 | kprobe_opcode_t insn = p->opcode; | ||
65 | int rd = (insn >> 8) & 0xf; | 49 | int rd = (insn >> 8) & 0xf; |
66 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ | 50 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ |
67 | regs->uregs[rd] = regs->ARM_cpsr & mask; | 51 | regs->uregs[rd] = regs->ARM_cpsr & mask; |
68 | } | 52 | } |
69 | 53 | ||
70 | static void __kprobes | 54 | static void __kprobes |
71 | t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) | 55 | t32_simulate_cond_branch(probes_opcode_t insn, |
56 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
72 | { | 57 | { |
73 | kprobe_opcode_t insn = p->opcode; | 58 | unsigned long pc = regs->ARM_pc; |
74 | unsigned long pc = thumb_probe_pc(p); | ||
75 | 59 | ||
76 | long offset = insn & 0x7ff; /* imm11 */ | 60 | long offset = insn & 0x7ff; /* imm11 */ |
77 | offset += (insn & 0x003f0000) >> 5; /* imm6 */ | 61 | offset += (insn & 0x003f0000) >> 5; /* imm6 */ |
@@ -82,20 +66,21 @@ t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) | |||
82 | regs->ARM_pc = pc + (offset * 2); | 66 | regs->ARM_pc = pc + (offset * 2); |
83 | } | 67 | } |
84 | 68 | ||
85 | static enum kprobe_insn __kprobes | 69 | static enum probes_insn __kprobes |
86 | t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 70 | t32_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi, |
71 | const struct decode_header *d) | ||
87 | { | 72 | { |
88 | int cc = (insn >> 22) & 0xf; | 73 | int cc = (insn >> 22) & 0xf; |
89 | asi->insn_check_cc = kprobe_condition_checks[cc]; | 74 | asi->insn_check_cc = probes_condition_checks[cc]; |
90 | asi->insn_handler = t32_simulate_cond_branch; | 75 | asi->insn_handler = t32_simulate_cond_branch; |
91 | return INSN_GOOD_NO_SLOT; | 76 | return INSN_GOOD_NO_SLOT; |
92 | } | 77 | } |
93 | 78 | ||
94 | static void __kprobes | 79 | static void __kprobes |
95 | t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) | 80 | t32_simulate_branch(probes_opcode_t insn, |
81 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
96 | { | 82 | { |
97 | kprobe_opcode_t insn = p->opcode; | 83 | unsigned long pc = regs->ARM_pc; |
98 | unsigned long pc = thumb_probe_pc(p); | ||
99 | 84 | ||
100 | long offset = insn & 0x7ff; /* imm11 */ | 85 | long offset = insn & 0x7ff; /* imm11 */ |
101 | offset += (insn & 0x03ff0000) >> 5; /* imm10 */ | 86 | offset += (insn & 0x03ff0000) >> 5; /* imm10 */ |
@@ -108,7 +93,7 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) | |||
108 | 93 | ||
109 | if (insn & (1 << 14)) { | 94 | if (insn & (1 << 14)) { |
110 | /* BL or BLX */ | 95 | /* BL or BLX */ |
111 | regs->ARM_lr = (unsigned long)p->addr + 4; | 96 | regs->ARM_lr = regs->ARM_pc | 1; |
112 | if (!(insn & (1 << 12))) { | 97 | if (!(insn & (1 << 12))) { |
113 | /* BLX so switch to ARM mode */ | 98 | /* BLX so switch to ARM mode */ |
114 | regs->ARM_cpsr &= ~PSR_T_BIT; | 99 | regs->ARM_cpsr &= ~PSR_T_BIT; |
@@ -120,10 +105,10 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) | |||
120 | } | 105 | } |
121 | 106 | ||
122 | static void __kprobes | 107 | static void __kprobes |
123 | t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) | 108 | t32_simulate_ldr_literal(probes_opcode_t insn, |
109 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
124 | { | 110 | { |
125 | kprobe_opcode_t insn = p->opcode; | 111 | unsigned long addr = regs->ARM_pc & ~3; |
126 | unsigned long addr = thumb_probe_pc(p) & ~3; | ||
127 | int rt = (insn >> 12) & 0xf; | 112 | int rt = (insn >> 12) & 0xf; |
128 | unsigned long rtv; | 113 | unsigned long rtv; |
129 | 114 | ||
@@ -157,10 +142,11 @@ t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) | |||
157 | regs->uregs[rt] = rtv; | 142 | regs->uregs[rt] = rtv; |
158 | } | 143 | } |
159 | 144 | ||
160 | static enum kprobe_insn __kprobes | 145 | static enum probes_insn __kprobes |
161 | t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 146 | t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, |
147 | const struct decode_header *d) | ||
162 | { | 148 | { |
163 | enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi); | 149 | enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d); |
164 | 150 | ||
165 | /* Fixup modified instruction to have halfwords in correct order...*/ | 151 | /* Fixup modified instruction to have halfwords in correct order...*/ |
166 | insn = asi->insn[0]; | 152 | insn = asi->insn[0]; |
@@ -171,10 +157,10 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
171 | } | 157 | } |
172 | 158 | ||
173 | static void __kprobes | 159 | static void __kprobes |
174 | t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | 160 | t32_emulate_ldrdstrd(probes_opcode_t insn, |
161 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
175 | { | 162 | { |
176 | kprobe_opcode_t insn = p->opcode; | 163 | unsigned long pc = regs->ARM_pc & ~3; |
177 | unsigned long pc = thumb_probe_pc(p) & ~3; | ||
178 | int rt1 = (insn >> 12) & 0xf; | 164 | int rt1 = (insn >> 12) & 0xf; |
179 | int rt2 = (insn >> 8) & 0xf; | 165 | int rt2 = (insn >> 8) & 0xf; |
180 | int rn = (insn >> 16) & 0xf; | 166 | int rn = (insn >> 16) & 0xf; |
@@ -187,7 +173,7 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
187 | __asm__ __volatile__ ( | 173 | __asm__ __volatile__ ( |
188 | "blx %[fn]" | 174 | "blx %[fn]" |
189 | : "=r" (rt1v), "=r" (rt2v), "=r" (rnv) | 175 | : "=r" (rt1v), "=r" (rt2v), "=r" (rnv) |
190 | : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn) | 176 | : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn) |
191 | : "lr", "memory", "cc" | 177 | : "lr", "memory", "cc" |
192 | ); | 178 | ); |
193 | 179 | ||
@@ -198,9 +184,9 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
198 | } | 184 | } |
199 | 185 | ||
200 | static void __kprobes | 186 | static void __kprobes |
201 | t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) | 187 | t32_emulate_ldrstr(probes_opcode_t insn, |
188 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
202 | { | 189 | { |
203 | kprobe_opcode_t insn = p->opcode; | ||
204 | int rt = (insn >> 12) & 0xf; | 190 | int rt = (insn >> 12) & 0xf; |
205 | int rn = (insn >> 16) & 0xf; | 191 | int rn = (insn >> 16) & 0xf; |
206 | int rm = insn & 0xf; | 192 | int rm = insn & 0xf; |
@@ -212,7 +198,7 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) | |||
212 | __asm__ __volatile__ ( | 198 | __asm__ __volatile__ ( |
213 | "blx %[fn]" | 199 | "blx %[fn]" |
214 | : "=r" (rtv), "=r" (rnv) | 200 | : "=r" (rtv), "=r" (rnv) |
215 | : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | 201 | : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) |
216 | : "lr", "memory", "cc" | 202 | : "lr", "memory", "cc" |
217 | ); | 203 | ); |
218 | 204 | ||
@@ -224,9 +210,9 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) | |||
224 | } | 210 | } |
225 | 211 | ||
226 | static void __kprobes | 212 | static void __kprobes |
227 | t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) | 213 | t32_emulate_rd8rn16rm0_rwflags(probes_opcode_t insn, |
214 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
228 | { | 215 | { |
229 | kprobe_opcode_t insn = p->opcode; | ||
230 | int rd = (insn >> 8) & 0xf; | 216 | int rd = (insn >> 8) & 0xf; |
231 | int rn = (insn >> 16) & 0xf; | 217 | int rn = (insn >> 16) & 0xf; |
232 | int rm = insn & 0xf; | 218 | int rm = insn & 0xf; |
@@ -242,7 +228,7 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
242 | "mrs %[cpsr], cpsr \n\t" | 228 | "mrs %[cpsr], cpsr \n\t" |
243 | : "=r" (rdv), [cpsr] "=r" (cpsr) | 229 | : "=r" (rdv), [cpsr] "=r" (cpsr) |
244 | : "0" (rdv), "r" (rnv), "r" (rmv), | 230 | : "0" (rdv), "r" (rnv), "r" (rmv), |
245 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 231 | "1" (cpsr), [fn] "r" (asi->insn_fn) |
246 | : "lr", "memory", "cc" | 232 | : "lr", "memory", "cc" |
247 | ); | 233 | ); |
248 | 234 | ||
@@ -251,10 +237,10 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
251 | } | 237 | } |
252 | 238 | ||
253 | static void __kprobes | 239 | static void __kprobes |
254 | t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) | 240 | t32_emulate_rd8pc16_noflags(probes_opcode_t insn, |
241 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
255 | { | 242 | { |
256 | kprobe_opcode_t insn = p->opcode; | 243 | unsigned long pc = regs->ARM_pc; |
257 | unsigned long pc = thumb_probe_pc(p); | ||
258 | int rd = (insn >> 8) & 0xf; | 244 | int rd = (insn >> 8) & 0xf; |
259 | 245 | ||
260 | register unsigned long rdv asm("r1") = regs->uregs[rd]; | 246 | register unsigned long rdv asm("r1") = regs->uregs[rd]; |
@@ -263,7 +249,7 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) | |||
263 | __asm__ __volatile__ ( | 249 | __asm__ __volatile__ ( |
264 | "blx %[fn]" | 250 | "blx %[fn]" |
265 | : "=r" (rdv) | 251 | : "=r" (rdv) |
266 | : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn) | 252 | : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn) |
267 | : "lr", "memory", "cc" | 253 | : "lr", "memory", "cc" |
268 | ); | 254 | ); |
269 | 255 | ||
@@ -271,9 +257,9 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) | |||
271 | } | 257 | } |
272 | 258 | ||
273 | static void __kprobes | 259 | static void __kprobes |
274 | t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) | 260 | t32_emulate_rd8rn16_noflags(probes_opcode_t insn, |
261 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
275 | { | 262 | { |
276 | kprobe_opcode_t insn = p->opcode; | ||
277 | int rd = (insn >> 8) & 0xf; | 263 | int rd = (insn >> 8) & 0xf; |
278 | int rn = (insn >> 16) & 0xf; | 264 | int rn = (insn >> 16) & 0xf; |
279 | 265 | ||
@@ -283,7 +269,7 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) | |||
283 | __asm__ __volatile__ ( | 269 | __asm__ __volatile__ ( |
284 | "blx %[fn]" | 270 | "blx %[fn]" |
285 | : "=r" (rdv) | 271 | : "=r" (rdv) |
286 | : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn) | 272 | : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn) |
287 | : "lr", "memory", "cc" | 273 | : "lr", "memory", "cc" |
288 | ); | 274 | ); |
289 | 275 | ||
@@ -291,9 +277,10 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) | |||
291 | } | 277 | } |
292 | 278 | ||
293 | static void __kprobes | 279 | static void __kprobes |
294 | t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) | 280 | t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn, |
281 | struct arch_probes_insn *asi, | ||
282 | struct pt_regs *regs) | ||
295 | { | 283 | { |
296 | kprobe_opcode_t insn = p->opcode; | ||
297 | int rdlo = (insn >> 12) & 0xf; | 284 | int rdlo = (insn >> 12) & 0xf; |
298 | int rdhi = (insn >> 8) & 0xf; | 285 | int rdhi = (insn >> 8) & 0xf; |
299 | int rn = (insn >> 16) & 0xf; | 286 | int rn = (insn >> 16) & 0xf; |
@@ -308,674 +295,43 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) | |||
308 | "blx %[fn]" | 295 | "blx %[fn]" |
309 | : "=r" (rdlov), "=r" (rdhiv) | 296 | : "=r" (rdlov), "=r" (rdhiv) |
310 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), | 297 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), |
311 | [fn] "r" (p->ainsn.insn_fn) | 298 | [fn] "r" (asi->insn_fn) |
312 | : "lr", "memory", "cc" | 299 | : "lr", "memory", "cc" |
313 | ); | 300 | ); |
314 | 301 | ||
315 | regs->uregs[rdlo] = rdlov; | 302 | regs->uregs[rdlo] = rdlov; |
316 | regs->uregs[rdhi] = rdhiv; | 303 | regs->uregs[rdhi] = rdhiv; |
317 | } | 304 | } |
318 | 305 | /* t16 thumb actions */ | |
319 | /* These emulation encodings are functionally equivalent... */ | ||
320 | #define t32_emulate_rd8rn16rm0ra12_noflags \ | ||
321 | t32_emulate_rdlo12rdhi8rn16rm0_noflags | ||
322 | |||
323 | static const union decode_item t32_table_1110_100x_x0xx[] = { | ||
324 | /* Load/store multiple instructions */ | ||
325 | |||
326 | /* Rn is PC 1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */ | ||
327 | DECODE_REJECT (0xfe4f0000, 0xe80f0000), | ||
328 | |||
329 | /* SRS 1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */ | ||
330 | /* RFE 1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */ | ||
331 | DECODE_REJECT (0xffc00000, 0xe8000000), | ||
332 | /* SRS 1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */ | ||
333 | /* RFE 1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */ | ||
334 | DECODE_REJECT (0xffc00000, 0xe9800000), | ||
335 | |||
336 | /* STM Rn, {...pc} 1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */ | ||
337 | DECODE_REJECT (0xfe508000, 0xe8008000), | ||
338 | /* LDM Rn, {...lr,pc} 1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */ | ||
339 | DECODE_REJECT (0xfe50c000, 0xe810c000), | ||
340 | /* LDM/STM Rn, {...sp} 1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */ | ||
341 | DECODE_REJECT (0xfe402000, 0xe8002000), | ||
342 | |||
343 | /* STMIA 1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */ | ||
344 | /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */ | ||
345 | /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */ | ||
346 | /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */ | ||
347 | DECODE_CUSTOM (0xfe400000, 0xe8000000, t32_decode_ldmstm), | ||
348 | |||
349 | DECODE_END | ||
350 | }; | ||
351 | |||
352 | static const union decode_item t32_table_1110_100x_x1xx[] = { | ||
353 | /* Load/store dual, load/store exclusive, table branch */ | ||
354 | |||
355 | /* STRD (immediate) 1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */ | ||
356 | /* LDRD (immediate) 1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */ | ||
357 | DECODE_OR (0xff600000, 0xe8600000), | ||
358 | /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
359 | /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
360 | DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd, | ||
361 | REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)), | ||
362 | |||
363 | /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */ | ||
364 | /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */ | ||
365 | DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch, | ||
366 | REGS(NOSP, 0, 0, 0, NOSPPC)), | ||
367 | |||
368 | /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
369 | /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
370 | /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */ | ||
371 | /* STREXH 1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */ | ||
372 | /* STREXD 1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */ | ||
373 | /* LDREXB 1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */ | ||
374 | /* LDREXH 1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */ | ||
375 | /* LDREXD 1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */ | ||
376 | /* And unallocated instructions... */ | ||
377 | DECODE_END | ||
378 | }; | ||
379 | |||
380 | static const union decode_item t32_table_1110_101x[] = { | ||
381 | /* Data-processing (shifted register) */ | ||
382 | |||
383 | /* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */ | ||
384 | /* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */ | ||
385 | DECODE_EMULATEX (0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags, | ||
386 | REGS(NOSPPC, 0, 0, 0, NOSPPC)), | ||
387 | |||
388 | /* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */ | ||
389 | DECODE_OR (0xfff00f00, 0xeb100f00), | ||
390 | /* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */ | ||
391 | DECODE_EMULATEX (0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags, | ||
392 | REGS(NOPC, 0, 0, 0, NOSPPC)), | ||
393 | |||
394 | /* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */ | ||
395 | /* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */ | ||
396 | DECODE_EMULATEX (0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags, | ||
397 | REGS(0, 0, NOSPPC, 0, NOSPPC)), | ||
398 | |||
399 | /* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */ | ||
400 | /* ??? 1110 1010 111x xxxx xxxx xxxx xxxx xxxx */ | ||
401 | DECODE_REJECT (0xffa00000, 0xeaa00000), | ||
402 | /* ??? 1110 1011 001x xxxx xxxx xxxx xxxx xxxx */ | ||
403 | DECODE_REJECT (0xffe00000, 0xeb200000), | ||
404 | /* ??? 1110 1011 100x xxxx xxxx xxxx xxxx xxxx */ | ||
405 | DECODE_REJECT (0xffe00000, 0xeb800000), | ||
406 | /* ??? 1110 1011 111x xxxx xxxx xxxx xxxx xxxx */ | ||
407 | DECODE_REJECT (0xffe00000, 0xebe00000), | ||
408 | |||
409 | /* ADD/SUB SP, SP, Rm, LSL #0..3 */ | ||
410 | /* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */ | ||
411 | DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags, | ||
412 | REGS(SP, 0, SP, 0, NOSPPC)), | ||
413 | |||
414 | /* ADD/SUB SP, SP, Rm, shift */ | ||
415 | /* 1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */ | ||
416 | DECODE_REJECT (0xff4f0f00, 0xeb0d0d00), | ||
417 | |||
418 | /* ADD/SUB Rd, SP, Rm, shift */ | ||
419 | /* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */ | ||
420 | DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags, | ||
421 | REGS(SP, 0, NOPC, 0, NOSPPC)), | ||
422 | |||
423 | /* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */ | ||
424 | /* BIC 1110 1010 001x xxxx xxxx xxxx xxxx xxxx */ | ||
425 | /* ORR 1110 1010 010x xxxx xxxx xxxx xxxx xxxx */ | ||
426 | /* ORN 1110 1010 011x xxxx xxxx xxxx xxxx xxxx */ | ||
427 | /* EOR 1110 1010 100x xxxx xxxx xxxx xxxx xxxx */ | ||
428 | /* PKH 1110 1010 110x xxxx xxxx xxxx xxxx xxxx */ | ||
429 | /* ADD 1110 1011 000x xxxx xxxx xxxx xxxx xxxx */ | ||
430 | /* ADC 1110 1011 010x xxxx xxxx xxxx xxxx xxxx */ | ||
431 | /* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */ | ||
432 | /* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */ | ||
433 | /* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */ | ||
434 | DECODE_EMULATEX (0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags, | ||
435 | REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), | ||
436 | |||
437 | DECODE_END | ||
438 | }; | ||
439 | |||
440 | static const union decode_item t32_table_1111_0x0x___0[] = { | ||
441 | /* Data-processing (modified immediate) */ | ||
442 | |||
443 | /* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */ | ||
444 | /* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */ | ||
445 | DECODE_EMULATEX (0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags, | ||
446 | REGS(NOSPPC, 0, 0, 0, 0)), | ||
447 | |||
448 | /* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */ | ||
449 | DECODE_OR (0xfbf08f00, 0xf1100f00), | ||
450 | /* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */ | ||
451 | DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags, | ||
452 | REGS(NOPC, 0, 0, 0, 0)), | ||
453 | |||
454 | /* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */ | ||
455 | /* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */ | ||
456 | DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags, | ||
457 | REGS(0, 0, NOSPPC, 0, 0)), | ||
458 | |||
459 | /* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */ | ||
460 | DECODE_REJECT (0xfbe08000, 0xf0a00000), | ||
461 | /* ??? 1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */ | ||
462 | /* ??? 1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */ | ||
463 | DECODE_REJECT (0xfbc08000, 0xf0c00000), | ||
464 | /* ??? 1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */ | ||
465 | DECODE_REJECT (0xfbe08000, 0xf1200000), | ||
466 | /* ??? 1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */ | ||
467 | DECODE_REJECT (0xfbe08000, 0xf1800000), | ||
468 | /* ??? 1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */ | ||
469 | DECODE_REJECT (0xfbe08000, 0xf1e00000), | ||
470 | |||
471 | /* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */ | ||
472 | /* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */ | ||
473 | DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags, | ||
474 | REGS(SP, 0, NOPC, 0, 0)), | ||
475 | |||
476 | /* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */ | ||
477 | /* BIC 1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */ | ||
478 | /* ORR 1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */ | ||
479 | /* ORN 1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */ | ||
480 | /* EOR 1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */ | ||
481 | /* ADD 1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */ | ||
482 | /* ADC 1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */ | ||
483 | /* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */ | ||
484 | /* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */ | ||
485 | /* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */ | ||
486 | DECODE_EMULATEX (0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags, | ||
487 | REGS(NOSPPC, 0, NOSPPC, 0, 0)), | ||
488 | |||
489 | DECODE_END | ||
490 | }; | ||
491 | |||
492 | static const union decode_item t32_table_1111_0x1x___0[] = { | ||
493 | /* Data-processing (plain binary immediate) */ | ||
494 | |||
495 | /* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */ | ||
496 | DECODE_OR (0xfbff8000, 0xf20f0000), | ||
497 | /* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */ | ||
498 | DECODE_EMULATEX (0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags, | ||
499 | REGS(PC, 0, NOSPPC, 0, 0)), | ||
500 | |||
501 | /* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */ | ||
502 | DECODE_OR (0xfbff8f00, 0xf20d0d00), | ||
503 | /* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */ | ||
504 | DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags, | ||
505 | REGS(SP, 0, SP, 0, 0)), | ||
506 | |||
507 | /* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */ | ||
508 | DECODE_OR (0xfbf08000, 0xf2000000), | ||
509 | /* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */ | ||
510 | DECODE_EMULATEX (0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags, | ||
511 | REGS(NOPCX, 0, NOSPPC, 0, 0)), | ||
512 | |||
513 | /* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */ | ||
514 | /* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */ | ||
515 | DECODE_EMULATEX (0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags, | ||
516 | REGS(0, 0, NOSPPC, 0, 0)), | ||
517 | |||
518 | /* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */ | ||
519 | /* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */ | ||
520 | /* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */ | ||
521 | /* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */ | ||
522 | DECODE_EMULATEX (0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags, | ||
523 | REGS(NOSPPC, 0, NOSPPC, 0, 0)), | ||
524 | |||
525 | /* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */ | ||
526 | /* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */ | ||
527 | DECODE_EMULATEX (0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags, | ||
528 | REGS(NOSPPC, 0, NOSPPC, 0, 0)), | ||
529 | |||
530 | /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */ | ||
531 | DECODE_EMULATEX (0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags, | ||
532 | REGS(0, 0, NOSPPC, 0, 0)), | ||
533 | |||
534 | /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */ | ||
535 | DECODE_EMULATEX (0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags, | ||
536 | REGS(NOSPPCX, 0, NOSPPC, 0, 0)), | ||
537 | |||
538 | DECODE_END | ||
539 | }; | ||
540 | |||
541 | static const union decode_item t32_table_1111_0xxx___1[] = { | ||
542 | /* Branches and miscellaneous control */ | ||
543 | |||
544 | /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */ | ||
545 | DECODE_OR (0xfff0d7ff, 0xf3a08001), | ||
546 | /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */ | ||
547 | DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, kprobe_emulate_none), | ||
548 | /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */ | ||
549 | /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */ | ||
550 | /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */ | ||
551 | DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop), | ||
552 | |||
553 | /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */ | ||
554 | DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs, | ||
555 | REGS(0, 0, NOSPPC, 0, 0)), | ||
556 | |||
557 | /* | ||
558 | * Unsupported instructions | ||
559 | * 1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx | ||
560 | * | ||
561 | * MSR 1111 0011 100x xxxx 10x0 xxxx xxxx xxxx | ||
562 | * DBG hint 1111 0011 1010 xxxx 10x0 x000 1111 xxxx | ||
563 | * Unallocated hints 1111 0011 1010 xxxx 10x0 x000 xxxx xxxx | ||
564 | * CPS 1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx | ||
565 | * CLREX/DSB/DMB/ISB 1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx | ||
566 | * BXJ 1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx | ||
567 | * SUBS PC,LR,#<imm8> 1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx | ||
568 | * MRS Rd, SPSR 1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx | ||
569 | * SMC 1111 0111 1111 xxxx 1000 xxxx xxxx xxxx | ||
570 | * UNDEFINED 1111 0111 1111 xxxx 1010 xxxx xxxx xxxx | ||
571 | * ??? 1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx | ||
572 | */ | ||
573 | DECODE_REJECT (0xfb80d000, 0xf3808000), | ||
574 | |||
575 | /* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */ | ||
576 | DECODE_CUSTOM (0xf800d000, 0xf0008000, t32_decode_cond_branch), | ||
577 | |||
578 | /* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */ | ||
579 | DECODE_OR (0xf800d001, 0xf000c000), | ||
580 | /* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */ | ||
581 | /* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */ | ||
582 | DECODE_SIMULATE (0xf8009000, 0xf0009000, t32_simulate_branch), | ||
583 | |||
584 | DECODE_END | ||
585 | }; | ||
586 | |||
587 | static const union decode_item t32_table_1111_100x_x0x1__1111[] = { | ||
588 | /* Memory hints */ | ||
589 | |||
590 | /* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */ | ||
591 | /* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */ | ||
592 | DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, kprobe_simulate_nop), | ||
593 | |||
594 | /* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */ | ||
595 | DECODE_OR (0xffd0f000, 0xf890f000), | ||
596 | /* PLD{W} (immediate) 1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */ | ||
597 | DECODE_OR (0xffd0ff00, 0xf810fc00), | ||
598 | /* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */ | ||
599 | DECODE_OR (0xfff0f000, 0xf990f000), | ||
600 | /* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */ | ||
601 | DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop, | ||
602 | REGS(NOPCX, 0, 0, 0, 0)), | ||
603 | |||
604 | /* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */ | ||
605 | DECODE_OR (0xffd0ffc0, 0xf810f000), | ||
606 | /* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */ | ||
607 | DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop, | ||
608 | REGS(NOPCX, 0, 0, 0, NOSPPC)), | ||
609 | |||
610 | /* Other unallocated instructions... */ | ||
611 | DECODE_END | ||
612 | }; | ||
613 | |||
614 | static const union decode_item t32_table_1111_100x[] = { | ||
615 | /* Store/Load single data item */ | ||
616 | |||
617 | /* ??? 1111 100x x11x xxxx xxxx xxxx xxxx xxxx */ | ||
618 | DECODE_REJECT (0xfe600000, 0xf8600000), | ||
619 | |||
620 | /* ??? 1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
621 | DECODE_REJECT (0xfff00000, 0xf9500000), | ||
622 | |||
623 | /* ??? 1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */ | ||
624 | DECODE_REJECT (0xfe800d00, 0xf8000800), | ||
625 | |||
626 | /* STRBT 1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */ | ||
627 | /* STRHT 1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */ | ||
628 | /* STRT 1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */ | ||
629 | /* LDRBT 1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */ | ||
630 | /* LDRSBT 1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */ | ||
631 | /* LDRHT 1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */ | ||
632 | /* LDRSHT 1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */ | ||
633 | /* LDRT 1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */ | ||
634 | DECODE_REJECT (0xfe800f00, 0xf8000e00), | ||
635 | |||
636 | /* STR{,B,H} Rn,[PC...] 1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */ | ||
637 | DECODE_REJECT (0xff1f0000, 0xf80f0000), | ||
638 | |||
639 | /* STR{,B,H} PC,[Rn...] 1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */ | ||
640 | DECODE_REJECT (0xff10f000, 0xf800f000), | ||
641 | |||
642 | /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */ | ||
643 | DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal, | ||
644 | REGS(PC, ANY, 0, 0, 0)), | ||
645 | |||
646 | /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */ | ||
647 | /* LDR (immediate) 1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */ | ||
648 | DECODE_OR (0xffe00800, 0xf8400800), | ||
649 | /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */ | ||
650 | /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */ | ||
651 | DECODE_EMULATEX (0xffe00000, 0xf8c00000, t32_emulate_ldrstr, | ||
652 | REGS(NOPCX, ANY, 0, 0, 0)), | ||
653 | |||
654 | /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ | ||
655 | /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */ | ||
656 | DECODE_EMULATEX (0xffe00fc0, 0xf8400000, t32_emulate_ldrstr, | ||
657 | REGS(NOPCX, ANY, 0, 0, NOSPPC)), | ||
658 | |||
659 | /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */ | ||
660 | /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */ | ||
661 | /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */ | ||
662 | /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */ | ||
663 | DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal, | ||
664 | REGS(PC, NOSPPCX, 0, 0, 0)), | ||
665 | |||
666 | /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */ | ||
667 | /* STRH (immediate) 1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */ | ||
668 | /* LDRB (immediate) 1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */ | ||
669 | /* LDRSB (immediate) 1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */ | ||
670 | /* LDRH (immediate) 1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */ | ||
671 | /* LDRSH (immediate) 1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */ | ||
672 | DECODE_OR (0xfec00800, 0xf8000800), | ||
673 | /* STRB (immediate) 1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */ | ||
674 | /* STRH (immediate) 1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */ | ||
675 | /* LDRB (immediate) 1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */ | ||
676 | /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */ | ||
677 | /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */ | ||
678 | /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */ | ||
679 | DECODE_EMULATEX (0xfec00000, 0xf8800000, t32_emulate_ldrstr, | ||
680 | REGS(NOPCX, NOSPPCX, 0, 0, 0)), | ||
681 | |||
682 | /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ | ||
683 | /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */ | ||
684 | /* LDRB (register) 1111 1000 0001 xxxx xxxx 0000 00xx xxxx */ | ||
685 | /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */ | ||
686 | /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */ | ||
687 | /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */ | ||
688 | DECODE_EMULATEX (0xfe800fc0, 0xf8000000, t32_emulate_ldrstr, | ||
689 | REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)), | ||
690 | |||
691 | /* Other unallocated instructions... */ | ||
692 | DECODE_END | ||
693 | }; | ||
694 | |||
695 | static const union decode_item t32_table_1111_1010___1111[] = { | ||
696 | /* Data-processing (register) */ | ||
697 | |||
698 | /* ??? 1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */ | ||
699 | DECODE_REJECT (0xffe0f080, 0xfa60f080), | ||
700 | |||
701 | /* SXTH 1111 1010 0000 1111 1111 xxxx 1xxx xxxx */ | ||
702 | /* UXTH 1111 1010 0001 1111 1111 xxxx 1xxx xxxx */ | ||
703 | /* SXTB16 1111 1010 0010 1111 1111 xxxx 1xxx xxxx */ | ||
704 | /* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */ | ||
705 | /* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */ | ||
706 | /* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */ | ||
707 | DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags, | ||
708 | REGS(0, 0, NOSPPC, 0, NOSPPC)), | ||
709 | |||
710 | |||
711 | /* ??? 1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */ | ||
712 | DECODE_REJECT (0xff80f0b0, 0xfa80f030), | ||
713 | /* ??? 1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */ | ||
714 | DECODE_REJECT (0xffb0f080, 0xfab0f000), | ||
715 | |||
716 | /* SADD16 1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */ | ||
717 | /* SASX 1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */ | ||
718 | /* SSAX 1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */ | ||
719 | /* SSUB16 1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */ | ||
720 | /* SADD8 1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */ | ||
721 | /* SSUB8 1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */ | ||
722 | |||
723 | /* QADD16 1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */ | ||
724 | /* QASX 1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */ | ||
725 | /* QSAX 1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */ | ||
726 | /* QSUB16 1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */ | ||
727 | /* QADD8 1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */ | ||
728 | /* QSUB8 1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */ | ||
729 | |||
730 | /* SHADD16 1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */ | ||
731 | /* SHASX 1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */ | ||
732 | /* SHSAX 1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */ | ||
733 | /* SHSUB16 1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */ | ||
734 | /* SHADD8 1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */ | ||
735 | /* SHSUB8 1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */ | ||
736 | |||
737 | /* UADD16 1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */ | ||
738 | /* UASX 1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */ | ||
739 | /* USAX 1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */ | ||
740 | /* USUB16 1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */ | ||
741 | /* UADD8 1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */ | ||
742 | /* USUB8 1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */ | ||
743 | |||
744 | /* UQADD16 1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */ | ||
745 | /* UQASX 1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */ | ||
746 | /* UQSAX 1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */ | ||
747 | /* UQSUB16 1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */ | ||
748 | /* UQADD8 1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */ | ||
749 | /* UQSUB8 1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */ | ||
750 | |||
751 | /* UHADD16 1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */ | ||
752 | /* UHASX 1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */ | ||
753 | /* UHSAX 1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */ | ||
754 | /* UHSUB16 1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */ | ||
755 | /* UHADD8 1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */ | ||
756 | /* UHSUB8 1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */ | ||
757 | DECODE_OR (0xff80f080, 0xfa80f000), | ||
758 | |||
759 | /* SXTAH 1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */ | ||
760 | /* UXTAH 1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */ | ||
761 | /* SXTAB16 1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */ | ||
762 | /* UXTAB16 1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */ | ||
763 | /* SXTAB 1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */ | ||
764 | /* UXTAB 1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */ | ||
765 | DECODE_OR (0xff80f080, 0xfa00f080), | ||
766 | |||
767 | /* QADD 1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */ | ||
768 | /* QDADD 1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */ | ||
769 | /* QSUB 1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */ | ||
770 | /* QDSUB 1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */ | ||
771 | DECODE_OR (0xfff0f0c0, 0xfa80f080), | ||
772 | |||
773 | /* SEL 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */ | ||
774 | DECODE_OR (0xfff0f0f0, 0xfaa0f080), | ||
775 | |||
776 | /* LSL 1111 1010 000x xxxx 1111 xxxx 0000 xxxx */ | ||
777 | /* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */ | ||
778 | /* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */ | ||
779 | /* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */ | ||
780 | DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags, | ||
781 | REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), | ||
782 | |||
783 | /* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */ | ||
784 | DECODE_OR (0xfff0f0f0, 0xfab0f080), | ||
785 | |||
786 | /* REV 1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */ | ||
787 | /* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */ | ||
788 | /* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */ | ||
789 | /* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */ | ||
790 | DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags, | ||
791 | REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)), | ||
792 | |||
793 | /* Other unallocated instructions... */ | ||
794 | DECODE_END | ||
795 | }; | ||
796 | |||
797 | static const union decode_item t32_table_1111_1011_0[] = { | ||
798 | /* Multiply, multiply accumulate, and absolute difference */ | ||
799 | |||
800 | /* ??? 1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */ | ||
801 | DECODE_REJECT (0xfff0f0f0, 0xfb00f010), | ||
802 | /* ??? 1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */ | ||
803 | DECODE_REJECT (0xfff0f0f0, 0xfb70f010), | ||
804 | |||
805 | /* SMULxy 1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */ | ||
806 | DECODE_OR (0xfff0f0c0, 0xfb10f000), | ||
807 | /* MUL 1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */ | ||
808 | /* SMUAD{X} 1111 1011 0010 xxxx 1111 xxxx 000x xxxx */ | ||
809 | /* SMULWy 1111 1011 0011 xxxx 1111 xxxx 000x xxxx */ | ||
810 | /* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */ | ||
811 | /* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */ | ||
812 | /* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */ | ||
813 | DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags, | ||
814 | REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), | ||
815 | |||
816 | /* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */ | ||
817 | DECODE_REJECT (0xfff000f0, 0xfb700010), | ||
818 | |||
819 | /* SMLAxy 1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */ | ||
820 | DECODE_OR (0xfff000c0, 0xfb100000), | ||
821 | /* MLA 1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */ | ||
822 | /* MLS 1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */ | ||
823 | /* SMLAD{X} 1111 1011 0010 xxxx xxxx xxxx 000x xxxx */ | ||
824 | /* SMLAWy 1111 1011 0011 xxxx xxxx xxxx 000x xxxx */ | ||
825 | /* SMLSD{X} 1111 1011 0100 xxxx xxxx xxxx 000x xxxx */ | ||
826 | /* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */ | ||
827 | /* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */ | ||
828 | /* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */ | ||
829 | DECODE_EMULATEX (0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags, | ||
830 | REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)), | ||
831 | |||
832 | /* Other unallocated instructions... */ | ||
833 | DECODE_END | ||
834 | }; | ||
835 | |||
836 | static const union decode_item t32_table_1111_1011_1[] = { | ||
837 | /* Long multiply, long multiply accumulate, and divide */ | ||
838 | |||
839 | /* UMAAL 1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */ | ||
840 | DECODE_OR (0xfff000f0, 0xfbe00060), | ||
841 | /* SMLALxy 1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */ | ||
842 | DECODE_OR (0xfff000c0, 0xfbc00080), | ||
843 | /* SMLALD{X} 1111 1011 1100 xxxx xxxx xxxx 110x xxxx */ | ||
844 | /* SMLSLD{X} 1111 1011 1101 xxxx xxxx xxxx 110x xxxx */ | ||
845 | DECODE_OR (0xffe000e0, 0xfbc000c0), | ||
846 | /* SMULL 1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */ | ||
847 | /* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */ | ||
848 | /* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */ | ||
849 | /* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */ | ||
850 | DECODE_EMULATEX (0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags, | ||
851 | REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)), | ||
852 | |||
853 | /* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */ | ||
854 | /* UDIV 1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */ | ||
855 | /* Other unallocated instructions... */ | ||
856 | DECODE_END | ||
857 | }; | ||
858 | |||
859 | const union decode_item kprobe_decode_thumb32_table[] = { | ||
860 | |||
861 | /* | ||
862 | * Load/store multiple instructions | ||
863 | * 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx | ||
864 | */ | ||
865 | DECODE_TABLE (0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx), | ||
866 | |||
867 | /* | ||
868 | * Load/store dual, load/store exclusive, table branch | ||
869 | * 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx | ||
870 | */ | ||
871 | DECODE_TABLE (0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx), | ||
872 | |||
873 | /* | ||
874 | * Data-processing (shifted register) | ||
875 | * 1110 101x xxxx xxxx xxxx xxxx xxxx xxxx | ||
876 | */ | ||
877 | DECODE_TABLE (0xfe000000, 0xea000000, t32_table_1110_101x), | ||
878 | |||
879 | /* | ||
880 | * Coprocessor instructions | ||
881 | * 1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx | ||
882 | */ | ||
883 | DECODE_REJECT (0xfc000000, 0xec000000), | ||
884 | |||
885 | /* | ||
886 | * Data-processing (modified immediate) | ||
887 | * 1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx | ||
888 | */ | ||
889 | DECODE_TABLE (0xfa008000, 0xf0000000, t32_table_1111_0x0x___0), | ||
890 | |||
891 | /* | ||
892 | * Data-processing (plain binary immediate) | ||
893 | * 1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx | ||
894 | */ | ||
895 | DECODE_TABLE (0xfa008000, 0xf2000000, t32_table_1111_0x1x___0), | ||
896 | |||
897 | /* | ||
898 | * Branches and miscellaneous control | ||
899 | * 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx | ||
900 | */ | ||
901 | DECODE_TABLE (0xf8008000, 0xf0008000, t32_table_1111_0xxx___1), | ||
902 | |||
903 | /* | ||
904 | * Advanced SIMD element or structure load/store instructions | ||
905 | * 1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx | ||
906 | */ | ||
907 | DECODE_REJECT (0xff100000, 0xf9000000), | ||
908 | |||
909 | /* | ||
910 | * Memory hints | ||
911 | * 1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx | ||
912 | */ | ||
913 | DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111), | ||
914 | |||
915 | /* | ||
916 | * Store single data item | ||
917 | * 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx | ||
918 | * Load single data items | ||
919 | * 1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx | ||
920 | */ | ||
921 | DECODE_TABLE (0xfe000000, 0xf8000000, t32_table_1111_100x), | ||
922 | |||
923 | /* | ||
924 | * Data-processing (register) | ||
925 | * 1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx | ||
926 | */ | ||
927 | DECODE_TABLE (0xff00f000, 0xfa00f000, t32_table_1111_1010___1111), | ||
928 | |||
929 | /* | ||
930 | * Multiply, multiply accumulate, and absolute difference | ||
931 | * 1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx | ||
932 | */ | ||
933 | DECODE_TABLE (0xff800000, 0xfb000000, t32_table_1111_1011_0), | ||
934 | |||
935 | /* | ||
936 | * Long multiply, long multiply accumulate, and divide | ||
937 | * 1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx | ||
938 | */ | ||
939 | DECODE_TABLE (0xff800000, 0xfb800000, t32_table_1111_1011_1), | ||
940 | |||
941 | /* | ||
942 | * Coprocessor instructions | ||
943 | * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx | ||
944 | */ | ||
945 | DECODE_END | ||
946 | }; | ||
947 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE | ||
948 | EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table); | ||
949 | #endif | ||
950 | 306 | ||
951 | static void __kprobes | 307 | static void __kprobes |
952 | t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs) | 308 | t16_simulate_bxblx(probes_opcode_t insn, |
309 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
953 | { | 310 | { |
954 | kprobe_opcode_t insn = p->opcode; | 311 | unsigned long pc = regs->ARM_pc + 2; |
955 | unsigned long pc = thumb_probe_pc(p); | ||
956 | int rm = (insn >> 3) & 0xf; | 312 | int rm = (insn >> 3) & 0xf; |
957 | unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; | 313 | unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; |
958 | 314 | ||
959 | if (insn & (1 << 7)) /* BLX ? */ | 315 | if (insn & (1 << 7)) /* BLX ? */ |
960 | regs->ARM_lr = (unsigned long)p->addr + 2; | 316 | regs->ARM_lr = regs->ARM_pc | 1; |
961 | 317 | ||
962 | bx_write_pc(rmv, regs); | 318 | bx_write_pc(rmv, regs); |
963 | } | 319 | } |
964 | 320 | ||
965 | static void __kprobes | 321 | static void __kprobes |
966 | t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) | 322 | t16_simulate_ldr_literal(probes_opcode_t insn, |
323 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
967 | { | 324 | { |
968 | kprobe_opcode_t insn = p->opcode; | 325 | unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3); |
969 | unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3); | ||
970 | long index = insn & 0xff; | 326 | long index = insn & 0xff; |
971 | int rt = (insn >> 8) & 0x7; | 327 | int rt = (insn >> 8) & 0x7; |
972 | regs->uregs[rt] = base[index]; | 328 | regs->uregs[rt] = base[index]; |
973 | } | 329 | } |
974 | 330 | ||
975 | static void __kprobes | 331 | static void __kprobes |
976 | t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) | 332 | t16_simulate_ldrstr_sp_relative(probes_opcode_t insn, |
333 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
977 | { | 334 | { |
978 | kprobe_opcode_t insn = p->opcode; | ||
979 | unsigned long* base = (unsigned long *)regs->ARM_sp; | 335 | unsigned long* base = (unsigned long *)regs->ARM_sp; |
980 | long index = insn & 0xff; | 336 | long index = insn & 0xff; |
981 | int rt = (insn >> 8) & 0x7; | 337 | int rt = (insn >> 8) & 0x7; |
@@ -986,20 +342,20 @@ t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) | |||
986 | } | 342 | } |
987 | 343 | ||
988 | static void __kprobes | 344 | static void __kprobes |
989 | t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs) | 345 | t16_simulate_reladr(probes_opcode_t insn, |
346 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
990 | { | 347 | { |
991 | kprobe_opcode_t insn = p->opcode; | ||
992 | unsigned long base = (insn & 0x800) ? regs->ARM_sp | 348 | unsigned long base = (insn & 0x800) ? regs->ARM_sp |
993 | : (thumb_probe_pc(p) & ~3); | 349 | : ((regs->ARM_pc + 2) & ~3); |
994 | long offset = insn & 0xff; | 350 | long offset = insn & 0xff; |
995 | int rt = (insn >> 8) & 0x7; | 351 | int rt = (insn >> 8) & 0x7; |
996 | regs->uregs[rt] = base + offset * 4; | 352 | regs->uregs[rt] = base + offset * 4; |
997 | } | 353 | } |
998 | 354 | ||
999 | static void __kprobes | 355 | static void __kprobes |
1000 | t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) | 356 | t16_simulate_add_sp_imm(probes_opcode_t insn, |
357 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1001 | { | 358 | { |
1002 | kprobe_opcode_t insn = p->opcode; | ||
1003 | long imm = insn & 0x7f; | 359 | long imm = insn & 0x7f; |
1004 | if (insn & 0x80) /* SUB */ | 360 | if (insn & 0x80) /* SUB */ |
1005 | regs->ARM_sp -= imm * 4; | 361 | regs->ARM_sp -= imm * 4; |
@@ -1008,21 +364,22 @@ t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) | |||
1008 | } | 364 | } |
1009 | 365 | ||
1010 | static void __kprobes | 366 | static void __kprobes |
1011 | t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs) | 367 | t16_simulate_cbz(probes_opcode_t insn, |
368 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1012 | { | 369 | { |
1013 | kprobe_opcode_t insn = p->opcode; | ||
1014 | int rn = insn & 0x7; | 370 | int rn = insn & 0x7; |
1015 | kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; | 371 | probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; |
1016 | if (nonzero & 0x800) { | 372 | if (nonzero & 0x800) { |
1017 | long i = insn & 0x200; | 373 | long i = insn & 0x200; |
1018 | long imm5 = insn & 0xf8; | 374 | long imm5 = insn & 0xf8; |
1019 | unsigned long pc = thumb_probe_pc(p); | 375 | unsigned long pc = regs->ARM_pc + 2; |
1020 | regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); | 376 | regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); |
1021 | } | 377 | } |
1022 | } | 378 | } |
1023 | 379 | ||
1024 | static void __kprobes | 380 | static void __kprobes |
1025 | t16_simulate_it(struct kprobe *p, struct pt_regs *regs) | 381 | t16_simulate_it(probes_opcode_t insn, |
382 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1026 | { | 383 | { |
1027 | /* | 384 | /* |
1028 | * The 8 IT state bits are split into two parts in CPSR: | 385 | * The 8 IT state bits are split into two parts in CPSR: |
@@ -1030,7 +387,6 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs) | |||
1030 | * ITSTATE<7:2> are in CPSR<15:10> | 387 | * ITSTATE<7:2> are in CPSR<15:10> |
1031 | * The new IT state is in the lower byte of insn. | 388 | * The new IT state is in the lower byte of insn. |
1032 | */ | 389 | */ |
1033 | kprobe_opcode_t insn = p->opcode; | ||
1034 | unsigned long cpsr = regs->ARM_cpsr; | 390 | unsigned long cpsr = regs->ARM_cpsr; |
1035 | cpsr &= ~PSR_IT_MASK; | 391 | cpsr &= ~PSR_IT_MASK; |
1036 | cpsr |= (insn & 0xfc) << 8; | 392 | cpsr |= (insn & 0xfc) << 8; |
@@ -1039,50 +395,54 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs) | |||
1039 | } | 395 | } |
1040 | 396 | ||
1041 | static void __kprobes | 397 | static void __kprobes |
1042 | t16_singlestep_it(struct kprobe *p, struct pt_regs *regs) | 398 | t16_singlestep_it(probes_opcode_t insn, |
399 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1043 | { | 400 | { |
1044 | regs->ARM_pc += 2; | 401 | regs->ARM_pc += 2; |
1045 | t16_simulate_it(p, regs); | 402 | t16_simulate_it(insn, asi, regs); |
1046 | } | 403 | } |
1047 | 404 | ||
1048 | static enum kprobe_insn __kprobes | 405 | static enum probes_insn __kprobes |
1049 | t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 406 | t16_decode_it(probes_opcode_t insn, struct arch_probes_insn *asi, |
407 | const struct decode_header *d) | ||
1050 | { | 408 | { |
1051 | asi->insn_singlestep = t16_singlestep_it; | 409 | asi->insn_singlestep = t16_singlestep_it; |
1052 | return INSN_GOOD_NO_SLOT; | 410 | return INSN_GOOD_NO_SLOT; |
1053 | } | 411 | } |
1054 | 412 | ||
1055 | static void __kprobes | 413 | static void __kprobes |
1056 | t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) | 414 | t16_simulate_cond_branch(probes_opcode_t insn, |
415 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1057 | { | 416 | { |
1058 | kprobe_opcode_t insn = p->opcode; | 417 | unsigned long pc = regs->ARM_pc + 2; |
1059 | unsigned long pc = thumb_probe_pc(p); | ||
1060 | long offset = insn & 0x7f; | 418 | long offset = insn & 0x7f; |
1061 | offset -= insn & 0x80; /* Apply sign bit */ | 419 | offset -= insn & 0x80; /* Apply sign bit */ |
1062 | regs->ARM_pc = pc + (offset * 2); | 420 | regs->ARM_pc = pc + (offset * 2); |
1063 | } | 421 | } |
1064 | 422 | ||
1065 | static enum kprobe_insn __kprobes | 423 | static enum probes_insn __kprobes |
1066 | t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 424 | t16_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi, |
425 | const struct decode_header *d) | ||
1067 | { | 426 | { |
1068 | int cc = (insn >> 8) & 0xf; | 427 | int cc = (insn >> 8) & 0xf; |
1069 | asi->insn_check_cc = kprobe_condition_checks[cc]; | 428 | asi->insn_check_cc = probes_condition_checks[cc]; |
1070 | asi->insn_handler = t16_simulate_cond_branch; | 429 | asi->insn_handler = t16_simulate_cond_branch; |
1071 | return INSN_GOOD_NO_SLOT; | 430 | return INSN_GOOD_NO_SLOT; |
1072 | } | 431 | } |
1073 | 432 | ||
1074 | static void __kprobes | 433 | static void __kprobes |
1075 | t16_simulate_branch(struct kprobe *p, struct pt_regs *regs) | 434 | t16_simulate_branch(probes_opcode_t insn, |
435 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1076 | { | 436 | { |
1077 | kprobe_opcode_t insn = p->opcode; | 437 | unsigned long pc = regs->ARM_pc + 2; |
1078 | unsigned long pc = thumb_probe_pc(p); | ||
1079 | long offset = insn & 0x3ff; | 438 | long offset = insn & 0x3ff; |
1080 | offset -= insn & 0x400; /* Apply sign bit */ | 439 | offset -= insn & 0x400; /* Apply sign bit */ |
1081 | regs->ARM_pc = pc + (offset * 2); | 440 | regs->ARM_pc = pc + (offset * 2); |
1082 | } | 441 | } |
1083 | 442 | ||
1084 | static unsigned long __kprobes | 443 | static unsigned long __kprobes |
1085 | t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) | 444 | t16_emulate_loregs(probes_opcode_t insn, |
445 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1086 | { | 446 | { |
1087 | unsigned long oldcpsr = regs->ARM_cpsr; | 447 | unsigned long oldcpsr = regs->ARM_cpsr; |
1088 | unsigned long newcpsr; | 448 | unsigned long newcpsr; |
@@ -1095,7 +455,7 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) | |||
1095 | "mrs %[newcpsr], cpsr \n\t" | 455 | "mrs %[newcpsr], cpsr \n\t" |
1096 | : [newcpsr] "=r" (newcpsr) | 456 | : [newcpsr] "=r" (newcpsr) |
1097 | : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), | 457 | : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), |
1098 | [fn] "r" (p->ainsn.insn_fn) | 458 | [fn] "r" (asi->insn_fn) |
1099 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 459 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
1100 | "lr", "memory", "cc" | 460 | "lr", "memory", "cc" |
1101 | ); | 461 | ); |
@@ -1104,24 +464,26 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) | |||
1104 | } | 464 | } |
1105 | 465 | ||
1106 | static void __kprobes | 466 | static void __kprobes |
1107 | t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs) | 467 | t16_emulate_loregs_rwflags(probes_opcode_t insn, |
468 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1108 | { | 469 | { |
1109 | regs->ARM_cpsr = t16_emulate_loregs(p, regs); | 470 | regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs); |
1110 | } | 471 | } |
1111 | 472 | ||
1112 | static void __kprobes | 473 | static void __kprobes |
1113 | t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs) | 474 | t16_emulate_loregs_noitrwflags(probes_opcode_t insn, |
475 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1114 | { | 476 | { |
1115 | unsigned long cpsr = t16_emulate_loregs(p, regs); | 477 | unsigned long cpsr = t16_emulate_loregs(insn, asi, regs); |
1116 | if (!in_it_block(cpsr)) | 478 | if (!in_it_block(cpsr)) |
1117 | regs->ARM_cpsr = cpsr; | 479 | regs->ARM_cpsr = cpsr; |
1118 | } | 480 | } |
1119 | 481 | ||
1120 | static void __kprobes | 482 | static void __kprobes |
1121 | t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) | 483 | t16_emulate_hiregs(probes_opcode_t insn, |
484 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1122 | { | 485 | { |
1123 | kprobe_opcode_t insn = p->opcode; | 486 | unsigned long pc = regs->ARM_pc + 2; |
1124 | unsigned long pc = thumb_probe_pc(p); | ||
1125 | int rdn = (insn & 0x7) | ((insn & 0x80) >> 4); | 487 | int rdn = (insn & 0x7) | ((insn & 0x80) >> 4); |
1126 | int rm = (insn >> 3) & 0xf; | 488 | int rm = (insn >> 3) & 0xf; |
1127 | 489 | ||
@@ -1137,7 +499,7 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) | |||
1137 | "blx %[fn] \n\t" | 499 | "blx %[fn] \n\t" |
1138 | "mrs %[cpsr], cpsr \n\t" | 500 | "mrs %[cpsr], cpsr \n\t" |
1139 | : "=r" (rdnv), [cpsr] "=r" (cpsr) | 501 | : "=r" (rdnv), [cpsr] "=r" (cpsr) |
1140 | : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 502 | : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn) |
1141 | : "lr", "memory", "cc" | 503 | : "lr", "memory", "cc" |
1142 | ); | 504 | ); |
1143 | 505 | ||
@@ -1148,8 +510,9 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) | |||
1148 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 510 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
1149 | } | 511 | } |
1150 | 512 | ||
1151 | static enum kprobe_insn __kprobes | 513 | static enum probes_insn __kprobes |
1152 | t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 514 | t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi, |
515 | const struct decode_header *d) | ||
1153 | { | 516 | { |
1154 | insn &= ~0x00ff; | 517 | insn &= ~0x00ff; |
1155 | insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ | 518 | insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ |
@@ -1159,7 +522,8 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1159 | } | 522 | } |
1160 | 523 | ||
1161 | static void __kprobes | 524 | static void __kprobes |
1162 | t16_emulate_push(struct kprobe *p, struct pt_regs *regs) | 525 | t16_emulate_push(probes_opcode_t insn, |
526 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1163 | { | 527 | { |
1164 | __asm__ __volatile__ ( | 528 | __asm__ __volatile__ ( |
1165 | "ldr r9, [%[regs], #13*4] \n\t" | 529 | "ldr r9, [%[regs], #13*4] \n\t" |
@@ -1168,14 +532,15 @@ t16_emulate_push(struct kprobe *p, struct pt_regs *regs) | |||
1168 | "blx %[fn] \n\t" | 532 | "blx %[fn] \n\t" |
1169 | "str r9, [%[regs], #13*4] \n\t" | 533 | "str r9, [%[regs], #13*4] \n\t" |
1170 | : | 534 | : |
1171 | : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) | 535 | : [regs] "r" (regs), [fn] "r" (asi->insn_fn) |
1172 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", | 536 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", |
1173 | "lr", "memory", "cc" | 537 | "lr", "memory", "cc" |
1174 | ); | 538 | ); |
1175 | } | 539 | } |
1176 | 540 | ||
1177 | static enum kprobe_insn __kprobes | 541 | static enum probes_insn __kprobes |
1178 | t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 542 | t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi, |
543 | const struct decode_header *d) | ||
1179 | { | 544 | { |
1180 | /* | 545 | /* |
1181 | * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}" | 546 | * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}" |
@@ -1189,7 +554,8 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1189 | } | 554 | } |
1190 | 555 | ||
1191 | static void __kprobes | 556 | static void __kprobes |
1192 | t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) | 557 | t16_emulate_pop_nopc(probes_opcode_t insn, |
558 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1193 | { | 559 | { |
1194 | __asm__ __volatile__ ( | 560 | __asm__ __volatile__ ( |
1195 | "ldr r9, [%[regs], #13*4] \n\t" | 561 | "ldr r9, [%[regs], #13*4] \n\t" |
@@ -1198,14 +564,15 @@ t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) | |||
1198 | "stmia %[regs], {r0-r7} \n\t" | 564 | "stmia %[regs], {r0-r7} \n\t" |
1199 | "str r9, [%[regs], #13*4] \n\t" | 565 | "str r9, [%[regs], #13*4] \n\t" |
1200 | : | 566 | : |
1201 | : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) | 567 | : [regs] "r" (regs), [fn] "r" (asi->insn_fn) |
1202 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", | 568 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", |
1203 | "lr", "memory", "cc" | 569 | "lr", "memory", "cc" |
1204 | ); | 570 | ); |
1205 | } | 571 | } |
1206 | 572 | ||
1207 | static void __kprobes | 573 | static void __kprobes |
1208 | t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) | 574 | t16_emulate_pop_pc(probes_opcode_t insn, |
575 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
1209 | { | 576 | { |
1210 | register unsigned long pc asm("r8"); | 577 | register unsigned long pc asm("r8"); |
1211 | 578 | ||
@@ -1216,7 +583,7 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) | |||
1216 | "stmia %[regs], {r0-r7} \n\t" | 583 | "stmia %[regs], {r0-r7} \n\t" |
1217 | "str r9, [%[regs], #13*4] \n\t" | 584 | "str r9, [%[regs], #13*4] \n\t" |
1218 | : "=r" (pc) | 585 | : "=r" (pc) |
1219 | : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) | 586 | : [regs] "r" (regs), [fn] "r" (asi->insn_fn) |
1220 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", | 587 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", |
1221 | "lr", "memory", "cc" | 588 | "lr", "memory", "cc" |
1222 | ); | 589 | ); |
@@ -1224,8 +591,9 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) | |||
1224 | bx_write_pc(pc, regs); | 591 | bx_write_pc(pc, regs); |
1225 | } | 592 | } |
1226 | 593 | ||
1227 | static enum kprobe_insn __kprobes | 594 | static enum probes_insn __kprobes |
1228 | t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 595 | t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi, |
596 | const struct decode_header *d) | ||
1229 | { | 597 | { |
1230 | /* | 598 | /* |
1231 | * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}" | 599 | * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}" |
@@ -1239,231 +607,56 @@ t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1239 | return INSN_GOOD; | 607 | return INSN_GOOD; |
1240 | } | 608 | } |
1241 | 609 | ||
1242 | static const union decode_item t16_table_1011[] = { | 610 | const union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = { |
1243 | /* Miscellaneous 16-bit instructions */ | 611 | [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm}, |
1244 | 612 | [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz}, | |
1245 | /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */ | 613 | [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags}, |
1246 | /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */ | 614 | [PROBES_T16_PUSH] = {.decoder = t16_decode_push}, |
1247 | DECODE_SIMULATE (0xff00, 0xb000, t16_simulate_add_sp_imm), | 615 | [PROBES_T16_POP] = {.decoder = t16_decode_pop}, |
1248 | 616 | [PROBES_T16_SEV] = {.handler = probes_emulate_none}, | |
1249 | /* CBZ 1011 00x1 xxxx xxxx */ | 617 | [PROBES_T16_WFE] = {.handler = probes_simulate_nop}, |
1250 | /* CBNZ 1011 10x1 xxxx xxxx */ | 618 | [PROBES_T16_IT] = {.decoder = t16_decode_it}, |
1251 | DECODE_SIMULATE (0xf500, 0xb100, t16_simulate_cbz), | 619 | [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags}, |
1252 | 620 | [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags}, | |
1253 | /* SXTH 1011 0010 00xx xxxx */ | 621 | [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags}, |
1254 | /* SXTB 1011 0010 01xx xxxx */ | 622 | [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal}, |
1255 | /* UXTH 1011 0010 10xx xxxx */ | 623 | [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx}, |
1256 | /* UXTB 1011 0010 11xx xxxx */ | 624 | [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs}, |
1257 | /* REV 1011 1010 00xx xxxx */ | 625 | [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags}, |
1258 | /* REV16 1011 1010 01xx xxxx */ | 626 | [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative}, |
1259 | /* ??? 1011 1010 10xx xxxx */ | 627 | [PROBES_T16_ADR] = {.handler = t16_simulate_reladr}, |
1260 | /* REVSH 1011 1010 11xx xxxx */ | 628 | [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags}, |
1261 | DECODE_REJECT (0xffc0, 0xba80), | 629 | [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch}, |
1262 | DECODE_EMULATE (0xf500, 0xb000, t16_emulate_loregs_rwflags), | 630 | [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch}, |
1263 | |||
1264 | /* PUSH 1011 010x xxxx xxxx */ | ||
1265 | DECODE_CUSTOM (0xfe00, 0xb400, t16_decode_push), | ||
1266 | /* POP 1011 110x xxxx xxxx */ | ||
1267 | DECODE_CUSTOM (0xfe00, 0xbc00, t16_decode_pop), | ||
1268 | |||
1269 | /* | ||
1270 | * If-Then, and hints | ||
1271 | * 1011 1111 xxxx xxxx | ||
1272 | */ | ||
1273 | |||
1274 | /* YIELD 1011 1111 0001 0000 */ | ||
1275 | DECODE_OR (0xffff, 0xbf10), | ||
1276 | /* SEV 1011 1111 0100 0000 */ | ||
1277 | DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none), | ||
1278 | /* NOP 1011 1111 0000 0000 */ | ||
1279 | /* WFE 1011 1111 0010 0000 */ | ||
1280 | /* WFI 1011 1111 0011 0000 */ | ||
1281 | DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop), | ||
1282 | /* Unassigned hints 1011 1111 xxxx 0000 */ | ||
1283 | DECODE_REJECT (0xff0f, 0xbf00), | ||
1284 | /* IT 1011 1111 xxxx xxxx */ | ||
1285 | DECODE_CUSTOM (0xff00, 0xbf00, t16_decode_it), | ||
1286 | |||
1287 | /* SETEND 1011 0110 010x xxxx */ | ||
1288 | /* CPS 1011 0110 011x xxxx */ | ||
1289 | /* BKPT 1011 1110 xxxx xxxx */ | ||
1290 | /* And unallocated instructions... */ | ||
1291 | DECODE_END | ||
1292 | }; | 631 | }; |
1293 | 632 | ||
1294 | const union decode_item kprobe_decode_thumb16_table[] = { | 633 | const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { |
1295 | 634 | [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm}, | |
1296 | /* | 635 | [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd}, |
1297 | * Shift (immediate), add, subtract, move, and compare | 636 | [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch}, |
1298 | * 00xx xxxx xxxx xxxx | 637 | [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, |
1299 | */ | 638 | [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, |
1300 | 639 | [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, | |
1301 | /* CMP (immediate) 0010 1xxx xxxx xxxx */ | 640 | [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, |
1302 | DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags), | 641 | [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, |
1303 | 642 | [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,}, | |
1304 | /* ADD (register) 0001 100x xxxx xxxx */ | 643 | [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags}, |
1305 | /* SUB (register) 0001 101x xxxx xxxx */ | 644 | [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags}, |
1306 | /* LSL (immediate) 0000 0xxx xxxx xxxx */ | 645 | [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, |
1307 | /* LSR (immediate) 0000 1xxx xxxx xxxx */ | 646 | [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags}, |
1308 | /* ASR (immediate) 0001 0xxx xxxx xxxx */ | 647 | [PROBES_T32_SEV] = {.handler = probes_emulate_none}, |
1309 | /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */ | 648 | [PROBES_T32_WFE] = {.handler = probes_simulate_nop}, |
1310 | /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */ | 649 | [PROBES_T32_MRS] = {.handler = t32_simulate_mrs}, |
1311 | /* MOV (immediate) 0010 0xxx xxxx xxxx */ | 650 | [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch}, |
1312 | /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */ | 651 | [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch}, |
1313 | /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */ | 652 | [PROBES_T32_PLDI] = {.handler = probes_simulate_nop}, |
1314 | DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags), | 653 | [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal}, |
1315 | 654 | [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr}, | |
1316 | /* | 655 | [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, |
1317 | * 16-bit Thumb data-processing instructions | 656 | [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, |
1318 | * 0100 00xx xxxx xxxx | 657 | [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags}, |
1319 | */ | 658 | [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, |
1320 | 659 | [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags}, | |
1321 | /* TST (register) 0100 0010 00xx xxxx */ | 660 | [PROBES_T32_MUL_ADD_LONG] = { |
1322 | DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags), | 661 | .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, |
1323 | /* CMP (register) 0100 0010 10xx xxxx */ | ||
1324 | /* CMN (register) 0100 0010 11xx xxxx */ | ||
1325 | DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags), | ||
1326 | /* AND (register) 0100 0000 00xx xxxx */ | ||
1327 | /* EOR (register) 0100 0000 01xx xxxx */ | ||
1328 | /* LSL (register) 0100 0000 10xx xxxx */ | ||
1329 | /* LSR (register) 0100 0000 11xx xxxx */ | ||
1330 | /* ASR (register) 0100 0001 00xx xxxx */ | ||
1331 | /* ADC (register) 0100 0001 01xx xxxx */ | ||
1332 | /* SBC (register) 0100 0001 10xx xxxx */ | ||
1333 | /* ROR (register) 0100 0001 11xx xxxx */ | ||
1334 | /* RSB (immediate) 0100 0010 01xx xxxx */ | ||
1335 | /* ORR (register) 0100 0011 00xx xxxx */ | ||
1336 | /* MUL 0100 0011 00xx xxxx */ | ||
1337 | /* BIC (register) 0100 0011 10xx xxxx */ | ||
1338 | /* MVN (register) 0100 0011 10xx xxxx */ | ||
1339 | DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags), | ||
1340 | |||
1341 | /* | ||
1342 | * Special data instructions and branch and exchange | ||
1343 | * 0100 01xx xxxx xxxx | ||
1344 | */ | ||
1345 | |||
1346 | /* BLX pc 0100 0111 1111 1xxx */ | ||
1347 | DECODE_REJECT (0xfff8, 0x47f8), | ||
1348 | |||
1349 | /* BX (register) 0100 0111 0xxx xxxx */ | ||
1350 | /* BLX (register) 0100 0111 1xxx xxxx */ | ||
1351 | DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx), | ||
1352 | |||
1353 | /* ADD pc, pc 0100 0100 1111 1111 */ | ||
1354 | DECODE_REJECT (0xffff, 0x44ff), | ||
1355 | |||
1356 | /* ADD (register) 0100 0100 xxxx xxxx */ | ||
1357 | /* CMP (register) 0100 0101 xxxx xxxx */ | ||
1358 | /* MOV (register) 0100 0110 xxxx xxxx */ | ||
1359 | DECODE_CUSTOM (0xfc00, 0x4400, t16_decode_hiregs), | ||
1360 | |||
1361 | /* | ||
1362 | * Load from Literal Pool | ||
1363 | * LDR (literal) 0100 1xxx xxxx xxxx | ||
1364 | */ | ||
1365 | DECODE_SIMULATE (0xf800, 0x4800, t16_simulate_ldr_literal), | ||
1366 | |||
1367 | /* | ||
1368 | * 16-bit Thumb Load/store instructions | ||
1369 | * 0101 xxxx xxxx xxxx | ||
1370 | * 011x xxxx xxxx xxxx | ||
1371 | * 100x xxxx xxxx xxxx | ||
1372 | */ | ||
1373 | |||
1374 | /* STR (register) 0101 000x xxxx xxxx */ | ||
1375 | /* STRH (register) 0101 001x xxxx xxxx */ | ||
1376 | /* STRB (register) 0101 010x xxxx xxxx */ | ||
1377 | /* LDRSB (register) 0101 011x xxxx xxxx */ | ||
1378 | /* LDR (register) 0101 100x xxxx xxxx */ | ||
1379 | /* LDRH (register) 0101 101x xxxx xxxx */ | ||
1380 | /* LDRB (register) 0101 110x xxxx xxxx */ | ||
1381 | /* LDRSH (register) 0101 111x xxxx xxxx */ | ||
1382 | /* STR (immediate, Thumb) 0110 0xxx xxxx xxxx */ | ||
1383 | /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */ | ||
1384 | /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */ | ||
1385 | /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */ | ||
1386 | DECODE_EMULATE (0xc000, 0x4000, t16_emulate_loregs_rwflags), | ||
1387 | /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */ | ||
1388 | /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */ | ||
1389 | DECODE_EMULATE (0xf000, 0x8000, t16_emulate_loregs_rwflags), | ||
1390 | /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */ | ||
1391 | /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */ | ||
1392 | DECODE_SIMULATE (0xf000, 0x9000, t16_simulate_ldrstr_sp_relative), | ||
1393 | |||
1394 | /* | ||
1395 | * Generate PC-/SP-relative address | ||
1396 | * ADR (literal) 1010 0xxx xxxx xxxx | ||
1397 | * ADD (SP plus immediate) 1010 1xxx xxxx xxxx | ||
1398 | */ | ||
1399 | DECODE_SIMULATE (0xf000, 0xa000, t16_simulate_reladr), | ||
1400 | |||
1401 | /* | ||
1402 | * Miscellaneous 16-bit instructions | ||
1403 | * 1011 xxxx xxxx xxxx | ||
1404 | */ | ||
1405 | DECODE_TABLE (0xf000, 0xb000, t16_table_1011), | ||
1406 | |||
1407 | /* STM 1100 0xxx xxxx xxxx */ | ||
1408 | /* LDM 1100 1xxx xxxx xxxx */ | ||
1409 | DECODE_EMULATE (0xf000, 0xc000, t16_emulate_loregs_rwflags), | ||
1410 | |||
1411 | /* | ||
1412 | * Conditional branch, and Supervisor Call | ||
1413 | */ | ||
1414 | |||
1415 | /* Permanently UNDEFINED 1101 1110 xxxx xxxx */ | ||
1416 | /* SVC 1101 1111 xxxx xxxx */ | ||
1417 | DECODE_REJECT (0xfe00, 0xde00), | ||
1418 | |||
1419 | /* Conditional branch 1101 xxxx xxxx xxxx */ | ||
1420 | DECODE_CUSTOM (0xf000, 0xd000, t16_decode_cond_branch), | ||
1421 | |||
1422 | /* | ||
1423 | * Unconditional branch | ||
1424 | * B 1110 0xxx xxxx xxxx | ||
1425 | */ | ||
1426 | DECODE_SIMULATE (0xf800, 0xe000, t16_simulate_branch), | ||
1427 | |||
1428 | DECODE_END | ||
1429 | }; | 662 | }; |
1430 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE | ||
1431 | EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table); | ||
1432 | #endif | ||
1433 | |||
1434 | static unsigned long __kprobes thumb_check_cc(unsigned long cpsr) | ||
1435 | { | ||
1436 | if (unlikely(in_it_block(cpsr))) | ||
1437 | return kprobe_condition_checks[current_cond(cpsr)](cpsr); | ||
1438 | return true; | ||
1439 | } | ||
1440 | |||
1441 | static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs) | ||
1442 | { | ||
1443 | regs->ARM_pc += 2; | ||
1444 | p->ainsn.insn_handler(p, regs); | ||
1445 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); | ||
1446 | } | ||
1447 | |||
1448 | static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs) | ||
1449 | { | ||
1450 | regs->ARM_pc += 4; | ||
1451 | p->ainsn.insn_handler(p, regs); | ||
1452 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); | ||
1453 | } | ||
1454 | |||
1455 | enum kprobe_insn __kprobes | ||
1456 | thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | ||
1457 | { | ||
1458 | asi->insn_singlestep = thumb16_singlestep; | ||
1459 | asi->insn_check_cc = thumb_check_cc; | ||
1460 | return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true); | ||
1461 | } | ||
1462 | |||
1463 | enum kprobe_insn __kprobes | ||
1464 | thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | ||
1465 | { | ||
1466 | asi->insn_singlestep = thumb32_singlestep; | ||
1467 | asi->insn_check_cc = thumb_check_cc; | ||
1468 | return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true); | ||
1469 | } | ||
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index a7b621ece23d..8795f9f819d5 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
@@ -27,8 +27,12 @@ | |||
27 | #include <linux/stringify.h> | 27 | #include <linux/stringify.h> |
28 | #include <asm/traps.h> | 28 | #include <asm/traps.h> |
29 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
30 | #include <linux/percpu.h> | ||
31 | #include <linux/bug.h> | ||
30 | 32 | ||
31 | #include "kprobes.h" | 33 | #include "kprobes.h" |
34 | #include "probes-arm.h" | ||
35 | #include "probes-thumb.h" | ||
32 | #include "patch.h" | 36 | #include "patch.h" |
33 | 37 | ||
34 | #define MIN_STACK_SIZE(addr) \ | 38 | #define MIN_STACK_SIZE(addr) \ |
@@ -54,6 +58,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
54 | unsigned long addr = (unsigned long)p->addr; | 58 | unsigned long addr = (unsigned long)p->addr; |
55 | bool thumb; | 59 | bool thumb; |
56 | kprobe_decode_insn_t *decode_insn; | 60 | kprobe_decode_insn_t *decode_insn; |
61 | const union decode_action *actions; | ||
57 | int is; | 62 | int is; |
58 | 63 | ||
59 | if (in_exception_text(addr)) | 64 | if (in_exception_text(addr)) |
@@ -66,21 +71,25 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
66 | if (is_wide_instruction(insn)) { | 71 | if (is_wide_instruction(insn)) { |
67 | insn <<= 16; | 72 | insn <<= 16; |
68 | insn |= ((u16 *)addr)[1]; | 73 | insn |= ((u16 *)addr)[1]; |
69 | decode_insn = thumb32_kprobe_decode_insn; | 74 | decode_insn = thumb32_probes_decode_insn; |
70 | } else | 75 | actions = kprobes_t32_actions; |
71 | decode_insn = thumb16_kprobe_decode_insn; | 76 | } else { |
77 | decode_insn = thumb16_probes_decode_insn; | ||
78 | actions = kprobes_t16_actions; | ||
79 | } | ||
72 | #else /* !CONFIG_THUMB2_KERNEL */ | 80 | #else /* !CONFIG_THUMB2_KERNEL */ |
73 | thumb = false; | 81 | thumb = false; |
74 | if (addr & 0x3) | 82 | if (addr & 0x3) |
75 | return -EINVAL; | 83 | return -EINVAL; |
76 | insn = *p->addr; | 84 | insn = *p->addr; |
77 | decode_insn = arm_kprobe_decode_insn; | 85 | decode_insn = arm_probes_decode_insn; |
86 | actions = kprobes_arm_actions; | ||
78 | #endif | 87 | #endif |
79 | 88 | ||
80 | p->opcode = insn; | 89 | p->opcode = insn; |
81 | p->ainsn.insn = tmp_insn; | 90 | p->ainsn.insn = tmp_insn; |
82 | 91 | ||
83 | switch ((*decode_insn)(insn, &p->ainsn)) { | 92 | switch ((*decode_insn)(insn, &p->ainsn, true, actions)) { |
84 | case INSN_REJECTED: /* not supported */ | 93 | case INSN_REJECTED: /* not supported */ |
85 | return -EINVAL; | 94 | return -EINVAL; |
86 | 95 | ||
@@ -92,7 +101,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
92 | p->ainsn.insn[is] = tmp_insn[is]; | 101 | p->ainsn.insn[is] = tmp_insn[is]; |
93 | flush_insns(p->ainsn.insn, | 102 | flush_insns(p->ainsn.insn, |
94 | sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE); | 103 | sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE); |
95 | p->ainsn.insn_fn = (kprobe_insn_fn_t *) | 104 | p->ainsn.insn_fn = (probes_insn_fn_t *) |
96 | ((uintptr_t)p->ainsn.insn | thumb); | 105 | ((uintptr_t)p->ainsn.insn | thumb); |
97 | break; | 106 | break; |
98 | 107 | ||
@@ -197,7 +206,7 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs) | |||
197 | static inline void __kprobes | 206 | static inline void __kprobes |
198 | singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) | 207 | singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) |
199 | { | 208 | { |
200 | p->ainsn.insn_singlestep(p, regs); | 209 | p->ainsn.insn_singlestep(p->opcode, &p->ainsn, regs); |
201 | } | 210 | } |
202 | 211 | ||
203 | /* | 212 | /* |
@@ -607,7 +616,7 @@ static struct undef_hook kprobes_arm_break_hook = { | |||
607 | 616 | ||
608 | int __init arch_init_kprobes() | 617 | int __init arch_init_kprobes() |
609 | { | 618 | { |
610 | arm_kprobe_decode_init(); | 619 | arm_probes_decode_init(); |
611 | #ifdef CONFIG_THUMB2_KERNEL | 620 | #ifdef CONFIG_THUMB2_KERNEL |
612 | register_undef_hook(&kprobes_thumb16_break_hook); | 621 | register_undef_hook(&kprobes_thumb16_break_hook); |
613 | register_undef_hook(&kprobes_thumb32_break_hook); | 622 | register_undef_hook(&kprobes_thumb32_break_hook); |
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h index 38945f78f9f1..9a2712ecefc3 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/kernel/kprobes.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #ifndef _ARM_KERNEL_KPROBES_H | 19 | #ifndef _ARM_KERNEL_KPROBES_H |
20 | #define _ARM_KERNEL_KPROBES_H | 20 | #define _ARM_KERNEL_KPROBES_H |
21 | 21 | ||
22 | #include "probes.h" | ||
23 | |||
22 | /* | 24 | /* |
23 | * These undefined instructions must be unique and | 25 | * These undefined instructions must be unique and |
24 | * reserved solely for kprobes' use. | 26 | * reserved solely for kprobes' use. |
@@ -27,402 +29,24 @@ | |||
27 | #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 | 29 | #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 |
28 | #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 | 30 | #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 |
29 | 31 | ||
32 | enum probes_insn __kprobes | ||
33 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, | ||
34 | const struct decode_header *h); | ||
30 | 35 | ||
31 | enum kprobe_insn { | 36 | typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, |
32 | INSN_REJECTED, | 37 | struct arch_probes_insn *, |
33 | INSN_GOOD, | 38 | bool, |
34 | INSN_GOOD_NO_SLOT | 39 | const union decode_action *); |
35 | }; | ||
36 | |||
37 | typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t, | ||
38 | struct arch_specific_insn *); | ||
39 | 40 | ||
40 | #ifdef CONFIG_THUMB2_KERNEL | 41 | #ifdef CONFIG_THUMB2_KERNEL |
41 | 42 | ||
42 | enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t, | 43 | extern const union decode_action kprobes_t32_actions[]; |
43 | struct arch_specific_insn *); | 44 | extern const union decode_action kprobes_t16_actions[]; |
44 | enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t, | ||
45 | struct arch_specific_insn *); | ||
46 | 45 | ||
47 | #else /* !CONFIG_THUMB2_KERNEL */ | 46 | #else /* !CONFIG_THUMB2_KERNEL */ |
48 | 47 | ||
49 | enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t, | 48 | extern const union decode_action kprobes_arm_actions[]; |
50 | struct arch_specific_insn *); | ||
51 | #endif | ||
52 | |||
53 | void __init arm_kprobe_decode_init(void); | ||
54 | |||
55 | extern kprobe_check_cc * const kprobe_condition_checks[16]; | ||
56 | |||
57 | |||
58 | #if __LINUX_ARM_ARCH__ >= 7 | ||
59 | |||
60 | /* str_pc_offset is architecturally defined from ARMv7 onwards */ | ||
61 | #define str_pc_offset 8 | ||
62 | #define find_str_pc_offset() | ||
63 | |||
64 | #else /* __LINUX_ARM_ARCH__ < 7 */ | ||
65 | |||
66 | /* We need a run-time check to determine str_pc_offset */ | ||
67 | extern int str_pc_offset; | ||
68 | void __init find_str_pc_offset(void); | ||
69 | 49 | ||
70 | #endif | 50 | #endif |
71 | 51 | ||
72 | |||
73 | /* | ||
74 | * Update ITSTATE after normal execution of an IT block instruction. | ||
75 | * | ||
76 | * The 8 IT state bits are split into two parts in CPSR: | ||
77 | * ITSTATE<1:0> are in CPSR<26:25> | ||
78 | * ITSTATE<7:2> are in CPSR<15:10> | ||
79 | */ | ||
80 | static inline unsigned long it_advance(unsigned long cpsr) | ||
81 | { | ||
82 | if ((cpsr & 0x06000400) == 0) { | ||
83 | /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */ | ||
84 | cpsr &= ~PSR_IT_MASK; | ||
85 | } else { | ||
86 | /* We need to shift left ITSTATE<4:0> */ | ||
87 | const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */ | ||
88 | unsigned long it = cpsr & mask; | ||
89 | it <<= 1; | ||
90 | it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */ | ||
91 | it &= mask; | ||
92 | cpsr &= ~mask; | ||
93 | cpsr |= it; | ||
94 | } | ||
95 | return cpsr; | ||
96 | } | ||
97 | |||
98 | static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs) | ||
99 | { | ||
100 | long cpsr = regs->ARM_cpsr; | ||
101 | if (pcv & 0x1) { | ||
102 | cpsr |= PSR_T_BIT; | ||
103 | pcv &= ~0x1; | ||
104 | } else { | ||
105 | cpsr &= ~PSR_T_BIT; | ||
106 | pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */ | ||
107 | } | ||
108 | regs->ARM_cpsr = cpsr; | ||
109 | regs->ARM_pc = pcv; | ||
110 | } | ||
111 | |||
112 | |||
113 | #if __LINUX_ARM_ARCH__ >= 6 | ||
114 | |||
115 | /* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */ | ||
116 | #define load_write_pc_interworks true | ||
117 | #define test_load_write_pc_interworking() | ||
118 | |||
119 | #else /* __LINUX_ARM_ARCH__ < 6 */ | ||
120 | |||
121 | /* We need run-time testing to determine if load_write_pc() should interwork. */ | ||
122 | extern bool load_write_pc_interworks; | ||
123 | void __init test_load_write_pc_interworking(void); | ||
124 | |||
125 | #endif | ||
126 | |||
127 | static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs) | ||
128 | { | ||
129 | if (load_write_pc_interworks) | ||
130 | bx_write_pc(pcv, regs); | ||
131 | else | ||
132 | regs->ARM_pc = pcv; | ||
133 | } | ||
134 | |||
135 | |||
136 | #if __LINUX_ARM_ARCH__ >= 7 | ||
137 | |||
138 | #define alu_write_pc_interworks true | ||
139 | #define test_alu_write_pc_interworking() | ||
140 | |||
141 | #elif __LINUX_ARM_ARCH__ <= 5 | ||
142 | |||
143 | /* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */ | ||
144 | #define alu_write_pc_interworks false | ||
145 | #define test_alu_write_pc_interworking() | ||
146 | |||
147 | #else /* __LINUX_ARM_ARCH__ == 6 */ | ||
148 | |||
149 | /* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */ | ||
150 | extern bool alu_write_pc_interworks; | ||
151 | void __init test_alu_write_pc_interworking(void); | ||
152 | |||
153 | #endif /* __LINUX_ARM_ARCH__ == 6 */ | ||
154 | |||
155 | static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs) | ||
156 | { | ||
157 | if (alu_write_pc_interworks) | ||
158 | bx_write_pc(pcv, regs); | ||
159 | else | ||
160 | regs->ARM_pc = pcv; | ||
161 | } | ||
162 | |||
163 | |||
164 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); | ||
165 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); | ||
166 | |||
167 | enum kprobe_insn __kprobes | ||
168 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); | ||
169 | |||
170 | /* | ||
171 | * Test if load/store instructions writeback the address register. | ||
172 | * if P (bit 24) == 0 or W (bit 21) == 1 | ||
173 | */ | ||
174 | #define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000) | ||
175 | |||
176 | /* | ||
177 | * The following definitions and macros are used to build instruction | ||
178 | * decoding tables for use by kprobe_decode_insn. | ||
179 | * | ||
180 | * These tables are a concatenation of entries each of which consist of one of | ||
181 | * the decode_* structs. All of the fields in every type of decode structure | ||
182 | * are of the union type decode_item, therefore the entire decode table can be | ||
183 | * viewed as an array of these and declared like: | ||
184 | * | ||
185 | * static const union decode_item table_name[] = {}; | ||
186 | * | ||
187 | * In order to construct each entry in the table, macros are used to | ||
188 | * initialise a number of sequential decode_item values in a layout which | ||
189 | * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct | ||
190 | * decode_simulate by initialising four decode_item objects like this... | ||
191 | * | ||
192 | * {.bits = _type}, | ||
193 | * {.bits = _mask}, | ||
194 | * {.bits = _value}, | ||
195 | * {.handler = _handler}, | ||
196 | * | ||
197 | * Initialising a specified member of the union means that the compiler | ||
198 | * will produce a warning if the argument is of an incorrect type. | ||
199 | * | ||
200 | * Below is a list of each of the macros used to initialise entries and a | ||
201 | * description of the action performed when that entry is matched to an | ||
202 | * instruction. A match is found when (instruction & mask) == value. | ||
203 | * | ||
204 | * DECODE_TABLE(mask, value, table) | ||
205 | * Instruction decoding jumps to parsing the new sub-table 'table'. | ||
206 | * | ||
207 | * DECODE_CUSTOM(mask, value, decoder) | ||
208 | * The custom function 'decoder' is called to the complete decoding | ||
209 | * of an instruction. | ||
210 | * | ||
211 | * DECODE_SIMULATE(mask, value, handler) | ||
212 | * Set the probes instruction handler to 'handler', this will be used | ||
213 | * to simulate the instruction when the probe is hit. Decoding returns | ||
214 | * with INSN_GOOD_NO_SLOT. | ||
215 | * | ||
216 | * DECODE_EMULATE(mask, value, handler) | ||
217 | * Set the probes instruction handler to 'handler', this will be used | ||
218 | * to emulate the instruction when the probe is hit. The modified | ||
219 | * instruction (see below) is placed in the probes instruction slot so it | ||
220 | * may be called by the emulation code. Decoding returns with INSN_GOOD. | ||
221 | * | ||
222 | * DECODE_REJECT(mask, value) | ||
223 | * Instruction decoding fails with INSN_REJECTED | ||
224 | * | ||
225 | * DECODE_OR(mask, value) | ||
226 | * This allows the mask/value test of multiple table entries to be | ||
227 | * logically ORed. Once an 'or' entry is matched the decoding action to | ||
228 | * be performed is that of the next entry which isn't an 'or'. E.g. | ||
229 | * | ||
230 | * DECODE_OR (mask1, value1) | ||
231 | * DECODE_OR (mask2, value2) | ||
232 | * DECODE_SIMULATE (mask3, value3, simulation_handler) | ||
233 | * | ||
234 | * This means that if any of the three mask/value pairs match the | ||
235 | * instruction being decoded, then 'simulation_handler' will be used | ||
236 | * for it. | ||
237 | * | ||
238 | * Both the SIMULATE and EMULATE macros have a second form which take an | ||
239 | * additional 'regs' argument. | ||
240 | * | ||
241 | * DECODE_SIMULATEX(mask, value, handler, regs) | ||
242 | * DECODE_EMULATEX (mask, value, handler, regs) | ||
243 | * | ||
244 | * These are used to specify what kind of CPU register is encoded in each of the | ||
245 | * least significant 5 nibbles of the instruction being decoded. The regs value | ||
246 | * is specified using the REGS macro, this takes any of the REG_TYPE_* values | ||
247 | * from enum decode_reg_type as arguments; only the '*' part of the name is | ||
248 | * given. E.g. | ||
249 | * | ||
250 | * REGS(0, ANY, NOPC, 0, ANY) | ||
251 | * | ||
252 | * This indicates an instruction is encoded like: | ||
253 | * | ||
254 | * bits 19..16 ignore | ||
255 | * bits 15..12 any register allowed here | ||
256 | * bits 11.. 8 any register except PC allowed here | ||
257 | * bits 7.. 4 ignore | ||
258 | * bits 3.. 0 any register allowed here | ||
259 | * | ||
260 | * This register specification is checked after a decode table entry is found to | ||
261 | * match an instruction (through the mask/value test). Any invalid register then | ||
262 | * found in the instruction will cause decoding to fail with INSN_REJECTED. In | ||
263 | * the above example this would happen if bits 11..8 of the instruction were | ||
264 | * 1111, indicating R15 or PC. | ||
265 | * | ||
266 | * As well as checking for legal combinations of registers, this data is also | ||
267 | * used to modify the registers encoded in the instructions so that an | ||
268 | * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.) | ||
269 | * | ||
270 | * Here is a real example which matches ARM instructions of the form | ||
271 | * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>" | ||
272 | * | ||
273 | * DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, | ||
274 | * REGS(ANY, ANY, NOPC, 0, ANY)), | ||
275 | * ^ ^ ^ ^ | ||
276 | * Rn Rd Rs Rm | ||
277 | * | ||
278 | * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because | ||
279 | * Rs == R15 | ||
280 | * | ||
281 | * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the | ||
282 | * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into | ||
283 | * the kprobes instruction slot. This can then be called later by the handler | ||
284 | * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction. | ||
285 | */ | ||
286 | |||
287 | enum decode_type { | ||
288 | DECODE_TYPE_END, | ||
289 | DECODE_TYPE_TABLE, | ||
290 | DECODE_TYPE_CUSTOM, | ||
291 | DECODE_TYPE_SIMULATE, | ||
292 | DECODE_TYPE_EMULATE, | ||
293 | DECODE_TYPE_OR, | ||
294 | DECODE_TYPE_REJECT, | ||
295 | NUM_DECODE_TYPES /* Must be last enum */ | ||
296 | }; | ||
297 | |||
298 | #define DECODE_TYPE_BITS 4 | ||
299 | #define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1) | ||
300 | |||
301 | enum decode_reg_type { | ||
302 | REG_TYPE_NONE = 0, /* Not a register, ignore */ | ||
303 | REG_TYPE_ANY, /* Any register allowed */ | ||
304 | REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */ | ||
305 | REG_TYPE_SP, /* Register must be SP */ | ||
306 | REG_TYPE_PC, /* Register must be PC */ | ||
307 | REG_TYPE_NOSP, /* Register must not be SP */ | ||
308 | REG_TYPE_NOSPPC, /* Register must not be SP or PC */ | ||
309 | REG_TYPE_NOPC, /* Register must not be PC */ | ||
310 | REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */ | ||
311 | |||
312 | /* The following types are used when the encoding for PC indicates | ||
313 | * another instruction form. This distiction only matters for test | ||
314 | * case coverage checks. | ||
315 | */ | ||
316 | REG_TYPE_NOPCX, /* Register must not be PC */ | ||
317 | REG_TYPE_NOSPPCX, /* Register must not be SP or PC */ | ||
318 | |||
319 | /* Alias to allow '0' arg to be used in REGS macro. */ | ||
320 | REG_TYPE_0 = REG_TYPE_NONE | ||
321 | }; | ||
322 | |||
323 | #define REGS(r16, r12, r8, r4, r0) \ | ||
324 | ((REG_TYPE_##r16) << 16) + \ | ||
325 | ((REG_TYPE_##r12) << 12) + \ | ||
326 | ((REG_TYPE_##r8) << 8) + \ | ||
327 | ((REG_TYPE_##r4) << 4) + \ | ||
328 | (REG_TYPE_##r0) | ||
329 | |||
330 | union decode_item { | ||
331 | u32 bits; | ||
332 | const union decode_item *table; | ||
333 | kprobe_insn_handler_t *handler; | ||
334 | kprobe_decode_insn_t *decoder; | ||
335 | }; | ||
336 | |||
337 | |||
338 | #define DECODE_END \ | ||
339 | {.bits = DECODE_TYPE_END} | ||
340 | |||
341 | |||
342 | struct decode_header { | ||
343 | union decode_item type_regs; | ||
344 | union decode_item mask; | ||
345 | union decode_item value; | ||
346 | }; | ||
347 | |||
348 | #define DECODE_HEADER(_type, _mask, _value, _regs) \ | ||
349 | {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \ | ||
350 | {.bits = (_mask)}, \ | ||
351 | {.bits = (_value)} | ||
352 | |||
353 | |||
354 | struct decode_table { | ||
355 | struct decode_header header; | ||
356 | union decode_item table; | ||
357 | }; | ||
358 | |||
359 | #define DECODE_TABLE(_mask, _value, _table) \ | ||
360 | DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \ | ||
361 | {.table = (_table)} | ||
362 | |||
363 | |||
364 | struct decode_custom { | ||
365 | struct decode_header header; | ||
366 | union decode_item decoder; | ||
367 | }; | ||
368 | |||
369 | #define DECODE_CUSTOM(_mask, _value, _decoder) \ | ||
370 | DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \ | ||
371 | {.decoder = (_decoder)} | ||
372 | |||
373 | |||
374 | struct decode_simulate { | ||
375 | struct decode_header header; | ||
376 | union decode_item handler; | ||
377 | }; | ||
378 | |||
379 | #define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \ | ||
380 | DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \ | ||
381 | {.handler = (_handler)} | ||
382 | |||
383 | #define DECODE_SIMULATE(_mask, _value, _handler) \ | ||
384 | DECODE_SIMULATEX(_mask, _value, _handler, 0) | ||
385 | |||
386 | |||
387 | struct decode_emulate { | ||
388 | struct decode_header header; | ||
389 | union decode_item handler; | ||
390 | }; | ||
391 | |||
392 | #define DECODE_EMULATEX(_mask, _value, _handler, _regs) \ | ||
393 | DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \ | ||
394 | {.handler = (_handler)} | ||
395 | |||
396 | #define DECODE_EMULATE(_mask, _value, _handler) \ | ||
397 | DECODE_EMULATEX(_mask, _value, _handler, 0) | ||
398 | |||
399 | |||
400 | struct decode_or { | ||
401 | struct decode_header header; | ||
402 | }; | ||
403 | |||
404 | #define DECODE_OR(_mask, _value) \ | ||
405 | DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0) | ||
406 | |||
407 | |||
408 | struct decode_reject { | ||
409 | struct decode_header header; | ||
410 | }; | ||
411 | |||
412 | #define DECODE_REJECT(_mask, _value) \ | ||
413 | DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) | ||
414 | |||
415 | |||
416 | #ifdef CONFIG_THUMB2_KERNEL | ||
417 | extern const union decode_item kprobe_decode_thumb16_table[]; | ||
418 | extern const union decode_item kprobe_decode_thumb32_table[]; | ||
419 | #else | ||
420 | extern const union decode_item kprobe_decode_arm_table[]; | ||
421 | #endif | ||
422 | |||
423 | |||
424 | int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
425 | const union decode_item *table, bool thumb16); | ||
426 | |||
427 | |||
428 | #endif /* _ARM_KERNEL_KPROBES_H */ | 52 | #endif /* _ARM_KERNEL_KPROBES_H */ |
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c new file mode 100644 index 000000000000..51a13a027989 --- /dev/null +++ b/arch/arm/kernel/probes-arm.c | |||
@@ -0,0 +1,734 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes-arm.c | ||
3 | * | ||
4 | * Some code moved here from arch/arm/kernel/kprobes-arm.c | ||
5 | * | ||
6 | * Copyright (C) 2006, 2007 Motorola Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
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 GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/stddef.h> | ||
21 | #include <linux/ptrace.h> | ||
22 | |||
23 | #include "probes.h" | ||
24 | #include "probes-arm.h" | ||
25 | |||
26 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) | ||
27 | |||
28 | #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) | ||
29 | |||
30 | /* | ||
31 | * To avoid the complications of mimicing single-stepping on a | ||
32 | * processor without a Next-PC or a single-step mode, and to | ||
33 | * avoid having to deal with the side-effects of boosting, we | ||
34 | * simulate or emulate (almost) all ARM instructions. | ||
35 | * | ||
36 | * "Simulation" is where the instruction's behavior is duplicated in | ||
37 | * C code. "Emulation" is where the original instruction is rewritten | ||
38 | * and executed, often by altering its registers. | ||
39 | * | ||
40 | * By having all behavior of the kprobe'd instruction completed before | ||
41 | * returning from the kprobe_handler(), all locks (scheduler and | ||
42 | * interrupt) can safely be released. There is no need for secondary | ||
43 | * breakpoints, no race with MP or preemptable kernels, nor having to | ||
44 | * clean up resources counts at a later time impacting overall system | ||
45 | * performance. By rewriting the instruction, only the minimum registers | ||
46 | * need to be loaded and saved back optimizing performance. | ||
47 | * | ||
48 | * Calling the insnslot_*_rwflags version of a function doesn't hurt | ||
49 | * anything even when the CPSR flags aren't updated by the | ||
50 | * instruction. It's just a little slower in return for saving | ||
51 | * a little space by not having a duplicate function that doesn't | ||
52 | * update the flags. (The same optimization can be said for | ||
53 | * instructions that do or don't perform register writeback) | ||
54 | * Also, instructions can either read the flags, only write the | ||
55 | * flags, or read and write the flags. To save combinations | ||
56 | * rather than for sheer performance, flag functions just assume | ||
57 | * read and write of flags. | ||
58 | */ | ||
59 | |||
60 | void __kprobes simulate_bbl(probes_opcode_t insn, | ||
61 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
62 | { | ||
63 | long iaddr = (long) regs->ARM_pc - 4; | ||
64 | int disp = branch_displacement(insn); | ||
65 | |||
66 | if (insn & (1 << 24)) | ||
67 | regs->ARM_lr = iaddr + 4; | ||
68 | |||
69 | regs->ARM_pc = iaddr + 8 + disp; | ||
70 | } | ||
71 | |||
72 | void __kprobes simulate_blx1(probes_opcode_t insn, | ||
73 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
74 | { | ||
75 | long iaddr = (long) regs->ARM_pc - 4; | ||
76 | int disp = branch_displacement(insn); | ||
77 | |||
78 | regs->ARM_lr = iaddr + 4; | ||
79 | regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2); | ||
80 | regs->ARM_cpsr |= PSR_T_BIT; | ||
81 | } | ||
82 | |||
83 | void __kprobes simulate_blx2bx(probes_opcode_t insn, | ||
84 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
85 | { | ||
86 | int rm = insn & 0xf; | ||
87 | long rmv = regs->uregs[rm]; | ||
88 | |||
89 | if (insn & (1 << 5)) | ||
90 | regs->ARM_lr = (long) regs->ARM_pc; | ||
91 | |||
92 | regs->ARM_pc = rmv & ~0x1; | ||
93 | regs->ARM_cpsr &= ~PSR_T_BIT; | ||
94 | if (rmv & 0x1) | ||
95 | regs->ARM_cpsr |= PSR_T_BIT; | ||
96 | } | ||
97 | |||
98 | void __kprobes simulate_mrs(probes_opcode_t insn, | ||
99 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
100 | { | ||
101 | int rd = (insn >> 12) & 0xf; | ||
102 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ | ||
103 | regs->uregs[rd] = regs->ARM_cpsr & mask; | ||
104 | } | ||
105 | |||
106 | void __kprobes simulate_mov_ipsp(probes_opcode_t insn, | ||
107 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
108 | { | ||
109 | regs->uregs[12] = regs->uregs[13]; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * For the instruction masking and comparisons in all the "space_*" | ||
114 | * functions below, Do _not_ rearrange the order of tests unless | ||
115 | * you're very, very sure of what you are doing. For the sake of | ||
116 | * efficiency, the masks for some tests sometimes assume other test | ||
117 | * have been done prior to them so the number of patterns to test | ||
118 | * for an instruction set can be as broad as possible to reduce the | ||
119 | * number of tests needed. | ||
120 | */ | ||
121 | |||
122 | static const union decode_item arm_1111_table[] = { | ||
123 | /* Unconditional instructions */ | ||
124 | |||
125 | /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */ | ||
126 | /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */ | ||
127 | /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */ | ||
128 | /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */ | ||
129 | DECODE_SIMULATE (0xfe300000, 0xf4100000, PROBES_PRELOAD_IMM), | ||
130 | |||
131 | /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */ | ||
132 | /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */ | ||
133 | /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */ | ||
134 | /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */ | ||
135 | DECODE_SIMULATE (0xfe300010, 0xf6100000, PROBES_PRELOAD_REG), | ||
136 | |||
137 | /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
138 | DECODE_SIMULATE (0xfe000000, 0xfa000000, PROBES_BRANCH_IMM), | ||
139 | |||
140 | /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */ | ||
141 | /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ | ||
142 | /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
143 | /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
144 | |||
145 | /* Coprocessor instructions... */ | ||
146 | /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
147 | /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
148 | /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | ||
149 | /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | ||
150 | /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | ||
151 | /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | ||
152 | /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | ||
153 | |||
154 | /* Other unallocated instructions... */ | ||
155 | DECODE_END | ||
156 | }; | ||
157 | |||
158 | static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = { | ||
159 | /* Miscellaneous instructions */ | ||
160 | |||
161 | /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ | ||
162 | DECODE_SIMULATEX(0x0ff000f0, 0x01000000, PROBES_MRS, | ||
163 | REGS(0, NOPC, 0, 0, 0)), | ||
164 | |||
165 | /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
166 | DECODE_SIMULATE (0x0ff000f0, 0x01200010, PROBES_BRANCH_REG), | ||
167 | |||
168 | /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
169 | DECODE_SIMULATEX(0x0ff000f0, 0x01200030, PROBES_BRANCH_REG, | ||
170 | REGS(0, 0, 0, 0, NOPC)), | ||
171 | |||
172 | /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
173 | DECODE_EMULATEX (0x0ff000f0, 0x01600010, PROBES_CLZ, | ||
174 | REGS(0, NOPC, 0, 0, NOPC)), | ||
175 | |||
176 | /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */ | ||
177 | /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
178 | /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */ | ||
179 | /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
180 | DECODE_EMULATEX (0x0f9000f0, 0x01000050, PROBES_SATURATING_ARITHMETIC, | ||
181 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
182 | |||
183 | /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ | ||
184 | /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ | ||
185 | /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ | ||
186 | /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
187 | /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
188 | /* And unallocated instructions... */ | ||
189 | DECODE_END | ||
190 | }; | ||
191 | |||
192 | static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = { | ||
193 | /* Halfword multiply and multiply-accumulate */ | ||
194 | |||
195 | /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ | ||
196 | DECODE_EMULATEX (0x0ff00090, 0x01400080, PROBES_MUL1, | ||
197 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
198 | |||
199 | /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ | ||
200 | DECODE_OR (0x0ff000b0, 0x012000a0), | ||
201 | /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ | ||
202 | DECODE_EMULATEX (0x0ff00090, 0x01600080, PROBES_MUL2, | ||
203 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
204 | |||
205 | /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */ | ||
206 | DECODE_OR (0x0ff00090, 0x01000080), | ||
207 | /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */ | ||
208 | DECODE_EMULATEX (0x0ff000b0, 0x01200080, PROBES_MUL2, | ||
209 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
210 | |||
211 | DECODE_END | ||
212 | }; | ||
213 | |||
214 | static const union decode_item arm_cccc_0000_____1001_table[] = { | ||
215 | /* Multiply and multiply-accumulate */ | ||
216 | |||
217 | /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */ | ||
218 | /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
219 | DECODE_EMULATEX (0x0fe000f0, 0x00000090, PROBES_MUL2, | ||
220 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
221 | |||
222 | /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
223 | /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
224 | DECODE_OR (0x0fe000f0, 0x00200090), | ||
225 | /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
226 | DECODE_EMULATEX (0x0ff000f0, 0x00600090, PROBES_MUL2, | ||
227 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
228 | |||
229 | /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */ | ||
230 | DECODE_OR (0x0ff000f0, 0x00400090), | ||
231 | /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */ | ||
232 | /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */ | ||
233 | /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */ | ||
234 | /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */ | ||
235 | /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */ | ||
236 | /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */ | ||
237 | /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */ | ||
238 | /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */ | ||
239 | DECODE_EMULATEX (0x0f8000f0, 0x00800090, PROBES_MUL1, | ||
240 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
241 | |||
242 | DECODE_END | ||
243 | }; | ||
244 | |||
245 | static const union decode_item arm_cccc_0001_____1001_table[] = { | ||
246 | /* Synchronization primitives */ | ||
247 | |||
248 | #if __LINUX_ARM_ARCH__ < 6 | ||
249 | /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ | ||
250 | /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ | ||
251 | DECODE_EMULATEX (0x0fb000f0, 0x01000090, PROBES_SWP, | ||
252 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
253 | #endif | ||
254 | /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ | ||
255 | /* And unallocated instructions... */ | ||
256 | DECODE_END | ||
257 | }; | ||
258 | |||
259 | static const union decode_item arm_cccc_000x_____1xx1_table[] = { | ||
260 | /* Extra load/store instructions */ | ||
261 | |||
262 | /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */ | ||
263 | /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */ | ||
264 | /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */ | ||
265 | /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */ | ||
266 | /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */ | ||
267 | DECODE_REJECT (0x0f200090, 0x00200090), | ||
268 | |||
269 | /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */ | ||
270 | DECODE_REJECT (0x0e10e0d0, 0x0000e0d0), | ||
271 | |||
272 | /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */ | ||
273 | /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */ | ||
274 | DECODE_EMULATEX (0x0e5000d0, 0x000000d0, PROBES_LDRSTRD, | ||
275 | REGS(NOPCWB, NOPCX, 0, 0, NOPC)), | ||
276 | |||
277 | /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */ | ||
278 | /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */ | ||
279 | DECODE_EMULATEX (0x0e5000d0, 0x004000d0, PROBES_LDRSTRD, | ||
280 | REGS(NOPCWB, NOPCX, 0, 0, 0)), | ||
281 | |||
282 | /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ | ||
283 | DECODE_EMULATEX (0x0e5000f0, 0x000000b0, PROBES_STORE_EXTRA, | ||
284 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | ||
285 | |||
286 | /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */ | ||
287 | /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */ | ||
288 | /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */ | ||
289 | DECODE_EMULATEX (0x0e500090, 0x00100090, PROBES_LOAD_EXTRA, | ||
290 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | ||
291 | |||
292 | /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ | ||
293 | DECODE_EMULATEX (0x0e5000f0, 0x004000b0, PROBES_STORE_EXTRA, | ||
294 | REGS(NOPCWB, NOPC, 0, 0, 0)), | ||
295 | |||
296 | /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */ | ||
297 | /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */ | ||
298 | /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */ | ||
299 | DECODE_EMULATEX (0x0e500090, 0x00500090, PROBES_LOAD_EXTRA, | ||
300 | REGS(NOPCWB, NOPC, 0, 0, 0)), | ||
301 | |||
302 | DECODE_END | ||
303 | }; | ||
304 | |||
305 | static const union decode_item arm_cccc_000x_table[] = { | ||
306 | /* Data-processing (register) */ | ||
307 | |||
308 | /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */ | ||
309 | DECODE_REJECT (0x0e10f000, 0x0010f000), | ||
310 | |||
311 | /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */ | ||
312 | DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, PROBES_MOV_IP_SP), | ||
313 | |||
314 | /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */ | ||
315 | /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */ | ||
316 | /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */ | ||
317 | /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */ | ||
318 | DECODE_EMULATEX (0x0f900010, 0x01100000, PROBES_DATA_PROCESSING_REG, | ||
319 | REGS(ANY, 0, 0, 0, ANY)), | ||
320 | |||
321 | /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */ | ||
322 | /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */ | ||
323 | DECODE_EMULATEX (0x0fa00010, 0x01a00000, PROBES_DATA_PROCESSING_REG, | ||
324 | REGS(0, ANY, 0, 0, ANY)), | ||
325 | |||
326 | /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */ | ||
327 | /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */ | ||
328 | /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */ | ||
329 | /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */ | ||
330 | /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */ | ||
331 | /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */ | ||
332 | /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */ | ||
333 | /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */ | ||
334 | /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */ | ||
335 | /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */ | ||
336 | DECODE_EMULATEX (0x0e000010, 0x00000000, PROBES_DATA_PROCESSING_REG, | ||
337 | REGS(ANY, ANY, 0, 0, ANY)), | ||
338 | |||
339 | /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */ | ||
340 | /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */ | ||
341 | /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */ | ||
342 | /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */ | ||
343 | DECODE_EMULATEX (0x0f900090, 0x01100010, PROBES_DATA_PROCESSING_REG, | ||
344 | REGS(ANY, 0, NOPC, 0, ANY)), | ||
345 | |||
346 | /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */ | ||
347 | /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */ | ||
348 | DECODE_EMULATEX (0x0fa00090, 0x01a00010, PROBES_DATA_PROCESSING_REG, | ||
349 | REGS(0, ANY, NOPC, 0, ANY)), | ||
350 | |||
351 | /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */ | ||
352 | /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */ | ||
353 | /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */ | ||
354 | /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */ | ||
355 | /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */ | ||
356 | /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */ | ||
357 | /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */ | ||
358 | /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */ | ||
359 | /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */ | ||
360 | /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */ | ||
361 | DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG, | ||
362 | REGS(ANY, ANY, NOPC, 0, ANY)), | ||
363 | |||
364 | DECODE_END | ||
365 | }; | ||
366 | |||
367 | static const union decode_item arm_cccc_001x_table[] = { | ||
368 | /* Data-processing (immediate) */ | ||
369 | |||
370 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ | ||
371 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
372 | DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_DATA_PROCESSING_IMM, | ||
373 | REGS(0, NOPC, 0, 0, 0)), | ||
374 | |||
375 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | ||
376 | DECODE_OR (0x0fff00ff, 0x03200001), | ||
377 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ | ||
378 | DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_EMULATE_NONE), | ||
379 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ | ||
380 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ | ||
381 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ | ||
382 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_SIMULATE_NOP), | ||
383 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ | ||
384 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ | ||
385 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ | ||
386 | DECODE_REJECT (0x0fb00000, 0x03200000), | ||
387 | |||
388 | /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ | ||
389 | DECODE_REJECT (0x0e10f000, 0x0210f000), | ||
390 | |||
391 | /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */ | ||
392 | /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */ | ||
393 | /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
394 | /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */ | ||
395 | DECODE_EMULATEX (0x0f900000, 0x03100000, PROBES_DATA_PROCESSING_IMM, | ||
396 | REGS(ANY, 0, 0, 0, 0)), | ||
397 | |||
398 | /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */ | ||
399 | /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */ | ||
400 | DECODE_EMULATEX (0x0fa00000, 0x03a00000, PROBES_DATA_PROCESSING_IMM, | ||
401 | REGS(0, ANY, 0, 0, 0)), | ||
402 | |||
403 | /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */ | ||
404 | /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */ | ||
405 | /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */ | ||
406 | /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */ | ||
407 | /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */ | ||
408 | /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */ | ||
409 | /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */ | ||
410 | /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */ | ||
411 | /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */ | ||
412 | /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */ | ||
413 | DECODE_EMULATEX (0x0e000000, 0x02000000, PROBES_DATA_PROCESSING_IMM, | ||
414 | REGS(ANY, ANY, 0, 0, 0)), | ||
415 | |||
416 | DECODE_END | ||
417 | }; | ||
418 | |||
419 | static const union decode_item arm_cccc_0110_____xxx1_table[] = { | ||
420 | /* Media instructions */ | ||
421 | |||
422 | /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */ | ||
423 | DECODE_EMULATEX (0x0ff000f0, 0x068000b0, PROBES_SATURATE, | ||
424 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
425 | |||
426 | /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */ | ||
427 | /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */ | ||
428 | DECODE_OR(0x0fa00030, 0x06a00010), | ||
429 | /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */ | ||
430 | /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */ | ||
431 | DECODE_EMULATEX (0x0fb000f0, 0x06a00030, PROBES_SATURATE, | ||
432 | REGS(0, NOPC, 0, 0, NOPC)), | ||
433 | |||
434 | /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */ | ||
435 | /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */ | ||
436 | /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */ | ||
437 | /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */ | ||
438 | DECODE_EMULATEX (0x0fb00070, 0x06b00030, PROBES_REV, | ||
439 | REGS(0, NOPC, 0, 0, NOPC)), | ||
440 | |||
441 | /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */ | ||
442 | DECODE_REJECT (0x0fb00010, 0x06000010), | ||
443 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */ | ||
444 | DECODE_REJECT (0x0f8000f0, 0x060000b0), | ||
445 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */ | ||
446 | DECODE_REJECT (0x0f8000f0, 0x060000d0), | ||
447 | /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */ | ||
448 | /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */ | ||
449 | /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */ | ||
450 | /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */ | ||
451 | /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
452 | /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */ | ||
453 | /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
454 | /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
455 | /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
456 | /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
457 | /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
458 | /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */ | ||
459 | /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */ | ||
460 | /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */ | ||
461 | /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */ | ||
462 | /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */ | ||
463 | /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
464 | /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */ | ||
465 | /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */ | ||
466 | /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */ | ||
467 | /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */ | ||
468 | /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */ | ||
469 | /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */ | ||
470 | /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */ | ||
471 | /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
472 | /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */ | ||
473 | /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
474 | /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
475 | /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
476 | /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */ | ||
477 | /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */ | ||
478 | /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */ | ||
479 | /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */ | ||
480 | /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */ | ||
481 | /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */ | ||
482 | /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */ | ||
483 | DECODE_EMULATEX (0x0f800010, 0x06000010, PROBES_MMI, | ||
484 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
485 | |||
486 | /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */ | ||
487 | /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */ | ||
488 | DECODE_EMULATEX (0x0ff00030, 0x06800010, PROBES_PACK, | ||
489 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
490 | |||
491 | /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */ | ||
492 | /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */ | ||
493 | DECODE_REJECT (0x0fb000f0, 0x06900070), | ||
494 | |||
495 | /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */ | ||
496 | /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */ | ||
497 | /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */ | ||
498 | /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */ | ||
499 | /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */ | ||
500 | /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */ | ||
501 | DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, PROBES_EXTEND, | ||
502 | REGS(0, NOPC, 0, 0, NOPC)), | ||
503 | |||
504 | /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */ | ||
505 | /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */ | ||
506 | /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */ | ||
507 | /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */ | ||
508 | /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */ | ||
509 | /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */ | ||
510 | DECODE_EMULATEX (0x0f8000f0, 0x06800070, PROBES_EXTEND_ADD, | ||
511 | REGS(NOPCX, NOPC, 0, 0, NOPC)), | ||
512 | |||
513 | DECODE_END | ||
514 | }; | ||
515 | |||
516 | static const union decode_item arm_cccc_0111_____xxx1_table[] = { | ||
517 | /* Media instructions */ | ||
518 | |||
519 | /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */ | ||
520 | DECODE_REJECT (0x0ff000f0, 0x07f000f0), | ||
521 | |||
522 | /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */ | ||
523 | /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */ | ||
524 | DECODE_EMULATEX (0x0ff00090, 0x07400010, PROBES_MUL_ADD_LONG, | ||
525 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
526 | |||
527 | /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */ | ||
528 | /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */ | ||
529 | DECODE_OR (0x0ff0f090, 0x0700f010), | ||
530 | /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */ | ||
531 | DECODE_OR (0x0ff0f0d0, 0x0750f010), | ||
532 | /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */ | ||
533 | DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, PROBES_MUL_ADD, | ||
534 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
535 | |||
536 | /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */ | ||
537 | /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */ | ||
538 | DECODE_OR (0x0ff00090, 0x07000010), | ||
539 | /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */ | ||
540 | DECODE_OR (0x0ff000d0, 0x07500010), | ||
541 | /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */ | ||
542 | DECODE_EMULATEX (0x0ff000f0, 0x07800010, PROBES_MUL_ADD, | ||
543 | REGS(NOPC, NOPCX, NOPC, 0, NOPC)), | ||
544 | |||
545 | /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ | ||
546 | DECODE_EMULATEX (0x0ff000d0, 0x075000d0, PROBES_MUL_ADD, | ||
547 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
548 | |||
549 | /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */ | ||
550 | /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */ | ||
551 | DECODE_EMULATEX (0x0fa00070, 0x07a00050, PROBES_BITFIELD, | ||
552 | REGS(0, NOPC, 0, 0, NOPC)), | ||
553 | |||
554 | /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ | ||
555 | DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, PROBES_BITFIELD, | ||
556 | REGS(0, NOPC, 0, 0, 0)), | ||
557 | |||
558 | /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ | ||
559 | DECODE_EMULATEX (0x0fe00070, 0x07c00010, PROBES_BITFIELD, | ||
560 | REGS(0, NOPC, 0, 0, NOPCX)), | ||
561 | |||
562 | DECODE_END | ||
563 | }; | ||
564 | |||
565 | static const union decode_item arm_cccc_01xx_table[] = { | ||
566 | /* Load/store word and unsigned byte */ | ||
567 | |||
568 | /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */ | ||
569 | DECODE_REJECT (0x0c40f000, 0x0440f000), | ||
570 | |||
571 | /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */ | ||
572 | /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */ | ||
573 | /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */ | ||
574 | /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */ | ||
575 | DECODE_REJECT (0x0d200000, 0x04200000), | ||
576 | |||
577 | /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
578 | /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
579 | DECODE_EMULATEX (0x0e100000, 0x04000000, PROBES_STORE, | ||
580 | REGS(NOPCWB, ANY, 0, 0, 0)), | ||
581 | |||
582 | /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
583 | /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
584 | DECODE_EMULATEX (0x0e100000, 0x04100000, PROBES_LOAD, | ||
585 | REGS(NOPCWB, ANY, 0, 0, 0)), | ||
586 | |||
587 | /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
588 | /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
589 | DECODE_EMULATEX (0x0e100000, 0x06000000, PROBES_STORE, | ||
590 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | ||
591 | |||
592 | /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
593 | /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
594 | DECODE_EMULATEX (0x0e100000, 0x06100000, PROBES_LOAD, | ||
595 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | ||
596 | |||
597 | DECODE_END | ||
598 | }; | ||
599 | |||
600 | static const union decode_item arm_cccc_100x_table[] = { | ||
601 | /* Block data transfer instructions */ | ||
602 | |||
603 | /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
604 | /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
605 | DECODE_CUSTOM (0x0e400000, 0x08000000, PROBES_LDMSTM), | ||
606 | |||
607 | /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
608 | /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */ | ||
609 | /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */ | ||
610 | DECODE_END | ||
611 | }; | ||
612 | |||
613 | const union decode_item probes_decode_arm_table[] = { | ||
614 | /* | ||
615 | * Unconditional instructions | ||
616 | * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx | ||
617 | */ | ||
618 | DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table), | ||
619 | |||
620 | /* | ||
621 | * Miscellaneous instructions | ||
622 | * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx | ||
623 | */ | ||
624 | DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table), | ||
625 | |||
626 | /* | ||
627 | * Halfword multiply and multiply-accumulate | ||
628 | * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx | ||
629 | */ | ||
630 | DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table), | ||
631 | |||
632 | /* | ||
633 | * Multiply and multiply-accumulate | ||
634 | * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx | ||
635 | */ | ||
636 | DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table), | ||
637 | |||
638 | /* | ||
639 | * Synchronization primitives | ||
640 | * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx | ||
641 | */ | ||
642 | DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table), | ||
643 | |||
644 | /* | ||
645 | * Extra load/store instructions | ||
646 | * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx | ||
647 | */ | ||
648 | DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table), | ||
649 | |||
650 | /* | ||
651 | * Data-processing (register) | ||
652 | * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx | ||
653 | * Data-processing (register-shifted register) | ||
654 | * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx | ||
655 | */ | ||
656 | DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table), | ||
657 | |||
658 | /* | ||
659 | * Data-processing (immediate) | ||
660 | * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx | ||
661 | */ | ||
662 | DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table), | ||
663 | |||
664 | /* | ||
665 | * Media instructions | ||
666 | * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx | ||
667 | */ | ||
668 | DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table), | ||
669 | DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table), | ||
670 | |||
671 | /* | ||
672 | * Load/store word and unsigned byte | ||
673 | * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx | ||
674 | */ | ||
675 | DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table), | ||
676 | |||
677 | /* | ||
678 | * Block data transfer instructions | ||
679 | * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx | ||
680 | */ | ||
681 | DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table), | ||
682 | |||
683 | /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
684 | /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
685 | DECODE_SIMULATE (0x0e000000, 0x0a000000, PROBES_BRANCH), | ||
686 | |||
687 | /* | ||
688 | * Supervisor Call, and coprocessor instructions | ||
689 | */ | ||
690 | |||
691 | /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
692 | /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
693 | /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | ||
694 | /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | ||
695 | /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | ||
696 | /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | ||
697 | /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | ||
698 | /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
699 | DECODE_REJECT (0x0c000000, 0x0c000000), | ||
700 | |||
701 | DECODE_END | ||
702 | }; | ||
703 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE | ||
704 | EXPORT_SYMBOL_GPL(probes_decode_arm_table); | ||
705 | #endif | ||
706 | |||
707 | static void __kprobes arm_singlestep(probes_opcode_t insn, | ||
708 | struct arch_probes_insn *asi, struct pt_regs *regs) | ||
709 | { | ||
710 | regs->ARM_pc += 4; | ||
711 | asi->insn_handler(insn, asi, regs); | ||
712 | } | ||
713 | |||
714 | /* Return: | ||
715 | * INSN_REJECTED If instruction is one not allowed to kprobe, | ||
716 | * INSN_GOOD If instruction is supported and uses instruction slot, | ||
717 | * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. | ||
718 | * | ||
719 | * For instructions we don't want to kprobe (INSN_REJECTED return result): | ||
720 | * These are generally ones that modify the processor state making | ||
721 | * them "hard" to simulate such as switches processor modes or | ||
722 | * make accesses in alternate modes. Any of these could be simulated | ||
723 | * if the work was put into it, but low return considering they | ||
724 | * should also be very rare. | ||
725 | */ | ||
726 | enum probes_insn __kprobes | ||
727 | arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
728 | bool emulate, const union decode_action *actions) | ||
729 | { | ||
730 | asi->insn_singlestep = arm_singlestep; | ||
731 | asi->insn_check_cc = probes_condition_checks[insn>>28]; | ||
732 | return probes_decode_insn(insn, asi, probes_decode_arm_table, false, | ||
733 | emulate, actions); | ||
734 | } | ||
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h new file mode 100644 index 000000000000..ace6572f6e26 --- /dev/null +++ b/arch/arm/kernel/probes-arm.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes-arm.h | ||
3 | * | ||
4 | * Copyright 2013 Linaro Ltd. | ||
5 | * Written by: David A. Long | ||
6 | * | ||
7 | * The code contained herein is licensed under the GNU General Public | ||
8 | * License. You may obtain a copy of the GNU General Public License | ||
9 | * Version 2 or later at the following locations: | ||
10 | * | ||
11 | * http://www.opensource.org/licenses/gpl-license.html | ||
12 | * http://www.gnu.org/copyleft/gpl.html | ||
13 | */ | ||
14 | |||
15 | #ifndef _ARM_KERNEL_PROBES_ARM_H | ||
16 | #define _ARM_KERNEL_PROBES_ARM_H | ||
17 | |||
18 | enum probes_arm_action { | ||
19 | PROBES_EMULATE_NONE, | ||
20 | PROBES_SIMULATE_NOP, | ||
21 | PROBES_PRELOAD_IMM, | ||
22 | PROBES_PRELOAD_REG, | ||
23 | PROBES_BRANCH_IMM, | ||
24 | PROBES_BRANCH_REG, | ||
25 | PROBES_MRS, | ||
26 | PROBES_CLZ, | ||
27 | PROBES_SATURATING_ARITHMETIC, | ||
28 | PROBES_MUL1, | ||
29 | PROBES_MUL2, | ||
30 | PROBES_SWP, | ||
31 | PROBES_LDRSTRD, | ||
32 | PROBES_LOAD, | ||
33 | PROBES_STORE, | ||
34 | PROBES_LOAD_EXTRA, | ||
35 | PROBES_STORE_EXTRA, | ||
36 | PROBES_MOV_IP_SP, | ||
37 | PROBES_DATA_PROCESSING_REG, | ||
38 | PROBES_DATA_PROCESSING_IMM, | ||
39 | PROBES_MOV_HALFWORD, | ||
40 | PROBES_SEV, | ||
41 | PROBES_WFE, | ||
42 | PROBES_SATURATE, | ||
43 | PROBES_REV, | ||
44 | PROBES_MMI, | ||
45 | PROBES_PACK, | ||
46 | PROBES_EXTEND, | ||
47 | PROBES_EXTEND_ADD, | ||
48 | PROBES_MUL_ADD_LONG, | ||
49 | PROBES_MUL_ADD, | ||
50 | PROBES_BITFIELD, | ||
51 | PROBES_BRANCH, | ||
52 | PROBES_LDMSTM, | ||
53 | NUM_PROBES_ARM_ACTIONS | ||
54 | }; | ||
55 | |||
56 | void __kprobes simulate_bbl(probes_opcode_t opcode, | ||
57 | struct arch_probes_insn *asi, struct pt_regs *regs); | ||
58 | void __kprobes simulate_blx1(probes_opcode_t opcode, | ||
59 | struct arch_probes_insn *asi, struct pt_regs *regs); | ||
60 | void __kprobes simulate_blx2bx(probes_opcode_t opcode, | ||
61 | struct arch_probes_insn *asi, struct pt_regs *regs); | ||
62 | void __kprobes simulate_mrs(probes_opcode_t opcode, | ||
63 | struct arch_probes_insn *asi, struct pt_regs *regs); | ||
64 | void __kprobes simulate_mov_ipsp(probes_opcode_t opcode, | ||
65 | struct arch_probes_insn *asi, struct pt_regs *regs); | ||
66 | |||
67 | extern const union decode_item probes_decode_arm_table[]; | ||
68 | |||
69 | enum probes_insn arm_probes_decode_insn(probes_opcode_t, | ||
70 | struct arch_probes_insn *, bool emulate, | ||
71 | const union decode_action *actions); | ||
72 | |||
73 | #endif | ||
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c new file mode 100644 index 000000000000..4131351e812f --- /dev/null +++ b/arch/arm/kernel/probes-thumb.c | |||
@@ -0,0 +1,882 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes-thumb.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | ||
5 | * | ||
6 | * 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 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/stddef.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | |||
15 | #include "probes.h" | ||
16 | #include "probes-thumb.h" | ||
17 | |||
18 | |||
19 | static const union decode_item t32_table_1110_100x_x0xx[] = { | ||
20 | /* Load/store multiple instructions */ | ||
21 | |||
22 | /* Rn is PC 1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */ | ||
23 | DECODE_REJECT (0xfe4f0000, 0xe80f0000), | ||
24 | |||
25 | /* SRS 1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */ | ||
26 | /* RFE 1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */ | ||
27 | DECODE_REJECT (0xffc00000, 0xe8000000), | ||
28 | /* SRS 1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */ | ||
29 | /* RFE 1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */ | ||
30 | DECODE_REJECT (0xffc00000, 0xe9800000), | ||
31 | |||
32 | /* STM Rn, {...pc} 1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */ | ||
33 | DECODE_REJECT (0xfe508000, 0xe8008000), | ||
34 | /* LDM Rn, {...lr,pc} 1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */ | ||
35 | DECODE_REJECT (0xfe50c000, 0xe810c000), | ||
36 | /* LDM/STM Rn, {...sp} 1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */ | ||
37 | DECODE_REJECT (0xfe402000, 0xe8002000), | ||
38 | |||
39 | /* STMIA 1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */ | ||
40 | /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */ | ||
41 | /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */ | ||
42 | /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */ | ||
43 | DECODE_CUSTOM (0xfe400000, 0xe8000000, PROBES_T32_LDMSTM), | ||
44 | |||
45 | DECODE_END | ||
46 | }; | ||
47 | |||
48 | static const union decode_item t32_table_1110_100x_x1xx[] = { | ||
49 | /* Load/store dual, load/store exclusive, table branch */ | ||
50 | |||
51 | /* STRD (immediate) 1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */ | ||
52 | /* LDRD (immediate) 1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */ | ||
53 | DECODE_OR (0xff600000, 0xe8600000), | ||
54 | /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
55 | /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
56 | DECODE_EMULATEX (0xff400000, 0xe9400000, PROBES_T32_LDRDSTRD, | ||
57 | REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)), | ||
58 | |||
59 | /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */ | ||
60 | /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */ | ||
61 | DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, PROBES_T32_TABLE_BRANCH, | ||
62 | REGS(NOSP, 0, 0, 0, NOSPPC)), | ||
63 | |||
64 | /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
65 | /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
66 | /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */ | ||
67 | /* STREXH 1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */ | ||
68 | /* STREXD 1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */ | ||
69 | /* LDREXB 1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */ | ||
70 | /* LDREXH 1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */ | ||
71 | /* LDREXD 1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */ | ||
72 | /* And unallocated instructions... */ | ||
73 | DECODE_END | ||
74 | }; | ||
75 | |||
76 | static const union decode_item t32_table_1110_101x[] = { | ||
77 | /* Data-processing (shifted register) */ | ||
78 | |||
79 | /* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */ | ||
80 | /* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */ | ||
81 | DECODE_EMULATEX (0xff700f00, 0xea100f00, PROBES_T32_TST, | ||
82 | REGS(NOSPPC, 0, 0, 0, NOSPPC)), | ||
83 | |||
84 | /* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */ | ||
85 | DECODE_OR (0xfff00f00, 0xeb100f00), | ||
86 | /* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */ | ||
87 | DECODE_EMULATEX (0xfff00f00, 0xebb00f00, PROBES_T32_TST, | ||
88 | REGS(NOPC, 0, 0, 0, NOSPPC)), | ||
89 | |||
90 | /* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */ | ||
91 | /* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */ | ||
92 | DECODE_EMULATEX (0xffcf0000, 0xea4f0000, PROBES_T32_MOV, | ||
93 | REGS(0, 0, NOSPPC, 0, NOSPPC)), | ||
94 | |||
95 | /* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */ | ||
96 | /* ??? 1110 1010 111x xxxx xxxx xxxx xxxx xxxx */ | ||
97 | DECODE_REJECT (0xffa00000, 0xeaa00000), | ||
98 | /* ??? 1110 1011 001x xxxx xxxx xxxx xxxx xxxx */ | ||
99 | DECODE_REJECT (0xffe00000, 0xeb200000), | ||
100 | /* ??? 1110 1011 100x xxxx xxxx xxxx xxxx xxxx */ | ||
101 | DECODE_REJECT (0xffe00000, 0xeb800000), | ||
102 | /* ??? 1110 1011 111x xxxx xxxx xxxx xxxx xxxx */ | ||
103 | DECODE_REJECT (0xffe00000, 0xebe00000), | ||
104 | |||
105 | /* ADD/SUB SP, SP, Rm, LSL #0..3 */ | ||
106 | /* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */ | ||
107 | DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, PROBES_T32_ADDSUB, | ||
108 | REGS(SP, 0, SP, 0, NOSPPC)), | ||
109 | |||
110 | /* ADD/SUB SP, SP, Rm, shift */ | ||
111 | /* 1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */ | ||
112 | DECODE_REJECT (0xff4f0f00, 0xeb0d0d00), | ||
113 | |||
114 | /* ADD/SUB Rd, SP, Rm, shift */ | ||
115 | /* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */ | ||
116 | DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, PROBES_T32_ADDSUB, | ||
117 | REGS(SP, 0, NOPC, 0, NOSPPC)), | ||
118 | |||
119 | /* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */ | ||
120 | /* BIC 1110 1010 001x xxxx xxxx xxxx xxxx xxxx */ | ||
121 | /* ORR 1110 1010 010x xxxx xxxx xxxx xxxx xxxx */ | ||
122 | /* ORN 1110 1010 011x xxxx xxxx xxxx xxxx xxxx */ | ||
123 | /* EOR 1110 1010 100x xxxx xxxx xxxx xxxx xxxx */ | ||
124 | /* PKH 1110 1010 110x xxxx xxxx xxxx xxxx xxxx */ | ||
125 | /* ADD 1110 1011 000x xxxx xxxx xxxx xxxx xxxx */ | ||
126 | /* ADC 1110 1011 010x xxxx xxxx xxxx xxxx xxxx */ | ||
127 | /* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */ | ||
128 | /* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */ | ||
129 | /* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */ | ||
130 | DECODE_EMULATEX (0xfe000000, 0xea000000, PROBES_T32_LOGICAL, | ||
131 | REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), | ||
132 | |||
133 | DECODE_END | ||
134 | }; | ||
135 | |||
136 | static const union decode_item t32_table_1111_0x0x___0[] = { | ||
137 | /* Data-processing (modified immediate) */ | ||
138 | |||
139 | /* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */ | ||
140 | /* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */ | ||
141 | DECODE_EMULATEX (0xfb708f00, 0xf0100f00, PROBES_T32_TST, | ||
142 | REGS(NOSPPC, 0, 0, 0, 0)), | ||
143 | |||
144 | /* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */ | ||
145 | DECODE_OR (0xfbf08f00, 0xf1100f00), | ||
146 | /* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */ | ||
147 | DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, PROBES_T32_CMP, | ||
148 | REGS(NOPC, 0, 0, 0, 0)), | ||
149 | |||
150 | /* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */ | ||
151 | /* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */ | ||
152 | DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, PROBES_T32_MOV, | ||
153 | REGS(0, 0, NOSPPC, 0, 0)), | ||
154 | |||
155 | /* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */ | ||
156 | DECODE_REJECT (0xfbe08000, 0xf0a00000), | ||
157 | /* ??? 1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */ | ||
158 | /* ??? 1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */ | ||
159 | DECODE_REJECT (0xfbc08000, 0xf0c00000), | ||
160 | /* ??? 1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */ | ||
161 | DECODE_REJECT (0xfbe08000, 0xf1200000), | ||
162 | /* ??? 1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */ | ||
163 | DECODE_REJECT (0xfbe08000, 0xf1800000), | ||
164 | /* ??? 1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */ | ||
165 | DECODE_REJECT (0xfbe08000, 0xf1e00000), | ||
166 | |||
167 | /* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */ | ||
168 | /* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */ | ||
169 | DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, PROBES_T32_ADDSUB, | ||
170 | REGS(SP, 0, NOPC, 0, 0)), | ||
171 | |||
172 | /* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */ | ||
173 | /* BIC 1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */ | ||
174 | /* ORR 1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */ | ||
175 | /* ORN 1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */ | ||
176 | /* EOR 1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */ | ||
177 | /* ADD 1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */ | ||
178 | /* ADC 1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */ | ||
179 | /* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */ | ||
180 | /* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */ | ||
181 | /* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */ | ||
182 | DECODE_EMULATEX (0xfa008000, 0xf0000000, PROBES_T32_LOGICAL, | ||
183 | REGS(NOSPPC, 0, NOSPPC, 0, 0)), | ||
184 | |||
185 | DECODE_END | ||
186 | }; | ||
187 | |||
188 | static const union decode_item t32_table_1111_0x1x___0[] = { | ||
189 | /* Data-processing (plain binary immediate) */ | ||
190 | |||
191 | /* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */ | ||
192 | DECODE_OR (0xfbff8000, 0xf20f0000), | ||
193 | /* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */ | ||
194 | DECODE_EMULATEX (0xfbff8000, 0xf2af0000, PROBES_T32_ADDWSUBW_PC, | ||
195 | REGS(PC, 0, NOSPPC, 0, 0)), | ||
196 | |||
197 | /* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */ | ||
198 | DECODE_OR (0xfbff8f00, 0xf20d0d00), | ||
199 | /* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */ | ||
200 | DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, PROBES_T32_ADDWSUBW, | ||
201 | REGS(SP, 0, SP, 0, 0)), | ||
202 | |||
203 | /* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */ | ||
204 | DECODE_OR (0xfbf08000, 0xf2000000), | ||
205 | /* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */ | ||
206 | DECODE_EMULATEX (0xfbf08000, 0xf2a00000, PROBES_T32_ADDWSUBW, | ||
207 | REGS(NOPCX, 0, NOSPPC, 0, 0)), | ||
208 | |||
209 | /* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */ | ||
210 | /* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */ | ||
211 | DECODE_EMULATEX (0xfb708000, 0xf2400000, PROBES_T32_MOVW, | ||
212 | REGS(0, 0, NOSPPC, 0, 0)), | ||
213 | |||
214 | /* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */ | ||
215 | /* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */ | ||
216 | /* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */ | ||
217 | /* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */ | ||
218 | DECODE_EMULATEX (0xfb508000, 0xf3000000, PROBES_T32_SAT, | ||
219 | REGS(NOSPPC, 0, NOSPPC, 0, 0)), | ||
220 | |||
221 | /* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */ | ||
222 | /* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */ | ||
223 | DECODE_EMULATEX (0xfb708000, 0xf3400000, PROBES_T32_BITFIELD, | ||
224 | REGS(NOSPPC, 0, NOSPPC, 0, 0)), | ||
225 | |||
226 | /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */ | ||
227 | DECODE_EMULATEX (0xfbff8000, 0xf36f0000, PROBES_T32_BITFIELD, | ||
228 | REGS(0, 0, NOSPPC, 0, 0)), | ||
229 | |||
230 | /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */ | ||
231 | DECODE_EMULATEX (0xfbf08000, 0xf3600000, PROBES_T32_BITFIELD, | ||
232 | REGS(NOSPPCX, 0, NOSPPC, 0, 0)), | ||
233 | |||
234 | DECODE_END | ||
235 | }; | ||
236 | |||
237 | static const union decode_item t32_table_1111_0xxx___1[] = { | ||
238 | /* Branches and miscellaneous control */ | ||
239 | |||
240 | /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */ | ||
241 | DECODE_OR (0xfff0d7ff, 0xf3a08001), | ||
242 | /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */ | ||
243 | DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, PROBES_T32_SEV), | ||
244 | /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */ | ||
245 | /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */ | ||
246 | /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */ | ||
247 | DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, PROBES_T32_WFE), | ||
248 | |||
249 | /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */ | ||
250 | DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, PROBES_T32_MRS, | ||
251 | REGS(0, 0, NOSPPC, 0, 0)), | ||
252 | |||
253 | /* | ||
254 | * Unsupported instructions | ||
255 | * 1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx | ||
256 | * | ||
257 | * MSR 1111 0011 100x xxxx 10x0 xxxx xxxx xxxx | ||
258 | * DBG hint 1111 0011 1010 xxxx 10x0 x000 1111 xxxx | ||
259 | * Unallocated hints 1111 0011 1010 xxxx 10x0 x000 xxxx xxxx | ||
260 | * CPS 1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx | ||
261 | * CLREX/DSB/DMB/ISB 1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx | ||
262 | * BXJ 1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx | ||
263 | * SUBS PC,LR,#<imm8> 1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx | ||
264 | * MRS Rd, SPSR 1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx | ||
265 | * SMC 1111 0111 1111 xxxx 1000 xxxx xxxx xxxx | ||
266 | * UNDEFINED 1111 0111 1111 xxxx 1010 xxxx xxxx xxxx | ||
267 | * ??? 1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx | ||
268 | */ | ||
269 | DECODE_REJECT (0xfb80d000, 0xf3808000), | ||
270 | |||
271 | /* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */ | ||
272 | DECODE_CUSTOM (0xf800d000, 0xf0008000, PROBES_T32_BRANCH_COND), | ||
273 | |||
274 | /* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */ | ||
275 | DECODE_OR (0xf800d001, 0xf000c000), | ||
276 | /* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */ | ||
277 | /* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */ | ||
278 | DECODE_SIMULATE (0xf8009000, 0xf0009000, PROBES_T32_BRANCH), | ||
279 | |||
280 | DECODE_END | ||
281 | }; | ||
282 | |||
283 | static const union decode_item t32_table_1111_100x_x0x1__1111[] = { | ||
284 | /* Memory hints */ | ||
285 | |||
286 | /* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */ | ||
287 | /* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */ | ||
288 | DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, PROBES_T32_PLDI), | ||
289 | |||
290 | /* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */ | ||
291 | DECODE_OR (0xffd0f000, 0xf890f000), | ||
292 | /* PLD{W} (immediate) 1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */ | ||
293 | DECODE_OR (0xffd0ff00, 0xf810fc00), | ||
294 | /* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */ | ||
295 | DECODE_OR (0xfff0f000, 0xf990f000), | ||
296 | /* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */ | ||
297 | DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, PROBES_T32_PLDI, | ||
298 | REGS(NOPCX, 0, 0, 0, 0)), | ||
299 | |||
300 | /* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */ | ||
301 | DECODE_OR (0xffd0ffc0, 0xf810f000), | ||
302 | /* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */ | ||
303 | DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, PROBES_T32_PLDI, | ||
304 | REGS(NOPCX, 0, 0, 0, NOSPPC)), | ||
305 | |||
306 | /* Other unallocated instructions... */ | ||
307 | DECODE_END | ||
308 | }; | ||
309 | |||
310 | static const union decode_item t32_table_1111_100x[] = { | ||
311 | /* Store/Load single data item */ | ||
312 | |||
313 | /* ??? 1111 100x x11x xxxx xxxx xxxx xxxx xxxx */ | ||
314 | DECODE_REJECT (0xfe600000, 0xf8600000), | ||
315 | |||
316 | /* ??? 1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
317 | DECODE_REJECT (0xfff00000, 0xf9500000), | ||
318 | |||
319 | /* ??? 1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */ | ||
320 | DECODE_REJECT (0xfe800d00, 0xf8000800), | ||
321 | |||
322 | /* STRBT 1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */ | ||
323 | /* STRHT 1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */ | ||
324 | /* STRT 1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */ | ||
325 | /* LDRBT 1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */ | ||
326 | /* LDRSBT 1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */ | ||
327 | /* LDRHT 1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */ | ||
328 | /* LDRSHT 1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */ | ||
329 | /* LDRT 1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */ | ||
330 | DECODE_REJECT (0xfe800f00, 0xf8000e00), | ||
331 | |||
332 | /* STR{,B,H} Rn,[PC...] 1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */ | ||
333 | DECODE_REJECT (0xff1f0000, 0xf80f0000), | ||
334 | |||
335 | /* STR{,B,H} PC,[Rn...] 1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */ | ||
336 | DECODE_REJECT (0xff10f000, 0xf800f000), | ||
337 | |||
338 | /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */ | ||
339 | DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, PROBES_T32_LDR_LIT, | ||
340 | REGS(PC, ANY, 0, 0, 0)), | ||
341 | |||
342 | /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */ | ||
343 | /* LDR (immediate) 1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */ | ||
344 | DECODE_OR (0xffe00800, 0xf8400800), | ||
345 | /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */ | ||
346 | /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */ | ||
347 | DECODE_EMULATEX (0xffe00000, 0xf8c00000, PROBES_T32_LDRSTR, | ||
348 | REGS(NOPCX, ANY, 0, 0, 0)), | ||
349 | |||
350 | /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ | ||
351 | /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */ | ||
352 | DECODE_EMULATEX (0xffe00fc0, 0xf8400000, PROBES_T32_LDRSTR, | ||
353 | REGS(NOPCX, ANY, 0, 0, NOSPPC)), | ||
354 | |||
355 | /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */ | ||
356 | /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */ | ||
357 | /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */ | ||
358 | /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */ | ||
359 | DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, PROBES_T32_LDR_LIT, | ||
360 | REGS(PC, NOSPPCX, 0, 0, 0)), | ||
361 | |||
362 | /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */ | ||
363 | /* STRH (immediate) 1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */ | ||
364 | /* LDRB (immediate) 1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */ | ||
365 | /* LDRSB (immediate) 1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */ | ||
366 | /* LDRH (immediate) 1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */ | ||
367 | /* LDRSH (immediate) 1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */ | ||
368 | DECODE_OR (0xfec00800, 0xf8000800), | ||
369 | /* STRB (immediate) 1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */ | ||
370 | /* STRH (immediate) 1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */ | ||
371 | /* LDRB (immediate) 1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */ | ||
372 | /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */ | ||
373 | /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */ | ||
374 | /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */ | ||
375 | DECODE_EMULATEX (0xfec00000, 0xf8800000, PROBES_T32_LDRSTR, | ||
376 | REGS(NOPCX, NOSPPCX, 0, 0, 0)), | ||
377 | |||
378 | /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ | ||
379 | /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */ | ||
380 | /* LDRB (register) 1111 1000 0001 xxxx xxxx 0000 00xx xxxx */ | ||
381 | /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */ | ||
382 | /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */ | ||
383 | /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */ | ||
384 | DECODE_EMULATEX (0xfe800fc0, 0xf8000000, PROBES_T32_LDRSTR, | ||
385 | REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)), | ||
386 | |||
387 | /* Other unallocated instructions... */ | ||
388 | DECODE_END | ||
389 | }; | ||
390 | |||
391 | static const union decode_item t32_table_1111_1010___1111[] = { | ||
392 | /* Data-processing (register) */ | ||
393 | |||
394 | /* ??? 1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */ | ||
395 | DECODE_REJECT (0xffe0f080, 0xfa60f080), | ||
396 | |||
397 | /* SXTH 1111 1010 0000 1111 1111 xxxx 1xxx xxxx */ | ||
398 | /* UXTH 1111 1010 0001 1111 1111 xxxx 1xxx xxxx */ | ||
399 | /* SXTB16 1111 1010 0010 1111 1111 xxxx 1xxx xxxx */ | ||
400 | /* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */ | ||
401 | /* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */ | ||
402 | /* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */ | ||
403 | DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, PROBES_T32_SIGN_EXTEND, | ||
404 | REGS(0, 0, NOSPPC, 0, NOSPPC)), | ||
405 | |||
406 | |||
407 | /* ??? 1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */ | ||
408 | DECODE_REJECT (0xff80f0b0, 0xfa80f030), | ||
409 | /* ??? 1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */ | ||
410 | DECODE_REJECT (0xffb0f080, 0xfab0f000), | ||
411 | |||
412 | /* SADD16 1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */ | ||
413 | /* SASX 1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */ | ||
414 | /* SSAX 1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */ | ||
415 | /* SSUB16 1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */ | ||
416 | /* SADD8 1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */ | ||
417 | /* SSUB8 1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */ | ||
418 | |||
419 | /* QADD16 1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */ | ||
420 | /* QASX 1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */ | ||
421 | /* QSAX 1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */ | ||
422 | /* QSUB16 1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */ | ||
423 | /* QADD8 1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */ | ||
424 | /* QSUB8 1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */ | ||
425 | |||
426 | /* SHADD16 1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */ | ||
427 | /* SHASX 1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */ | ||
428 | /* SHSAX 1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */ | ||
429 | /* SHSUB16 1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */ | ||
430 | /* SHADD8 1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */ | ||
431 | /* SHSUB8 1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */ | ||
432 | |||
433 | /* UADD16 1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */ | ||
434 | /* UASX 1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */ | ||
435 | /* USAX 1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */ | ||
436 | /* USUB16 1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */ | ||
437 | /* UADD8 1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */ | ||
438 | /* USUB8 1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */ | ||
439 | |||
440 | /* UQADD16 1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */ | ||
441 | /* UQASX 1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */ | ||
442 | /* UQSAX 1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */ | ||
443 | /* UQSUB16 1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */ | ||
444 | /* UQADD8 1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */ | ||
445 | /* UQSUB8 1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */ | ||
446 | |||
447 | /* UHADD16 1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */ | ||
448 | /* UHASX 1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */ | ||
449 | /* UHSAX 1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */ | ||
450 | /* UHSUB16 1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */ | ||
451 | /* UHADD8 1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */ | ||
452 | /* UHSUB8 1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */ | ||
453 | DECODE_OR (0xff80f080, 0xfa80f000), | ||
454 | |||
455 | /* SXTAH 1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */ | ||
456 | /* UXTAH 1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */ | ||
457 | /* SXTAB16 1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */ | ||
458 | /* UXTAB16 1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */ | ||
459 | /* SXTAB 1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */ | ||
460 | /* UXTAB 1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */ | ||
461 | DECODE_OR (0xff80f080, 0xfa00f080), | ||
462 | |||
463 | /* QADD 1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */ | ||
464 | /* QDADD 1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */ | ||
465 | /* QSUB 1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */ | ||
466 | /* QDSUB 1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */ | ||
467 | DECODE_OR (0xfff0f0c0, 0xfa80f080), | ||
468 | |||
469 | /* SEL 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */ | ||
470 | DECODE_OR (0xfff0f0f0, 0xfaa0f080), | ||
471 | |||
472 | /* LSL 1111 1010 000x xxxx 1111 xxxx 0000 xxxx */ | ||
473 | /* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */ | ||
474 | /* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */ | ||
475 | /* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */ | ||
476 | DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, PROBES_T32_MEDIA, | ||
477 | REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), | ||
478 | |||
479 | /* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */ | ||
480 | DECODE_OR (0xfff0f0f0, 0xfab0f080), | ||
481 | |||
482 | /* REV 1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */ | ||
483 | /* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */ | ||
484 | /* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */ | ||
485 | /* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */ | ||
486 | DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, PROBES_T32_REVERSE, | ||
487 | REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)), | ||
488 | |||
489 | /* Other unallocated instructions... */ | ||
490 | DECODE_END | ||
491 | }; | ||
492 | |||
493 | static const union decode_item t32_table_1111_1011_0[] = { | ||
494 | /* Multiply, multiply accumulate, and absolute difference */ | ||
495 | |||
496 | /* ??? 1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */ | ||
497 | DECODE_REJECT (0xfff0f0f0, 0xfb00f010), | ||
498 | /* ??? 1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */ | ||
499 | DECODE_REJECT (0xfff0f0f0, 0xfb70f010), | ||
500 | |||
501 | /* SMULxy 1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */ | ||
502 | DECODE_OR (0xfff0f0c0, 0xfb10f000), | ||
503 | /* MUL 1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */ | ||
504 | /* SMUAD{X} 1111 1011 0010 xxxx 1111 xxxx 000x xxxx */ | ||
505 | /* SMULWy 1111 1011 0011 xxxx 1111 xxxx 000x xxxx */ | ||
506 | /* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */ | ||
507 | /* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */ | ||
508 | /* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */ | ||
509 | DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, PROBES_T32_MUL_ADD, | ||
510 | REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), | ||
511 | |||
512 | /* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */ | ||
513 | DECODE_REJECT (0xfff000f0, 0xfb700010), | ||
514 | |||
515 | /* SMLAxy 1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */ | ||
516 | DECODE_OR (0xfff000c0, 0xfb100000), | ||
517 | /* MLA 1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */ | ||
518 | /* MLS 1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */ | ||
519 | /* SMLAD{X} 1111 1011 0010 xxxx xxxx xxxx 000x xxxx */ | ||
520 | /* SMLAWy 1111 1011 0011 xxxx xxxx xxxx 000x xxxx */ | ||
521 | /* SMLSD{X} 1111 1011 0100 xxxx xxxx xxxx 000x xxxx */ | ||
522 | /* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */ | ||
523 | /* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */ | ||
524 | /* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */ | ||
525 | DECODE_EMULATEX (0xff8000c0, 0xfb000000, PROBES_T32_MUL_ADD2, | ||
526 | REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)), | ||
527 | |||
528 | /* Other unallocated instructions... */ | ||
529 | DECODE_END | ||
530 | }; | ||
531 | |||
532 | static const union decode_item t32_table_1111_1011_1[] = { | ||
533 | /* Long multiply, long multiply accumulate, and divide */ | ||
534 | |||
535 | /* UMAAL 1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */ | ||
536 | DECODE_OR (0xfff000f0, 0xfbe00060), | ||
537 | /* SMLALxy 1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */ | ||
538 | DECODE_OR (0xfff000c0, 0xfbc00080), | ||
539 | /* SMLALD{X} 1111 1011 1100 xxxx xxxx xxxx 110x xxxx */ | ||
540 | /* SMLSLD{X} 1111 1011 1101 xxxx xxxx xxxx 110x xxxx */ | ||
541 | DECODE_OR (0xffe000e0, 0xfbc000c0), | ||
542 | /* SMULL 1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */ | ||
543 | /* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */ | ||
544 | /* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */ | ||
545 | /* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */ | ||
546 | DECODE_EMULATEX (0xff9000f0, 0xfb800000, PROBES_T32_MUL_ADD_LONG, | ||
547 | REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)), | ||
548 | |||
549 | /* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */ | ||
550 | /* UDIV 1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */ | ||
551 | /* Other unallocated instructions... */ | ||
552 | DECODE_END | ||
553 | }; | ||
554 | |||
555 | const union decode_item probes_decode_thumb32_table[] = { | ||
556 | |||
557 | /* | ||
558 | * Load/store multiple instructions | ||
559 | * 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx | ||
560 | */ | ||
561 | DECODE_TABLE (0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx), | ||
562 | |||
563 | /* | ||
564 | * Load/store dual, load/store exclusive, table branch | ||
565 | * 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx | ||
566 | */ | ||
567 | DECODE_TABLE (0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx), | ||
568 | |||
569 | /* | ||
570 | * Data-processing (shifted register) | ||
571 | * 1110 101x xxxx xxxx xxxx xxxx xxxx xxxx | ||
572 | */ | ||
573 | DECODE_TABLE (0xfe000000, 0xea000000, t32_table_1110_101x), | ||
574 | |||
575 | /* | ||
576 | * Coprocessor instructions | ||
577 | * 1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx | ||
578 | */ | ||
579 | DECODE_REJECT (0xfc000000, 0xec000000), | ||
580 | |||
581 | /* | ||
582 | * Data-processing (modified immediate) | ||
583 | * 1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx | ||
584 | */ | ||
585 | DECODE_TABLE (0xfa008000, 0xf0000000, t32_table_1111_0x0x___0), | ||
586 | |||
587 | /* | ||
588 | * Data-processing (plain binary immediate) | ||
589 | * 1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx | ||
590 | */ | ||
591 | DECODE_TABLE (0xfa008000, 0xf2000000, t32_table_1111_0x1x___0), | ||
592 | |||
593 | /* | ||
594 | * Branches and miscellaneous control | ||
595 | * 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx | ||
596 | */ | ||
597 | DECODE_TABLE (0xf8008000, 0xf0008000, t32_table_1111_0xxx___1), | ||
598 | |||
599 | /* | ||
600 | * Advanced SIMD element or structure load/store instructions | ||
601 | * 1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx | ||
602 | */ | ||
603 | DECODE_REJECT (0xff100000, 0xf9000000), | ||
604 | |||
605 | /* | ||
606 | * Memory hints | ||
607 | * 1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx | ||
608 | */ | ||
609 | DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111), | ||
610 | |||
611 | /* | ||
612 | * Store single data item | ||
613 | * 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx | ||
614 | * Load single data items | ||
615 | * 1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx | ||
616 | */ | ||
617 | DECODE_TABLE (0xfe000000, 0xf8000000, t32_table_1111_100x), | ||
618 | |||
619 | /* | ||
620 | * Data-processing (register) | ||
621 | * 1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx | ||
622 | */ | ||
623 | DECODE_TABLE (0xff00f000, 0xfa00f000, t32_table_1111_1010___1111), | ||
624 | |||
625 | /* | ||
626 | * Multiply, multiply accumulate, and absolute difference | ||
627 | * 1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx | ||
628 | */ | ||
629 | DECODE_TABLE (0xff800000, 0xfb000000, t32_table_1111_1011_0), | ||
630 | |||
631 | /* | ||
632 | * Long multiply, long multiply accumulate, and divide | ||
633 | * 1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx | ||
634 | */ | ||
635 | DECODE_TABLE (0xff800000, 0xfb800000, t32_table_1111_1011_1), | ||
636 | |||
637 | /* | ||
638 | * Coprocessor instructions | ||
639 | * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx | ||
640 | */ | ||
641 | DECODE_END | ||
642 | }; | ||
643 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE | ||
644 | EXPORT_SYMBOL_GPL(probes_decode_thumb32_table); | ||
645 | #endif | ||
646 | |||
647 | static const union decode_item t16_table_1011[] = { | ||
648 | /* Miscellaneous 16-bit instructions */ | ||
649 | |||
650 | /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */ | ||
651 | /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */ | ||
652 | DECODE_SIMULATE (0xff00, 0xb000, PROBES_T16_ADD_SP), | ||
653 | |||
654 | /* CBZ 1011 00x1 xxxx xxxx */ | ||
655 | /* CBNZ 1011 10x1 xxxx xxxx */ | ||
656 | DECODE_SIMULATE (0xf500, 0xb100, PROBES_T16_CBZ), | ||
657 | |||
658 | /* SXTH 1011 0010 00xx xxxx */ | ||
659 | /* SXTB 1011 0010 01xx xxxx */ | ||
660 | /* UXTH 1011 0010 10xx xxxx */ | ||
661 | /* UXTB 1011 0010 11xx xxxx */ | ||
662 | /* REV 1011 1010 00xx xxxx */ | ||
663 | /* REV16 1011 1010 01xx xxxx */ | ||
664 | /* ??? 1011 1010 10xx xxxx */ | ||
665 | /* REVSH 1011 1010 11xx xxxx */ | ||
666 | DECODE_REJECT (0xffc0, 0xba80), | ||
667 | DECODE_EMULATE (0xf500, 0xb000, PROBES_T16_SIGN_EXTEND), | ||
668 | |||
669 | /* PUSH 1011 010x xxxx xxxx */ | ||
670 | DECODE_CUSTOM (0xfe00, 0xb400, PROBES_T16_PUSH), | ||
671 | /* POP 1011 110x xxxx xxxx */ | ||
672 | DECODE_CUSTOM (0xfe00, 0xbc00, PROBES_T16_POP), | ||
673 | |||
674 | /* | ||
675 | * If-Then, and hints | ||
676 | * 1011 1111 xxxx xxxx | ||
677 | */ | ||
678 | |||
679 | /* YIELD 1011 1111 0001 0000 */ | ||
680 | DECODE_OR (0xffff, 0xbf10), | ||
681 | /* SEV 1011 1111 0100 0000 */ | ||
682 | DECODE_EMULATE (0xffff, 0xbf40, PROBES_T16_SEV), | ||
683 | /* NOP 1011 1111 0000 0000 */ | ||
684 | /* WFE 1011 1111 0010 0000 */ | ||
685 | /* WFI 1011 1111 0011 0000 */ | ||
686 | DECODE_SIMULATE (0xffcf, 0xbf00, PROBES_T16_WFE), | ||
687 | /* Unassigned hints 1011 1111 xxxx 0000 */ | ||
688 | DECODE_REJECT (0xff0f, 0xbf00), | ||
689 | /* IT 1011 1111 xxxx xxxx */ | ||
690 | DECODE_CUSTOM (0xff00, 0xbf00, PROBES_T16_IT), | ||
691 | |||
692 | /* SETEND 1011 0110 010x xxxx */ | ||
693 | /* CPS 1011 0110 011x xxxx */ | ||
694 | /* BKPT 1011 1110 xxxx xxxx */ | ||
695 | /* And unallocated instructions... */ | ||
696 | DECODE_END | ||
697 | }; | ||
698 | |||
699 | const union decode_item probes_decode_thumb16_table[] = { | ||
700 | |||
701 | /* | ||
702 | * Shift (immediate), add, subtract, move, and compare | ||
703 | * 00xx xxxx xxxx xxxx | ||
704 | */ | ||
705 | |||
706 | /* CMP (immediate) 0010 1xxx xxxx xxxx */ | ||
707 | DECODE_EMULATE (0xf800, 0x2800, PROBES_T16_CMP), | ||
708 | |||
709 | /* ADD (register) 0001 100x xxxx xxxx */ | ||
710 | /* SUB (register) 0001 101x xxxx xxxx */ | ||
711 | /* LSL (immediate) 0000 0xxx xxxx xxxx */ | ||
712 | /* LSR (immediate) 0000 1xxx xxxx xxxx */ | ||
713 | /* ASR (immediate) 0001 0xxx xxxx xxxx */ | ||
714 | /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */ | ||
715 | /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */ | ||
716 | /* MOV (immediate) 0010 0xxx xxxx xxxx */ | ||
717 | /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */ | ||
718 | /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */ | ||
719 | DECODE_EMULATE (0xc000, 0x0000, PROBES_T16_ADDSUB), | ||
720 | |||
721 | /* | ||
722 | * 16-bit Thumb data-processing instructions | ||
723 | * 0100 00xx xxxx xxxx | ||
724 | */ | ||
725 | |||
726 | /* TST (register) 0100 0010 00xx xxxx */ | ||
727 | DECODE_EMULATE (0xffc0, 0x4200, PROBES_T16_CMP), | ||
728 | /* CMP (register) 0100 0010 10xx xxxx */ | ||
729 | /* CMN (register) 0100 0010 11xx xxxx */ | ||
730 | DECODE_EMULATE (0xff80, 0x4280, PROBES_T16_CMP), | ||
731 | /* AND (register) 0100 0000 00xx xxxx */ | ||
732 | /* EOR (register) 0100 0000 01xx xxxx */ | ||
733 | /* LSL (register) 0100 0000 10xx xxxx */ | ||
734 | /* LSR (register) 0100 0000 11xx xxxx */ | ||
735 | /* ASR (register) 0100 0001 00xx xxxx */ | ||
736 | /* ADC (register) 0100 0001 01xx xxxx */ | ||
737 | /* SBC (register) 0100 0001 10xx xxxx */ | ||
738 | /* ROR (register) 0100 0001 11xx xxxx */ | ||
739 | /* RSB (immediate) 0100 0010 01xx xxxx */ | ||
740 | /* ORR (register) 0100 0011 00xx xxxx */ | ||
741 | /* MUL 0100 0011 00xx xxxx */ | ||
742 | /* BIC (register) 0100 0011 10xx xxxx */ | ||
743 | /* MVN (register) 0100 0011 10xx xxxx */ | ||
744 | DECODE_EMULATE (0xfc00, 0x4000, PROBES_T16_LOGICAL), | ||
745 | |||
746 | /* | ||
747 | * Special data instructions and branch and exchange | ||
748 | * 0100 01xx xxxx xxxx | ||
749 | */ | ||
750 | |||
751 | /* BLX pc 0100 0111 1111 1xxx */ | ||
752 | DECODE_REJECT (0xfff8, 0x47f8), | ||
753 | |||
754 | /* BX (register) 0100 0111 0xxx xxxx */ | ||
755 | /* BLX (register) 0100 0111 1xxx xxxx */ | ||
756 | DECODE_SIMULATE (0xff00, 0x4700, PROBES_T16_BLX), | ||
757 | |||
758 | /* ADD pc, pc 0100 0100 1111 1111 */ | ||
759 | DECODE_REJECT (0xffff, 0x44ff), | ||
760 | |||
761 | /* ADD (register) 0100 0100 xxxx xxxx */ | ||
762 | /* CMP (register) 0100 0101 xxxx xxxx */ | ||
763 | /* MOV (register) 0100 0110 xxxx xxxx */ | ||
764 | DECODE_CUSTOM (0xfc00, 0x4400, PROBES_T16_HIREGOPS), | ||
765 | |||
766 | /* | ||
767 | * Load from Literal Pool | ||
768 | * LDR (literal) 0100 1xxx xxxx xxxx | ||
769 | */ | ||
770 | DECODE_SIMULATE (0xf800, 0x4800, PROBES_T16_LDR_LIT), | ||
771 | |||
772 | /* | ||
773 | * 16-bit Thumb Load/store instructions | ||
774 | * 0101 xxxx xxxx xxxx | ||
775 | * 011x xxxx xxxx xxxx | ||
776 | * 100x xxxx xxxx xxxx | ||
777 | */ | ||
778 | |||
779 | /* STR (register) 0101 000x xxxx xxxx */ | ||
780 | /* STRH (register) 0101 001x xxxx xxxx */ | ||
781 | /* STRB (register) 0101 010x xxxx xxxx */ | ||
782 | /* LDRSB (register) 0101 011x xxxx xxxx */ | ||
783 | /* LDR (register) 0101 100x xxxx xxxx */ | ||
784 | /* LDRH (register) 0101 101x xxxx xxxx */ | ||
785 | /* LDRB (register) 0101 110x xxxx xxxx */ | ||
786 | /* LDRSH (register) 0101 111x xxxx xxxx */ | ||
787 | /* STR (immediate, Thumb) 0110 0xxx xxxx xxxx */ | ||
788 | /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */ | ||
789 | /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */ | ||
790 | /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */ | ||
791 | DECODE_EMULATE (0xc000, 0x4000, PROBES_T16_LDRHSTRH), | ||
792 | /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */ | ||
793 | /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */ | ||
794 | DECODE_EMULATE (0xf000, 0x8000, PROBES_T16_LDRHSTRH), | ||
795 | /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */ | ||
796 | /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */ | ||
797 | DECODE_SIMULATE (0xf000, 0x9000, PROBES_T16_LDRSTR), | ||
798 | |||
799 | /* | ||
800 | * Generate PC-/SP-relative address | ||
801 | * ADR (literal) 1010 0xxx xxxx xxxx | ||
802 | * ADD (SP plus immediate) 1010 1xxx xxxx xxxx | ||
803 | */ | ||
804 | DECODE_SIMULATE (0xf000, 0xa000, PROBES_T16_ADR), | ||
805 | |||
806 | /* | ||
807 | * Miscellaneous 16-bit instructions | ||
808 | * 1011 xxxx xxxx xxxx | ||
809 | */ | ||
810 | DECODE_TABLE (0xf000, 0xb000, t16_table_1011), | ||
811 | |||
812 | /* STM 1100 0xxx xxxx xxxx */ | ||
813 | /* LDM 1100 1xxx xxxx xxxx */ | ||
814 | DECODE_EMULATE (0xf000, 0xc000, PROBES_T16_LDMSTM), | ||
815 | |||
816 | /* | ||
817 | * Conditional branch, and Supervisor Call | ||
818 | */ | ||
819 | |||
820 | /* Permanently UNDEFINED 1101 1110 xxxx xxxx */ | ||
821 | /* SVC 1101 1111 xxxx xxxx */ | ||
822 | DECODE_REJECT (0xfe00, 0xde00), | ||
823 | |||
824 | /* Conditional branch 1101 xxxx xxxx xxxx */ | ||
825 | DECODE_CUSTOM (0xf000, 0xd000, PROBES_T16_BRANCH_COND), | ||
826 | |||
827 | /* | ||
828 | * Unconditional branch | ||
829 | * B 1110 0xxx xxxx xxxx | ||
830 | */ | ||
831 | DECODE_SIMULATE (0xf800, 0xe000, PROBES_T16_BRANCH), | ||
832 | |||
833 | DECODE_END | ||
834 | }; | ||
835 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE | ||
836 | EXPORT_SYMBOL_GPL(probes_decode_thumb16_table); | ||
837 | #endif | ||
838 | |||
839 | static unsigned long __kprobes thumb_check_cc(unsigned long cpsr) | ||
840 | { | ||
841 | if (unlikely(in_it_block(cpsr))) | ||
842 | return probes_condition_checks[current_cond(cpsr)](cpsr); | ||
843 | return true; | ||
844 | } | ||
845 | |||
846 | static void __kprobes thumb16_singlestep(probes_opcode_t opcode, | ||
847 | struct arch_probes_insn *asi, | ||
848 | struct pt_regs *regs) | ||
849 | { | ||
850 | regs->ARM_pc += 2; | ||
851 | asi->insn_handler(opcode, asi, regs); | ||
852 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); | ||
853 | } | ||
854 | |||
855 | static void __kprobes thumb32_singlestep(probes_opcode_t opcode, | ||
856 | struct arch_probes_insn *asi, | ||
857 | struct pt_regs *regs) | ||
858 | { | ||
859 | regs->ARM_pc += 4; | ||
860 | asi->insn_handler(opcode, asi, regs); | ||
861 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); | ||
862 | } | ||
863 | |||
864 | enum probes_insn __kprobes | ||
865 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
866 | bool emulate, const union decode_action *actions) | ||
867 | { | ||
868 | asi->insn_singlestep = thumb16_singlestep; | ||
869 | asi->insn_check_cc = thumb_check_cc; | ||
870 | return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, | ||
871 | emulate, actions); | ||
872 | } | ||
873 | |||
874 | enum probes_insn __kprobes | ||
875 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
876 | bool emulate, const union decode_action *actions) | ||
877 | { | ||
878 | asi->insn_singlestep = thumb32_singlestep; | ||
879 | asi->insn_check_cc = thumb_check_cc; | ||
880 | return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, | ||
881 | emulate, actions); | ||
882 | } | ||
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h new file mode 100644 index 000000000000..7c6f6ebe514f --- /dev/null +++ b/arch/arm/kernel/probes-thumb.h | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes-thumb.h | ||
3 | * | ||
4 | * Copyright 2013 Linaro Ltd. | ||
5 | * Written by: David A. Long | ||
6 | * | ||
7 | * The code contained herein is licensed under the GNU General Public | ||
8 | * License. You may obtain a copy of the GNU General Public License | ||
9 | * Version 2 or later at the following locations: | ||
10 | * | ||
11 | * http://www.opensource.org/licenses/gpl-license.html | ||
12 | * http://www.gnu.org/copyleft/gpl.html | ||
13 | */ | ||
14 | |||
15 | #ifndef _ARM_KERNEL_PROBES_THUMB_H | ||
16 | #define _ARM_KERNEL_PROBES_THUMB_H | ||
17 | |||
18 | /* | ||
19 | * True if current instruction is in an IT block. | ||
20 | */ | ||
21 | #define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000) | ||
22 | |||
23 | /* | ||
24 | * Return the condition code to check for the currently executing instruction. | ||
25 | * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if | ||
26 | * in_it_block returns true. | ||
27 | */ | ||
28 | #define current_cond(cpsr) ((cpsr >> 12) & 0xf) | ||
29 | |||
30 | enum probes_t32_action { | ||
31 | PROBES_T32_EMULATE_NONE, | ||
32 | PROBES_T32_SIMULATE_NOP, | ||
33 | PROBES_T32_LDMSTM, | ||
34 | PROBES_T32_LDRDSTRD, | ||
35 | PROBES_T32_TABLE_BRANCH, | ||
36 | PROBES_T32_TST, | ||
37 | PROBES_T32_CMP, | ||
38 | PROBES_T32_MOV, | ||
39 | PROBES_T32_ADDSUB, | ||
40 | PROBES_T32_LOGICAL, | ||
41 | PROBES_T32_ADDWSUBW_PC, | ||
42 | PROBES_T32_ADDWSUBW, | ||
43 | PROBES_T32_MOVW, | ||
44 | PROBES_T32_SAT, | ||
45 | PROBES_T32_BITFIELD, | ||
46 | PROBES_T32_SEV, | ||
47 | PROBES_T32_WFE, | ||
48 | PROBES_T32_MRS, | ||
49 | PROBES_T32_BRANCH_COND, | ||
50 | PROBES_T32_BRANCH, | ||
51 | PROBES_T32_PLDI, | ||
52 | PROBES_T32_LDR_LIT, | ||
53 | PROBES_T32_LDRSTR, | ||
54 | PROBES_T32_SIGN_EXTEND, | ||
55 | PROBES_T32_MEDIA, | ||
56 | PROBES_T32_REVERSE, | ||
57 | PROBES_T32_MUL_ADD, | ||
58 | PROBES_T32_MUL_ADD2, | ||
59 | PROBES_T32_MUL_ADD_LONG, | ||
60 | NUM_PROBES_T32_ACTIONS | ||
61 | }; | ||
62 | |||
63 | enum probes_t16_action { | ||
64 | PROBES_T16_ADD_SP, | ||
65 | PROBES_T16_CBZ, | ||
66 | PROBES_T16_SIGN_EXTEND, | ||
67 | PROBES_T16_PUSH, | ||
68 | PROBES_T16_POP, | ||
69 | PROBES_T16_SEV, | ||
70 | PROBES_T16_WFE, | ||
71 | PROBES_T16_IT, | ||
72 | PROBES_T16_CMP, | ||
73 | PROBES_T16_ADDSUB, | ||
74 | PROBES_T16_LOGICAL, | ||
75 | PROBES_T16_BLX, | ||
76 | PROBES_T16_HIREGOPS, | ||
77 | PROBES_T16_LDR_LIT, | ||
78 | PROBES_T16_LDRHSTRH, | ||
79 | PROBES_T16_LDRSTR, | ||
80 | PROBES_T16_ADR, | ||
81 | PROBES_T16_LDMSTM, | ||
82 | PROBES_T16_BRANCH_COND, | ||
83 | PROBES_T16_BRANCH, | ||
84 | NUM_PROBES_T16_ACTIONS | ||
85 | }; | ||
86 | |||
87 | extern const union decode_item probes_decode_thumb32_table[]; | ||
88 | extern const union decode_item probes_decode_thumb16_table[]; | ||
89 | |||
90 | enum probes_insn __kprobes | ||
91 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
92 | bool emulate, const union decode_action *actions); | ||
93 | enum probes_insn __kprobes | ||
94 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
95 | bool emulate, const union decode_action *actions); | ||
96 | |||
97 | #endif | ||
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c new file mode 100644 index 000000000000..b41873f33e69 --- /dev/null +++ b/arch/arm/kernel/probes.c | |||
@@ -0,0 +1,455 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | ||
5 | * | ||
6 | * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is | ||
7 | * Copyright (C) 2006, 2007 Motorola Inc. | ||
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 version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <asm/system_info.h> | ||
17 | #include <asm/ptrace.h> | ||
18 | #include <linux/bug.h> | ||
19 | |||
20 | #include "probes.h" | ||
21 | |||
22 | |||
23 | #ifndef find_str_pc_offset | ||
24 | |||
25 | /* | ||
26 | * For STR and STM instructions, an ARM core may choose to use either | ||
27 | * a +8 or a +12 displacement from the current instruction's address. | ||
28 | * Whichever value is chosen for a given core, it must be the same for | ||
29 | * both instructions and may not change. This function measures it. | ||
30 | */ | ||
31 | |||
32 | int str_pc_offset; | ||
33 | |||
34 | void __init find_str_pc_offset(void) | ||
35 | { | ||
36 | int addr, scratch, ret; | ||
37 | |||
38 | __asm__ ( | ||
39 | "sub %[ret], pc, #4 \n\t" | ||
40 | "str pc, %[addr] \n\t" | ||
41 | "ldr %[scr], %[addr] \n\t" | ||
42 | "sub %[ret], %[scr], %[ret] \n\t" | ||
43 | : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr)); | ||
44 | |||
45 | str_pc_offset = ret; | ||
46 | } | ||
47 | |||
48 | #endif /* !find_str_pc_offset */ | ||
49 | |||
50 | |||
51 | #ifndef test_load_write_pc_interworking | ||
52 | |||
53 | bool load_write_pc_interworks; | ||
54 | |||
55 | void __init test_load_write_pc_interworking(void) | ||
56 | { | ||
57 | int arch = cpu_architecture(); | ||
58 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
59 | load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T; | ||
60 | } | ||
61 | |||
62 | #endif /* !test_load_write_pc_interworking */ | ||
63 | |||
64 | |||
65 | #ifndef test_alu_write_pc_interworking | ||
66 | |||
67 | bool alu_write_pc_interworks; | ||
68 | |||
69 | void __init test_alu_write_pc_interworking(void) | ||
70 | { | ||
71 | int arch = cpu_architecture(); | ||
72 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
73 | alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7; | ||
74 | } | ||
75 | |||
76 | #endif /* !test_alu_write_pc_interworking */ | ||
77 | |||
78 | |||
79 | void __init arm_probes_decode_init(void) | ||
80 | { | ||
81 | find_str_pc_offset(); | ||
82 | test_load_write_pc_interworking(); | ||
83 | test_alu_write_pc_interworking(); | ||
84 | } | ||
85 | |||
86 | |||
87 | static unsigned long __kprobes __check_eq(unsigned long cpsr) | ||
88 | { | ||
89 | return cpsr & PSR_Z_BIT; | ||
90 | } | ||
91 | |||
92 | static unsigned long __kprobes __check_ne(unsigned long cpsr) | ||
93 | { | ||
94 | return (~cpsr) & PSR_Z_BIT; | ||
95 | } | ||
96 | |||
97 | static unsigned long __kprobes __check_cs(unsigned long cpsr) | ||
98 | { | ||
99 | return cpsr & PSR_C_BIT; | ||
100 | } | ||
101 | |||
102 | static unsigned long __kprobes __check_cc(unsigned long cpsr) | ||
103 | { | ||
104 | return (~cpsr) & PSR_C_BIT; | ||
105 | } | ||
106 | |||
107 | static unsigned long __kprobes __check_mi(unsigned long cpsr) | ||
108 | { | ||
109 | return cpsr & PSR_N_BIT; | ||
110 | } | ||
111 | |||
112 | static unsigned long __kprobes __check_pl(unsigned long cpsr) | ||
113 | { | ||
114 | return (~cpsr) & PSR_N_BIT; | ||
115 | } | ||
116 | |||
117 | static unsigned long __kprobes __check_vs(unsigned long cpsr) | ||
118 | { | ||
119 | return cpsr & PSR_V_BIT; | ||
120 | } | ||
121 | |||
122 | static unsigned long __kprobes __check_vc(unsigned long cpsr) | ||
123 | { | ||
124 | return (~cpsr) & PSR_V_BIT; | ||
125 | } | ||
126 | |||
127 | static unsigned long __kprobes __check_hi(unsigned long cpsr) | ||
128 | { | ||
129 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
130 | return cpsr & PSR_C_BIT; | ||
131 | } | ||
132 | |||
133 | static unsigned long __kprobes __check_ls(unsigned long cpsr) | ||
134 | { | ||
135 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
136 | return (~cpsr) & PSR_C_BIT; | ||
137 | } | ||
138 | |||
139 | static unsigned long __kprobes __check_ge(unsigned long cpsr) | ||
140 | { | ||
141 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
142 | return (~cpsr) & PSR_N_BIT; | ||
143 | } | ||
144 | |||
145 | static unsigned long __kprobes __check_lt(unsigned long cpsr) | ||
146 | { | ||
147 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
148 | return cpsr & PSR_N_BIT; | ||
149 | } | ||
150 | |||
151 | static unsigned long __kprobes __check_gt(unsigned long cpsr) | ||
152 | { | ||
153 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
154 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
155 | return (~temp) & PSR_N_BIT; | ||
156 | } | ||
157 | |||
158 | static unsigned long __kprobes __check_le(unsigned long cpsr) | ||
159 | { | ||
160 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
161 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
162 | return temp & PSR_N_BIT; | ||
163 | } | ||
164 | |||
165 | static unsigned long __kprobes __check_al(unsigned long cpsr) | ||
166 | { | ||
167 | return true; | ||
168 | } | ||
169 | |||
170 | probes_check_cc * const probes_condition_checks[16] = { | ||
171 | &__check_eq, &__check_ne, &__check_cs, &__check_cc, | ||
172 | &__check_mi, &__check_pl, &__check_vs, &__check_vc, | ||
173 | &__check_hi, &__check_ls, &__check_ge, &__check_lt, | ||
174 | &__check_gt, &__check_le, &__check_al, &__check_al | ||
175 | }; | ||
176 | |||
177 | |||
178 | void __kprobes probes_simulate_nop(probes_opcode_t opcode, | ||
179 | struct arch_probes_insn *asi, | ||
180 | struct pt_regs *regs) | ||
181 | { | ||
182 | } | ||
183 | |||
184 | void __kprobes probes_emulate_none(probes_opcode_t opcode, | ||
185 | struct arch_probes_insn *asi, | ||
186 | struct pt_regs *regs) | ||
187 | { | ||
188 | asi->insn_fn(); | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * Prepare an instruction slot to receive an instruction for emulating. | ||
193 | * This is done by placing a subroutine return after the location where the | ||
194 | * instruction will be placed. We also modify ARM instructions to be | ||
195 | * unconditional as the condition code will already be checked before any | ||
196 | * emulation handler is called. | ||
197 | */ | ||
198 | static probes_opcode_t __kprobes | ||
199 | prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
200 | bool thumb) | ||
201 | { | ||
202 | #ifdef CONFIG_THUMB2_KERNEL | ||
203 | if (thumb) { | ||
204 | u16 *thumb_insn = (u16 *)asi->insn; | ||
205 | thumb_insn[1] = 0x4770; /* Thumb bx lr */ | ||
206 | thumb_insn[2] = 0x4770; /* Thumb bx lr */ | ||
207 | return insn; | ||
208 | } | ||
209 | asi->insn[1] = 0xe12fff1e; /* ARM bx lr */ | ||
210 | #else | ||
211 | asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */ | ||
212 | #endif | ||
213 | /* Make an ARM instruction unconditional */ | ||
214 | if (insn < 0xe0000000) | ||
215 | insn = (insn | 0xe0000000) & ~0x10000000; | ||
216 | return insn; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Write a (probably modified) instruction into the slot previously prepared by | ||
221 | * prepare_emulated_insn | ||
222 | */ | ||
223 | static void __kprobes | ||
224 | set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
225 | bool thumb) | ||
226 | { | ||
227 | #ifdef CONFIG_THUMB2_KERNEL | ||
228 | if (thumb) { | ||
229 | u16 *ip = (u16 *)asi->insn; | ||
230 | if (is_wide_instruction(insn)) | ||
231 | *ip++ = insn >> 16; | ||
232 | *ip++ = insn; | ||
233 | return; | ||
234 | } | ||
235 | #endif | ||
236 | asi->insn[0] = insn; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * When we modify the register numbers encoded in an instruction to be emulated, | ||
241 | * the new values come from this define. For ARM and 32-bit Thumb instructions | ||
242 | * this gives... | ||
243 | * | ||
244 | * bit position 16 12 8 4 0 | ||
245 | * ---------------+---+---+---+---+---+ | ||
246 | * register r2 r0 r1 -- r3 | ||
247 | */ | ||
248 | #define INSN_NEW_BITS 0x00020103 | ||
249 | |||
250 | /* Each nibble has same value as that at INSN_NEW_BITS bit 16 */ | ||
251 | #define INSN_SAMEAS16_BITS 0x22222222 | ||
252 | |||
253 | /* | ||
254 | * Validate and modify each of the registers encoded in an instruction. | ||
255 | * | ||
256 | * Each nibble in regs contains a value from enum decode_reg_type. For each | ||
257 | * non-zero value, the corresponding nibble in pinsn is validated and modified | ||
258 | * according to the type. | ||
259 | */ | ||
260 | static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) | ||
261 | { | ||
262 | probes_opcode_t insn = *pinsn; | ||
263 | probes_opcode_t mask = 0xf; /* Start at least significant nibble */ | ||
264 | |||
265 | for (; regs != 0; regs >>= 4, mask <<= 4) { | ||
266 | |||
267 | probes_opcode_t new_bits = INSN_NEW_BITS; | ||
268 | |||
269 | switch (regs & 0xf) { | ||
270 | |||
271 | case REG_TYPE_NONE: | ||
272 | /* Nibble not a register, skip to next */ | ||
273 | continue; | ||
274 | |||
275 | case REG_TYPE_ANY: | ||
276 | /* Any register is allowed */ | ||
277 | break; | ||
278 | |||
279 | case REG_TYPE_SAMEAS16: | ||
280 | /* Replace register with same as at bit position 16 */ | ||
281 | new_bits = INSN_SAMEAS16_BITS; | ||
282 | break; | ||
283 | |||
284 | case REG_TYPE_SP: | ||
285 | /* Only allow SP (R13) */ | ||
286 | if ((insn ^ 0xdddddddd) & mask) | ||
287 | goto reject; | ||
288 | break; | ||
289 | |||
290 | case REG_TYPE_PC: | ||
291 | /* Only allow PC (R15) */ | ||
292 | if ((insn ^ 0xffffffff) & mask) | ||
293 | goto reject; | ||
294 | break; | ||
295 | |||
296 | case REG_TYPE_NOSP: | ||
297 | /* Reject SP (R13) */ | ||
298 | if (((insn ^ 0xdddddddd) & mask) == 0) | ||
299 | goto reject; | ||
300 | break; | ||
301 | |||
302 | case REG_TYPE_NOSPPC: | ||
303 | case REG_TYPE_NOSPPCX: | ||
304 | /* Reject SP and PC (R13 and R15) */ | ||
305 | if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0) | ||
306 | goto reject; | ||
307 | break; | ||
308 | |||
309 | case REG_TYPE_NOPCWB: | ||
310 | if (!is_writeback(insn)) | ||
311 | break; /* No writeback, so any register is OK */ | ||
312 | /* fall through... */ | ||
313 | case REG_TYPE_NOPC: | ||
314 | case REG_TYPE_NOPCX: | ||
315 | /* Reject PC (R15) */ | ||
316 | if (((insn ^ 0xffffffff) & mask) == 0) | ||
317 | goto reject; | ||
318 | break; | ||
319 | } | ||
320 | |||
321 | /* Replace value of nibble with new register number... */ | ||
322 | insn &= ~mask; | ||
323 | insn |= new_bits & mask; | ||
324 | } | ||
325 | |||
326 | if (modify) | ||
327 | *pinsn = insn; | ||
328 | |||
329 | return true; | ||
330 | |||
331 | reject: | ||
332 | return false; | ||
333 | } | ||
334 | |||
335 | static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | ||
336 | [DECODE_TYPE_TABLE] = sizeof(struct decode_table), | ||
337 | [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), | ||
338 | [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), | ||
339 | [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), | ||
340 | [DECODE_TYPE_OR] = sizeof(struct decode_or), | ||
341 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) | ||
342 | }; | ||
343 | |||
344 | /* | ||
345 | * probes_decode_insn operates on data tables in order to decode an ARM | ||
346 | * architecture instruction onto which a kprobe has been placed. | ||
347 | * | ||
348 | * These instruction decoding tables are a concatenation of entries each | ||
349 | * of which consist of one of the following structs: | ||
350 | * | ||
351 | * decode_table | ||
352 | * decode_custom | ||
353 | * decode_simulate | ||
354 | * decode_emulate | ||
355 | * decode_or | ||
356 | * decode_reject | ||
357 | * | ||
358 | * Each of these starts with a struct decode_header which has the following | ||
359 | * fields: | ||
360 | * | ||
361 | * type_regs | ||
362 | * mask | ||
363 | * value | ||
364 | * | ||
365 | * The least significant DECODE_TYPE_BITS of type_regs contains a value | ||
366 | * from enum decode_type, this indicates which of the decode_* structs | ||
367 | * the entry contains. The value DECODE_TYPE_END indicates the end of the | ||
368 | * table. | ||
369 | * | ||
370 | * When the table is parsed, each entry is checked in turn to see if it | ||
371 | * matches the instruction to be decoded using the test: | ||
372 | * | ||
373 | * (insn & mask) == value | ||
374 | * | ||
375 | * If no match is found before the end of the table is reached then decoding | ||
376 | * fails with INSN_REJECTED. | ||
377 | * | ||
378 | * When a match is found, decode_regs() is called to validate and modify each | ||
379 | * of the registers encoded in the instruction; the data it uses to do this | ||
380 | * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding | ||
381 | * to fail with INSN_REJECTED. | ||
382 | * | ||
383 | * Once the instruction has passed the above tests, further processing | ||
384 | * depends on the type of the table entry's decode struct. | ||
385 | * | ||
386 | */ | ||
387 | int __kprobes | ||
388 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
389 | const union decode_item *table, bool thumb, | ||
390 | bool emulate, const union decode_action *actions) | ||
391 | { | ||
392 | const struct decode_header *h = (struct decode_header *)table; | ||
393 | const struct decode_header *next; | ||
394 | bool matched = false; | ||
395 | |||
396 | if (emulate) | ||
397 | insn = prepare_emulated_insn(insn, asi, thumb); | ||
398 | |||
399 | for (;; h = next) { | ||
400 | enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; | ||
401 | u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; | ||
402 | |||
403 | if (type == DECODE_TYPE_END) | ||
404 | return INSN_REJECTED; | ||
405 | |||
406 | next = (struct decode_header *) | ||
407 | ((uintptr_t)h + decode_struct_sizes[type]); | ||
408 | |||
409 | if (!matched && (insn & h->mask.bits) != h->value.bits) | ||
410 | continue; | ||
411 | |||
412 | if (!decode_regs(&insn, regs, emulate)) | ||
413 | return INSN_REJECTED; | ||
414 | |||
415 | switch (type) { | ||
416 | |||
417 | case DECODE_TYPE_TABLE: { | ||
418 | struct decode_table *d = (struct decode_table *)h; | ||
419 | next = (struct decode_header *)d->table.table; | ||
420 | break; | ||
421 | } | ||
422 | |||
423 | case DECODE_TYPE_CUSTOM: { | ||
424 | struct decode_custom *d = (struct decode_custom *)h; | ||
425 | return actions[d->decoder.action].decoder(insn, asi, h); | ||
426 | } | ||
427 | |||
428 | case DECODE_TYPE_SIMULATE: { | ||
429 | struct decode_simulate *d = (struct decode_simulate *)h; | ||
430 | asi->insn_handler = actions[d->handler.action].handler; | ||
431 | return INSN_GOOD_NO_SLOT; | ||
432 | } | ||
433 | |||
434 | case DECODE_TYPE_EMULATE: { | ||
435 | struct decode_emulate *d = (struct decode_emulate *)h; | ||
436 | |||
437 | if (!emulate) | ||
438 | return actions[d->handler.action].decoder(insn, | ||
439 | asi, h); | ||
440 | |||
441 | asi->insn_handler = actions[d->handler.action].handler; | ||
442 | set_emulated_insn(insn, asi, thumb); | ||
443 | return INSN_GOOD; | ||
444 | } | ||
445 | |||
446 | case DECODE_TYPE_OR: | ||
447 | matched = true; | ||
448 | break; | ||
449 | |||
450 | case DECODE_TYPE_REJECT: | ||
451 | default: | ||
452 | return INSN_REJECTED; | ||
453 | } | ||
454 | } | ||
455 | } | ||
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h new file mode 100644 index 000000000000..dba9f2466a93 --- /dev/null +++ b/arch/arm/kernel/probes.h | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes.h | ||
3 | * | ||
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | ||
5 | * | ||
6 | * Some contents moved here from arch/arm/include/asm/kprobes.h which is | ||
7 | * Copyright (C) 2006, 2007 Motorola Inc. | ||
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 version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #ifndef _ARM_KERNEL_PROBES_H | ||
20 | #define _ARM_KERNEL_PROBES_H | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | #include <linux/stddef.h> | ||
24 | #include <asm/probes.h> | ||
25 | |||
26 | void __init arm_probes_decode_init(void); | ||
27 | |||
28 | extern probes_check_cc * const probes_condition_checks[16]; | ||
29 | |||
30 | #if __LINUX_ARM_ARCH__ >= 7 | ||
31 | |||
32 | /* str_pc_offset is architecturally defined from ARMv7 onwards */ | ||
33 | #define str_pc_offset 8 | ||
34 | #define find_str_pc_offset() | ||
35 | |||
36 | #else /* __LINUX_ARM_ARCH__ < 7 */ | ||
37 | |||
38 | /* We need a run-time check to determine str_pc_offset */ | ||
39 | extern int str_pc_offset; | ||
40 | void __init find_str_pc_offset(void); | ||
41 | |||
42 | #endif | ||
43 | |||
44 | |||
45 | /* | ||
46 | * Update ITSTATE after normal execution of an IT block instruction. | ||
47 | * | ||
48 | * The 8 IT state bits are split into two parts in CPSR: | ||
49 | * ITSTATE<1:0> are in CPSR<26:25> | ||
50 | * ITSTATE<7:2> are in CPSR<15:10> | ||
51 | */ | ||
52 | static inline unsigned long it_advance(unsigned long cpsr) | ||
53 | { | ||
54 | if ((cpsr & 0x06000400) == 0) { | ||
55 | /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */ | ||
56 | cpsr &= ~PSR_IT_MASK; | ||
57 | } else { | ||
58 | /* We need to shift left ITSTATE<4:0> */ | ||
59 | const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */ | ||
60 | unsigned long it = cpsr & mask; | ||
61 | it <<= 1; | ||
62 | it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */ | ||
63 | it &= mask; | ||
64 | cpsr &= ~mask; | ||
65 | cpsr |= it; | ||
66 | } | ||
67 | return cpsr; | ||
68 | } | ||
69 | |||
70 | static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs) | ||
71 | { | ||
72 | long cpsr = regs->ARM_cpsr; | ||
73 | if (pcv & 0x1) { | ||
74 | cpsr |= PSR_T_BIT; | ||
75 | pcv &= ~0x1; | ||
76 | } else { | ||
77 | cpsr &= ~PSR_T_BIT; | ||
78 | pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */ | ||
79 | } | ||
80 | regs->ARM_cpsr = cpsr; | ||
81 | regs->ARM_pc = pcv; | ||
82 | } | ||
83 | |||
84 | |||
85 | #if __LINUX_ARM_ARCH__ >= 6 | ||
86 | |||
87 | /* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */ | ||
88 | #define load_write_pc_interworks true | ||
89 | #define test_load_write_pc_interworking() | ||
90 | |||
91 | #else /* __LINUX_ARM_ARCH__ < 6 */ | ||
92 | |||
93 | /* We need run-time testing to determine if load_write_pc() should interwork. */ | ||
94 | extern bool load_write_pc_interworks; | ||
95 | void __init test_load_write_pc_interworking(void); | ||
96 | |||
97 | #endif | ||
98 | |||
99 | static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs) | ||
100 | { | ||
101 | if (load_write_pc_interworks) | ||
102 | bx_write_pc(pcv, regs); | ||
103 | else | ||
104 | regs->ARM_pc = pcv; | ||
105 | } | ||
106 | |||
107 | |||
108 | #if __LINUX_ARM_ARCH__ >= 7 | ||
109 | |||
110 | #define alu_write_pc_interworks true | ||
111 | #define test_alu_write_pc_interworking() | ||
112 | |||
113 | #elif __LINUX_ARM_ARCH__ <= 5 | ||
114 | |||
115 | /* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */ | ||
116 | #define alu_write_pc_interworks false | ||
117 | #define test_alu_write_pc_interworking() | ||
118 | |||
119 | #else /* __LINUX_ARM_ARCH__ == 6 */ | ||
120 | |||
121 | /* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */ | ||
122 | extern bool alu_write_pc_interworks; | ||
123 | void __init test_alu_write_pc_interworking(void); | ||
124 | |||
125 | #endif /* __LINUX_ARM_ARCH__ == 6 */ | ||
126 | |||
127 | static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs) | ||
128 | { | ||
129 | if (alu_write_pc_interworks) | ||
130 | bx_write_pc(pcv, regs); | ||
131 | else | ||
132 | regs->ARM_pc = pcv; | ||
133 | } | ||
134 | |||
135 | |||
136 | /* | ||
137 | * Test if load/store instructions writeback the address register. | ||
138 | * if P (bit 24) == 0 or W (bit 21) == 1 | ||
139 | */ | ||
140 | #define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000) | ||
141 | |||
142 | /* | ||
143 | * The following definitions and macros are used to build instruction | ||
144 | * decoding tables for use by probes_decode_insn. | ||
145 | * | ||
146 | * These tables are a concatenation of entries each of which consist of one of | ||
147 | * the decode_* structs. All of the fields in every type of decode structure | ||
148 | * are of the union type decode_item, therefore the entire decode table can be | ||
149 | * viewed as an array of these and declared like: | ||
150 | * | ||
151 | * static const union decode_item table_name[] = {}; | ||
152 | * | ||
153 | * In order to construct each entry in the table, macros are used to | ||
154 | * initialise a number of sequential decode_item values in a layout which | ||
155 | * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct | ||
156 | * decode_simulate by initialising four decode_item objects like this... | ||
157 | * | ||
158 | * {.bits = _type}, | ||
159 | * {.bits = _mask}, | ||
160 | * {.bits = _value}, | ||
161 | * {.action = _handler}, | ||
162 | * | ||
163 | * Initialising a specified member of the union means that the compiler | ||
164 | * will produce a warning if the argument is of an incorrect type. | ||
165 | * | ||
166 | * Below is a list of each of the macros used to initialise entries and a | ||
167 | * description of the action performed when that entry is matched to an | ||
168 | * instruction. A match is found when (instruction & mask) == value. | ||
169 | * | ||
170 | * DECODE_TABLE(mask, value, table) | ||
171 | * Instruction decoding jumps to parsing the new sub-table 'table'. | ||
172 | * | ||
173 | * DECODE_CUSTOM(mask, value, decoder) | ||
174 | * The value of 'decoder' is used as an index into the array of | ||
175 | * action functions, and the retrieved decoder function is invoked | ||
176 | * to complete decoding of the instruction. | ||
177 | * | ||
178 | * DECODE_SIMULATE(mask, value, handler) | ||
179 | * The probes instruction handler is set to the value found by | ||
180 | * indexing into the action array using the value of 'handler'. This | ||
181 | * will be used to simulate the instruction when the probe is hit. | ||
182 | * Decoding returns with INSN_GOOD_NO_SLOT. | ||
183 | * | ||
184 | * DECODE_EMULATE(mask, value, handler) | ||
185 | * The probes instruction handler is set to the value found by | ||
186 | * indexing into the action array using the value of 'handler'. This | ||
187 | * will be used to emulate the instruction when the probe is hit. The | ||
188 | * modified instruction (see below) is placed in the probes instruction | ||
189 | * slot so it may be called by the emulation code. Decoding returns | ||
190 | * with INSN_GOOD. | ||
191 | * | ||
192 | * DECODE_REJECT(mask, value) | ||
193 | * Instruction decoding fails with INSN_REJECTED | ||
194 | * | ||
195 | * DECODE_OR(mask, value) | ||
196 | * This allows the mask/value test of multiple table entries to be | ||
197 | * logically ORed. Once an 'or' entry is matched the decoding action to | ||
198 | * be performed is that of the next entry which isn't an 'or'. E.g. | ||
199 | * | ||
200 | * DECODE_OR (mask1, value1) | ||
201 | * DECODE_OR (mask2, value2) | ||
202 | * DECODE_SIMULATE (mask3, value3, simulation_handler) | ||
203 | * | ||
204 | * This means that if any of the three mask/value pairs match the | ||
205 | * instruction being decoded, then 'simulation_handler' will be used | ||
206 | * for it. | ||
207 | * | ||
208 | * Both the SIMULATE and EMULATE macros have a second form which take an | ||
209 | * additional 'regs' argument. | ||
210 | * | ||
211 | * DECODE_SIMULATEX(mask, value, handler, regs) | ||
212 | * DECODE_EMULATEX (mask, value, handler, regs) | ||
213 | * | ||
214 | * These are used to specify what kind of CPU register is encoded in each of the | ||
215 | * least significant 5 nibbles of the instruction being decoded. The regs value | ||
216 | * is specified using the REGS macro, this takes any of the REG_TYPE_* values | ||
217 | * from enum decode_reg_type as arguments; only the '*' part of the name is | ||
218 | * given. E.g. | ||
219 | * | ||
220 | * REGS(0, ANY, NOPC, 0, ANY) | ||
221 | * | ||
222 | * This indicates an instruction is encoded like: | ||
223 | * | ||
224 | * bits 19..16 ignore | ||
225 | * bits 15..12 any register allowed here | ||
226 | * bits 11.. 8 any register except PC allowed here | ||
227 | * bits 7.. 4 ignore | ||
228 | * bits 3.. 0 any register allowed here | ||
229 | * | ||
230 | * This register specification is checked after a decode table entry is found to | ||
231 | * match an instruction (through the mask/value test). Any invalid register then | ||
232 | * found in the instruction will cause decoding to fail with INSN_REJECTED. In | ||
233 | * the above example this would happen if bits 11..8 of the instruction were | ||
234 | * 1111, indicating R15 or PC. | ||
235 | * | ||
236 | * As well as checking for legal combinations of registers, this data is also | ||
237 | * used to modify the registers encoded in the instructions so that an | ||
238 | * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.) | ||
239 | * | ||
240 | * Here is a real example which matches ARM instructions of the form | ||
241 | * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>" | ||
242 | * | ||
243 | * DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG, | ||
244 | * REGS(ANY, ANY, NOPC, 0, ANY)), | ||
245 | * ^ ^ ^ ^ | ||
246 | * Rn Rd Rs Rm | ||
247 | * | ||
248 | * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because | ||
249 | * Rs == R15 | ||
250 | * | ||
251 | * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the | ||
252 | * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into | ||
253 | * the kprobes instruction slot. This can then be called later by the handler | ||
254 | * function emulate_rd12rn16rm0rs8_rwflags (a pointer to which is retrieved from | ||
255 | * the indicated slot in the action array), in order to simulate the instruction. | ||
256 | */ | ||
257 | |||
258 | enum decode_type { | ||
259 | DECODE_TYPE_END, | ||
260 | DECODE_TYPE_TABLE, | ||
261 | DECODE_TYPE_CUSTOM, | ||
262 | DECODE_TYPE_SIMULATE, | ||
263 | DECODE_TYPE_EMULATE, | ||
264 | DECODE_TYPE_OR, | ||
265 | DECODE_TYPE_REJECT, | ||
266 | NUM_DECODE_TYPES /* Must be last enum */ | ||
267 | }; | ||
268 | |||
269 | #define DECODE_TYPE_BITS 4 | ||
270 | #define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1) | ||
271 | |||
272 | enum decode_reg_type { | ||
273 | REG_TYPE_NONE = 0, /* Not a register, ignore */ | ||
274 | REG_TYPE_ANY, /* Any register allowed */ | ||
275 | REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */ | ||
276 | REG_TYPE_SP, /* Register must be SP */ | ||
277 | REG_TYPE_PC, /* Register must be PC */ | ||
278 | REG_TYPE_NOSP, /* Register must not be SP */ | ||
279 | REG_TYPE_NOSPPC, /* Register must not be SP or PC */ | ||
280 | REG_TYPE_NOPC, /* Register must not be PC */ | ||
281 | REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */ | ||
282 | |||
283 | /* The following types are used when the encoding for PC indicates | ||
284 | * another instruction form. This distiction only matters for test | ||
285 | * case coverage checks. | ||
286 | */ | ||
287 | REG_TYPE_NOPCX, /* Register must not be PC */ | ||
288 | REG_TYPE_NOSPPCX, /* Register must not be SP or PC */ | ||
289 | |||
290 | /* Alias to allow '0' arg to be used in REGS macro. */ | ||
291 | REG_TYPE_0 = REG_TYPE_NONE | ||
292 | }; | ||
293 | |||
294 | #define REGS(r16, r12, r8, r4, r0) \ | ||
295 | (((REG_TYPE_##r16) << 16) + \ | ||
296 | ((REG_TYPE_##r12) << 12) + \ | ||
297 | ((REG_TYPE_##r8) << 8) + \ | ||
298 | ((REG_TYPE_##r4) << 4) + \ | ||
299 | (REG_TYPE_##r0)) | ||
300 | |||
301 | union decode_item { | ||
302 | u32 bits; | ||
303 | const union decode_item *table; | ||
304 | int action; | ||
305 | }; | ||
306 | |||
307 | struct decode_header; | ||
308 | typedef enum probes_insn (probes_custom_decode_t)(probes_opcode_t, | ||
309 | struct arch_probes_insn *, | ||
310 | const struct decode_header *); | ||
311 | |||
312 | union decode_action { | ||
313 | probes_insn_handler_t *handler; | ||
314 | probes_custom_decode_t *decoder; | ||
315 | }; | ||
316 | |||
317 | #define DECODE_END \ | ||
318 | {.bits = DECODE_TYPE_END} | ||
319 | |||
320 | |||
321 | struct decode_header { | ||
322 | union decode_item type_regs; | ||
323 | union decode_item mask; | ||
324 | union decode_item value; | ||
325 | }; | ||
326 | |||
327 | #define DECODE_HEADER(_type, _mask, _value, _regs) \ | ||
328 | {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \ | ||
329 | {.bits = (_mask)}, \ | ||
330 | {.bits = (_value)} | ||
331 | |||
332 | |||
333 | struct decode_table { | ||
334 | struct decode_header header; | ||
335 | union decode_item table; | ||
336 | }; | ||
337 | |||
338 | #define DECODE_TABLE(_mask, _value, _table) \ | ||
339 | DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \ | ||
340 | {.table = (_table)} | ||
341 | |||
342 | |||
343 | struct decode_custom { | ||
344 | struct decode_header header; | ||
345 | union decode_item decoder; | ||
346 | }; | ||
347 | |||
348 | #define DECODE_CUSTOM(_mask, _value, _decoder) \ | ||
349 | DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \ | ||
350 | {.action = (_decoder)} | ||
351 | |||
352 | |||
353 | struct decode_simulate { | ||
354 | struct decode_header header; | ||
355 | union decode_item handler; | ||
356 | }; | ||
357 | |||
358 | #define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \ | ||
359 | DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \ | ||
360 | {.action = (_handler)} | ||
361 | |||
362 | #define DECODE_SIMULATE(_mask, _value, _handler) \ | ||
363 | DECODE_SIMULATEX(_mask, _value, _handler, 0) | ||
364 | |||
365 | |||
366 | struct decode_emulate { | ||
367 | struct decode_header header; | ||
368 | union decode_item handler; | ||
369 | }; | ||
370 | |||
371 | #define DECODE_EMULATEX(_mask, _value, _handler, _regs) \ | ||
372 | DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \ | ||
373 | {.action = (_handler)} | ||
374 | |||
375 | #define DECODE_EMULATE(_mask, _value, _handler) \ | ||
376 | DECODE_EMULATEX(_mask, _value, _handler, 0) | ||
377 | |||
378 | |||
379 | struct decode_or { | ||
380 | struct decode_header header; | ||
381 | }; | ||
382 | |||
383 | #define DECODE_OR(_mask, _value) \ | ||
384 | DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0) | ||
385 | |||
386 | enum probes_insn { | ||
387 | INSN_REJECTED, | ||
388 | INSN_GOOD, | ||
389 | INSN_GOOD_NO_SLOT | ||
390 | }; | ||
391 | |||
392 | struct decode_reject { | ||
393 | struct decode_header header; | ||
394 | }; | ||
395 | |||
396 | #define DECODE_REJECT(_mask, _value) \ | ||
397 | DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) | ||
398 | |||
399 | probes_insn_handler_t probes_simulate_nop; | ||
400 | probes_insn_handler_t probes_emulate_none; | ||
401 | |||
402 | int __kprobes | ||
403 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
404 | const union decode_item *table, bool thumb, bool emulate, | ||
405 | const union decode_action *actions); | ||
406 | |||
407 | #endif | ||
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b0df9761de6d..1e8b030dbefd 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -731,7 +731,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) | |||
731 | kernel_data.end = virt_to_phys(_end - 1); | 731 | kernel_data.end = virt_to_phys(_end - 1); |
732 | 732 | ||
733 | for_each_memblock(memory, region) { | 733 | for_each_memblock(memory, region) { |
734 | res = memblock_virt_alloc_low(sizeof(*res), 0); | 734 | res = memblock_virt_alloc(sizeof(*res), 0); |
735 | res->name = "System RAM"; | 735 | res->name = "System RAM"; |
736 | res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); | 736 | res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); |
737 | res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; | 737 | res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; |
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 04d63880037f..bd1983437205 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/personality.h> | 13 | #include <linux/personality.h> |
14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | #include <linux/tracehook.h> | 15 | #include <linux/tracehook.h> |
16 | #include <linux/uprobes.h> | ||
16 | 17 | ||
17 | #include <asm/elf.h> | 18 | #include <asm/elf.h> |
18 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
@@ -590,6 +591,9 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) | |||
590 | return restart; | 591 | return restart; |
591 | } | 592 | } |
592 | syscall = 0; | 593 | syscall = 0; |
594 | } else if (thread_flags & _TIF_UPROBE) { | ||
595 | clear_thread_flag(TIF_UPROBE); | ||
596 | uprobe_notify_resume(regs); | ||
593 | } else { | 597 | } else { |
594 | clear_thread_flag(TIF_NOTIFY_RESUME); | 598 | clear_thread_flag(TIF_NOTIFY_RESUME); |
595 | tracehook_notify_resume(regs); | 599 | tracehook_notify_resume(regs); |
diff --git a/arch/arm/kernel/uprobes-arm.c b/arch/arm/kernel/uprobes-arm.c new file mode 100644 index 000000000000..d3b655ff17da --- /dev/null +++ b/arch/arm/kernel/uprobes-arm.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Rabin Vincent <rabin at rab.in> | ||
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 version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/types.h> | ||
11 | #include <linux/stddef.h> | ||
12 | #include <linux/wait.h> | ||
13 | #include <linux/uprobes.h> | ||
14 | #include <linux/module.h> | ||
15 | |||
16 | #include "probes.h" | ||
17 | #include "probes-arm.h" | ||
18 | #include "uprobes.h" | ||
19 | |||
20 | static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs) | ||
21 | { | ||
22 | probes_opcode_t insn = __mem_to_opcode_arm(*pinsn); | ||
23 | probes_opcode_t temp; | ||
24 | probes_opcode_t mask; | ||
25 | int freereg; | ||
26 | u32 free = 0xffff; | ||
27 | u32 regs; | ||
28 | |||
29 | for (regs = oregs; regs; regs >>= 4, insn >>= 4) { | ||
30 | if ((regs & 0xf) == REG_TYPE_NONE) | ||
31 | continue; | ||
32 | |||
33 | free &= ~(1 << (insn & 0xf)); | ||
34 | } | ||
35 | |||
36 | /* No PC, no problem */ | ||
37 | if (free & (1 << 15)) | ||
38 | return 15; | ||
39 | |||
40 | if (!free) | ||
41 | return -1; | ||
42 | |||
43 | /* | ||
44 | * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would | ||
45 | * pick LR instead of R1. | ||
46 | */ | ||
47 | freereg = free = fls(free) - 1; | ||
48 | |||
49 | temp = __mem_to_opcode_arm(*pinsn); | ||
50 | insn = temp; | ||
51 | regs = oregs; | ||
52 | mask = 0xf; | ||
53 | |||
54 | for (; regs; regs >>= 4, mask <<= 4, free <<= 4, temp >>= 4) { | ||
55 | if ((regs & 0xf) == REG_TYPE_NONE) | ||
56 | continue; | ||
57 | |||
58 | if ((temp & 0xf) != 15) | ||
59 | continue; | ||
60 | |||
61 | insn &= ~mask; | ||
62 | insn |= free & mask; | ||
63 | } | ||
64 | |||
65 | *pinsn = __opcode_to_mem_arm(insn); | ||
66 | return freereg; | ||
67 | } | ||
68 | |||
69 | static void uprobe_set_pc(struct arch_uprobe *auprobe, | ||
70 | struct arch_uprobe_task *autask, | ||
71 | struct pt_regs *regs) | ||
72 | { | ||
73 | u32 pcreg = auprobe->pcreg; | ||
74 | |||
75 | autask->backup = regs->uregs[pcreg]; | ||
76 | regs->uregs[pcreg] = regs->ARM_pc + 8; | ||
77 | } | ||
78 | |||
79 | static void uprobe_unset_pc(struct arch_uprobe *auprobe, | ||
80 | struct arch_uprobe_task *autask, | ||
81 | struct pt_regs *regs) | ||
82 | { | ||
83 | /* PC will be taken care of by common code */ | ||
84 | regs->uregs[auprobe->pcreg] = autask->backup; | ||
85 | } | ||
86 | |||
87 | static void uprobe_aluwrite_pc(struct arch_uprobe *auprobe, | ||
88 | struct arch_uprobe_task *autask, | ||
89 | struct pt_regs *regs) | ||
90 | { | ||
91 | u32 pcreg = auprobe->pcreg; | ||
92 | |||
93 | alu_write_pc(regs->uregs[pcreg], regs); | ||
94 | regs->uregs[pcreg] = autask->backup; | ||
95 | } | ||
96 | |||
97 | static void uprobe_write_pc(struct arch_uprobe *auprobe, | ||
98 | struct arch_uprobe_task *autask, | ||
99 | struct pt_regs *regs) | ||
100 | { | ||
101 | u32 pcreg = auprobe->pcreg; | ||
102 | |||
103 | load_write_pc(regs->uregs[pcreg], regs); | ||
104 | regs->uregs[pcreg] = autask->backup; | ||
105 | } | ||
106 | |||
107 | enum probes_insn | ||
108 | decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
109 | const struct decode_header *d) | ||
110 | { | ||
111 | struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, | ||
112 | asi); | ||
113 | struct decode_emulate *decode = (struct decode_emulate *) d; | ||
114 | u32 regs = decode->header.type_regs.bits >> DECODE_TYPE_BITS; | ||
115 | int reg; | ||
116 | |||
117 | reg = uprobes_substitute_pc(&auprobe->ixol[0], regs); | ||
118 | if (reg == 15) | ||
119 | return INSN_GOOD; | ||
120 | |||
121 | if (reg == -1) | ||
122 | return INSN_REJECTED; | ||
123 | |||
124 | auprobe->pcreg = reg; | ||
125 | auprobe->prehandler = uprobe_set_pc; | ||
126 | auprobe->posthandler = uprobe_unset_pc; | ||
127 | |||
128 | return INSN_GOOD; | ||
129 | } | ||
130 | |||
131 | enum probes_insn | ||
132 | decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
133 | const struct decode_header *d, bool alu) | ||
134 | { | ||
135 | struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, | ||
136 | asi); | ||
137 | enum probes_insn ret = decode_pc_ro(insn, asi, d); | ||
138 | |||
139 | if (((insn >> 12) & 0xf) == 15) | ||
140 | auprobe->posthandler = alu ? uprobe_aluwrite_pc | ||
141 | : uprobe_write_pc; | ||
142 | |||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | enum probes_insn | ||
147 | decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, | ||
148 | struct arch_probes_insn *asi, | ||
149 | const struct decode_header *d) | ||
150 | { | ||
151 | return decode_wb_pc(insn, asi, d, true); | ||
152 | } | ||
153 | |||
154 | enum probes_insn | ||
155 | decode_ldr(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
156 | const struct decode_header *d) | ||
157 | { | ||
158 | return decode_wb_pc(insn, asi, d, false); | ||
159 | } | ||
160 | |||
161 | enum probes_insn | ||
162 | uprobe_decode_ldmstm(probes_opcode_t insn, | ||
163 | struct arch_probes_insn *asi, | ||
164 | const struct decode_header *d) | ||
165 | { | ||
166 | struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, | ||
167 | asi); | ||
168 | unsigned reglist = insn & 0xffff; | ||
169 | int rn = (insn >> 16) & 0xf; | ||
170 | int lbit = insn & (1 << 20); | ||
171 | unsigned used = reglist | (1 << rn); | ||
172 | |||
173 | if (rn == 15) | ||
174 | return INSN_REJECTED; | ||
175 | |||
176 | if (!(used & (1 << 15))) | ||
177 | return INSN_GOOD; | ||
178 | |||
179 | if (used & (1 << 14)) | ||
180 | return INSN_REJECTED; | ||
181 | |||
182 | /* Use LR instead of PC */ | ||
183 | insn ^= 0xc000; | ||
184 | |||
185 | auprobe->pcreg = 14; | ||
186 | auprobe->ixol[0] = __opcode_to_mem_arm(insn); | ||
187 | |||
188 | auprobe->prehandler = uprobe_set_pc; | ||
189 | if (lbit) | ||
190 | auprobe->posthandler = uprobe_write_pc; | ||
191 | else | ||
192 | auprobe->posthandler = uprobe_unset_pc; | ||
193 | |||
194 | return INSN_GOOD; | ||
195 | } | ||
196 | |||
197 | const union decode_action uprobes_probes_actions[] = { | ||
198 | [PROBES_EMULATE_NONE] = {.handler = probes_simulate_nop}, | ||
199 | [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, | ||
200 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, | ||
201 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, | ||
202 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, | ||
203 | [PROBES_MRS] = {.handler = simulate_mrs}, | ||
204 | [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, | ||
205 | [PROBES_CLZ] = {.handler = probes_simulate_nop}, | ||
206 | [PROBES_SATURATING_ARITHMETIC] = {.handler = probes_simulate_nop}, | ||
207 | [PROBES_MUL1] = {.handler = probes_simulate_nop}, | ||
208 | [PROBES_MUL2] = {.handler = probes_simulate_nop}, | ||
209 | [PROBES_SWP] = {.handler = probes_simulate_nop}, | ||
210 | [PROBES_LDRSTRD] = {.decoder = decode_pc_ro}, | ||
211 | [PROBES_LOAD_EXTRA] = {.decoder = decode_pc_ro}, | ||
212 | [PROBES_LOAD] = {.decoder = decode_ldr}, | ||
213 | [PROBES_STORE_EXTRA] = {.decoder = decode_pc_ro}, | ||
214 | [PROBES_STORE] = {.decoder = decode_pc_ro}, | ||
215 | [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, | ||
216 | [PROBES_DATA_PROCESSING_REG] = { | ||
217 | .decoder = decode_rd12rn16rm0rs8_rwflags}, | ||
218 | [PROBES_DATA_PROCESSING_IMM] = { | ||
219 | .decoder = decode_rd12rn16rm0rs8_rwflags}, | ||
220 | [PROBES_MOV_HALFWORD] = {.handler = probes_simulate_nop}, | ||
221 | [PROBES_SEV] = {.handler = probes_simulate_nop}, | ||
222 | [PROBES_WFE] = {.handler = probes_simulate_nop}, | ||
223 | [PROBES_SATURATE] = {.handler = probes_simulate_nop}, | ||
224 | [PROBES_REV] = {.handler = probes_simulate_nop}, | ||
225 | [PROBES_MMI] = {.handler = probes_simulate_nop}, | ||
226 | [PROBES_PACK] = {.handler = probes_simulate_nop}, | ||
227 | [PROBES_EXTEND] = {.handler = probes_simulate_nop}, | ||
228 | [PROBES_EXTEND_ADD] = {.handler = probes_simulate_nop}, | ||
229 | [PROBES_MUL_ADD_LONG] = {.handler = probes_simulate_nop}, | ||
230 | [PROBES_MUL_ADD] = {.handler = probes_simulate_nop}, | ||
231 | [PROBES_BITFIELD] = {.handler = probes_simulate_nop}, | ||
232 | [PROBES_BRANCH] = {.handler = simulate_bbl}, | ||
233 | [PROBES_LDMSTM] = {.decoder = uprobe_decode_ldmstm} | ||
234 | }; | ||
diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/kernel/uprobes.c new file mode 100644 index 000000000000..f9bacee973bf --- /dev/null +++ b/arch/arm/kernel/uprobes.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Rabin Vincent <rabin at rab.in> | ||
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 version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/stddef.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/highmem.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/uprobes.h> | ||
15 | #include <linux/notifier.h> | ||
16 | |||
17 | #include <asm/opcodes.h> | ||
18 | #include <asm/traps.h> | ||
19 | |||
20 | #include "probes.h" | ||
21 | #include "probes-arm.h" | ||
22 | #include "uprobes.h" | ||
23 | |||
24 | #define UPROBE_TRAP_NR UINT_MAX | ||
25 | |||
26 | bool is_swbp_insn(uprobe_opcode_t *insn) | ||
27 | { | ||
28 | return (__mem_to_opcode_arm(*insn) & 0x0fffffff) == | ||
29 | (UPROBE_SWBP_ARM_INSN & 0x0fffffff); | ||
30 | } | ||
31 | |||
32 | int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, | ||
33 | unsigned long vaddr) | ||
34 | { | ||
35 | return uprobe_write_opcode(mm, vaddr, | ||
36 | __opcode_to_mem_arm(auprobe->bpinsn)); | ||
37 | } | ||
38 | |||
39 | bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs) | ||
40 | { | ||
41 | if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) { | ||
42 | regs->ARM_pc += 4; | ||
43 | return true; | ||
44 | } | ||
45 | |||
46 | return false; | ||
47 | } | ||
48 | |||
49 | bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | ||
50 | { | ||
51 | probes_opcode_t opcode; | ||
52 | |||
53 | if (!auprobe->simulate) | ||
54 | return false; | ||
55 | |||
56 | opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn); | ||
57 | |||
58 | auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs); | ||
59 | |||
60 | return true; | ||
61 | } | ||
62 | |||
63 | unsigned long | ||
64 | arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, | ||
65 | struct pt_regs *regs) | ||
66 | { | ||
67 | unsigned long orig_ret_vaddr; | ||
68 | |||
69 | orig_ret_vaddr = regs->ARM_lr; | ||
70 | /* Replace the return addr with trampoline addr */ | ||
71 | regs->ARM_lr = trampoline_vaddr; | ||
72 | return orig_ret_vaddr; | ||
73 | } | ||
74 | |||
75 | int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, | ||
76 | unsigned long addr) | ||
77 | { | ||
78 | unsigned int insn; | ||
79 | unsigned int bpinsn; | ||
80 | enum probes_insn ret; | ||
81 | |||
82 | /* Thumb not yet support */ | ||
83 | if (addr & 0x3) | ||
84 | return -EINVAL; | ||
85 | |||
86 | insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn); | ||
87 | auprobe->ixol[0] = __opcode_to_mem_arm(insn); | ||
88 | auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); | ||
89 | |||
90 | ret = arm_probes_decode_insn(insn, &auprobe->asi, false, | ||
91 | uprobes_probes_actions); | ||
92 | switch (ret) { | ||
93 | case INSN_REJECTED: | ||
94 | return -EINVAL; | ||
95 | |||
96 | case INSN_GOOD_NO_SLOT: | ||
97 | auprobe->simulate = true; | ||
98 | break; | ||
99 | |||
100 | case INSN_GOOD: | ||
101 | default: | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff; | ||
106 | if (insn >= 0xe0000000) | ||
107 | bpinsn |= 0xe0000000; /* Unconditional instruction */ | ||
108 | else | ||
109 | bpinsn |= insn & 0xf0000000; /* Copy condition from insn */ | ||
110 | |||
111 | auprobe->bpinsn = bpinsn; | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | ||
117 | { | ||
118 | struct uprobe_task *utask = current->utask; | ||
119 | |||
120 | if (auprobe->prehandler) | ||
121 | auprobe->prehandler(auprobe, &utask->autask, regs); | ||
122 | |||
123 | utask->autask.saved_trap_no = current->thread.trap_no; | ||
124 | current->thread.trap_no = UPROBE_TRAP_NR; | ||
125 | regs->ARM_pc = utask->xol_vaddr; | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | ||
131 | { | ||
132 | struct uprobe_task *utask = current->utask; | ||
133 | |||
134 | WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR); | ||
135 | |||
136 | current->thread.trap_no = utask->autask.saved_trap_no; | ||
137 | regs->ARM_pc = utask->vaddr + 4; | ||
138 | |||
139 | if (auprobe->posthandler) | ||
140 | auprobe->posthandler(auprobe, &utask->autask, regs); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | bool arch_uprobe_xol_was_trapped(struct task_struct *t) | ||
146 | { | ||
147 | if (t->thread.trap_no != UPROBE_TRAP_NR) | ||
148 | return true; | ||
149 | |||
150 | return false; | ||
151 | } | ||
152 | |||
153 | void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | ||
154 | { | ||
155 | struct uprobe_task *utask = current->utask; | ||
156 | |||
157 | current->thread.trap_no = utask->autask.saved_trap_no; | ||
158 | instruction_pointer_set(regs, utask->vaddr); | ||
159 | } | ||
160 | |||
161 | int arch_uprobe_exception_notify(struct notifier_block *self, | ||
162 | unsigned long val, void *data) | ||
163 | { | ||
164 | return NOTIFY_DONE; | ||
165 | } | ||
166 | |||
167 | static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr) | ||
168 | { | ||
169 | unsigned long flags; | ||
170 | |||
171 | local_irq_save(flags); | ||
172 | instr &= 0x0fffffff; | ||
173 | if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff)) | ||
174 | uprobe_pre_sstep_notifier(regs); | ||
175 | else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff)) | ||
176 | uprobe_post_sstep_notifier(regs); | ||
177 | local_irq_restore(flags); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) | ||
183 | { | ||
184 | return instruction_pointer(regs); | ||
185 | } | ||
186 | |||
187 | static struct undef_hook uprobes_arm_break_hook = { | ||
188 | .instr_mask = 0x0fffffff, | ||
189 | .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff), | ||
190 | .cpsr_mask = MODE_MASK, | ||
191 | .cpsr_val = USR_MODE, | ||
192 | .fn = uprobe_trap_handler, | ||
193 | }; | ||
194 | |||
195 | static struct undef_hook uprobes_arm_ss_hook = { | ||
196 | .instr_mask = 0x0fffffff, | ||
197 | .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff), | ||
198 | .cpsr_mask = MODE_MASK, | ||
199 | .cpsr_val = USR_MODE, | ||
200 | .fn = uprobe_trap_handler, | ||
201 | }; | ||
202 | |||
203 | static int arch_uprobes_init(void) | ||
204 | { | ||
205 | register_undef_hook(&uprobes_arm_break_hook); | ||
206 | register_undef_hook(&uprobes_arm_ss_hook); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | device_initcall(arch_uprobes_init); | ||
diff --git a/arch/arm/kernel/uprobes.h b/arch/arm/kernel/uprobes.h new file mode 100644 index 000000000000..1d0c12dfbd03 --- /dev/null +++ b/arch/arm/kernel/uprobes.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Rabin Vincent <rabin at rab.in> | ||
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 version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef __ARM_KERNEL_UPROBES_H | ||
10 | #define __ARM_KERNEL_UPROBES_H | ||
11 | |||
12 | enum probes_insn uprobe_decode_ldmstm(probes_opcode_t insn, | ||
13 | struct arch_probes_insn *asi, | ||
14 | const struct decode_header *d); | ||
15 | |||
16 | enum probes_insn decode_ldr(probes_opcode_t insn, | ||
17 | struct arch_probes_insn *asi, | ||
18 | const struct decode_header *d); | ||
19 | |||
20 | enum probes_insn | ||
21 | decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, | ||
22 | struct arch_probes_insn *asi, | ||
23 | const struct decode_header *d); | ||
24 | |||
25 | enum probes_insn | ||
26 | decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
27 | const struct decode_header *d, bool alu); | ||
28 | |||
29 | enum probes_insn | ||
30 | decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi, | ||
31 | const struct decode_header *d); | ||
32 | |||
33 | extern const union decode_action uprobes_probes_actions[]; | ||
34 | |||
35 | #endif | ||
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1d8248ea5669..bd18bb8b2770 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -878,7 +878,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, | |||
878 | unsigned long cmd, | 878 | unsigned long cmd, |
879 | void *v) | 879 | void *v) |
880 | { | 880 | { |
881 | if (cmd == CPU_PM_EXIT) { | 881 | if (cmd == CPU_PM_EXIT && |
882 | __hyp_get_vectors() == hyp_default_vectors) { | ||
882 | cpu_init_hyp_mode(NULL); | 883 | cpu_init_hyp_mode(NULL); |
883 | return NOTIFY_OK; | 884 | return NOTIFY_OK; |
884 | } | 885 | } |
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S index ddc15539bad2..0d68d4073068 100644 --- a/arch/arm/kvm/interrupts.S +++ b/arch/arm/kvm/interrupts.S | |||
@@ -220,6 +220,10 @@ after_vfp_restore: | |||
220 | * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c). Return values are | 220 | * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c). Return values are |
221 | * passed in r0 and r1. | 221 | * passed in r0 and r1. |
222 | * | 222 | * |
223 | * A function pointer with a value of 0xffffffff has a special meaning, | ||
224 | * and is used to implement __hyp_get_vectors in the same way as in | ||
225 | * arch/arm/kernel/hyp_stub.S. | ||
226 | * | ||
223 | * The calling convention follows the standard AAPCS: | 227 | * The calling convention follows the standard AAPCS: |
224 | * r0 - r3: caller save | 228 | * r0 - r3: caller save |
225 | * r12: caller save | 229 | * r12: caller save |
@@ -363,6 +367,11 @@ hyp_hvc: | |||
363 | host_switch_to_hyp: | 367 | host_switch_to_hyp: |
364 | pop {r0, r1, r2} | 368 | pop {r0, r1, r2} |
365 | 369 | ||
370 | /* Check for __hyp_get_vectors */ | ||
371 | cmp r0, #-1 | ||
372 | mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR | ||
373 | beq 1f | ||
374 | |||
366 | push {lr} | 375 | push {lr} |
367 | mrs lr, SPSR | 376 | mrs lr, SPSR |
368 | push {lr} | 377 | push {lr} |
@@ -378,7 +387,7 @@ THUMB( orr lr, #1) | |||
378 | pop {lr} | 387 | pop {lr} |
379 | msr SPSR_csxf, lr | 388 | msr SPSR_csxf, lr |
380 | pop {lr} | 389 | pop {lr} |
381 | eret | 390 | 1: eret |
382 | 391 | ||
383 | guest_trap: | 392 | guest_trap: |
384 | load_vcpu @ Load VCPU pointer to r0 | 393 | load_vcpu @ Load VCPU pointer to r0 |
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index befcaf5d0574..ec419649320f 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile | |||
@@ -101,11 +101,9 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | |||
101 | obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o | 101 | obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o |
102 | obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o | 102 | obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o |
103 | 103 | ||
104 | ifeq ($(CONFIG_PM),y) | ||
105 | obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o | 104 | obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o |
106 | # i.MX6SL reuses i.MX6Q code | 105 | # i.MX6SL reuses i.MX6Q code |
107 | obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o | 106 | obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o |
108 | endif | ||
109 | 107 | ||
110 | # i.MX5 based machines | 108 | # i.MX5 based machines |
111 | obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o | 109 | obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o |
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 59c3b9b26bb4..baf439dc22d8 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h | |||
@@ -144,13 +144,11 @@ void imx6q_set_chicken_bit(void); | |||
144 | void imx_cpu_die(unsigned int cpu); | 144 | void imx_cpu_die(unsigned int cpu); |
145 | int imx_cpu_kill(unsigned int cpu); | 145 | int imx_cpu_kill(unsigned int cpu); |
146 | 146 | ||
147 | #ifdef CONFIG_PM | ||
148 | void imx6q_pm_init(void); | 147 | void imx6q_pm_init(void); |
149 | void imx6q_pm_set_ccm_base(void __iomem *base); | 148 | void imx6q_pm_set_ccm_base(void __iomem *base); |
149 | #ifdef CONFIG_PM | ||
150 | void imx5_pm_init(void); | 150 | void imx5_pm_init(void); |
151 | #else | 151 | #else |
152 | static inline void imx6q_pm_init(void) {} | ||
153 | static inline void imx6q_pm_set_ccm_base(void __iomem *base) {} | ||
154 | static inline void imx5_pm_init(void) {} | 152 | static inline void imx5_pm_init(void) {} |
155 | #endif | 153 | #endif |
156 | 154 | ||
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 91449c5cb70f..85089d821982 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c | |||
@@ -156,6 +156,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = { | |||
156 | .register_dev = 1, | 156 | .register_dev = 1, |
157 | .hmc_mode = 16, | 157 | .hmc_mode = 16, |
158 | .pins[0] = 6, | 158 | .pins[0] = 6, |
159 | .extcon = "tahvo-usb", | ||
159 | }; | 160 | }; |
160 | 161 | ||
161 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) | 162 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) |
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index e2ce4f8366a7..0af7ca02314d 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -50,6 +50,7 @@ config SOC_OMAP5 | |||
50 | bool "TI OMAP5" | 50 | bool "TI OMAP5" |
51 | depends on ARCH_MULTI_V7 | 51 | depends on ARCH_MULTI_V7 |
52 | select ARCH_OMAP2PLUS | 52 | select ARCH_OMAP2PLUS |
53 | select ARCH_HAS_OPP | ||
53 | select ARM_CPU_SUSPEND if PM | 54 | select ARM_CPU_SUSPEND if PM |
54 | select ARM_GIC | 55 | select ARM_GIC |
55 | select CPU_V7 | 56 | select CPU_V7 |
@@ -63,6 +64,7 @@ config SOC_AM33XX | |||
63 | bool "TI AM33XX" | 64 | bool "TI AM33XX" |
64 | depends on ARCH_MULTI_V7 | 65 | depends on ARCH_MULTI_V7 |
65 | select ARCH_OMAP2PLUS | 66 | select ARCH_OMAP2PLUS |
67 | select ARCH_HAS_OPP | ||
66 | select ARM_CPU_SUSPEND if PM | 68 | select ARM_CPU_SUSPEND if PM |
67 | select CPU_V7 | 69 | select CPU_V7 |
68 | select MULTI_IRQ_HANDLER | 70 | select MULTI_IRQ_HANDLER |
@@ -72,6 +74,7 @@ config SOC_AM43XX | |||
72 | depends on ARCH_MULTI_V7 | 74 | depends on ARCH_MULTI_V7 |
73 | select CPU_V7 | 75 | select CPU_V7 |
74 | select ARCH_OMAP2PLUS | 76 | select ARCH_OMAP2PLUS |
77 | select ARCH_HAS_OPP | ||
75 | select MULTI_IRQ_HANDLER | 78 | select MULTI_IRQ_HANDLER |
76 | select ARM_GIC | 79 | select ARM_GIC |
77 | select MACH_OMAP_GENERIC | 80 | select MACH_OMAP_GENERIC |
@@ -80,6 +83,7 @@ config SOC_DRA7XX | |||
80 | bool "TI DRA7XX" | 83 | bool "TI DRA7XX" |
81 | depends on ARCH_MULTI_V7 | 84 | depends on ARCH_MULTI_V7 |
82 | select ARCH_OMAP2PLUS | 85 | select ARCH_OMAP2PLUS |
86 | select ARCH_HAS_OPP | ||
83 | select ARM_CPU_SUSPEND if PM | 87 | select ARM_CPU_SUSPEND if PM |
84 | select ARM_GIC | 88 | select ARM_GIC |
85 | select CPU_V7 | 89 | select CPU_V7 |
@@ -268,9 +272,6 @@ config MACH_OMAP_3430SDP | |||
268 | default y | 272 | default y |
269 | select OMAP_PACKAGE_CBB | 273 | select OMAP_PACKAGE_CBB |
270 | 274 | ||
271 | config MACH_NOKIA_N800 | ||
272 | bool | ||
273 | |||
274 | config MACH_NOKIA_N810 | 275 | config MACH_NOKIA_N810 |
275 | bool | 276 | bool |
276 | 277 | ||
@@ -281,7 +282,6 @@ config MACH_NOKIA_N8X0 | |||
281 | bool "Nokia N800/N810" | 282 | bool "Nokia N800/N810" |
282 | depends on SOC_OMAP2420 | 283 | depends on SOC_OMAP2420 |
283 | default y | 284 | default y |
284 | select MACH_NOKIA_N800 | ||
285 | select MACH_NOKIA_N810 | 285 | select MACH_NOKIA_N810 |
286 | select MACH_NOKIA_N810_WIMAX | 286 | select MACH_NOKIA_N810_WIMAX |
287 | select OMAP_PACKAGE_ZAC | 287 | select OMAP_PACKAGE_ZAC |
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index d24926e6340f..ab43755364f5 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -1339,7 +1339,7 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, | |||
1339 | of_property_read_bool(np, "gpmc,time-para-granularity"); | 1339 | of_property_read_bool(np, "gpmc,time-para-granularity"); |
1340 | } | 1340 | } |
1341 | 1341 | ||
1342 | #ifdef CONFIG_MTD_NAND | 1342 | #if IS_ENABLED(CONFIG_MTD_NAND) |
1343 | 1343 | ||
1344 | static const char * const nand_xfer_types[] = { | 1344 | static const char * const nand_xfer_types[] = { |
1345 | [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", | 1345 | [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", |
@@ -1429,7 +1429,7 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, | |||
1429 | } | 1429 | } |
1430 | #endif | 1430 | #endif |
1431 | 1431 | ||
1432 | #ifdef CONFIG_MTD_ONENAND | 1432 | #if IS_ENABLED(CONFIG_MTD_ONENAND) |
1433 | static int gpmc_probe_onenand_child(struct platform_device *pdev, | 1433 | static int gpmc_probe_onenand_child(struct platform_device *pdev, |
1434 | struct device_node *child) | 1434 | struct device_node *child) |
1435 | { | 1435 | { |
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index d408b15b4fbf..af432b191255 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c | |||
@@ -179,15 +179,6 @@ static struct map_desc omap34xx_io_desc[] __initdata = { | |||
179 | .length = L4_EMU_34XX_SIZE, | 179 | .length = L4_EMU_34XX_SIZE, |
180 | .type = MT_DEVICE | 180 | .type = MT_DEVICE |
181 | }, | 181 | }, |
182 | #if defined(CONFIG_DEBUG_LL) && \ | ||
183 | (defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3)) | ||
184 | { | ||
185 | .virtual = ZOOM_UART_VIRT, | ||
186 | .pfn = __phys_to_pfn(ZOOM_UART_BASE), | ||
187 | .length = SZ_1M, | ||
188 | .type = MT_DEVICE | ||
189 | }, | ||
190 | #endif | ||
191 | }; | 182 | }; |
192 | #endif | 183 | #endif |
193 | 184 | ||
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index f70583fee59f..29997bde277d 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/mtd/physmap.h> | 38 | #include <linux/mtd/physmap.h> |
39 | #include <linux/usb/gpio_vbus.h> | 39 | #include <linux/usb/gpio_vbus.h> |
40 | #include <linux/reboot.h> | 40 | #include <linux/reboot.h> |
41 | #include <linux/regulator/fixed.h> | ||
41 | #include <linux/regulator/max1586.h> | 42 | #include <linux/regulator/max1586.h> |
42 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
43 | #include <linux/i2c/pxa-i2c.h> | 44 | #include <linux/i2c/pxa-i2c.h> |
@@ -714,6 +715,10 @@ static struct gpio global_gpios[] = { | |||
714 | { GPIO56_MT9M111_nOE, GPIOF_OUT_INIT_LOW, "Camera nOE" }, | 715 | { GPIO56_MT9M111_nOE, GPIOF_OUT_INIT_LOW, "Camera nOE" }, |
715 | }; | 716 | }; |
716 | 717 | ||
718 | static struct regulator_consumer_supply fixed_5v0_consumers[] = { | ||
719 | REGULATOR_SUPPLY("power", "pwm-backlight"), | ||
720 | }; | ||
721 | |||
717 | static void __init mioa701_machine_init(void) | 722 | static void __init mioa701_machine_init(void) |
718 | { | 723 | { |
719 | int rc; | 724 | int rc; |
@@ -753,6 +758,10 @@ static void __init mioa701_machine_init(void) | |||
753 | pxa_set_i2c_info(&i2c_pdata); | 758 | pxa_set_i2c_info(&i2c_pdata); |
754 | pxa27x_set_i2c_power_info(NULL); | 759 | pxa27x_set_i2c_power_info(NULL); |
755 | pxa_set_camera_info(&mioa701_pxacamera_platform_data); | 760 | pxa_set_camera_info(&mioa701_pxacamera_platform_data); |
761 | |||
762 | regulator_register_always_on(0, "fixed-5.0V", fixed_5v0_consumers, | ||
763 | ARRAY_SIZE(fixed_5v0_consumers), | ||
764 | 5000000); | ||
756 | } | 765 | } |
757 | 766 | ||
758 | static void mioa701_machine_exit(void) | 767 | static void mioa701_machine_exit(void) |
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 4ae0286b468d..f55b05a29b55 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/cpu_pm.h> | 24 | #include <linux/cpu_pm.h> |
25 | #include <linux/suspend.h> | 25 | #include <linux/suspend.h> |
26 | #include <linux/err.h> | 26 | #include <linux/err.h> |
27 | #include <linux/slab.h> | ||
27 | #include <linux/clk/tegra.h> | 28 | #include <linux/clk/tegra.h> |
28 | 29 | ||
29 | #include <asm/smp_plat.h> | 30 | #include <asm/smp_plat.h> |
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 303a285d80fd..6191603379e1 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c | |||
@@ -73,10 +73,20 @@ u32 tegra_uart_config[3] = { | |||
73 | static void __init tegra_init_cache(void) | 73 | static void __init tegra_init_cache(void) |
74 | { | 74 | { |
75 | #ifdef CONFIG_CACHE_L2X0 | 75 | #ifdef CONFIG_CACHE_L2X0 |
76 | static const struct of_device_id pl310_ids[] __initconst = { | ||
77 | { .compatible = "arm,pl310-cache", }, | ||
78 | {} | ||
79 | }; | ||
80 | |||
81 | struct device_node *np; | ||
76 | int ret; | 82 | int ret; |
77 | void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; | 83 | void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; |
78 | u32 aux_ctrl, cache_type; | 84 | u32 aux_ctrl, cache_type; |
79 | 85 | ||
86 | np = of_find_matching_node(NULL, pl310_ids); | ||
87 | if (!np) | ||
88 | return; | ||
89 | |||
80 | cache_type = readl(p + L2X0_CACHE_TYPE); | 90 | cache_type = readl(p + L2X0_CACHE_TYPE); |
81 | aux_ctrl = (cache_type & 0x700) << (17-8); | 91 | aux_ctrl = (cache_type & 0x700) << (17-8); |
82 | aux_ctrl |= 0x7C400001; | 92 | aux_ctrl |= 0x7C400001; |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 1a77450e728a..11b3914660d2 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -1358,7 +1358,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, | |||
1358 | *handle = DMA_ERROR_CODE; | 1358 | *handle = DMA_ERROR_CODE; |
1359 | size = PAGE_ALIGN(size); | 1359 | size = PAGE_ALIGN(size); |
1360 | 1360 | ||
1361 | if (gfp & GFP_ATOMIC) | 1361 | if (!(gfp & __GFP_WAIT)) |
1362 | return __iommu_alloc_atomic(dev, size, handle); | 1362 | return __iommu_alloc_atomic(dev, size, handle); |
1363 | 1363 | ||
1364 | /* | 1364 | /* |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index d5a982d15a88..7ea641b7aa7d 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -38,6 +38,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt) | |||
38 | 38 | ||
39 | struct mem_type { | 39 | struct mem_type { |
40 | pteval_t prot_pte; | 40 | pteval_t prot_pte; |
41 | pteval_t prot_pte_s2; | ||
41 | pmdval_t prot_l1; | 42 | pmdval_t prot_l1; |
42 | pmdval_t prot_sect; | 43 | pmdval_t prot_sect; |
43 | unsigned int domain; | 44 | unsigned int domain; |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4f08c133cc25..a623cb3ad012 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -232,12 +232,16 @@ __setup("noalign", noalign_setup); | |||
232 | #endif /* ifdef CONFIG_CPU_CP15 / else */ | 232 | #endif /* ifdef CONFIG_CPU_CP15 / else */ |
233 | 233 | ||
234 | #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN | 234 | #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN |
235 | #define PROT_PTE_S2_DEVICE PROT_PTE_DEVICE | ||
235 | #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE | 236 | #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE |
236 | 237 | ||
237 | static struct mem_type mem_types[] = { | 238 | static struct mem_type mem_types[] = { |
238 | [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ | 239 | [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ |
239 | .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | | 240 | .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | |
240 | L_PTE_SHARED, | 241 | L_PTE_SHARED, |
242 | .prot_pte_s2 = s2_policy(PROT_PTE_S2_DEVICE) | | ||
243 | s2_policy(L_PTE_S2_MT_DEV_SHARED) | | ||
244 | L_PTE_SHARED, | ||
241 | .prot_l1 = PMD_TYPE_TABLE, | 245 | .prot_l1 = PMD_TYPE_TABLE, |
242 | .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S, | 246 | .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S, |
243 | .domain = DOMAIN_IO, | 247 | .domain = DOMAIN_IO, |
@@ -508,7 +512,8 @@ static void __init build_mem_type_table(void) | |||
508 | cp = &cache_policies[cachepolicy]; | 512 | cp = &cache_policies[cachepolicy]; |
509 | vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; | 513 | vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; |
510 | s2_pgprot = cp->pte_s2; | 514 | s2_pgprot = cp->pte_s2; |
511 | hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; | 515 | hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte; |
516 | s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2; | ||
512 | 517 | ||
513 | /* | 518 | /* |
514 | * ARMv6 and above have extended page tables. | 519 | * ARMv6 and above have extended page tables. |
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 45dc29f85d56..32b3558321c4 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S | |||
@@ -208,7 +208,6 @@ __v6_setup: | |||
208 | mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache | 208 | mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache |
209 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | 209 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache |
210 | mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache | 210 | mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache |
211 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
212 | #ifdef CONFIG_MMU | 211 | #ifdef CONFIG_MMU |
213 | mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs | 212 | mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs |
214 | mcr p15, 0, r0, c2, c0, 2 @ TTB control register | 213 | mcr p15, 0, r0, c2, c0, 2 @ TTB control register |
@@ -218,6 +217,8 @@ __v6_setup: | |||
218 | ALT_UP(orr r8, r8, #TTB_FLAGS_UP) | 217 | ALT_UP(orr r8, r8, #TTB_FLAGS_UP) |
219 | mcr p15, 0, r8, c2, c0, 1 @ load TTB1 | 218 | mcr p15, 0, r8, c2, c0, 1 @ load TTB1 |
220 | #endif /* CONFIG_MMU */ | 219 | #endif /* CONFIG_MMU */ |
220 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer and | ||
221 | @ complete invalidations | ||
221 | adr r5, v6_crval | 222 | adr r5, v6_crval |
222 | ldmia r5, {r5, r6} | 223 | ldmia r5, {r5, r6} |
223 | ARM_BE8(orr r6, r6, #1 << 25) @ big-endian page tables | 224 | ARM_BE8(orr r6, r6, #1 << 25) @ big-endian page tables |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index bd1781979a39..74f6033e76dd 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -351,7 +351,6 @@ __v7_setup: | |||
351 | 351 | ||
352 | 4: mov r10, #0 | 352 | 4: mov r10, #0 |
353 | mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate | 353 | mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate |
354 | dsb | ||
355 | #ifdef CONFIG_MMU | 354 | #ifdef CONFIG_MMU |
356 | mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs | 355 | mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs |
357 | v7_ttb_setup r10, r4, r8, r5 @ TTBCR, TTBRx setup | 356 | v7_ttb_setup r10, r4, r8, r5 @ TTBCR, TTBRx setup |
@@ -360,6 +359,7 @@ __v7_setup: | |||
360 | mcr p15, 0, r5, c10, c2, 0 @ write PRRR | 359 | mcr p15, 0, r5, c10, c2, 0 @ write PRRR |
361 | mcr p15, 0, r6, c10, c2, 1 @ write NMRR | 360 | mcr p15, 0, r6, c10, c2, 1 @ write NMRR |
362 | #endif | 361 | #endif |
362 | dsb @ Complete invalidations | ||
363 | #ifndef CONFIG_ARM_THUMBEE | 363 | #ifndef CONFIG_ARM_THUMBEE |
364 | mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE | 364 | mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE |
365 | and r0, r0, #(0xf << 12) @ ThumbEE enabled field | 365 | and r0, r0, #(0xf << 12) @ ThumbEE enabled field |