~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/openbios/arch/ppc/ofmem.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   Creation Date: <1999/11/07 19:02:11 samuel>
 
3
 *   Time-stamp: <2004/01/07 19:42:36 samuel>
 
4
 *
 
5
 *      <ofmem.c>
 
6
 *
 
7
 *      OF Memory manager
 
8
 *
 
9
 *   Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
 
10
 *   Copyright (C) 2004 Stefan Reinauer
 
11
 *
 
12
 *   This program is free software; you can redistribute it and/or
 
13
 *   modify it under the terms of the GNU General Public License
 
14
 *   as published by the Free Software Foundation
 
15
 *
 
16
 */
 
17
 
 
18
/* TODO: Clean up MOLisms in a decent way */
 
19
 
 
20
#include "config.h"
 
21
#include "libopenbios/bindings.h"
 
22
#include "libc/string.h"
 
23
#include "libopenbios/ofmem.h"
 
24
#include "kernel.h"
 
25
#ifdef I_WANT_MOLISMS
 
26
#include "mol/prom.h"
 
27
#include "mol/mol.h"
 
28
#endif
 
29
#include "mmutypes.h"
 
30
#include "asm/processor.h"
 
31
#ifdef I_WANT_MOLISMS
 
32
#include "osi_calls.h"
 
33
#endif
 
34
 
 
35
#define BIT(n)          (1U<<(31-(n)))
 
36
 
 
37
/* called from assembly */
 
38
extern void     dsi_exception( void );
 
39
extern void     isi_exception( void );
 
40
extern void     setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize );
 
41
 
 
42
/****************************************************************
 
43
 * Memory usage (before of_quiesce is called)
 
44
 *
 
45
 *                      Physical
 
46
 *
 
47
 *      0x00000000      Exception vectors
 
48
 *      0x00004000      Free space
 
49
 *      0x01e00000      Open Firmware (us)
 
50
 *      0x01f00000      OF allocations
 
51
 *      0x01ff0000      PTE Hash
 
52
 *      0x02000000-     Free space
 
53
 *
 
54
 * Allocations grow downwards from 0x01e00000
 
55
 *
 
56
 ****************************************************************/
 
57
 
 
58
#define HASH_SIZE               (2 << 15)
 
59
#define SEGR_BASE               0x400           /* segment number range to use */
 
60
 
 
61
#define FREE_BASE_1             0x00004000
 
62
#define OF_CODE_START           0x01e00000
 
63
/* #define OF_MALLOC_BASE       0x01f00000 */
 
64
extern char _end[];
 
65
#define OF_MALLOC_BASE          _end
 
66
 
 
67
#define HASH_BASE               (0x02000000 - HASH_SIZE)
 
68
#define FREE_BASE_2             0x02000000
 
69
 
 
70
#define RAMSIZE                 0x02000000      /* XXXXXXXXXXXXXXXXXXX FIXME XXXXXXXXXXXXXXX */
 
71
 
 
72
static ofmem_t s_ofmem;
 
73
 
 
74
#define IO_BASE                 0x80000000
 
75
#define OFMEM (&s_ofmem)
 
76
 
 
77
static inline unsigned long
 
78
get_hash_base( void )
 
79
{
 
80
        return HASH_BASE;
 
81
}
 
82
 
 
83
static inline unsigned long
 
84
get_hash_size( void )
 
85
{
 
86
        return HASH_SIZE;
 
87
}
 
88
 
 
89
static ucell get_heap_top( void )
 
90
{
 
91
        return HASH_BASE;
 
92
}
 
93
 
 
94
static inline size_t ALIGN_SIZE(size_t x, size_t a)
 
95
{
 
96
    return (x + a - 1) & ~(a-1);
 
97
}
 
98
 
 
99
ofmem_t* ofmem_arch_get_private(void)
 
100
{
 
101
        return OFMEM;
 
102
}
 
103
 
 
104
void* ofmem_arch_get_malloc_base(void)
 
105
{
 
106
        return OF_MALLOC_BASE;
 
107
}
 
108
 
 
109
ucell ofmem_arch_get_heap_top(void)
 
110
{
 
111
        return get_heap_top();
 
112
}
 
113
 
 
114
ucell ofmem_arch_get_virt_top(void)
 
115
{
 
116
        return IO_BASE;
 
117
}
 
118
 
 
119
void ofmem_arch_unmap_pages(ucell virt, ucell size)
 
120
{
 
121
        /* kill page mappings in provided range */
 
122
}
 
123
 
 
124
void ofmem_arch_map_pages(ucell phys, ucell virt, ucell size, ucell mode)
 
125
{
 
126
        /* none yet */
 
127
}
 
128
 
 
129
/************************************************************************/
 
130
/*      OF private allocations                                          */
 
131
/************************************************************************/
 
132
 
 
133
void *
 
134
malloc( int size )
 
135
{
 
136
        return ofmem_malloc(size);
 
137
}
 
138
 
 
139
void
 
140
free( void *ptr )
 
141
{
 
142
        return ofmem_free(ptr);
 
143
}
 
144
 
 
145
void *
 
146
realloc( void *ptr, size_t size )
 
147
{
 
148
        return ofmem_realloc(ptr, size);
 
149
}
 
150
 
 
151
 
 
152
/************************************************************************/
 
153
/*      misc                                                            */
 
154
/************************************************************************/
 
155
 
 
156
ucell ofmem_arch_default_translation_mode( ucell phys )
 
157
{
 
158
        /* XXX: Guard bit not set as it should! */
 
159
        if( phys < IO_BASE || phys >= 0xffc00000 )
 
160
                return 0x02;    /*0xa*/ /* wim GxPp */
 
161
        return 0x6a;            /* WIm GxPp, I/O */
 
162
}
 
163
 
 
164
 
 
165
/************************************************************************/
 
166
/*      page fault handler                                              */
 
167
/************************************************************************/
 
168
 
 
169
static ucell
 
170
ea_to_phys( ucell ea, ucell *mode )
 
171
{
 
172
        ucell phys;
 
173
 
 
174
        /* hardcode our translation needs */
 
175
        if( ea >= OF_CODE_START && ea < FREE_BASE_2 ) {
 
176
                *mode = ofmem_arch_default_translation_mode( ea );
 
177
                return ea;
 
178
        }
 
179
 
 
180
        phys = ofmem_translate(ea, mode);
 
181
        if( phys == (ucell)-1 ) {
 
182
#ifdef I_WANT_MOLISMS
 
183
                if( ea != 0x80816c00 )
 
184
                        printk("ea_to_phys: no translation for %08lx, using 1-1\n", ea );
 
185
#endif
 
186
                phys = ea;
 
187
                *mode = ofmem_arch_default_translation_mode( phys );
 
188
 
 
189
#ifdef I_WANT_MOLISMS
 
190
                forth_segv_handler( (char*)ea );
 
191
                OSI_Debugger(1);
 
192
#endif
 
193
                /* print_virt_range(); */
 
194
                /* print_phys_range(); */
 
195
                /* print_trans(); */
 
196
        }
 
197
        return phys;
 
198
}
 
199
 
 
200
static void
 
201
hash_page( ucell ea, ucell phys, ucell mode )
 
202
{
 
203
        static int next_grab_slot=0;
 
204
        unsigned long *upte, cmp, hash1;
 
205
        int i, vsid, found;
 
206
        mPTE_t *pp;
 
207
 
 
208
        vsid = (ea>>28) + SEGR_BASE;
 
209
        cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22);
 
210
 
 
211
        hash1 = vsid;
 
212
        hash1 ^= (ea >> 12) & 0xffff;
 
213
        hash1 &= (get_hash_size() - 1) >> 6;
 
214
 
 
215
        pp = (mPTE_t*)(get_hash_base() + (hash1 << 6));
 
216
        upte = (unsigned long*)pp;
 
217
 
 
218
        /* replace old translation */
 
219
        for( found=0, i=0; !found && i<8; i++ )
 
220
                if( cmp == upte[i*2] )
 
221
                        found=1;
 
222
 
 
223
        /* otherwise use a free slot */
 
224
        for( i=0; !found && i<8; i++ )
 
225
                if( !pp[i].v )
 
226
                        found=1;
 
227
 
 
228
        /* out of slots, just evict one */
 
229
        if( !found ) {
 
230
                i = next_grab_slot + 1;
 
231
                next_grab_slot = (next_grab_slot + 1) % 8;
 
232
        }
 
233
        i--;
 
234
        upte[i*2] = cmp;
 
235
        upte[i*2+1] = (phys & ~0xfff) | mode;
 
236
 
 
237
        asm volatile( "tlbie %0"  :: "r"(ea) );
 
238
}
 
239
 
 
240
void
 
241
dsi_exception( void )
 
242
{
 
243
        unsigned long dar, dsisr;
 
244
        ucell mode;
 
245
        ucell phys;
 
246
 
 
247
        asm volatile("mfdar %0" : "=r" (dar) : );
 
248
        asm volatile("mfdsisr %0" : "=r" (dsisr) : );
 
249
 
 
250
        //printk("dsi-exception @ %08lx <%08lx>\n", dar, dsisr );
 
251
 
 
252
        phys = ea_to_phys(dar, &mode);
 
253
        hash_page( dar, phys, mode );
 
254
}
 
255
 
 
256
void
 
257
isi_exception( void )
 
258
{
 
259
        unsigned long nip, srr1;
 
260
        ucell mode;
 
261
        ucell phys;
 
262
 
 
263
        asm volatile("mfsrr0 %0" : "=r" (nip) : );
 
264
        asm volatile("mfsrr1 %0" : "=r" (srr1) : );
 
265
 
 
266
        //printk("isi-exception @ %08lx <%08lx>\n", nip, srr1 );
 
267
 
 
268
        phys = ea_to_phys(nip, &mode);
 
269
        hash_page( nip, phys, mode );
 
270
}
 
271
 
 
272
 
 
273
/************************************************************************/
 
274
/*      init / cleanup                                                  */
 
275
/************************************************************************/
 
276
 
 
277
void
 
278
setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize )
 
279
{
 
280
        unsigned long sdr1 = HASH_BASE | ((HASH_SIZE-1) >> 16);
 
281
        unsigned long sr_base = (0x20 << 24) | SEGR_BASE;
 
282
        unsigned long msr;
 
283
        int i;
 
284
 
 
285
        asm volatile("mtsdr1 %0" :: "r" (sdr1) );
 
286
        for( i=0; i<16; i++ ) {
 
287
                int j = i << 28;
 
288
                asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j) );
 
289
        }
 
290
        asm volatile("mfmsr %0" : "=r" (msr) : );
 
291
        msr |= MSR_IR | MSR_DR;
 
292
        asm volatile("mtmsr %0" :: "r" (msr) );
 
293
}
 
294
 
 
295
void
 
296
ofmem_init( void )
 
297
{
 
298
        ofmem_t *ofmem = OFMEM;
 
299
        /* In case we can't rely on memory being zero initialized */
 
300
        memset(ofmem, 0, sizeof(ofmem));
 
301
 
 
302
        ofmem->ramsize = RAMSIZE;
 
303
 
 
304
        ofmem_claim_phys( 0, FREE_BASE_1, 0 );
 
305
        ofmem_claim_virt( 0, FREE_BASE_1, 0 );
 
306
        ofmem_claim_phys( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 );
 
307
        ofmem_claim_virt( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 );
 
308
}