Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / qemu-palcode / init.c
1 /* Initialization of the system and the HWRPB.
2
3    Copyright (C) 2011 Richard Henderson
4
5    This file is part of QEMU PALcode.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the text
15    of the GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; see the file COPYING.  If not see
19    <http://www.gnu.org/licenses/>.  */
20
21 #include <string.h>
22 #include <stddef.h>
23 #include "hwrpb.h"
24 #include "osf.h"
25 #include "ioport.h"
26 #include "uart.h"
27 #include "protos.h"
28 #include SYSTEM_H
29
30 #define PAGE_SHIFT      13
31 #define PAGE_SIZE       (1ul << PAGE_SHIFT)
32 #define PAGE_OFFSET     0xfffffc0000000000UL
33
34 #define VPTPTR          0xfffffffe00000000UL
35
36 #define PA(VA)          ((unsigned long)(VA) & 0xfffffffffful)
37 #define VA(PA)          ((void *)(PA) + PAGE_OFFSET)
38
39 #define HZ      1024
40
41 struct hwrpb_combine {
42   struct hwrpb_struct hwrpb;
43   struct percpu_struct processor;
44   struct memdesc_struct md;
45   struct memclust_struct mc[2];
46   struct crb_struct crb;
47   struct procdesc_struct proc_dispatch;
48   struct procdesc_struct proc_fixup;
49 };
50
51 extern char stack[PAGE_SIZE] __attribute__((section(".sbss")));
52 extern char _end[] __attribute__((visibility("hidden"), nocommon));
53
54 struct pcb_struct pcb __attribute__((section(".sbss")));
55
56 static unsigned long page_dir[1024]
57   __attribute__((aligned(PAGE_SIZE), section(".bss.page_dir")));
58
59 /* The HWRPB must be aligned because it is exported at INIT_HWRPB.  */
60 struct hwrpb_combine hwrpb __attribute__((aligned(PAGE_SIZE)));
61
62 void *last_alloc;
63 bool have_vga;
64
65 static void *
66 alloc (unsigned long size, unsigned long align)
67 {
68   void *p = (void *)(((unsigned long)last_alloc + align - 1) & ~(align - 1));
69   last_alloc = p + size;
70   return memset (p, 0, size);
71 }
72
73 static inline unsigned long
74 pt_index(unsigned long addr, int level)
75 {
76   return (addr >> (PAGE_SHIFT + (10 * level))) & 0x3ff;
77 }
78
79 static inline unsigned long
80 build_pte (void *page)
81 {
82   unsigned long bits;
83
84   bits = PA((unsigned long)page) << (32 - PAGE_SHIFT);
85   bits += _PAGE_VALID | _PAGE_KRE | _PAGE_KWE;
86
87   return bits;
88 }
89
90 static inline void *
91 pte_page (unsigned long pte)
92 {
93   return VA(pte >> 32 << PAGE_SHIFT);
94 }
95
96 static void
97 set_pte (unsigned long addr, void *page)
98 {
99   unsigned long *pt = page_dir;
100   unsigned long index;
101
102   index = pt_index(addr, 2);
103   if (pt[index] != 0)
104     pt = pte_page (pt[index]);
105   else
106     {
107       unsigned long *npt = alloc(PAGE_SIZE, PAGE_SIZE);
108       pt[index] = build_pte (npt);
109       pt = npt;
110     }
111
112   index = pt_index(addr, 1);
113   if (pt[index] != 0)
114     pt = pte_page (pt[index]);
115   else
116     {
117       unsigned long *npt = alloc(PAGE_SIZE, PAGE_SIZE);
118       pt[index] = build_pte (npt);
119       pt = npt;
120     }
121
122   index = pt_index(addr, 0);
123   pt[index] = build_pte (page);
124 }
125
126 static void
127 init_page_table(void)
128 {
129   /* Install the self-reference for the virtual page table base register.  */
130   page_dir[pt_index(VPTPTR, 2)] = build_pte(page_dir);
131
132   set_pte ((unsigned long)INIT_HWRPB, &hwrpb);
133   
134   /* ??? SRM maps some amount of memory at 0x20000000 for use by programs
135      started from the console prompt.  Including the bootloader.  While
136      we're emulating MILO, don't bother as we jump straight to the kernel
137      loaded into KSEG.  */
138 }
139
140 static void
141 init_hwrpb (unsigned long memsize)
142 {
143   unsigned long pal_pages;
144   unsigned long amask;
145   
146   hwrpb.hwrpb.phys_addr = PA(&hwrpb);
147
148   /* Yes, the 'HWRPB' magic is in big-endian byte ordering.  */
149   hwrpb.hwrpb.id = ( (long)'H' << 56
150                    | (long)'W' << 48
151                    | (long)'R' << 40
152                    | (long)'P' << 32
153                    | (long)'B' << 24);
154
155   hwrpb.hwrpb.size = sizeof(struct hwrpb_struct);
156
157   ((int *)hwrpb.hwrpb.ssn)[0] = ( 'Q' << 0
158                                 | 'E' << 8
159                                 | 'M' << 16
160                                 | 'U' << 24);
161
162   amask = ~__builtin_alpha_amask(-1);
163   switch (__builtin_alpha_implver())
164     {
165     case 0: /* EV4 */
166       hwrpb.hwrpb.cpuid = EV4_CPU;
167       hwrpb.hwrpb.max_asn = 63;
168       break;
169
170     case 1: /* EV5 */
171       hwrpb.hwrpb.cpuid
172         = ((amask & 0x101) == 0x101 ? PCA56_CPU         /* MAX+BWX */
173            : amask & 1 ? EV56_CPU                       /* BWX */
174            : EV5_CPU);
175       hwrpb.hwrpb.max_asn = 127;
176       break;
177
178     case 2: /* EV6 */
179       hwrpb.hwrpb.cpuid = (amask & 4 ? EV67_CPU : EV6_CPU);  /* CIX */
180       hwrpb.hwrpb.max_asn = 255;
181       break;
182     }
183
184   hwrpb.hwrpb.pagesize = PAGE_SIZE;
185   hwrpb.hwrpb.pa_bits = 40;
186   hwrpb.hwrpb.sys_type = SYS_TYPE;
187   hwrpb.hwrpb.sys_variation = SYS_VARIATION;
188   hwrpb.hwrpb.sys_revision = SYS_REVISION;
189   hwrpb.processor.type = hwrpb.hwrpb.cpuid;
190
191   hwrpb.hwrpb.intr_freq = HZ * 4096;
192   hwrpb.hwrpb.cycle_freq = 250000000;   /* QEMU architects 250MHz.  */
193
194   hwrpb.hwrpb.vptb = VPTPTR;
195
196   hwrpb.hwrpb.nr_processors = 1;
197   hwrpb.hwrpb.processor_size = sizeof(struct percpu_struct);
198   hwrpb.hwrpb.processor_offset = offsetof(struct hwrpb_combine, processor);
199
200   hwrpb.hwrpb.mddt_offset = offsetof(struct hwrpb_combine, md);
201   hwrpb.md.numclusters = 2;
202
203   pal_pages = (PA(last_alloc) + PAGE_SIZE - 1) >> PAGE_SHIFT;
204
205   hwrpb.mc[0].numpages = pal_pages;
206   hwrpb.mc[0].usage = 1;
207   hwrpb.mc[1].start_pfn = pal_pages;
208   hwrpb.mc[1].numpages = (memsize >> PAGE_SHIFT) - pal_pages;
209
210   hwrpb.hwrpb.crb_offset = offsetof(struct hwrpb_combine, crb);
211   hwrpb.crb.dispatch_va = &hwrpb.proc_dispatch;
212   hwrpb.crb.dispatch_pa = PA(&hwrpb.proc_dispatch);
213   hwrpb.crb.fixup_va = &hwrpb.proc_fixup;
214   hwrpb.crb.fixup_pa = PA(&hwrpb.proc_fixup);
215   hwrpb.crb.map_entries = 1;
216   hwrpb.crb.map_pages = 1;
217   hwrpb.crb.map[0].va = &hwrpb;
218   hwrpb.crb.map[0].pa = PA(&hwrpb);
219   hwrpb.crb.map[0].count = 1;
220
221   /* See crb.c for how we match the VMS calling conventions to Unix.  */
222   hwrpb.proc_dispatch.address = (unsigned long)crb_dispatch;
223   hwrpb.proc_fixup.address = (unsigned long)crb_fixup;
224
225   hwrpb_update_checksum(&hwrpb.hwrpb);
226 }
227
228 static void
229 init_pcb (void)
230 {
231   pcb.ksp = (unsigned long)stack + sizeof(stack);
232   pcb.ptbr = PA(page_dir) >> PAGE_SHIFT;
233   pcb.flags = 1; /* FEN */
234 }
235
236 static void
237 init_i8259 (void)
238 {
239   /* ??? MILO initializes the PIC as edge triggered; I do not know how SRM
240      initializes them.  However, Linux seems to expect that these are level
241      triggered.  That may be a kernel bug, but level triggers are more
242      reliable anyway so lets go with that.  */
243
244   /* Initialize the slave PIC.  */
245   outb(0x11, PORT_PIC2_CMD);    /* ICW1: edge trigger, cascade, ICW4 req */
246   outb(0x08, PORT_PIC2_DATA);   /* ICW2: irq offset = 8 */
247   outb(0x02, PORT_PIC2_DATA);   /* ICW3: slave ID 2 */
248   outb(0x01, PORT_PIC2_DATA);   /* ICW4: not special nested, normal eoi */
249
250   /* Initialize the master PIC.  */
251   outb(0x11, PORT_PIC1_CMD);    /* ICW1 */
252   outb(0x00, PORT_PIC1_DATA);   /* ICW2: irq offset = 0 */
253   outb(0x04, PORT_PIC1_DATA);   /* ICW3: slave control INTC2 */
254   outb(0x01, PORT_PIC1_DATA);   /* ICW4 */
255
256   /* Initialize level triggers.  The CY82C693UB that's on real alpha
257      hardware doesn't have this; this is a PIIX extension.  However,
258      QEMU doesn't implement regular level triggers.  */
259   outb(0xff, PORT_PIC2_ELCR);
260   outb(0xff, PORT_PIC1_ELCR);
261
262   /* Disable all interrupts.  */
263   outb(0xff, PORT_PIC2_DATA);
264   outb(0xff, PORT_PIC1_DATA);
265
266   /* Non-specific EOI, clearing anything the might be pending.  */
267   outb(0x20, PORT_PIC2_CMD);
268   outb(0x20, PORT_PIC1_CMD);
269 }
270
271 void
272 do_start(unsigned long memsize, void (*kernel_entry)(void), long cpus)
273 {
274   last_alloc = _end;
275
276   init_page_table();
277   init_hwrpb(memsize);
278   init_pcb();
279   init_i8259();
280   uart_init();
281   ps2port_setup();
282   pci_setup();
283   vgahw_init();
284
285   {
286     register int variant __asm__("$16") = 2;    /* OSF/1 PALcode */
287     register void (*pc)(void) __asm__("$17");
288     register unsigned long pa_pcb __asm__("$18");
289     register unsigned long vptptr __asm__("$19");
290
291     pc = (kernel_entry ? kernel_entry : do_console);
292     pa_pcb = PA(&pcb);
293     vptptr = VPTPTR;
294     asm("call_pal 0x0a" : : "r"(variant), "r"(pc), "r"(pa_pcb), "r"(vptptr));
295   }
296   __builtin_unreachable ();
297 }
298
299 void
300 do_start_wait(void)
301 {
302   while (1)
303     {
304       // WtInt with interrupts off.  Rely on the fact that QEMU will
305       // un-halt the CPU when an interrupt arrives.
306       asm("lda $16,-1\n\tcall_pal 0x3e" : : : "$0", "$16");
307
308       // FIXME do something with the IPI.
309     }
310 }