blob: 7e3e7da6e8d1b87246b256e58972005076e2c941 [file] [log] [blame]
#!/bin/sh
# Copyright 2016 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
JOB=$(basename "$0")
DEVICE_SHUTTING_DOWN=4 # Defined in session_manager_service.h
# Check if file exists and is writeable by us. -w is always true under root.
is_writeable() {
local file="$1"
local v=0
if [ -f "${file}" ]; then
local wfile
wfile=$(find "${file}" -maxdepth 1 | awk '$1 ~ /^.*w.*/ { print $NF; }')
if [ -n "${wfile}" ]; then
v=1
fi
fi
echo "${v}"
}
# Read chrome OS configurations
read_cros_config() {
local path="$1"
local key="$2"
local def="$3"
# cros_config exits with non-zero when a key isn't existed,
cros_config "${path}" "${key}" || echo "${def}"
}
read_cros_config_int() {
local v
v=$(read_cros_config "$@")
# config value should be an integer
case "${v}" in
''|*[!0-9]*)
logger -t "${JOB}" -p warn \
"cros_config ${path}/${key} is not an integer! "\
"Let me use ${def} instead of ${v}."
echo "${def}"
;;
*)
echo "${v}"
;;
esac
}
# The ui job can be restarted asynchronously via ui-respawn. This allows the
# possibility that ui can be started while shutdown/reboot is in process.
# Make sure that the reboot/halt jobs are not active at the time we are
# restarting ui.
if ! initctl status reboot | grep -q 'stop/waiting' || \
! initctl status halt | grep -q 'stop/waiting'; then
logger -t "${UPSTART_JOB:-}" "ERROR: reboot/shutdown in progress, quit."
stop ui
exit "${DEVICE_SHUTTING_DOWN}"
fi
# Setup drm log tracing if available. This will allow us to access more verbose
# logs to debug display connectivity issues when they arise. The traces are
# accessible via chrome://system and included in feedback/crash reports.
#
# As configured, we won't have a lot of volume in these traces, they will only
# be written in cases where the display configuration changes, or an error
# occurs. As such, there is no performance impact during steady-state operation.
#
# TODO(seanpaul): Once we've finished moving over to the upstream tracefs
# implementation, remove the block initializing the downstream
# debugfs code. Tracked in b/163580546.
DRM_TRACE_DIR="/sys/kernel/debug/dri"
DRM_TRACE_MASK="${DRM_TRACE_DIR}/trace_mask"
if [ -w "${DRM_TRACE_MASK}" ]; then
# 64kB per-cpu of drm logs.
echo 64 > "${DRM_TRACE_DIR}/trace_size_kb"
# 0x106 corresponds to (DRM_UT_DRIVER | DRM_UT_KMS | DRM_UT_DP).
echo 0x106 > "${DRM_TRACE_MASK}"
fi
DRM_TRACEFS_INSTANCE="/sys/kernel/tracing/instances/drm"
DRM_TRACEFS_BUF_SIZE="${DRM_TRACEFS_INSTANCE}/buffer_size_kb"
if [ -w "${DRM_TRACEFS_BUF_SIZE}" ]; then
# 64kB per-cpu of drm logs.
echo 64 > "${DRM_TRACEFS_BUF_SIZE}"
fi
mkdir -p "${UI_LOG_DIR:-}"
ln -sf ui."$(date --utc +%Y%m%d-%H%M%S)" "${UI_LOG_DIR}/${UI_LOG_FILE:-}"
mkdir -p "${CONTAINER_ROOT_DIR:-}"
# Create a top-level cpu cgroup for ui tasks. This will be used to share cpu
# resources with tasks not managed by the UI. Android will be placed in a
# parallel cgroup allowing priority to be given to one or the other depending
# on what the user is doing at the time.
if [ ! -d "${UI_CPU_CGROUP_DIR:-}" ]; then
mkdir -p "${UI_CPU_CGROUP_DIR}"
fi
# Set up cgroups for chrome. We create two task groups, one for at most one
# foreground renderer and one for all the background renderers and set the
# background group to a very low priority. We specifically do not set it to
# the lowest "2" such that other processes like the update-engine can be even
# lower. The default value is 1024.
CHROME_CPU_CGROUP_DIR=/sys/fs/cgroup/cpu/chrome_renderers
if [ ! -d "${CHROME_CPU_CGROUP_DIR}" ]; then
mkdir -p "${CHROME_CPU_CGROUP_DIR}/foreground"
mkdir -p "${CHROME_CPU_CGROUP_DIR}/background"
echo "10" > "${CHROME_CPU_CGROUP_DIR}/background/cpu.shares"
chown -R chronos "${CHROME_CPU_CGROUP_DIR}"
fi
# TODO(ikjn): This scheduler settings are a bit complex,
# Let's move these out to an another executable (c++).
# Tracked in b/182958867
# apply ui and chrome foreground cgroup's uclamp.min, default 20%,
v=$(read_cros_config_int "/scheduler-tune" "boost-urgent" "20")
for knob in "${UI_CPU_CGROUP_DIR}/cpu.uclamp.min" \
"${CHROME_CPU_CGROUP_DIR}/cpu.uclamp.min" \
"${CHROME_CPU_CGROUP_DIR}/foreground/cpu.uclamp.min"; do
if [ -f "${knob}" ]; then
echo "${v}" > "${knob}"
fi
done
# Apply boosting values for platforms using schedtune
SCHEDTUNE_BOOST_DIR=/sys/fs/cgroup/schedtune/chrome/urgent
if [ -d "${SCHEDTUNE_BOOST_DIR}" ]; then
echo "${v}" > "${SCHEDTUNE_BOOST_DIR}/schedtune.boost"
echo "1" > "${SCHEDTUNE_BOOST_DIR}/schedtune.prefer_idle"
fi
# Apply Input boosting
INPUT_BOOST=/sys/module/cpu_boost/parameters/input_boost_freq_percent
INPUT_BOOST_DEFAULT=0
CPUFREQ_CONF=/etc/cpufreq.conf
if [ -f "${INPUT_BOOST}" ]; then
# Default value is 75 for platforms using EAS
if [ -f "${CPUFREQ_CONF}" ]; then
# shellcheck source=/dev/null
. "${CPUFREQ_CONF}"
if [ "${CPUFREQ_GOVERNOR:-}" = "schedutil" ] || \
[ "${CPUFREQ_GOVERNOR}" = "sched" ]; then
INPUT_BOOST_DEFAULT=75
fi
fi
read_cros_config_int "/scheduler-tune" "input-boost" \
"${INPUT_BOOST_DEFAULT}" > "${INPUT_BOOST}"
fi
# Limit non-urgent tasks to small cores
CPUBUSDIR=/sys/bus/cpu/devices
CPUSET_NONURGENT_DIR=/sys/fs/cgroup/cpuset/chrome/non-urgent
if [ -d "${CPUSET_NONURGENT_DIR}" ]; then
v=$(read_cros_config "/scheduler-tune" "cpuset-nonurgent" "")
# If a cpuset-nonurgent isn't specified in cros_config,
# use all little cores as a non-urgent cpuset.
if [ -z "${v}" ] && grep -q '^big_little$' /etc/ui_use_flags.txt; then
nr_cpus=0
nr_small_cpus=0
min_cap=1025
if [ -f "${CPUBUSDIR}/cpu0/cpufreq/cpuinfo_max_freq" ]; then
min_maxfreq=$(cat "${CPUBUSDIR}/cpu0/cpufreq/cpuinfo_max_freq")
fi
cpus=""
prefix="${CPUBUSDIR}/cpu"
for cpu in "${CPUBUSDIR}"/cpu*; do
if [ -f "${cpu}/cpu_capacity" ]; then
cap=$(cat "${cpu}/cpu_capacity")
if [ "${cap}" -lt "${min_cap}" ]; then
cpus="${cpu##${prefix}}"
min_cap="${cap}"
nr_small_cpus=1
elif [ "${cap}" -eq "${min_cap}" ]; then
cpus="${cpus},${cpu##${prefix}}"
nr_small_cpus=$((nr_small_cpus + 1))
fi
elif [ -f "${cpu}/cpufreq/cpuinfo_max_freq" ]; then
maxfreq=$(cat "${cpu}/cpufreq/cpuinfo_max_freq")
if [ "${maxfreq}" -lt "${min_maxfreq}" ]; then
cpus="${cpu##${prefix}}"
min_maxfreq="${maxfreq}"
nr_small_cpus=1
elif [ "${maxfreq}" -eq "${min_maxfreq}" ]; then
cpus="${cpus},${cpu##${prefix}}"
nr_small_cpus=$((nr_small_cpus + 1))
fi
else
cpus=""
break;
fi
nr_cpus=$((nr_cpus + 1))
done
if [ "${nr_small_cpus}" -lt "${nr_cpus}" ]; then
v="${cpus}"
fi
fi
if [ -n "${v}" ]; then
echo "${v}" > "${CPUSET_NONURGENT_DIR}/cpus"
fi
fi
# Set up a folder on the stateful partition for ephemeral encrypted swap
# files.
USERSPACE_SWAP_DIR=/mnt/stateful_partition/unencrypted/userspace_swap.tmp/
if [ ! -d "${USERSPACE_SWAP_DIR}" ]; then
mkdir -p "${USERSPACE_SWAP_DIR}"
chown -R chronos "${USERSPACE_SWAP_DIR}"
fi
# Set up the ui freezer cgroup. This is used during suspend to order the
# freezing of processes to avoid FUSE causing freeze to timeout.
if [ ! -d "${UI_FREEZER_CGROUP_DIR:-}" ]; then
mkdir -p "${UI_FREEZER_CGROUP_DIR}"
chown -R chronos "${UI_FREEZER_CGROUP_DIR}"
chown power:power "${UI_FREEZER_CGROUP_DIR}"/freezer.state
fi
# Set up the renderer freezer. This is used during the suspend/resume cycle
# to freeze all the chrome renderers so that they don't take up a lot of power
# when the system comes up in dark resume
if [ ! -d "${CHROME_FREEZER_CGROUP_DIR:-}" ]; then
mkdir -p "${CHROME_FREEZER_CGROUP_DIR}"
mkdir -p "${CHROME_FREEZER_CGROUP_DIR}/to_be_frozen"
chown -R chronos "${CHROME_FREEZER_CGROUP_DIR}"
fi
# Set up a cgroup for containers(Android) started by session manager. To
# start, limit the cpu shares of Android. This will be reset to the default
# once the user clicks on an Android app. Keeping the usage low prevents
# Android boot from slowing the login process.
CONTAINER_CGROUP_DIR=/sys/fs/cgroup/cpu/session_manager_containers
if [ -d "${CONTAINER_CGROUP_DIR}" ]; then
echo "32" > "${CONTAINER_CGROUP_DIR}/cpu.shares"
echo "-1" > "${CONTAINER_CGROUP_DIR}/cpu.cfs_quota_us"
if [ -f "${CONTAINER_CGROUP_DIR}/cpu.uclamp.min" ]; then
echo "100" > "${CONTAINER_CGROUP_DIR}/cpu.uclamp.min"
fi
fi
# Enable madvise(MADV_HUGEPAGE) for VMs guest mappings
if [ -f "/sys/kernel/mm/transparent_hugepage/shmem_enabled" ]; then
echo "advise" > "/sys/kernel/mm/transparent_hugepage/shmem_enabled"
fi
# Tweak KVM HLT polling only for x86
if uname -m | grep -q x86; then
HALT_POLL_NS_SHRINK=/sys/module/kvm/parameters/halt_poll_ns_shrink
HALT_POLL_NS=/sys/module/kvm/parameters/halt_poll_ns
# Older kernels (e.g. 4.4) do not permit dynamic halt_poll_ns_shrink and
# have this attr as read-only.
v=$(is_writeable "${HALT_POLL_NS_SHRINK}")
if [ "${v}" != "0" ]; then
echo 2 > "${HALT_POLL_NS_SHRINK}"
fi
# Ditto, just in case
v=$(is_writeable "${HALT_POLL_NS}")
if [ "${v}" != "0" ]; then
echo 160000 > "${HALT_POLL_NS}"
fi
fi
if crossystem "cros_debug?1"; then
# Set up the alt-syscall kernel module (on systems with kernel 3.14 or later)
# to allow developer mode only system calls to be exposed to Android
# containers (and potentially other containers) when the system is in
# developer mode.
DEVMODE_SYSCALL=/proc/sys/kernel/chromiumos/alt_syscall/allow_devmode_syscalls
if [ -e "${DEVMODE_SYSCALL}" ]; then
echo "1" > "${DEVMODE_SYSCALL}"
fi
# /proc/sys/kernel/perf_event_paranoid controls the use of kernel perf events
# system by users without the CAP_SYS_ADMIN capability (see
# kernel/Documentation/sysctl/kernel.txt for details). On systems with kernel
# 3.14 or later, we enable CONFIG_SECURITY_PERF_EVENTS_RESTRICT in kernel,
# which sets the default value of perf_event_paranoid to a more restrictive
# level "3", instead of "1". As alt-syscall exposes perf_event_open() to
# Android containers when the system is in developer mode, restore
# perf_event_paranoid to the less restrictive level "1".
PERF_EVENT_PARANOID=/proc/sys/kernel/perf_event_paranoid
if [ -e "${PERF_EVENT_PARANOID}" ]; then
echo "1" > "${PERF_EVENT_PARANOID}"
fi
fi
# Set up the lucid sleep debug flag. This file only exists on devices that
# use kernel 3.14. When this sysfs entry is set to 1, the kernel will treat
# all resumes as dark resumes, relying on chrome and powerd to detect any user
# activity and to transition out of dark resume into regular resume. Since we
# are currently unable to distinguish the source that woke up the system, this
# is a temporary workaround to allow for apps and extensions to test lucid
# sleep functionality. Chrome will write 1 to this file only if the
# wake-on-packets flag is set.
#
# TODO(chirantan): Remove this once the firmware change and corresponding
# kernel change for querying the wakeup source is ready (crbug.com/414949).
DARK_RESUME_ALWAYS_FILE=/sys/power/dark_resume_always
if [ -e "${DARK_RESUME_ALWAYS_FILE}" ]; then
chown chronos "${DARK_RESUME_ALWAYS_FILE}"
fi