summaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/DocBook/media/Makefile4
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt4
-rw-r--r--Documentation/devicetree/bindings/clock/ti/apll.txt24
-rw-r--r--Documentation/devicetree/bindings/clock/ti/dpll.txt10
-rw-r--r--Documentation/devicetree/bindings/clock/ti/dra7-atl.txt96
-rw-r--r--Documentation/devicetree/bindings/clock/ti/gate.txt29
-rw-r--r--Documentation/devicetree/bindings/clock/ti/interface.txt2
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-rk3x.txt42
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt41
-rw-r--r--Documentation/hwmon/shtc143
-rw-r--r--Documentation/kbuild/makefiles.txt2
-rw-r--r--Documentation/kernel-parameters.txt14
-rw-r--r--Documentation/thermal/nouveau_thermal7
-rw-r--r--Documentation/vDSO/parse_vdso.c67
-rw-r--r--Documentation/vDSO/vdso_standalone_test_x86.c128
-rw-r--r--Documentation/vDSO/vdso_test.c107
16 files changed, 491 insertions, 129 deletions
diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile
index 1d27f0a1abd..639e7485796 100644
--- a/Documentation/DocBook/media/Makefile
+++ b/Documentation/DocBook/media/Makefile
@@ -202,8 +202,8 @@ $(MEDIA_OBJ_DIR)/%: $(MEDIA_SRC_DIR)/%.b64
$(MEDIA_OBJ_DIR)/v4l2.xml: $(OBJIMGFILES)
@$($(quiet)gen_xml)
- @(ln -sf $(MEDIA_SRC_DIR)/v4l/*xml $(MEDIA_OBJ_DIR)/)
- @(ln -sf $(MEDIA_SRC_DIR)/dvb/*xml $(MEDIA_OBJ_DIR)/)
+ @(ln -sf `cd $(MEDIA_SRC_DIR) && /bin/pwd`/v4l/*xml $(MEDIA_OBJ_DIR)/)
+ @(ln -sf `cd $(MEDIA_SRC_DIR) && /bin/pwd`/dvb/*xml $(MEDIA_OBJ_DIR)/)
$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/uapi/linux/videodev2.h $(MEDIA_OBJ_DIR)/v4l2.xml
@$($(quiet)gen_xml)
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index a5160d8cbb5..b9ec668bfe6 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -20,12 +20,15 @@ Required properties:
"allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
+ "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
+ "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
"allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
+ "allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
@@ -41,6 +44,7 @@ Required properties:
"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
"allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
"allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
+ "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31
Required properties for all clocks:
- reg : shall be the control register address for the clock.
diff --git a/Documentation/devicetree/bindings/clock/ti/apll.txt b/Documentation/devicetree/bindings/clock/ti/apll.txt
index 7faf5a68b3b..ade4dd4c30f 100644
--- a/Documentation/devicetree/bindings/clock/ti/apll.txt
+++ b/Documentation/devicetree/bindings/clock/ti/apll.txt
@@ -14,18 +14,32 @@ a subtype of a DPLL [2], although a simplified one at that.
[2] Documentation/devicetree/bindings/clock/ti/dpll.txt
Required properties:
-- compatible : shall be "ti,dra7-apll-clock"
+- compatible : shall be "ti,dra7-apll-clock" or "ti,omap2-apll-clock"
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : link phandles of parent clocks (clk-ref and clk-bypass)
- reg : address and length of the register set for controlling the APLL.
It contains the information of registers in the following order:
- "control" - contains the control register base address
- "idlest" - contains the idlest register base address
+ "control" - contains the control register offset
+ "idlest" - contains the idlest register offset
+ "autoidle" - contains the autoidle register offset (OMAP2 only)
+- ti,clock-frequency : static clock frequency for the clock (OMAP2 only)
+- ti,idlest-shift : bit-shift for the idlest field (OMAP2 only)
+- ti,bit-shift : bit-shift for enable and autoidle fields (OMAP2 only)
Examples:
- apll_pcie_ck: apll_pcie_ck@4a008200 {
+ apll_pcie_ck: apll_pcie_ck {
#clock-cells = <0>;
clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
- reg = <0x4a00821c 0x4>, <0x4a008220 0x4>;
+ reg = <0x021c>, <0x0220>;
compatible = "ti,dra7-apll-clock";
};
+
+ apll96_ck: apll96_ck {
+ #clock-cells = <0>;
+ compatible = "ti,omap2-apll-clock";
+ clocks = <&sys_ck>;
+ ti,bit-shift = <2>;
+ ti,idlest-shift = <8>;
+ ti,clock-frequency = <96000000>;
+ reg = <0x0500>, <0x0530>, <0x0520>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/ti/dpll.txt b/Documentation/devicetree/bindings/clock/ti/dpll.txt
index 30bfdb7c9f1..df57009ff8e 100644
--- a/Documentation/devicetree/bindings/clock/ti/dpll.txt
+++ b/Documentation/devicetree/bindings/clock/ti/dpll.txt
@@ -24,12 +24,14 @@ Required properties:
"ti,omap4-dpll-core-clock",
"ti,omap4-dpll-m4xen-clock",
"ti,omap4-dpll-j-type-clock",
+ "ti,omap5-mpu-dpll-clock",
"ti,am3-dpll-no-gate-clock",
"ti,am3-dpll-j-type-clock",
"ti,am3-dpll-no-gate-j-type-clock",
"ti,am3-dpll-clock",
"ti,am3-dpll-core-clock",
"ti,am3-dpll-x2-clock",
+ "ti,omap2-dpll-core-clock",
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : link phandles of parent clocks, first entry lists reference clock
@@ -41,6 +43,7 @@ Required properties:
"mult-div1" - contains the multiplier / divider register base address
"autoidle" - contains the autoidle register base address (optional)
ti,am3-* dpll types do not have autoidle register
+ ti,omap2-* dpll type does not support idlest / autoidle registers
Optional properties:
- DPLL mode setting - defining any one or more of the following overrides
@@ -73,3 +76,10 @@ Examples:
clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
reg = <0x90>, <0x5c>, <0x68>;
};
+
+ dpll_ck: dpll_ck {
+ #clock-cells = <0>;
+ compatible = "ti,omap2-dpll-core-clock";
+ clocks = <&sys_ck>, <&sys_ck>;
+ reg = <0x0500>, <0x0540>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt b/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt
new file mode 100644
index 00000000000..585e8c191f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt
@@ -0,0 +1,96 @@
+Device Tree Clock bindings for ATL (Audio Tracking Logic) of DRA7 SoC.
+
+The ATL IP is used to generate clock to be used to synchronize baseband and
+audio codec. A single ATL IP provides four ATL clock instances sharing the same
+functional clock but can be configured to provide different clocks.
+ATL can maintain a clock averages to some desired frequency based on the bws/aws
+signals - can compensate the drift between the two ws signal.
+
+In order to provide the support for ATL and it's output clocks (which can be used
+internally within the SoC or external components) two sets of bindings is needed:
+
+Clock tree binding:
+This binding uses the common clock binding[1].
+To be able to integrate the ATL clocks with DT clock tree.
+Provides ccf level representation of the ATL clocks to be used by drivers.
+Since the clock instances are part of a single IP this binding is used as a node
+for the DT clock tree, the IP driver is needed to handle the actual configuration
+of the IP.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,dra7-atl-clock"
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles to functional clock of ATL
+
+Binding for the IP driver:
+This binding is used to configure the IP driver which is going to handle the
+configuration of the IP for the ATL clock instances.
+
+Required properties:
+- compatible : shall be "ti,dra7-atl"
+- reg : base address for the ATL IP
+- ti,provided-clocks : List of phandles to the clocks associated with the ATL
+- clocks : link phandles to functional clock of ATL
+- clock-names : Shall be set to "fck"
+- ti,hwmods : Shall be set to "atl"
+
+Optional properties:
+Configuration of ATL instances:
+- atl{0/1/2/3} {
+ - bws : Baseband word select signal selection
+ - aws : Audio word select signal selection
+};
+
+For valid word select signals, see the dt-bindings/clk/ti-dra7-atl.h include
+file.
+
+Examples:
+/* clock bindings for atl provided clocks */
+atl_clkin0_ck: atl_clkin0_ck {
+ #clock-cells = <0>;
+ compatible = "ti,dra7-atl-clock";
+ clocks = <&atl_gfclk_mux>;
+};
+
+atl_clkin1_ck: atl_clkin1_ck {
+ #clock-cells = <0>;
+ compatible = "ti,dra7-atl-clock";
+ clocks = <&atl_gfclk_mux>;
+};
+
+atl_clkin2_ck: atl_clkin2_ck {
+ #clock-cells = <0>;
+ compatible = "ti,dra7-atl-clock";
+ clocks = <&atl_gfclk_mux>;
+};
+
+atl_clkin3_ck: atl_clkin3_ck {
+ #clock-cells = <0>;
+ compatible = "ti,dra7-atl-clock";
+ clocks = <&atl_gfclk_mux>;
+};
+
+/* binding for the IP */
+atl: atl@4843c000 {
+ compatible = "ti,dra7-atl";
+ reg = <0x4843c000 0x3ff>;
+ ti,hwmods = "atl";
+ ti,provided-clocks = <&atl_clkin0_ck>, <&atl_clkin1_ck>,
+ <&atl_clkin2_ck>, <&atl_clkin3_ck>;
+ clocks = <&atl_gfclk_mux>;
+ clock-names = "fck";
+ status = "disabled";
+};
+
+#include <dt-bindings/clk/ti-dra7-atl.h>
+
+&atl {
+ status = "okay";
+
+ atl2 {
+ bws = <DRA7_ATL_WS_MCASP2_FSX>;
+ aws = <DRA7_ATL_WS_MCASP3_FSX>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/clock/ti/gate.txt b/Documentation/devicetree/bindings/clock/ti/gate.txt
index 125281aaa4c..03f8fdee62a 100644
--- a/Documentation/devicetree/bindings/clock/ti/gate.txt
+++ b/Documentation/devicetree/bindings/clock/ti/gate.txt
@@ -25,6 +25,11 @@ Required properties:
to map clockdomains properly
"ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling,
required for a hardware errata
+ "ti,composite-gate-clock" - composite gate clock, to be part of composite
+ clock
+ "ti,composite-no-wait-gate-clock" - composite gate clock that does not wait
+ for clock to be active before returning
+ from clk_enable()
- #clock-cells : from common clock binding; shall be set to 0
- clocks : link to phandle of parent clock
- reg : offset for register controlling adjustable gate, not needed for
@@ -41,7 +46,7 @@ Examples:
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&core_96m_fck>;
- reg = <0x48004a00 0x4>;
+ reg = <0x0a00>;
ti,bit-shift = <25>;
};
@@ -57,7 +62,7 @@ Examples:
#clock-cells = <0>;
compatible = "ti,dss-gate-clock";
clocks = <&dpll4_m4x2_ck>;
- reg = <0x48004e00 0x4>;
+ reg = <0x0e00>;
ti,bit-shift = <0>;
};
@@ -65,7 +70,7 @@ Examples:
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&ipss_ick>;
- reg = <0x4800259c 0x4>;
+ reg = <0x059c>;
ti,bit-shift = <1>;
};
@@ -80,6 +85,22 @@ Examples:
compatible = "ti,hsdiv-gate-clock";
clocks = <&dpll4_m2x2_mul_ck>;
ti,bit-shift = <0x1b>;
- reg = <0x48004d00 0x4>;
+ reg = <0x0d00>;
ti,set-bit-to-disable;
};
+
+ vlynq_gate_fck: vlynq_gate_fck {
+ #clock-cells = <0>;
+ compatible = "ti,composite-gate-clock";
+ clocks = <&core_ck>;
+ ti,bit-shift = <3>;
+ reg = <0x0200>;
+ };
+
+ sys_clkout2_src_gate: sys_clkout2_src_gate {
+ #clock-cells = <0>;
+ compatible = "ti,composite-no-wait-gate-clock";
+ clocks = <&core_ck>;
+ ti,bit-shift = <15>;
+ reg = <0x0070>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt
index 064e8caccac..3111a409fea 100644
--- a/Documentation/devicetree/bindings/clock/ti/interface.txt
+++ b/Documentation/devicetree/bindings/clock/ti/interface.txt
@@ -21,6 +21,8 @@ Required properties:
"ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling
"ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling
"ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling
+ "ti,omap2430-interface-clock" - interface clock with OMAP2430 specific HW
+ handling
- #clock-cells : from common clock binding; shall be set to 0
- clocks : link to phandle of parent clock
- reg : base address for the control register
diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
new file mode 100644
index 00000000000..dde6c22ce91
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
@@ -0,0 +1,42 @@
+* Rockchip RK3xxx I2C controller
+
+This driver interfaces with the native I2C controller present in Rockchip
+RK3xxx SoCs.
+
+Required properties :
+
+ - reg : Offset and length of the register set for the device
+ - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c" or
+ "rockchip,rk3288-i2c".
+ - interrupts : interrupt number
+ - clocks : parent clock
+
+Required on RK3066, RK3188 :
+
+ - rockchip,grf : the phandle of the syscon node for the general register
+ file (GRF)
+ - on those SoCs an alias with the correct I2C bus ID (bit offset in the GRF)
+ is also required.
+
+Optional properties :
+
+ - clock-frequency : SCL frequency to use (in Hz). If omitted, 100kHz is used.
+
+Example:
+
+aliases {
+ i2c0 = &i2c0;
+}
+
+i2c0: i2c@2002d000 {
+ compatible = "rockchip,rk3188-i2c";
+ reg = <0x2002d000 0x1000>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rockchip,grf = <&grf>;
+
+ clock-names = "i2c";
+ clocks = <&cru PCLK_I2C0>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt b/Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt
new file mode 100644
index 00000000000..6b765485af7
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt
@@ -0,0 +1,41 @@
+
+* Allwinner P2WI (Push/Pull 2 Wire Interface) controller
+
+Required properties :
+
+ - reg : Offset and length of the register set for the device.
+ - compatible : Should one of the following:
+ - "allwinner,sun6i-a31-p2wi"
+ - interrupts : The interrupt line connected to the P2WI peripheral.
+ - clocks : The gate clk connected to the P2WI peripheral.
+ - resets : The reset line connected to the P2WI peripheral.
+
+Optional properties :
+
+ - clock-frequency : Desired P2WI bus clock frequency in Hz. If not set the
+default frequency is 100kHz
+
+A P2WI may contain one child node encoding a P2WI slave device.
+
+Slave device properties:
+ Required properties:
+ - reg : the I2C slave address used during the initialization
+ process to switch from I2C to P2WI mode
+
+Example:
+
+ p2wi@01f03400 {
+ compatible = "allwinner,sun6i-a31-p2wi";
+ reg = <0x01f03400 0x400>;
+ interrupts = <0 39 4>;
+ clocks = <&apb0_gates 3>;
+ clock-frequency = <6000000>;
+ resets = <&apb0_rst 3>;
+
+ axp221: pmic@68 {
+ compatible = "x-powers,axp221";
+ reg = <0x68>;
+
+ /* ... */
+ };
+ };
diff --git a/Documentation/hwmon/shtc1 b/Documentation/hwmon/shtc1
new file mode 100644
index 00000000000..6b1e05458f0
--- /dev/null
+++ b/Documentation/hwmon/shtc1
@@ -0,0 +1,43 @@
+Kernel driver shtc1
+===================
+
+Supported chips:
+ * Sensirion SHTC1
+ Prefix: 'shtc1'
+ Addresses scanned: none
+ Datasheet: http://www.sensirion.com/file/datasheet_shtc1
+
+ * Sensirion SHTW1
+ Prefix: 'shtw1'
+ Addresses scanned: none
+ Datasheet: Not publicly available
+
+Author:
+ Johannes Winkelmann <johannes.winkelmann@sensirion.com>
+
+Description
+-----------
+
+This driver implements support for the Sensirion SHTC1 chip, a humidity and
+temperature sensor. Temperature is measured in degrees celsius, relative
+humidity is expressed as a percentage. Driver can be used as well for SHTW1
+chip, which has the same electrical interface.
+
+The device communicates with the I2C protocol. All sensors are set to I2C
+address 0x70. See Documentation/i2c/instantiating-devices for methods to
+instantiate the device.
+
+There are two options configurable by means of shtc1_platform_data:
+1. blocking (pull the I2C clock line down while performing the measurement) or
+ non-blocking mode. Blocking mode will guarantee the fastest result but
+ the I2C bus will be busy during that time. By default, non-blocking mode
+ is used. Make sure clock-stretching works properly on your device if you
+ want to use blocking mode.
+2. high or low accuracy. High accuracy is used by default and using it is
+ strongly recommended.
+
+sysfs-Interface
+---------------
+
+temp1_input - temperature input
+humidity1_input - humidity input
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index d567a7cc552..c600e2f44a6 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1171,7 +1171,7 @@ When kbuild executes, the following steps are followed (roughly):
obvious reason.
dtc
- Create flattend device tree blob object suitable for linking
+ Create flattened device tree blob object suitable for linking
into vmlinux. Device tree blobs linked into vmlinux are placed
in an init section in the image. Platform code *must* copy the
blob to non-init memory prior to calling unflatten_device_tree().
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 6eaa9cdb709..884904975d0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1474,6 +1474,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
js= [HW,JOY] Analog joystick
See Documentation/input/joystick.txt.
+ kaslr/nokaslr [X86]
+ Enable/disable kernel and module base offset ASLR
+ (Address Space Layout Randomization) if built into
+ the kernel. When CONFIG_HIBERNATION is selected,
+ kASLR is disabled by default. When kASLR is enabled,
+ hibernation will be disabled.
+
keepinitrd [HW,ARM]
kernelcore=nn[KMG] [KNL,X86,IA-64,PPC] This parameter
@@ -2110,10 +2117,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
noapic [SMP,APIC] Tells the kernel to not make use of any
IOAPICs that may be present in the system.
- nokaslr [X86]
- Disable kernel and module base offset ASLR (Address
- Space Layout Randomization) if built into the kernel.
-
noautogroup Disable scheduler automatic task group creation.
nobats [PPC] Do not use BATs for mapping kernel lowmem
@@ -2184,6 +2187,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
in certain environments such as networked servers or
real-time systems.
+ nohibernate [HIBERNATION] Disable hibernation and resume.
+
nohz= [KNL] Boottime enable/disable dynamic ticks
Valid arguments: on, off
Default: on
@@ -2980,6 +2985,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
noresume Don't check if there's a hibernation image
present during boot.
nocompress Don't compress/decompress hibernation images.
+ no Disable hibernation and resume.
retain_initrd [RAM] Keep initrd memory after extraction
diff --git a/Documentation/thermal/nouveau_thermal b/Documentation/thermal/nouveau_thermal
index efceb7828f5..60bc29357ac 100644
--- a/Documentation/thermal/nouveau_thermal
+++ b/Documentation/thermal/nouveau_thermal
@@ -4,7 +4,7 @@ Kernel driver nouveau
Supported chips:
* NV43+
-Authors: Martin Peres (mupuf) <martin.peres@labri.fr>
+Authors: Martin Peres (mupuf) <martin.peres@free.fr>
Description
---------
@@ -68,8 +68,9 @@ Your fan can be driven in different modes:
NOTE: Be sure to use the manual mode if you want to drive the fan speed manually
-NOTE2: Not all fan management modes may be supported on all chipsets. We are
-working on it.
+NOTE2: When operating in manual mode outside the vbios-defined
+[PWM_min, PWM_max] range, the reported fan speed (RPM) may not be accurate
+depending on your hardware.
Bug reports
---------
diff --git a/Documentation/vDSO/parse_vdso.c b/Documentation/vDSO/parse_vdso.c
index 85870208edc..1dbb4b87268 100644
--- a/Documentation/vDSO/parse_vdso.c
+++ b/Documentation/vDSO/parse_vdso.c
@@ -1,6 +1,6 @@
/*
* parse_vdso.c: Linux reference vDSO parser
- * Written by Andrew Lutomirski, 2011.
+ * Written by Andrew Lutomirski, 2011-2014.
*
* This code is meant to be linked in to various programs that run on Linux.
* As such, it is available with as few restrictions as possible. This file
@@ -11,13 +11,14 @@
* it starts a program. It works equally well in statically and dynamically
* linked binaries.
*
- * This code is tested on x86_64. In principle it should work on any 64-bit
+ * This code is tested on x86. In principle it should work on any
* architecture that has a vDSO.
*/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
+#include <limits.h>
#include <elf.h>
/*
@@ -45,11 +46,18 @@ extern void *vdso_sym(const char *version, const char *name);
/* And here's the code. */
-
-#ifndef __x86_64__
-# error Not yet ported to non-x86_64 architectures
+#ifndef ELF_BITS
+# if ULONG_MAX > 0xffffffffUL
+# define ELF_BITS 64
+# else
+# define ELF_BITS 32
+# endif
#endif
+#define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
+#define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
+#define ELF(x) ELF_BITS_XFORM(ELF_BITS, x)
+
static struct vdso_info
{
bool valid;
@@ -59,14 +67,14 @@ static struct vdso_info
uintptr_t load_offset; /* load_addr - recorded vaddr */
/* Symbol table */
- Elf64_Sym *symtab;
+ ELF(Sym) *symtab;
const char *symstrings;
- Elf64_Word *bucket, *chain;
- Elf64_Word nbucket, nchain;
+ ELF(Word) *bucket, *chain;
+ ELF(Word) nbucket, nchain;
/* Version table */
- Elf64_Versym *versym;
- Elf64_Verdef *verdef;
+ ELF(Versym) *versym;
+ ELF(Verdef) *verdef;
} vdso_info;
/* Straight from the ELF specification. */
@@ -92,9 +100,14 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base)
vdso_info.load_addr = base;
- Elf64_Ehdr *hdr = (Elf64_Ehdr*)base;
- Elf64_Phdr *pt = (Elf64_Phdr*)(vdso_info.load_addr + hdr->e_phoff);
- Elf64_Dyn *dyn = 0;
+ ELF(Ehdr) *hdr = (ELF(Ehdr)*)base;
+ if (hdr->e_ident[EI_CLASS] !=
+ (ELF_BITS == 32 ? ELFCLASS32 : ELFCLASS64)) {
+ return; /* Wrong ELF class -- check ELF_BITS */
+ }
+
+ ELF(Phdr) *pt = (ELF(Phdr)*)(vdso_info.load_addr + hdr->e_phoff);
+ ELF(Dyn) *dyn = 0;
/*
* We need two things from the segment table: the load offset
@@ -108,7 +121,7 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base)
+ (uintptr_t)pt[i].p_offset
- (uintptr_t)pt[i].p_vaddr;
} else if (pt[i].p_type == PT_DYNAMIC) {
- dyn = (Elf64_Dyn*)(base + pt[i].p_offset);
+ dyn = (ELF(Dyn)*)(base + pt[i].p_offset);
}
}
@@ -118,7 +131,7 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base)
/*
* Fish out the useful bits of the dynamic table.
*/
- Elf64_Word *hash = 0;
+ ELF(Word) *hash = 0;
vdso_info.symstrings = 0;
vdso_info.symtab = 0;
vdso_info.versym = 0;
@@ -131,22 +144,22 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base)
+ vdso_info.load_offset);
break;
case DT_SYMTAB:
- vdso_info.symtab = (Elf64_Sym *)
+ vdso_info.symtab = (ELF(Sym) *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
case DT_HASH:
- hash = (Elf64_Word *)
+ hash = (ELF(Word) *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
case DT_VERSYM:
- vdso_info.versym = (Elf64_Versym *)
+ vdso_info.versym = (ELF(Versym) *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
case DT_VERDEF:
- vdso_info.verdef = (Elf64_Verdef *)
+ vdso_info.verdef = (ELF(Verdef) *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
@@ -168,8 +181,8 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base)
vdso_info.valid = true;
}
-static bool vdso_match_version(Elf64_Versym ver,
- const char *name, Elf64_Word hash)
+static bool vdso_match_version(ELF(Versym) ver,
+ const char *name, ELF(Word) hash)
{
/*
* This is a helper function to check if the version indexed by
@@ -188,7 +201,7 @@ static bool vdso_match_version(Elf64_Versym ver,
/* First step: find the version definition */
ver &= 0x7fff; /* Apparently bit 15 means "hidden" */
- Elf64_Verdef *def = vdso_info.verdef;
+ ELF(Verdef) *def = vdso_info.verdef;
while(true) {
if ((def->vd_flags & VER_FLG_BASE) == 0
&& (def->vd_ndx & 0x7fff) == ver)
@@ -197,11 +210,11 @@ static bool vdso_match_version(Elf64_Versym ver,
if (def->vd_next == 0)
return false; /* No definition. */
- def = (Elf64_Verdef *)((char *)def + def->vd_next);
+ def = (ELF(Verdef) *)((char *)def + def->vd_next);
}
/* Now figure out whether it matches. */
- Elf64_Verdaux *aux = (Elf64_Verdaux*)((char *)def + def->vd_aux);
+ ELF(Verdaux) *aux = (ELF(Verdaux)*)((char *)def + def->vd_aux);
return def->vd_hash == hash
&& !strcmp(name, vdso_info.symstrings + aux->vda_name);
}
@@ -213,10 +226,10 @@ void *vdso_sym(const char *version, const char *name)
return 0;
ver_hash = elf_hash(version);
- Elf64_Word chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
+ ELF(Word) chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) {
- Elf64_Sym *sym = &vdso_info.symtab[chain];
+ ELF(Sym) *sym = &vdso_info.symtab[chain];
/* Check for a defined global or weak function w/ right name. */
if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
@@ -243,7 +256,7 @@ void *vdso_sym(const char *version, const char *name)
void vdso_init_from_auxv(void *auxv)
{
- Elf64_auxv_t *elf_auxv = auxv;
+ ELF(auxv_t) *elf_auxv = auxv;
for (int i = 0; elf_auxv[i].a_type != AT_NULL; i++)
{
if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
diff --git a/Documentation/vDSO/vdso_standalone_test_x86.c b/Documentation/vDSO/vdso_standalone_test_x86.c
new file mode 100644
index 00000000000..d46240265c5
--- /dev/null
+++ b/Documentation/vDSO/vdso_standalone_test_x86.c
@@ -0,0 +1,128 @@
+/*
+ * vdso_test.c: Sample code to test parse_vdso.c on x86
+ * Copyright (c) 2011-2014 Andy Lutomirski
+ * Subject to the GNU General Public License, version 2
+ *
+ * You can amuse yourself by compiling with:
+ * gcc -std=gnu99 -nostdlib
+ * -Os -fno-asynchronous-unwind-tables -flto -lgcc_s
+ * vdso_standalone_test_x86.c parse_vdso.c
+ * to generate a small binary. On x86_64, you can omit -lgcc_s
+ * if you want the binary to be completely standalone.
+ */
+
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdint.h>
+
+extern void *vdso_sym(const char *version, const char *name);
+extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
+extern void vdso_init_from_auxv(void *auxv);
+
+/* We need a libc functions... */
+int strcmp(const char *a, const char *b)
+{
+ /* This implementation is buggy: it never returns -1. */
+ while (*a || *b) {
+ if (*a != *b)
+ return 1;
+ if (*a == 0 || *b == 0)
+ return 1;
+ a++;
+ b++;
+ }
+
+ return 0;
+}
+
+/* ...and two syscalls. This is x86-specific. */
+static inline long x86_syscall3(long nr, long a0, long a1, long a2)
+{
+ long ret;
+#ifdef __x86_64__
+ asm volatile ("syscall" : "=a" (ret) : "a" (nr),
+ "D" (a0), "S" (a1), "d" (a2) :
+ "cc", "memory", "rcx",
+ "r8", "r9", "r10", "r11" );
+#else
+ asm volatile ("int $0x80" : "=a" (ret) : "a" (nr),
+ "b" (a0), "c" (a1), "d" (a2) :
+ "cc", "memory" );
+#endif
+ return ret;
+}
+
+static inline long linux_write(int fd, const void *data, size_t len)
+{
+ return x86_syscall3(__NR_write, fd, (long)data, (long)len);
+}
+
+static inline void linux_exit(int code)
+{
+ x86_syscall3(__NR_exit, code, 0, 0);
+}
+
+void to_base10(char *lastdig, uint64_t n)
+{
+ while (n) {
+ *lastdig = (n % 10) + '0';
+ n /= 10;
+ lastdig--;
+ }
+}
+
+__attribute__((externally_visible)) void c_main(void **stack)
+{
+ /* Parse the stack */
+ long argc = (long)*stack;
+ stack += argc + 2;
+
+ /* Now we're pointing at the environment. Skip it. */
+ while(*stack)
+ stack++;
+ stack++;
+
+ /* Now we're pointing at auxv. Initialize the vDSO parser. */
+ vdso_init_from_auxv((void *)stack);
+
+ /* Find gettimeofday. */
+ typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
+ gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
+
+ if (!gtod)
+ linux_exit(1);
+
+ struct timeval tv;
+ long ret = gtod(&tv, 0);
+
+ if (ret == 0) {
+ char buf[] = "The time is .000000\n";
+ to_base10(buf + 31, tv.tv_sec);
+ to_base10(buf + 38, tv.tv_usec);
+ linux_write(1, buf, sizeof(buf) - 1);
+ } else {
+ linux_exit(ret);
+ }
+
+ linux_exit(0);
+}
+
+/*
+ * This is the real entry point. It passes the initial stack into
+ * the C entry point.
+ */
+asm (
+ ".text\n"
+ ".global _start\n"
+ ".type _start,@function\n"
+ "_start:\n\t"
+#ifdef __x86_64__
+ "mov %rsp,%rdi\n\t"
+ "jmp c_main"
+#else
+ "push %esp\n\t"
+ "call c_main\n\t"
+ "int $3"
+#endif
+ );
diff --git a/Documentation/vDSO/vdso_test.c b/Documentation/vDSO/vdso_test.c
index fff633432df..8daeb7d7032 100644
--- a/Documentation/vDSO/vdso_test.c
+++ b/Documentation/vDSO/vdso_test.c
@@ -1,111 +1,52 @@
/*
- * vdso_test.c: Sample code to test parse_vdso.c on x86_64
- * Copyright (c) 2011 Andy Lutomirski
+ * vdso_test.c: Sample code to test parse_vdso.c
+ * Copyright (c) 2014 Andy Lutomirski
* Subject to the GNU General Public License, version 2
*
- * You can amuse yourself by compiling with:
- * gcc -std=gnu99 -nostdlib
- * -Os -fno-asynchronous-unwind-tables -flto
- * vdso_test.c parse_vdso.c -o vdso_test
- * to generate a small binary with no dependencies at all.
+ * Compile with:
+ * gcc -std=gnu99 vdso_test.c parse_vdso.c
+ *
+ * Tested on x86, 32-bit and 64-bit. It may work on other architectures, too.
*/
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <unistd.h>
#include <stdint.h>
+#include <elf.h>
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/time.h>
extern void *vdso_sym(const char *version, const char *name);
extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
extern void vdso_init_from_auxv(void *auxv);
-/* We need a libc functions... */
-int strcmp(const char *a, const char *b)
+int main(int argc, char **argv)
{
- /* This implementation is buggy: it never returns -1. */
- while (*a || *b) {
- if (*a != *b)
- return 1;
- if (*a == 0 || *b == 0)
- return 1;
- a++;
- b++;
+ unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
+ if (!sysinfo_ehdr) {
+ printf("AT_SYSINFO_EHDR is not present!\n");
+ return 0;
}
- return 0;
-}
-
-/* ...and two syscalls. This is x86_64-specific. */
-static inline long linux_write(int fd, const void *data, size_t len)
-{
-
- long ret;
- asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write),
- "D" (fd), "S" (data), "d" (len) :
- "cc", "memory", "rcx",
- "r8", "r9", "r10", "r11" );
- return ret;
-}
-
-static inline void linux_exit(int code)
-{
- asm volatile ("syscall" : : "a" (__NR_exit), "D" (code));
-}
-
-void to_base10(char *lastdig, uint64_t n)
-{
- while (n) {
- *lastdig = (n % 10) + '0';
- n /= 10;
- lastdig--;
- }
-}
-
-__attribute__((externally_visible)) void c_main(void **stack)
-{
- /* Parse the stack */
- long argc = (long)*stack;
- stack += argc + 2;
-
- /* Now we're pointing at the environment. Skip it. */
- while(*stack)
- stack++;
- stack++;
-
- /* Now we're pointing at auxv. Initialize the vDSO parser. */
- vdso_init_from_auxv((void *)stack);
+ vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
/* Find gettimeofday. */
typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
- if (!gtod)
- linux_exit(1);
+ if (!gtod) {
+ printf("Could not find __vdso_gettimeofday\n");
+ return 1;
+ }
struct timeval tv;
long ret = gtod(&tv, 0);
if (ret == 0) {
- char buf[] = "The time is .000000\n";
- to_base10(buf + 31, tv.tv_sec);
- to_base10(buf + 38, tv.tv_usec);
- linux_write(1, buf, sizeof(buf) - 1);
+ printf("The time is %lld.%06lld\n",
+ (long long)tv.tv_sec, (long long)tv.tv_usec);
} else {
- linux_exit(ret);
+ printf("__vdso_gettimeofday failed\n");
}
- linux_exit(0);
+ return 0;
}
-
-/*
- * This is the real entry point. It passes the initial stack into
- * the C entry point.
- */
-asm (
- ".text\n"
- ".global _start\n"
- ".type _start,@function\n"
- "_start:\n\t"
- "mov %rsp,%rdi\n\t"
- "jmp c_main"
- );