Merge remote-tracking branch 'origin/tmp-441e17f' into msm-kona

* origin/tmp-441e17f:
  ANDROID: xt_qtaguid: Remove unnecessary null checks to device's name
  ANDROID: qtaguid: Fix the UAF probelm with tag_ref_tree
  ANDROID: netfilter: xt_qtaguid: Fix 4.14 compilation
  ANDROID: netfilter: xt_qtaguid: Use sk_uid to replace uid get from socket file
  ANDROID: netfilter: xt_qtaguid: fix handling for cases where tunnels are used.
  ANDROID: netfilter: xt_qtaguid: handle properly request sockets
  ANDROID: netfilter: xt_qtaguid: Add untag hacks to inet_release function
  ANDROID: netfilter: xt_qtaguid: don't check if embedded arrays are NULL
  ANDROID: netfilter: xt_qtaguid: fix the deadlock when enable DDEBUG
  ANDROID: netfilter: xt_qtaguid: Don't show empty tag stats for unprivileged uids
  ANDROID: netfilter: xt_qtaguid: Fix panic caused by processing non-full socket.
  ANDROID: netfilter: xt_qtaguid: Fix panic caused by synack processing
  ANDROID: netfilter: xt_qtaguid: fix a race condition in if_tag_stat_update
  ANDROID: netfilter: xt_qtaguid: xt_socket: build fixes
  ANDROID: netfilter: xt_qtaguid: Use sk_callback_lock read locks before reading sk->sk_socket
  ANDROID: netfilter: xt_qtaguid/xt_socket: Build fixups
  ANDROID: netfilter: xt_qtaguid: Fix boot panic
  ANDROID: netfilter: xt_qtaguid: fix bad tcp_time_wait sock handling
  ANDROID: netfilter: xt_qtaguid: 3.10 fixes
  ANDROID: netfilter: xt_qtaguid: rate limit some of the printks
  ANDROID: netfilter: xt_qtaguid: Allow tracking loopback
  ANDROID: netfilter: xt_qtaguid: extend iface stat to report protocols
  ANDROID: netfilter: xt_qtaguid: remove AID_* dependency for access control
  ANDROID: netfilter: xt_qtaguid: Don't BUG_ON if create_if_tag_stat fails
  ANDROID: netfilter: xt_qtaguid: fix error exit that would keep a spinlock.
  ANDROID: netfilter: xt_qtaguid: report only uid tags to non-privileged processes
  ANDROID: netfilter: xt_qtaguid: start tracking iface rx/tx at low level
  ANDROID: netfilter: xt_qtaguid: fix ipv6 protocol lookup
  ANDROID: netfilter: xt_qtaguid: add qtaguid matching module
  RFC: ANDROID: net: ipv6: Flip FIB entries to fib6_info
  RFC: ANDROID: proc/uid: switch instantiate_t to d_splice_alias()
  RFC: ANDROID: fs: sdcardfs: Use inode iversion helpers
  RFC: ANDROID: net: ipv4: sysfs_net_ipv4: Fix TCP window size controlling knobs
  RFC: ANDROID: net: ipv4: tcp: Namespace-ify sysctl_tcp_default_init_rwnd
  ANDROID: x86_64_cuttlefish_defconfig: Enable lz4 compression for zram
  ANDROID: x86_64_cuttlefish_defconfig: Enable zram and zstd
  ANDROID: AVB error handler to invalidate vbmeta partition.
  ANDROID: remove android config fragments
  ANDROID: ftrace: fix function type mismatches
  ANDROID: sdcardfs: Check stacked filesystem depth
  ANDROID: verity: really fix android-verity Kconfig
  x86_64_cuttlefish_defconfig: Enable android-verity
  x86_64_cuttlefish_defconfig: enable verity cert
  ANDROID: android-verity: Fix broken parameter handling.
  ANDROID: android-verity: Make it work with newer kernels
  ANDROID: android-verity: Add API to verify signature with builtin keys.
  ANDROID: verity: fix android-verity Kconfig dependencies
  ANDROID: uid_sys_stats: Replace tasklist lock with RCU in uid_cputime_show
  ANDROID: mnt: Fix next_descendent
  ANDROID: Fix massive cpufreq_times memory leaks
  ANDROID: Reduce use of #ifdef CONFIG_CPU_FREQ_TIMES
  ANDROID: sdcardfs: fix potential crash when reserved_mb is not zero
  ANDROID: Add kconfig to make dm-verity check_at_most_once default enabled
  ANDROID: add extra free kbytes tunable
  ANDROID: x86_64_cuttlefish_defconfig: Enable F2FS
  ANDROID: Update x86_64_cuttlefish_defconfig
  ANDROID: proc: fix undefined behavior in proc_uid_base_readdir
  ANDROID: x86_64_cuttlefish_defconfig: Disable ORC unwinder.
  ANDROID: build: cuttlefish: Upgrade clang to newer version.
  ANDROID: build: cuttlefish: Upgrade clang to newer version.
  ANDROID: build: cuttlefish: Fix path to clang.
  ANDROID: sdcardfs: Don't d_drop in d_revalidate
  ANDROID: goldfish: drop CONFIG_INPUT_KEYCHORD
  ANDROID: build.config: enforce trace_printk check
  cfi: print target address on failure
  ANDROID: fs: gfs2: fix filler function type
  ANDROID: fs: exofs: fix filler function type
  ANDROID: fs: afs: fix filler function type
  ANDROID: fs: nfs: fix filler function type
  ANDROID: fs: fuse: fix filler function type mismatch
  ANDROID: mm: fix filler function type mismatch
  ANDROID: arch/arm64/crypto: fix CFI in SHA CE
  ANDROID: arm64: kvm: disable CFI
  ANDROID: arm64: mark kpti_install_ng_mappings as __nocfi
  ANDROID: arm64: disable CFI for cpu_replace_ttbr1
  ANDROID: kallsyms: strip the .cfi postfix from symbols with CONFIG_CFI_CLANG
  RFC: ANDROID: add support for clang Control Flow Integrity (CFI)
  ANDROID: sdcardfs: Set s_root to NULL after putting
  ANDROID: sdcardfs: d_make_root calls iput
  ANDROID: sdcardfs: Check for private data earlier
  FROMLIST: arm64: kvm: use -fno-jump-tables with clang
  ANDROID: Add build server config for cuttlefish.
  ANDROID: Add defconfig for cuttlefish.
  ANDROID: cpufreq: Add time_in_state to /proc/uid directories
  ANDROID: proc: Add /proc/uid directory
  ANDROID: cpufreq: times: track per-uid time in state
  ANDROID: cpufreq: track per-task time in state
  ANDROID: fuse: Add null terminator to path in canonical path to avoid issue
  ANDROID: sdcardfs: Fix sdcardfs to stop creating cases-sensitive duplicate entries.
  ANDROID: arm64: Image.gz-dtb build target depends on Image.gz
  ANDROID: sdcardfs: fix lock issue on 32 bit/SMP architectures
  ANDROID: uid_sys_stats: Copy task_struct comm field to bigger buffer
  ANDROID: sdcardfs: Set num in extension_details during make_item
  ANDROID: sdcardfs: Hold i_mutex for i_size_write
  ANDROID: sdcardfs: Protect set_top
  ANDROID: fsnotify: Notify lower fs of open
  ANDROID: sdcardfs: Use lower getattr times/size
  ANDROID: Revert "fs: unexport vfs_read and vfs_write"
  ANDROID: sdcardfs: port to 4.14
  ANDROID: fs: Export vfs_rmdir2
  ANDROID: mm: Export do_munmap
  ANDROID: fs: Export d_absolute_path
  ANDROID: fs: Export free_fs_struct and set_fs_pwd
  ANDROID: export security_path_chown
  ANDROID: sdcardfs: Add default_normal option
  ANDROID: Sdcardfs: Move gid derivation under flag
  ANDROID: sdcardfs: override credential for ioctl to lower fs
  ANDROID: sdcardfs: Remove unnecessary lock
  ANDROID: sdcardfs: use mount_nodev and fix a issue in sdcardfs_kill_sb
  ANDROID: sdcardfs: remove dead function open_flags_to_access_mode()
  ANDROID: sdcardfs: d_splice_alias can return error values
  ANDROID: sdcardfs: Check for NULL in revalidate
  ANDROID: sdcardfs: Move top to its own struct
  ANDROID: sdcardfs: fix sdcardfs_destroy_inode for the inode RCU approach
  ANDROID: sdcardfs: Don't iput if we didn't igrab
  ANDROID: sdcardfs: Call lower fs's revalidate
  ANDROID: sdcardfs: Avoid setting GIDs outside of valid ranges
  ANDROID: sdcardfs: Copy meta-data from lower inode
  ANDROID: sdcardfs: Use filesystem specific hash
  ANDROID: sdcardfs: Don't complain in fixup_lower_ownership
  ANDROID: sdcardfs: Don't do d_add for lower fs
  ANDROID: sdcardfs: ->iget fixes
  ANDROID: sdcardfs: Change cache GID value
  ANDROID: sdcardfs: Directly pass lower file for mmap
  ANDROID: sdcardfs: update module info
  ANDROID: sdcardfs: use d_splice_alias
  ANDROID: sdcardfs: add read_iter/write_iter opeations
  ANDROID: sdcardfs: fix ->llseek to update upper and lower offset
  ANDROID: sdcardfs: copy lower inode attributes in ->ioctl
  ANDROID: sdcardfs: remove unnecessary call to do_munmap
  ANDROID: sdcardfs: Fix style issues in macros
  ANDROID: sdcardfs: Use seq_puts over seq_printf
  ANDROID: sdcardfs: Use to kstrout
  ANDROID: sdcardfs: Use pr_[...] instead of printk
  ANDROID: sdcardfs: remove unneeded null check
  ANDROID: sdcardfs: Fix style issues with comments
  ANDROID: sdcardfs: Fix formatting
  ANDROID: sdcardfs: correct order of descriptors
  ANDROID: sdcardfs: Fix gid issue
  ANDROID: sdcardfs: Remove uninformative prints
  ANDROID: sdcardfs: move path_put outside of spinlock
  ANDROID: sdcardfs: Use case insensitive hash function
  ANDROID: sdcardfs: declare MODULE_ALIAS_FS
  ANDROID: sdcardfs: Get the blocksize from the lower fs
  ANDROID: sdcardfs: Use d_invalidate instead of drop_recurisve
  ANDROID: sdcardfs: Switch to internal case insensitive compare
  ANDROID: sdcardfs: Use spin_lock_nested
  ANDROID: sdcardfs: Replace get/put with d_lock
  ANDROID: sdcardfs: rate limit warning print
  ANDROID: sdcardfs: Fix case insensitive lookup
  ANDROID: sdcardfs: support direct-IO (DIO) operations
  ANDROID: sdcardfs: implement vm_ops->page_mkwrite
  ANDROID: sdcardfs: Don't bother deleting freelist
  ANDROID: sdcardfs: Add missing path_put
  ANDROID: sdcardfs: Fix incorrect hash
  ANDROID: sdcardfs: Switch strcasecmp for internal call
  ANDROID: sdcardfs: switch to full_name_hash and qstr
  ANDROID: sdcardfs: Add GID Derivation to sdcardfs
  ANDROID: sdcardfs: Remove redundant operation
  ANDROID: sdcardfs: add support for user permission isolation
  ANDROID: sdcardfs: Refactor configfs interface
  ANDROID: sdcardfs: Allow non-owners to touch
  ANDROID: sdcardfs: eliminate the offset argument to ->direct_IO
  ANDROID: sdcardfs: make it use new .rename i_op
  ANDROID: sdcardfs: Propagate dentry down to inode_change_ok()
  ANDROID: sdcardfs: get rid of 'parent' argument of ->d_compare()
  ANDROID: sdcardfs: add parent pointer into dentry name hash
  ANDROID: sdcardfs: use wrappers to access i_mutex
  ANDROID: sdcardfs: Fix locking issue with permision fix up
  ANDROID: sdcardfs: Switch ->d_inode to d_inode()
  ANDROID: sdcardfs: Change magic value
  ANDROID: sdcardfs: Use per mount permissions
  ANDROID: sdcardfs: Add gid and mask to private mount data
  ANDROID: sdcardfs: User new permission2 functions
  ANDROID: sdcardfs: Move directory unlock before touch
  ANDROID: sdcardfs: fix external storage exporting incorrect uid
  ANDROID: sdcardfs: Added top to sdcardfs_inode_info
  ANDROID: sdcardfs: Switch package list to RCU
  ANDROID: sdcardfs: Fix locking for permission fix up
  ANDROID: sdcardfs: Check for other cases on path lookup
  ANDROID: sdcardfs: override umask on mkdir and create
  ANDROID: sdcardfs: fix itnull.cocci warnings
  ANDROID: sdcardfs: Truncate packages_gid.list on overflow
  ANDROID: sdcardfs: remove unneeded __init and __exit
  ANDROID: sdcardfs: Remove unused code
  ANDROID: sdcardfs: remove effectless config option
  ANDROID: sdcardfs: Add support for d_canonical_path
  ANDROID: sdcardfs: Bring up to date with Android M permissions:
  ANDROID: Changed type-casting in packagelist management
  ANDROID: Port of sdcardfs to 4.4
  ANDROID: xattr: Pass EOPNOTSUPP to permission2
  RFC: ANDROID: vfs: Add permission2 for filesystems with per mount permissions
  ANDROID: vfs: Add setattr2 for filesystems with per mount permissions
  ANDROID: vfs: Allow filesystems to access their private mount data
  ANDROID: fuse: Add support for d_canonical_path
  ANDROID: mnt: Add filesystem private data to mount points
  ANDROID: vfs: add d_canonical_path for stacked filesystem support
  ANDROID: Included sdcardfs source code for kernel 3.0
  ANDROID: Fix script to fetch android kernel config fragments for 4.14
  ANDROID: uid_sys_stats: fix the comment
  ANDROID: initramfs: call free_initrd() when skipping init
  ANDROID: memory_state_time: fix undefined behavior with missing DT properties
  ANDROID: memory_state_time: Implement memory_state_time, used by qcom,cpubw
  ANDROID: uid_sys_stats: log task io with a debug flag
  ANDROID: uid_sys_stats: check previous uid_entry before call find_or_register_uid
  ANDROID: uid_sys_stats: Kconfig: add depends for UID_SYS_STATS
  ANDROID: uid_sys_stats: defer io stats calulation for dead tasks
  ANDROID: uid_sys_stats: fix access of task_uid(task)
  ANDROID: uid_sys_stats: reduce update_io_stats overhead
  ANDROID: uid_sys_stats: change to use rt_mutex
  ANDROID: uid_sys_stats: account for fsync syscalls
  ANDROID: uid_sys_stats: fix negative write bytes.
  ANDROID: uid_sys_stats: allow writing same state
  ANDROID: uid_sys_stats: rename uid_cputime.c to uid_sys_stats.c
  ANDROID: uid_cputime: add per-uid IO usage accounting
  ANDROID: uid_cputime: Check for the range while removing range of UIDs.
  ANDROID: uid_cputime: Iterates over all the threads instead of processes.
  ANDROID: uid_cputime: fix cputime overflow
  ANDROID: uid_cputime: Adds accounting for the cputimes per uid.
  CHROMIUM: usb: gadget: f_accessory: add .raw_request callback
  CHROMIUM: usb: gadget: f_audio_source: add .free_func callback
  ANDROID: usb: gadget: f_midi: set fi->f to NULL when free f_midi function
  ANDROID: usb: gadget: f_midi: create F_midi device
  ANDROID: usb: gadget: f_accessory: assign no-op request complete callbacks
  ANDROID: usb: gadget: f_accessory: Fix for UsbAccessory clean unbind.
  ANDROID: usb: gadget: f_accessory: fix false disconnect due to a signal sent to the reading process
  ANDROID: usb: gadget: f_accessory: Move gadget functions code
  ANDROID: usb: gadget: f_accessory: Migrate to USB_FUNCTION API
  ANDROID: usb: gadget: f_audio_source: disable the CPU C-states upon playback
  ANDROID: usb: gadget: f_audio_source: Move gadget functions code
  ANDROID: usb: gadget: f_audio_source: Move to USB_FUNCTION API
  ANDROID: usb: gadget: configfs: fix null ptr in android_disconnect
  ANDROID: usb: gadget: configfs: Add device attribute to determine gadget state
  ANDROID: usb: gadget: configfs: Add "state" attribute to android_device
  ANDROID: usb: gadget: configfs: Add function devices to the parent
  ANDROID: usb: gadget: configfs: Add Uevent to notify userspace
  ANDROID: usb: gadget: configfs: Add usb_function ptr to fi struct
  ANDROID: usb: gadget: f_audio_source: Fixed USB Audio Class Interface Descriptor
  ANDROID: usb: gadget: f_audio_source: change max ISO packet size
  ANDROID: usb: gadget: f_audio_source: New gadget driver for audio output
  ANDROID: usb: gadget: f_accessory: check for accessory device before disconnecting HIDs
  ANDROID: usb: gadget: f_accessory: Enabled Zero Length Packet (ZLP) for acc_write
  ANDROID: usb: gadget: f_accessory: move userspace interface to uapi
  ANDROID: usb: gadget: f_accessory: Add support for HID input devices
  ANDROID: usb: gadget: f_accessory: Add ACCESSORY_SET_AUDIO_MODE control request and ioctl
  ANDROID: usb: gadget: f_accessory: Add Android Accessory function
  ANDROID: trace: sched: add sched blocked tracepoint which dumps out context of sleep.
  ANDROID: security,perf: Allow further restriction of perf_event_open
  ANDROID: power: wakeup: Add the guard condition for len in pm_get_active_wakeup_sources
  ANDROID: power: wakeup: Add last wake up source logging for suspend abort reason.
  ANDROID: power: wakeup_reason: fix suspend time reporting
  ANDROID: power: wakeup_reason: Report suspend times from last_suspend_time
  ANDROID: power: wakeup_reason: Adds functionality to log the last suspend abort reason.
  ANDROID: power: wakeup_reason: Avoids bogus error messages for the suspend aborts.
  ANDROID: power: wakeup_reason: Add guard condition for maximum wakeup reasons
  ANDROID: power: wakeup_reason: add an API to log wakeup reasons
  ANDROID: power: power_supply: Add property CHARGE_COUNTER_EXT and 64-bit precision properties
  ANDROID: power: power_supply: add POWER_SUPPLY_PROP_CHARGE_ENABLED
  ANDROID: power: power_supply: add POWER_SUPPLY_PROP_USB_OTG
  ANDROID: power: power_supply: Add custom property for USB High Current mode
  ANDROID: arm64: copy CONFIG_CMDLINE_EXTEND from ARM
  ANDROID: of: Support CONFIG_CMDLINE_EXTEND config option
  ANDROID: NFC: st21nfca: Fix memory OOB and leak issues in connectivity events handler
  ANDROID: NFC: Fix possible memory corruption when handling SHDLC I-Frame commands
  ANDROID: nfc: fdp: Fix possible buffer overflow in WCS4000 NFC driver
  ANDROID: NFC: st21nfca: Fix out of bounds kernel access when handling ATR_REQ
  ANDROID: netfilter: xt_IDLETIMER: Use fullsock when querying uid
  ANDROID: netfilter: xt_IDLETIMER: Fix use after free condition during work
  ANDROID: netfilter: xt_IDLETIMER: Adds the uid field in the msg
  ANDROID: netfilter: xt_IDLETIMER: time-stamp and suspend/resume handling.
  ANDROID: netfilter: xt_IDLETIMER: Add new netlink msg type
  ANDROID: netfilter: xt_quota2: fixup the quota2, and enable.
  ANDROID: netfilter: xt_quota2: adding the original quota2 from xtables-addons
  ANDROID: net: xfrm: make PF_KEY SHA256 use RFC-compliant truncation.
  ANDROID: net: wireless: wlcore: Disable filtering in AP role
  ANDROID: net: wireless: Decrease scan entry expiration to avoid stall results
  ANDROID: net: rfkill: Introduce CONFIG_RFKILL_PM and use instead of CONFIG_PM to power down
  ANDROID: net: ipv6: autoconf routes into per-device tables
  ANDROID: net: ipv6: fix crash caused by ipv6_find_hdr()
  ANDROID: net: ipv4: tcp: add a sysctl to config the tcp_default_init_rwnd
  ANDROID: net: ipv4: sysfs_net_ipv4: Add sysfs-based knobs for controlling TCP window size
  ANDROID: net: ip-sysctl: Document tcp_fwmark_accept
  ANDROID: net: paranoid: commoncap: Begin to warn users of implicit PARANOID_NETWORK capability grants
  ANDROID: net: paranoid: security: Add proper checks for Android specific capability checks
  ANDROID: net: paranoid: Only NET_ADMIN is allowed to fully control TUN interfaces.
  ANDROID: net: paranoid: Replace AID_NET_RAW checks with capable(CAP_NET_RAW).
  ANDROID: net: paranoid: security: Add AID_NET_RAW and AID_NET_ADMIN capability check in cap_capable().
  ANDROID: net: Paranoid network.
  ANDROID: mmc: core: Add "ignore mmc pm notify" functionality
  ANDROID: mm: add a field to store names for private anonymous memory
  ANDROID: Kbuild, LLVMLinux: allow overriding clang target triple
  CHROMIUM: kbuild: clang: Disable the 'duplicate-decl-specifier' warning
  ANDROID: kbuild: Makefile.clean: make Kbuild and Makefile optional
  ANDROID: kbuild: make it possible to specify the module output dir
  ANDROID: input: keyreset: switch to orderly_reboot
  ANDROID: input: keyreset: Made keyreset more robust
  ANDROID: input: keyreset: Changed keyreset to act as a wrapper for keycombo.
  ANDROID: input: keycombo: add keycombo, a general key combo driver.
  ANDROID: input: keyreset: Add keyreset driver.
  ANDROID: input: gpio_matrix: Remove wakelock.h dependencies
  ANDROID: input: gpio_input: convert from wakelocks to wakeup sources
  ANDROID: input: gpio_event: remove early suspend
  ANDROID: input: Generic GPIO Input devices
  ANDROID: initramfs: Add skip_initramfs command line option
  ANDROID: build: add build server configs for goldfish
  ANDROID: goldfish: add ranchu defconfigs
  ANDROID: fs: Fix for in kernel emergency remount when loop mounts are used
  ANDROID: fs: Refactor FS readpage/write tracepoints.
  ANDROID: fs: FS tracepoints to track IO.
  ANDROID: fs: sched: add a counter to track fsync
  ANDROID: fs: epoll: use freezable blocking call
  ANDROID: dm: verity: add minimum prefetch size
  ANDROID: dm: android-verity: mark dev as rw for linear target
  ANDROID: dm: android-verity: allow disable dm-verity for Treble VTS
  ANDROID: dm: android-verity: fix table_make_digest() error handling
  ANDROID: dm: android-verity: rebase for 4.9
  ANDROID: dm: android-verity: Remove fec_header location constraint
  ANDROID: dm: android-verity: adopt changes made to dm callbacks
  ANDROID: dm: android-verity: pack the fec_header structure
  ANDROID: dm: android-verity: Verify header before fetching table
  ANDROID: dm: android-verity: allow adb disable-verity only in userdebug
  ANDROID: dm: android-verity: mount as linear target if eng build
  ANDROID: dm: android-verity: use default verity public key
  ANDROID: dm: android-verity: fix signature verification flag
  ANDROID: dm: android-verity: use name_to_dev_t
  ANDROID: dm: android-verity: Mounting root as linear device when verity disabled
  ANDROID: dm: android-verity: Add android verity target
  ANDROID: dm: do_mounts_dm: Update init/do_mounts_dm.c to the latest ChromiumOS version.
  ANDROID: dm: do_mounts_dm: fix dm_substitute_devices()
  ANDROID: dm: do_mounts_dm: Rebase on top of 4.9
  CHROMIUM: dm: boot time specification of dm=
  ANDROID: dm: verity-fec: add sysfs attribute fec/corrected
  CHROMIUM: cgroups: relax permissions on moving tasks between cgroups
  ANDROID: cpuset: Make cpusets restore on hotplug
  ANDROID: cpu: send KOBJ_ONLINE event when enabling cpus
  ANDROID: cpuidle: governor: menu: don't use loadavg
  ANDROID: binder: fix node sched policy calculation
  ANDROID: binder: init desired_prio.sched_policy before use it
  ANDROID: binder: Add tracing for binder priority inheritance.
  ANDROID: binder: don't check prio permissions on restore.
  ANDROID: binder: add RT inheritance flag to node.
  ANDROID: binder: improve priority inheritance.
  ANDROID: binder: add min sched_policy to node.
  ANDROID: binder: add support for RT prio inheritance.
  ANDROID: kdb: support new lines without carriage returns
  ANDROID: arm64: Allow to choose appended kernel image
  ANDROID: arm64: add option to build Image-dtb
  ANDROID: arm64: add option to build Image.gz/dtb combo
  ANDROID: arm: convert build of appended dtb zImage to list of dtbs
  ANDROID: arm: add config option to build zImage/dtb combo
  ANDROID: arm: Fix dtb list when DTB_IMAGE_NAMES is empty
  ANDROID: add script to fetch android kernel config fragments

Change-Id: Ibaa7c53d9f63499e5e96579a36e178edad19be75
[rishabhb@codeaurora.org: LLCT tree taken from:
https://android-git.linaro.org/kernel/linaro-android.git/log/?h=test/amt-4.19]
Signed-off-by: Rishabh Bhatnagar <rishabhb@codeaurora.org>
This commit is contained in:
Rishabh Bhatnagar 2018-09-04 14:22:16 -07:00
commit 3bca5c7ace
273 changed files with 24021 additions and 705 deletions

3
.gitignore vendored
View file

@ -132,3 +132,6 @@ all.config
# Kdevelop4
*.kdev4
# fetched Android config fragments
kernel/configs/android-*.cfg

View file

@ -0,0 +1,16 @@
What: /sys/kernel/wakeup_reasons/last_resume_reason
Date: February 2014
Contact: Ruchi Kandoi <kandoiruchi@google.com>
Description:
The /sys/kernel/wakeup_reasons/last_resume_reason is
used to report wakeup reasons after system exited suspend.
What: /sys/kernel/wakeup_reasons/last_suspend_time
Date: March 2015
Contact: jinqian <jinqian@google.com>
Description:
The /sys/kernel/wakeup_reasons/last_suspend_time is
used to report time spent in last suspend cycle. It contains
two numbers (in seconds) separated by space. First number is
the time spent in suspend and resume processes. Second number
is the time spent in sleep state.

View file

@ -884,6 +884,9 @@
dis_ucode_ldr [X86] Disable the microcode loader.
dm= [DM] Allows early creation of a device-mapper device.
See Documentation/device-mapper/boot.txt.
dma_debug=off If the kernel is compiled with DMA_API_DEBUG support,
this option disables the debugging code at boot.

View file

@ -0,0 +1,42 @@
Boot time creation of mapped devices
===================================
It is possible to configure a device mapper device to act as the root
device for your system in two ways.
The first is to build an initial ramdisk which boots to a minimal
userspace which configures the device, then pivot_root(8) in to it.
For simple device mapper configurations, it is possible to boot directly
using the following kernel command line:
dm="<name> <uuid> <ro>,table line 1,...,table line n"
name = the name to associate with the device
after boot, udev, if used, will use that name to label
the device node.
uuid = may be 'none' or the UUID desired for the device.
ro = may be "ro" or "rw". If "ro", the device and device table will be
marked read-only.
Each table line may be as normal when using the dmsetup tool except for
two variations:
1. Any use of commas will be interpreted as a newline
2. Quotation marks cannot be escaped and cannot be used without
terminating the dm= argument.
Unless renamed by udev, the device node created will be dm-0 as the
first minor number for the device-mapper is used during early creation.
Example
=======
- Booting to a linear array made up of user-mode linux block devices:
dm="lroot none 0, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" \
root=/dev/dm-0
Will boot to a rw dm-linear target of 8192 sectors split across two
block devices identified by their major:minor numbers. After boot, udev
will rename this target to /dev/mapper/lroot (depending on the rules).
No uuid was assigned.

View file

@ -0,0 +1,8 @@
Memory bandwidth and frequency state tracking
Required properties:
- compatible : should be:
"memory-state-time"
- freq-tbl: Should contain entries with each frequency in Hz.
- bw-buckets: Should contain upper-bound limits for each bandwidth bucket in Mbps.
Must match the framework power_profile.xml for the device.

View file

@ -398,6 +398,8 @@ is not associated with a file:
[stack] = the stack of the main process
[vdso] = the "virtual dynamic shared object",
the kernel system call handler
[anon:<name>] = an anonymous mapping that has been
named by userspace
or if empty, the mapping is anonymous.
@ -426,6 +428,7 @@ KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd ex mr mw me dw
Name: name from userspace
the first of these lines shows the same information as is displayed for the
mapping in /proc/PID/maps. The remaining lines show the size of the mapping
@ -498,6 +501,9 @@ Note that there is no guarantee that every flag and associated mnemonic will
be present in all further kernel releases. Things get changed, the flags may
be vanished or the reverse -- new added.
The "Name" field will only be present on a mapping that has been named by
userspace, and will show the name passed in by userspace.
This file is only present if the CONFIG_MMU kernel configuration option is
enabled.

View file

@ -630,6 +630,16 @@ tcp_fastopen_blackhole_timeout_sec - INTEGER
0 to disable the blackhole detection.
By default, it is set to 1hr.
tcp_fwmark_accept - BOOLEAN
If set, incoming connections to listening sockets that do not have a
socket mark will set the mark of the accepting socket to the fwmark of
the incoming SYN packet. This will cause all packets on that connection
(starting from the first SYNACK) to be sent with that fwmark. The
listening socket's mark is unchanged. Listening sockets that already
have a fwmark set via setsockopt(SOL_SOCKET, SO_MARK, ...) are
unaffected.
Default: 0
tcp_syn_retries - INTEGER
Number of times initial SYNs for an active TCP connection attempt
will be retransmitted. Should not be higher than 127. Default value

View file

@ -693,7 +693,8 @@ allowed to execute.
perf_event_paranoid:
Controls use of the performance events system by unprivileged
users (without CAP_SYS_ADMIN). The default value is 2.
users (without CAP_SYS_ADMIN). The default value is 3 if
CONFIG_SECURITY_PERF_EVENTS_RESTRICT is set, or 2 otherwise.
-1: Allow use of (almost) all events by all users
Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
@ -701,6 +702,7 @@ users (without CAP_SYS_ADMIN). The default value is 2.
Disallow raw tracepoint access by users without CAP_SYS_ADMIN
>=1: Disallow CPU event access by users without CAP_SYS_ADMIN
>=2: Disallow kernel profiling by users without CAP_SYS_ADMIN
>=3: Disallow all event access by users without CAP_SYS_ADMIN
==============================================================

View file

@ -31,6 +31,7 @@ Currently, these files are in /proc/sys/vm:
- dirty_writeback_centisecs
- drop_caches
- extfrag_threshold
- extra_free_kbytes
- hugetlb_shm_group
- laptop_mode
- legacy_va_layout
@ -274,6 +275,21 @@ any throttling.
==============================================================
extra_free_kbytes
This parameter tells the VM to keep extra free memory between the threshold
where background reclaim (kswapd) kicks in, and the threshold where direct
reclaim (by allocating processes) kicks in.
This is useful for workloads that require low latency memory allocations
and have a bounded burstiness in memory allocations, for example a
realtime application that receives and transmits network traffic
(causing in-kernel memory allocations) with a maximum total message burst
size of 200MB may need 200MB of extra free memory to avoid direct reclaim
related latencies.
==============================================================
hugetlb_shm_group
hugetlb_shm_group contains group id that is allowed to create SysV

View file

@ -498,7 +498,8 @@ endif
ifeq ($(cc-name),clang)
ifneq ($(CROSS_COMPILE),)
CLANG_TARGET := --target=$(notdir $(CROSS_COMPILE:%-=%))
CLANG_TRIPLE ?= $(CROSS_COMPILE)
CLANG_TARGET := --target=$(notdir $(CLANG_TRIPLE:%-=%))
GCC_TOOLCHAIN := $(realpath $(dir $(shell which $(LD)))/..)
endif
ifneq ($(GCC_TOOLCHAIN),)
@ -722,7 +723,6 @@ KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier)
KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
KBUILD_CFLAGS += $(call cc-disable-warning, duplicate-decl-specifier)
KBUILD_CFLAGS += -Wno-asm-operand-widths
KBUILD_CFLAGS += -Wno-initializer-overrides
KBUILD_CFLAGS += -fno-builtin
@ -821,6 +821,30 @@ KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
LDFLAGS_vmlinux += --gc-sections
endif
ifdef CONFIG_CFI_CLANG
cfi-clang-flags += -fsanitize=cfi
DISABLE_CFI_CLANG := -fno-sanitize=cfi
ifdef CONFIG_MODULES
cfi-clang-flags += -fsanitize-cfi-cross-dso
DISABLE_CFI_CLANG += -fno-sanitize-cfi-cross-dso
endif
ifdef CONFIG_CFI_PERMISSIVE
cfi-clang-flags += -fsanitize-recover=cfi -fno-sanitize-trap=cfi
endif
# allow disabling only clang CFI where needed
export DISABLE_CFI_CLANG
endif
ifdef CONFIG_CFI
# cfi-flags are re-tested in prepare-compiler-check
cfi-flags := $(cfi-clang-flags)
KBUILD_CFLAGS += $(cfi-flags)
DISABLE_CFI := $(DISABLE_CFI_CLANG)
export DISABLE_CFI
endif
# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
@ -1144,6 +1168,12 @@ uapi-asm-generic:
PHONY += prepare-objtool
prepare-objtool: $(objtool_target)
ifdef cfi-flags
ifeq ($(call cc-option, $(cfi-flags)),)
@echo Cannot use CONFIG_CFI: $(cfi-flags) not supported by compiler >&2 && exit 1
endif
endif
# Generate some files
# ---------------------------------------------------------------------------

View file

@ -474,6 +474,34 @@ config STACKPROTECTOR_STRONG
about 20% of all kernel functions, which increases the kernel code
size by about 2%.
config CFI
bool
config CFI_PERMISSIVE
bool "Use CFI in permissive mode"
depends on CFI
help
When selected, Control Flow Integrity (CFI) violations result in a
warning instead of a kernel panic. This option is useful for finding
CFI violations in drivers during development.
config CFI_CLANG
bool "Use clang Control Flow Integrity (CFI) (EXPERIMENTAL)"
depends on LTO_CLANG
depends on KALLSYMS
select CFI
help
This option enables clang Control Flow Integrity (CFI), which adds
runtime checking for indirect function calls.
config CFI_CLANG_SHADOW
bool "Use CFI shadow to speed up cross-module checks"
default y
depends on CFI_CLANG
help
If you select this option, the kernel builds a fast look-up table of
CFI check functions in loaded modules to reduce overhead.
config HAVE_ARCH_WITHIN_STACK_FRAMES
bool
help

View file

@ -16,6 +16,7 @@ OBJCOPYFLAGS :=-O binary -R .comment -S
ifneq ($(MACHINE),)
include $(MACHINE)/Makefile.boot
endif
include $(srctree)/arch/arm/boot/dts/Makefile
# Note: the following conditions must always be true:
# ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)

View file

@ -0,0 +1,313 @@
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_ARCH_MMAP_RND_BITS=16
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_VIRT=y
CONFIG_ARM_KERNMEM_PERMS=y
CONFIG_SMP=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_KSM=y
CONFIG_SECCOMP=y
CONFIG_CMDLINE="console=ttyAMA0"
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_DEBUG=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_ESP=y
# CONFIG_INET_LRO is not set
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_CLS_ACT=y
# CONFIG_WIRELESS is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_VIRTIO_BLK=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_TUN=y
CONFIG_VIRTIO_NET=y
CONFIG_SMSC911X=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN is not set
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_XPAD=y
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=y
CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_GTCO=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_SERIO_AMBAKMI=y
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVMEM is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_VIRTIO_CONSOLE=y
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
CONFIG_MEDIA_SUPPORT=y
CONFIG_FB=y
CONFIG_FB_GOLDFISH=y
CONFIG_FB_SIMPLE=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_HOLTEK=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_UCLOGIC=y
CONFIG_HID_WALTOP=y
CONFIG_HID_GYRATION=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NTRIG=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_ROCCAT=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
CONFIG_HID_ZEROPLUS=y
CONFIG_HID_ZYDACRON=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OTG_WAKELOCK=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PL031=y
CONFIG_VIRTIO_MMIO=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_SYNC=y
CONFIG_SW_SYNC=y
CONFIG_SW_SYNC_USER=y
CONFIG_ION=y
CONFIG_GOLDFISH_AUDIO=y
CONFIG_GOLDFISH=y
CONFIG_GOLDFISH_PIPE=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_PSTORE=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_RAM=y
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_DEBUG_INFO=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_PANIC_TIMEOUT=5
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
CONFIG_VIRTUALIZATION=y

View file

@ -1289,6 +1289,23 @@ config CMDLINE
entering them here. As a minimum, you should specify the the
root device (e.g. root=/dev/nfs).
choice
prompt "Kernel command line type" if CMDLINE != ""
default CMDLINE_FROM_BOOTLOADER
config CMDLINE_FROM_BOOTLOADER
bool "Use bootloader kernel arguments if available"
help
Uses the command-line options passed by the boot loader. If
the boot loader doesn't provide any, the default kernel command
string provided in CMDLINE will be used.
config CMDLINE_EXTEND
bool "Extend bootloader kernel arguments"
help
The command-line arguments provided by the boot loader will be
appended to the default kernel command string.
config CMDLINE_FORCE
bool "Always use the default kernel command string"
help
@ -1296,6 +1313,7 @@ config CMDLINE_FORCE
loader passes other arguments to the kernel.
This is useful if you cannot or don't want to change the
command-line options your boot loader passes to the kernel.
endchoice
config EFI_STUB
bool

View file

@ -119,7 +119,7 @@ core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
boot := arch/arm64/boot
ifeq ($(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE),y)
KBUILD_IMAGE := $(boot)/$(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME))
KBUILD_IMAGE := $(boot)/$(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME))
else
KBUILD_IMAGE := $(boot)/Image.gz
endif
@ -152,7 +152,10 @@ dtbs: prepare scripts
dtbs_install:
$(Q)$(MAKE) $(dtbinst)=$(boot)/dts
Image.gz-dtb: vmlinux scripts dtbs
Image-dtb: vmlinux scripts dtbs
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
Image.gz-dtb: vmlinux scripts dtbs Image.gz
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
PHONY += vdso_install

View file

@ -1,3 +1,4 @@
Image
Image-dtb
Image.gz
Image.gz-dtb

View file

@ -34,6 +34,9 @@ $(obj)/Image: vmlinux FORCE
$(obj)/Image.bz2: $(obj)/Image FORCE
$(call if_changed,bzip2)
$(obj)/Image-dtb: $(obj)/Image $(DTB_OBJS) FORCE
$(call if_changed,cat)
$(obj)/Image.gz: $(obj)/Image FORCE
$(call if_changed,gzip)

View file

@ -0,0 +1,309 @@
# CONFIG_LOCALVERSION_AUTO is not set
# CONFIG_SWAP is not set
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_ARCH_MMAP_RND_BITS=24
CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_VEXPRESS=y
CONFIG_NR_CPUS=4
CONFIG_PREEMPT=y
CONFIG_KSM=y
CONFIG_SECCOMP=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
CONFIG_CMDLINE="console=ttyAMA0"
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_DEBUG=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_ESP=y
# CONFIG_INET_LRO is not set
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_RPFILTER=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_TARGET_ECN=y
CONFIG_IP_NF_TARGET_TTL=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MATCH_AH=y
CONFIG_IP6_NF_MATCH_EUI64=y
CONFIG_IP6_NF_MATCH_FRAG=y
CONFIG_IP6_NF_MATCH_OPTS=y
CONFIG_IP6_NF_MATCH_HL=y
CONFIG_IP6_NF_MATCH_IPV6HEADER=y
CONFIG_IP6_NF_MATCH_MH=y
CONFIG_IP6_NF_MATCH_RT=y
CONFIG_IP6_NF_TARGET_HL=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_CLS_ACT=y
# CONFIG_WIRELESS is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_VIRTIO_BLK=y
CONFIG_SCSI=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_TUN=y
CONFIG_VIRTIO_NET=y
CONFIG_SMC91X=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
# CONFIG_WLAN is not set
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TABLET=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVMEM is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_VIRTIO_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_BATTERY_GOLDFISH=y
# CONFIG_HWMON is not set
CONFIG_MEDIA_SUPPORT=y
CONFIG_FB=y
CONFIG_FB_GOLDFISH=y
CONFIG_FB_SIMPLE=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_WALTOP=y
CONFIG_HID_GYRATION=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
CONFIG_HID_ZEROPLUS=y
CONFIG_HID_ZYDACRON=y
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
CONFIG_VIRTIO_MMIO=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_SYNC=y
CONFIG_SW_SYNC=y
CONFIG_SW_SYNC_USER=y
CONFIG_ION=y
CONFIG_GOLDFISH_AUDIO=y
CONFIG_GOLDFISH=y
CONFIG_GOLDFISH_PIPE=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_EXT2_FS=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_PANIC_TIMEOUT=5
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
# CONFIG_FTRACE is not set
CONFIG_ATOMIC64_SELFTEST=y
CONFIG_DEBUG_RODATA=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y

View file

@ -29,6 +29,14 @@ struct sha1_ce_state {
asmlinkage void sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src,
int blocks);
#ifdef CONFIG_CFI_CLANG
static inline void __cfi_sha1_ce_transform(struct sha1_state *sst,
u8 const *src, int blocks)
{
sha1_ce_transform((struct sha1_ce_state *)sst, src, blocks);
}
#define sha1_ce_transform __cfi_sha1_ce_transform
#endif
const u32 sha1_ce_offsetof_count = offsetof(struct sha1_ce_state, sst.count);
const u32 sha1_ce_offsetof_finalize = offsetof(struct sha1_ce_state, finalize);

View file

@ -29,6 +29,14 @@ struct sha256_ce_state {
asmlinkage void sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src,
int blocks);
#ifdef CONFIG_CFI_CLANG
static inline void __cfi_sha2_ce_transform(struct sha256_state *sst,
u8 const *src, int blocks)
{
sha2_ce_transform((struct sha256_ce_state *)sst, src, blocks);
}
#define sha2_ce_transform __cfi_sha2_ce_transform
#endif
const u32 sha256_ce_offsetof_count = offsetof(struct sha256_ce_state,
sst.count);

View file

@ -147,7 +147,7 @@ static inline void cpu_install_idmap(void)
* Atomically replaces the active TTBR1_EL1 PGD with a new VA-compatible PGD,
* avoiding the possibility of conflicting TLB entries being allocated.
*/
static inline void cpu_replace_ttbr1(pgd_t *pgdp)
static inline void __nocfi cpu_replace_ttbr1(pgd_t *pgdp)
{
typedef void (ttbr_replace_func)(phys_addr_t);
extern ttbr_replace_func idmap_cpu_replace_ttbr1;

View file

@ -902,7 +902,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
return !has_cpuid_feature(entry, scope);
}
static void
static void __nocfi
kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
{
typedef void (kpti_remap_fn)(int, int, phys_addr_t);

View file

@ -4,7 +4,11 @@
#
ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \
$(DISABLE_STACKLEAK_PLUGIN)
$(DISABLE_STACKLEAK_PLUGIN) $(DISABLE_CFI)
ifeq ($(cc-name),clang)
ccflags-y += -fno-jump-tables
endif
KVM=../../../../virt/kvm

View file

@ -0,0 +1,421 @@
# CONFIG_64BIT is not set
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_ARCH_MMAP_RND_BITS=16
CONFIG_PARTITION_ADVANCED=y
CONFIG_OSF_PARTITION=y
CONFIG_AMIGA_PARTITION=y
CONFIG_MAC_PARTITION=y
CONFIG_BSD_DISKLABEL=y
CONFIG_MINIX_SUBPARTITION=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_UNIXWARE_DISKLABEL=y
CONFIG_SGI_PARTITION=y
CONFIG_SUN_PARTITION=y
CONFIG_KARMA_PARTITION=y
CONFIG_SMP=y
CONFIG_X86_BIGSMP=y
CONFIG_MCORE2=y
CONFIG_X86_GENERIC=y
CONFIG_HPET_TIMER=y
CONFIG_NR_CPUS=512
CONFIG_PREEMPT=y
# CONFIG_X86_MCE is not set
CONFIG_X86_REBOOTFIXUPS=y
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_KSM=y
CONFIG_CMA=y
# CONFIG_MTRR_SANITIZER is not set
CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_HZ_100=y
CONFIG_PHYSICAL_START=0x100000
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_DEBUG=y
CONFIG_CPU_FREQ=y
# CONFIG_CPU_FREQ_STAT is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_PCIEPORTBUS=y
# CONFIG_PCIEASPM is not set
CONFIG_PCCARD=y
CONFIG_YENTA=y
CONFIG_HOTPLUG_PCI=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_IP_MROUTE=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_SYN_COOKIES=y
CONFIG_INET_ESP=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETLABEL=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_CLS_ACT=y
CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_MAC80211_LEDS=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=16
CONFIG_CONNECTOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_ISCSI_ATTRS=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_ATA_PIIX=y
CONFIG_PATA_AMD=y
CONFIG_PATA_OLDPIIX=y
CONFIG_PATA_SCH=y
CONFIG_PATA_MPIIX=y
CONFIG_ATA_GENERIC=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_DEBUG=y
CONFIG_DM_CRYPT=y
CONFIG_DM_MIRROR=y
CONFIG_DM_ZERO=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_NETCONSOLE=y
CONFIG_TUN=y
CONFIG_VIRTIO_NET=y
CONFIG_BNX2=y
CONFIG_TIGON3=y
CONFIG_NET_TULIP=y
CONFIG_E100=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_SKY2=y
CONFIG_NE2K_PCI=y
CONFIG_FORCEDETH=y
CONFIG_8139TOO=y
# CONFIG_8139TOO_PIO is not set
CONFIG_R8169=y
CONFIG_FDDI=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_USB_USBNET=y
CONFIG_INPUT_POLLDEV=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_XPAD=y
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=y
CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_GTCO=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_DEVMEM is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_NVRAM=y
CONFIG_I2C_I801=y
CONFIG_BATTERY_GOLDFISH=y
CONFIG_WATCHDOG=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_AGP=y
CONFIG_AGP_AMD64=y
CONFIG_AGP_INTEL=y
CONFIG_DRM=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
CONFIG_FB_EFI=y
CONFIG_FB_GOLDFISH=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_HOLTEK=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_UCLOGIC=y
CONFIG_HID_WALTOP=y
CONFIG_HID_GYRATION=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NTRIG=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_ROCCAT=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
CONFIG_HID_ZEROPLUS=y
CONFIG_HID_ZYDACRON=y
CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_UHCI_HCD=y
CONFIG_USB_PRINTER=y
CONFIG_USB_STORAGE=y
CONFIG_USB_OTG_WAKELOCK=y
CONFIG_EDAC=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_DMADEVICES=y
CONFIG_VIRTIO_PCI=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_SYNC=y
CONFIG_SW_SYNC=y
CONFIG_SYNC_FILE=y
CONFIG_ION=y
CONFIG_GOLDFISH_AUDIO=y
CONFIG_SND_HDA_INTEL=y
CONFIG_GOLDFISH=y
CONFIG_GOLDFISH_PIPE=y
CONFIG_GOLDFISH_SYNC=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ISCSI_IBFT_FIND=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_FUSE_FS=y
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_PSTORE=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_RAM=y
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_FRAME_WARN=2048
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
CONFIG_SCHED_TRACER=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
CONFIG_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_AES_586=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CONFIG_X509_CERTIFICATE_PARSER=y
CONFIG_PKCS7_MESSAGE_PARSER=y
CONFIG_PKCS7_TEST_KEY=y
# CONFIG_VIRTUALIZATION is not set
CONFIG_CRC_T10DIF=y

View file

@ -0,0 +1,464 @@
CONFIG_POSIX_MQUEUE=y
# CONFIG_FHANDLE is not set
# CONFIG_USELIB is not set
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
# CONFIG_PCSPKR_PLATFORM is not set
CONFIG_BPF_SYSCALL=y
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_CC_STACKPROTECTOR_STRONG=y
CONFIG_REFCOUNT_FULL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_SMP=y
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
CONFIG_PARAVIRT_SPINLOCKS=y
CONFIG_MCORE2=y
CONFIG_PROCESSOR_SELECT=y
# CONFIG_CPU_SUP_CENTAUR is not set
CONFIG_NR_CPUS=8
CONFIG_PREEMPT=y
# CONFIG_MICROCODE is not set
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_ZSMALLOC=y
# CONFIG_MTRR is not set
CONFIG_HZ_100=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_PHYSICAL_START=0x200000
CONFIG_PHYSICAL_ALIGN=0x1000000
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0 reboot=p"
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_DEBUG=y
CONFIG_ACPI_PROCFS_POWER=y
# CONFIG_ACPI_FAN is not set
# CONFIG_ACPI_THERMAL is not set
# CONFIG_X86_PM_TIMER is not set
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_X86_ACPI_CPUFREQ=y
CONFIG_PCI_MMCONFIG=y
CONFIG_PCI_MSI=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=y
CONFIG_IA32_EMULATION=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_MROUTE=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=y
CONFIG_INET_ESP=y
# CONFIG_INET_XFRM_MODE_BEET is not set
CONFIG_INET_DIAG_DESTROY=y
CONFIG_TCP_CONG_ADVANCED=y
# CONFIG_TCP_CONG_BIC is not set
# CONFIG_TCP_CONG_WESTWOOD is not set
# CONFIG_TCP_CONG_HTCP is not set
CONFIG_TCP_MD5SIG=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_VTI=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETLABEL=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_NF_SOCKET_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
CONFIG_NF_SOCKET_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MATCH_IPV6HEADER=y
CONFIG_IP6_NF_MATCH_RPFILTER=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_CLS_ACT=y
CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_RFKILL=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEBUG_DEVRES=y
CONFIG_OF=y
CONFIG_OF_UNITTEST=y
# CONFIG_PNP_DEBUG_MESSAGES is not set
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_VIRTIO_BLK=y
CONFIG_UID_SYS_STATS=y
CONFIG_MEMORY_STATE_TIME=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_VIRTIO=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_MIRROR=y
CONFIG_DM_ZERO=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1
CONFIG_DM_VERITY_FEC=y
CONFIG_DM_ANDROID_VERITY=y
CONFIG_NETDEVICES=y
CONFIG_NETCONSOLE=y
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_TUN=y
CONFIG_VIRTIO_NET=y
# CONFIG_ETHERNET is not set
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_USB_USBNET=y
# CONFIG_USB_NET_AX8817X is not set
# CONFIG_USB_NET_AX88179_178A is not set
# CONFIG_USB_NET_CDCETHER is not set
# CONFIG_USB_NET_CDC_NCM is not set
# CONFIG_USB_NET_NET1080 is not set
# CONFIG_USB_NET_CDC_SUBSET is not set
# CONFIG_USB_NET_ZAURUS is not set
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
# CONFIG_WLAN_VENDOR_ATMEL is not set
# CONFIG_WLAN_VENDOR_BROADCOM is not set
# CONFIG_WLAN_VENDOR_CISCO is not set
# CONFIG_WLAN_VENDOR_INTEL is not set
# CONFIG_WLAN_VENDOR_INTERSIL is not set
# CONFIG_WLAN_VENDOR_MARVELL is not set
# CONFIG_WLAN_VENDOR_MEDIATEK is not set
# CONFIG_WLAN_VENDOR_RALINK is not set
# CONFIG_WLAN_VENDOR_REALTEK is not set
# CONFIG_WLAN_VENDOR_RSI is not set
# CONFIG_WLAN_VENDOR_ST is not set
# CONFIG_WLAN_VENDOR_TI is not set
# CONFIG_WLAN_VENDOR_ZYDAS is not set
# CONFIG_WLAN_VENDOR_QUANTENNA is not set
CONFIG_MAC80211_HWSIM=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_XPAD=y
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=y
CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_GTCO=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
# CONFIG_SERIO_I8042 is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVMEM is not set
CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_SERIAL_8250_EXAR is not set
CONFIG_SERIAL_8250_NR_UARTS=48
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_INTEL is not set
# CONFIG_HW_RANDOM_AMD is not set
# CONFIG_HW_RANDOM_VIA is not set
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_HPET=y
# CONFIG_HPET_MMAP_DEFAULT is not set
# CONFIG_DEVPORT is not set
# CONFIG_ACPI_I2C_OPREGION is not set
# CONFIG_I2C_COMPAT is not set
# CONFIG_I2C_HELPER_AUTO is not set
CONFIG_PTP_1588_CLOCK=y
# CONFIG_HWMON is not set
# CONFIG_X86_PKG_TEMP_THERMAL is not set
CONFIG_WATCHDOG=y
CONFIG_SOFT_WATCHDOG=y
CONFIG_MEDIA_SUPPORT=y
# CONFIG_VGA_ARB is not set
CONFIG_DRM=y
# CONFIG_DRM_FBDEV_EMULATION is not set
CONFIG_DRM_VIRTIO_GPU=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_HOLTEK=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_UCLOGIC=y
CONFIG_HID_WALTOP=y
CONFIG_HID_GYRATION=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NTRIG=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_ROCCAT=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
CONFIG_HID_ZEROPLUS=y
CONFIG_HID_ZYDACRON=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_GADGET=y
CONFIG_USB_DUMMY_HCD=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_SW_SYNC=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_VSOC=y
CONFIG_ION=y
# CONFIG_X86_PLATFORM_DEVICES is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
# CONFIG_FIRMWARE_MEMMAP is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_ENCRYPTION=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_QFMT_V2=y
CONFIG_AUTOFS4_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_SDCARD_FS=y
CONFIG_PSTORE=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_RAM=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_FRAME_WARN=1024
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_SCHEDSTATS=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_IO_DELAY_NONE=y
CONFIG_DEBUG_BOOT_PARAMS=y
CONFIG_OPTIMIZE_INLINING=y
CONFIG_UNWINDER_FRAME_POINTER=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_PATH=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
CONFIG_CRYPTO_RSA=y
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_LZ4=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_CRYPTO_DEV_VIRTIO=y
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CONFIG_X509_CERTIFICATE_PARSER=y
CONFIG_SYSTEM_TRUSTED_KEYRING=y
CONFIG_SYSTEM_TRUSTED_KEYS="verity_dev_keys.x509"

View file

@ -0,0 +1,416 @@
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_ARCH_MMAP_RND_BITS=32
CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
CONFIG_PARTITION_ADVANCED=y
CONFIG_OSF_PARTITION=y
CONFIG_AMIGA_PARTITION=y
CONFIG_MAC_PARTITION=y
CONFIG_BSD_DISKLABEL=y
CONFIG_MINIX_SUBPARTITION=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_UNIXWARE_DISKLABEL=y
CONFIG_SGI_PARTITION=y
CONFIG_SUN_PARTITION=y
CONFIG_KARMA_PARTITION=y
CONFIG_SMP=y
CONFIG_MCORE2=y
CONFIG_MAXSMP=y
CONFIG_PREEMPT=y
# CONFIG_X86_MCE is not set
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_KSM=y
CONFIG_CMA=y
# CONFIG_MTRR_SANITIZER is not set
CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_HZ_100=y
CONFIG_PHYSICAL_START=0x100000
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_DEBUG=y
CONFIG_CPU_FREQ=y
# CONFIG_CPU_FREQ_STAT is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_PCI_MMCONFIG=y
CONFIG_PCIEPORTBUS=y
# CONFIG_PCIEASPM is not set
CONFIG_PCCARD=y
CONFIG_YENTA=y
CONFIG_HOTPLUG_PCI=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=y
CONFIG_IA32_EMULATION=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_IP_MROUTE=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_SYN_COOKIES=y
CONFIG_INET_ESP=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETLABEL=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_CLS_ACT=y
CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_MAC80211_LEDS=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DMA_CMA=y
CONFIG_CONNECTOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_ISCSI_ATTRS=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_ATA_PIIX=y
CONFIG_PATA_AMD=y
CONFIG_PATA_OLDPIIX=y
CONFIG_PATA_SCH=y
CONFIG_PATA_MPIIX=y
CONFIG_ATA_GENERIC=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_DEBUG=y
CONFIG_DM_CRYPT=y
CONFIG_DM_MIRROR=y
CONFIG_DM_ZERO=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_NETCONSOLE=y
CONFIG_TUN=y
CONFIG_VIRTIO_NET=y
CONFIG_BNX2=y
CONFIG_TIGON3=y
CONFIG_NET_TULIP=y
CONFIG_E100=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_SKY2=y
CONFIG_NE2K_PCI=y
CONFIG_FORCEDETH=y
CONFIG_8139TOO=y
# CONFIG_8139TOO_PIO is not set
CONFIG_R8169=y
CONFIG_FDDI=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_USB_USBNET=y
CONFIG_INPUT_POLLDEV=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_XPAD=y
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=y
CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_GTCO=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_DEVMEM is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_NVRAM=y
CONFIG_I2C_I801=y
CONFIG_BATTERY_GOLDFISH=y
CONFIG_WATCHDOG=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_AGP=y
CONFIG_AGP_AMD64=y
CONFIG_AGP_INTEL=y
CONFIG_DRM=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
CONFIG_FB_EFI=y
CONFIG_FB_GOLDFISH=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_HOLTEK=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_UCLOGIC=y
CONFIG_HID_WALTOP=y
CONFIG_HID_GYRATION=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NTRIG=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_ROCCAT=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
CONFIG_HID_ZEROPLUS=y
CONFIG_HID_ZYDACRON=y
CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_UHCI_HCD=y
CONFIG_USB_PRINTER=y
CONFIG_USB_STORAGE=y
CONFIG_USB_OTG_WAKELOCK=y
CONFIG_EDAC=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_DMADEVICES=y
CONFIG_VIRTIO_PCI=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_SYNC=y
CONFIG_SW_SYNC=y
CONFIG_SYNC_FILE=y
CONFIG_ION=y
CONFIG_GOLDFISH_AUDIO=y
CONFIG_SND_HDA_INTEL=y
CONFIG_GOLDFISH=y
CONFIG_GOLDFISH_PIPE=y
CONFIG_GOLDFISH_SYNC=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ISCSI_IBFT_FIND=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_FUSE_FS=y
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_PSTORE=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_RAM=y
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
CONFIG_SCHED_TRACER=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
CONFIG_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CONFIG_X509_CERTIFICATE_PARSER=y
CONFIG_PKCS7_MESSAGE_PARSER=y
CONFIG_PKCS7_TEST_KEY=y
# CONFIG_VIRTUALIZATION is not set
CONFIG_CRC_T10DIF=y

View file

@ -0,0 +1,16 @@
ARCH=x86_64
BRANCH=android-4.14
CLANG_TRIPLE=x86_64-linux-gnu-
CROSS_COMPILE=x86_64-linux-androidkernel-
DEFCONFIG=x86_64_cuttlefish_defconfig
EXTRA_CMDS=''
KERNEL_DIR=common
POST_DEFCONFIG_CMDS="check_defconfig"
CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r328903/bin
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
FILES="
arch/x86/boot/bzImage
vmlinux
System.map
"
STOP_SHIP_TRACEPRINTK=1

13
build.config.goldfish.arm Normal file
View file

@ -0,0 +1,13 @@
ARCH=arm
BRANCH=android-4.4
CROSS_COMPILE=arm-linux-androidkernel-
DEFCONFIG=ranchu_defconfig
EXTRA_CMDS=''
KERNEL_DIR=common
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin
FILES="
arch/arm/boot/zImage
vmlinux
System.map
"
STOP_SHIP_TRACEPRINTK=1

View file

@ -0,0 +1,13 @@
ARCH=arm64
BRANCH=android-4.4
CROSS_COMPILE=aarch64-linux-android-
DEFCONFIG=ranchu64_defconfig
EXTRA_CMDS=''
KERNEL_DIR=common
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin
FILES="
arch/arm64/boot/Image
vmlinux
System.map
"
STOP_SHIP_TRACEPRINTK=1

View file

@ -0,0 +1,12 @@
ARCH=mips
BRANCH=android-4.4
CROSS_COMPILE=mips64el-linux-android-
DEFCONFIG=ranchu_defconfig
EXTRA_CMDS=''
KERNEL_DIR=common
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/mips/mips64el-linux-android-4.9/bin
FILES="
vmlinux
System.map
"
STOP_SHIP_TRACEPRINTK=1

View file

@ -0,0 +1,12 @@
ARCH=mips
BRANCH=android-4.4
CROSS_COMPILE=mips64el-linux-android-
DEFCONFIG=ranchu64_defconfig
EXTRA_CMDS=''
KERNEL_DIR=common
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/mips/mips64el-linux-android-4.9/bin
FILES="
vmlinux
System.map
"
STOP_SHIP_TRACEPRINTK=1

13
build.config.goldfish.x86 Normal file
View file

@ -0,0 +1,13 @@
ARCH=x86
BRANCH=android-4.4
CROSS_COMPILE=x86_64-linux-android-
DEFCONFIG=i386_ranchu_defconfig
EXTRA_CMDS=''
KERNEL_DIR=common
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
FILES="
arch/x86/boot/bzImage
vmlinux
System.map
"
STOP_SHIP_TRACEPRINTK=1

View file

@ -0,0 +1,13 @@
ARCH=x86_64
BRANCH=android-4.4
CROSS_COMPILE=x86_64-linux-android-
DEFCONFIG=x86_64_ranchu_defconfig
EXTRA_CMDS=''
KERNEL_DIR=common
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
FILES="
arch/x86/boot/bzImage
vmlinux
System.map
"
STOP_SHIP_TRACEPRINTK=1

View file

@ -264,5 +264,46 @@ int verify_pkcs7_signature(const void *data, size_t len,
return ret;
}
EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
/**
* verify_signature_one - Verify a signature with keys from given keyring
* @sig: The signature to be verified
* @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
* (void *)1UL for all trusted keys).
* @keyid: key description (not partial)
*/
int verify_signature_one(const struct public_key_signature *sig,
struct key *trusted_keys, const char *keyid)
{
key_ref_t ref;
struct key *key;
int ret;
if (!sig)
return -EBADMSG;
if (!trusted_keys) {
trusted_keys = builtin_trusted_keys;
} else if (trusted_keys == (void *)1UL) {
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
trusted_keys = secondary_trusted_keys;
#else
trusted_keys = builtin_trusted_keys;
#endif
}
ref = keyring_search(make_key_ref(trusted_keys, 1),
&key_type_asymmetric, keyid);
if (IS_ERR(ref)) {
pr_err("Asymmetric key (%s) not found in keyring(%s)\n",
keyid, trusted_keys->description);
return -ENOKEY;
}
key = key_ref_to_ptr(ref);
ret = verify_signature(key, sig);
key_put(key);
return ret;
}
EXPORT_SYMBOL_GPL(verify_signature_one);

View file

@ -73,6 +73,7 @@
#include <linux/ratelimit.h>
#include <uapi/linux/android/binder.h>
#include <uapi/linux/sched/types.h>
#include <asm/cacheflush.h>
@ -350,10 +351,14 @@ struct binder_error {
* and by @lock)
* @has_async_transaction: async transaction to node in progress
* (protected by @lock)
* @sched_policy: minimum scheduling policy for node
* (invariant after initialized)
* @accept_fds: file descriptor operations supported for node
* (invariant after initialized)
* @min_priority: minimum scheduling priority
* (invariant after initialized)
* @inherit_rt: inherit RT scheduling policy from caller
* (invariant after initialized)
* @async_todo: list of async work items
* (protected by @proc->inner_lock)
*
@ -389,6 +394,8 @@ struct binder_node {
/*
* invariant after initialization
*/
u8 sched_policy:2;
u8 inherit_rt:1;
u8 accept_fds:1;
u8 min_priority;
};
@ -462,6 +469,22 @@ enum binder_deferred_state {
BINDER_DEFERRED_RELEASE = 0x04,
};
/**
* struct binder_priority - scheduler policy and priority
* @sched_policy scheduler policy
* @prio [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT
*
* The binder driver supports inheriting the following scheduler policies:
* SCHED_NORMAL
* SCHED_BATCH
* SCHED_FIFO
* SCHED_RR
*/
struct binder_priority {
unsigned int sched_policy;
int prio;
};
/**
* struct binder_proc - binder process bookkeeping
* @proc_node: element for binder_procs list
@ -540,7 +563,7 @@ struct binder_proc {
int requested_threads;
int requested_threads_started;
int tmp_ref;
long default_priority;
struct binder_priority default_priority;
struct dentry *debugfs_entry;
struct binder_alloc alloc;
struct binder_context *context;
@ -590,6 +613,7 @@ enum {
* @is_dead: thread is dead and awaiting free
* when outstanding transactions are cleaned up
* (protected by @proc->inner_lock)
* @task: struct task_struct for this thread
*
* Bookkeeping structure for binder threads.
*/
@ -609,6 +633,7 @@ struct binder_thread {
struct binder_stats stats;
atomic_t tmp_ref;
bool is_dead;
struct task_struct *task;
};
struct binder_transaction {
@ -625,8 +650,9 @@ struct binder_transaction {
struct binder_buffer *buffer;
unsigned int code;
unsigned int flags;
long priority;
long saved_priority;
struct binder_priority priority;
struct binder_priority saved_priority;
bool set_priority_called;
kuid_t sender_euid;
/**
* @lock: protects @from, @to_proc, and @to_thread
@ -1107,22 +1133,145 @@ static void binder_wakeup_proc_ilocked(struct binder_proc *proc)
binder_wakeup_thread_ilocked(proc, thread, /* sync = */false);
}
static void binder_set_nice(long nice)
static bool is_rt_policy(int policy)
{
long min_nice;
return policy == SCHED_FIFO || policy == SCHED_RR;
}
if (can_nice(current, nice)) {
set_user_nice(current, nice);
static bool is_fair_policy(int policy)
{
return policy == SCHED_NORMAL || policy == SCHED_BATCH;
}
static bool binder_supported_policy(int policy)
{
return is_fair_policy(policy) || is_rt_policy(policy);
}
static int to_userspace_prio(int policy, int kernel_priority)
{
if (is_fair_policy(policy))
return PRIO_TO_NICE(kernel_priority);
else
return MAX_USER_RT_PRIO - 1 - kernel_priority;
}
static int to_kernel_prio(int policy, int user_priority)
{
if (is_fair_policy(policy))
return NICE_TO_PRIO(user_priority);
else
return MAX_USER_RT_PRIO - 1 - user_priority;
}
static void binder_do_set_priority(struct task_struct *task,
struct binder_priority desired,
bool verify)
{
int priority; /* user-space prio value */
bool has_cap_nice;
unsigned int policy = desired.sched_policy;
if (task->policy == policy && task->normal_prio == desired.prio)
return;
has_cap_nice = has_capability_noaudit(task, CAP_SYS_NICE);
priority = to_userspace_prio(policy, desired.prio);
if (verify && is_rt_policy(policy) && !has_cap_nice) {
long max_rtprio = task_rlimit(task, RLIMIT_RTPRIO);
if (max_rtprio == 0) {
policy = SCHED_NORMAL;
priority = MIN_NICE;
} else if (priority > max_rtprio) {
priority = max_rtprio;
}
}
min_nice = rlimit_to_nice(rlimit(RLIMIT_NICE));
binder_debug(BINDER_DEBUG_PRIORITY_CAP,
"%d: nice value %ld not allowed use %ld instead\n",
current->pid, nice, min_nice);
set_user_nice(current, min_nice);
if (min_nice <= MAX_NICE)
if (verify && is_fair_policy(policy) && !has_cap_nice) {
long min_nice = rlimit_to_nice(task_rlimit(task, RLIMIT_NICE));
if (min_nice > MAX_NICE) {
binder_user_error("%d RLIMIT_NICE not set\n",
task->pid);
return;
} else if (priority < min_nice) {
priority = min_nice;
}
}
if (policy != desired.sched_policy ||
to_kernel_prio(policy, priority) != desired.prio)
binder_debug(BINDER_DEBUG_PRIORITY_CAP,
"%d: priority %d not allowed, using %d instead\n",
task->pid, desired.prio,
to_kernel_prio(policy, priority));
trace_binder_set_priority(task->tgid, task->pid, task->normal_prio,
to_kernel_prio(policy, priority),
desired.prio);
/* Set the actual priority */
if (task->policy != policy || is_rt_policy(policy)) {
struct sched_param params;
params.sched_priority = is_rt_policy(policy) ? priority : 0;
sched_setscheduler_nocheck(task,
policy | SCHED_RESET_ON_FORK,
&params);
}
if (is_fair_policy(policy))
set_user_nice(task, priority);
}
static void binder_set_priority(struct task_struct *task,
struct binder_priority desired)
{
binder_do_set_priority(task, desired, /* verify = */ true);
}
static void binder_restore_priority(struct task_struct *task,
struct binder_priority desired)
{
binder_do_set_priority(task, desired, /* verify = */ false);
}
static void binder_transaction_priority(struct task_struct *task,
struct binder_transaction *t,
struct binder_priority node_prio,
bool inherit_rt)
{
struct binder_priority desired_prio = t->priority;
if (t->set_priority_called)
return;
binder_user_error("%d RLIMIT_NICE not set\n", current->pid);
t->set_priority_called = true;
t->saved_priority.sched_policy = task->policy;
t->saved_priority.prio = task->normal_prio;
if (!inherit_rt && is_rt_policy(desired_prio.sched_policy)) {
desired_prio.prio = NICE_TO_PRIO(0);
desired_prio.sched_policy = SCHED_NORMAL;
}
if (node_prio.prio < t->priority.prio ||
(node_prio.prio == t->priority.prio &&
node_prio.sched_policy == SCHED_FIFO)) {
/*
* In case the minimum priority on the node is
* higher (lower value), use that priority. If
* the priority is the same, but the node uses
* SCHED_FIFO, prefer SCHED_FIFO, since it can
* run unbounded, unlike SCHED_RR.
*/
desired_prio = node_prio;
}
binder_set_priority(task, desired_prio);
}
static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc,
@ -1175,6 +1324,7 @@ static struct binder_node *binder_init_node_ilocked(
binder_uintptr_t ptr = fp ? fp->binder : 0;
binder_uintptr_t cookie = fp ? fp->cookie : 0;
__u32 flags = fp ? fp->flags : 0;
s8 priority;
assert_spin_locked(&proc->inner_lock);
@ -1207,8 +1357,12 @@ static struct binder_node *binder_init_node_ilocked(
node->ptr = ptr;
node->cookie = cookie;
node->work.type = BINDER_WORK_NODE;
node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
node->sched_policy = (flags & FLAT_BINDER_FLAG_SCHED_POLICY_MASK) >>
FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT;
node->min_priority = to_kernel_prio(node->sched_policy, priority);
node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
node->inherit_rt = !!(flags & FLAT_BINDER_FLAG_INHERIT_RT);
spin_lock_init(&node->lock);
INIT_LIST_HEAD(&node->work.entry);
INIT_LIST_HEAD(&node->async_todo);
@ -2633,11 +2787,15 @@ static bool binder_proc_transaction(struct binder_transaction *t,
struct binder_thread *thread)
{
struct binder_node *node = t->buffer->target_node;
struct binder_priority node_prio;
bool oneway = !!(t->flags & TF_ONE_WAY);
bool pending_async = false;
BUG_ON(!node);
binder_node_lock(node);
node_prio.prio = node->min_priority;
node_prio.sched_policy = node->sched_policy;
if (oneway) {
BUG_ON(thread);
if (node->has_async_transaction) {
@ -2658,12 +2816,15 @@ static bool binder_proc_transaction(struct binder_transaction *t,
if (!thread && !pending_async)
thread = binder_select_thread_ilocked(proc);
if (thread)
if (thread) {
binder_transaction_priority(thread->task, t, node_prio,
node->inherit_rt);
binder_enqueue_thread_work_ilocked(thread, &t->work);
else if (!pending_async)
} else if (!pending_async) {
binder_enqueue_work_ilocked(&t->work, &proc->todo);
else
} else {
binder_enqueue_work_ilocked(&t->work, &node->async_todo);
}
if (!pending_async)
binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */);
@ -2780,7 +2941,6 @@ static void binder_transaction(struct binder_proc *proc,
}
thread->transaction_stack = in_reply_to->to_parent;
binder_inner_proc_unlock(proc);
binder_set_nice(in_reply_to->saved_priority);
target_thread = binder_get_txn_from_and_acq_inner(in_reply_to);
if (target_thread == NULL) {
return_error = BR_DEAD_REPLY;
@ -2953,7 +3113,15 @@ static void binder_transaction(struct binder_proc *proc,
t->to_thread = target_thread;
t->code = tr->code;
t->flags = tr->flags;
t->priority = task_nice(current);
if (!(t->flags & TF_ONE_WAY) &&
binder_supported_policy(current->policy)) {
/* Inherit supported policies for synchronous transactions */
t->priority.sched_policy = current->policy;
t->priority.prio = current->normal_prio;
} else {
/* Otherwise, fall back to the default priority */
t->priority = target_proc->default_priority;
}
trace_binder_transaction(reply, t, target_node);
@ -3182,6 +3350,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_enqueue_thread_work_ilocked(target_thread, &t->work);
binder_inner_proc_unlock(target_proc);
wake_up_interruptible_sync(&target_thread->wait);
binder_restore_priority(current, in_reply_to->saved_priority);
binder_free_transaction(in_reply_to);
} else if (!(t->flags & TF_ONE_WAY)) {
BUG_ON(t->buffer->async_transaction != 0);
@ -3285,6 +3454,7 @@ static void binder_transaction(struct binder_proc *proc,
BUG_ON(thread->return_error.cmd != BR_OK);
if (in_reply_to) {
binder_restore_priority(current, in_reply_to->saved_priority);
thread->return_error.cmd = BR_TRANSACTION_COMPLETE;
binder_enqueue_thread_work(thread, &thread->return_error.work);
binder_send_failed_reply(in_reply_to, return_error);
@ -3865,7 +4035,7 @@ static int binder_thread_read(struct binder_proc *proc,
wait_event_interruptible(binder_user_error_wait,
binder_stop_on_user_error < 2);
}
binder_set_nice(proc->default_priority);
binder_restore_priority(current, proc->default_priority);
}
if (non_block) {
@ -4080,16 +4250,14 @@ static int binder_thread_read(struct binder_proc *proc,
BUG_ON(t->buffer == NULL);
if (t->buffer->target_node) {
struct binder_node *target_node = t->buffer->target_node;
struct binder_priority node_prio;
tr.target.ptr = target_node->ptr;
tr.cookie = target_node->cookie;
t->saved_priority = task_nice(current);
if (t->priority < target_node->min_priority &&
!(t->flags & TF_ONE_WAY))
binder_set_nice(t->priority);
else if (!(t->flags & TF_ONE_WAY) ||
t->saved_priority > target_node->min_priority)
binder_set_nice(target_node->min_priority);
node_prio.sched_policy = target_node->sched_policy;
node_prio.prio = target_node->min_priority;
binder_transaction_priority(current, t, node_prio,
target_node->inherit_rt);
cmd = BR_TRANSACTION;
} else {
tr.target.ptr = 0;
@ -4267,6 +4435,8 @@ static struct binder_thread *binder_get_thread_ilocked(
binder_stats_created(BINDER_STAT_THREAD);
thread->proc = proc;
thread->pid = current->pid;
get_task_struct(current);
thread->task = current;
atomic_set(&thread->tmp_ref, 0);
init_waitqueue_head(&thread->wait);
INIT_LIST_HEAD(&thread->todo);
@ -4317,6 +4487,7 @@ static void binder_free_thread(struct binder_thread *thread)
BUG_ON(!list_empty(&thread->todo));
binder_stats_deleted(BINDER_STAT_THREAD);
binder_proc_dec_tmpref(thread->proc);
put_task_struct(thread->task);
kfree(thread);
}
@ -4767,7 +4938,14 @@ static int binder_open(struct inode *nodp, struct file *filp)
proc->tsk = current->group_leader;
mutex_init(&proc->files_lock);
INIT_LIST_HEAD(&proc->todo);
proc->default_priority = task_nice(current);
if (binder_supported_policy(current->policy)) {
proc->default_priority.sched_policy = current->policy;
proc->default_priority.prio = current->normal_prio;
} else {
proc->default_priority.sched_policy = SCHED_NORMAL;
proc->default_priority.prio = NICE_TO_PRIO(0);
}
binder_dev = container_of(filp->private_data, struct binder_device,
miscdev);
proc->context = &binder_dev->context;
@ -5061,13 +5239,14 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
spin_lock(&t->lock);
to_proc = t->to_proc;
seq_printf(m,
"%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d",
"%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %d:%d r%d",
prefix, t->debug_id, t,
t->from ? t->from->proc->pid : 0,
t->from ? t->from->pid : 0,
to_proc ? to_proc->pid : 0,
t->to_thread ? t->to_thread->pid : 0,
t->code, t->flags, t->priority, t->need_reply);
t->code, t->flags, t->priority.sched_policy,
t->priority.prio, t->need_reply);
spin_unlock(&t->lock);
if (proc != to_proc) {
@ -5185,8 +5364,9 @@ static void print_binder_node_nilocked(struct seq_file *m,
hlist_for_each_entry(ref, &node->refs, node_entry)
count++;
seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d",
seq_printf(m, " node %d: u%016llx c%016llx pri %d:%d hs %d hw %d ls %d lw %d is %d iw %d tr %d",
node->debug_id, (u64)node->ptr, (u64)node->cookie,
node->sched_policy, node->min_priority,
node->has_strong_ref, node->has_weak_ref,
node->local_strong_refs, node->local_weak_refs,
node->internal_strong_refs, count, node->tmp_refs);

View file

@ -85,6 +85,30 @@ DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_ioctl_done);
DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_write_done);
DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_read_done);
TRACE_EVENT(binder_set_priority,
TP_PROTO(int proc, int thread, unsigned int old_prio,
unsigned int desired_prio, unsigned int new_prio),
TP_ARGS(proc, thread, old_prio, new_prio, desired_prio),
TP_STRUCT__entry(
__field(int, proc)
__field(int, thread)
__field(unsigned int, old_prio)
__field(unsigned int, new_prio)
__field(unsigned int, desired_prio)
),
TP_fast_assign(
__entry->proc = proc;
__entry->thread = thread;
__entry->old_prio = old_prio;
__entry->new_prio = new_prio;
__entry->desired_prio = desired_prio;
),
TP_printk("proc=%d thread=%d old=%d => new=%d desired=%d",
__entry->proc, __entry->thread, __entry->old_prio,
__entry->new_prio, __entry->desired_prio)
);
TRACE_EVENT(binder_wait_for_work,
TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo),
TP_ARGS(proc_work, transaction_stack, thread_todo),

View file

@ -33,6 +33,7 @@
#include <linux/cpufreq.h>
#include <linux/cpuidle.h>
#include <linux/timer.h>
#include <linux/wakeup_reason.h>
#include "../base.h"
#include "power.h"
@ -1706,6 +1707,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
pm_callback_t callback = NULL;
const char *info = NULL;
int error = 0;
char suspend_abort[MAX_SUSPEND_ABORT_LEN];
DECLARE_DPM_WATCHDOG_ON_STACK(wd);
TRACE_DEVICE(dev);
@ -1726,6 +1728,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
pm_wakeup_event(dev, 0);
if (pm_wakeup_pending()) {
pm_get_active_wakeup_sources(suspend_abort,
MAX_SUSPEND_ABORT_LEN);
log_suspend_abort_reason(suspend_abort);
async_error = -EBUSY;
goto Complete;
}

View file

@ -15,6 +15,7 @@
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <linux/pm_wakeirq.h>
#include <linux/types.h>
#include <trace/events/power.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
@ -806,6 +807,37 @@ void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard)
}
EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
void pm_get_active_wakeup_sources(char *pending_wakeup_source, size_t max)
{
struct wakeup_source *ws, *last_active_ws = NULL;
int len = 0;
bool active = false;
rcu_read_lock();
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
if (ws->active && len < max) {
if (!active)
len += scnprintf(pending_wakeup_source, max,
"Pending Wakeup Sources: ");
len += scnprintf(pending_wakeup_source + len, max - len,
"%s ", ws->name);
active = true;
} else if (!active &&
(!last_active_ws ||
ktime_to_ns(ws->last_time) >
ktime_to_ns(last_active_ws->last_time))) {
last_active_ws = ws;
}
}
if (!active && last_active_ws) {
scnprintf(pending_wakeup_source, max,
"Last active Wakeup Source: %s",
last_active_ws->name);
}
rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(pm_get_active_wakeup_sources);
void pm_print_active_wakeup_sources(void)
{
struct wakeup_source *ws;

View file

@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/suspend.h>
#include <trace/events/power.h>
#include <linux/wakeup_reason.h>
static LIST_HEAD(syscore_ops_list);
static DEFINE_MUTEX(syscore_ops_lock);
@ -74,6 +75,8 @@ int syscore_suspend(void)
return 0;
err_out:
log_suspend_abort_reason("System core suspend callback %pF failed",
ops->suspend);
pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend);
list_for_each_entry_continue(ops, &syscore_ops_list, node)

View file

@ -37,6 +37,13 @@ config CPU_FREQ_STAT
If in doubt, say N.
config CPU_FREQ_TIMES
bool "CPU frequency time-in-state statistics"
help
Export CPU time-in-state information through procfs.
If in doubt, say N.
choice
prompt "Default CPUFreq governor"
default CPU_FREQ_DEFAULT_GOV_USERSPACE if ARM_SA1100_CPUFREQ || ARM_SA1110_CPUFREQ

View file

@ -5,7 +5,10 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o freq_table.o
# CPUfreq stats
obj-$(CONFIG_CPU_FREQ_STAT) += cpufreq_stats.o
# CPUfreq governors
# CPUfreq times
obj-$(CONFIG_CPU_FREQ_TIMES) += cpufreq_times.o
# CPUfreq governors
obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o

View file

@ -19,6 +19,7 @@
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpufreq_times.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
@ -349,6 +350,7 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
}
cpufreq_stats_record_transition(policy, freqs->new);
cpufreq_times_record_transition(freqs);
policy->cur = freqs->new;
}
}
@ -1295,6 +1297,7 @@ static int cpufreq_online(unsigned int cpu)
goto out_destroy_policy;
cpufreq_stats_create_table(policy);
cpufreq_times_create_policy(policy);
write_lock_irqsave(&cpufreq_driver_lock, flags);
list_add(&policy->policy_list, &cpufreq_policy_list);

View file

@ -0,0 +1,464 @@
/* drivers/cpufreq/cpufreq_times.c
*
* Copyright (C) 2018 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/cpufreq.h>
#include <linux/cpufreq_times.h>
#include <linux/hashtable.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/threads.h>
#define UID_HASH_BITS 10
static DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS);
static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */
static DEFINE_SPINLOCK(uid_lock); /* uid_hash_table */
struct uid_entry {
uid_t uid;
unsigned int max_state;
struct hlist_node hash;
struct rcu_head rcu;
u64 time_in_state[0];
};
/**
* struct cpu_freqs - per-cpu frequency information
* @offset: start of these freqs' stats in task time_in_state array
* @max_state: number of entries in freq_table
* @last_index: index in freq_table of last frequency switched to
* @freq_table: list of available frequencies
*/
struct cpu_freqs {
unsigned int offset;
unsigned int max_state;
unsigned int last_index;
unsigned int freq_table[0];
};
static struct cpu_freqs *all_freqs[NR_CPUS];
static unsigned int next_offset;
/* Caller must hold rcu_read_lock() */
static struct uid_entry *find_uid_entry_rcu(uid_t uid)
{
struct uid_entry *uid_entry;
hash_for_each_possible_rcu(uid_hash_table, uid_entry, hash, uid) {
if (uid_entry->uid == uid)
return uid_entry;
}
return NULL;
}
/* Caller must hold uid lock */
static struct uid_entry *find_uid_entry_locked(uid_t uid)
{
struct uid_entry *uid_entry;
hash_for_each_possible(uid_hash_table, uid_entry, hash, uid) {
if (uid_entry->uid == uid)
return uid_entry;
}
return NULL;
}
/* Caller must hold uid lock */
static struct uid_entry *find_or_register_uid_locked(uid_t uid)
{
struct uid_entry *uid_entry, *temp;
unsigned int max_state = READ_ONCE(next_offset);
size_t alloc_size = sizeof(*uid_entry) + max_state *
sizeof(uid_entry->time_in_state[0]);
uid_entry = find_uid_entry_locked(uid);
if (uid_entry) {
if (uid_entry->max_state == max_state)
return uid_entry;
/* uid_entry->time_in_state is too small to track all freqs, so
* expand it.
*/
temp = __krealloc(uid_entry, alloc_size, GFP_ATOMIC);
if (!temp)
return uid_entry;
temp->max_state = max_state;
memset(temp->time_in_state + uid_entry->max_state, 0,
(max_state - uid_entry->max_state) *
sizeof(uid_entry->time_in_state[0]));
if (temp != uid_entry) {
hlist_replace_rcu(&uid_entry->hash, &temp->hash);
kfree_rcu(uid_entry, rcu);
}
return temp;
}
uid_entry = kzalloc(alloc_size, GFP_ATOMIC);
if (!uid_entry)
return NULL;
uid_entry->uid = uid;
uid_entry->max_state = max_state;
hash_add_rcu(uid_hash_table, &uid_entry->hash, uid);
return uid_entry;
}
static bool freq_index_invalid(unsigned int index)
{
unsigned int cpu;
struct cpu_freqs *freqs;
for_each_possible_cpu(cpu) {
freqs = all_freqs[cpu];
if (!freqs || index < freqs->offset ||
freqs->offset + freqs->max_state <= index)
continue;
return freqs->freq_table[index - freqs->offset] ==
CPUFREQ_ENTRY_INVALID;
}
return true;
}
static int single_uid_time_in_state_show(struct seq_file *m, void *ptr)
{
struct uid_entry *uid_entry;
unsigned int i;
u64 time;
uid_t uid = from_kuid_munged(current_user_ns(), *(kuid_t *)m->private);
if (uid == overflowuid)
return -EINVAL;
rcu_read_lock();
uid_entry = find_uid_entry_rcu(uid);
if (!uid_entry) {
rcu_read_unlock();
return 0;
}
for (i = 0; i < uid_entry->max_state; ++i) {
if (freq_index_invalid(i))
continue;
time = nsec_to_clock_t(uid_entry->time_in_state[i]);
seq_write(m, &time, sizeof(time));
}
rcu_read_unlock();
return 0;
}
static void *uid_seq_start(struct seq_file *seq, loff_t *pos)
{
if (*pos >= HASH_SIZE(uid_hash_table))
return NULL;
return &uid_hash_table[*pos];
}
static void *uid_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
(*pos)++;
if (*pos >= HASH_SIZE(uid_hash_table))
return NULL;
return &uid_hash_table[*pos];
}
static void uid_seq_stop(struct seq_file *seq, void *v) { }
static int uid_time_in_state_seq_show(struct seq_file *m, void *v)
{
struct uid_entry *uid_entry;
struct cpu_freqs *freqs, *last_freqs = NULL;
int i, cpu;
if (v == uid_hash_table) {
seq_puts(m, "uid:");
for_each_possible_cpu(cpu) {
freqs = all_freqs[cpu];
if (!freqs || freqs == last_freqs)
continue;
last_freqs = freqs;
for (i = 0; i < freqs->max_state; i++) {
if (freqs->freq_table[i] ==
CPUFREQ_ENTRY_INVALID)
continue;
seq_printf(m, " %d", freqs->freq_table[i]);
}
}
seq_putc(m, '\n');
}
rcu_read_lock();
hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) {
if (uid_entry->max_state)
seq_printf(m, "%d:", uid_entry->uid);
for (i = 0; i < uid_entry->max_state; ++i) {
if (freq_index_invalid(i))
continue;
seq_printf(m, " %lu", (unsigned long)nsec_to_clock_t(
uid_entry->time_in_state[i]));
}
if (uid_entry->max_state)
seq_putc(m, '\n');
}
rcu_read_unlock();
return 0;
}
void cpufreq_task_times_init(struct task_struct *p)
{
unsigned long flags;
spin_lock_irqsave(&task_time_in_state_lock, flags);
p->time_in_state = NULL;
spin_unlock_irqrestore(&task_time_in_state_lock, flags);
p->max_state = 0;
}
void cpufreq_task_times_alloc(struct task_struct *p)
{
void *temp;
unsigned long flags;
unsigned int max_state = READ_ONCE(next_offset);
/* We use one array to avoid multiple allocs per task */
temp = kcalloc(max_state, sizeof(p->time_in_state[0]), GFP_ATOMIC);
if (!temp)
return;
spin_lock_irqsave(&task_time_in_state_lock, flags);
p->time_in_state = temp;
spin_unlock_irqrestore(&task_time_in_state_lock, flags);
p->max_state = max_state;
}
/* Caller must hold task_time_in_state_lock */
static int cpufreq_task_times_realloc_locked(struct task_struct *p)
{
void *temp;
unsigned int max_state = READ_ONCE(next_offset);
temp = krealloc(p->time_in_state, max_state * sizeof(u64), GFP_ATOMIC);
if (!temp)
return -ENOMEM;
p->time_in_state = temp;
memset(p->time_in_state + p->max_state, 0,
(max_state - p->max_state) * sizeof(u64));
p->max_state = max_state;
return 0;
}
void cpufreq_task_times_exit(struct task_struct *p)
{
unsigned long flags;
void *temp;
if (!p->time_in_state)
return;
spin_lock_irqsave(&task_time_in_state_lock, flags);
temp = p->time_in_state;
p->time_in_state = NULL;
spin_unlock_irqrestore(&task_time_in_state_lock, flags);
kfree(temp);
}
int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *p)
{
unsigned int cpu, i;
u64 cputime;
unsigned long flags;
struct cpu_freqs *freqs;
struct cpu_freqs *last_freqs = NULL;
spin_lock_irqsave(&task_time_in_state_lock, flags);
for_each_possible_cpu(cpu) {
freqs = all_freqs[cpu];
if (!freqs || freqs == last_freqs)
continue;
last_freqs = freqs;
seq_printf(m, "cpu%u\n", cpu);
for (i = 0; i < freqs->max_state; i++) {
if (freqs->freq_table[i] == CPUFREQ_ENTRY_INVALID)
continue;
cputime = 0;
if (freqs->offset + i < p->max_state &&
p->time_in_state)
cputime = p->time_in_state[freqs->offset + i];
seq_printf(m, "%u %lu\n", freqs->freq_table[i],
(unsigned long)nsec_to_clock_t(cputime));
}
}
spin_unlock_irqrestore(&task_time_in_state_lock, flags);
return 0;
}
void cpufreq_acct_update_power(struct task_struct *p, u64 cputime)
{
unsigned long flags;
unsigned int state;
struct uid_entry *uid_entry;
struct cpu_freqs *freqs = all_freqs[task_cpu(p)];
uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p));
if (!freqs || p->flags & PF_EXITING)
return;
state = freqs->offset + READ_ONCE(freqs->last_index);
spin_lock_irqsave(&task_time_in_state_lock, flags);
if ((state < p->max_state || !cpufreq_task_times_realloc_locked(p)) &&
p->time_in_state)
p->time_in_state[state] += cputime;
spin_unlock_irqrestore(&task_time_in_state_lock, flags);
spin_lock_irqsave(&uid_lock, flags);
uid_entry = find_or_register_uid_locked(uid);
if (uid_entry && state < uid_entry->max_state)
uid_entry->time_in_state[state] += cputime;
spin_unlock_irqrestore(&uid_lock, flags);
}
void cpufreq_times_create_policy(struct cpufreq_policy *policy)
{
int cpu, index;
unsigned int count = 0;
struct cpufreq_frequency_table *pos, *table;
struct cpu_freqs *freqs;
void *tmp;
if (all_freqs[policy->cpu])
return;
table = policy->freq_table;
if (!table)
return;
cpufreq_for_each_entry(pos, table)
count++;
tmp = kzalloc(sizeof(*freqs) + sizeof(freqs->freq_table[0]) * count,
GFP_KERNEL);
if (!tmp)
return;
freqs = tmp;
freqs->max_state = count;
index = cpufreq_frequency_table_get_index(policy, policy->cur);
if (index >= 0)
WRITE_ONCE(freqs->last_index, index);
cpufreq_for_each_entry(pos, table)
freqs->freq_table[pos - table] = pos->frequency;
freqs->offset = next_offset;
WRITE_ONCE(next_offset, freqs->offset + count);
for_each_cpu(cpu, policy->related_cpus)
all_freqs[cpu] = freqs;
}
void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end)
{
struct uid_entry *uid_entry;
struct hlist_node *tmp;
unsigned long flags;
spin_lock_irqsave(&uid_lock, flags);
for (; uid_start <= uid_end; uid_start++) {
hash_for_each_possible_safe(uid_hash_table, uid_entry, tmp,
hash, uid_start) {
if (uid_start == uid_entry->uid) {
hash_del_rcu(&uid_entry->hash);
kfree_rcu(uid_entry, rcu);
}
}
}
spin_unlock_irqrestore(&uid_lock, flags);
}
void cpufreq_times_record_transition(struct cpufreq_freqs *freq)
{
int index;
struct cpu_freqs *freqs = all_freqs[freq->cpu];
struct cpufreq_policy *policy;
if (!freqs)
return;
policy = cpufreq_cpu_get(freq->cpu);
if (!policy)
return;
index = cpufreq_frequency_table_get_index(policy, freq->new);
if (index >= 0)
WRITE_ONCE(freqs->last_index, index);
cpufreq_cpu_put(policy);
}
static const struct seq_operations uid_time_in_state_seq_ops = {
.start = uid_seq_start,
.next = uid_seq_next,
.stop = uid_seq_stop,
.show = uid_time_in_state_seq_show,
};
static int uid_time_in_state_open(struct inode *inode, struct file *file)
{
return seq_open(file, &uid_time_in_state_seq_ops);
}
int single_uid_time_in_state_open(struct inode *inode, struct file *file)
{
return single_open(file, single_uid_time_in_state_show,
&(inode->i_uid));
}
static const struct file_operations uid_time_in_state_fops = {
.open = uid_time_in_state_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static int __init cpufreq_times_init(void)
{
proc_create_data("uid_time_in_state", 0444, NULL,
&uid_time_in_state_fops, NULL);
return 0;
}
early_initcall(cpufreq_times_init);

View file

@ -179,7 +179,12 @@ static inline int performance_multiplier(unsigned long nr_iowaiters, unsigned lo
/* for higher loadavg, we are more reluctant */
mult += 2 * get_loadavg(load);
/*
* this doesn't work as intended - it is almost always 0, but can
* sometimes, depending on workload, spike very high into the hundreds
* even when the average cpu load is under 10%.
*/
/* mult += 2 * get_loadavg(); */
/* for IO wait tasks (per cpu!) we add 5x each */
mult += 10 * nr_iowaiters;

View file

@ -184,6 +184,19 @@ config INPUT_APMPOWER
To compile this driver as a module, choose M here: the
module will be called apm-power.
config INPUT_KEYRESET
bool "Reset key"
depends on INPUT
select INPUT_KEYCOMBO
---help---
Say Y here if you want to reboot when some keys are pressed;
config INPUT_KEYCOMBO
bool "Key combo"
depends on INPUT
---help---
Say Y here if you want to take action when some keys are pressed;
comment "Input Device Drivers"
source "drivers/input/keyboard/Kconfig"

View file

@ -27,5 +27,7 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
obj-$(CONFIG_INPUT_MISC) += misc/
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
obj-$(CONFIG_INPUT_KEYRESET) += keyreset.o
obj-$(CONFIG_INPUT_KEYCOMBO) += keycombo.o
obj-$(CONFIG_RMI4_CORE) += rmi4/

261
drivers/input/keycombo.c Normal file
View file

@ -0,0 +1,261 @@
/* drivers/input/keycombo.c
*
* Copyright (C) 2014 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/input.h>
#include <linux/keycombo.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/sched.h>
#include <linux/slab.h>
struct keycombo_state {
struct input_handler input_handler;
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
unsigned long upbit[BITS_TO_LONGS(KEY_CNT)];
unsigned long key[BITS_TO_LONGS(KEY_CNT)];
spinlock_t lock;
struct workqueue_struct *wq;
int key_down_target;
int key_down;
int key_up;
struct delayed_work key_down_work;
int delay;
struct work_struct key_up_work;
void (*key_up_fn)(void *);
void (*key_down_fn)(void *);
void *priv;
int key_is_down;
struct wakeup_source combo_held_wake_source;
struct wakeup_source combo_up_wake_source;
};
static void do_key_down(struct work_struct *work)
{
struct delayed_work *dwork = container_of(work, struct delayed_work,
work);
struct keycombo_state *state = container_of(dwork,
struct keycombo_state, key_down_work);
if (state->key_down_fn)
state->key_down_fn(state->priv);
}
static void do_key_up(struct work_struct *work)
{
struct keycombo_state *state = container_of(work, struct keycombo_state,
key_up_work);
if (state->key_up_fn)
state->key_up_fn(state->priv);
__pm_relax(&state->combo_up_wake_source);
}
static void keycombo_event(struct input_handle *handle, unsigned int type,
unsigned int code, int value)
{
unsigned long flags;
struct keycombo_state *state = handle->private;
if (type != EV_KEY)
return;
if (code >= KEY_MAX)
return;
if (!test_bit(code, state->keybit))
return;
spin_lock_irqsave(&state->lock, flags);
if (!test_bit(code, state->key) == !value)
goto done;
__change_bit(code, state->key);
if (test_bit(code, state->upbit)) {
if (value)
state->key_up++;
else
state->key_up--;
} else {
if (value)
state->key_down++;
else
state->key_down--;
}
if (state->key_down == state->key_down_target && state->key_up == 0) {
__pm_stay_awake(&state->combo_held_wake_source);
state->key_is_down = 1;
if (queue_delayed_work(state->wq, &state->key_down_work,
state->delay))
pr_debug("Key down work already queued!");
} else if (state->key_is_down) {
if (!cancel_delayed_work(&state->key_down_work)) {
__pm_stay_awake(&state->combo_up_wake_source);
queue_work(state->wq, &state->key_up_work);
}
__pm_relax(&state->combo_held_wake_source);
state->key_is_down = 0;
}
done:
spin_unlock_irqrestore(&state->lock, flags);
}
static int keycombo_connect(struct input_handler *handler,
struct input_dev *dev,
const struct input_device_id *id)
{
int i;
int ret;
struct input_handle *handle;
struct keycombo_state *state =
container_of(handler, struct keycombo_state, input_handler);
for (i = 0; i < KEY_MAX; i++) {
if (test_bit(i, state->keybit) && test_bit(i, dev->keybit))
break;
}
if (i == KEY_MAX)
return -ENODEV;
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
if (!handle)
return -ENOMEM;
handle->dev = dev;
handle->handler = handler;
handle->name = KEYCOMBO_NAME;
handle->private = state;
ret = input_register_handle(handle);
if (ret)
goto err_input_register_handle;
ret = input_open_device(handle);
if (ret)
goto err_input_open_device;
return 0;
err_input_open_device:
input_unregister_handle(handle);
err_input_register_handle:
kfree(handle);
return ret;
}
static void keycombo_disconnect(struct input_handle *handle)
{
input_close_device(handle);
input_unregister_handle(handle);
kfree(handle);
}
static const struct input_device_id keycombo_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT_MASK(EV_KEY) },
},
{ },
};
MODULE_DEVICE_TABLE(input, keycombo_ids);
static int keycombo_probe(struct platform_device *pdev)
{
int ret;
int key, *keyp;
struct keycombo_state *state;
struct keycombo_platform_data *pdata = pdev->dev.platform_data;
if (!pdata)
return -EINVAL;
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
spin_lock_init(&state->lock);
keyp = pdata->keys_down;
while ((key = *keyp++)) {
if (key >= KEY_MAX)
continue;
state->key_down_target++;
__set_bit(key, state->keybit);
}
if (pdata->keys_up) {
keyp = pdata->keys_up;
while ((key = *keyp++)) {
if (key >= KEY_MAX)
continue;
__set_bit(key, state->keybit);
__set_bit(key, state->upbit);
}
}
state->wq = alloc_ordered_workqueue("keycombo", 0);
if (!state->wq)
return -ENOMEM;
state->priv = pdata->priv;
if (pdata->key_down_fn)
state->key_down_fn = pdata->key_down_fn;
INIT_DELAYED_WORK(&state->key_down_work, do_key_down);
if (pdata->key_up_fn)
state->key_up_fn = pdata->key_up_fn;
INIT_WORK(&state->key_up_work, do_key_up);
wakeup_source_init(&state->combo_held_wake_source, "key combo");
wakeup_source_init(&state->combo_up_wake_source, "key combo up");
state->delay = msecs_to_jiffies(pdata->key_down_delay);
state->input_handler.event = keycombo_event;
state->input_handler.connect = keycombo_connect;
state->input_handler.disconnect = keycombo_disconnect;
state->input_handler.name = KEYCOMBO_NAME;
state->input_handler.id_table = keycombo_ids;
ret = input_register_handler(&state->input_handler);
if (ret) {
kfree(state);
return ret;
}
platform_set_drvdata(pdev, state);
return 0;
}
int keycombo_remove(struct platform_device *pdev)
{
struct keycombo_state *state = platform_get_drvdata(pdev);
input_unregister_handler(&state->input_handler);
destroy_workqueue(state->wq);
kfree(state);
return 0;
}
struct platform_driver keycombo_driver = {
.driver.name = KEYCOMBO_NAME,
.probe = keycombo_probe,
.remove = keycombo_remove,
};
static int __init keycombo_init(void)
{
return platform_driver_register(&keycombo_driver);
}
static void __exit keycombo_exit(void)
{
return platform_driver_unregister(&keycombo_driver);
}
module_init(keycombo_init);
module_exit(keycombo_exit);

144
drivers/input/keyreset.c Normal file
View file

@ -0,0 +1,144 @@
/* drivers/input/keyreset.c
*
* Copyright (C) 2014 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/input.h>
#include <linux/keyreset.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/keycombo.h>
struct keyreset_state {
int restart_requested;
int (*reset_fn)(void);
struct platform_device *pdev_child;
struct work_struct restart_work;
};
static void do_restart(struct work_struct *unused)
{
orderly_reboot();
}
static void do_reset_fn(void *priv)
{
struct keyreset_state *state = priv;
if (state->restart_requested)
panic("keyboard reset failed, %d", state->restart_requested);
if (state->reset_fn) {
state->restart_requested = state->reset_fn();
} else {
pr_info("keyboard reset\n");
schedule_work(&state->restart_work);
state->restart_requested = 1;
}
}
static int keyreset_probe(struct platform_device *pdev)
{
int ret = -ENOMEM;
struct keycombo_platform_data *pdata_child;
struct keyreset_platform_data *pdata = pdev->dev.platform_data;
int up_size = 0, down_size = 0, size;
int key, *keyp;
struct keyreset_state *state;
if (!pdata)
return -EINVAL;
state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
state->pdev_child = platform_device_alloc(KEYCOMBO_NAME,
PLATFORM_DEVID_AUTO);
if (!state->pdev_child)
return -ENOMEM;
state->pdev_child->dev.parent = &pdev->dev;
INIT_WORK(&state->restart_work, do_restart);
keyp = pdata->keys_down;
while ((key = *keyp++)) {
if (key >= KEY_MAX)
continue;
down_size++;
}
if (pdata->keys_up) {
keyp = pdata->keys_up;
while ((key = *keyp++)) {
if (key >= KEY_MAX)
continue;
up_size++;
}
}
size = sizeof(struct keycombo_platform_data)
+ sizeof(int) * (down_size + 1);
pdata_child = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!pdata_child)
goto error;
memcpy(pdata_child->keys_down, pdata->keys_down,
sizeof(int) * down_size);
if (up_size > 0) {
pdata_child->keys_up = devm_kzalloc(&pdev->dev, up_size + 1,
GFP_KERNEL);
if (!pdata_child->keys_up)
goto error;
memcpy(pdata_child->keys_up, pdata->keys_up,
sizeof(int) * up_size);
if (!pdata_child->keys_up)
goto error;
}
state->reset_fn = pdata->reset_fn;
pdata_child->key_down_fn = do_reset_fn;
pdata_child->priv = state;
pdata_child->key_down_delay = pdata->key_down_delay;
ret = platform_device_add_data(state->pdev_child, pdata_child, size);
if (ret)
goto error;
platform_set_drvdata(pdev, state);
return platform_device_add(state->pdev_child);
error:
platform_device_put(state->pdev_child);
return ret;
}
int keyreset_remove(struct platform_device *pdev)
{
struct keyreset_state *state = platform_get_drvdata(pdev);
platform_device_put(state->pdev_child);
return 0;
}
struct platform_driver keyreset_driver = {
.driver.name = KEYRESET_NAME,
.probe = keyreset_probe,
.remove = keyreset_remove,
};
static int __init keyreset_init(void)
{
return platform_driver_register(&keyreset_driver);
}
static void __exit keyreset_exit(void)
{
return platform_driver_unregister(&keyreset_driver);
}
module_init(keyreset_init);
module_exit(keyreset_exit);

View file

@ -521,6 +521,11 @@ config INPUT_SGI_BTNS
To compile this driver as a module, choose M here: the
module will be called sgi_btns.
config INPUT_GPIO
tristate "GPIO driver support"
help
Say Y here if you want to support gpio based keys, wheels etc...
config HP_SDC_RTC
tristate "HP SDC Real Time Clock"
depends on (GSC || HP300) && SERIO

View file

@ -36,6 +36,7 @@ obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o
obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o
obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o
obj-$(CONFIG_INPUT_GPIO_DECODER) += gpio_decoder.o
obj-$(CONFIG_INPUT_GPIO) += gpio_event.o gpio_matrix.o gpio_input.o gpio_output.o gpio_axis.o
obj-$(CONFIG_INPUT_HISI_POWERKEY) += hisi_powerkey.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o

View file

@ -0,0 +1,192 @@
/* drivers/input/misc/gpio_axis.c
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/gpio_event.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
struct gpio_axis_state {
struct gpio_event_input_devs *input_devs;
struct gpio_event_axis_info *info;
uint32_t pos;
};
uint16_t gpio_axis_4bit_gray_map_table[] = {
[0x0] = 0x0, [0x1] = 0x1, /* 0000 0001 */
[0x3] = 0x2, [0x2] = 0x3, /* 0011 0010 */
[0x6] = 0x4, [0x7] = 0x5, /* 0110 0111 */
[0x5] = 0x6, [0x4] = 0x7, /* 0101 0100 */
[0xc] = 0x8, [0xd] = 0x9, /* 1100 1101 */
[0xf] = 0xa, [0xe] = 0xb, /* 1111 1110 */
[0xa] = 0xc, [0xb] = 0xd, /* 1010 1011 */
[0x9] = 0xe, [0x8] = 0xf, /* 1001 1000 */
};
uint16_t gpio_axis_4bit_gray_map(struct gpio_event_axis_info *info, uint16_t in)
{
return gpio_axis_4bit_gray_map_table[in];
}
uint16_t gpio_axis_5bit_singletrack_map_table[] = {
[0x10] = 0x00, [0x14] = 0x01, [0x1c] = 0x02, /* 10000 10100 11100 */
[0x1e] = 0x03, [0x1a] = 0x04, [0x18] = 0x05, /* 11110 11010 11000 */
[0x08] = 0x06, [0x0a] = 0x07, [0x0e] = 0x08, /* 01000 01010 01110 */
[0x0f] = 0x09, [0x0d] = 0x0a, [0x0c] = 0x0b, /* 01111 01101 01100 */
[0x04] = 0x0c, [0x05] = 0x0d, [0x07] = 0x0e, /* 00100 00101 00111 */
[0x17] = 0x0f, [0x16] = 0x10, [0x06] = 0x11, /* 10111 10110 00110 */
[0x02] = 0x12, [0x12] = 0x13, [0x13] = 0x14, /* 00010 10010 10011 */
[0x1b] = 0x15, [0x0b] = 0x16, [0x03] = 0x17, /* 11011 01011 00011 */
[0x01] = 0x18, [0x09] = 0x19, [0x19] = 0x1a, /* 00001 01001 11001 */
[0x1d] = 0x1b, [0x15] = 0x1c, [0x11] = 0x1d, /* 11101 10101 10001 */
};
uint16_t gpio_axis_5bit_singletrack_map(
struct gpio_event_axis_info *info, uint16_t in)
{
return gpio_axis_5bit_singletrack_map_table[in];
}
static void gpio_event_update_axis(struct gpio_axis_state *as, int report)
{
struct gpio_event_axis_info *ai = as->info;
int i;
int change;
uint16_t state = 0;
uint16_t pos;
uint16_t old_pos = as->pos;
for (i = ai->count - 1; i >= 0; i--)
state = (state << 1) | gpio_get_value(ai->gpio[i]);
pos = ai->map(ai, state);
if (ai->flags & GPIOEAF_PRINT_RAW)
pr_info("axis %d-%d raw %x, pos %d -> %d\n",
ai->type, ai->code, state, old_pos, pos);
if (report && pos != old_pos) {
if (ai->type == EV_REL) {
change = (ai->decoded_size + pos - old_pos) %
ai->decoded_size;
if (change > ai->decoded_size / 2)
change -= ai->decoded_size;
if (change == ai->decoded_size / 2) {
if (ai->flags & GPIOEAF_PRINT_EVENT)
pr_info("axis %d-%d unknown direction, "
"pos %d -> %d\n", ai->type,
ai->code, old_pos, pos);
change = 0; /* no closest direction */
}
if (ai->flags & GPIOEAF_PRINT_EVENT)
pr_info("axis %d-%d change %d\n",
ai->type, ai->code, change);
input_report_rel(as->input_devs->dev[ai->dev],
ai->code, change);
} else {
if (ai->flags & GPIOEAF_PRINT_EVENT)
pr_info("axis %d-%d now %d\n",
ai->type, ai->code, pos);
input_event(as->input_devs->dev[ai->dev],
ai->type, ai->code, pos);
}
input_sync(as->input_devs->dev[ai->dev]);
}
as->pos = pos;
}
static irqreturn_t gpio_axis_irq_handler(int irq, void *dev_id)
{
struct gpio_axis_state *as = dev_id;
gpio_event_update_axis(as, 1);
return IRQ_HANDLED;
}
int gpio_event_axis_func(struct gpio_event_input_devs *input_devs,
struct gpio_event_info *info, void **data, int func)
{
int ret;
int i;
int irq;
struct gpio_event_axis_info *ai;
struct gpio_axis_state *as;
ai = container_of(info, struct gpio_event_axis_info, info);
if (func == GPIO_EVENT_FUNC_SUSPEND) {
for (i = 0; i < ai->count; i++)
disable_irq(gpio_to_irq(ai->gpio[i]));
return 0;
}
if (func == GPIO_EVENT_FUNC_RESUME) {
for (i = 0; i < ai->count; i++)
enable_irq(gpio_to_irq(ai->gpio[i]));
return 0;
}
if (func == GPIO_EVENT_FUNC_INIT) {
*data = as = kmalloc(sizeof(*as), GFP_KERNEL);
if (as == NULL) {
ret = -ENOMEM;
goto err_alloc_axis_state_failed;
}
as->input_devs = input_devs;
as->info = ai;
if (ai->dev >= input_devs->count) {
pr_err("gpio_event_axis: bad device index %d >= %d "
"for %d:%d\n", ai->dev, input_devs->count,
ai->type, ai->code);
ret = -EINVAL;
goto err_bad_device_index;
}
input_set_capability(input_devs->dev[ai->dev],
ai->type, ai->code);
if (ai->type == EV_ABS) {
input_set_abs_params(input_devs->dev[ai->dev], ai->code,
0, ai->decoded_size - 1, 0, 0);
}
for (i = 0; i < ai->count; i++) {
ret = gpio_request(ai->gpio[i], "gpio_event_axis");
if (ret < 0)
goto err_request_gpio_failed;
ret = gpio_direction_input(ai->gpio[i]);
if (ret < 0)
goto err_gpio_direction_input_failed;
ret = irq = gpio_to_irq(ai->gpio[i]);
if (ret < 0)
goto err_get_irq_num_failed;
ret = request_irq(irq, gpio_axis_irq_handler,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
"gpio_event_axis", as);
if (ret < 0)
goto err_request_irq_failed;
}
gpio_event_update_axis(as, 0);
return 0;
}
ret = 0;
as = *data;
for (i = ai->count - 1; i >= 0; i--) {
free_irq(gpio_to_irq(ai->gpio[i]), as);
err_request_irq_failed:
err_get_irq_num_failed:
err_gpio_direction_input_failed:
gpio_free(ai->gpio[i]);
err_request_gpio_failed:
;
}
err_bad_device_index:
kfree(as);
*data = NULL;
err_alloc_axis_state_failed:
return ret;
}

View file

@ -0,0 +1,228 @@
/* drivers/input/misc/gpio_event.c
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/input.h>
#include <linux/gpio_event.h>
#include <linux/hrtimer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
struct gpio_event {
struct gpio_event_input_devs *input_devs;
const struct gpio_event_platform_data *info;
void *state[0];
};
static int gpio_input_event(
struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
int i;
int devnr;
int ret = 0;
int tmp_ret;
struct gpio_event_info **ii;
struct gpio_event *ip = input_get_drvdata(dev);
for (devnr = 0; devnr < ip->input_devs->count; devnr++)
if (ip->input_devs->dev[devnr] == dev)
break;
if (devnr == ip->input_devs->count) {
pr_err("gpio_input_event: unknown device %p\n", dev);
return -EIO;
}
for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) {
if ((*ii)->event) {
tmp_ret = (*ii)->event(ip->input_devs, *ii,
&ip->state[i],
devnr, type, code, value);
if (tmp_ret)
ret = tmp_ret;
}
}
return ret;
}
static int gpio_event_call_all_func(struct gpio_event *ip, int func)
{
int i;
int ret;
struct gpio_event_info **ii;
if (func == GPIO_EVENT_FUNC_INIT || func == GPIO_EVENT_FUNC_RESUME) {
ii = ip->info->info;
for (i = 0; i < ip->info->info_count; i++, ii++) {
if ((*ii)->func == NULL) {
ret = -ENODEV;
pr_err("gpio_event_probe: Incomplete pdata, "
"no function\n");
goto err_no_func;
}
if (func == GPIO_EVENT_FUNC_RESUME && (*ii)->no_suspend)
continue;
ret = (*ii)->func(ip->input_devs, *ii, &ip->state[i],
func);
if (ret) {
pr_err("gpio_event_probe: function failed\n");
goto err_func_failed;
}
}
return 0;
}
ret = 0;
i = ip->info->info_count;
ii = ip->info->info + i;
while (i > 0) {
i--;
ii--;
if ((func & ~1) == GPIO_EVENT_FUNC_SUSPEND && (*ii)->no_suspend)
continue;
(*ii)->func(ip->input_devs, *ii, &ip->state[i], func & ~1);
err_func_failed:
err_no_func:
;
}
return ret;
}
static void __maybe_unused gpio_event_suspend(struct gpio_event *ip)
{
gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_SUSPEND);
if (ip->info->power)
ip->info->power(ip->info, 0);
}
static void __maybe_unused gpio_event_resume(struct gpio_event *ip)
{
if (ip->info->power)
ip->info->power(ip->info, 1);
gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_RESUME);
}
static int gpio_event_probe(struct platform_device *pdev)
{
int err;
struct gpio_event *ip;
struct gpio_event_platform_data *event_info;
int dev_count = 1;
int i;
int registered = 0;
event_info = pdev->dev.platform_data;
if (event_info == NULL) {
pr_err("gpio_event_probe: No pdata\n");
return -ENODEV;
}
if ((!event_info->name && !event_info->names[0]) ||
!event_info->info || !event_info->info_count) {
pr_err("gpio_event_probe: Incomplete pdata\n");
return -ENODEV;
}
if (!event_info->name)
while (event_info->names[dev_count])
dev_count++;
ip = kzalloc(sizeof(*ip) +
sizeof(ip->state[0]) * event_info->info_count +
sizeof(*ip->input_devs) +
sizeof(ip->input_devs->dev[0]) * dev_count, GFP_KERNEL);
if (ip == NULL) {
err = -ENOMEM;
pr_err("gpio_event_probe: Failed to allocate private data\n");
goto err_kp_alloc_failed;
}
ip->input_devs = (void*)&ip->state[event_info->info_count];
platform_set_drvdata(pdev, ip);
for (i = 0; i < dev_count; i++) {
struct input_dev *input_dev = input_allocate_device();
if (input_dev == NULL) {
err = -ENOMEM;
pr_err("gpio_event_probe: "
"Failed to allocate input device\n");
goto err_input_dev_alloc_failed;
}
input_set_drvdata(input_dev, ip);
input_dev->name = event_info->name ?
event_info->name : event_info->names[i];
input_dev->event = gpio_input_event;
ip->input_devs->dev[i] = input_dev;
}
ip->input_devs->count = dev_count;
ip->info = event_info;
if (event_info->power)
ip->info->power(ip->info, 1);
err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT);
if (err)
goto err_call_all_func_failed;
for (i = 0; i < dev_count; i++) {
err = input_register_device(ip->input_devs->dev[i]);
if (err) {
pr_err("gpio_event_probe: Unable to register %s "
"input device\n", ip->input_devs->dev[i]->name);
goto err_input_register_device_failed;
}
registered++;
}
return 0;
err_input_register_device_failed:
gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
err_call_all_func_failed:
if (event_info->power)
ip->info->power(ip->info, 0);
for (i = 0; i < registered; i++)
input_unregister_device(ip->input_devs->dev[i]);
for (i = dev_count - 1; i >= registered; i--) {
input_free_device(ip->input_devs->dev[i]);
err_input_dev_alloc_failed:
;
}
kfree(ip);
err_kp_alloc_failed:
return err;
}
static int gpio_event_remove(struct platform_device *pdev)
{
struct gpio_event *ip = platform_get_drvdata(pdev);
int i;
gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
if (ip->info->power)
ip->info->power(ip->info, 0);
for (i = 0; i < ip->input_devs->count; i++)
input_unregister_device(ip->input_devs->dev[i]);
kfree(ip);
return 0;
}
static struct platform_driver gpio_event_driver = {
.probe = gpio_event_probe,
.remove = gpio_event_remove,
.driver = {
.name = GPIO_EVENT_DEV_NAME,
},
};
module_platform_driver(gpio_event_driver);
MODULE_DESCRIPTION("GPIO Event Driver");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,390 @@
/* drivers/input/misc/gpio_input.c
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/gpio_event.h>
#include <linux/hrtimer.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/pm_wakeup.h>
enum {
DEBOUNCE_UNSTABLE = BIT(0), /* Got irq, while debouncing */
DEBOUNCE_PRESSED = BIT(1),
DEBOUNCE_NOTPRESSED = BIT(2),
DEBOUNCE_WAIT_IRQ = BIT(3), /* Stable irq state */
DEBOUNCE_POLL = BIT(4), /* Stable polling state */
DEBOUNCE_UNKNOWN =
DEBOUNCE_PRESSED | DEBOUNCE_NOTPRESSED,
};
struct gpio_key_state {
struct gpio_input_state *ds;
uint8_t debounce;
};
struct gpio_input_state {
struct gpio_event_input_devs *input_devs;
const struct gpio_event_input_info *info;
struct hrtimer timer;
int use_irq;
int debounce_count;
spinlock_t irq_lock;
struct wakeup_source *ws;
struct gpio_key_state key_state[0];
};
static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer)
{
int i;
int pressed;
struct gpio_input_state *ds =
container_of(timer, struct gpio_input_state, timer);
unsigned gpio_flags = ds->info->flags;
unsigned npolarity;
int nkeys = ds->info->keymap_size;
const struct gpio_event_direct_entry *key_entry;
struct gpio_key_state *key_state;
unsigned long irqflags;
uint8_t debounce;
bool sync_needed;
#if 0
key_entry = kp->keys_info->keymap;
key_state = kp->key_state;
for (i = 0; i < nkeys; i++, key_entry++, key_state++)
pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio,
gpio_read_detect_status(key_entry->gpio));
#endif
key_entry = ds->info->keymap;
key_state = ds->key_state;
sync_needed = false;
spin_lock_irqsave(&ds->irq_lock, irqflags);
for (i = 0; i < nkeys; i++, key_entry++, key_state++) {
debounce = key_state->debounce;
if (debounce & DEBOUNCE_WAIT_IRQ)
continue;
if (key_state->debounce & DEBOUNCE_UNSTABLE) {
debounce = key_state->debounce = DEBOUNCE_UNKNOWN;
enable_irq(gpio_to_irq(key_entry->gpio));
if (gpio_flags & GPIOEDF_PRINT_KEY_UNSTABLE)
pr_info("gpio_keys_scan_keys: key %x-%x, %d "
"(%d) continue debounce\n",
ds->info->type, key_entry->code,
i, key_entry->gpio);
}
npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH);
pressed = gpio_get_value(key_entry->gpio) ^ npolarity;
if (debounce & DEBOUNCE_POLL) {
if (pressed == !(debounce & DEBOUNCE_PRESSED)) {
ds->debounce_count++;
key_state->debounce = DEBOUNCE_UNKNOWN;
if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
pr_info("gpio_keys_scan_keys: key %x-"
"%x, %d (%d) start debounce\n",
ds->info->type, key_entry->code,
i, key_entry->gpio);
}
continue;
}
if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) {
if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
pr_info("gpio_keys_scan_keys: key %x-%x, %d "
"(%d) debounce pressed 1\n",
ds->info->type, key_entry->code,
i, key_entry->gpio);
key_state->debounce = DEBOUNCE_PRESSED;
continue;
}
if (!pressed && (debounce & DEBOUNCE_PRESSED)) {
if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
pr_info("gpio_keys_scan_keys: key %x-%x, %d "
"(%d) debounce pressed 0\n",
ds->info->type, key_entry->code,
i, key_entry->gpio);
key_state->debounce = DEBOUNCE_NOTPRESSED;
continue;
}
/* key is stable */
ds->debounce_count--;
if (ds->use_irq)
key_state->debounce |= DEBOUNCE_WAIT_IRQ;
else
key_state->debounce |= DEBOUNCE_POLL;
if (gpio_flags & GPIOEDF_PRINT_KEYS)
pr_info("gpio_keys_scan_keys: key %x-%x, %d (%d) "
"changed to %d\n", ds->info->type,
key_entry->code, i, key_entry->gpio, pressed);
input_event(ds->input_devs->dev[key_entry->dev], ds->info->type,
key_entry->code, pressed);
sync_needed = true;
}
if (sync_needed) {
for (i = 0; i < ds->input_devs->count; i++)
input_sync(ds->input_devs->dev[i]);
}
#if 0
key_entry = kp->keys_info->keymap;
key_state = kp->key_state;
for (i = 0; i < nkeys; i++, key_entry++, key_state++) {
pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio,
gpio_read_detect_status(key_entry->gpio));
}
#endif
if (ds->debounce_count)
hrtimer_start(timer, ds->info->debounce_time, HRTIMER_MODE_REL);
else if (!ds->use_irq)
hrtimer_start(timer, ds->info->poll_time, HRTIMER_MODE_REL);
else
__pm_relax(ds->ws);
spin_unlock_irqrestore(&ds->irq_lock, irqflags);
return HRTIMER_NORESTART;
}
static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id)
{
struct gpio_key_state *ks = dev_id;
struct gpio_input_state *ds = ks->ds;
int keymap_index = ks - ds->key_state;
const struct gpio_event_direct_entry *key_entry;
unsigned long irqflags;
int pressed;
if (!ds->use_irq)
return IRQ_HANDLED;
key_entry = &ds->info->keymap[keymap_index];
if (ds->info->debounce_time) {
spin_lock_irqsave(&ds->irq_lock, irqflags);
if (ks->debounce & DEBOUNCE_WAIT_IRQ) {
ks->debounce = DEBOUNCE_UNKNOWN;
if (ds->debounce_count++ == 0) {
__pm_stay_awake(ds->ws);
hrtimer_start(
&ds->timer, ds->info->debounce_time,
HRTIMER_MODE_REL);
}
if (ds->info->flags & GPIOEDF_PRINT_KEY_DEBOUNCE)
pr_info("gpio_event_input_irq_handler: "
"key %x-%x, %d (%d) start debounce\n",
ds->info->type, key_entry->code,
keymap_index, key_entry->gpio);
} else {
disable_irq_nosync(irq);
ks->debounce = DEBOUNCE_UNSTABLE;
}
spin_unlock_irqrestore(&ds->irq_lock, irqflags);
} else {
pressed = gpio_get_value(key_entry->gpio) ^
!(ds->info->flags & GPIOEDF_ACTIVE_HIGH);
if (ds->info->flags & GPIOEDF_PRINT_KEYS)
pr_info("gpio_event_input_irq_handler: key %x-%x, %d "
"(%d) changed to %d\n",
ds->info->type, key_entry->code, keymap_index,
key_entry->gpio, pressed);
input_event(ds->input_devs->dev[key_entry->dev], ds->info->type,
key_entry->code, pressed);
input_sync(ds->input_devs->dev[key_entry->dev]);
}
return IRQ_HANDLED;
}
static int gpio_event_input_request_irqs(struct gpio_input_state *ds)
{
int i;
int err;
unsigned int irq;
unsigned long req_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
for (i = 0; i < ds->info->keymap_size; i++) {
err = irq = gpio_to_irq(ds->info->keymap[i].gpio);
if (err < 0)
goto err_gpio_get_irq_num_failed;
err = request_irq(irq, gpio_event_input_irq_handler,
req_flags, "gpio_keys", &ds->key_state[i]);
if (err) {
pr_err("gpio_event_input_request_irqs: request_irq "
"failed for input %d, irq %d\n",
ds->info->keymap[i].gpio, irq);
goto err_request_irq_failed;
}
if (ds->info->info.no_suspend) {
err = enable_irq_wake(irq);
if (err) {
pr_err("gpio_event_input_request_irqs: "
"enable_irq_wake failed for input %d, "
"irq %d\n",
ds->info->keymap[i].gpio, irq);
goto err_enable_irq_wake_failed;
}
}
}
return 0;
for (i = ds->info->keymap_size - 1; i >= 0; i--) {
irq = gpio_to_irq(ds->info->keymap[i].gpio);
if (ds->info->info.no_suspend)
disable_irq_wake(irq);
err_enable_irq_wake_failed:
free_irq(irq, &ds->key_state[i]);
err_request_irq_failed:
err_gpio_get_irq_num_failed:
;
}
return err;
}
int gpio_event_input_func(struct gpio_event_input_devs *input_devs,
struct gpio_event_info *info, void **data, int func)
{
int ret;
int i;
unsigned long irqflags;
struct gpio_event_input_info *di;
struct gpio_input_state *ds = *data;
char *wlname;
di = container_of(info, struct gpio_event_input_info, info);
if (func == GPIO_EVENT_FUNC_SUSPEND) {
if (ds->use_irq)
for (i = 0; i < di->keymap_size; i++)
disable_irq(gpio_to_irq(di->keymap[i].gpio));
hrtimer_cancel(&ds->timer);
return 0;
}
if (func == GPIO_EVENT_FUNC_RESUME) {
spin_lock_irqsave(&ds->irq_lock, irqflags);
if (ds->use_irq)
for (i = 0; i < di->keymap_size; i++)
enable_irq(gpio_to_irq(di->keymap[i].gpio));
hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
spin_unlock_irqrestore(&ds->irq_lock, irqflags);
return 0;
}
if (func == GPIO_EVENT_FUNC_INIT) {
if (ktime_to_ns(di->poll_time) <= 0)
di->poll_time = ktime_set(0, 20 * NSEC_PER_MSEC);
*data = ds = kzalloc(sizeof(*ds) + sizeof(ds->key_state[0]) *
di->keymap_size, GFP_KERNEL);
if (ds == NULL) {
ret = -ENOMEM;
pr_err("gpio_event_input_func: "
"Failed to allocate private data\n");
goto err_ds_alloc_failed;
}
ds->debounce_count = di->keymap_size;
ds->input_devs = input_devs;
ds->info = di;
wlname = kasprintf(GFP_KERNEL, "gpio_input:%s%s",
input_devs->dev[0]->name,
(input_devs->count > 1) ? "..." : "");
ds->ws = wakeup_source_register(wlname);
kfree(wlname);
if (!ds->ws) {
ret = -ENOMEM;
pr_err("gpio_event_input_func: "
"Failed to allocate wakeup source\n");
goto err_ws_failed;
}
spin_lock_init(&ds->irq_lock);
for (i = 0; i < di->keymap_size; i++) {
int dev = di->keymap[i].dev;
if (dev >= input_devs->count) {
pr_err("gpio_event_input_func: bad device "
"index %d >= %d for key code %d\n",
dev, input_devs->count,
di->keymap[i].code);
ret = -EINVAL;
goto err_bad_keymap;
}
input_set_capability(input_devs->dev[dev], di->type,
di->keymap[i].code);
ds->key_state[i].ds = ds;
ds->key_state[i].debounce = DEBOUNCE_UNKNOWN;
}
for (i = 0; i < di->keymap_size; i++) {
ret = gpio_request(di->keymap[i].gpio, "gpio_kp_in");
if (ret) {
pr_err("gpio_event_input_func: gpio_request "
"failed for %d\n", di->keymap[i].gpio);
goto err_gpio_request_failed;
}
ret = gpio_direction_input(di->keymap[i].gpio);
if (ret) {
pr_err("gpio_event_input_func: "
"gpio_direction_input failed for %d\n",
di->keymap[i].gpio);
goto err_gpio_configure_failed;
}
}
ret = gpio_event_input_request_irqs(ds);
spin_lock_irqsave(&ds->irq_lock, irqflags);
ds->use_irq = ret == 0;
pr_info("GPIO Input Driver: Start gpio inputs for %s%s in %s "
"mode\n", input_devs->dev[0]->name,
(input_devs->count > 1) ? "..." : "",
ret == 0 ? "interrupt" : "polling");
hrtimer_init(&ds->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ds->timer.function = gpio_event_input_timer_func;
hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
spin_unlock_irqrestore(&ds->irq_lock, irqflags);
return 0;
}
ret = 0;
spin_lock_irqsave(&ds->irq_lock, irqflags);
hrtimer_cancel(&ds->timer);
if (ds->use_irq) {
for (i = di->keymap_size - 1; i >= 0; i--) {
int irq = gpio_to_irq(di->keymap[i].gpio);
if (ds->info->info.no_suspend)
disable_irq_wake(irq);
free_irq(irq, &ds->key_state[i]);
}
}
spin_unlock_irqrestore(&ds->irq_lock, irqflags);
for (i = di->keymap_size - 1; i >= 0; i--) {
err_gpio_configure_failed:
gpio_free(di->keymap[i].gpio);
err_gpio_request_failed:
;
}
err_bad_keymap:
wakeup_source_unregister(ds->ws);
err_ws_failed:
kfree(ds);
err_ds_alloc_failed:
return ret;
}

View file

@ -0,0 +1,440 @@
/* drivers/input/misc/gpio_matrix.c
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/gpio_event.h>
#include <linux/hrtimer.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
struct gpio_kp {
struct gpio_event_input_devs *input_devs;
struct gpio_event_matrix_info *keypad_info;
struct hrtimer timer;
struct wakeup_source wake_src;
int current_output;
unsigned int use_irq:1;
unsigned int key_state_changed:1;
unsigned int last_key_state_changed:1;
unsigned int some_keys_pressed:2;
unsigned int disabled_irq:1;
unsigned long keys_pressed[0];
};
static void clear_phantom_key(struct gpio_kp *kp, int out, int in)
{
struct gpio_event_matrix_info *mi = kp->keypad_info;
int key_index = out * mi->ninputs + in;
unsigned short keyentry = mi->keymap[key_index];
unsigned short keycode = keyentry & MATRIX_KEY_MASK;
unsigned short dev = keyentry >> MATRIX_CODE_BITS;
if (!test_bit(keycode, kp->input_devs->dev[dev]->key)) {
if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
"cleared\n", keycode, out, in,
mi->output_gpios[out], mi->input_gpios[in]);
__clear_bit(key_index, kp->keys_pressed);
} else {
if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
"not cleared\n", keycode, out, in,
mi->output_gpios[out], mi->input_gpios[in]);
}
}
static int restore_keys_for_input(struct gpio_kp *kp, int out, int in)
{
int rv = 0;
int key_index;
key_index = out * kp->keypad_info->ninputs + in;
while (out < kp->keypad_info->noutputs) {
if (test_bit(key_index, kp->keys_pressed)) {
rv = 1;
clear_phantom_key(kp, out, in);
}
key_index += kp->keypad_info->ninputs;
out++;
}
return rv;
}
static void remove_phantom_keys(struct gpio_kp *kp)
{
int out, in, inp;
int key_index;
if (kp->some_keys_pressed < 3)
return;
for (out = 0; out < kp->keypad_info->noutputs; out++) {
inp = -1;
key_index = out * kp->keypad_info->ninputs;
for (in = 0; in < kp->keypad_info->ninputs; in++, key_index++) {
if (test_bit(key_index, kp->keys_pressed)) {
if (inp == -1) {
inp = in;
continue;
}
if (inp >= 0) {
if (!restore_keys_for_input(kp, out + 1,
inp))
break;
clear_phantom_key(kp, out, inp);
inp = -2;
}
restore_keys_for_input(kp, out, in);
}
}
}
}
static void report_key(struct gpio_kp *kp, int key_index, int out, int in)
{
struct gpio_event_matrix_info *mi = kp->keypad_info;
int pressed = test_bit(key_index, kp->keys_pressed);
unsigned short keyentry = mi->keymap[key_index];
unsigned short keycode = keyentry & MATRIX_KEY_MASK;
unsigned short dev = keyentry >> MATRIX_CODE_BITS;
if (pressed != test_bit(keycode, kp->input_devs->dev[dev]->key)) {
if (keycode == KEY_RESERVED) {
if (mi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS)
pr_info("gpiomatrix: unmapped key, %d-%d "
"(%d-%d) changed to %d\n",
out, in, mi->output_gpios[out],
mi->input_gpios[in], pressed);
} else {
if (mi->flags & GPIOKPF_PRINT_MAPPED_KEYS)
pr_info("gpiomatrix: key %x, %d-%d (%d-%d) "
"changed to %d\n", keycode,
out, in, mi->output_gpios[out],
mi->input_gpios[in], pressed);
input_report_key(kp->input_devs->dev[dev], keycode, pressed);
}
}
}
static void report_sync(struct gpio_kp *kp)
{
int i;
for (i = 0; i < kp->input_devs->count; i++)
input_sync(kp->input_devs->dev[i]);
}
static enum hrtimer_restart gpio_keypad_timer_func(struct hrtimer *timer)
{
int out, in;
int key_index;
int gpio;
struct gpio_kp *kp = container_of(timer, struct gpio_kp, timer);
struct gpio_event_matrix_info *mi = kp->keypad_info;
unsigned gpio_keypad_flags = mi->flags;
unsigned polarity = !!(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH);
out = kp->current_output;
if (out == mi->noutputs) {
out = 0;
kp->last_key_state_changed = kp->key_state_changed;
kp->key_state_changed = 0;
kp->some_keys_pressed = 0;
} else {
key_index = out * mi->ninputs;
for (in = 0; in < mi->ninputs; in++, key_index++) {
gpio = mi->input_gpios[in];
if (gpio_get_value(gpio) ^ !polarity) {
if (kp->some_keys_pressed < 3)
kp->some_keys_pressed++;
kp->key_state_changed |= !__test_and_set_bit(
key_index, kp->keys_pressed);
} else
kp->key_state_changed |= __test_and_clear_bit(
key_index, kp->keys_pressed);
}
gpio = mi->output_gpios[out];
if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set_value(gpio, !polarity);
else
gpio_direction_input(gpio);
out++;
}
kp->current_output = out;
if (out < mi->noutputs) {
gpio = mi->output_gpios[out];
if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set_value(gpio, polarity);
else
gpio_direction_output(gpio, polarity);
hrtimer_start(timer, mi->settle_time, HRTIMER_MODE_REL);
return HRTIMER_NORESTART;
}
if (gpio_keypad_flags & GPIOKPF_DEBOUNCE) {
if (kp->key_state_changed) {
hrtimer_start(&kp->timer, mi->debounce_delay,
HRTIMER_MODE_REL);
return HRTIMER_NORESTART;
}
kp->key_state_changed = kp->last_key_state_changed;
}
if (kp->key_state_changed) {
if (gpio_keypad_flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS)
remove_phantom_keys(kp);
key_index = 0;
for (out = 0; out < mi->noutputs; out++)
for (in = 0; in < mi->ninputs; in++, key_index++)
report_key(kp, key_index, out, in);
report_sync(kp);
}
if (!kp->use_irq || kp->some_keys_pressed) {
hrtimer_start(timer, mi->poll_time, HRTIMER_MODE_REL);
return HRTIMER_NORESTART;
}
/* No keys are pressed, reenable interrupt */
for (out = 0; out < mi->noutputs; out++) {
if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set_value(mi->output_gpios[out], polarity);
else
gpio_direction_output(mi->output_gpios[out], polarity);
}
for (in = 0; in < mi->ninputs; in++)
enable_irq(gpio_to_irq(mi->input_gpios[in]));
__pm_relax(&kp->wake_src);
return HRTIMER_NORESTART;
}
static irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id)
{
int i;
struct gpio_kp *kp = dev_id;
struct gpio_event_matrix_info *mi = kp->keypad_info;
unsigned gpio_keypad_flags = mi->flags;
if (!kp->use_irq) {
/* ignore interrupt while registering the handler */
kp->disabled_irq = 1;
disable_irq_nosync(irq_in);
return IRQ_HANDLED;
}
for (i = 0; i < mi->ninputs; i++)
disable_irq_nosync(gpio_to_irq(mi->input_gpios[i]));
for (i = 0; i < mi->noutputs; i++) {
if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set_value(mi->output_gpios[i],
!(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH));
else
gpio_direction_input(mi->output_gpios[i]);
}
__pm_stay_awake(&kp->wake_src);
hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
return IRQ_HANDLED;
}
static int gpio_keypad_request_irqs(struct gpio_kp *kp)
{
int i;
int err;
unsigned int irq;
unsigned long request_flags;
struct gpio_event_matrix_info *mi = kp->keypad_info;
switch (mi->flags & (GPIOKPF_ACTIVE_HIGH|GPIOKPF_LEVEL_TRIGGERED_IRQ)) {
default:
request_flags = IRQF_TRIGGER_FALLING;
break;
case GPIOKPF_ACTIVE_HIGH:
request_flags = IRQF_TRIGGER_RISING;
break;
case GPIOKPF_LEVEL_TRIGGERED_IRQ:
request_flags = IRQF_TRIGGER_LOW;
break;
case GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_ACTIVE_HIGH:
request_flags = IRQF_TRIGGER_HIGH;
break;
}
for (i = 0; i < mi->ninputs; i++) {
err = irq = gpio_to_irq(mi->input_gpios[i]);
if (err < 0)
goto err_gpio_get_irq_num_failed;
err = request_irq(irq, gpio_keypad_irq_handler, request_flags,
"gpio_kp", kp);
if (err) {
pr_err("gpiomatrix: request_irq failed for input %d, "
"irq %d\n", mi->input_gpios[i], irq);
goto err_request_irq_failed;
}
err = enable_irq_wake(irq);
if (err) {
pr_err("gpiomatrix: set_irq_wake failed for input %d, "
"irq %d\n", mi->input_gpios[i], irq);
}
disable_irq(irq);
if (kp->disabled_irq) {
kp->disabled_irq = 0;
enable_irq(irq);
}
}
return 0;
for (i = mi->noutputs - 1; i >= 0; i--) {
free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
err_request_irq_failed:
err_gpio_get_irq_num_failed:
;
}
return err;
}
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
struct gpio_event_info *info, void **data, int func)
{
int i;
int err;
int key_count;
struct gpio_kp *kp;
struct gpio_event_matrix_info *mi;
mi = container_of(info, struct gpio_event_matrix_info, info);
if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
/* TODO: disable scanning */
return 0;
}
if (func == GPIO_EVENT_FUNC_INIT) {
if (mi->keymap == NULL ||
mi->input_gpios == NULL ||
mi->output_gpios == NULL) {
err = -ENODEV;
pr_err("gpiomatrix: Incomplete pdata\n");
goto err_invalid_platform_data;
}
key_count = mi->ninputs * mi->noutputs;
*data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
BITS_TO_LONGS(key_count), GFP_KERNEL);
if (kp == NULL) {
err = -ENOMEM;
pr_err("gpiomatrix: Failed to allocate private data\n");
goto err_kp_alloc_failed;
}
kp->input_devs = input_devs;
kp->keypad_info = mi;
for (i = 0; i < key_count; i++) {
unsigned short keyentry = mi->keymap[i];
unsigned short keycode = keyentry & MATRIX_KEY_MASK;
unsigned short dev = keyentry >> MATRIX_CODE_BITS;
if (dev >= input_devs->count) {
pr_err("gpiomatrix: bad device index %d >= "
"%d for key code %d\n",
dev, input_devs->count, keycode);
err = -EINVAL;
goto err_bad_keymap;
}
if (keycode && keycode <= KEY_MAX)
input_set_capability(input_devs->dev[dev],
EV_KEY, keycode);
}
for (i = 0; i < mi->noutputs; i++) {
err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
if (err) {
pr_err("gpiomatrix: gpio_request failed for "
"output %d\n", mi->output_gpios[i]);
goto err_request_output_gpio_failed;
}
if (gpio_cansleep(mi->output_gpios[i])) {
pr_err("gpiomatrix: unsupported output gpio %d,"
" can sleep\n", mi->output_gpios[i]);
err = -EINVAL;
goto err_output_gpio_configure_failed;
}
if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
err = gpio_direction_output(mi->output_gpios[i],
!(mi->flags & GPIOKPF_ACTIVE_HIGH));
else
err = gpio_direction_input(mi->output_gpios[i]);
if (err) {
pr_err("gpiomatrix: gpio_configure failed for "
"output %d\n", mi->output_gpios[i]);
goto err_output_gpio_configure_failed;
}
}
for (i = 0; i < mi->ninputs; i++) {
err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
if (err) {
pr_err("gpiomatrix: gpio_request failed for "
"input %d\n", mi->input_gpios[i]);
goto err_request_input_gpio_failed;
}
err = gpio_direction_input(mi->input_gpios[i]);
if (err) {
pr_err("gpiomatrix: gpio_direction_input failed"
" for input %d\n", mi->input_gpios[i]);
goto err_gpio_direction_input_failed;
}
}
kp->current_output = mi->noutputs;
kp->key_state_changed = 1;
hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
kp->timer.function = gpio_keypad_timer_func;
wakeup_source_init(&kp->wake_src, "gpio_kp");
err = gpio_keypad_request_irqs(kp);
kp->use_irq = err == 0;
pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for "
"%s%s in %s mode\n", input_devs->dev[0]->name,
(input_devs->count > 1) ? "..." : "",
kp->use_irq ? "interrupt" : "polling");
if (kp->use_irq)
__pm_stay_awake(&kp->wake_src);
hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
return 0;
}
err = 0;
kp = *data;
if (kp->use_irq)
for (i = mi->noutputs - 1; i >= 0; i--)
free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
hrtimer_cancel(&kp->timer);
wakeup_source_trash(&kp->wake_src);
for (i = mi->noutputs - 1; i >= 0; i--) {
err_gpio_direction_input_failed:
gpio_free(mi->input_gpios[i]);
err_request_input_gpio_failed:
;
}
for (i = mi->noutputs - 1; i >= 0; i--) {
err_output_gpio_configure_failed:
gpio_free(mi->output_gpios[i]);
err_request_output_gpio_failed:
;
}
err_bad_keymap:
kfree(kp);
err_kp_alloc_failed:
err_invalid_platform_data:
return err;
}

View file

@ -0,0 +1,97 @@
/* drivers/input/misc/gpio_output.c
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/gpio_event.h>
int gpio_event_output_event(
struct gpio_event_input_devs *input_devs, struct gpio_event_info *info,
void **data, unsigned int dev, unsigned int type,
unsigned int code, int value)
{
int i;
struct gpio_event_output_info *oi;
oi = container_of(info, struct gpio_event_output_info, info);
if (type != oi->type)
return 0;
if (!(oi->flags & GPIOEDF_ACTIVE_HIGH))
value = !value;
for (i = 0; i < oi->keymap_size; i++)
if (dev == oi->keymap[i].dev && code == oi->keymap[i].code)
gpio_set_value(oi->keymap[i].gpio, value);
return 0;
}
int gpio_event_output_func(
struct gpio_event_input_devs *input_devs, struct gpio_event_info *info,
void **data, int func)
{
int ret;
int i;
struct gpio_event_output_info *oi;
oi = container_of(info, struct gpio_event_output_info, info);
if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME)
return 0;
if (func == GPIO_EVENT_FUNC_INIT) {
int output_level = !(oi->flags & GPIOEDF_ACTIVE_HIGH);
for (i = 0; i < oi->keymap_size; i++) {
int dev = oi->keymap[i].dev;
if (dev >= input_devs->count) {
pr_err("gpio_event_output_func: bad device "
"index %d >= %d for key code %d\n",
dev, input_devs->count,
oi->keymap[i].code);
ret = -EINVAL;
goto err_bad_keymap;
}
input_set_capability(input_devs->dev[dev], oi->type,
oi->keymap[i].code);
}
for (i = 0; i < oi->keymap_size; i++) {
ret = gpio_request(oi->keymap[i].gpio,
"gpio_event_output");
if (ret) {
pr_err("gpio_event_output_func: gpio_request "
"failed for %d\n", oi->keymap[i].gpio);
goto err_gpio_request_failed;
}
ret = gpio_direction_output(oi->keymap[i].gpio,
output_level);
if (ret) {
pr_err("gpio_event_output_func: "
"gpio_direction_output failed for %d\n",
oi->keymap[i].gpio);
goto err_gpio_direction_output_failed;
}
}
return 0;
}
ret = 0;
for (i = oi->keymap_size - 1; i >= 0; i--) {
err_gpio_direction_output_failed:
gpio_free(oi->keymap[i].gpio);
err_gpio_request_failed:
;
}
err_bad_keymap:
return ret;
}

View file

@ -479,6 +479,21 @@ config DM_VERITY
If unsure, say N.
config DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
bool "Prefetch size 128"
config DM_VERITY_HASH_PREFETCH_MIN_SIZE
int "Verity hash prefetch minimum size"
depends on DM_VERITY
range 1 4096
default 128 if DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
default 1
---help---
This sets minimum number of hash blocks to prefetch for dm-verity.
For devices like eMMC, having larger prefetch size like 128 can improve
performance with increased memory consumption for keeping more hashes
in RAM.
config DM_VERITY_FEC
bool "Verity forward error correction support"
depends on DM_VERITY
@ -559,4 +574,51 @@ config DM_ZONED
If unsure, say N.
config DM_VERITY_AVB
tristate "Support AVB specific verity error behavior"
depends on DM_VERITY
---help---
Enables Android Verified Boot platform-specific error
behavior. In particular, it will modify the vbmeta partition
specified on the kernel command-line when non-transient error
occurs (followed by a panic).
config DM_ANDROID_VERITY
bool "Android verity target support"
depends on BLK_DEV_DM=y
depends on DM_VERITY=y
depends on X509_CERTIFICATE_PARSER
depends on SYSTEM_TRUSTED_KEYRING
depends on CRYPTO_RSA
depends on KEYS
depends on ASYMMETRIC_KEY_TYPE
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
---help---
This device-mapper target is virtually a VERITY target. This
target is setup by reading the metadata contents piggybacked
to the actual data blocks in the block device. The signature
of the metadata contents are verified against the key included
in the system keyring. Upon success, the underlying verity
target is setup.
config DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED
bool "Verity will validate blocks at most once"
depends on DM_VERITY
---help---
Default enables at_most_once option for dm-verity
Verify data blocks only the first time they are read from the
data device, rather than every time. This reduces the overhead
of dm-verity so that it can be used on systems that are memory
and/or CPU constrained. However, it provides a reduced level
of security because only offline tampering of the data device's
content will be detected, not online tampering.
Hash blocks are still verified each time they are read from the
hash device, since verification of hash blocks is less performance
critical than data blocks, and a hash block will not be verified
any more after all the data blocks it covers have been verified anyway.
If unsure, say N.
endif # MD

View file

@ -76,3 +76,11 @@ endif
ifeq ($(CONFIG_DM_VERITY_FEC),y)
dm-verity-objs += dm-verity-fec.o
endif
ifeq ($(CONFIG_DM_VERITY_AVB),y)
dm-verity-objs += dm-verity-avb.o
endif
ifeq ($(CONFIG_DM_ANDROID_VERITY),y)
dm-verity-objs += dm-android-verity.o
endif

View file

@ -0,0 +1,925 @@
/*
* Copyright (C) 2015 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/buffer_head.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/device-mapper.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/key.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/of.h>
#include <linux/reboot.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <asm/setup.h>
#include <crypto/hash.h>
#include <crypto/hash_info.h>
#include <crypto/public_key.h>
#include <crypto/sha.h>
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>
#include "dm-verity.h"
#include "dm-android-verity.h"
static char verifiedbootstate[VERITY_COMMANDLINE_PARAM_LENGTH];
static char veritymode[VERITY_COMMANDLINE_PARAM_LENGTH];
static char veritykeyid[VERITY_DEFAULT_KEY_ID_LENGTH];
static char buildvariant[BUILD_VARIANT];
static bool target_added;
static bool verity_enabled = true;
struct dentry *debug_dir;
static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv);
static struct target_type android_verity_target = {
.name = "android-verity",
.version = {1, 0, 0},
.module = THIS_MODULE,
.ctr = android_verity_ctr,
.dtr = verity_dtr,
.map = verity_map,
.status = verity_status,
.prepare_ioctl = verity_prepare_ioctl,
.iterate_devices = verity_iterate_devices,
.io_hints = verity_io_hints,
};
static int __init verified_boot_state_param(char *line)
{
strlcpy(verifiedbootstate, line, sizeof(verifiedbootstate));
return 1;
}
__setup("androidboot.verifiedbootstate=", verified_boot_state_param);
static int __init verity_mode_param(char *line)
{
strlcpy(veritymode, line, sizeof(veritymode));
return 1;
}
__setup("androidboot.veritymode=", verity_mode_param);
static int __init verity_keyid_param(char *line)
{
strlcpy(veritykeyid, line, sizeof(veritykeyid));
return 1;
}
__setup("veritykeyid=", verity_keyid_param);
static int __init verity_buildvariant(char *line)
{
strlcpy(buildvariant, line, sizeof(buildvariant));
return 1;
}
__setup("buildvariant=", verity_buildvariant);
static inline bool default_verity_key_id(void)
{
return veritykeyid[0] != '\0';
}
static inline bool is_eng(void)
{
static const char typeeng[] = "eng";
return !strncmp(buildvariant, typeeng, sizeof(typeeng));
}
static inline bool is_userdebug(void)
{
static const char typeuserdebug[] = "userdebug";
return !strncmp(buildvariant, typeuserdebug, sizeof(typeuserdebug));
}
static inline bool is_unlocked(void)
{
static const char unlocked[] = "orange";
return !strncmp(verifiedbootstate, unlocked, sizeof(unlocked));
}
static int read_block_dev(struct bio_read *payload, struct block_device *bdev,
sector_t offset, int length)
{
struct bio *bio;
int err = 0, i;
payload->number_of_pages = DIV_ROUND_UP(length, PAGE_SIZE);
bio = bio_alloc(GFP_KERNEL, payload->number_of_pages);
if (!bio) {
DMERR("Error while allocating bio");
return -ENOMEM;
}
bio_set_dev(bio, bdev);
bio->bi_iter.bi_sector = offset;
bio_set_op_attrs(bio, REQ_OP_READ, 0);
payload->page_io = kzalloc(sizeof(struct page *) *
payload->number_of_pages, GFP_KERNEL);
if (!payload->page_io) {
DMERR("page_io array alloc failed");
err = -ENOMEM;
goto free_bio;
}
for (i = 0; i < payload->number_of_pages; i++) {
payload->page_io[i] = alloc_page(GFP_KERNEL);
if (!payload->page_io[i]) {
DMERR("alloc_page failed");
err = -ENOMEM;
goto free_pages;
}
if (!bio_add_page(bio, payload->page_io[i], PAGE_SIZE, 0)) {
DMERR("bio_add_page error");
err = -EIO;
goto free_pages;
}
}
if (!submit_bio_wait(bio))
/* success */
goto free_bio;
DMERR("bio read failed");
err = -EIO;
free_pages:
for (i = 0; i < payload->number_of_pages; i++)
if (payload->page_io[i])
__free_page(payload->page_io[i]);
kfree(payload->page_io);
free_bio:
bio_put(bio);
return err;
}
static inline u64 fec_div_round_up(u64 x, u64 y)
{
u64 remainder;
return div64_u64_rem(x, y, &remainder) +
(remainder > 0 ? 1 : 0);
}
static inline void populate_fec_metadata(struct fec_header *header,
struct fec_ecc_metadata *ecc)
{
ecc->blocks = fec_div_round_up(le64_to_cpu(header->inp_size),
FEC_BLOCK_SIZE);
ecc->roots = le32_to_cpu(header->roots);
ecc->start = le64_to_cpu(header->inp_size);
}
static inline int validate_fec_header(struct fec_header *header, u64 offset)
{
/* move offset to make the sanity check work for backup header
* as well. */
offset -= offset % FEC_BLOCK_SIZE;
if (le32_to_cpu(header->magic) != FEC_MAGIC ||
le32_to_cpu(header->version) != FEC_VERSION ||
le32_to_cpu(header->size) != sizeof(struct fec_header) ||
le32_to_cpu(header->roots) == 0 ||
le32_to_cpu(header->roots) >= FEC_RSM)
return -EINVAL;
return 0;
}
static int extract_fec_header(dev_t dev, struct fec_header *fec,
struct fec_ecc_metadata *ecc)
{
u64 device_size;
struct bio_read payload;
int i, err = 0;
struct block_device *bdev;
bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
if (IS_ERR_OR_NULL(bdev)) {
DMERR("bdev get error");
return PTR_ERR(bdev);
}
device_size = i_size_read(bdev->bd_inode);
/* fec metadata size is a power of 2 and PAGE_SIZE
* is a power of 2 as well.
*/
BUG_ON(FEC_BLOCK_SIZE > PAGE_SIZE);
/* 512 byte sector alignment */
BUG_ON(((device_size - FEC_BLOCK_SIZE) % (1 << SECTOR_SHIFT)) != 0);
err = read_block_dev(&payload, bdev, (device_size -
FEC_BLOCK_SIZE) / (1 << SECTOR_SHIFT), FEC_BLOCK_SIZE);
if (err) {
DMERR("Error while reading verity metadata");
goto error;
}
BUG_ON(sizeof(struct fec_header) > PAGE_SIZE);
memcpy(fec, page_address(payload.page_io[0]),
sizeof(*fec));
ecc->valid = true;
if (validate_fec_header(fec, device_size - FEC_BLOCK_SIZE)) {
/* Try the backup header */
memcpy(fec, page_address(payload.page_io[0]) + FEC_BLOCK_SIZE
- sizeof(*fec) ,
sizeof(*fec));
if (validate_fec_header(fec, device_size -
sizeof(struct fec_header)))
ecc->valid = false;
}
if (ecc->valid)
populate_fec_metadata(fec, ecc);
for (i = 0; i < payload.number_of_pages; i++)
__free_page(payload.page_io[i]);
kfree(payload.page_io);
error:
blkdev_put(bdev, FMODE_READ);
return err;
}
static void find_metadata_offset(struct fec_header *fec,
struct block_device *bdev, u64 *metadata_offset)
{
u64 device_size;
device_size = i_size_read(bdev->bd_inode);
if (le32_to_cpu(fec->magic) == FEC_MAGIC)
*metadata_offset = le64_to_cpu(fec->inp_size) -
VERITY_METADATA_SIZE;
else
*metadata_offset = device_size - VERITY_METADATA_SIZE;
}
static int find_size(dev_t dev, u64 *device_size)
{
struct block_device *bdev;
bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
if (IS_ERR_OR_NULL(bdev)) {
DMERR("blkdev_get_by_dev failed");
return PTR_ERR(bdev);
}
*device_size = i_size_read(bdev->bd_inode);
*device_size >>= SECTOR_SHIFT;
DMINFO("blkdev size in sectors: %llu", *device_size);
blkdev_put(bdev, FMODE_READ);
return 0;
}
static int verify_header(struct android_metadata_header *header)
{
int retval = -EINVAL;
if (is_userdebug() && le32_to_cpu(header->magic_number) ==
VERITY_METADATA_MAGIC_DISABLE)
return VERITY_STATE_DISABLE;
if (!(le32_to_cpu(header->magic_number) ==
VERITY_METADATA_MAGIC_NUMBER) ||
(le32_to_cpu(header->magic_number) ==
VERITY_METADATA_MAGIC_DISABLE)) {
DMERR("Incorrect magic number");
return retval;
}
if (le32_to_cpu(header->protocol_version) !=
VERITY_METADATA_VERSION) {
DMERR("Unsupported version %u",
le32_to_cpu(header->protocol_version));
return retval;
}
return 0;
}
static int extract_metadata(dev_t dev, struct fec_header *fec,
struct android_metadata **metadata,
bool *verity_enabled)
{
struct block_device *bdev;
struct android_metadata_header *header;
int i;
u32 table_length, copy_length, offset;
u64 metadata_offset;
struct bio_read payload;
int err = 0;
bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
if (IS_ERR_OR_NULL(bdev)) {
DMERR("blkdev_get_by_dev failed");
return -ENODEV;
}
find_metadata_offset(fec, bdev, &metadata_offset);
/* Verity metadata size is a power of 2 and PAGE_SIZE
* is a power of 2 as well.
* PAGE_SIZE is also a multiple of 512 bytes.
*/
if (VERITY_METADATA_SIZE > PAGE_SIZE)
BUG_ON(VERITY_METADATA_SIZE % PAGE_SIZE != 0);
/* 512 byte sector alignment */
BUG_ON(metadata_offset % (1 << SECTOR_SHIFT) != 0);
err = read_block_dev(&payload, bdev, metadata_offset /
(1 << SECTOR_SHIFT), VERITY_METADATA_SIZE);
if (err) {
DMERR("Error while reading verity metadata");
goto blkdev_release;
}
header = kzalloc(sizeof(*header), GFP_KERNEL);
if (!header) {
DMERR("kzalloc failed for header");
err = -ENOMEM;
goto free_payload;
}
memcpy(header, page_address(payload.page_io[0]),
sizeof(*header));
DMINFO("bio magic_number:%u protocol_version:%d table_length:%u",
le32_to_cpu(header->magic_number),
le32_to_cpu(header->protocol_version),
le32_to_cpu(header->table_length));
err = verify_header(header);
if (err == VERITY_STATE_DISABLE) {
DMERR("Mounting root with verity disabled");
*verity_enabled = false;
/* we would still have to read the metadata to figure out
* the data blocks size. Or may be could map the entire
* partition similar to mounting the device.
*
* Reset error as well as the verity_enabled flag is changed.
*/
err = 0;
} else if (err)
goto free_header;
*metadata = kzalloc(sizeof(**metadata), GFP_KERNEL);
if (!*metadata) {
DMERR("kzalloc for metadata failed");
err = -ENOMEM;
goto free_header;
}
(*metadata)->header = header;
table_length = le32_to_cpu(header->table_length);
if (table_length == 0 ||
table_length > (VERITY_METADATA_SIZE -
sizeof(struct android_metadata_header))) {
DMERR("table_length too long");
err = -EINVAL;
goto free_metadata;
}
(*metadata)->verity_table = kzalloc(table_length + 1, GFP_KERNEL);
if (!(*metadata)->verity_table) {
DMERR("kzalloc verity_table failed");
err = -ENOMEM;
goto free_metadata;
}
if (sizeof(struct android_metadata_header) +
table_length <= PAGE_SIZE) {
memcpy((*metadata)->verity_table,
page_address(payload.page_io[0])
+ sizeof(struct android_metadata_header),
table_length);
} else {
copy_length = PAGE_SIZE -
sizeof(struct android_metadata_header);
memcpy((*metadata)->verity_table,
page_address(payload.page_io[0])
+ sizeof(struct android_metadata_header),
copy_length);
table_length -= copy_length;
offset = copy_length;
i = 1;
while (table_length != 0) {
if (table_length > PAGE_SIZE) {
memcpy((*metadata)->verity_table + offset,
page_address(payload.page_io[i]),
PAGE_SIZE);
offset += PAGE_SIZE;
table_length -= PAGE_SIZE;
} else {
memcpy((*metadata)->verity_table + offset,
page_address(payload.page_io[i]),
table_length);
table_length = 0;
}
i++;
}
}
(*metadata)->verity_table[table_length] = '\0';
DMINFO("verity_table: %s", (*metadata)->verity_table);
goto free_payload;
free_metadata:
kfree(*metadata);
free_header:
kfree(header);
free_payload:
for (i = 0; i < payload.number_of_pages; i++)
if (payload.page_io[i])
__free_page(payload.page_io[i]);
kfree(payload.page_io);
blkdev_release:
blkdev_put(bdev, FMODE_READ);
return err;
}
/* helper functions to extract properties from dts */
const char *find_dt_value(const char *name)
{
struct device_node *firmware;
const char *value;
firmware = of_find_node_by_path("/firmware/android");
if (!firmware)
return NULL;
value = of_get_property(firmware, name, NULL);
of_node_put(firmware);
return value;
}
static int verity_mode(void)
{
static const char enforcing[] = "enforcing";
static const char verified_mode_prop[] = "veritymode";
const char *value;
value = find_dt_value(verified_mode_prop);
if (!value)
value = veritymode;
if (!strncmp(value, enforcing, sizeof(enforcing) - 1))
return DM_VERITY_MODE_RESTART;
return DM_VERITY_MODE_EIO;
}
static void handle_error(void)
{
int mode = verity_mode();
if (mode == DM_VERITY_MODE_RESTART) {
DMERR("triggering restart");
kernel_restart("dm-verity device corrupted");
} else {
DMERR("Mounting verity root failed");
}
}
static struct public_key_signature *table_make_digest(
enum hash_algo hash,
const void *table,
unsigned long table_len)
{
struct public_key_signature *pks = NULL;
struct crypto_shash *tfm;
struct shash_desc *desc;
size_t digest_size, desc_size;
int ret;
/* Allocate the hashing algorithm we're going to need and find out how
* big the hash operational data will be.
*/
tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0);
if (IS_ERR(tfm))
return ERR_CAST(tfm);
desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
digest_size = crypto_shash_digestsize(tfm);
/* We allocate the hash operational data storage on the end of out
* context data and the digest output buffer on the end of that.
*/
ret = -ENOMEM;
pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
if (!pks)
goto error;
pks->pkey_algo = "rsa";
pks->hash_algo = hash_algo_name[hash];
pks->digest = (u8 *)pks + sizeof(*pks) + desc_size;
pks->digest_size = digest_size;
desc = (struct shash_desc *)(pks + 1);
desc->tfm = tfm;
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
ret = crypto_shash_init(desc);
if (ret < 0)
goto error;
ret = crypto_shash_finup(desc, table, table_len, pks->digest);
if (ret < 0)
goto error;
crypto_free_shash(tfm);
return pks;
error:
kfree(pks);
crypto_free_shash(tfm);
return ERR_PTR(ret);
}
static int verify_verity_signature(char *key_id,
struct android_metadata *metadata)
{
struct public_key_signature *pks = NULL;
int retval = -EINVAL;
if (!key_id)
goto error;
pks = table_make_digest(HASH_ALGO_SHA256,
(const void *)metadata->verity_table,
le32_to_cpu(metadata->header->table_length));
if (IS_ERR(pks)) {
DMERR("hashing failed");
retval = PTR_ERR(pks);
pks = NULL;
goto error;
}
pks->s = kmemdup(&metadata->header->signature[0], RSANUMBYTES, GFP_KERNEL);
if (!pks->s) {
DMERR("Error allocating memory for signature");
goto error;
}
pks->s_size = RSANUMBYTES;
retval = verify_signature_one(pks, NULL, key_id);
kfree(pks->s);
error:
kfree(pks);
return retval;
}
static inline bool test_mult_overflow(sector_t a, u32 b)
{
sector_t r = (sector_t)~0ULL;
sector_div(r, b);
return a > r;
}
static int add_as_linear_device(struct dm_target *ti, char *dev)
{
/*Move to linear mapping defines*/
char *linear_table_args[DM_LINEAR_ARGS] = {dev,
DM_LINEAR_TARGET_OFFSET};
int err = 0;
android_verity_target.dtr = dm_linear_dtr,
android_verity_target.map = dm_linear_map,
android_verity_target.status = dm_linear_status,
android_verity_target.end_io = dm_linear_end_io,
android_verity_target.prepare_ioctl = dm_linear_prepare_ioctl,
android_verity_target.iterate_devices = dm_linear_iterate_devices,
android_verity_target.direct_access = dm_linear_dax_direct_access,
android_verity_target.dax_copy_from_iter = dm_linear_dax_copy_from_iter,
android_verity_target.io_hints = NULL;
set_disk_ro(dm_disk(dm_table_get_md(ti->table)), 0);
err = dm_linear_ctr(ti, DM_LINEAR_ARGS, linear_table_args);
if (!err) {
DMINFO("Added android-verity as a linear target");
target_added = true;
} else
DMERR("Failed to add android-verity as linear target");
return err;
}
static int create_linear_device(struct dm_target *ti, dev_t dev,
char *target_device)
{
u64 device_size = 0;
int err = find_size(dev, &device_size);
if (err) {
DMERR("error finding bdev size");
handle_error();
return err;
}
ti->len = device_size;
err = add_as_linear_device(ti, target_device);
if (err) {
handle_error();
return err;
}
verity_enabled = false;
return 0;
}
/*
* Target parameters:
* <key id> Key id of the public key in the system keyring.
* Verity metadata's signature would be verified against
* this. If the key id contains spaces, replace them
* with '#'.
* <block device> The block device for which dm-verity is being setup.
*/
static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
{
dev_t uninitialized_var(dev);
struct android_metadata *metadata = NULL;
int err = 0, i, mode;
char *key_id = NULL, *table_ptr, dummy, *target_device;
char *verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS];
/* One for specifying number of opt args and one for mode */
sector_t data_sectors;
u32 data_block_size;
unsigned int no_of_args = VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS;
struct fec_header uninitialized_var(fec);
struct fec_ecc_metadata uninitialized_var(ecc);
char buf[FEC_ARG_LENGTH], *buf_ptr;
unsigned long long tmpll;
if (argc == 1) {
/* Use the default keyid */
if (default_verity_key_id())
key_id = veritykeyid;
else if (!is_eng()) {
DMERR("veritykeyid= is not set");
handle_error();
return -EINVAL;
}
target_device = argv[0];
} else if (argc == 2) {
key_id = argv[0];
target_device = argv[1];
} else {
DMERR("Incorrect number of arguments");
handle_error();
return -EINVAL;
}
dev = name_to_dev_t(target_device);
if (!dev) {
DMERR("no dev found for %s", target_device);
handle_error();
return -EINVAL;
}
if (is_eng())
return create_linear_device(ti, dev, target_device);
strreplace(key_id, '#', ' ');
DMINFO("key:%s dev:%s", key_id, target_device);
if (extract_fec_header(dev, &fec, &ecc)) {
DMERR("Error while extracting fec header");
handle_error();
return -EINVAL;
}
err = extract_metadata(dev, &fec, &metadata, &verity_enabled);
if (err) {
/* Allow invalid metadata when the device is unlocked */
if (is_unlocked()) {
DMWARN("Allow invalid metadata when unlocked");
return create_linear_device(ti, dev, target_device);
}
DMERR("Error while extracting metadata");
handle_error();
goto free_metadata;
}
if (verity_enabled) {
err = verify_verity_signature(key_id, metadata);
if (err) {
DMERR("Signature verification failed");
handle_error();
goto free_metadata;
} else
DMINFO("Signature verification success");
}
table_ptr = metadata->verity_table;
for (i = 0; i < VERITY_TABLE_ARGS; i++) {
verity_table_args[i] = strsep(&table_ptr, " ");
if (verity_table_args[i] == NULL)
break;
}
if (i != VERITY_TABLE_ARGS) {
DMERR("Verity table not in the expected format");
err = -EINVAL;
handle_error();
goto free_metadata;
}
if (sscanf(verity_table_args[5], "%llu%c", &tmpll, &dummy)
!= 1) {
DMERR("Verity table not in the expected format");
handle_error();
err = -EINVAL;
goto free_metadata;
}
if (tmpll > ULONG_MAX) {
DMERR("<num_data_blocks> too large. Forgot to turn on CONFIG_LBDAF?");
handle_error();
err = -EINVAL;
goto free_metadata;
}
data_sectors = tmpll;
if (sscanf(verity_table_args[3], "%u%c", &data_block_size, &dummy)
!= 1) {
DMERR("Verity table not in the expected format");
handle_error();
err = -EINVAL;
goto free_metadata;
}
if (test_mult_overflow(data_sectors, data_block_size >>
SECTOR_SHIFT)) {
DMERR("data_sectors too large");
handle_error();
err = -EOVERFLOW;
goto free_metadata;
}
data_sectors *= data_block_size >> SECTOR_SHIFT;
DMINFO("Data sectors %llu", (unsigned long long)data_sectors);
/* update target length */
ti->len = data_sectors;
/* Setup linear target and free */
if (!verity_enabled) {
err = add_as_linear_device(ti, target_device);
goto free_metadata;
}
/*substitute data_dev and hash_dev*/
verity_table_args[1] = target_device;
verity_table_args[2] = target_device;
mode = verity_mode();
if (ecc.valid && IS_BUILTIN(CONFIG_DM_VERITY_FEC)) {
if (mode) {
err = snprintf(buf, FEC_ARG_LENGTH,
"%u %s " VERITY_TABLE_OPT_FEC_FORMAT,
1 + VERITY_TABLE_OPT_FEC_ARGS,
mode == DM_VERITY_MODE_RESTART ?
VERITY_TABLE_OPT_RESTART :
VERITY_TABLE_OPT_LOGGING,
target_device,
ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
ecc.roots);
} else {
err = snprintf(buf, FEC_ARG_LENGTH,
"%u " VERITY_TABLE_OPT_FEC_FORMAT,
VERITY_TABLE_OPT_FEC_ARGS, target_device,
ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
ecc.roots);
}
} else if (mode) {
err = snprintf(buf, FEC_ARG_LENGTH,
"2 " VERITY_TABLE_OPT_IGNZERO " %s",
mode == DM_VERITY_MODE_RESTART ?
VERITY_TABLE_OPT_RESTART : VERITY_TABLE_OPT_LOGGING);
} else {
err = snprintf(buf, FEC_ARG_LENGTH, "1 %s",
"ignore_zero_blocks");
}
if (err < 0 || err >= FEC_ARG_LENGTH)
goto free_metadata;
buf_ptr = buf;
for (i = VERITY_TABLE_ARGS; i < (VERITY_TABLE_ARGS +
VERITY_TABLE_OPT_FEC_ARGS + 2); i++) {
verity_table_args[i] = strsep(&buf_ptr, " ");
if (verity_table_args[i] == NULL) {
no_of_args = i;
break;
}
}
err = verity_ctr(ti, no_of_args, verity_table_args);
if (err) {
DMERR("android-verity failed to create a verity target");
} else {
target_added = true;
DMINFO("android-verity created as verity target");
}
free_metadata:
if (metadata) {
kfree(metadata->header);
kfree(metadata->verity_table);
}
kfree(metadata);
return err;
}
static int __init dm_android_verity_init(void)
{
int r;
struct dentry *file;
r = dm_register_target(&android_verity_target);
if (r < 0)
DMERR("register failed %d", r);
/* Tracks the status of the last added target */
debug_dir = debugfs_create_dir("android_verity", NULL);
if (IS_ERR_OR_NULL(debug_dir)) {
DMERR("Cannot create android_verity debugfs directory: %ld",
PTR_ERR(debug_dir));
goto end;
}
file = debugfs_create_bool("target_added", S_IRUGO, debug_dir,
&target_added);
if (IS_ERR_OR_NULL(file)) {
DMERR("Cannot create android_verity debugfs directory: %ld",
PTR_ERR(debug_dir));
debugfs_remove_recursive(debug_dir);
goto end;
}
file = debugfs_create_bool("verity_enabled", S_IRUGO, debug_dir,
&verity_enabled);
if (IS_ERR_OR_NULL(file)) {
DMERR("Cannot create android_verity debugfs directory: %ld",
PTR_ERR(debug_dir));
debugfs_remove_recursive(debug_dir);
}
end:
return r;
}
static void __exit dm_android_verity_exit(void)
{
if (!IS_ERR_OR_NULL(debug_dir))
debugfs_remove_recursive(debug_dir);
dm_unregister_target(&android_verity_target);
}
module_init(dm_android_verity_init);
module_exit(dm_android_verity_exit);

View file

@ -0,0 +1,132 @@
/*
* Copyright (C) 2015 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef DM_ANDROID_VERITY_H
#define DM_ANDROID_VERITY_H
#include <crypto/sha.h>
#define RSANUMBYTES 256
#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56
#define VERITY_METADATA_VERSION 0
#define VERITY_STATE_DISABLE 1
#define DATA_BLOCK_SIZE (4 * 1024)
#define VERITY_METADATA_SIZE (8 * DATA_BLOCK_SIZE)
#define VERITY_TABLE_ARGS 10
#define VERITY_COMMANDLINE_PARAM_LENGTH 20
#define BUILD_VARIANT 20
/*
* <subject>:<sha1-id> is the format for the identifier.
* subject can either be the Common Name(CN) + Organization Name(O) or
* just the CN if the it is prefixed with O
* From https://tools.ietf.org/html/rfc5280#appendix-A
* ub-organization-name-length INTEGER ::= 64
* ub-common-name-length INTEGER ::= 64
*
* http://lxr.free-electrons.com/source/crypto/asymmetric_keys/x509_cert_parser.c?v=3.9#L278
* ctx->o_size + 2 + ctx->cn_size + 1
* + 41 characters for ":" and sha1 id
* 64 + 2 + 64 + 1 + 1 + 40 (172)
* setting VERITY_DEFAULT_KEY_ID_LENGTH to 200 characters.
*/
#define VERITY_DEFAULT_KEY_ID_LENGTH 200
#define FEC_MAGIC 0xFECFECFE
#define FEC_BLOCK_SIZE (4 * 1024)
#define FEC_VERSION 0
#define FEC_RSM 255
#define FEC_ARG_LENGTH 300
#define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
#define VERITY_TABLE_OPT_LOGGING "ignore_corruption"
#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
#define VERITY_TABLE_OPT_FEC_FORMAT \
"use_fec_from_device %s fec_start %llu fec_blocks %llu fec_roots %u ignore_zero_blocks"
#define VERITY_TABLE_OPT_FEC_ARGS 9
#define VERITY_DEBUG 0
#define DM_MSG_PREFIX "android-verity"
#define DM_LINEAR_ARGS 2
#define DM_LINEAR_TARGET_OFFSET "0"
/*
* There can be two formats.
* if fec is present
* <data_blocks> <verity_tree> <verity_metdata_32K><fec_data><fec_data_4K>
* if fec is not present
* <data_blocks> <verity_tree> <verity_metdata_32K>
*/
struct fec_header {
__le32 magic;
__le32 version;
__le32 size;
__le32 roots;
__le32 fec_size;
__le64 inp_size;
u8 hash[SHA256_DIGEST_SIZE];
} __attribute__((packed));
struct android_metadata_header {
__le32 magic_number;
__le32 protocol_version;
char signature[RSANUMBYTES];
__le32 table_length;
};
struct android_metadata {
struct android_metadata_header *header;
char *verity_table;
};
struct fec_ecc_metadata {
bool valid;
u32 roots;
u64 blocks;
u64 rounds;
u64 start;
};
struct bio_read {
struct page **page_io;
int number_of_pages;
};
extern struct target_type linear_target;
extern void dm_linear_dtr(struct dm_target *ti);
extern int dm_linear_map(struct dm_target *ti, struct bio *bio);
extern int dm_linear_end_io(struct dm_target *ti, struct bio *bio,
blk_status_t *error);
extern void dm_linear_status(struct dm_target *ti, status_type_t type,
unsigned status_flags, char *result, unsigned maxlen);
extern int dm_linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev);
extern int dm_linear_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data);
extern int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv);
#if IS_ENABLED(CONFIG_DAX_DRIVER)
extern long dm_linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr,
pfn_t *pfn);
extern size_t dm_linear_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff,
void *addr, size_t bytes, struct iov_iter *i);
#else
#define dm_linear_dax_direct_access NULL
#define dm_linear_dax_copy_from_iter NULL
#endif
#endif /* DM_ANDROID_VERITY_H */

View file

@ -1993,6 +1993,45 @@ void dm_interface_exit(void)
dm_hash_exit();
}
/**
* dm_ioctl_export - Permanently export a mapped device via the ioctl interface
* @md: Pointer to mapped_device
* @name: Buffer (size DM_NAME_LEN) for name
* @uuid: Buffer (size DM_UUID_LEN) for uuid or NULL if not desired
*/
int dm_ioctl_export(struct mapped_device *md, const char *name,
const char *uuid)
{
int r = 0;
struct hash_cell *hc;
if (!md) {
r = -ENXIO;
goto out;
}
/* The name and uuid can only be set once. */
mutex_lock(&dm_hash_cells_mutex);
hc = dm_get_mdptr(md);
mutex_unlock(&dm_hash_cells_mutex);
if (hc) {
DMERR("%s: already exported", dm_device_name(md));
r = -ENXIO;
goto out;
}
r = dm_hash_insert(name, uuid, md);
if (r) {
DMERR("%s: could not bind to '%s'", dm_device_name(md), name);
goto out;
}
/* Let udev know we've changed. */
dm_kobject_uevent(md, KOBJ_CHANGE, dm_get_event_nr(md));
out:
return r;
}
/**
* dm_copy_name_and_uuid - Copy mapped device name & uuid into supplied buffers
* @md: Pointer to mapped_device

View file

@ -26,7 +26,7 @@ struct linear_c {
/*
* Construct a linear mapping: <dev_path> <offset>
*/
static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct linear_c *lc;
unsigned long long tmp;
@ -70,7 +70,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return ret;
}
static void linear_dtr(struct dm_target *ti)
void dm_linear_dtr(struct dm_target *ti)
{
struct linear_c *lc = (struct linear_c *) ti->private;
@ -95,14 +95,14 @@ static void linear_map_bio(struct dm_target *ti, struct bio *bio)
linear_map_sector(ti, bio->bi_iter.bi_sector);
}
static int linear_map(struct dm_target *ti, struct bio *bio)
int dm_linear_map(struct dm_target *ti, struct bio *bio)
{
linear_map_bio(ti, bio);
return DM_MAPIO_REMAPPED;
}
static int linear_end_io(struct dm_target *ti, struct bio *bio,
int dm_linear_end_io(struct dm_target *ti, struct bio *bio,
blk_status_t *error)
{
struct linear_c *lc = ti->private;
@ -112,8 +112,9 @@ static int linear_end_io(struct dm_target *ti, struct bio *bio,
return DM_ENDIO_DONE;
}
EXPORT_SYMBOL_GPL(dm_linear_end_io);
static void linear_status(struct dm_target *ti, status_type_t type,
void dm_linear_status(struct dm_target *ti, status_type_t type,
unsigned status_flags, char *result, unsigned maxlen)
{
struct linear_c *lc = (struct linear_c *) ti->private;
@ -130,7 +131,7 @@ static void linear_status(struct dm_target *ti, status_type_t type,
}
}
static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
int dm_linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
{
struct linear_c *lc = (struct linear_c *) ti->private;
struct dm_dev *dev = lc->dev;
@ -146,7 +147,7 @@ static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
return 0;
}
static int linear_iterate_devices(struct dm_target *ti,
int dm_linear_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{
struct linear_c *lc = ti->private;
@ -155,7 +156,7 @@ static int linear_iterate_devices(struct dm_target *ti,
}
#if IS_ENABLED(CONFIG_DAX_DRIVER)
static long linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long dm_linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
{
long ret;
@ -170,8 +171,9 @@ static long linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
return ret;
return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
}
EXPORT_SYMBOL_GPL(dm_linear_dax_direct_access);
static size_t linear_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff,
size_t dm_linear_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff,
void *addr, size_t bytes, struct iov_iter *i)
{
struct linear_c *lc = ti->private;
@ -184,8 +186,9 @@ static size_t linear_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff,
return 0;
return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i);
}
EXPORT_SYMBOL_GPL(dm_linear_dax_copy_from_iter);
static size_t linear_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff,
static size_t dm_linear_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff,
void *addr, size_t bytes, struct iov_iter *i)
{
struct linear_c *lc = ti->private;
@ -200,9 +203,9 @@ static size_t linear_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff,
}
#else
#define linear_dax_direct_access NULL
#define linear_dax_copy_from_iter NULL
#define linear_dax_copy_to_iter NULL
#define dm_linear_dax_direct_access NULL
#define dm_linear_dax_copy_from_iter NULL
#define dm_linear_dax_copy_to_iter NULL
#endif
static struct target_type linear_target = {
@ -210,16 +213,16 @@ static struct target_type linear_target = {
.version = {1, 4, 0},
.features = DM_TARGET_PASSES_INTEGRITY | DM_TARGET_ZONED_HM,
.module = THIS_MODULE,
.ctr = linear_ctr,
.dtr = linear_dtr,
.map = linear_map,
.end_io = linear_end_io,
.status = linear_status,
.prepare_ioctl = linear_prepare_ioctl,
.iterate_devices = linear_iterate_devices,
.direct_access = linear_dax_direct_access,
.dax_copy_from_iter = linear_dax_copy_from_iter,
.dax_copy_to_iter = linear_dax_copy_to_iter,
.ctr = dm_linear_ctr,
.dtr = dm_linear_dtr,
.map = dm_linear_map,
.status = dm_linear_status,
.end_io = dm_linear_end_io,
.prepare_ioctl = dm_linear_prepare_ioctl,
.iterate_devices = dm_linear_iterate_devices,
.direct_access = dm_linear_dax_direct_access,
.dax_copy_from_iter = dm_linear_dax_copy_from_iter,
.dax_copy_to_iter = dm_linear_dax_copy_to_iter,
};
int __init dm_linear_init(void)

View file

@ -11,6 +11,7 @@
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/slab.h>

229
drivers/md/dm-verity-avb.c Normal file
View file

@ -0,0 +1,229 @@
/*
* Copyright (C) 2017 Google.
*
* This file is released under the GPLv2.
*
* Based on drivers/md/dm-verity-chromeos.c
*/
#include <linux/device-mapper.h>
#include <linux/module.h>
#include <linux/mount.h>
#define DM_MSG_PREFIX "verity-avb"
/* Set via module parameters. */
static char avb_vbmeta_device[64];
static char avb_invalidate_on_error[4];
static void invalidate_vbmeta_endio(struct bio *bio)
{
if (bio->bi_status)
DMERR("invalidate_vbmeta_endio: error %d", bio->bi_status);
complete(bio->bi_private);
}
static int invalidate_vbmeta_submit(struct bio *bio,
struct block_device *bdev,
int op, int access_last_sector,
struct page *page)
{
DECLARE_COMPLETION_ONSTACK(wait);
bio->bi_private = &wait;
bio->bi_end_io = invalidate_vbmeta_endio;
bio_set_dev(bio, bdev);
bio_set_op_attrs(bio, op, REQ_SYNC);
bio->bi_iter.bi_sector = 0;
if (access_last_sector) {
sector_t last_sector;
last_sector = (i_size_read(bdev->bd_inode)>>SECTOR_SHIFT) - 1;
bio->bi_iter.bi_sector = last_sector;
}
if (!bio_add_page(bio, page, PAGE_SIZE, 0)) {
DMERR("invalidate_vbmeta_submit: bio_add_page error");
return -EIO;
}
submit_bio(bio);
/* Wait up to 2 seconds for completion or fail. */
if (!wait_for_completion_timeout(&wait, msecs_to_jiffies(2000)))
return -EIO;
return 0;
}
static int invalidate_vbmeta(dev_t vbmeta_devt)
{
int ret = 0;
struct block_device *bdev;
struct bio *bio;
struct page *page;
fmode_t dev_mode;
/* Ensure we do synchronous unblocked I/O. We may also need
* sync_bdev() on completion, but it really shouldn't.
*/
int access_last_sector = 0;
DMINFO("invalidate_vbmeta: acting on device %d:%d",
MAJOR(vbmeta_devt), MINOR(vbmeta_devt));
/* First we open the device for reading. */
dev_mode = FMODE_READ | FMODE_EXCL;
bdev = blkdev_get_by_dev(vbmeta_devt, dev_mode,
invalidate_vbmeta);
if (IS_ERR(bdev)) {
DMERR("invalidate_kernel: could not open device for reading");
dev_mode = 0;
ret = -ENOENT;
goto failed_to_read;
}
bio = bio_alloc(GFP_NOIO, 1);
if (!bio) {
ret = -ENOMEM;
goto failed_bio_alloc;
}
page = alloc_page(GFP_NOIO);
if (!page) {
ret = -ENOMEM;
goto failed_to_alloc_page;
}
access_last_sector = 0;
ret = invalidate_vbmeta_submit(bio, bdev, REQ_OP_READ,
access_last_sector, page);
if (ret) {
DMERR("invalidate_vbmeta: error reading");
goto failed_to_submit_read;
}
/* We have a page. Let's make sure it looks right. */
if (memcmp("AVB0", page_address(page), 4) == 0) {
/* Stamp it. */
memcpy(page_address(page), "AVE0", 4);
DMINFO("invalidate_vbmeta: found vbmeta partition");
} else {
/* Could be this is on a AVB footer, check. Also, since the
* AVB footer is in the last 64 bytes, adjust for the fact that
* we're dealing with 512-byte sectors.
*/
size_t offset = (1<<SECTOR_SHIFT) - 64;
access_last_sector = 1;
ret = invalidate_vbmeta_submit(bio, bdev, REQ_OP_READ,
access_last_sector, page);
if (ret) {
DMERR("invalidate_vbmeta: error reading");
goto failed_to_submit_read;
}
if (memcmp("AVBf", page_address(page) + offset, 4) != 0) {
DMERR("invalidate_vbmeta on non-vbmeta partition");
ret = -EINVAL;
goto invalid_header;
}
/* Stamp it. */
memcpy(page_address(page) + offset, "AVE0", 4);
DMINFO("invalidate_vbmeta: found vbmeta footer partition");
}
/* Now rewrite the changed page - the block dev was being
* changed on read. Let's reopen here.
*/
blkdev_put(bdev, dev_mode);
dev_mode = FMODE_WRITE | FMODE_EXCL;
bdev = blkdev_get_by_dev(vbmeta_devt, dev_mode,
invalidate_vbmeta);
if (IS_ERR(bdev)) {
DMERR("invalidate_vbmeta: could not open device for writing");
dev_mode = 0;
ret = -ENOENT;
goto failed_to_write;
}
/* We re-use the same bio to do the write after the read. Need to reset
* it to initialize bio->bi_remaining.
*/
bio_reset(bio);
ret = invalidate_vbmeta_submit(bio, bdev, REQ_OP_WRITE,
access_last_sector, page);
if (ret) {
DMERR("invalidate_vbmeta: error writing");
goto failed_to_submit_write;
}
DMERR("invalidate_vbmeta: completed.");
ret = 0;
failed_to_submit_write:
failed_to_write:
invalid_header:
__free_page(page);
failed_to_submit_read:
/* Technically, we'll leak a page with the pending bio, but
* we're about to reboot anyway.
*/
failed_to_alloc_page:
bio_put(bio);
failed_bio_alloc:
if (dev_mode)
blkdev_put(bdev, dev_mode);
failed_to_read:
return ret;
}
void dm_verity_avb_error_handler(void)
{
dev_t dev;
DMINFO("AVB error handler called for %s", avb_vbmeta_device);
if (strcmp(avb_invalidate_on_error, "yes") != 0) {
DMINFO("Not configured to invalidate");
return;
}
if (avb_vbmeta_device[0] == '\0') {
DMERR("avb_vbmeta_device parameter not set");
goto fail_no_dev;
}
dev = name_to_dev_t(avb_vbmeta_device);
if (!dev) {
DMERR("No matching partition for device: %s",
avb_vbmeta_device);
goto fail_no_dev;
}
invalidate_vbmeta(dev);
fail_no_dev:
;
}
static int __init dm_verity_avb_init(void)
{
DMINFO("AVB error handler initialized with vbmeta device: %s",
avb_vbmeta_device);
return 0;
}
static void __exit dm_verity_avb_exit(void)
{
}
module_init(dm_verity_avb_init);
module_exit(dm_verity_avb_exit);
MODULE_AUTHOR("David Zeuthen <zeuthen@google.com>");
MODULE_DESCRIPTION("AVB-specific error handler for dm-verity");
MODULE_LICENSE("GPL");
/* Declare parameter with no module prefix */
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "androidboot.vbmeta."
module_param_string(device, avb_vbmeta_device, sizeof(avb_vbmeta_device), 0);
module_param_string(invalidate_on_error, avb_invalidate_on_error,
sizeof(avb_invalidate_on_error), 0);

View file

@ -11,6 +11,7 @@
#include "dm-verity-fec.h"
#include <linux/math64.h>
#include <linux/sysfs.h>
#define DM_MSG_PREFIX "verity-fec"
@ -175,9 +176,11 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,
if (r < 0 && neras)
DMERR_LIMIT("%s: FEC %llu: failed to correct: %d",
v->data_dev->name, (unsigned long long)rsb, r);
else if (r > 0)
else if (r > 0) {
DMWARN_LIMIT("%s: FEC %llu: corrected %d errors",
v->data_dev->name, (unsigned long long)rsb, r);
atomic_add_unless(&v->fec->corrected, 1, INT_MAX);
}
return r;
}
@ -545,6 +548,7 @@ unsigned verity_fec_status_table(struct dm_verity *v, unsigned sz,
void verity_fec_dtr(struct dm_verity *v)
{
struct dm_verity_fec *f = v->fec;
struct kobject *kobj = &f->kobj_holder.kobj;
if (!verity_fec_is_enabled(v))
goto out;
@ -561,6 +565,12 @@ void verity_fec_dtr(struct dm_verity *v)
if (f->dev)
dm_put_device(v->ti, f->dev);
if (kobj->state_initialized) {
kobject_put(kobj);
wait_for_completion(dm_get_completion_from_kobject(kobj));
}
out:
kfree(f);
v->fec = NULL;
@ -649,6 +659,28 @@ int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
return 0;
}
static ssize_t corrected_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
struct dm_verity_fec *f = container_of(kobj, struct dm_verity_fec,
kobj_holder.kobj);
return sprintf(buf, "%d\n", atomic_read(&f->corrected));
}
static struct kobj_attribute attr_corrected = __ATTR_RO(corrected);
static struct attribute *fec_attrs[] = {
&attr_corrected.attr,
NULL
};
static struct kobj_type fec_ktype = {
.sysfs_ops = &kobj_sysfs_ops,
.default_attrs = fec_attrs,
.release = dm_kobject_release
};
/*
* Allocate dm_verity_fec for v->fec. Must be called before verity_fec_ctr.
*/
@ -672,8 +704,10 @@ int verity_fec_ctr_alloc(struct dm_verity *v)
*/
int verity_fec_ctr(struct dm_verity *v)
{
int r;
struct dm_verity_fec *f = v->fec;
struct dm_target *ti = v->ti;
struct mapped_device *md = dm_table_get_md(ti->table);
u64 hash_blocks;
int ret;
@ -682,6 +716,16 @@ int verity_fec_ctr(struct dm_verity *v)
return 0;
}
/* Create a kobject and sysfs attributes */
init_completion(&f->kobj_holder.completion);
r = kobject_init_and_add(&f->kobj_holder.kobj, &fec_ktype,
&disk_to_dev(dm_disk(md))->kobj, "%s", "fec");
if (r) {
ti->error = "Cannot create kobject";
return r;
}
/*
* FEC is computed over data blocks, possible metadata, and
* hash blocks. In other words, FEC covers total of fec_blocks

View file

@ -12,6 +12,8 @@
#ifndef DM_VERITY_FEC_H
#define DM_VERITY_FEC_H
#include "dm.h"
#include "dm-core.h"
#include "dm-verity.h"
#include <linux/rslib.h>
@ -51,6 +53,8 @@ struct dm_verity_fec {
mempool_t extra_pool; /* mempool for extra buffers */
mempool_t output_pool; /* mempool for output */
struct kmem_cache *cache; /* cache for buffers */
atomic_t corrected; /* corrected errors */
struct dm_kobject_holder kobj_holder; /* for sysfs attributes */
};
/* per-bio data */

View file

@ -235,8 +235,12 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type,
if (v->mode == DM_VERITY_MODE_LOGGING)
return 0;
if (v->mode == DM_VERITY_MODE_RESTART)
if (v->mode == DM_VERITY_MODE_RESTART) {
#ifdef CONFIG_DM_VERITY_AVB
dm_verity_avb_error_handler();
#endif
kernel_restart("dm-verity device corrupted");
}
return 1;
}
@ -564,6 +568,7 @@ static void verity_prefetch_io(struct work_struct *work)
container_of(work, struct dm_verity_prefetch_work, work);
struct dm_verity *v = pw->v;
int i;
sector_t prefetch_size;
for (i = v->levels - 2; i >= 0; i--) {
sector_t hash_block_start;
@ -586,8 +591,14 @@ static void verity_prefetch_io(struct work_struct *work)
hash_block_end = v->hash_blocks - 1;
}
no_prefetch_cluster:
// for emmc, it is more efficient to send bigger read
prefetch_size = max((sector_t)CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE,
hash_block_end - hash_block_start + 1);
if ((hash_block_start + prefetch_size) >= (v->hash_start + v->hash_blocks)) {
prefetch_size = hash_block_end - hash_block_start + 1;
}
dm_bufio_prefetch(v->bufio, hash_block_start,
hash_block_end - hash_block_start + 1);
prefetch_size);
}
kfree(pw);
@ -614,7 +625,7 @@ static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io)
* Bio map function. It allocates dm_verity_io structure and bio vector and
* fills them. Then it issues prefetches and the I/O.
*/
static int verity_map(struct dm_target *ti, struct bio *bio)
int verity_map(struct dm_target *ti, struct bio *bio)
{
struct dm_verity *v = ti->private;
struct dm_verity_io *io;
@ -659,7 +670,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
/*
* Status: V (valid) or C (corruption found)
*/
static void verity_status(struct dm_target *ti, status_type_t type,
void verity_status(struct dm_target *ti, status_type_t type,
unsigned status_flags, char *result, unsigned maxlen)
{
struct dm_verity *v = ti->private;
@ -723,7 +734,7 @@ static void verity_status(struct dm_target *ti, status_type_t type,
}
}
static int verity_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
int verity_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
{
struct dm_verity *v = ti->private;
@ -735,7 +746,7 @@ static int verity_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
return 0;
}
static int verity_iterate_devices(struct dm_target *ti,
int verity_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{
struct dm_verity *v = ti->private;
@ -743,7 +754,7 @@ static int verity_iterate_devices(struct dm_target *ti,
return fn(ti, v->data_dev, v->data_start, ti->len, data);
}
static void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
struct dm_verity *v = ti->private;
@ -756,7 +767,7 @@ static void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
blk_limits_io_min(limits, limits->logical_block_size);
}
static void verity_dtr(struct dm_target *ti)
void verity_dtr(struct dm_target *ti)
{
struct dm_verity *v = ti->private;
@ -911,7 +922,7 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v)
* <digest>
* <salt> Hex string or "-" if no salt.
*/
static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
{
struct dm_verity *v;
struct dm_arg_set as;
@ -1075,6 +1086,14 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto bad;
}
#ifdef CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED
if (!v->validated_blocks) {
r = verity_alloc_most_once(v);
if (r)
goto bad;
}
#endif
v->hash_per_block_bits =
__fls((1 << v->hash_dev_block_bits) / v->digest_size);

View file

@ -127,4 +127,14 @@ extern int verity_hash(struct dm_verity *v, struct ahash_request *req,
extern int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io,
sector_t block, u8 *digest, bool *is_zero);
extern void verity_status(struct dm_target *ti, status_type_t type,
unsigned status_flags, char *result, unsigned maxlen);
extern int verity_prepare_ioctl(struct dm_target *ti, struct block_device **bdev);
extern int verity_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data);
extern void verity_io_hints(struct dm_target *ti, struct queue_limits *limits);
extern void verity_dtr(struct dm_target *ti);
extern int verity_ctr(struct dm_target *ti, unsigned argc, char **argv);
extern int verity_map(struct dm_target *ti, struct bio *bio);
extern void dm_verity_avb_error_handler(void);
#endif /* DM_VERITY_H */

View file

@ -80,8 +80,6 @@ void dm_set_md_type(struct mapped_device *md, enum dm_queue_mode type);
enum dm_queue_mode dm_get_md_type(struct mapped_device *md);
struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t);
/*
* To check the return value from dm_table_find_target().
*/

View file

@ -513,6 +513,27 @@ config MISC_RTSX
tristate
default MISC_RTSX_PCI || MISC_RTSX_USB
config UID_SYS_STATS
bool "Per-UID statistics"
depends on PROFILING && TASK_XACCT && TASK_IO_ACCOUNTING
help
Per UID based cpu time statistics exported to /proc/uid_cputime
Per UID based io statistics exported to /proc/uid_io
Per UID based procstat control in /proc/uid_procstat
config UID_SYS_STATS_DEBUG
bool "Per-TASK statistics"
depends on UID_SYS_STATS
default n
help
Per TASK based io statistics exported to /proc/uid_io
config MEMORY_STATE_TIME
tristate "Memory freq/bandwidth time statistics"
depends on PROFILING
help
Memory time statistics exported to /sys/kernel/memory_state_time
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"

View file

@ -58,3 +58,5 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
obj-$(CONFIG_OCXL) += ocxl/
obj-$(CONFIG_MISC_RTSX) += cardreader/
obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o
obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o

View file

@ -0,0 +1,462 @@
/* drivers/misc/memory_state_time.c
*
* Copyright (C) 2016 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/hashtable.h>
#include <linux/kconfig.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/memory-state-time.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/time.h>
#include <linux/timekeeping.h>
#include <linux/workqueue.h>
#define KERNEL_ATTR_RO(_name) \
static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
#define KERNEL_ATTR_RW(_name) \
static struct kobj_attribute _name##_attr = \
__ATTR(_name, 0644, _name##_show, _name##_store)
#define FREQ_HASH_BITS 4
DECLARE_HASHTABLE(freq_hash_table, FREQ_HASH_BITS);
static DEFINE_MUTEX(mem_lock);
#define TAG "memory_state_time"
#define BW_NODE "/soc/memory-state-time"
#define FREQ_TBL "freq-tbl"
#define BW_TBL "bw-buckets"
#define NUM_SOURCES "num-sources"
#define LOWEST_FREQ 2
static int curr_bw;
static int curr_freq;
static u32 *bw_buckets;
static u32 *freq_buckets;
static int num_freqs;
static int num_buckets;
static int registered_bw_sources;
static u64 last_update;
static bool init_success;
static struct workqueue_struct *memory_wq;
static u32 num_sources = 10;
static int *bandwidths;
struct freq_entry {
int freq;
u64 *buckets; /* Bandwidth buckets. */
struct hlist_node hash;
};
struct queue_container {
struct work_struct update_state;
int value;
u64 time_now;
int id;
struct mutex *lock;
};
static int find_bucket(int bw)
{
int i;
if (bw_buckets != NULL) {
for (i = 0; i < num_buckets; i++) {
if (bw_buckets[i] > bw) {
pr_debug("Found bucket %d for bandwidth %d\n",
i, bw);
return i;
}
}
return num_buckets - 1;
}
return 0;
}
static u64 get_time_diff(u64 time_now)
{
u64 ms;
ms = time_now - last_update;
last_update = time_now;
return ms;
}
static ssize_t show_stat_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
int i, j;
int len = 0;
struct freq_entry *freq_entry;
for (i = 0; i < num_freqs; i++) {
hash_for_each_possible(freq_hash_table, freq_entry, hash,
freq_buckets[i]) {
if (freq_entry->freq == freq_buckets[i]) {
len += scnprintf(buf + len, PAGE_SIZE - len,
"%d ", freq_buckets[i]);
if (len >= PAGE_SIZE)
break;
for (j = 0; j < num_buckets; j++) {
len += scnprintf(buf + len,
PAGE_SIZE - len,
"%llu ",
freq_entry->buckets[j]);
}
len += scnprintf(buf + len, PAGE_SIZE - len,
"\n");
}
}
}
pr_debug("Current Time: %llu\n", ktime_get_boot_ns());
return len;
}
KERNEL_ATTR_RO(show_stat);
static void update_table(u64 time_now)
{
struct freq_entry *freq_entry;
pr_debug("Last known bw %d freq %d\n", curr_bw, curr_freq);
hash_for_each_possible(freq_hash_table, freq_entry, hash, curr_freq) {
if (curr_freq == freq_entry->freq) {
freq_entry->buckets[find_bucket(curr_bw)]
+= get_time_diff(time_now);
break;
}
}
}
static bool freq_exists(int freq)
{
int i;
for (i = 0; i < num_freqs; i++) {
if (freq == freq_buckets[i])
return true;
}
return false;
}
static int calculate_total_bw(int bw, int index)
{
int i;
int total_bw = 0;
pr_debug("memory_state_time New bw %d for id %d\n", bw, index);
bandwidths[index] = bw;
for (i = 0; i < registered_bw_sources; i++)
total_bw += bandwidths[i];
return total_bw;
}
static void freq_update_do_work(struct work_struct *work)
{
struct queue_container *freq_state_update
= container_of(work, struct queue_container,
update_state);
if (freq_state_update) {
mutex_lock(&mem_lock);
update_table(freq_state_update->time_now);
curr_freq = freq_state_update->value;
mutex_unlock(&mem_lock);
kfree(freq_state_update);
}
}
static void bw_update_do_work(struct work_struct *work)
{
struct queue_container *bw_state_update
= container_of(work, struct queue_container,
update_state);
if (bw_state_update) {
mutex_lock(&mem_lock);
update_table(bw_state_update->time_now);
curr_bw = calculate_total_bw(bw_state_update->value,
bw_state_update->id);
mutex_unlock(&mem_lock);
kfree(bw_state_update);
}
}
static void memory_state_freq_update(struct memory_state_update_block *ub,
int value)
{
if (IS_ENABLED(CONFIG_MEMORY_STATE_TIME)) {
if (freq_exists(value) && init_success) {
struct queue_container *freq_container
= kmalloc(sizeof(struct queue_container),
GFP_KERNEL);
if (!freq_container)
return;
INIT_WORK(&freq_container->update_state,
freq_update_do_work);
freq_container->time_now = ktime_get_boot_ns();
freq_container->value = value;
pr_debug("Scheduling freq update in work queue\n");
queue_work(memory_wq, &freq_container->update_state);
} else {
pr_debug("Freq does not exist.\n");
}
}
}
static void memory_state_bw_update(struct memory_state_update_block *ub,
int value)
{
if (IS_ENABLED(CONFIG_MEMORY_STATE_TIME)) {
if (init_success) {
struct queue_container *bw_container
= kmalloc(sizeof(struct queue_container),
GFP_KERNEL);
if (!bw_container)
return;
INIT_WORK(&bw_container->update_state,
bw_update_do_work);
bw_container->time_now = ktime_get_boot_ns();
bw_container->value = value;
bw_container->id = ub->id;
pr_debug("Scheduling bandwidth update in work queue\n");
queue_work(memory_wq, &bw_container->update_state);
}
}
}
struct memory_state_update_block *memory_state_register_frequency_source(void)
{
struct memory_state_update_block *block;
if (IS_ENABLED(CONFIG_MEMORY_STATE_TIME)) {
pr_debug("Allocating frequency source\n");
block = kmalloc(sizeof(struct memory_state_update_block),
GFP_KERNEL);
if (!block)
return NULL;
block->update_call = memory_state_freq_update;
return block;
}
pr_err("Config option disabled.\n");
return NULL;
}
EXPORT_SYMBOL_GPL(memory_state_register_frequency_source);
struct memory_state_update_block *memory_state_register_bandwidth_source(void)
{
struct memory_state_update_block *block;
if (IS_ENABLED(CONFIG_MEMORY_STATE_TIME)) {
pr_debug("Allocating bandwidth source %d\n",
registered_bw_sources);
block = kmalloc(sizeof(struct memory_state_update_block),
GFP_KERNEL);
if (!block)
return NULL;
block->update_call = memory_state_bw_update;
if (registered_bw_sources < num_sources) {
block->id = registered_bw_sources++;
} else {
pr_err("Unable to allocate source; max number reached\n");
kfree(block);
return NULL;
}
return block;
}
pr_err("Config option disabled.\n");
return NULL;
}
EXPORT_SYMBOL_GPL(memory_state_register_bandwidth_source);
/* Buckets are designated by their maximum.
* Returns the buckets decided by the capability of the device.
*/
static int get_bw_buckets(struct device *dev)
{
int ret, lenb;
struct device_node *node = dev->of_node;
of_property_read_u32(node, NUM_SOURCES, &num_sources);
if (!of_find_property(node, BW_TBL, &lenb)) {
pr_err("Missing %s property\n", BW_TBL);
return -ENODATA;
}
bandwidths = devm_kzalloc(dev,
sizeof(*bandwidths) * num_sources, GFP_KERNEL);
if (!bandwidths)
return -ENOMEM;
lenb /= sizeof(*bw_buckets);
bw_buckets = devm_kzalloc(dev, lenb * sizeof(*bw_buckets),
GFP_KERNEL);
if (!bw_buckets) {
devm_kfree(dev, bandwidths);
return -ENOMEM;
}
ret = of_property_read_u32_array(node, BW_TBL, bw_buckets,
lenb);
if (ret < 0) {
devm_kfree(dev, bandwidths);
devm_kfree(dev, bw_buckets);
pr_err("Unable to read bandwidth table from device tree.\n");
return ret;
}
curr_bw = 0;
num_buckets = lenb;
return 0;
}
/* Adds struct freq_entry nodes to the hashtable for each compatible frequency.
* Returns the supported number of frequencies.
*/
static int freq_buckets_init(struct device *dev)
{
struct freq_entry *freq_entry;
int i;
int ret, lenf;
struct device_node *node = dev->of_node;
if (!of_find_property(node, FREQ_TBL, &lenf)) {
pr_err("Missing %s property\n", FREQ_TBL);
return -ENODATA;
}
lenf /= sizeof(*freq_buckets);
freq_buckets = devm_kzalloc(dev, lenf * sizeof(*freq_buckets),
GFP_KERNEL);
if (!freq_buckets)
return -ENOMEM;
pr_debug("freqs found len %d\n", lenf);
ret = of_property_read_u32_array(node, FREQ_TBL, freq_buckets,
lenf);
if (ret < 0) {
devm_kfree(dev, freq_buckets);
pr_err("Unable to read frequency table from device tree.\n");
return ret;
}
pr_debug("ret freq %d\n", ret);
num_freqs = lenf;
curr_freq = freq_buckets[LOWEST_FREQ];
for (i = 0; i < num_freqs; i++) {
freq_entry = devm_kzalloc(dev, sizeof(struct freq_entry),
GFP_KERNEL);
if (!freq_entry)
return -ENOMEM;
freq_entry->buckets = devm_kzalloc(dev, sizeof(u64)*num_buckets,
GFP_KERNEL);
if (!freq_entry->buckets) {
devm_kfree(dev, freq_entry);
return -ENOMEM;
}
pr_debug("memory_state_time Adding freq to ht %d\n",
freq_buckets[i]);
freq_entry->freq = freq_buckets[i];
hash_add(freq_hash_table, &freq_entry->hash, freq_buckets[i]);
}
return 0;
}
struct kobject *memory_kobj;
EXPORT_SYMBOL_GPL(memory_kobj);
static struct attribute *memory_attrs[] = {
&show_stat_attr.attr,
NULL
};
static struct attribute_group memory_attr_group = {
.attrs = memory_attrs,
};
static int memory_state_time_probe(struct platform_device *pdev)
{
int error;
error = get_bw_buckets(&pdev->dev);
if (error)
return error;
error = freq_buckets_init(&pdev->dev);
if (error)
return error;
last_update = ktime_get_boot_ns();
init_success = true;
pr_debug("memory_state_time initialized with num_freqs %d\n",
num_freqs);
return 0;
}
static const struct of_device_id match_table[] = {
{ .compatible = "memory-state-time" },
{}
};
static struct platform_driver memory_state_time_driver = {
.probe = memory_state_time_probe,
.driver = {
.name = "memory-state-time",
.of_match_table = match_table,
.owner = THIS_MODULE,
},
};
static int __init memory_state_time_init(void)
{
int error;
hash_init(freq_hash_table);
memory_wq = create_singlethread_workqueue("memory_wq");
if (!memory_wq) {
pr_err("Unable to create workqueue.\n");
return -EINVAL;
}
/*
* Create sys/kernel directory for memory_state_time.
*/
memory_kobj = kobject_create_and_add(TAG, kernel_kobj);
if (!memory_kobj) {
pr_err("Unable to allocate memory_kobj for sysfs directory.\n");
error = -ENOMEM;
goto wq;
}
error = sysfs_create_group(memory_kobj, &memory_attr_group);
if (error) {
pr_err("Unable to create sysfs folder.\n");
goto kobj;
}
error = platform_driver_register(&memory_state_time_driver);
if (error) {
pr_err("Unable to register memory_state_time platform driver.\n");
goto group;
}
return 0;
group: sysfs_remove_group(memory_kobj, &memory_attr_group);
kobj: kobject_put(memory_kobj);
wq: destroy_workqueue(memory_wq);
return error;
}
module_init(memory_state_time_init);

View file

@ -0,0 +1,703 @@
/* drivers/misc/uid_sys_stats.c
*
* Copyright (C) 2014 - 2015 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/atomic.h>
#include <linux/cpufreq_times.h>
#include <linux/err.h>
#include <linux/hashtable.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/profile.h>
#include <linux/rtmutex.h>
#include <linux/sched/cputime.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#define UID_HASH_BITS 10
DECLARE_HASHTABLE(hash_table, UID_HASH_BITS);
static DEFINE_RT_MUTEX(uid_lock);
static struct proc_dir_entry *cpu_parent;
static struct proc_dir_entry *io_parent;
static struct proc_dir_entry *proc_parent;
struct io_stats {
u64 read_bytes;
u64 write_bytes;
u64 rchar;
u64 wchar;
u64 fsync;
};
#define UID_STATE_FOREGROUND 0
#define UID_STATE_BACKGROUND 1
#define UID_STATE_BUCKET_SIZE 2
#define UID_STATE_TOTAL_CURR 2
#define UID_STATE_TOTAL_LAST 3
#define UID_STATE_DEAD_TASKS 4
#define UID_STATE_SIZE 5
#define MAX_TASK_COMM_LEN 256
struct task_entry {
char comm[MAX_TASK_COMM_LEN];
pid_t pid;
struct io_stats io[UID_STATE_SIZE];
struct hlist_node hash;
};
struct uid_entry {
uid_t uid;
u64 utime;
u64 stime;
u64 active_utime;
u64 active_stime;
int state;
struct io_stats io[UID_STATE_SIZE];
struct hlist_node hash;
#ifdef CONFIG_UID_SYS_STATS_DEBUG
DECLARE_HASHTABLE(task_entries, UID_HASH_BITS);
#endif
};
static u64 compute_write_bytes(struct task_struct *task)
{
if (task->ioac.write_bytes <= task->ioac.cancelled_write_bytes)
return 0;
return task->ioac.write_bytes - task->ioac.cancelled_write_bytes;
}
static void compute_io_bucket_stats(struct io_stats *io_bucket,
struct io_stats *io_curr,
struct io_stats *io_last,
struct io_stats *io_dead)
{
/* tasks could switch to another uid group, but its io_last in the
* previous uid group could still be positive.
* therefore before each update, do an overflow check first
*/
int64_t delta;
delta = io_curr->read_bytes + io_dead->read_bytes -
io_last->read_bytes;
io_bucket->read_bytes += delta > 0 ? delta : 0;
delta = io_curr->write_bytes + io_dead->write_bytes -
io_last->write_bytes;
io_bucket->write_bytes += delta > 0 ? delta : 0;
delta = io_curr->rchar + io_dead->rchar - io_last->rchar;
io_bucket->rchar += delta > 0 ? delta : 0;
delta = io_curr->wchar + io_dead->wchar - io_last->wchar;
io_bucket->wchar += delta > 0 ? delta : 0;
delta = io_curr->fsync + io_dead->fsync - io_last->fsync;
io_bucket->fsync += delta > 0 ? delta : 0;
io_last->read_bytes = io_curr->read_bytes;
io_last->write_bytes = io_curr->write_bytes;
io_last->rchar = io_curr->rchar;
io_last->wchar = io_curr->wchar;
io_last->fsync = io_curr->fsync;
memset(io_dead, 0, sizeof(struct io_stats));
}
#ifdef CONFIG_UID_SYS_STATS_DEBUG
static void get_full_task_comm(struct task_entry *task_entry,
struct task_struct *task)
{
int i = 0, offset = 0, len = 0;
/* save one byte for terminating null character */
int unused_len = MAX_TASK_COMM_LEN - TASK_COMM_LEN - 1;
char buf[unused_len];
struct mm_struct *mm = task->mm;
/* fill the first TASK_COMM_LEN bytes with thread name */
__get_task_comm(task_entry->comm, TASK_COMM_LEN, task);
i = strlen(task_entry->comm);
while (i < TASK_COMM_LEN)
task_entry->comm[i++] = ' ';
/* next the executable file name */
if (mm) {
down_read(&mm->mmap_sem);
if (mm->exe_file) {
char *pathname = d_path(&mm->exe_file->f_path, buf,
unused_len);
if (!IS_ERR(pathname)) {
len = strlcpy(task_entry->comm + i, pathname,
unused_len);
i += len;
task_entry->comm[i++] = ' ';
unused_len--;
}
}
up_read(&mm->mmap_sem);
}
unused_len -= len;
/* fill the rest with command line argument
* replace each null or new line character
* between args in argv with whitespace */
len = get_cmdline(task, buf, unused_len);
while (offset < len) {
if (buf[offset] != '\0' && buf[offset] != '\n')
task_entry->comm[i++] = buf[offset];
else
task_entry->comm[i++] = ' ';
offset++;
}
/* get rid of trailing whitespaces in case when arg is memset to
* zero before being reset in userspace
*/
while (task_entry->comm[i-1] == ' ')
i--;
task_entry->comm[i] = '\0';
}
static struct task_entry *find_task_entry(struct uid_entry *uid_entry,
struct task_struct *task)
{
struct task_entry *task_entry;
hash_for_each_possible(uid_entry->task_entries, task_entry, hash,
task->pid) {
if (task->pid == task_entry->pid) {
/* if thread name changed, update the entire command */
int len = strnchr(task_entry->comm, ' ', TASK_COMM_LEN)
- task_entry->comm;
if (strncmp(task_entry->comm, task->comm, len))
get_full_task_comm(task_entry, task);
return task_entry;
}
}
return NULL;
}
static struct task_entry *find_or_register_task(struct uid_entry *uid_entry,
struct task_struct *task)
{
struct task_entry *task_entry;
pid_t pid = task->pid;
task_entry = find_task_entry(uid_entry, task);
if (task_entry)
return task_entry;
task_entry = kzalloc(sizeof(struct task_entry), GFP_ATOMIC);
if (!task_entry)
return NULL;
get_full_task_comm(task_entry, task);
task_entry->pid = pid;
hash_add(uid_entry->task_entries, &task_entry->hash, (unsigned int)pid);
return task_entry;
}
static void remove_uid_tasks(struct uid_entry *uid_entry)
{
struct task_entry *task_entry;
unsigned long bkt_task;
struct hlist_node *tmp_task;
hash_for_each_safe(uid_entry->task_entries, bkt_task,
tmp_task, task_entry, hash) {
hash_del(&task_entry->hash);
kfree(task_entry);
}
}
static void set_io_uid_tasks_zero(struct uid_entry *uid_entry)
{
struct task_entry *task_entry;
unsigned long bkt_task;
hash_for_each(uid_entry->task_entries, bkt_task, task_entry, hash) {
memset(&task_entry->io[UID_STATE_TOTAL_CURR], 0,
sizeof(struct io_stats));
}
}
static void add_uid_tasks_io_stats(struct uid_entry *uid_entry,
struct task_struct *task, int slot)
{
struct task_entry *task_entry = find_or_register_task(uid_entry, task);
struct io_stats *task_io_slot = &task_entry->io[slot];
task_io_slot->read_bytes += task->ioac.read_bytes;
task_io_slot->write_bytes += compute_write_bytes(task);
task_io_slot->rchar += task->ioac.rchar;
task_io_slot->wchar += task->ioac.wchar;
task_io_slot->fsync += task->ioac.syscfs;
}
static void compute_io_uid_tasks(struct uid_entry *uid_entry)
{
struct task_entry *task_entry;
unsigned long bkt_task;
hash_for_each(uid_entry->task_entries, bkt_task, task_entry, hash) {
compute_io_bucket_stats(&task_entry->io[uid_entry->state],
&task_entry->io[UID_STATE_TOTAL_CURR],
&task_entry->io[UID_STATE_TOTAL_LAST],
&task_entry->io[UID_STATE_DEAD_TASKS]);
}
}
static void show_io_uid_tasks(struct seq_file *m, struct uid_entry *uid_entry)
{
struct task_entry *task_entry;
unsigned long bkt_task;
hash_for_each(uid_entry->task_entries, bkt_task, task_entry, hash) {
/* Separated by comma because space exists in task comm */
seq_printf(m, "task,%s,%lu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n",
task_entry->comm,
(unsigned long)task_entry->pid,
task_entry->io[UID_STATE_FOREGROUND].rchar,
task_entry->io[UID_STATE_FOREGROUND].wchar,
task_entry->io[UID_STATE_FOREGROUND].read_bytes,
task_entry->io[UID_STATE_FOREGROUND].write_bytes,
task_entry->io[UID_STATE_BACKGROUND].rchar,
task_entry->io[UID_STATE_BACKGROUND].wchar,
task_entry->io[UID_STATE_BACKGROUND].read_bytes,
task_entry->io[UID_STATE_BACKGROUND].write_bytes,
task_entry->io[UID_STATE_FOREGROUND].fsync,
task_entry->io[UID_STATE_BACKGROUND].fsync);
}
}
#else
static void remove_uid_tasks(struct uid_entry *uid_entry) {};
static void set_io_uid_tasks_zero(struct uid_entry *uid_entry) {};
static void add_uid_tasks_io_stats(struct uid_entry *uid_entry,
struct task_struct *task, int slot) {};
static void compute_io_uid_tasks(struct uid_entry *uid_entry) {};
static void show_io_uid_tasks(struct seq_file *m,
struct uid_entry *uid_entry) {}
#endif
static struct uid_entry *find_uid_entry(uid_t uid)
{
struct uid_entry *uid_entry;
hash_for_each_possible(hash_table, uid_entry, hash, uid) {
if (uid_entry->uid == uid)
return uid_entry;
}
return NULL;
}
static struct uid_entry *find_or_register_uid(uid_t uid)
{
struct uid_entry *uid_entry;
uid_entry = find_uid_entry(uid);
if (uid_entry)
return uid_entry;
uid_entry = kzalloc(sizeof(struct uid_entry), GFP_ATOMIC);
if (!uid_entry)
return NULL;
uid_entry->uid = uid;
#ifdef CONFIG_UID_SYS_STATS_DEBUG
hash_init(uid_entry->task_entries);
#endif
hash_add(hash_table, &uid_entry->hash, uid);
return uid_entry;
}
static int uid_cputime_show(struct seq_file *m, void *v)
{
struct uid_entry *uid_entry = NULL;
struct task_struct *task, *temp;
struct user_namespace *user_ns = current_user_ns();
u64 utime;
u64 stime;
unsigned long bkt;
uid_t uid;
rt_mutex_lock(&uid_lock);
hash_for_each(hash_table, bkt, uid_entry, hash) {
uid_entry->active_stime = 0;
uid_entry->active_utime = 0;
}
rcu_read_lock();
do_each_thread(temp, task) {
uid = from_kuid_munged(user_ns, task_uid(task));
if (!uid_entry || uid_entry->uid != uid)
uid_entry = find_or_register_uid(uid);
if (!uid_entry) {
rcu_read_unlock();
rt_mutex_unlock(&uid_lock);
pr_err("%s: failed to find the uid_entry for uid %d\n",
__func__, uid);
return -ENOMEM;
}
task_cputime_adjusted(task, &utime, &stime);
uid_entry->active_utime += utime;
uid_entry->active_stime += stime;
} while_each_thread(temp, task);
rcu_read_unlock();
hash_for_each(hash_table, bkt, uid_entry, hash) {
u64 total_utime = uid_entry->utime +
uid_entry->active_utime;
u64 total_stime = uid_entry->stime +
uid_entry->active_stime;
seq_printf(m, "%d: %llu %llu\n", uid_entry->uid,
ktime_to_ms(total_utime), ktime_to_ms(total_stime));
}
rt_mutex_unlock(&uid_lock);
return 0;
}
static int uid_cputime_open(struct inode *inode, struct file *file)
{
return single_open(file, uid_cputime_show, PDE_DATA(inode));
}
static const struct file_operations uid_cputime_fops = {
.open = uid_cputime_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int uid_remove_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, NULL);
}
static ssize_t uid_remove_write(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos)
{
struct uid_entry *uid_entry;
struct hlist_node *tmp;
char uids[128];
char *start_uid, *end_uid = NULL;
long int uid_start = 0, uid_end = 0;
if (count >= sizeof(uids))
count = sizeof(uids) - 1;
if (copy_from_user(uids, buffer, count))
return -EFAULT;
uids[count] = '\0';
end_uid = uids;
start_uid = strsep(&end_uid, "-");
if (!start_uid || !end_uid)
return -EINVAL;
if (kstrtol(start_uid, 10, &uid_start) != 0 ||
kstrtol(end_uid, 10, &uid_end) != 0) {
return -EINVAL;
}
/* Also remove uids from /proc/uid_time_in_state */
cpufreq_task_times_remove_uids(uid_start, uid_end);
rt_mutex_lock(&uid_lock);
for (; uid_start <= uid_end; uid_start++) {
hash_for_each_possible_safe(hash_table, uid_entry, tmp,
hash, (uid_t)uid_start) {
if (uid_start == uid_entry->uid) {
remove_uid_tasks(uid_entry);
hash_del(&uid_entry->hash);
kfree(uid_entry);
}
}
}
rt_mutex_unlock(&uid_lock);
return count;
}
static const struct file_operations uid_remove_fops = {
.open = uid_remove_open,
.release = single_release,
.write = uid_remove_write,
};
static void add_uid_io_stats(struct uid_entry *uid_entry,
struct task_struct *task, int slot)
{
struct io_stats *io_slot = &uid_entry->io[slot];
io_slot->read_bytes += task->ioac.read_bytes;
io_slot->write_bytes += compute_write_bytes(task);
io_slot->rchar += task->ioac.rchar;
io_slot->wchar += task->ioac.wchar;
io_slot->fsync += task->ioac.syscfs;
add_uid_tasks_io_stats(uid_entry, task, slot);
}
static void update_io_stats_all_locked(void)
{
struct uid_entry *uid_entry = NULL;
struct task_struct *task, *temp;
struct user_namespace *user_ns = current_user_ns();
unsigned long bkt;
uid_t uid;
hash_for_each(hash_table, bkt, uid_entry, hash) {
memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0,
sizeof(struct io_stats));
set_io_uid_tasks_zero(uid_entry);
}
rcu_read_lock();
do_each_thread(temp, task) {
uid = from_kuid_munged(user_ns, task_uid(task));
if (!uid_entry || uid_entry->uid != uid)
uid_entry = find_or_register_uid(uid);
if (!uid_entry)
continue;
add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR);
} while_each_thread(temp, task);
rcu_read_unlock();
hash_for_each(hash_table, bkt, uid_entry, hash) {
compute_io_bucket_stats(&uid_entry->io[uid_entry->state],
&uid_entry->io[UID_STATE_TOTAL_CURR],
&uid_entry->io[UID_STATE_TOTAL_LAST],
&uid_entry->io[UID_STATE_DEAD_TASKS]);
compute_io_uid_tasks(uid_entry);
}
}
static void update_io_stats_uid_locked(struct uid_entry *uid_entry)
{
struct task_struct *task, *temp;
struct user_namespace *user_ns = current_user_ns();
memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0,
sizeof(struct io_stats));
set_io_uid_tasks_zero(uid_entry);
rcu_read_lock();
do_each_thread(temp, task) {
if (from_kuid_munged(user_ns, task_uid(task)) != uid_entry->uid)
continue;
add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR);
} while_each_thread(temp, task);
rcu_read_unlock();
compute_io_bucket_stats(&uid_entry->io[uid_entry->state],
&uid_entry->io[UID_STATE_TOTAL_CURR],
&uid_entry->io[UID_STATE_TOTAL_LAST],
&uid_entry->io[UID_STATE_DEAD_TASKS]);
compute_io_uid_tasks(uid_entry);
}
static int uid_io_show(struct seq_file *m, void *v)
{
struct uid_entry *uid_entry;
unsigned long bkt;
rt_mutex_lock(&uid_lock);
update_io_stats_all_locked();
hash_for_each(hash_table, bkt, uid_entry, hash) {
seq_printf(m, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
uid_entry->uid,
uid_entry->io[UID_STATE_FOREGROUND].rchar,
uid_entry->io[UID_STATE_FOREGROUND].wchar,
uid_entry->io[UID_STATE_FOREGROUND].read_bytes,
uid_entry->io[UID_STATE_FOREGROUND].write_bytes,
uid_entry->io[UID_STATE_BACKGROUND].rchar,
uid_entry->io[UID_STATE_BACKGROUND].wchar,
uid_entry->io[UID_STATE_BACKGROUND].read_bytes,
uid_entry->io[UID_STATE_BACKGROUND].write_bytes,
uid_entry->io[UID_STATE_FOREGROUND].fsync,
uid_entry->io[UID_STATE_BACKGROUND].fsync);
show_io_uid_tasks(m, uid_entry);
}
rt_mutex_unlock(&uid_lock);
return 0;
}
static int uid_io_open(struct inode *inode, struct file *file)
{
return single_open(file, uid_io_show, PDE_DATA(inode));
}
static const struct file_operations uid_io_fops = {
.open = uid_io_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int uid_procstat_open(struct inode *inode, struct file *file)
{
return single_open(file, NULL, NULL);
}
static ssize_t uid_procstat_write(struct file *file,
const char __user *buffer, size_t count, loff_t *ppos)
{
struct uid_entry *uid_entry;
uid_t uid;
int argc, state;
char input[128];
if (count >= sizeof(input))
return -EINVAL;
if (copy_from_user(input, buffer, count))
return -EFAULT;
input[count] = '\0';
argc = sscanf(input, "%u %d", &uid, &state);
if (argc != 2)
return -EINVAL;
if (state != UID_STATE_BACKGROUND && state != UID_STATE_FOREGROUND)
return -EINVAL;
rt_mutex_lock(&uid_lock);
uid_entry = find_or_register_uid(uid);
if (!uid_entry) {
rt_mutex_unlock(&uid_lock);
return -EINVAL;
}
if (uid_entry->state == state) {
rt_mutex_unlock(&uid_lock);
return count;
}
update_io_stats_uid_locked(uid_entry);
uid_entry->state = state;
rt_mutex_unlock(&uid_lock);
return count;
}
static const struct file_operations uid_procstat_fops = {
.open = uid_procstat_open,
.release = single_release,
.write = uid_procstat_write,
};
static int process_notifier(struct notifier_block *self,
unsigned long cmd, void *v)
{
struct task_struct *task = v;
struct uid_entry *uid_entry;
u64 utime, stime;
uid_t uid;
if (!task)
return NOTIFY_OK;
rt_mutex_lock(&uid_lock);
uid = from_kuid_munged(current_user_ns(), task_uid(task));
uid_entry = find_or_register_uid(uid);
if (!uid_entry) {
pr_err("%s: failed to find uid %d\n", __func__, uid);
goto exit;
}
task_cputime_adjusted(task, &utime, &stime);
uid_entry->utime += utime;
uid_entry->stime += stime;
add_uid_io_stats(uid_entry, task, UID_STATE_DEAD_TASKS);
exit:
rt_mutex_unlock(&uid_lock);
return NOTIFY_OK;
}
static struct notifier_block process_notifier_block = {
.notifier_call = process_notifier,
};
static int __init proc_uid_sys_stats_init(void)
{
hash_init(hash_table);
cpu_parent = proc_mkdir("uid_cputime", NULL);
if (!cpu_parent) {
pr_err("%s: failed to create uid_cputime proc entry\n",
__func__);
goto err;
}
proc_create_data("remove_uid_range", 0222, cpu_parent,
&uid_remove_fops, NULL);
proc_create_data("show_uid_stat", 0444, cpu_parent,
&uid_cputime_fops, NULL);
io_parent = proc_mkdir("uid_io", NULL);
if (!io_parent) {
pr_err("%s: failed to create uid_io proc entry\n",
__func__);
goto err;
}
proc_create_data("stats", 0444, io_parent,
&uid_io_fops, NULL);
proc_parent = proc_mkdir("uid_procstat", NULL);
if (!proc_parent) {
pr_err("%s: failed to create uid_procstat proc entry\n",
__func__);
goto err;
}
proc_create_data("set", 0222, proc_parent,
&uid_procstat_fops, NULL);
profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block);
return 0;
err:
remove_proc_subtree("uid_cputime", NULL);
remove_proc_subtree("uid_io", NULL);
remove_proc_subtree("uid_procstat", NULL);
return -ENOMEM;
}
early_initcall(proc_uid_sys_stats_init);

View file

@ -441,7 +441,8 @@ int mmc_add_host(struct mmc_host *host)
#endif
mmc_start_host(host);
mmc_register_pm_notifier(host);
if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
mmc_register_pm_notifier(host);
return 0;
}
@ -458,7 +459,8 @@ EXPORT_SYMBOL(mmc_add_host);
*/
void mmc_remove_host(struct mmc_host *host)
{
mmc_unregister_pm_notifier(host);
if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
mmc_unregister_pm_notifier(host);
mmc_stop_host(host);
#ifdef CONFIG_DEBUG_FS

View file

@ -2879,6 +2879,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
int ret;
bool do_notify = false;
#ifdef CONFIG_ANDROID_PARANOID_NETWORK
if (cmd != TUNGETIFF && !capable(CAP_NET_ADMIN)) {
return -EPERM;
}
#endif
if (cmd == TUNSETIFF || cmd == TUNSETQUEUE ||
(_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) {
if (copy_from_user(&ifr, argp, ifreq_len))

View file

@ -549,6 +549,11 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
int ret;
/* Disable filtering */
ret = wl1271_acx_group_address_tbl(wl, wlvif, false, NULL, 0);
if (ret < 0)
return ret;
ret = wl1271_acx_ap_max_tx_retry(wl, wlvif);
if (ret < 0)
return ret;

View file

@ -176,6 +176,16 @@ static int fdp_nci_i2c_read(struct fdp_i2c_phy *phy, struct sk_buff **skb)
/* Packet that contains a length */
if (tmp[0] == 0 && tmp[1] == 0) {
phy->next_read_size = (tmp[2] << 8) + tmp[3] + 3;
/*
* Ensure next_read_size does not exceed sizeof(tmp)
* for reading that many bytes during next iteration
*/
if (phy->next_read_size > FDP_NCI_I2C_MAX_PAYLOAD) {
dev_dbg(&client->dev, "%s: corrupted packet\n",
__func__);
phy->next_read_size = 5;
goto flush;
}
} else {
phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD;

View file

@ -217,7 +217,8 @@ static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
atr_req = (struct st21nfca_atr_req *)skb->data;
if (atr_req->length < sizeof(struct st21nfca_atr_req)) {
if (atr_req->length < sizeof(struct st21nfca_atr_req) ||
atr_req->length > skb->len) {
r = -EPROTO;
goto exit;
}

View file

@ -322,23 +322,33 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
* AID 81 5 to 16
* PARAMETERS 82 0 to 255
*/
if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
if (skb->len < NFC_MIN_AID_LENGTH + 2 ||
skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
return -EPROTO;
/*
* Buffer should have enough space for at least
* two tag fields + two length fields + aid_len (skb->data[1])
*/
if (skb->len < skb->data[1] + 4)
return -EPROTO;
transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
skb->len - 2, GFP_KERNEL);
transaction->aid_len = skb->data[1];
memcpy(transaction->aid, &skb->data[2],
transaction->aid_len);
/* Check next byte is PARAMETERS tag (82) */
if (skb->data[transaction->aid_len + 2] !=
NFC_EVT_TRANSACTION_PARAMS_TAG)
return -EPROTO;
transaction->params_len = skb->data[transaction->aid_len + 3];
/* Check next byte is PARAMETERS tag (82) and the length field */
if (skb->data[transaction->aid_len + 2] !=
NFC_EVT_TRANSACTION_PARAMS_TAG ||
skb->len < transaction->aid_len + transaction->params_len + 4) {
devm_kfree(dev, transaction);
return -EPROTO;
}
memcpy(transaction->params, skb->data +
transaction->aid_len + 4, transaction->params_len);

View file

@ -1072,42 +1072,66 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
return 0;
}
/*
* Convert configs to something easy to use in C code
*/
#if defined(CONFIG_CMDLINE_FORCE)
static const int overwrite_incoming_cmdline = 1;
static const int read_dt_cmdline;
static const int concat_cmdline;
#elif defined(CONFIG_CMDLINE_EXTEND)
static const int overwrite_incoming_cmdline;
static const int read_dt_cmdline = 1;
static const int concat_cmdline = 1;
#else /* CMDLINE_FROM_BOOTLOADER */
static const int overwrite_incoming_cmdline;
static const int read_dt_cmdline = 1;
static const int concat_cmdline;
#endif
#ifdef CONFIG_CMDLINE
static const char *config_cmdline = CONFIG_CMDLINE;
#else
static const char *config_cmdline = "";
#endif
int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
int depth, void *data)
{
int l;
const char *p;
int l = 0;
const char *p = NULL;
char *cmdline = data;
pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
if (depth != 1 || !data ||
if (depth != 1 || !cmdline ||
(strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
return 0;
early_init_dt_check_for_initrd(node);
/* Retrieve command line */
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0)
strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
/* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */
if (overwrite_incoming_cmdline || !cmdline[0])
strlcpy(cmdline, config_cmdline, COMMAND_LINE_SIZE);
/*
* CONFIG_CMDLINE is meant to be a default in case nothing else
* managed to set the command line, unless CONFIG_CMDLINE_FORCE
* is set in which case we override whatever was found earlier.
*/
#ifdef CONFIG_CMDLINE
#if defined(CONFIG_CMDLINE_EXTEND)
strlcat(data, " ", COMMAND_LINE_SIZE);
strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#else
/* No arguments from boot loader, use kernel's cmdl*/
if (!((char *)data)[0])
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#endif
#endif /* CONFIG_CMDLINE */
/* Retrieve command line unless forcing */
if (read_dt_cmdline)
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0) {
if (concat_cmdline) {
int cmdline_len;
int copy_len;
strlcat(cmdline, " ", COMMAND_LINE_SIZE);
cmdline_len = strlen(cmdline);
copy_len = COMMAND_LINE_SIZE - cmdline_len - 1;
copy_len = min((int)l, copy_len);
strncpy(cmdline + cmdline_len, p, copy_len);
cmdline[cmdline_len + copy_len] = '\0';
} else {
strlcpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE));
}
}
pr_debug("Command line is: %s\n", (char*)data);

View file

@ -171,6 +171,9 @@ static ssize_t power_supply_show_property(struct device *dev,
ret = sprintf(buf, "%s\n",
power_supply_scope_text[value.intval]);
break;
case POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT:
ret = sprintf(buf, "%lld\n", value.int64val);
break;
case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER:
ret = sprintf(buf, "%s\n", value.strval);
break;
@ -302,6 +305,12 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(precharge_current),
POWER_SUPPLY_ATTR(charge_term_current),
POWER_SUPPLY_ATTR(calibrate),
/* Local extensions */
POWER_SUPPLY_ATTR(usb_hc),
POWER_SUPPLY_ATTR(usb_otg),
POWER_SUPPLY_ATTR(charge_enabled),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
POWER_SUPPLY_ATTR(model_name),
POWER_SUPPLY_ATTR(manufacturer),

View file

@ -226,6 +226,12 @@ config USB_F_CDEV
config USB_F_CCID
tristate
config USB_F_AUDIO_SRC
tristate
config USB_F_ACC
tristate
# this first set of drivers all depend on bulk-capable hardware.
config USB_CONFIGFS
@ -379,6 +385,30 @@ config USB_CONFIGFS_F_FS
implemented in kernel space (for instance Ethernet, serial or
mass storage) and other are implemented in user space.
config USB_CONFIGFS_F_ACC
bool "Accessory gadget"
depends on USB_CONFIGFS
select USB_F_ACC
help
USB gadget Accessory support
config USB_CONFIGFS_F_AUDIO_SRC
bool "Audio Source gadget"
depends on USB_CONFIGFS && USB_CONFIGFS_F_ACC
depends on SND
select SND_PCM
select USB_F_AUDIO_SRC
help
USB gadget Audio Source support
config USB_CONFIGFS_UEVENT
bool "Uevent notification of Gadget state"
depends on USB_CONFIGFS
help
Enable uevent notifications to userspace when the gadget
state changes. The gadget can be in any of the following
three states: "CONNECTED/DISCONNECTED/CONFIGURED"
config USB_CONFIGFS_F_UAC1
bool "Audio Class 1.0"
depends on USB_CONFIGFS

View file

@ -10,6 +10,31 @@
#include "u_f.h"
#include "u_os_desc.h"
#ifdef CONFIG_USB_CONFIGFS_UEVENT
#include <linux/platform_device.h>
#include <linux/kdev_t.h>
#include <linux/usb/ch9.h>
#ifdef CONFIG_USB_CONFIGFS_F_ACC
extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl);
void acc_disconnect(void);
#endif
static struct class *android_class;
static struct device *android_device;
static int index;
struct device *create_function_device(char *name)
{
if (android_device && !IS_ERR(android_device))
return device_create(android_class, android_device,
MKDEV(0, index++), NULL, name);
else
return ERR_PTR(-EINVAL);
}
EXPORT_SYMBOL_GPL(create_function_device);
#endif
int check_user_usb_string(const char *name,
struct usb_gadget_strings *stringtab_dev)
{
@ -61,6 +86,12 @@ struct gadget_info {
bool use_os_desc;
char b_vendor_code;
char qw_sign[OS_STRING_QW_SIGN_LEN];
#ifdef CONFIG_USB_CONFIGFS_UEVENT
bool connected;
bool sw_connected;
struct work_struct work;
struct device *dev;
#endif
};
static inline struct gadget_info *to_gadget_info(struct config_item *item)
@ -266,7 +297,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
mutex_lock(&gi->lock);
if (!strlen(name)) {
if (!strlen(name) || strcmp(name, "none") == 0) {
ret = unregister_gadget(gi);
if (ret)
goto err;
@ -1372,6 +1403,60 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
return ret;
}
#ifdef CONFIG_USB_CONFIGFS_UEVENT
static void android_work(struct work_struct *data)
{
struct gadget_info *gi = container_of(data, struct gadget_info, work);
struct usb_composite_dev *cdev = &gi->cdev;
char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
char *connected[2] = { "USB_STATE=CONNECTED", NULL };
char *configured[2] = { "USB_STATE=CONFIGURED", NULL };
/* 0-connected 1-configured 2-disconnected*/
bool status[3] = { false, false, false };
unsigned long flags;
bool uevent_sent = false;
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->config)
status[1] = true;
if (gi->connected != gi->sw_connected) {
if (gi->connected)
status[0] = true;
else
status[2] = true;
gi->sw_connected = gi->connected;
}
spin_unlock_irqrestore(&cdev->lock, flags);
if (status[0]) {
kobject_uevent_env(&android_device->kobj,
KOBJ_CHANGE, connected);
pr_info("%s: sent uevent %s\n", __func__, connected[0]);
uevent_sent = true;
}
if (status[1]) {
kobject_uevent_env(&android_device->kobj,
KOBJ_CHANGE, configured);
pr_info("%s: sent uevent %s\n", __func__, configured[0]);
uevent_sent = true;
}
if (status[2]) {
kobject_uevent_env(&android_device->kobj,
KOBJ_CHANGE, disconnected);
pr_info("%s: sent uevent %s\n", __func__, disconnected[0]);
uevent_sent = true;
}
if (!uevent_sent) {
pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
gi->connected, gi->sw_connected, cdev->config);
}
}
#endif
static void configfs_composite_unbind(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
@ -1391,14 +1476,91 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
set_gadget_data(gadget, NULL);
}
#ifdef CONFIG_USB_CONFIGFS_UEVENT
static int android_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *c)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
unsigned long flags;
struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
int value = -EOPNOTSUPP;
struct usb_function_instance *fi;
spin_lock_irqsave(&cdev->lock, flags);
if (!gi->connected) {
gi->connected = 1;
schedule_work(&gi->work);
}
spin_unlock_irqrestore(&cdev->lock, flags);
list_for_each_entry(fi, &gi->available_func, cfs_list) {
if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) {
value = fi->f->setup(fi->f, c);
if (value >= 0)
break;
}
}
#ifdef CONFIG_USB_CONFIGFS_F_ACC
if (value < 0)
value = acc_ctrlrequest(cdev, c);
#endif
if (value < 0)
value = composite_setup(gadget, c);
spin_lock_irqsave(&cdev->lock, flags);
if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
cdev->config) {
schedule_work(&gi->work);
}
spin_unlock_irqrestore(&cdev->lock, flags);
return value;
}
static void android_disconnect(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
/* FIXME: There's a race between usb_gadget_udc_stop() which is likely
* to set the gadget driver to NULL in the udc driver and this drivers
* gadget disconnect fn which likely checks for the gadget driver to
* be a null ptr. It happens that unbind (doing set_gadget_data(NULL))
* is called before the gadget driver is set to NULL and the udc driver
* calls disconnect fn which results in cdev being a null ptr.
*/
if (cdev == NULL) {
WARN(1, "%s: gadget driver already disconnected\n", __func__);
return;
}
/* accessory HID support can be active while the
accessory function is not actually enabled,
so we need to inform it when we are disconnected.
*/
#ifdef CONFIG_USB_CONFIGFS_F_ACC
acc_disconnect();
#endif
gi->connected = 0;
schedule_work(&gi->work);
composite_disconnect(gadget);
}
#endif
static const struct usb_gadget_driver configfs_driver_template = {
.bind = configfs_composite_bind,
.unbind = configfs_composite_unbind,
#ifdef CONFIG_USB_CONFIGFS_UEVENT
.setup = android_setup,
.reset = android_disconnect,
.disconnect = android_disconnect,
#else
.setup = composite_setup,
.reset = composite_disconnect,
.disconnect = composite_disconnect,
#endif
.suspend = composite_suspend,
.resume = composite_resume,
@ -1410,6 +1572,89 @@ static const struct usb_gadget_driver configfs_driver_template = {
.match_existing_only = 1,
};
#ifdef CONFIG_USB_CONFIGFS_UEVENT
static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
char *buf)
{
struct gadget_info *dev = dev_get_drvdata(pdev);
struct usb_composite_dev *cdev;
char *state = "DISCONNECTED";
unsigned long flags;
if (!dev)
goto out;
cdev = &dev->cdev;
if (!cdev)
goto out;
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->config)
state = "CONFIGURED";
else if (dev->connected)
state = "CONNECTED";
spin_unlock_irqrestore(&cdev->lock, flags);
out:
return sprintf(buf, "%s\n", state);
}
static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
static struct device_attribute *android_usb_attributes[] = {
&dev_attr_state,
NULL
};
static int android_device_create(struct gadget_info *gi)
{
struct device_attribute **attrs;
struct device_attribute *attr;
INIT_WORK(&gi->work, android_work);
android_device = device_create(android_class, NULL,
MKDEV(0, 0), NULL, "android0");
if (IS_ERR(android_device))
return PTR_ERR(android_device);
dev_set_drvdata(android_device, gi);
attrs = android_usb_attributes;
while ((attr = *attrs++)) {
int err;
err = device_create_file(android_device, attr);
if (err) {
device_destroy(android_device->class,
android_device->devt);
return err;
}
}
return 0;
}
static void android_device_destroy(void)
{
struct device_attribute **attrs;
struct device_attribute *attr;
attrs = android_usb_attributes;
while ((attr = *attrs++))
device_remove_file(android_device, attr);
device_destroy(android_device->class, android_device->devt);
}
#else
static inline int android_device_create(struct gadget_info *gi)
{
return 0;
}
static inline void android_device_destroy(void)
{
}
#endif
static struct config_group *gadgets_make(
struct config_group *group,
const char *name)
@ -1461,7 +1706,11 @@ static struct config_group *gadgets_make(
if (!gi->composite.gadget_driver.function)
goto err;
if (android_device_create(gi) < 0)
goto err;
return &gi->group;
err:
kfree(gi);
return ERR_PTR(-ENOMEM);
@ -1470,6 +1719,7 @@ static struct config_group *gadgets_make(
static void gadgets_drop(struct config_group *group, struct config_item *item)
{
config_item_put(item);
android_device_destroy();
}
static struct configfs_group_operations gadgets_ops = {
@ -1509,6 +1759,13 @@ static int __init gadget_cfs_init(void)
config_group_init(&gadget_subsys.su_group);
ret = configfs_register_subsystem(&gadget_subsys);
#ifdef CONFIG_USB_CONFIGFS_UEVENT
android_class = class_create(THIS_MODULE, "android_usb");
if (IS_ERR(android_class))
return PTR_ERR(android_class);
#endif
return ret;
}
module_init(gadget_cfs_init);
@ -1516,5 +1773,10 @@ module_init(gadget_cfs_init);
static void __exit gadget_cfs_exit(void)
{
configfs_unregister_subsystem(&gadget_subsys);
#ifdef CONFIG_USB_CONFIGFS_UEVENT
if (!IS_ERR(android_class))
class_destroy(android_class);
#endif
}
module_exit(gadget_cfs_exit);

View file

@ -56,3 +56,7 @@ usb_f_cdev-y := f_cdev.o
obj-$(CONFIG_USB_F_CDEV) += usb_f_cdev.o
usb_f_ccid-y := f_ccid.o
obj-$(CONFIG_USB_F_CCID) += usb_f_ccid.o
usb_f_audio_source-y := f_audio_source.o
obj-$(CONFIG_USB_F_AUDIO_SRC) += usb_f_audio_source.o
usb_f_accessory-y := f_accessory.o
obj-$(CONFIG_USB_F_ACC) += usb_f_accessory.o

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1216,6 +1216,65 @@ static void f_midi_free_inst(struct usb_function_instance *f)
}
}
#ifdef CONFIG_USB_CONFIGFS_UEVENT
extern struct device *create_function_device(char *name);
static ssize_t alsa_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_function_instance *fi_midi = dev_get_drvdata(dev);
struct f_midi *midi;
if (!fi_midi->f)
dev_warn(dev, "f_midi: function not set\n");
if (fi_midi && fi_midi->f) {
midi = func_to_midi(fi_midi->f);
if (midi->rmidi && midi->rmidi->card)
return sprintf(buf, "%d %d\n",
midi->rmidi->card->number, midi->rmidi->device);
}
/* print PCM card and device numbers */
return sprintf(buf, "%d %d\n", -1, -1);
}
static DEVICE_ATTR(alsa, S_IRUGO, alsa_show, NULL);
static struct device_attribute *alsa_function_attributes[] = {
&dev_attr_alsa,
NULL
};
static int create_alsa_device(struct usb_function_instance *fi)
{
struct device *dev;
struct device_attribute **attrs;
struct device_attribute *attr;
int err = 0;
dev = create_function_device("f_midi");
if (IS_ERR(dev))
return PTR_ERR(dev);
attrs = alsa_function_attributes;
if (attrs) {
while ((attr = *attrs++) && !err)
err = device_create_file(dev, attr);
if (err) {
device_destroy(dev->class, dev->devt);
return -EINVAL;
}
}
dev_set_drvdata(dev, fi);
return 0;
}
#else
static int create_alsa_device(struct usb_function_instance *fi)
{
return 0;
}
#endif
static struct usb_function_instance *f_midi_alloc_inst(void)
{
struct f_midi_opts *opts;
@ -1234,6 +1293,11 @@ static struct usb_function_instance *f_midi_alloc_inst(void)
opts->out_ports = 1;
opts->refcnt = 1;
if (create_alsa_device(&opts->func_inst)) {
kfree(opts);
return ERR_PTR(-ENODEV);
}
config_group_init_type_name(&opts->func_inst.group, "",
&midi_func_type);
@ -1254,6 +1318,7 @@ static void f_midi_free(struct usb_function *f)
kfifo_free(&midi->in_req_fifo);
kfree(midi);
free = true;
opts->func_inst.f = NULL;
}
mutex_unlock(&opts->lock);
@ -1341,6 +1406,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
midi->func.disable = f_midi_disable;
midi->func.free_func = f_midi_free;
fi->f = &midi->func;
return &midi->func;
setup_fail:

View file

@ -234,6 +234,7 @@ source "fs/orangefs/Kconfig"
source "fs/adfs/Kconfig"
source "fs/affs/Kconfig"
source "fs/ecryptfs/Kconfig"
source "fs/sdcardfs/Kconfig"
source "fs/hfs/Kconfig"
source "fs/hfsplus/Kconfig"
source "fs/befs/Kconfig"

View file

@ -4,7 +4,7 @@
#
# 14 Sep 2000, Christoph Hellwig <hch@infradead.org>
# Rewritten to use lists instead of if-statements.
#
#
obj-y := open.o read_write.o file_table.o super.o \
char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
@ -62,7 +62,7 @@ obj-y += devpts/
obj-$(CONFIG_PROFILING) += dcookies.o
obj-$(CONFIG_DLM) += dlm/
# Do not add any filesystems before this line
obj-$(CONFIG_FSCACHE) += fscache/
obj-$(CONFIG_REISERFS_FS) += reiserfs/
@ -84,6 +84,7 @@ obj-$(CONFIG_ISO9660_FS) += isofs/
obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
obj-$(CONFIG_HFS_FS) += hfs/
obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
obj-$(CONFIG_SDCARD_FS) += sdcardfs/
obj-$(CONFIG_VXFS_FS) += freevxfs/
obj-$(CONFIG_NFS_FS) += nfs/
obj-$(CONFIG_EXPORTFS) += exportfs/

View file

@ -260,12 +260,11 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de
/*
* read page from file, directory or symlink, given a key to use
*/
int afs_page_filler(void *data, struct page *page)
static int __afs_page_filler(struct key *key, struct page *page)
{
struct inode *inode = page->mapping->host;
struct afs_vnode *vnode = AFS_FS_I(inode);
struct afs_read *req;
struct key *key = data;
int ret;
_enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index);
@ -372,6 +371,13 @@ int afs_page_filler(void *data, struct page *page)
return ret;
}
int afs_page_filler(struct file *data, struct page *page)
{
struct key *key = (struct key *)data;
return __afs_page_filler(key, page);
}
/*
* read page from file, directory or symlink, given a file to nominate the key
* to be used
@ -384,14 +390,14 @@ static int afs_readpage(struct file *file, struct page *page)
if (file) {
key = afs_file_key(file);
ASSERT(key != NULL);
ret = afs_page_filler(key, page);
ret = __afs_page_filler(key, page);
} else {
struct inode *inode = page->mapping->host;
key = afs_request_key(AFS_FS_S(inode->i_sb)->cell);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
} else {
ret = afs_page_filler(key, page);
ret = __afs_page_filler(key, page);
key_put(key);
}
}

View file

@ -752,7 +752,7 @@ extern void afs_put_wb_key(struct afs_wb_key *);
extern int afs_open(struct inode *, struct file *);
extern int afs_release(struct inode *, struct file *);
extern int afs_fetch_data(struct afs_vnode *, struct key *, struct afs_read *);
extern int afs_page_filler(void *, struct page *);
extern int afs_page_filler(struct file *, struct page *);
extern void afs_put_read(struct afs_read *);
/*

View file

@ -223,7 +223,7 @@ EXPORT_SYMBOL(setattr_copy);
* the file open for write, as there can be no conflicting delegation in
* that case.
*/
int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
{
struct inode *inode = dentry->d_inode;
umode_t mode = inode->i_mode;
@ -247,7 +247,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
return -EPERM;
if (!inode_owner_or_capable(inode)) {
error = inode_permission(inode, MAY_WRITE);
error = inode_permission2(mnt, inode, MAY_WRITE);
if (error)
return error;
}
@ -330,7 +330,9 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
if (error)
return error;
if (inode->i_op->setattr)
if (mnt && inode->i_op->setattr2)
error = inode->i_op->setattr2(mnt, dentry, attr);
else if (inode->i_op->setattr)
error = inode->i_op->setattr(dentry, attr);
else
error = simple_setattr(dentry, attr);
@ -343,4 +345,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
return error;
}
EXPORT_SYMBOL(notify_change2);
int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
{
return notify_change2(NULL, dentry, attr, delegated_inode);
}
EXPORT_SYMBOL(notify_change);

View file

@ -742,7 +742,7 @@ void do_coredump(const siginfo_t *siginfo)
goto close_fail;
if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
goto close_fail;
if (do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file))
if (do_truncate2(cprm.file->f_path.mnt, cprm.file->f_path.dentry, 0, 0, cprm.file))
goto close_fail;
}

View file

@ -204,6 +204,7 @@ char *d_absolute_path(const struct path *path,
return ERR_PTR(error);
return res;
}
EXPORT_SYMBOL(d_absolute_path);
/*
* same as __d_path but appends "(deleted)" for unlinked files.

View file

@ -34,6 +34,7 @@
#include <linux/mutex.h>
#include <linux/anon_inodes.h>
#include <linux/device.h>
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/mman.h>
@ -1816,7 +1817,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
}
spin_unlock_irq(&ep->wq.lock);
if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
if (!freezable_schedule_hrtimeout_range(to, slack,
HRTIMER_MODE_ABS))
timed_out = 1;
spin_lock_irq(&ep->wq.lock);

View file

@ -1308,7 +1308,7 @@ EXPORT_SYMBOL(flush_old_exec);
void would_dump(struct linux_binprm *bprm, struct file *file)
{
struct inode *inode = file_inode(file);
if (inode_permission(inode, MAY_READ) < 0) {
if (inode_permission2(file->f_path.mnt, inode, MAY_READ) < 0) {
struct user_namespace *old, *user_ns;
bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;

View file

@ -377,9 +377,8 @@ static int read_exec(struct page_collect *pcol)
* and will start a new collection. Eventually caller must submit the last
* segment if present.
*/
static int readpage_strip(void *data, struct page *page)
static int __readpage_strip(struct page_collect *pcol, struct page *page)
{
struct page_collect *pcol = data;
struct inode *inode = pcol->inode;
struct exofs_i_info *oi = exofs_i(inode);
loff_t i_size = i_size_read(inode);
@ -470,6 +469,13 @@ static int readpage_strip(void *data, struct page *page)
return ret;
}
static int readpage_strip(struct file *data, struct page *page)
{
struct page_collect *pcol = (struct page_collect *)data;
return __readpage_strip(pcol, page);
}
static int exofs_readpages(struct file *file, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages)
{
@ -499,7 +505,7 @@ static int _readpage(struct page *page, bool read_4_write)
_pcol_init(&pcol, 1, page->mapping->host);
pcol.read_4_write = read_4_write;
ret = readpage_strip(&pcol, page);
ret = __readpage_strip(&pcol, page);
if (ret) {
EXOFS_ERR("_readpage => %d\n", ret);
return ret;

View file

@ -12,6 +12,7 @@
#include "ext4.h"
#include "xattr.h"
#include "truncate.h"
#include <trace/events/android_fs.h>
#define EXT4_XATTR_SYSTEM_DATA "data"
#define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS))
@ -505,6 +506,17 @@ int ext4_readpage_inline(struct inode *inode, struct page *page)
return -EAGAIN;
}
if (trace_android_fs_dataread_start_enabled()) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
inode);
trace_android_fs_dataread_start(inode, page_offset(page),
PAGE_SIZE, current->pid,
path, current->comm);
}
/*
* Current inline data can only exist in the 1st page,
* So for all the other pages, just set them uptodate.
@ -516,6 +528,8 @@ int ext4_readpage_inline(struct inode *inode, struct page *page)
SetPageUptodate(page);
}
trace_android_fs_dataread_end(inode, page_offset(page), PAGE_SIZE);
up_read(&EXT4_I(inode)->xattr_sem);
unlock_page(page);

View file

@ -47,6 +47,7 @@
#include "truncate.h"
#include <trace/events/ext4.h>
#include <trace/events/android_fs.h>
#define MPAGE_DA_EXTENT_TAIL 0x01
@ -1253,6 +1254,16 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
return -EIO;
if (trace_android_fs_datawrite_start_enabled()) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
inode);
trace_android_fs_datawrite_start(inode, pos, len,
current->pid, path,
current->comm);
}
trace_ext4_write_begin(inode, pos, len, flags);
/*
* Reserve one block more for addition to orphan list in case
@ -1391,6 +1402,7 @@ static int ext4_write_end(struct file *file,
int i_size_changed = 0;
int inline_data = ext4_has_inline_data(inode);
trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_write_end(inode, pos, len, copied);
if (inline_data) {
ret = ext4_write_inline_data_end(inode, pos, len,
@ -1496,6 +1508,7 @@ static int ext4_journalled_write_end(struct file *file,
int size_changed = 0;
int inline_data = ext4_has_inline_data(inode);
trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_journalled_write_end(inode, pos, len, copied);
from = pos & (PAGE_SIZE - 1);
to = from + len;
@ -3024,6 +3037,16 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
len, flags, pagep, fsdata);
}
*fsdata = (void *)0;
if (trace_android_fs_datawrite_start_enabled()) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
inode);
trace_android_fs_datawrite_start(inode, pos, len,
current->pid,
path, current->comm);
}
trace_ext4_da_write_begin(inode, pos, len, flags);
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@ -3142,6 +3165,7 @@ static int ext4_da_write_end(struct file *file,
return ext4_write_end(file, mapping, pos,
len, copied, page, fsdata);
trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_da_write_end(inode, pos, len, copied);
start = pos & (PAGE_SIZE - 1);
end = start + copied - 1;
@ -3843,6 +3867,7 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
size_t count = iov_iter_count(iter);
loff_t offset = iocb->ki_pos;
ssize_t ret;
int rw = iov_iter_rw(iter);
#ifdef CONFIG_EXT4_FS_ENCRYPTION
if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
@ -3859,12 +3884,42 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
if (ext4_has_inline_data(inode))
return 0;
if (trace_android_fs_dataread_start_enabled() &&
(rw == READ)) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
inode);
trace_android_fs_dataread_start(inode, offset, count,
current->pid, path,
current->comm);
}
if (trace_android_fs_datawrite_start_enabled() &&
(rw == WRITE)) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
inode);
trace_android_fs_datawrite_start(inode, offset, count,
current->pid, path,
current->comm);
}
trace_ext4_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
if (iov_iter_rw(iter) == READ)
ret = ext4_direct_IO_read(iocb, iter);
else
ret = ext4_direct_IO_write(iocb, iter);
trace_ext4_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), ret);
if (trace_android_fs_dataread_start_enabled() &&
(rw == READ))
trace_android_fs_dataread_end(inode, offset, count);
if (trace_android_fs_datawrite_start_enabled() &&
(rw == WRITE))
trace_android_fs_datawrite_end(inode, offset, count);
return ret;
}

View file

@ -46,6 +46,7 @@
#include <linux/cleancache.h>
#include "ext4.h"
#include <trace/events/android_fs.h>
static inline bool ext4_bio_encrypted(struct bio *bio)
{
@ -56,6 +57,17 @@ static inline bool ext4_bio_encrypted(struct bio *bio)
#endif
}
static void
ext4_trace_read_completion(struct bio *bio)
{
struct page *first_page = bio->bi_io_vec[0].bv_page;
if (first_page != NULL)
trace_android_fs_dataread_end(first_page->mapping->host,
page_offset(first_page),
bio->bi_iter.bi_size);
}
/*
* I/O completion handler for multipage BIOs.
*
@ -73,6 +85,9 @@ static void mpage_end_io(struct bio *bio)
struct bio_vec *bv;
int i;
if (trace_android_fs_dataread_start_enabled())
ext4_trace_read_completion(bio);
if (ext4_bio_encrypted(bio)) {
if (bio->bi_status) {
fscrypt_release_ctx(bio->bi_private);
@ -96,6 +111,30 @@ static void mpage_end_io(struct bio *bio)
bio_put(bio);
}
static void
ext4_submit_bio_read(struct bio *bio)
{
if (trace_android_fs_dataread_start_enabled()) {
struct page *first_page = bio->bi_io_vec[0].bv_page;
if (first_page != NULL) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
first_page->mapping->host);
trace_android_fs_dataread_start(
first_page->mapping->host,
page_offset(first_page),
bio->bi_iter.bi_size,
current->pid,
path,
current->comm);
}
}
submit_bio(bio);
}
int ext4_mpage_readpages(struct address_space *mapping,
struct list_head *pages, struct page *page,
unsigned nr_pages, bool is_readahead)
@ -236,7 +275,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
*/
if (bio && (last_block_in_bio != blocks[0] - 1)) {
submit_and_realloc:
submit_bio(bio);
ext4_submit_bio_read(bio);
bio = NULL;
}
if (bio == NULL) {
@ -270,14 +309,14 @@ int ext4_mpage_readpages(struct address_space *mapping,
if (((map.m_flags & EXT4_MAP_BOUNDARY) &&
(relative_block == map.m_len)) ||
(first_hole != blocks_per_page)) {
submit_bio(bio);
ext4_submit_bio_read(bio);
bio = NULL;
} else
last_block_in_bio = blocks[blocks_per_page - 1];
goto next_page;
confused:
if (bio) {
submit_bio(bio);
ext4_submit_bio_read(bio);
bio = NULL;
}
if (!PageUptodate(page))
@ -290,6 +329,6 @@ int ext4_mpage_readpages(struct address_space *mapping,
}
BUG_ON(pages && !list_empty(pages));
if (bio)
submit_bio(bio);
ext4_submit_bio_read(bio);
return 0;
}

View file

@ -27,6 +27,7 @@
#include "segment.h"
#include "trace.h"
#include <trace/events/f2fs.h>
#include <trace/events/android_fs.h>
#define NUM_PREALLOC_POST_READ_CTXS 128
@ -2330,6 +2331,16 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
block_t blkaddr = NULL_ADDR;
int err = 0;
if (trace_android_fs_datawrite_start_enabled()) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
inode);
trace_android_fs_datawrite_start(inode, pos, len,
current->pid, path,
current->comm);
}
trace_f2fs_write_begin(inode, pos, len, flags);
if ((f2fs_is_atomic_file(inode) &&
@ -2429,6 +2440,7 @@ static int f2fs_write_end(struct file *file,
{
struct inode *inode = page->mapping->host;
trace_android_fs_datawrite_end(inode, pos, len);
trace_f2fs_write_end(inode, pos, len, copied);
/*
@ -2496,6 +2508,29 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
trace_f2fs_direct_IO_enter(inode, offset, count, rw);
if (trace_android_fs_dataread_start_enabled() &&
(rw == READ)) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
inode);
trace_android_fs_dataread_start(inode, offset,
count, current->pid, path,
current->comm);
}
if (trace_android_fs_datawrite_start_enabled() &&
(rw == WRITE)) {
char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
path = android_fstrace_get_pathname(pathbuf,
MAX_TRACE_PATHBUF_LEN,
inode);
trace_android_fs_datawrite_start(inode, offset, count,
current->pid, path,
current->comm);
}
if (rw == WRITE && whint_mode == WHINT_MODE_OFF)
iocb->ki_hint = WRITE_LIFE_NOT_SET;
@ -2524,6 +2559,13 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
}
out:
if (trace_android_fs_dataread_start_enabled() &&
(rw == READ))
trace_android_fs_dataread_end(inode, offset, count);
if (trace_android_fs_datawrite_start_enabled() &&
(rw == WRITE))
trace_android_fs_datawrite_end(inode, offset, count);
trace_f2fs_direct_IO_exit(inode, offset, count, rw, err);
return err;

Some files were not shown because too many files have changed in this diff Show more