diff options
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/DocBook/media/Makefile | 4 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/clock/sunxi.txt | 4 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/clock/ti/apll.txt | 24 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/clock/ti/dpll.txt | 10 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/clock/ti/dra7-atl.txt | 96 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/clock/ti/gate.txt | 29 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/clock/ti/interface.txt | 2 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 42 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/i2c/i2c-sunxi-p2wi.txt | 41 | ||||
-rw-r--r-- | Documentation/hwmon/shtc1 | 43 | ||||
-rw-r--r-- | Documentation/kbuild/makefiles.txt | 2 | ||||
-rw-r--r-- | Documentation/kernel-parameters.txt | 14 | ||||
-rw-r--r-- | Documentation/thermal/nouveau_thermal | 7 | ||||
-rw-r--r-- | Documentation/vDSO/parse_vdso.c | 67 | ||||
-rw-r--r-- | Documentation/vDSO/vdso_standalone_test_x86.c | 128 | ||||
-rw-r--r-- | Documentation/vDSO/vdso_test.c | 107 |
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" - ); |