~ubuntu-branches/ubuntu/trusty/proll/trusty

« back to all changes in this revision

Viewing changes to qemu/system_qemu.c

  • Committer: Bazaar Package Importer
  • Author(s): Guillem Jover
  • Date: 2011-06-08 04:35:59 UTC
  • Revision ID: james.westby@ubuntu.com-20110608043559-8ln88b583x0uqcox
Tags: 18-5
* Switch to debhelper compatibility level 7.
* Use dh_prep instead of “dh_clean -k”.
* Use $(filter ...) instead of $(findstring ...) to extract space separated
  options from DEB_BUILD_OPTIONS in debian/rules.
* Switch to source format “3.0 (quilt)”:
  - Remove quilt from Build-Depends.
  - Remove quilt.make include from debian/rules.
  - Remove patch and unpatch targets from debian/rules.
  - Remove now unneeded debian/README.source.
* Now using Standards-Version 3.9.2 (no changes needed).
* Remove leading ‘./’ from lintian overrides.
* Rename build target to build-indep, install to install-indep, and add
  an empty build-arch target.
* Use dpkg-buildflags to set CPPFLAGS, CFLAGS and LDFLAGS.
* Disable Sparc V9 specific unbuildable code.
* Add ${misc:Depends} to Depends field.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 ** Proll (PROM replacement)
 
3
 ** system.c: shared miscallenea.
 
4
 ** Copyright 1999 Pete Zaitcev
 
5
 ** This code is licensed under GNU General Public License.
 
6
 **/
 
7
#include <stdarg.h>
 
8
#include <asi.h>
 
9
#include <crs.h>
 
10
#ifndef NULL
 
11
#define NULL ((void*)0)
 
12
#endif
 
13
 
 
14
#include "pgtsrmmu.h"
 
15
 
 
16
#include "vconsole.h"
 
17
#include <timer.h>              /* Local copy of 2.2 style include */
 
18
#include <general.h>            /* __P() */
 
19
#include <net.h>                /* init_net() */
 
20
#include <romlib.h>             /* we are a provider for part of this. */
 
21
#include <netpriv.h>            /* myipaddr */
 
22
#include <arpa.h>
 
23
#include <system.h>             /* our own prototypes */
 
24
 
 
25
/*
 
26
 * We export this.
 
27
 */
 
28
char idprom[IDPROM_SIZE];
 
29
 
 
30
 
 
31
/*
 
32
 * Create an I/O mapping to pa[size].
 
33
 * Returns va of the mapping or 0 if unsuccessful.
 
34
 */
 
35
void *
 
36
map_io(unsigned pa, int size)
 
37
{
 
38
        void *va;
 
39
        unsigned int npages;
 
40
        unsigned int off;
 
41
        unsigned int mva;
 
42
 
 
43
        off = pa & (PAGE_SIZE-1);
 
44
        npages = (off + size + (PAGE_SIZE-1)) / PAGE_SIZE;
 
45
        pa &= ~(PAGE_SIZE-1);
 
46
 
 
47
        va = mem_alloc(&cio, npages*PAGE_SIZE, PAGE_SIZE);
 
48
        if (va == 0) return va;
 
49
 
 
50
        mva = (unsigned int) va;
 
51
    /* printk("map_io: va 0x%x pa 0x%x off 0x%x npages %d\n", va, pa, off, npages); */ /* P3 */
 
52
        while (npages-- != 0) {
 
53
                map_page(pmem.pl1, mva, pa, 1, pmem.pbas);
 
54
                mva += PAGE_SIZE;
 
55
                pa += PAGE_SIZE;
 
56
        }
 
57
 
 
58
        return (void *)((unsigned int)va + off);
 
59
}
 
60
 
 
61
/*
 
62
 * Tablewalk routine used for testing.
 
63
 * Returns PTP/PTE.
 
64
 */
 
65
unsigned int
 
66
proc_tablewalk(int ctx, unsigned int va)
 
67
{
 
68
        unsigned int pa1;
 
69
 
 
70
        __asm__ __volatile__ ("lda [%1] %2, %0" :
 
71
                                "=r" (pa1) :
 
72
                                "r" (AC_M_CTPR), "i" (ASI_M_MMUREGS));
 
73
        /* printk(" ctpr %x ctx %x\n", pa1, ctx); */ /* P3 */
 
74
        pa1 <<= 4;
 
75
        pa1 = ld_bypass(pa1 + (ctx << 2));
 
76
        if ((pa1 & 0x03) == 0) goto invalid;
 
77
        return mem_tablewalk((pa1 & 0xFFFFFFF0) << 4, va);
 
78
 
 
79
invalid:
 
80
        printk(" invalid %x\n", pa1);
 
81
        return 0;
 
82
}
 
83
 
 
84
/*
 
85
 * Walk the tables in memory, starting at physical address pa.
 
86
 */
 
87
unsigned int
 
88
mem_tablewalk(unsigned int pa, unsigned int va)
 
89
{
 
90
        unsigned int pa1;
 
91
 
 
92
        printk("pa %x va %x", pa, va);
 
93
        pa1 = ld_bypass(pa + (((va&0xFF000000)>>24) << 2));
 
94
        if ((pa1 & 0x03) == 0) goto invalid;
 
95
        printk(" l1 %x", pa1);
 
96
        pa1 <<= 4;    pa1 &= 0xFFFFFF00;
 
97
        pa1 = ld_bypass(pa1 + (((va&0x00FC0000)>>18) << 2));
 
98
        if ((pa1 & 0x03) == 0) goto invalid;
 
99
        printk(" l2 %x", pa1);
 
100
        pa1 <<= 4;    pa1 &= 0xFFFFFF00;
 
101
        pa1 = ld_bypass(pa1 + (((va&0x0003F000)>>12) << 2));
 
102
        if ((pa1 & 0x03) == 0) goto invalid;
 
103
        printk(" l3 %x", pa1);
 
104
        printk(" off %x\n", va&0x00000FFF);
 
105
        return pa1;
 
106
invalid:
 
107
        printk(" invalid %x\n", pa1);
 
108
        return 0;
 
109
}
 
110
 
 
111
/*
 
112
 * Make CPU page tables.
 
113
 * Returns pointer to context table.
 
114
 * Here we ignore memory allocation errors which "should not happen"
 
115
 * because we cannot print anything anyways if memory initialization fails.
 
116
 */
 
117
void makepages(struct phym *t, unsigned int highbase)
 
118
{
 
119
        unsigned int *ctp, *l1, pte;
 
120
        int i;
 
121
        unsigned int pa, va;
 
122
 
 
123
        ctp = mem_zalloc(&cmem, NCTX_SWIFT*sizeof(int), NCTX_SWIFT*sizeof(int));
 
124
        l1 = mem_zalloc(&cmem, 256*sizeof(int), 256*sizeof(int));
 
125
 
 
126
        pte = SRMMU_ET_PTD | (((unsigned int)l1 - PROLBASE + highbase) >> 4);
 
127
        for (i = 0; i < NCTX_SWIFT; i++) {
 
128
                ctp[i] = pte;
 
129
        }
 
130
 
 
131
        pa = PROLBASE;
 
132
        for (va = PROLBASE; va < PROLDATA; va += PAGE_SIZE) {
 
133
                map_page(l1, va, pa, 0, highbase);
 
134
                pa += PAGE_SIZE;
 
135
        }
 
136
        pa = highbase + PROLDATA - PROLBASE;
 
137
        for (va = PROLDATA; va < PROLBASE + PROLSIZE; va += PAGE_SIZE) {
 
138
                map_page(l1, va, pa, 0, highbase);
 
139
                pa += PAGE_SIZE;
 
140
        }
 
141
 
 
142
        /* We need to start from LOADBASE, but kernel wants PAGE_SIZE. */
 
143
        pa = 0;
 
144
        for (va = 0; va < LOWMEMSZ; va += PAGE_SIZE) {
 
145
                map_page(l1, va, pa, 0, highbase);
 
146
                pa += PAGE_SIZE;
 
147
        }
 
148
 
 
149
        t->pctp = ctp;
 
150
        t->pl1 = l1;
 
151
        t->pbas = highbase;
 
152
}
 
153
 
 
154
/*
 
155
 * Create a memory mapping from va to epa in page table pgd.
 
156
 * highbase is used for v2p translation.
 
157
 */
 
158
int
 
159
map_page(unsigned int *pgd, unsigned int va,
 
160
    unsigned int epa, int type, unsigned int highbase)
 
161
{
 
162
        unsigned int pte;
 
163
        unsigned int *p;
 
164
        unsigned int pa;
 
165
 
 
166
        pte = pgd[((va)>>SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD-1)];
 
167
        if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
 
168
                p = mem_zalloc(&cmem, SRMMU_PTRS_PER_PMD*sizeof(int),
 
169
                    SRMMU_PTRS_PER_PMD*sizeof(int));
 
170
                if (p == 0) goto drop;
 
171
                pte = SRMMU_ET_PTD |
 
172
                    (((unsigned int)p - PROLBASE + highbase) >> 4);
 
173
                pgd[((va)>>SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD-1)] = pte;
 
174
                /* barrier() */
 
175
        }
 
176
 
 
177
        pa = ((pte & 0xFFFFFFF0) << 4);
 
178
        pa += (((va)>>SRMMU_PMD_SHIFT & (SRMMU_PTRS_PER_PMD-1)) << 2);
 
179
        pte = ld_bypass(pa);
 
180
        if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
 
181
                p = mem_zalloc(&cmem, SRMMU_PTRS_PER_PTE*sizeof(int),
 
182
                    SRMMU_PTRS_PER_PTE*sizeof(int));
 
183
                if (p == 0) goto drop;
 
184
                pte = SRMMU_ET_PTD |
 
185
                    (((unsigned int)p - PROLBASE + highbase) >> 4);
 
186
                st_bypass(pa, pte);
 
187
        }
 
188
 
 
189
        pa = ((pte & 0xFFFFFFF0) << 4);
 
190
        pa += (((va)>>PAGE_SHIFT & (SRMMU_PTRS_PER_PTE-1)) << 2);
 
191
 
 
192
        pte = SRMMU_ET_PTE | ((epa & PAGE_MASK) >> 4);
 
193
        if (type) {             /* I/O */
 
194
                pte |= SRMMU_REF;
 
195
                /* SRMMU cannot make Supervisor-only, but not exectutable */
 
196
                pte |= SRMMU_PRIV;
 
197
        } else {                /* memory */
 
198
                pte |= SRMMU_REF|SRMMU_CACHE;
 
199
                pte |= SRMMU_PRIV;              /* Supervisor only access */
 
200
        }
 
201
        st_bypass(pa, pte);
 
202
        return 0;
 
203
 
 
204
drop:
 
205
        return -1;
 
206
}
 
207
 
 
208
/*
 
209
 * Switch page tables.
 
210
 */
 
211
void
 
212
init_mmu_swift(unsigned int ctp_phy)
 
213
{
 
214
        unsigned int addr;
 
215
 
 
216
        /*
 
217
         * Flush cache
 
218
         */
 
219
        for (addr = 0; addr < 0x2000; addr += 0x10) {
 
220
                __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
 
221
                    "r" (addr), "i" (ASI_M_DATAC_TAG));
 
222
                __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
 
223
                    "r" (addr<<1), "i" (ASI_M_TXTC_TAG));
 
224
        }
 
225
 
 
226
        /*
 
227
         * Switch ctx table
 
228
         */
 
229
        ctp_phy >>= 4;
 
230
        /* printk("done flushing, switching to %x\n", ctp_phy); */
 
231
        __asm__ __volatile__ ("sta %0, [%1] %2\n\t" : :
 
232
            "r" (ctp_phy), "r" (AC_M_CTPR), "i" (ASI_M_MMUREGS));
 
233
 
 
234
        /*
 
235
         * Flush old page table references
 
236
         */
 
237
        __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
 
238
            "r" (0x400), "i" (ASI_M_FLUSH_PROBE) : "memory");
 
239
}
 
240
 
 
241
/*
 
242
 * add_timer, del_timer
 
243
 * This should go into sched.c, but we have it split for different archs.
 
244
 */
 
245
struct timer_list_head {
 
246
        struct timer_list *head, *tail;
 
247
};
 
248
 
 
249
static struct timer_list_head timers;           /* Anonymous heap of timers */
 
250
 
 
251
void add_timer(struct timer_list *timer) {
 
252
        struct timer_list *p;
 
253
        if (timer->prev != NULL || timer->next != NULL) {
 
254
                printk("bug: kernel timer added twice at 0x%x.\n",
 
255
                    __builtin_return_address(0));
 
256
                return;
 
257
        }
 
258
        if ((p = timers.tail) != NULL) {
 
259
                timer->prev = p;
 
260
                p->next = timer;
 
261
                timers.tail = timer;
 
262
        } else {
 
263
                timers.head = timer;
 
264
                timers.tail = timer;
 
265
        }
 
266
        return;
 
267
}
 
268
 
 
269
int del_timer(struct timer_list *timer) {
 
270
        struct timer_list *p;
 
271
        int ret;
 
272
 
 
273
        if (timers.head == timer) timers.head = timer->next;
 
274
        if (timers.tail == timer) timers.tail = timer->prev;
 
275
        if ((p = timer->prev) != NULL) p->next = timer->next;
 
276
        if ((p = timer->next) != NULL) p->prev = timer->prev;
 
277
        ret = timer->next != 0 || timer->prev != 0;
 
278
        timer->next = NULL;
 
279
        timer->prev = NULL;
 
280
        return ret;
 
281
}
 
282
 
 
283
void run_timers() {
 
284
        struct timer_list *p;
 
285
 
 
286
        p = timers.head;
 
287
        while (p != NULL) {
 
288
                if (p->expires < jiffies) {
 
289
                        del_timer(p);           /* XXX make nonstatic member */
 
290
                        (*p->function)(p->data);
 
291
                        p = timers.head;
 
292
                } else {
 
293
                        p = p->next;
 
294
                }
 
295
        }
 
296
}
 
297
 
 
298
/*
 
299
 * Allocate memory. This is reusable.
 
300
 */
 
301
void mem_init(struct mem *t, char *begin, char *limit)
 
302
{
 
303
        t->start = begin;
 
304
        t->uplim = limit;
 
305
        t->curp = begin;
 
306
}
 
307
 
 
308
void mem_fini(struct mem *t)
 
309
{
 
310
        t->curp = 0;
 
311
}
 
312
 
 
313
void *mem_alloc(struct mem *t, int size, int align)
 
314
{
 
315
        char *p;
 
316
 
 
317
        p = (char *)((((unsigned int)t->curp) + (align-1)) & ~(align-1));
 
318
        if (p >= t->uplim || p + size > t->uplim) return 0;
 
319
        t->curp = p + size;
 
320
        return p;
 
321
}
 
322
 
 
323
void *mem_zalloc(struct mem *t, int size, int align)
 
324
{
 
325
        char *p;
 
326
 
 
327
        if ((p = mem_alloc(t, size, align)) != 0) memset(p, 0, size);
 
328
        return p;
 
329
}
 
330
 
 
331
/*
 
332
 * Library functions
 
333
 */
 
334
void *memset(void *s, int c, size_t len)
 
335
{
 
336
        void *p = s;
 
337
 
 
338
        while (len--) {
 
339
                *(char *)s = c;
 
340
                s++;
 
341
        }
 
342
        return p;
 
343
}
 
344
 
 
345
void bcopy(const void *f, void *t, int len) {
 
346
        while (len--) {
 
347
                *(char *)t = *(char *)f;
 
348
                f++;
 
349
                t++;
 
350
        }
 
351
}
 
352
 
 
353
/* Comparison is 7-bit */
 
354
int bcmp(const void *s1, const void *s2, int len)
 
355
{
 
356
        int i;
 
357
        char ch;
 
358
 
 
359
        while (len--) {
 
360
                ch = *(char *)s1;
 
361
                i = ch - *(char *)s2;
 
362
                s1++;
 
363
                s2++;
 
364
                if (i != 0)
 
365
                        return i;
 
366
                if (ch == 0)
 
367
                        return 0;
 
368
        }
 
369
        return 0;
 
370
}
 
371
 
 
372
int strlen(const char *s) {
 
373
        const char *p;
 
374
        for (p = s; *p != 0; p++) { }
 
375
        return p - s;
 
376
}
 
377
 
 
378
extern void *printk_fn;
 
379
 
 
380
void printk(char *fmt, ...)
 
381
{
 
382
        struct prf_fp {
 
383
                void *xfp;
 
384
                void (*write)(void *, char *, int);
 
385
        } prfa;
 
386
        extern void prf(struct prf_fp *, char *fmt, va_list adx);
 
387
        va_list x1;
 
388
 
 
389
        va_start(x1, fmt);
 
390
        prfa.xfp = &dp0;
 
391
        prfa.write = printk_fn;
 
392
        prf(&prfa, fmt, x1);
 
393
        va_end(x1);
 
394
}
 
395
 
 
396
void fatal()
 
397
{
 
398
        printk("fatal.");
 
399
loop: goto loop;
 
400
}
 
401
 
 
402
/*
 
403
 * Get the highest bit number from the mask.
 
404
 */
 
405
int highc(int mask, int size)
 
406
{
 
407
        int m1;
 
408
 
 
409
        m1 = 1 << size;
 
410
        while (size != 0) {
 
411
                size--;
 
412
                m1 >>= 1;
 
413
                if (m1 & mask) break;
 
414
        }
 
415
        return size;
 
416
}
 
417
 
 
418
/*
 
419
 */
 
420
unsigned int ld_bp_swap(unsigned int ptr) {
 
421
        unsigned int n;
 
422
        n = ld_bypass(ptr);
 
423
        n = (n>>24 & 0xFF) | (n>>8 & 0xFF00) | ((n&0xFF00) << 8) | (n<<24);
 
424
        return n;
 
425
}
 
426
 
 
427
void st_bp_swap(unsigned int ptr, unsigned int n) {
 
428
        n = (n>>24 & 0xFF) | (n>>8 & 0xFF00) | ((n&0xFF00) << 8) | (n<<24);
 
429
        st_bypass(ptr, n);
 
430
};