mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
log: [ 0.13373200] Calibrating delay loop... [ 0.14077600] ------------[ cut here ]------------ [ 0.14116700] WARNING: CPU: 0 PID: 0 at kernel/sched/core.c:3790 preempt_count_add+0xc8/0x11c [ 0.14348000] DEBUG_LOCKS_WARN_ON((preempt_count() < 0))Modules linked in: [ 0.14395100] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.6.0 #7 [ 0.14410800] [ 0.14427400] Call Trace: [ 0.14450700] [<807cd226>] dump_stack+0x8a/0xe4 [ 0.14473500] [<80072792>] __warn+0x10e/0x15c [ 0.14495900] [<80072852>] warn_slowpath_fmt+0x72/0xc0 [ 0.14518600] [<800a5240>] preempt_count_add+0xc8/0x11c [ 0.14544900] [<807ef918>] _raw_spin_lock+0x28/0x68 [ 0.14572600] [<800e0eb8>] vprintk_emit+0x84/0x2d8 [ 0.14599000] [<800e113a>] vprintk_default+0x2e/0x44 [ 0.14625100] [<800e2042>] vprintk_func+0x12a/0x1d0 [ 0.14651300] [<800e1804>] printk+0x30/0x48 [ 0.14677600] [<80008052>] lockdep_init+0x12/0xb0 [ 0.14703800] [<80002080>] start_kernel+0x558/0x7f8 [ 0.14730000] [<800052bc>] csky_start+0x58/0x94 [ 0.14756600] irq event stamp: 34 [ 0.14775100] hardirqs last enabled at (33): [<80067370>] ret_from_exception+0x2c/0x72 [ 0.14793700] hardirqs last disabled at (34): [<800e0eae>] vprintk_emit+0x7a/0x2d8 [ 0.14812300] softirqs last enabled at (32): [<800655b0>] __do_softirq+0x578/0x6d8 [ 0.14830800] softirqs last disabled at (25): [<8007b3b8>] irq_exit+0xec/0x128 The preempt_count of reg could be destroyed after csky_do_IRQ without reload from memory. After reference to other architectures (arm64, riscv), we move preempt entry into ret_from_exception and disable irq at the beginning of ret_from_exception instead of RESTORE_ALL. Signed-off-by: Guo Ren <guoren@linux.alibaba.com> Reported-by: Lu Baoquan <lu.baoquan@intellif.com>
337 lines
6.1 KiB
ArmAsm
337 lines
6.1 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0 */
|
||
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
|
||
|
||
#include <linux/linkage.h>
|
||
#include <abi/entry.h>
|
||
#include <abi/pgtable-bits.h>
|
||
#include <asm/errno.h>
|
||
#include <asm/setup.h>
|
||
#include <asm/unistd.h>
|
||
#include <asm/asm-offsets.h>
|
||
#include <linux/threads.h>
|
||
#include <asm/setup.h>
|
||
#include <asm/page.h>
|
||
#include <asm/thread_info.h>
|
||
|
||
#define PTE_INDX_MSK 0xffc
|
||
#define PTE_INDX_SHIFT 10
|
||
#define _PGDIR_SHIFT 22
|
||
|
||
.macro zero_fp
|
||
#ifdef CONFIG_STACKTRACE
|
||
movi r8, 0
|
||
#endif
|
||
.endm
|
||
|
||
.macro tlbop_begin name, val0, val1, val2
|
||
ENTRY(csky_\name)
|
||
mtcr a3, ss2
|
||
mtcr r6, ss3
|
||
mtcr a2, ss4
|
||
|
||
RD_PGDR r6
|
||
RD_MEH a3
|
||
#ifdef CONFIG_CPU_HAS_TLBI
|
||
tlbi.vaas a3
|
||
sync.is
|
||
|
||
btsti a3, 31
|
||
bf 1f
|
||
RD_PGDR_K r6
|
||
1:
|
||
#else
|
||
bgeni a2, 31
|
||
WR_MCIR a2
|
||
bgeni a2, 25
|
||
WR_MCIR a2
|
||
#endif
|
||
bclri r6, 0
|
||
lrw a2, va_pa_offset
|
||
ld.w a2, (a2, 0)
|
||
subu r6, a2
|
||
bseti r6, 31
|
||
|
||
mov a2, a3
|
||
lsri a2, _PGDIR_SHIFT
|
||
lsli a2, 2
|
||
addu r6, a2
|
||
ldw r6, (r6)
|
||
|
||
lrw a2, va_pa_offset
|
||
ld.w a2, (a2, 0)
|
||
subu r6, a2
|
||
bseti r6, 31
|
||
|
||
lsri a3, PTE_INDX_SHIFT
|
||
lrw a2, PTE_INDX_MSK
|
||
and a3, a2
|
||
addu r6, a3
|
||
ldw a3, (r6)
|
||
|
||
movi a2, (_PAGE_PRESENT | \val0)
|
||
and a3, a2
|
||
cmpne a3, a2
|
||
bt \name
|
||
|
||
/* First read/write the page, just update the flags */
|
||
ldw a3, (r6)
|
||
bgeni a2, PAGE_VALID_BIT
|
||
bseti a2, PAGE_ACCESSED_BIT
|
||
bseti a2, \val1
|
||
bseti a2, \val2
|
||
or a3, a2
|
||
stw a3, (r6)
|
||
|
||
/* Some cpu tlb-hardrefill bypass the cache */
|
||
#ifdef CONFIG_CPU_NEED_TLBSYNC
|
||
movi a2, 0x22
|
||
bseti a2, 6
|
||
mtcr r6, cr22
|
||
mtcr a2, cr17
|
||
sync
|
||
#endif
|
||
|
||
mfcr a3, ss2
|
||
mfcr r6, ss3
|
||
mfcr a2, ss4
|
||
rte
|
||
\name:
|
||
mfcr a3, ss2
|
||
mfcr r6, ss3
|
||
mfcr a2, ss4
|
||
SAVE_ALL 0
|
||
.endm
|
||
.macro tlbop_end is_write
|
||
zero_fp
|
||
RD_MEH a2
|
||
psrset ee, ie
|
||
mov a0, sp
|
||
movi a1, \is_write
|
||
jbsr do_page_fault
|
||
jmpi ret_from_exception
|
||
.endm
|
||
|
||
.text
|
||
|
||
tlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT
|
||
tlbop_end 0
|
||
|
||
tlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
|
||
tlbop_end 1
|
||
|
||
tlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
|
||
#ifndef CONFIG_CPU_HAS_LDSTEX
|
||
jbsr csky_cmpxchg_fixup
|
||
#endif
|
||
tlbop_end 1
|
||
|
||
ENTRY(csky_systemcall)
|
||
SAVE_ALL TRAP0_SIZE
|
||
zero_fp
|
||
#ifdef CONFIG_RSEQ_DEBUG
|
||
mov a0, sp
|
||
jbsr rseq_syscall
|
||
#endif
|
||
psrset ee, ie
|
||
|
||
lrw r11, __NR_syscalls
|
||
cmphs syscallid, r11 /* Check nr of syscall */
|
||
bt ret_from_exception
|
||
|
||
lrw r13, sys_call_table
|
||
ixw r13, syscallid
|
||
ldw r11, (r13)
|
||
cmpnei r11, 0
|
||
bf ret_from_exception
|
||
|
||
mov r9, sp
|
||
bmaski r10, THREAD_SHIFT
|
||
andn r9, r10
|
||
ldw r12, (r9, TINFO_FLAGS)
|
||
ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
|
||
cmpnei r12, 0
|
||
bt csky_syscall_trace
|
||
#if defined(__CSKYABIV2__)
|
||
subi sp, 8
|
||
stw r5, (sp, 0x4)
|
||
stw r4, (sp, 0x0)
|
||
jsr r11 /* Do system call */
|
||
addi sp, 8
|
||
#else
|
||
jsr r11
|
||
#endif
|
||
stw a0, (sp, LSAVE_A0) /* Save return value */
|
||
jmpi ret_from_exception
|
||
|
||
csky_syscall_trace:
|
||
mov a0, sp /* sp = pt_regs pointer */
|
||
jbsr syscall_trace_enter
|
||
/* Prepare args before do system call */
|
||
ldw a0, (sp, LSAVE_A0)
|
||
ldw a1, (sp, LSAVE_A1)
|
||
ldw a2, (sp, LSAVE_A2)
|
||
ldw a3, (sp, LSAVE_A3)
|
||
#if defined(__CSKYABIV2__)
|
||
subi sp, 8
|
||
stw r5, (sp, 0x4)
|
||
stw r4, (sp, 0x0)
|
||
#else
|
||
ldw r6, (sp, LSAVE_A4)
|
||
ldw r7, (sp, LSAVE_A5)
|
||
#endif
|
||
jsr r11 /* Do system call */
|
||
#if defined(__CSKYABIV2__)
|
||
addi sp, 8
|
||
#endif
|
||
stw a0, (sp, LSAVE_A0) /* Save return value */
|
||
|
||
mov a0, sp /* right now, sp --> pt_regs */
|
||
jbsr syscall_trace_exit
|
||
br ret_from_exception
|
||
|
||
ENTRY(ret_from_kernel_thread)
|
||
jbsr schedule_tail
|
||
mov a0, r10
|
||
jsr r9
|
||
jbsr ret_from_exception
|
||
|
||
ENTRY(ret_from_fork)
|
||
jbsr schedule_tail
|
||
mov r9, sp
|
||
bmaski r10, THREAD_SHIFT
|
||
andn r9, r10
|
||
ldw r12, (r9, TINFO_FLAGS)
|
||
ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
|
||
cmpnei r12, 0
|
||
bf ret_from_exception
|
||
mov a0, sp /* sp = pt_regs pointer */
|
||
jbsr syscall_trace_exit
|
||
|
||
ret_from_exception:
|
||
psrclr ie
|
||
ld syscallid, (sp, LSAVE_PSR)
|
||
btsti syscallid, 31
|
||
|
||
/*
|
||
* Load address of current->thread_info, Then get address of task_struct
|
||
* Get task_needreshed in task_struct
|
||
*/
|
||
mov r9, sp
|
||
bmaski r10, THREAD_SHIFT
|
||
andn r9, r10
|
||
|
||
bt 1f
|
||
ldw r12, (r9, TINFO_FLAGS)
|
||
andi r12, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | _TIF_UPROBE)
|
||
cmpnei r12, 0
|
||
bt exit_work
|
||
1:
|
||
#ifdef CONFIG_PREEMPTION
|
||
ldw r12, (r9, TINFO_PREEMPT)
|
||
cmpnei r12, 0
|
||
bt 2f
|
||
jbsr preempt_schedule_irq /* irq en/disable is done inside */
|
||
2:
|
||
#endif
|
||
|
||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||
ld r10, (sp, LSAVE_PSR)
|
||
btsti r10, 6
|
||
bf 2f
|
||
jbsr trace_hardirqs_on
|
||
2:
|
||
#endif
|
||
RESTORE_ALL
|
||
|
||
exit_work:
|
||
lrw syscallid, ret_from_exception
|
||
mov lr, syscallid
|
||
|
||
btsti r12, TIF_NEED_RESCHED
|
||
bt work_resched
|
||
|
||
psrset ie
|
||
mov a0, sp
|
||
mov a1, r12
|
||
jmpi do_notify_resume
|
||
|
||
work_resched:
|
||
jmpi schedule
|
||
|
||
ENTRY(csky_trap)
|
||
SAVE_ALL 0
|
||
zero_fp
|
||
psrset ee
|
||
mov a0, sp /* Push Stack pointer arg */
|
||
jbsr trap_c /* Call C-level trap handler */
|
||
jmpi ret_from_exception
|
||
|
||
/*
|
||
* Prototype from libc for abiv1:
|
||
* register unsigned int __result asm("a0");
|
||
* asm( "trap 3" :"=r"(__result)::);
|
||
*/
|
||
ENTRY(csky_get_tls)
|
||
USPTOKSP
|
||
|
||
/* increase epc for continue */
|
||
mfcr a0, epc
|
||
addi a0, TRAP0_SIZE
|
||
mtcr a0, epc
|
||
|
||
/* get current task thread_info with kernel 8K stack */
|
||
bmaski a0, THREAD_SHIFT
|
||
not a0
|
||
subi sp, 1
|
||
and a0, sp
|
||
addi sp, 1
|
||
|
||
/* get tls */
|
||
ldw a0, (a0, TINFO_TP_VALUE)
|
||
|
||
KSPTOUSP
|
||
rte
|
||
|
||
ENTRY(csky_irq)
|
||
SAVE_ALL 0
|
||
zero_fp
|
||
psrset ee
|
||
|
||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||
jbsr trace_hardirqs_off
|
||
#endif
|
||
|
||
|
||
mov a0, sp
|
||
jbsr csky_do_IRQ
|
||
|
||
jmpi ret_from_exception
|
||
|
||
/*
|
||
* a0 = prev task_struct *
|
||
* a1 = next task_struct *
|
||
* a0 = return next
|
||
*/
|
||
ENTRY(__switch_to)
|
||
lrw a3, TASK_THREAD
|
||
addu a3, a0
|
||
|
||
SAVE_SWITCH_STACK
|
||
|
||
stw sp, (a3, THREAD_KSP)
|
||
|
||
/* Set up next process to run */
|
||
lrw a3, TASK_THREAD
|
||
addu a3, a1
|
||
|
||
ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */
|
||
|
||
#if defined(__CSKYABIV2__)
|
||
addi a3, a1, TASK_THREAD_INFO
|
||
ldw tls, (a3, TINFO_TP_VALUE)
|
||
#endif
|
||
|
||
RESTORE_SWITCH_STACK
|
||
|
||
rts
|
||
ENDPROC(__switch_to)
|