Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
  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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
/*
 *  mips/head.S
 *
 *  Copyright (C) 1994 Waldorf Electronics
 *  Written by Ralf Baechle and Andreas Busse
 *
 *  Head.S contains the MIPS exception handler and startup code.
 */

#undef DEBUGPICA /* undef this if you have a different system */

#include <linux/tasks.h>

#include <asm/segment.h>
#include <asm/cachectl.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
#include <asm/stackframe.h>
#include <asm/regdef.h>
#include <asm/bootinfo.h>
#include <asm/segment.h>

#define PAGE_SIZE	0x1000

/*
 * For now we can't enable write caching. This would cause trouble
 * with the page aliases used by the memory management.
 * The page table's aliases even have to be uncachable, but that
 * doesn't hurt much anyway.
 */
#define PAGE_TABLE	0x0580  /* uncachable */
#define PAGE_SHARED	0x0580  /* cachable, writethrough, no write allocate */
#define MODE_ALIAS	0x0016	/* uncachable */

		.globl	_empty_bad_page
		.globl	_empty_bad_page_table
		.globl	_pg0
		.globl	_empty_zero_page
		.globl	_tmp_floppy_area
		.globl	_floppy_track_buffer
		.globl	_swapper_pg_dir

		.text
		.globl	_kernelbase
_kernelbase:

/*
 * This is space for the interrupt handlers.
 * They are located at virtual address KSEG[01] (physical 0x0)
 */
		/*
		 * TLB refill, EXL == 0
		 */
		.set	noreorder
		.set	noat
except_vec0:
#if KERNELBASE == KSEG1
		la	k0,1f
		jr	k0
		nop
1:
#endif
		dmfc0	k1,CP0_CONTEXT
		dsra	k1,k1,1
		lwu	k0,(k1)			# May cause another exception
		lwu	k1,4(k1)
		dsrl	k0,k0,6			# Convert to EntryLo format
		dsrl	k1,k1,6			# Convert to EntryLo format
		dmtc0	k0,CP0_ENTRYLO0
		dmtc0	k1,CP0_ENTRYLO1
		tlbwr
		eret

		/*
		 * XTLB refill, EXL == 0
		 * Should never be reached
		 */
		.org	except_vec0+0x80
except_vec1:	
#if KERNELBASE == KSEG1
		la	k0,1f
		jr	k0
		nop
1:
#endif
		la	a0,xtlb_text
		jal	_panic
		nop
1:		j	1b
		nop
xtlb_text:	.asciz	"XTLB Refill exception.\n"

		/*
		 * Cache Error
		 */
		.org	except_vec1+0x80
except_vec2:
#if KERNELBASE == KSEG1
		la	k0,1f
		jr	k0
		nop
1:
#endif
		/*
		 * Should never be reached
		 */
		la	a0,xtlb_text
		jal	_panic
		nop
1:		j	1b
		nop
cache_text:	.asciz	"Cache error exception\n"

		/*
		 * General exception vector.
		 */
		.org	except_vec2+0x80
except_vec3:	/*
		 * Register saving is delayed as long as we don't know
		 * which registers really need to be saved.
		 */
#if KERNELBASE == KSEG1
		la	k0,1f
		jr	k0
		nop
1:
#endif
		.set	noat
		mfc0	k1,CP0_CAUSE
		la	k0,_exception_handlers
		/*
		 * Next lines assumes that the used CPU type has max.
		 * 32 different types of exceptions. We might use this
		 * to implement software exceptions in the future.
		 */
		andi	k1,k1,0x7c
		addu	k0,k0,k1
		lw	k0,(k0)
		FILL_LDS
		jr	k0
		nop

/******************************************************************************/

/*
 * Kernel entry
 */
		.set	noreorder
		.set	at
kernel_entry:
		jal	refill
		nop

		/*
		 * Clear BSS first so that there are no surprises...
		 */
		la	t0,__edata
		la	t1,__end
		sw	zero,(t0)
1:		addiu	t0,t0,4
		bnel	t0,t1,1b
		sw	zero,(t0)

#ifdef DEBUGPICA
		la      t0,_boot_info
		lw      t0,OFFSET_BOOTINFO_VRAM_BASE(t0)
		li      t1,0x0f00 + '3'
		sh      t1,4(t0)
#endif

		.set	noreorder
		jal	_tlbflush
		mtc0	zero,CP0_WIRED
		/*
		 * Spread some mines...
		 */
		la	t0,_end
		la	t1,0x003ffffc
		la	t2,KERNELBASE
		or	t1,t2
		li	t2,0xdeadbeef
1:		sw	t2,(t0)
		bne	t0,t1,1b
		addiu	t0,t0,4
		/*
		 * Initialize memory management, map lowest 4MB
		 */
		.set	reorder
		jal	setup_paging
#if KERNELBASE == KSEG0
		jal	_sys_cacheflush
#endif

#ifdef DEBUGPICA
		la      t0,_boot_info
		lw      t0,OFFSET_BOOTINFO_VRAM_BASE(t0)
		li      t1,0x0f00 + '4'
		sh      t1,6(t0)
#endif
		/*
		 * Stack for kernel and init
		 */
		la	sp,_init_user_stack+PAGE_SIZE-24
		sw	sp,_kernelsp

1:		jal	_start_kernel
		/*
		 * Main should never return here, but
		 * just in case, we know what happens.
		 */
		j	1b

/*
 * Setup_paging
 *
 * Wire mappings for page_tables.
 * The page tables are set up, identity-mapping
 * the first 4MB.  The rest are initialized later.
 */
		.set	noreorder
setup_paging:
		/*
 		 * get base address of map0 table for the
		 * the board we're running on
		 */
		la	t0,_boot_info
		lw	t1,OFFSET_BOOTINFO_MACHTYPE(t0)
		sll	t1,t1,2			# machtype used as index
		la	t0,map0table
		addu	t0,t0,t1
		lw	t0,(t0)			# get base address

		/*
		 * Get number of wired TLB entries and
		 * loop over selected map0 table.
		 */
		lw	t1,(t0)			# number of wired TLB entries
		move	t2,zero			# TLB entry counter
		addiu	t3,t1,1			# wire one additional entry
		beqz	t1,2f			# null, exit
		mtc0	t3,CP0_WIRED		# delay slot
		addiu	t0,t0,8
1:		lw	t4,24(t0)		# PageMask
		ld	t5,0(t0)		# entryHi
		ld	t6,8(t0)		# entryLo0
		ld	t7,16(t0)		# entryLo1
		addiu	t2,t2,1			# increment ctr
		mtc0	t2,CP0_INDEX		# set TLB entry
		mtc0	t4,CP0_PAGEMASK
		dmtc0	t5,CP0_ENTRYHI
		dmtc0	t6,CP0_ENTRYLO0
		dmtc0	t7,CP0_ENTRYLO1
 		tlbwi 
		bne	t1,t2,1b		# next TLB entry
		addiu	t0,t0,32		# delay slot

		/*
		 * We use only 4k pages. Therefore the PageMask register
		 * is expected to be setup for 4k pages.
		 */
2:		li	t0,PM_4K
		mtc0	t0,CP0_PAGEMASK

		la	t1,_swapper_pg_dir	# swapper_pg_dir is at 0x1000
		la	t2,_swapper_pg_dir+(PAGE_SIZE-4)
1:		sw	zero,(t1)
		bne	t1,t2,1b
		addiu	t1,t1,4			# delay slot

		/*
		 * Setup invalid_pg_table and
		 * clear page table for the first 4MB
		 */
		la	t0,_pg0			# swapper_pg_dir is at 0x1000
		la	t1,_pg0+PAGE_SIZE
		li	t2,KERNELBASE
		addu	t0,t2
		addu	t1,t2
1:		sw	zero,(t0)
		addiu	t0,t0,4
		bne	t0,t1,1b
		addiu	t2,t2,4			# delay slot

		/*
		 * Identity-map the kernel in low 4MB memory for ease
		 * of transition. Unlike the Intel version the kernel
		 * code/data is automagically being mapped by kseg0.
		 */
		la	t0,_pg0+PAGE_TABLE	# set valid bit/user r/w
		sw	t0,_swapper_pg_dir

		li	t0,PAGE_SHARED		# set valid bit/user r/w
		la	t1,_pg0
		la	t2,_pg0+PAGE_SIZE
		li	t3,KERNELBASE
		addu	t1,t3
		addu	t2,t3
1:		sw	t0,(t1)
		addiu	t1,t1,4
		bne	t1,t2,1b
		addiu	t0,t0,PAGE_SIZE		# delay slot

		/*
		 * Now map the pagetables
		 */
		mtc0	zero,CP0_INDEX
		la	t0,TLB_ROOT
		dmtc0	t0,CP0_ENTRYHI
		la	t0,_swapper_pg_dir
		srl	t0,t0,6
		ori	t0,t0,MODE_ALIAS	# uncachable, dirty, valid
		dmtc0	t0,CP0_ENTRYLO0
		dmtc0	zero,CP0_ENTRYLO1
		tlbwi
		/*
		 * Make page zero unaccessible to catch zero references
		 */
		la	t0,_pg0
		li	t0,KERNELBASE
		addu	t0,t1
		sw	zero,(t0)
		/*
		 * Load the context register with a value that allows
		 * it to be used as fast as possible in tlb exceptions.
		 * It is expected that this register's content never
		 * will be changed.
		 */
		li	t0,TLBMAP
		dsll	t0,t0,1
		jr	ra
		dmtc0	t0,CP0_CONTEXT		# delay slot

		/*
		 * Flush the TLB
		 *
		 * FIXME: knows only how to handle R4x00
		 * Read appendix f of the R4000 manual before you change
		 * something!
		 */
		.globl	_tlbflush
_tlbflush:	li	t0,PM_4K
		mtc0	t0,CP0_PAGEMASK
		lw	t0,_boot_info+OFFSET_BOOTINFO_TLB_ENTRIES(t0)
		dmtc0	zero,CP0_ENTRYLO0
		dmtc0	zero,CP0_ENTRYLO1
		mfc0	t2,CP0_WIRED
1:		subu	t0,t0,1
		mtc0	t0,CP0_INDEX
		lui	t1,0x0008
		or	t1,t0,t1
		dsll	t1,t1,13
		dmtc0	t1,CP0_ENTRYHI
		bne	t2,t0,1b
		tlbwi					# delay slot
		jr	ra
		nop

/*
 * Refill icache
 */
#include <asm/mipsconfig.h>
#include <asm/regdef.h>
#include <asm/segment.h>

#define PAGE_SIZE	0x1000

#define CACHELINES	512             /* number of cachelines    */

		.set	noreorder
		.text
refill:
		/*
		 * Refill icache with cache fill command
		 */
		li	t0,KSEG0
		li	t1,CACHELINES
1:		cache	21,0(t0)
		cache	21,32(t0)
		cache	21,64(t0)
		cache	21,96(t0)
		cache	21,128(t0)
		cache	21,160(t0)
		cache	21,192(t0)
		cache	21,224(t0)
		cache	21,256(t0)
		cache	21,288(t0)
		cache	21,320(t0)
		cache	21,352(t0)
		cache	21,384(t0)
		cache	21,416(t0)
		cache	21,448(t0)
		cache	21,480(t0)
		subu    t1,t1,1
		bnez	t1,1b
		addiu	t0,t0,512			# delay slot

		jr	ra
		nop

/*
 * Just for debugging...
 */
		.globl	_beep
_beep:		lw	t0,beepflag
		nop
		bnez	t0,1f
		lbu	t0,0xe0000061
		xori	t0,t0,3
		sb	t0,0xe0000061
		li	t0,1
		sw	t0,beepflag
1:		jr	ra
		nop

/*
 * Compute kernel code checksum to check kernel code against corruption
 */
		.globl	_csum
#if 0
_csum:		jal	_sys_cacheflush
		move	t8,ra			# delay slot
#else
_csum:		move	t8,ra
#endif
		li	t0,KSEG1
		la	t1,final
		li	t2,KSEG1
		or	t0,t2
		or	t1,t2
		move	v0,zero
1:		lw	t2,(t0)
		addiu	t0,t0,4
		bne	t0,t1,1b
		xor	v0,v0,t2
		jr	t8
		nop
final:

		.data
/*
 * Instead of Intel's strange and unportable segment descriptor magic
 * we difference user and kernel space by their address.
 * Kernel space (== physical memory) is mapped at KSEG[01],
 * User space is mapped at 0x0.
 */
		.globl	_segment_fs
_segment_fs:	.word	KERNEL_DS

/*
 * Initial mapping tables for supported Mips boards.
 * First item is always the number of wired TLB entries,
 * following by EntryHi/EntryLo pairs and page mask.
 * Since everything must be quad-aligned (8) we insert
 * some dummy zeros.
 */

/*
 * Address table of mapping tables for supported Mips boards.
 * Add your own stuff here but don't forget to define your
 * target system in bootinfo.h
 */

map0table:	.word	map0_dummy		# machtype = unknown
		.word	map0_tyne		# Deskstation Tyne
		.word	map0_pica61		# Acer Pica-61

map0_dummy:	.word	0			# 0 entries

/*
 * Initial mappings for Deskstation Tyne boards.
 */
		.align  8

map0_tyne: 	.word   3			# no. of wired TLB entries
		.word	0			# pad for alignment

# TLB entry 1: ISA I/O

		.quad	0xffffffffe0000000	# TLB #0 EntryHi
		.quad   0x24000017		# TLB #0 EntryLo0
		.quad	0			# TLB #0 EntryLo1
		.word   PM_64K			# page mask
		.word   0			# pad for alignment

# TLB entry 2: ISA memory space

		.quad	0xffffffffe1000000	# TLB #1 EntryHi
		.quad   0x04000017		# TLB #1 EntryLo0
		.quad	0			# TLB #1 EntryLo1
		.word   PM_1M
		.word	0			# pad for alignment

# TLB entry 3: ISA DMA cache

		.quad	0xffffffffe2000000	# TLB #2 EntryHi
		.quad 	0x04020017		# TLB #2 EntryLo0
		.quad	0			# TLB #2 EntryLo1
		.word	PM_1M
		.word 	0			# pad for alignment

/*
 * Initial mapping for ACER PICA-61 boards.
 * FIXME: These are rather preliminary since many drivers,
 * such as serial, parallel, scsi and ethernet need some
 * changes to distinguish between "local" (built-in) and
 * "optional" (ISA/PCI) I/O hardware.
 * Local video ram is mapped to the same location as the
 * bios maps it to. Console driver has been changed
 * accordingly (new video type: VIDEO_TYPE_PICA_S3).
 */

map0_pica61:	.word  	9			# no. wired TLB entries
		.word	0			# dummy

# TLB entry 1: PROM

#		.quad	0xffffffffe1000000	# BIOS mapping
		.quad	0xffffffffe4000000	# new mapping
		.quad	0x03ffc013
		.quad	0x00000001		# global, not valid
		.word	PM_256K
		.word	0

# TLB entry 2: local I/O space

		.quad   0xffffffffe0000000
		.quad 	0x02000017
		.quad	0x00000001		# global, not valid
		.word	PM_64K
		.word	0

# TLB entry 3: DRAM config register

		.quad	0xffffffffe00e0000
		.quad	0x02003817
		.quad	0x02003c17
		.word	PM_64K
		.word	0

# TLB entry 4: Interrupt source register

		.quad	0xffffffffe0100000
		.quad	0x03c00017
		.quad	0x00000001		# global, not valid
		.word	PM_4K
		.word	0

# TLB entry 5: Local video control

		.quad	0xffffffffe0200000
		.quad	0x01800017
		.quad	0x01804017
		.word	PM_1M
		.word	0

# TLB entry 6: Extended video control

		.quad	0xffffffffe0400000
		.quad	0x01808017
		.quad	0x0180c017
		.word	PM_1M
		.word	0

# TLB entry 7: Local video memory (BIOS mapping)

		.quad	0xffffffffe0800000
		.quad	0x01000017
		.quad	0x01010017
		.word   PM_4M
		.word	0

# TLB entry 8: Local video memory (mapped to where Linux expects it)
# not needed anymore
#		.quad	0xffffffffe1000000
#		.quad	0x01000017
#		.quad	0x01010017
#		.word   PM_4M
#		.word	0

# TLB entry 9: ISA I/O and ISA memory space (both 16M)

		.quad	0xffffffffe2000000
		.quad	0x02400017
		.quad	0x02440017
		.word	PM_16M
		.word	0

# TLB entry 10: PCR (???)

		.quad	0xffffffffffffe000
		.quad	0x00000001		# nonsense...
		.quad	0x0001ffd7
		.word	PM_4K
		.word	0


/* ------------------------------------------------
 * Mapping as presented by the PICA BIOS.
 * This table works. Please leave unmodified!
 * ------------------------------------------------ */
#if 0
map0_pica61:	.word	11			# no. wired TLB entries
		.word	0			# dummy

# TLB entry 0: Don't know what this is good for...

		.quad	0xfffffffffffe2000
		.quad	0x0000029e
		.quad	0x00000000
		.word	PM_4K
		.word	0

# TLB entry 1: PROM

		.quad	0xffffffffe1000000
		.quad	0x03ffc013
		.quad	0x00000001		# nonsense ...
		.word	PM_256K
		.word	0

# TLB entry 2: local I/O space

		.quad   0xffffffffe0000000
		.quad 	0x02000017
		.quad	0x00000001		# nonsense ...
		.word	PM_64K
		.word	0

# TLB entry 3: DRAM config register

		.quad	0xffffffffe00e0000
		.quad	0x02003817
		.quad	0x02003c17
		.word	PM_64K
		.word	0

# TLB entry 4: Interrupt source register

		.quad	0xffffffffe0100000
		.quad	0x03c00017
		.quad	0x00000001		# nonsense ...
		.word	PM_4K
		.word	0

# TLB entry 5: Local video control

		.quad	0xffffffffe0200000
		.quad	0x01800017
		.quad	0x01804017
		.word	PM_1M
		.word	0

# TLB entry 6: Extended video control

		.quad	0xffffffffe0400000
		.quad	0x01808017
		.quad	0x0180c017
		.word	PM_1M
		.word	0

# TLB entry 7: Local video memory

		.quad	0xffffffffe0800000
		.quad	0x01000017
		.quad	0x01010017
		.word   PM_4M
		.word	0

# TLB entry 8: ISA I/O space

		.quad	0xffffffffe2000000
		.quad	0x02400017
		.quad	0x02440017
		.word	PM_16M
		.word	0

# TLB entry 9: PCR (???)

		.quad	0xffffffffffffe000
		.quad	0x00000001		# nonsense...
		.quad	0x0001ffd7
		.word	PM_4K
		.word	0

# TLB entry 10: Extended video prom

		.quad	0xffffffff10000000
		.quad	0x0000141f
		.quad	0x00000001		# nonsense
		.word   PM_64K
		.word	0
#endif

/*
 * page 0 is made non-existent, so that kernel NULL pointer references get
 * caught. Thus the swapper page directory has been moved to 0x1000
 *
 * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte,
 * with the introduction of the compressed boot code.  Theoretically,
 * the original design of overlaying the startup code with the swapper
 * page directory is still possible --- it would reduce the size of the kernel
 * by 2-3k.  This would be a good thing to do at some point.....
 */
			.text

			.org	0x1000
_swapper_pg_dir		=	0x1000
/*
 * The page tables are initialized to only 4MB here - the final page
 * tables are set up later depending on memory size.
 */
			.org	0x2000
_pg0			=	0x2000

			.org	0x3000
_empty_bad_page		=	0x3000

			.org	0x4000
_empty_bad_page_table	=	0x4000

			.org	0x5000
_empty_zero_page	=	0x5000

			.org	0x6000

/*
 * tmp_floppy_area is used by the floppy-driver when DMA cannot
 * reach to a buffer-block. It needs to be aligned, so that it isn't
 * on a 64kB border.
 */
_tmp_floppy_area:	.fill	1024,1,0
/*
 * floppy_track_buffer is used to buffer one track of floppy data: it
 * has to be separate from the tmp_floppy area, as otherwise a single-
 * sector read/write can mess it up. It can contain one full cylinder (sic) of
 * data (36*2*512 bytes).
 */
_floppy_track_buffer:	.fill	512*2*36,1,0
			.globl	_kernelsp
_kernelsp:		.word	0
beepflag:		.word	0