cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dumpstack_32.c (3578B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  Copyright (C) 1991, 1992  Linus Torvalds
      4 *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
      5 */
      6#include <linux/sched/debug.h>
      7#include <linux/kallsyms.h>
      8#include <linux/kprobes.h>
      9#include <linux/uaccess.h>
     10#include <linux/hardirq.h>
     11#include <linux/kdebug.h>
     12#include <linux/export.h>
     13#include <linux/ptrace.h>
     14#include <linux/kexec.h>
     15#include <linux/sysfs.h>
     16#include <linux/bug.h>
     17#include <linux/nmi.h>
     18
     19#include <asm/stacktrace.h>
     20
     21const char *stack_type_name(enum stack_type type)
     22{
     23	if (type == STACK_TYPE_IRQ)
     24		return "IRQ";
     25
     26	if (type == STACK_TYPE_SOFTIRQ)
     27		return "SOFTIRQ";
     28
     29	if (type == STACK_TYPE_ENTRY)
     30		return "ENTRY_TRAMPOLINE";
     31
     32	if (type == STACK_TYPE_EXCEPTION)
     33		return "#DF";
     34
     35	return NULL;
     36}
     37
     38static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
     39{
     40	unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack_ptr);
     41	unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
     42
     43	/*
     44	 * This is a software stack, so 'end' can be a valid stack pointer.
     45	 * It just means the stack is empty.
     46	 */
     47	if (stack < begin || stack > end)
     48		return false;
     49
     50	info->type	= STACK_TYPE_IRQ;
     51	info->begin	= begin;
     52	info->end	= end;
     53
     54	/*
     55	 * See irq_32.c -- the next stack pointer is stored at the beginning of
     56	 * the stack.
     57	 */
     58	info->next_sp	= (unsigned long *)*begin;
     59
     60	return true;
     61}
     62
     63static bool in_softirq_stack(unsigned long *stack, struct stack_info *info)
     64{
     65	unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack_ptr);
     66	unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
     67
     68	/*
     69	 * This is a software stack, so 'end' can be a valid stack pointer.
     70	 * It just means the stack is empty.
     71	 */
     72	if (stack < begin || stack > end)
     73		return false;
     74
     75	info->type	= STACK_TYPE_SOFTIRQ;
     76	info->begin	= begin;
     77	info->end	= end;
     78
     79	/*
     80	 * The next stack pointer is stored at the beginning of the stack.
     81	 * See irq_32.c.
     82	 */
     83	info->next_sp	= (unsigned long *)*begin;
     84
     85	return true;
     86}
     87
     88static bool in_doublefault_stack(unsigned long *stack, struct stack_info *info)
     89{
     90	struct cpu_entry_area *cea = get_cpu_entry_area(raw_smp_processor_id());
     91	struct doublefault_stack *ss = &cea->doublefault_stack;
     92
     93	void *begin = ss->stack;
     94	void *end = begin + sizeof(ss->stack);
     95
     96	if ((void *)stack < begin || (void *)stack >= end)
     97		return false;
     98
     99	info->type	= STACK_TYPE_EXCEPTION;
    100	info->begin	= begin;
    101	info->end	= end;
    102	info->next_sp	= (unsigned long *)this_cpu_read(cpu_tss_rw.x86_tss.sp);
    103
    104	return true;
    105}
    106
    107
    108int get_stack_info(unsigned long *stack, struct task_struct *task,
    109		   struct stack_info *info, unsigned long *visit_mask)
    110{
    111	if (!stack)
    112		goto unknown;
    113
    114	task = task ? : current;
    115
    116	if (in_task_stack(stack, task, info))
    117		goto recursion_check;
    118
    119	if (task != current)
    120		goto unknown;
    121
    122	if (in_entry_stack(stack, info))
    123		goto recursion_check;
    124
    125	if (in_hardirq_stack(stack, info))
    126		goto recursion_check;
    127
    128	if (in_softirq_stack(stack, info))
    129		goto recursion_check;
    130
    131	if (in_doublefault_stack(stack, info))
    132		goto recursion_check;
    133
    134	goto unknown;
    135
    136recursion_check:
    137	/*
    138	 * Make sure we don't iterate through any given stack more than once.
    139	 * If it comes up a second time then there's something wrong going on:
    140	 * just break out and report an unknown stack type.
    141	 */
    142	if (visit_mask) {
    143		if (*visit_mask & (1UL << info->type)) {
    144			printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
    145			goto unknown;
    146		}
    147		*visit_mask |= 1UL << info->type;
    148	}
    149
    150	return 0;
    151
    152unknown:
    153	info->type = STACK_TYPE_UNKNOWN;
    154	return -EINVAL;
    155}