hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright 2010 IBM Corp, Benjamin Herrenschmidt <benh@kernel.crashing.org>
 *
 * Generic idle routine for Book3E processors
 */
 
#include <linux/threads.h>
#include <asm/reg.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/ppc-opcode.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
#include <asm/epapr_hcalls.h>
#include <asm/hw_irq.h>
 
/* 64-bit version only for now */
#ifdef CONFIG_PPC64
 
.macro BOOK3E_IDLE name loop
_GLOBAL(\name)
   /* Save LR for later */
   mflr    r0
   std    r0,16(r1)
 
   /* Hard disable interrupts */
   wrteei    0
 
   /* Now check if an interrupt came in while we were soft disabled
    * since we may otherwise lose it (doorbells etc...).
    */
   lbz    r3,PACAIRQHAPPENED(r13)
   cmpwi    cr0,r3,0
   bne    2f
 
   /* Now we are going to mark ourselves as soft and hard enabled in
    * order to be able to take interrupts while asleep. We inform lockdep
    * of that. We don't actually turn interrupts on just yet tho.
    */
#ifdef CONFIG_TRACE_IRQFLAGS
   stdu    r1,-128(r1)
   bl    trace_hardirqs_on
   addi    r1,r1,128
#endif
   li    r0,IRQS_ENABLED
   stb    r0,PACAIRQSOFTMASK(r13)
   
   /* Interrupts will make use return to LR, so get something we want
    * in there
    */
   bl    1f
 
   /* And return (interrupts are on) */
   ld    r0,16(r1)
   mtlr    r0
   blr
 
1:    /* Let's set the _TLF_NAPPING flag so interrupts make us return
    * to the right spot
   */
   ld    r11, PACACURRENT(r13)
   ld    r10,TI_LOCAL_FLAGS(r11)
   ori    r10,r10,_TLF_NAPPING
   std    r10,TI_LOCAL_FLAGS(r11)
 
   /* We can now re-enable hard interrupts and go to sleep */
   wrteei    1
   \loop
 
2:
   lbz    r10,PACAIRQHAPPENED(r13)
   ori    r10,r10,PACA_IRQ_HARD_DIS
   stb    r10,PACAIRQHAPPENED(r13)
   blr
.endm
 
.macro BOOK3E_IDLE_LOOP
1:
   PPC_WAIT(0)
   b    1b
.endm
 
/* epapr_ev_idle_start below is patched with the proper hcall
   opcodes during kernel initialization */
.macro EPAPR_EV_IDLE_LOOP
idle_loop:
   LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE))
 
.global epapr_ev_idle_start
epapr_ev_idle_start:
   li      r3, -1
   nop
   nop
   nop
   b       idle_loop
.endm
 
BOOK3E_IDLE epapr_ev_idle EPAPR_EV_IDLE_LOOP
 
BOOK3E_IDLE book3e_idle BOOK3E_IDLE_LOOP
 
#endif /* CONFIG_PPC64 */