Merge branch 'linaro-fixes/android-3.10' into linaro-android-3.10-lsk

This commit is contained in:
John Stultz 2014-05-09 15:16:56 -07:00
commit ff22184ab6
35 changed files with 1200 additions and 483 deletions

View File

@ -21,49 +21,3 @@ config SHARP_SCOOP
config FIQ_GLUE
bool
select FIQ
config FIQ_DEBUGGER
bool "FIQ Mode Serial Debugger"
select FIQ
select FIQ_GLUE
default n
help
The FIQ serial debugger can accept commands even when the
kernel is unresponsive due to being stuck with interrupts
disabled.
config FIQ_DEBUGGER_NO_SLEEP
bool "Keep serial debugger active"
depends on FIQ_DEBUGGER
default n
help
Enables the serial debugger at boot. Passing
fiq_debugger.no_sleep on the kernel commandline will
override this config option.
config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
bool "Don't disable wakeup IRQ when debugger is active"
depends on FIQ_DEBUGGER
default n
help
Don't disable the wakeup irq when enabling the uart clock. This will
cause extra interrupts, but it makes the serial debugger usable with
on some MSM radio builds that ignore the uart clock request in power
collapse.
config FIQ_DEBUGGER_CONSOLE
bool "Console on FIQ Serial Debugger port"
depends on FIQ_DEBUGGER
default n
help
Enables a console so that printk messages are displayed on
the debugger serial port as the occur.
config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
bool "Put the FIQ debugger into console mode by default"
depends on FIQ_DEBUGGER_CONSOLE
default n
help
If enabled, this puts the fiq debugger into console mode by default.
Otherwise, the fiq debugger will start out in debug mode.

View File

@ -4,7 +4,6 @@
obj-y += firmware.o
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger.o
obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o
obj-$(CONFIG_ICST) += icst.o
obj-$(CONFIG_SA1111) += sa1111.o

View File

@ -768,6 +768,8 @@ static const char *keys[KEY_MAX + 1] = {
[KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel",
[KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
[KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown",
[BTN_DPAD_UP] = "BtnDPadUp", [BTN_DPAD_DOWN] = "BtnDPadDown",
[BTN_DPAD_LEFT] = "BtnDPadLeft", [BTN_DPAD_RIGHT] = "BtnDPadRight",
[BTN_0] = "Btn0", [BTN_1] = "Btn1",
[BTN_2] = "Btn2", [BTN_3] = "Btn3",
[BTN_4] = "Btn4", [BTN_5] = "Btn5",
@ -797,7 +799,8 @@ static const char *keys[KEY_MAX + 1] = {
[BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
[BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
[BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
[BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
[BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_TOOL_QUADTAP] = "ToolQuadrupleTap",
[BTN_GEAR_DOWN] = "WheelBtn",
[BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
[KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
[KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
@ -852,6 +855,16 @@ static const char *keys[KEY_MAX + 1] = {
[KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
[KEY_KBDILLUMUP] = "KbdIlluminationUp",
[KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
[KEY_BUTTONCONFIG] = "ButtonConfig",
[KEY_TASKMANAGER] = "TaskManager",
[KEY_JOURNAL] = "Journal",
[KEY_CONTROLPANEL] = "ControlPanel",
[KEY_APPSELECT] = "AppSelect",
[KEY_SCREENSAVER] = "ScreenSaver",
[KEY_VOICECOMMAND] = "VoiceCommand",
[KEY_BRIGHTNESS_MIN] = "BrightnessMin",
[KEY_BRIGHTNESS_MAX] = "BrightnessMax",
[KEY_BRIGHTNESS_AUTO] = "BrightnessAuto",
};
static const char *relatives[REL_MAX + 1] = {

View File

@ -714,6 +714,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x06c: map_key_clear(KEY_YELLOW); break;
case 0x06d: map_key_clear(KEY_ZOOM); break;
case 0x06f: map_key_clear(KEY_BRIGHTNESSUP); break;
case 0x070: map_key_clear(KEY_BRIGHTNESSDOWN); break;
case 0x072: map_key_clear(KEY_BRIGHTNESS_TOGGLE); break;
case 0x073: map_key_clear(KEY_BRIGHTNESS_MIN); break;
case 0x074: map_key_clear(KEY_BRIGHTNESS_MAX); break;
case 0x075: map_key_clear(KEY_BRIGHTNESS_AUTO); break;
case 0x082: map_key_clear(KEY_VIDEO_NEXT); break;
case 0x083: map_key_clear(KEY_LAST); break;
case 0x084: map_key_clear(KEY_ENTER); break;
@ -754,6 +761,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0bf: map_key_clear(KEY_SLOW); break;
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break;
case 0x0e0: map_abs_clear(ABS_VOLUME); break;
case 0x0e2: map_key_clear(KEY_MUTE); break;
case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
@ -761,6 +769,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
case 0x0f5: map_key_clear(KEY_SLOW); break;
case 0x181: map_key_clear(KEY_BUTTONCONFIG); break;
case 0x182: map_key_clear(KEY_BOOKMARKS); break;
case 0x183: map_key_clear(KEY_CONFIG); break;
case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
@ -774,6 +783,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x18c: map_key_clear(KEY_VOICEMAIL); break;
case 0x18d: map_key_clear(KEY_ADDRESSBOOK); break;
case 0x18e: map_key_clear(KEY_CALENDAR); break;
case 0x18f: map_key_clear(KEY_TASKMANAGER); break;
case 0x190: map_key_clear(KEY_JOURNAL); break;
case 0x191: map_key_clear(KEY_FINANCE); break;
case 0x192: map_key_clear(KEY_CALC); break;
case 0x193: map_key_clear(KEY_PLAYER); break;
@ -782,10 +793,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x199: map_key_clear(KEY_CHAT); break;
case 0x19c: map_key_clear(KEY_LOGOFF); break;
case 0x19e: map_key_clear(KEY_COFFEE); break;
case 0x19f: map_key_clear(KEY_CONTROLPANEL); break;
case 0x1a2: map_key_clear(KEY_APPSELECT); break;
case 0x1a3: map_key_clear(KEY_NEXT); break;
case 0x1a4: map_key_clear(KEY_PREVIOUS); break;
case 0x1a6: map_key_clear(KEY_HELP); break;
case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
case 0x1ab: map_key_clear(KEY_SPELLCHECK); break;
case 0x1ae: map_key_clear(KEY_KEYBOARD); break;
case 0x1b1: map_key_clear(KEY_SCREENSAVER); break;
case 0x1b4: map_key_clear(KEY_FILE); break;
case 0x1b6: map_key_clear(KEY_IMAGES); break;
case 0x1b7: map_key_clear(KEY_AUDIO); break;
case 0x1b8: map_key_clear(KEY_VIDEO); break;

View File

@ -685,32 +685,38 @@ static const char *config_cmdline = "";
int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
int depth, void *data)
{
unsigned long l;
char *p;
unsigned long l = 0;
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);
/* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */
if (overwrite_incoming_cmdline || !((char *)data)[0])
strlcpy(data, config_cmdline, COMMAND_LINE_SIZE);
if (overwrite_incoming_cmdline || !cmdline[0])
strlcpy(cmdline, config_cmdline, COMMAND_LINE_SIZE);
/* Retrieve command line unless forcing */
if (read_dt_cmdline) {
if (read_dt_cmdline)
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0) {
if (concat_cmdline) {
strlcat(data, " ", COMMAND_LINE_SIZE);
strlcat(data, p, min_t(int, (int)l,
COMMAND_LINE_SIZE));
} else
strlcpy(data, p, min_t(int, (int)l,
COMMAND_LINE_SIZE));
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));
}
}

View File

@ -118,6 +118,8 @@ config SW_SYNC_USER
source "drivers/staging/android/ion/Kconfig"
source "drivers/staging/android/fiq_debugger/Kconfig"
endif # if ANDROID
endmenu

View File

@ -1,6 +1,7 @@
ccflags-y += -I$(src) # needed for trace events
obj-y += ion/
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
obj-$(CONFIG_ASHMEM) += ashmem.o

View File

@ -0,0 +1,49 @@
config FIQ_DEBUGGER
bool "FIQ Mode Serial Debugger"
default n
depends on ARM || ARM64
help
The FIQ serial debugger can accept commands even when the
kernel is unresponsive due to being stuck with interrupts
disabled.
config FIQ_DEBUGGER_NO_SLEEP
bool "Keep serial debugger active"
depends on FIQ_DEBUGGER
default n
help
Enables the serial debugger at boot. Passing
fiq_debugger.no_sleep on the kernel commandline will
override this config option.
config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
bool "Don't disable wakeup IRQ when debugger is active"
depends on FIQ_DEBUGGER
default n
help
Don't disable the wakeup irq when enabling the uart clock. This will
cause extra interrupts, but it makes the serial debugger usable with
on some MSM radio builds that ignore the uart clock request in power
collapse.
config FIQ_DEBUGGER_CONSOLE
bool "Console on FIQ Serial Debugger port"
depends on FIQ_DEBUGGER
default n
help
Enables a console so that printk messages are displayed on
the debugger serial port as the occur.
config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
bool "Put the FIQ debugger into console mode by default"
depends on FIQ_DEBUGGER_CONSOLE
default n
help
If enabled, this puts the fiq debugger into console mode by default.
Otherwise, the fiq debugger will start out in debug mode.
config FIQ_WATCHDOG
bool
select FIQ_DEBUGGER
select PSTORE_RAM
default n

View File

@ -0,0 +1,4 @@
obj-y += fiq_debugger.o
obj-$(CONFIG_ARM) += fiq_debugger_arm.o
obj-$(CONFIG_ARM64) += fiq_debugger_arm64.o
obj-$(CONFIG_FIQ_WATCHDOG) += fiq_watchdog.o

View File

@ -1,5 +1,5 @@
/*
* arch/arm/include/asm/fiq_debugger.h
* drivers/staging/android/fiq_debugger/fiq_debugger.h
*
* Copyright (C) 2010 Google, Inc.
* Author: Colin Cross <ccross@android.com>

View File

@ -0,0 +1,240 @@
/*
* Copyright (C) 2014 Google, Inc.
* Author: Colin Cross <ccross@android.com>
*
* 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/ptrace.h>
#include <linux/uaccess.h>
#include <asm/stacktrace.h>
#include "fiq_debugger_priv.h"
static char *mode_name(unsigned cpsr)
{
switch (cpsr & MODE_MASK) {
case USR_MODE: return "USR";
case FIQ_MODE: return "FIQ";
case IRQ_MODE: return "IRQ";
case SVC_MODE: return "SVC";
case ABT_MODE: return "ABT";
case UND_MODE: return "UND";
case SYSTEM_MODE: return "SYS";
default: return "???";
}
}
void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
const struct pt_regs *regs)
{
output->printf(output, " pc %08x cpsr %08x mode %s\n",
regs->ARM_pc, regs->ARM_cpsr, mode_name(regs->ARM_cpsr));
}
void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
const struct pt_regs *regs)
{
output->printf(output,
" r0 %08x r1 %08x r2 %08x r3 %08x\n",
regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
output->printf(output,
" r4 %08x r5 %08x r6 %08x r7 %08x\n",
regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
output->printf(output,
" r8 %08x r9 %08x r10 %08x r11 %08x mode %s\n",
regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp,
mode_name(regs->ARM_cpsr));
output->printf(output,
" ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc,
regs->ARM_cpsr);
}
struct mode_regs {
unsigned long sp_svc;
unsigned long lr_svc;
unsigned long spsr_svc;
unsigned long sp_abt;
unsigned long lr_abt;
unsigned long spsr_abt;
unsigned long sp_und;
unsigned long lr_und;
unsigned long spsr_und;
unsigned long sp_irq;
unsigned long lr_irq;
unsigned long spsr_irq;
unsigned long r8_fiq;
unsigned long r9_fiq;
unsigned long r10_fiq;
unsigned long r11_fiq;
unsigned long r12_fiq;
unsigned long sp_fiq;
unsigned long lr_fiq;
unsigned long spsr_fiq;
};
static void __naked get_mode_regs(struct mode_regs *regs)
{
asm volatile (
"mrs r1, cpsr\n"
"msr cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n"
"stmia r0!, {r13 - r14}\n"
"mrs r2, spsr\n"
"msr cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n"
"stmia r0!, {r2, r13 - r14}\n"
"mrs r2, spsr\n"
"msr cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n"
"stmia r0!, {r2, r13 - r14}\n"
"mrs r2, spsr\n"
"msr cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
"stmia r0!, {r2, r13 - r14}\n"
"mrs r2, spsr\n"
"msr cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
"stmia r0!, {r2, r8 - r14}\n"
"mrs r2, spsr\n"
"stmia r0!, {r2}\n"
"msr cpsr_c, r1\n"
"bx lr\n");
}
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
const struct pt_regs *regs)
{
struct mode_regs mode_regs;
unsigned long mode = regs->ARM_cpsr & MODE_MASK;
fiq_debugger_dump_regs(output, regs);
get_mode_regs(&mode_regs);
output->printf(output,
"%csvc: sp %08x lr %08x spsr %08x\n",
mode == SVC_MODE ? '*' : ' ',
mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc);
output->printf(output,
"%cabt: sp %08x lr %08x spsr %08x\n",
mode == ABT_MODE ? '*' : ' ',
mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt);
output->printf(output,
"%cund: sp %08x lr %08x spsr %08x\n",
mode == UND_MODE ? '*' : ' ',
mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und);
output->printf(output,
"%cirq: sp %08x lr %08x spsr %08x\n",
mode == IRQ_MODE ? '*' : ' ',
mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq);
output->printf(output,
"%cfiq: r8 %08x r9 %08x r10 %08x r11 %08x r12 %08x\n",
mode == FIQ_MODE ? '*' : ' ',
mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq,
mode_regs.r11_fiq, mode_regs.r12_fiq);
output->printf(output,
" fiq: sp %08x lr %08x spsr %08x\n",
mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq);
}
struct stacktrace_state {
struct fiq_debugger_output *output;
unsigned int depth;
};
static int report_trace(struct stackframe *frame, void *d)
{
struct stacktrace_state *sts = d;
if (sts->depth) {
sts->output->printf(sts->output,
" pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
frame->pc, frame->pc, frame->lr, frame->lr,
frame->sp, frame->fp);
sts->depth--;
return 0;
}
sts->output->printf(sts->output, " ...\n");
return sts->depth == 0;
}
struct frame_tail {
struct frame_tail *fp;
unsigned long sp;
unsigned long lr;
} __attribute__((packed));
static struct frame_tail *user_backtrace(struct fiq_debugger_output *output,
struct frame_tail *tail)
{
struct frame_tail buftail[2];
/* Also check accessibility of one struct frame_tail beyond */
if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) {
output->printf(output, " invalid frame pointer %p\n",
tail);
return NULL;
}
if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) {
output->printf(output,
" failed to copy frame pointer %p\n", tail);
return NULL;
}
output->printf(output, " %p\n", buftail[0].lr);
/* frame pointers should strictly progress back up the stack
* (towards higher addresses) */
if (tail >= buftail[0].fp)
return NULL;
return buftail[0].fp-1;
}
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
const struct pt_regs *regs, unsigned int depth, void *ssp)
{
struct frame_tail *tail;
struct thread_info *real_thread_info = THREAD_INFO(ssp);
struct stacktrace_state sts;
sts.depth = depth;
sts.output = output;
*current_thread_info() = *real_thread_info;
if (!current)
output->printf(output, "current NULL\n");
else
output->printf(output, "pid: %d comm: %s\n",
current->pid, current->comm);
fiq_debugger_dump_regs(output, regs);
if (!user_mode(regs)) {
struct stackframe frame;
frame.fp = regs->ARM_fp;
frame.sp = regs->ARM_sp;
frame.lr = regs->ARM_lr;
frame.pc = regs->ARM_pc;
output->printf(output,
" pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr,
regs->ARM_sp, regs->ARM_fp);
walk_stackframe(&frame, report_trace, &sts);
return;
}
tail = ((struct frame_tail *) regs->ARM_fp) - 1;
while (depth-- && tail && !((unsigned long) tail & 3))
tail = user_backtrace(output, tail);
}

View File

@ -0,0 +1,202 @@
/*
* Copyright (C) 2014 Google, Inc.
* Author: Colin Cross <ccross@android.com>
*
* 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/ptrace.h>
#include <asm/stacktrace.h>
#include "fiq_debugger_priv.h"
static char *mode_name(const struct pt_regs *regs)
{
if (compat_user_mode(regs)) {
return "USR";
} else {
switch (processor_mode(regs)) {
case PSR_MODE_EL0t: return "EL0t";
case PSR_MODE_EL1t: return "EL1t";
case PSR_MODE_EL1h: return "EL1h";
case PSR_MODE_EL2t: return "EL2t";
case PSR_MODE_EL2h: return "EL2h";
default: return "???";
}
}
}
void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
const struct pt_regs *regs)
{
output->printf(output, " pc %016lx cpsr %08lx mode %s\n",
regs->pc, regs->pstate, mode_name(regs));
}
void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_output *output,
const struct pt_regs *regs)
{
output->printf(output, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
regs->compat_usr(0), regs->compat_usr(1),
regs->compat_usr(2), regs->compat_usr(3));
output->printf(output, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
regs->compat_usr(4), regs->compat_usr(5),
regs->compat_usr(6), regs->compat_usr(7));
output->printf(output, " r8 %08x r9 %08x r10 %08x r11 %08x\n",
regs->compat_usr(8), regs->compat_usr(9),
regs->compat_usr(10), regs->compat_usr(11));
output->printf(output, " ip %08x sp %08x lr %08x pc %08x\n",
regs->compat_usr(12), regs->compat_sp,
regs->compat_lr, regs->pc);
output->printf(output, " cpsr %08x (%s)\n",
regs->pstate, mode_name(regs));
}
void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_output *output,
const struct pt_regs *regs)
{
output->printf(output, " x0 %016lx x1 %016lx\n",
regs->regs[0], regs->regs[1]);
output->printf(output, " x2 %016lx x3 %016lx\n",
regs->regs[2], regs->regs[3]);
output->printf(output, " x4 %016lx x5 %016lx\n",
regs->regs[4], regs->regs[5]);
output->printf(output, " x6 %016lx x7 %016lx\n",
regs->regs[6], regs->regs[7]);
output->printf(output, " x8 %016lx x9 %016lx\n",
regs->regs[8], regs->regs[9]);
output->printf(output, " x10 %016lx x11 %016lx\n",
regs->regs[10], regs->regs[11]);
output->printf(output, " x12 %016lx x13 %016lx\n",
regs->regs[12], regs->regs[13]);
output->printf(output, " x14 %016lx x15 %016lx\n",
regs->regs[14], regs->regs[15]);
output->printf(output, " x16 %016lx x17 %016lx\n",
regs->regs[16], regs->regs[17]);
output->printf(output, " x18 %016lx x19 %016lx\n",
regs->regs[18], regs->regs[19]);
output->printf(output, " x20 %016lx x21 %016lx\n",
regs->regs[20], regs->regs[21]);
output->printf(output, " x22 %016lx x23 %016lx\n",
regs->regs[22], regs->regs[23]);
output->printf(output, " x24 %016lx x25 %016lx\n",
regs->regs[24], regs->regs[25]);
output->printf(output, " x26 %016lx x27 %016lx\n",
regs->regs[26], regs->regs[27]);
output->printf(output, " x28 %016lx x29 %016lx\n",
regs->regs[28], regs->regs[29]);
output->printf(output, " x30 %016lx sp %016lx\n",
regs->regs[30], regs->sp);
output->printf(output, " pc %016lx cpsr %08x (%s)\n",
regs->pc, regs->pstate, mode_name(regs));
}
void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
const struct pt_regs *regs)
{
if (compat_user_mode(regs))
fiq_debugger_dump_regs_aarch32(output, regs);
else
fiq_debugger_dump_regs_aarch64(output, regs);
}
#define READ_SPECIAL_REG(x) ({ \
u64 val; \
asm volatile ("mrs %0, " # x : "=r"(val)); \
val; \
})
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
const struct pt_regs *regs)
{
u32 pstate = READ_SPECIAL_REG(CurrentEl);
bool in_el2 = (pstate & PSR_MODE_MASK) >= PSR_MODE_EL2t;
fiq_debugger_dump_regs(output, regs);
output->printf(output, " sp_el0 %016lx\n",
READ_SPECIAL_REG(sp_el0));
if (in_el2)
output->printf(output, " sp_el1 %016lx\n",
READ_SPECIAL_REG(sp_el1));
output->printf(output, " elr_el1 %016lx\n",
READ_SPECIAL_REG(elr_el1));
output->printf(output, " spsr_el1 %08lx\n",
READ_SPECIAL_REG(spsr_el1));
if (in_el2) {
output->printf(output, " spsr_irq %08lx\n",
READ_SPECIAL_REG(spsr_irq));
output->printf(output, " spsr_abt %08lx\n",
READ_SPECIAL_REG(spsr_abt));
output->printf(output, " spsr_und %08lx\n",
READ_SPECIAL_REG(spsr_und));
output->printf(output, " spsr_fiq %08lx\n",
READ_SPECIAL_REG(spsr_fiq));
output->printf(output, " spsr_el2 %08lx\n",
READ_SPECIAL_REG(elr_el2));
output->printf(output, " spsr_el2 %08lx\n",
READ_SPECIAL_REG(spsr_el2));
}
}
struct stacktrace_state {
struct fiq_debugger_output *output;
unsigned int depth;
};
static int report_trace(struct stackframe *frame, void *d)
{
struct stacktrace_state *sts = d;
if (sts->depth) {
sts->output->printf(sts->output, "%pF:\n", frame->pc);
sts->output->printf(sts->output,
" pc %016lx sp %016lx fp %016lx\n",
frame->pc, frame->sp, frame->fp);
sts->depth--;
return 0;
}
sts->output->printf(sts->output, " ...\n");
return sts->depth == 0;
}
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
const struct pt_regs *regs, unsigned int depth, void *ssp)
{
struct thread_info *real_thread_info = THREAD_INFO(ssp);
struct stacktrace_state sts;
sts.depth = depth;
sts.output = output;
*current_thread_info() = *real_thread_info;
if (!current)
output->printf(output, "current NULL\n");
else
output->printf(output, "pid: %d comm: %s\n",
current->pid, current->comm);
fiq_debugger_dump_regs(output, regs);
if (!user_mode(regs)) {
struct stackframe frame;
frame.fp = regs->regs[29];
frame.sp = regs->sp;
frame.pc = regs->pc;
output->printf(output, "\n");
walk_stackframe(&frame, report_trace, &sts);
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2014 Google, Inc.
* Author: Colin Cross <ccross@android.com>
*
* 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 _FIQ_DEBUGGER_PRIV_H_
#define _FIQ_DEBUGGER_PRIV_H_
#define THREAD_INFO(sp) ((struct thread_info *) \
((unsigned long)(sp) & ~(THREAD_SIZE - 1)))
struct fiq_debugger_output {
void (*printf)(struct fiq_debugger_output *output, const char *fmt, ...);
};
struct pt_regs;
void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
const struct pt_regs *regs);
void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
const struct pt_regs *regs);
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
const struct pt_regs *regs);
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
const struct pt_regs *regs, unsigned int depth, void *ssp);
#endif

View File

@ -1,5 +1,5 @@
/*
* arch/arm/common/fiq_debugger_ringbuf.c
* drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h
*
* simple lockless ringbuffer
*

View File

@ -0,0 +1,56 @@
/*
* 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/kernel.h>
#include <linux/spinlock.h>
#include <linux/pstore_ram.h>
#include "fiq_watchdog.h"
#include "fiq_debugger_priv.h"
static DEFINE_RAW_SPINLOCK(fiq_watchdog_lock);
static void fiq_watchdog_printf(struct fiq_debugger_output *output,
const char *fmt, ...)
{
char buf[256];
va_list ap;
int len;
va_start(ap, fmt);
len = vscnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
ramoops_console_write_buf(buf, len);
}
struct fiq_debugger_output fiq_watchdog_output = {
.printf = fiq_watchdog_printf,
};
void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp)
{
char msg[24];
int len;
raw_spin_lock(&fiq_watchdog_lock);
len = scnprintf(msg, sizeof(msg), "watchdog fiq cpu %d\n",
THREAD_INFO(svc_sp)->cpu);
ramoops_console_write_buf(msg, len);
fiq_debugger_dump_stacktrace(&fiq_watchdog_output, regs, 100, svc_sp);
raw_spin_unlock(&fiq_watchdog_lock);
}

View File

@ -0,0 +1,20 @@
/*
* 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.
*
*/
#ifndef _FIQ_WATCHDOG_H_
#define _FIQ_WATCHDOG_H_
void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp);
#endif

View File

@ -494,6 +494,7 @@ static void adf_obj_destroy(struct adf_obj *obj, struct idr *idr)
struct adf_event_refcount *refcount =
container_of(node, struct adf_event_refcount,
node);
rb_erase(&refcount->node, &obj->event_refcount);
kfree(refcount);
node = rb_first(&obj->event_refcount);
}

View File

@ -28,7 +28,7 @@ static struct sg_table *adf_memblock_map(struct dma_buf_attachment *attach,
unsigned long pfn = PFN_DOWN(pdata->base);
struct page *page = pfn_to_page(pfn);
struct sg_table *table;
int ret;
int nents, ret;
table = kzalloc(sizeof(*table), GFP_KERNEL);
if (!table)
@ -36,12 +36,21 @@ static struct sg_table *adf_memblock_map(struct dma_buf_attachment *attach,
ret = sg_alloc_table(table, 1, GFP_KERNEL);
if (ret < 0)
goto err;
goto err_alloc;
sg_set_page(table->sgl, page, attach->dmabuf->size, 0);
nents = dma_map_sg(attach->dev, table->sgl, 1, direction);
if (!nents) {
ret = -EINVAL;
goto err_map;
}
return table;
err:
err_map:
sg_free_table(table);
err_alloc:
kfree(table);
return ERR_PTR(ret);
}
@ -49,6 +58,7 @@ static struct sg_table *adf_memblock_map(struct dma_buf_attachment *attach,
static void adf_memblock_unmap(struct dma_buf_attachment *attach,
struct sg_table *table, enum dma_data_direction direction)
{
dma_unmap_sg(attach->dev, table->sgl, 1, direction);
sg_free_table(table);
}

View File

@ -2724,6 +2724,17 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
return memcpy(buffer, temp, sz);
}
char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
{
char *end = buffer + buflen;
/* these dentries are never renamed, so d_lock is not needed */
if (prepend(&end, &buflen, " (deleted)", 11) ||
prepend_name(&end, &buflen, &dentry->d_name) ||
prepend(&end, &buflen, "/", 1))
end = ERR_PTR(-ENAMETOOLONG);
return end;
}
/*
* Write full pathname from the root of the filesystem into the buffer.
*/

View File

@ -916,14 +916,8 @@ static int get_hstate_idx(int page_size_log)
return h - hstates;
}
static char *hugetlb_dname(struct dentry *dentry, char *buffer, int buflen)
{
return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
dentry->d_name.name);
}
static struct dentry_operations anon_ops = {
.d_dname = hugetlb_dname
.d_dname = simple_dname
};
/*

View File

@ -377,6 +377,12 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
return 0;
}
void notrace ramoops_console_write_buf(const char *buf, size_t size)
{
struct ramoops_context *cxt = &oops_cxt;
persistent_ram_write(cxt->cprz, buf, size);
}
static int ramoops_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;

View File

@ -332,6 +332,7 @@ extern int d_validate(struct dentry *, struct dentry *);
* helper function for dentry_operations.d_dname() members
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
extern char *simple_dname(struct dentry *, char *, int);
extern char *__d_path(const struct path *, const struct path *, char *, int);
extern char *d_absolute_path(const struct path *, char *, int);

View File

@ -67,6 +67,8 @@ void persistent_ram_free_old(struct persistent_ram_zone *prz);
ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
char *str, size_t len);
void ramoops_console_write_buf(const char *buf, size_t size);
/*
* Ramoops platform data
* @mem_size memory size for ramoops

View File

@ -461,10 +461,14 @@ struct input_keymap_entry {
#define KEY_VIDEO_NEXT 241 /* drive next video source */
#define KEY_VIDEO_PREV 242 /* drive previous video source */
#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */
#define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */
#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual
brightness control is off,
rely on ambient */
#define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO
#define KEY_DISPLAY_OFF 245 /* display device to off state */
#define KEY_WIMAX 246
#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */
#define KEY_WIMAX KEY_WWAN
#define KEY_RFKILL 247 /* Key that controls all radios */
#define KEY_MICMUTE 248 /* Mute / unmute the microphone */
@ -509,11 +513,15 @@ struct input_keymap_entry {
#define BTN_DEAD 0x12f
#define BTN_GAMEPAD 0x130
#define BTN_A 0x130
#define BTN_B 0x131
#define BTN_SOUTH 0x130
#define BTN_A BTN_SOUTH
#define BTN_EAST 0x131
#define BTN_B BTN_EAST
#define BTN_C 0x132
#define BTN_X 0x133
#define BTN_Y 0x134
#define BTN_NORTH 0x133
#define BTN_X BTN_NORTH
#define BTN_WEST 0x134
#define BTN_Y BTN_WEST
#define BTN_Z 0x135
#define BTN_TL 0x136
#define BTN_TR 0x137
@ -626,6 +634,7 @@ struct input_keymap_entry {
#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */
#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */
#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */
#define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE
#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */
#define KEY_LOGOFF 0x1b1 /* AL Logoff */
@ -710,6 +719,24 @@ struct input_keymap_entry {
#define KEY_ATTENDANT_TOGGLE 0x21d /* Attendant call on or off */
#define KEY_LIGHTS_TOGGLE 0x21e /* Reading light on or off */
#define BTN_DPAD_UP 0x220
#define BTN_DPAD_DOWN 0x221
#define BTN_DPAD_LEFT 0x222
#define BTN_DPAD_RIGHT 0x223
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
#define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */
#define KEY_CONTROLPANEL 0x243 /* AL Control Panel */
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
#define BTN_TRIGGER_HAPPY 0x2c0
#define BTN_TRIGGER_HAPPY1 0x2c0
#define BTN_TRIGGER_HAPPY2 0x2c1
@ -847,6 +874,7 @@ struct input_keymap_entry {
#define SW_FRONT_PROXIMITY 0x0b /* set = front proximity sensor active */
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
#define SW_MAX 0x0f
#define SW_CNT (SW_MAX+1)

View File

@ -149,6 +149,12 @@
#define PR_GET_TID_ADDRESS 40
/* Sets the timerslack for arbitrary threads
* arg2 slack value, 0 means "use default"
* arg3 pid of the thread whose timer slack needs to be set
*/
#define PR_SET_TIMERSLACK_PID 41
#define PR_SET_VMA 0x53564d41
# define PR_SET_VMA_ANON_NAME 0

View File

@ -39,6 +39,7 @@ struct adf_fbdev {
u32 default_format;
};
#if IS_ENABLED(CONFIG_ADF_FBDEV)
void adf_modeinfo_to_fb_videomode(const struct drm_mode_modeinfo *mode,
struct fb_videomode *vmode);
void adf_modeinfo_from_fb_videomode(const struct fb_videomode *vmode,
@ -57,5 +58,67 @@ int adf_fbdev_set_par(struct fb_info *info);
int adf_fbdev_blank(int blank, struct fb_info *info);
int adf_fbdev_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
int adf_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma);
#else
static inline void adf_modeinfo_to_fb_videomode(const struct drm_mode_modeinfo *mode,
struct fb_videomode *vmode)
{
WARN_ONCE(1, "%s: CONFIG_ADF_FBDEV is disabled\n", __func__);
}
static inline void adf_modeinfo_from_fb_videomode(const struct fb_videomode *vmode,
struct drm_mode_modeinfo *mode)
{
WARN_ONCE(1, "%s: CONFIG_ADF_FBDEV is disabled\n", __func__);
}
static inline int adf_fbdev_init(struct adf_fbdev *fbdev,
struct adf_interface *interface,
struct adf_overlay_engine *eng,
u16 xres_virtual, u16 yres_virtual, u32 format,
struct fb_ops *fbops, const char *fmt, ...)
{
return -ENODEV;
}
static inline void adf_fbdev_destroy(struct adf_fbdev *fbdev) { }
static inline int adf_fbdev_open(struct fb_info *info, int user)
{
return -ENODEV;
}
static inline int adf_fbdev_release(struct fb_info *info, int user)
{
return -ENODEV;
}
static inline int adf_fbdev_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
return -ENODEV;
}
static inline int adf_fbdev_set_par(struct fb_info *info)
{
return -ENODEV;
}
static inline int adf_fbdev_blank(int blank, struct fb_info *info)
{
return -ENODEV;
}
static inline int adf_fbdev_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
return -ENODEV;
}
static inline int adf_fbdev_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
return -ENODEV;
}
#endif
#endif /* _VIDEO_ADF_FBDEV_H_ */

View File

@ -34,7 +34,7 @@ static int irqcount;
static struct kobject *wakeup_reason;
static spinlock_t resume_reason_lock;
static ssize_t reason_show(struct kobject *kobj, struct kobj_attribute *attr,
static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
int irq_no, buf_offset = 0;
@ -53,8 +53,7 @@ static ssize_t reason_show(struct kobject *kobj, struct kobj_attribute *attr,
return buf_offset;
}
static struct kobj_attribute resume_reason = __ATTR(last_resume_reason, 0666,
reason_show, NULL);
static struct kobj_attribute resume_reason = __ATTR_RO(last_resume_reason);
static struct attribute *attrs[] = {
&resume_reason.attr,

View File

@ -44,6 +44,7 @@
#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/mempolicy.h>
#include <linux/sched.h>
#include <linux/compat.h>
#include <linux/syscalls.h>
@ -2252,6 +2253,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
unsigned long, arg4, unsigned long, arg5)
{
struct task_struct *me = current;
struct task_struct *tsk;
unsigned char comm[sizeof(me->comm)];
long error;
@ -2375,6 +2377,23 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
else
return -EINVAL;
break;
case PR_SET_TIMERSLACK_PID:
rcu_read_lock();
tsk = find_task_by_pid_ns((pid_t)arg3, &init_pid_ns);
if (tsk == NULL) {
rcu_read_unlock();
return -EINVAL;
}
get_task_struct(tsk);
rcu_read_unlock();
if (arg2 <= 0)
tsk->timer_slack_ns =
tsk->default_timer_slack_ns;
else
tsk->timer_slack_ns = arg2;
put_task_struct(tsk);
error = 0;
break;
default:
return -EINVAL;
}

View File

@ -2879,14 +2879,8 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
/* common code */
static char *shmem_dname(struct dentry *dentry, char *buffer, int buflen)
{
return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
dentry->d_name.name);
}
static struct dentry_operations anon_ops = {
.d_dname = shmem_dname
.d_dname = simple_dname
};
/**

View File

@ -249,26 +249,33 @@ int ping_init_sock(struct sock *sk)
{
struct net *net = sock_net(sk);
kgid_t group = current_egid();
struct group_info *group_info = get_current_groups();
int i, j, count = group_info->ngroups;
struct group_info *group_info;
int i, j, count;
kgid_t low, high;
int ret = 0;
inet_get_ping_group_range_net(net, &low, &high);
if (gid_lte(low, group) && gid_lte(group, high))
return 0;
group_info = get_current_groups();
count = group_info->ngroups;
for (i = 0; i < group_info->nblocks; i++) {
int cp_count = min_t(int, NGROUPS_PER_BLOCK, count);
for (j = 0; j < cp_count; j++) {
kgid_t gid = group_info->blocks[i][j];
if (gid_lte(low, gid) && gid_lte(gid, high))
return 0;
goto out_release_group;
}
count -= cp_count;
}
return -EACCES;
ret = -EACCES;
out_release_group:
put_group_info(group_info);
return ret;
}
EXPORT_SYMBOL_GPL(ping_init_sock);

View File

@ -42,6 +42,11 @@
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/sysfs.h>
#include <linux/rtc.h>
#include <linux/time.h>
#include <linux/math64.h>
#include <linux/suspend.h>
#include <linux/notifier.h>
#include <net/net_namespace.h>
struct idletimer_tg_attr {
@ -58,22 +63,65 @@ struct idletimer_tg {
struct kobject *kobj;
struct idletimer_tg_attr attr;
struct timespec delayed_timer_trigger;
struct timespec last_modified_timer;
struct timespec last_suspend_time;
struct notifier_block pm_nb;
int timeout;
unsigned int refcnt;
bool work_pending;
bool send_nl_msg;
bool active;
};
static LIST_HEAD(idletimer_tg_list);
static DEFINE_MUTEX(list_mutex);
static DEFINE_SPINLOCK(timestamp_lock);
static struct kobject *idletimer_tg_kobj;
static bool check_for_delayed_trigger(struct idletimer_tg *timer,
struct timespec *ts)
{
bool state;
struct timespec temp;
spin_lock_bh(&timestamp_lock);
timer->work_pending = false;
if ((ts->tv_sec - timer->last_modified_timer.tv_sec) > timer->timeout ||
timer->delayed_timer_trigger.tv_sec != 0) {
state = false;
temp.tv_sec = timer->timeout;
temp.tv_nsec = 0;
if (timer->delayed_timer_trigger.tv_sec != 0) {
temp = timespec_add(timer->delayed_timer_trigger, temp);
ts->tv_sec = temp.tv_sec;
ts->tv_nsec = temp.tv_nsec;
timer->delayed_timer_trigger.tv_sec = 0;
timer->work_pending = true;
schedule_work(&timer->work);
} else {
temp = timespec_add(timer->last_modified_timer, temp);
ts->tv_sec = temp.tv_sec;
ts->tv_nsec = temp.tv_nsec;
}
} else {
state = timer->active;
}
spin_unlock_bh(&timestamp_lock);
return state;
}
static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer)
{
char iface_msg[NLMSG_MAX_SIZE];
char state_msg[NLMSG_MAX_SIZE];
char *envp[] = { iface_msg, state_msg, NULL };
char timestamp_msg[NLMSG_MAX_SIZE];
char *envp[] = { iface_msg, state_msg, timestamp_msg, NULL };
int res;
struct timespec ts;
uint64_t time_ns;
bool state;
res = snprintf(iface_msg, NLMSG_MAX_SIZE, "INTERFACE=%s",
iface);
@ -81,12 +129,24 @@ static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer)
pr_err("message too long (%d)", res);
return;
}
get_monotonic_boottime(&ts);
state = check_for_delayed_trigger(timer, &ts);
res = snprintf(state_msg, NLMSG_MAX_SIZE, "STATE=%s",
timer->active ? "active" : "inactive");
state ? "active" : "inactive");
if (NLMSG_MAX_SIZE <= res) {
pr_err("message too long (%d)", res);
return;
}
time_ns = timespec_to_ns(&ts);
res = snprintf(timestamp_msg, NLMSG_MAX_SIZE, "TIME_NS=%llu", time_ns);
if (NLMSG_MAX_SIZE <= res) {
timestamp_msg[0] = '\0';
pr_err("message too long (%d)", res);
}
pr_debug("putting nlmsg: <%s> <%s>\n", iface_msg, state_msg);
kobject_uevent_env(idletimer_tg_kobj, KOBJ_CHANGE, envp);
return;
@ -151,9 +211,55 @@ static void idletimer_tg_expired(unsigned long data)
struct idletimer_tg *timer = (struct idletimer_tg *) data;
pr_debug("timer %s expired\n", timer->attr.attr.name);
spin_lock_bh(&timestamp_lock);
timer->active = false;
timer->work_pending = true;
schedule_work(&timer->work);
spin_unlock_bh(&timestamp_lock);
}
static int idletimer_resume(struct notifier_block *notifier,
unsigned long pm_event, void *unused)
{
struct timespec ts;
unsigned long time_diff, now = jiffies;
struct idletimer_tg *timer = container_of(notifier,
struct idletimer_tg, pm_nb);
if (!timer)
return NOTIFY_DONE;
switch (pm_event) {
case PM_SUSPEND_PREPARE:
get_monotonic_boottime(&timer->last_suspend_time);
break;
case PM_POST_SUSPEND:
spin_lock_bh(&timestamp_lock);
if (!timer->active) {
spin_unlock_bh(&timestamp_lock);
break;
}
/* since jiffies are not updated when suspended now represents
* the time it would have suspended */
if (time_after(timer->timer.expires, now)) {
get_monotonic_boottime(&ts);
ts = timespec_sub(ts, timer->last_suspend_time);
time_diff = timespec_to_jiffies(&ts);
if (timer->timer.expires > (time_diff + now)) {
mod_timer_pending(&timer->timer,
(timer->timer.expires - time_diff));
} else {
del_timer(&timer->timer);
timer->timer.expires = 0;
timer->active = false;
timer->work_pending = true;
schedule_work(&timer->work);
}
}
spin_unlock_bh(&timestamp_lock);
break;
default:
break;
}
return NOTIFY_DONE;
}
static int idletimer_tg_create(struct idletimer_tg_info *info)
@ -187,6 +293,18 @@ static int idletimer_tg_create(struct idletimer_tg_info *info)
info->timer->refcnt = 1;
info->timer->send_nl_msg = (info->send_nl_msg == 0) ? false : true;
info->timer->active = true;
info->timer->timeout = info->timeout;
info->timer->delayed_timer_trigger.tv_sec = 0;
info->timer->delayed_timer_trigger.tv_nsec = 0;
info->timer->work_pending = false;
get_monotonic_boottime(&info->timer->last_modified_timer);
info->timer->pm_nb.notifier_call = idletimer_resume;
ret = register_pm_notifier(&info->timer->pm_nb);
if (ret)
printk(KERN_WARNING "[%s] Failed to register pm notifier %d\n",
__func__, ret);
mod_timer(&info->timer->timer,
msecs_to_jiffies(info->timeout * 1000) + jiffies);
@ -203,6 +321,34 @@ static int idletimer_tg_create(struct idletimer_tg_info *info)
return ret;
}
static void reset_timer(const struct idletimer_tg_info *info)
{
unsigned long now = jiffies;
struct idletimer_tg *timer = info->timer;
bool timer_prev;
spin_lock_bh(&timestamp_lock);
timer_prev = timer->active;
timer->active = true;
/* timer_prev is used to guard overflow problem in time_before*/
if (!timer_prev || time_before(timer->timer.expires, now)) {
pr_debug("Starting Checkentry timer (Expired, Jiffies): %lu, %lu\n",
timer->timer.expires, now);
/* checks if there is a pending inactive notification*/
if (timer->work_pending)
timer->delayed_timer_trigger = timer->last_modified_timer;
else {
timer->work_pending = true;
schedule_work(&timer->work);
}
}
get_monotonic_boottime(&timer->last_modified_timer);
mod_timer(&timer->timer,
msecs_to_jiffies(info->timeout * 1000) + now);
spin_unlock_bh(&timestamp_lock);
}
/*
* The actual xt_tables plugin.
*/
@ -226,9 +372,7 @@ static unsigned int idletimer_tg_target(struct sk_buff *skb,
}
/* TODO: Avoid modifying timers on each packet */
mod_timer(&info->timer->timer,
msecs_to_jiffies(info->timeout * 1000) + now);
reset_timer(info);
return XT_CONTINUE;
}
@ -236,7 +380,6 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par)
{
struct idletimer_tg_info *info = par->targinfo;
int ret;
unsigned long now = jiffies;
pr_debug("checkentry targinfo %s\n", info->label);
@ -257,17 +400,7 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par)
info->timer = __idletimer_tg_find_by_label(info->label);
if (info->timer) {
info->timer->refcnt++;
info->timer->active = true;
if (time_before(info->timer->timer.expires, now)) {
schedule_work(&info->timer->work);
pr_debug("Starting Checkentry timer (Expired, Jiffies): %lu, %lu\n",
info->timer->timer.expires, now);
}
mod_timer(&info->timer->timer,
msecs_to_jiffies(info->timeout * 1000) + now);
reset_timer(info);
pr_debug("increased refcnt of timer %s to %u\n",
info->label, info->timer->refcnt);
} else {
@ -298,6 +431,7 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par)
list_del(&info->timer->entry);
del_timer_sync(&info->timer->timer);
sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
unregister_pm_notifier(&info->timer->pm_nb);
kfree(info->timer->attr.attr.name);
kfree(info->timer);
} else {

View File

@ -444,11 +444,15 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
avc_dump_query(ab, ad->selinux_audit_data->ssid,
ad->selinux_audit_data->tsid,
ad->selinux_audit_data->tclass);
if (ad->selinux_audit_data->denied) {
audit_log_format(ab, " permissive=%u",
ad->selinux_audit_data->result ? 0 : 1);
}
}
/* This is the slow part of avc audit with big stack footprint */
noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied,
u32 requested, u32 audited, u32 denied, int result,
struct common_audit_data *a,
unsigned flags)
{
@ -477,6 +481,7 @@ noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
sad.tsid = tsid;
sad.audited = audited;
sad.denied = denied;
sad.result = result;
a->selinux_audit_data = &sad;

View File

@ -2714,6 +2714,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
static noinline int audit_inode_permission(struct inode *inode,
u32 perms, u32 audited, u32 denied,
int result,
unsigned flags)
{
struct common_audit_data ad;
@ -2724,7 +2725,7 @@ static noinline int audit_inode_permission(struct inode *inode,
ad.u.inode = inode;
rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
audited, denied, &ad, flags);
audited, denied, result, &ad, flags);
if (rc)
return rc;
return 0;
@ -2766,7 +2767,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
if (likely(!audited))
return rc;
rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
if (rc2)
return rc2;
return rc;

View File

@ -102,7 +102,7 @@ static inline u32 avc_audit_required(u32 requested,
}
int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied,
u32 requested, u32 audited, u32 denied, int result,
struct common_audit_data *a,
unsigned flags);
@ -137,7 +137,7 @@ static inline int avc_audit(u32 ssid, u32 tsid,
if (likely(!audited))
return 0;
return slow_avc_audit(ssid, tsid, tclass,
requested, audited, denied,
requested, audited, denied, result,
a, flags);
}