Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / rtas / reloc.S
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13 #include <rtas.h>               
14                         
15 /*
16 Function:       
17         Input:
18                 r3:   Destination to copy rtas code to
19                 r4:   Configuration     
20         Output:         
21                 r3:   Entry point for rtas calls        
22 Decription: Called by OpenFirmware to instantiate rtas, needs to copy
23         itself to destination, also do a relocations.
24         
25 */
26
27 .extern rtas_entry
28 .extern .stack
29 .extern _got
30 .extern _got_end
31 .extern __bss_start
32 .extern __bss_end
33 .extern rtas_config
34
35
36         .section        ".rtasstart","ax";
37         .align  3
38         .globl _rtas_start
39 _rtas_start:
40         mflr    r10             # save link register
41         bcl     20,31,.over     # branch (always) to .over 
42
43 .base:
44         .align  3
45
46 /* Our Open Firmware needs to know the size of the RTAS binary and the
47  * size & address of the RTAS function jump table. SLOF always looks for this
48  * information in the following three quads here at the very beginning of the
49  * RTAS binary at offset 8. So DO NOT DELETE/MOVE them! */
50
51 ._rtas_size:            .quad   _rtas_end-_rtas_start
52 ._ptr_to_func_tab:      .quad   rtas_func_tab-_rtas_start
53 ._ptr_to_func_tab_size: .quad   rtas_func_tab_size-_rtas_start
54
55 /* The other variables are not accessed by SLOF anymore: */
56
57 ._rel_offset:           .quad   _reloc_table_start-_rtas_start
58 ._rel_end_offset:       .quad   _reloc_table_end-_rtas_start
59 ._bss_offset:           .quad   __bss_start-_rtas_start
60 ._bss_end_offset:       .quad   __bss_end-_rtas_start
61 ._rtas_entry_offset:    .quad   rtas_entry-_rtas_start
62 ._rtas_config_offset:   .quad   rtas_config-_rtas_start
63 ._rtas_stack:           .quad   .stack-_rtas_start+RTAS_STACKSIZE-0x60
64 ._rtas_toc:             .quad   _got-_rtas_start+0x8000
65
66 .over:  
67         mflr r8                 # gpr 8 is the base
68         addi r8,r8,_rtas_start-.base # points to _rtas_start
69         mr r11,r4               # Save config value     
70         
71 # Copy rtas code
72         
73         ld r5,._rtas_size-_rtas_start(r8) 
74         mr r4,r8                # Start of rtas
75         addi r6,r3,-8           # Destination
76         addi r4,r4,-8           # Source
77         srdi r5,r5,3            # Count in quads
78         mtctr r5
79 0:                              
80         ldu r0,8(r4)            
81         stdu r0,8(r6)
82         bdnz 0b         
83
84 # Clear bss
85
86         ld r4,._bss_offset-_rtas_start(r8)
87         ld r5,._bss_end_offset-_rtas_start(r8)
88         li r0,0
89         add r6,r3,r4            # Address bss in copied code
90         addi r6,r6,-8
91         sub r5,r5,r4            # Calculate bss size
92         srdi r5,r5,3            # Count in quads
93         mtctr r5        
94 0:      
95         stdu r0,8(r6)
96         bdnz 0b
97
98 # Relocate got
99
100         ld      r4, ._rel_offset-_rtas_start(r8)
101         ld      r5, ._rel_end_offset-_rtas_start(r8)
102         sub     r5, r5,r4       # Calculate reloc table size
103         cmpdi   r5, 0           # No reloc table ?
104         beq     1f
105
106         add     r4, r4, r3      # Calculate reloc table address
107         addi    r4, r4, -4
108         srdi    r5, r5, 2       # Count in words        
109         mtctr   r5
110 0:      
111         lwzu    r6, 4(r4)       # Load offset out of reloc table
112         ldx     r0, r6, r3      # Load value    
113         add     r0, r0, r3      # Add relocation offset = load address
114         stdx    r0, r6, r3
115         bdnz    0b              
116 1:                      
117
118 # Save config data
119
120         ld r5,._rtas_config_offset-_rtas_start(r8)
121         add r5,r5,r3
122         std r11,0(r5)
123         
124 # Flush to memory
125         
126         mr r4,r3                # Destination address
127         ld r5,._rtas_size-_rtas_start(r8) 
128                 
129         add r5,r5,r4
130         addi r5,r5,127
131         rlwinm r4,r4,0,0,24
132         rlwinm r5,r5,0,0,24
133         sub r5,r5,r4
134         srwi r5,r5,7
135         mtctr r5
136 0:
137         dcbst 0,r4
138         sync
139         icbi 0,r4
140         sync
141         isync
142         addi r4,r4,128
143         bdnz 0b
144
145 # Call init function
146         mfmsr   r11                     # Switch to 64 bit mode
147         mr      r7,r11
148         rotldi  r11,r11,1
149         ori     r11,r11,1
150         rotldi  r11,r11,63
151         mtmsrd  r11
152         isync
153         mr      r9,r1                   # save old stack pointer
154         ld      r1,._rtas_stack-_rtas_start(r8) # load new stack pointer
155         add     r1,r1,r3
156         std     r9,0(r1)                # save stack pointer
157         std     r2,64(r1)               # save toc
158         std     r7,72(r1)               # save old msr value
159
160         ld      r2,._rtas_toc-_rtas_start(r8)   # load got pointer
161         add     r2,r2,r3
162
163         bl      save_regs_r3_r12
164         bl      .rtas_init
165         bl      restore_regs_r3_r12
166
167         ld      r11,72(r1)              # restore msr value     
168         ld      r2,64(r1)               # restore toc
169         ld      r1,0(r1)                # get old stack
170
171         mtmsrd  r11                     # restore msr
172         isync
173
174
175 # Return rtas entry
176
177         ld r4,._rtas_entry_offset-_rtas_start(r8)
178         add r3,r3,r4
179         mtlr    r10
180         blr     
181
182
183