概述
-
一般user版本会关闭该功能,
因为当机器在用户手中发生死机时,机器会进入dump模式后一直处于黑屏状态,
此时,用户会不知所措,如果不能恢复正常,则会有极差的用户体验。
所以需要关闭该功能,让系统死机后直接进入reboot。 -
对于调试版本来说,
有些死机问题比较special,userdebug 版本不一定能复现问题,只有user版本才会复现,
所以此时开启该功能,则能让工程师通过dump log继续分析死机问题。
代码修改如下:
kenrel/msm-3.18/arch/arm64/configs/perf_defconfg
开启emergency_download_mode
CONFIG_MSM_DLOAD_MODE=y
关闭emergency_download_mode
# CONFIG_MSM_DLOAD_MODE is not set
原理如下:
因为时间问题,目前先把点贴上,后续抽时间再详细说明代码。
/kernel/msm-3.18/drivers/power/reset/msm-poweroff.c
#ifdef CONFIG_MSM_DLOAD_MODE
/* Runtime could be only changed value once.
* There is no API from TZ to re-enable the registers.
* So the SDI cannot be re-enabled when it already by-passed.
*/
static int download_mode = 1;
#else
static const int download_mode;
#endif
#ifdef CONFIG_MSM_DLOAD_MODE
#define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
#define DL_MODE_PROP "qcom,msm-imem-download_mode"
static int in_panic;
static void *dload_mode_addr;
static bool dload_mode_enabled;
static void *emergency_dload_mode_addr;
static bool scm_dload_supported;
static struct kobject dload_kobj;
static void *dload_type_addr;
static int dload_set(const char *val, struct kernel_param *kp);
/* interface for exporting attributes */
struct reset_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
char *buf);
size_t (*store)(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count);
};
#define to_reset_attr(_attr)
container_of(_attr, struct reset_attribute, attr)
#define RESET_ATTR(_name, _mode, _show, _store)
static struct reset_attribute reset_attr_##_name =
__ATTR(_name, _mode, _show, _store)
module_param_call(download_mode, dload_set, param_get_int,
&download_mode, 0644);
static int panic_prep_restart(struct notifier_block *this,
unsigned long event, void *ptr)
{
in_panic = 1;
return NOTIFY_DONE;
}
static struct notifier_block panic_blk = {
.notifier_call = panic_prep_restart,
};
int scm_set_dload_mode(int arg1, int arg2)
{
struct scm_desc desc = {
.args[0] = arg1,
.args[1] = arg2,
.arginfo = SCM_ARGS(2),
};
if (!scm_dload_supported) {
if (tcsr_boot_misc_detect)
return scm_io_write(tcsr_boot_misc_detect, arg1);
return 0;
}
if (!is_scm_armv8())
return scm_call_atomic2(SCM_SVC_BOOT, SCM_DLOAD_CMD, arg1,
arg2);
return scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, SCM_DLOAD_CMD),
&desc);
}
static void set_dload_mode(int on)
{
int ret;
if (dload_mode_addr) {
__raw_writel(on ? 0xE47B337D : 0, dload_mode_addr);
__raw_writel(on ? 0xCE14091A : 0,
dload_mode_addr + sizeof(unsigned int));
mb();
}
ret = scm_set_dload_mode(on ? SCM_DLOAD_MODE : 0, 0);
if (ret)
pr_err("Failed to set secure DLOAD mode: %dn", ret);
dload_mode_enabled = on;
}
static bool get_dload_mode(void)
{
return dload_mode_enabled;
}
static void enable_emergency_dload_mode(void)
{
int ret;
if (emergency_dload_mode_addr) {
__raw_writel(EMERGENCY_DLOAD_MAGIC1,
emergency_dload_mode_addr);
__raw_writel(EMERGENCY_DLOAD_MAGIC2,
emergency_dload_mode_addr +
sizeof(unsigned int));
__raw_writel(EMERGENCY_DLOAD_MAGIC3,
emergency_dload_mode_addr +
(2 * sizeof(unsigned int)));
/* Need disable the pmic wdt, then the emergency dload mode
* will not auto reset. */
qpnp_pon_wd_config(0);
mb();
}
ret = scm_set_dload_mode(SCM_EDLOAD_MODE, 0);
if (ret)
pr_err("Failed to set secure EDLOAD mode: %dn", ret);
}
static int dload_set(const char *val, struct kernel_param *kp)
{
int ret;
int old_val = download_mode;
ret = param_set_int(val, kp);
if (ret)
return ret;
/* If download_mode is not zero or one, ignore. */
if (download_mode >> 1) {
download_mode = old_val;
return -EINVAL;
}
set_dload_mode(download_mode);
return 0;
}
#else
static void set_dload_mode(int on)
{
return;
}
static void enable_emergency_dload_mode(void)
{
pr_err("dload mode is not enabled on targetn");
}
static bool get_dload_mode(void)
{
return false;
}
#endif
static void msm_restart_prepare(const char *cmd)
{
bool need_warm_reset = false;
#ifdef CONFIG_MSM_DLOAD_MODE
/* Write download mode flags if we're panic'ing
* Write download mode flags if restart_mode says so
* Kill download mode if master-kill switch is set
*/
set_dload_mode(download_mode &&
(in_panic || restart_mode == RESTART_DLOAD));
#endif
if (qpnp_pon_check_hard_reset_stored()) {
/* Set warm reset as true when device is in dload mode */
if (get_dload_mode() ||
((cmd != NULL && cmd[0] != '