forked from cores/microwatt
				
			
						commit
						da4be71bd3
					
				@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					TEST=modes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include ../Makefile.test
 | 
				
			||||||
@ -0,0 +1,232 @@
 | 
				
			|||||||
 | 
					/* Copyright 2013-2014 IBM Corp.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
				
			||||||
 | 
					 * implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Load an immediate 64-bit value into a register */
 | 
				
			||||||
 | 
					#define LOAD_IMM64(r, e)			\
 | 
				
			||||||
 | 
						lis     r,(e)@highest;			\
 | 
				
			||||||
 | 
						ori     r,r,(e)@higher;			\
 | 
				
			||||||
 | 
						rldicr  r,r, 32, 31;			\
 | 
				
			||||||
 | 
						oris    r,r, (e)@h;			\
 | 
				
			||||||
 | 
						ori     r,r, (e)@l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.section ".head","ax"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Microwatt currently enters in LE mode at 0x0, so we don't need to
 | 
				
			||||||
 | 
						 * do any endian fix ups
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						. = 0
 | 
				
			||||||
 | 
					.global _start
 | 
				
			||||||
 | 
					_start:
 | 
				
			||||||
 | 
						LOAD_IMM64(%r10,__bss_start)
 | 
				
			||||||
 | 
						LOAD_IMM64(%r11,__bss_end)
 | 
				
			||||||
 | 
						subf	%r11,%r10,%r11
 | 
				
			||||||
 | 
						addi	%r11,%r11,63
 | 
				
			||||||
 | 
						srdi.	%r11,%r11,6
 | 
				
			||||||
 | 
						beq	2f
 | 
				
			||||||
 | 
						mtctr	%r11
 | 
				
			||||||
 | 
					1:	dcbz	0,%r10
 | 
				
			||||||
 | 
						addi	%r10,%r10,64
 | 
				
			||||||
 | 
						bdnz	1b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2:	LOAD_IMM64(%r1,__stack_top)
 | 
				
			||||||
 | 
						li	%r0,0
 | 
				
			||||||
 | 
						stdu	%r0,-16(%r1)
 | 
				
			||||||
 | 
						mtsprg2	%r0
 | 
				
			||||||
 | 
						LOAD_IMM64(%r12, main)
 | 
				
			||||||
 | 
						mtctr	%r12
 | 
				
			||||||
 | 
						bctrl
 | 
				
			||||||
 | 
						attn // terminate on exit
 | 
				
			||||||
 | 
						b .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exception:
 | 
				
			||||||
 | 
						mfsprg2	%r0
 | 
				
			||||||
 | 
						cmpdi	%r0,0
 | 
				
			||||||
 | 
						bne	call_ret
 | 
				
			||||||
 | 
						attn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EXCEPTION(nr)		\
 | 
				
			||||||
 | 
						.= nr			;\
 | 
				
			||||||
 | 
						li	%r3,nr		;\
 | 
				
			||||||
 | 
						b	exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						EXCEPTION(0x300)
 | 
				
			||||||
 | 
						EXCEPTION(0x380)
 | 
				
			||||||
 | 
						EXCEPTION(0x400)
 | 
				
			||||||
 | 
						EXCEPTION(0x480)
 | 
				
			||||||
 | 
						EXCEPTION(0x500)
 | 
				
			||||||
 | 
						EXCEPTION(0x600)
 | 
				
			||||||
 | 
						EXCEPTION(0x700)
 | 
				
			||||||
 | 
						EXCEPTION(0x800)
 | 
				
			||||||
 | 
						EXCEPTION(0x900)
 | 
				
			||||||
 | 
						EXCEPTION(0x980)
 | 
				
			||||||
 | 
						EXCEPTION(0xa00)
 | 
				
			||||||
 | 
						EXCEPTION(0xb00)
 | 
				
			||||||
 | 
						EXCEPTION(0xd00)
 | 
				
			||||||
 | 
						EXCEPTION(0xe00)
 | 
				
			||||||
 | 
						EXCEPTION(0xe20)
 | 
				
			||||||
 | 
						EXCEPTION(0xe40)
 | 
				
			||||||
 | 
						EXCEPTION(0xe60)
 | 
				
			||||||
 | 
						EXCEPTION(0xe80)
 | 
				
			||||||
 | 
						EXCEPTION(0xf00)
 | 
				
			||||||
 | 
						EXCEPTION(0xf20)
 | 
				
			||||||
 | 
						EXCEPTION(0xf40)
 | 
				
			||||||
 | 
						EXCEPTION(0xf60)
 | 
				
			||||||
 | 
						EXCEPTION(0xf80)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						. = 0x1000
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * This page gets mapped at various locations and
 | 
				
			||||||
 | 
						 * the tests try to execute from it.
 | 
				
			||||||
 | 
						 * r3 contains the test number.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						.globl	test_code
 | 
				
			||||||
 | 
					test_code:
 | 
				
			||||||
 | 
						nop
 | 
				
			||||||
 | 
						nop
 | 
				
			||||||
 | 
						mflr	%r9
 | 
				
			||||||
 | 
						cmpdi	%r3,1
 | 
				
			||||||
 | 
						beq	test_1
 | 
				
			||||||
 | 
						cmpdi	%r3,2
 | 
				
			||||||
 | 
						beq	test_2
 | 
				
			||||||
 | 
						cmpdi	%r3,3
 | 
				
			||||||
 | 
						beq	test_3
 | 
				
			||||||
 | 
						li	%r3,0
 | 
				
			||||||
 | 
						blr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* test a doubleword load from memory */
 | 
				
			||||||
 | 
					test_1:	ld	%r3,0(%r4)
 | 
				
			||||||
 | 
						blr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* test a branch from the page at fffff000 */
 | 
				
			||||||
 | 
					test_2:
 | 
				
			||||||
 | 
						b	test_2a + 0x1000
 | 
				
			||||||
 | 
					test_2a:
 | 
				
			||||||
 | 
						b	test_2b - 0x1000
 | 
				
			||||||
 | 
					test_2b:
 | 
				
			||||||
 | 
						beq	test_2c + 0x1000
 | 
				
			||||||
 | 
					test_2c:
 | 
				
			||||||
 | 
						beq	test_2d - 0x1000
 | 
				
			||||||
 | 
					test_2d:
 | 
				
			||||||
 | 
						li	%r3,0
 | 
				
			||||||
 | 
						blr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_return:
 | 
				
			||||||
 | 
						mflr	%r3
 | 
				
			||||||
 | 
						mtlr	%r9
 | 
				
			||||||
 | 
						blr
 | 
				
			||||||
 | 
						. = 0x1ffc
 | 
				
			||||||
 | 
						/* test a branch with link from the 4G-4 address */
 | 
				
			||||||
 | 
					test_3:	bl	test_return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.globl	test_code_end
 | 
				
			||||||
 | 
					test_code_end:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						. = 0x2000
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Call a function in a context with a given MSR value.
 | 
				
			||||||
 | 
						 * r3, r4 = args; r5 = function; r6 = MSR
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						.globl	callit
 | 
				
			||||||
 | 
					callit:
 | 
				
			||||||
 | 
						mflr	%r0
 | 
				
			||||||
 | 
						std	%r0,16(%r1)
 | 
				
			||||||
 | 
						stdu	%r1,-256(%r1)
 | 
				
			||||||
 | 
						mfcr	%r8
 | 
				
			||||||
 | 
						stw	%r8,100(%r1)
 | 
				
			||||||
 | 
						std	%r13,104(%r1)
 | 
				
			||||||
 | 
						std	%r14,112(%r1)
 | 
				
			||||||
 | 
						std	%r15,120(%r1)
 | 
				
			||||||
 | 
						std	%r16,128(%r1)
 | 
				
			||||||
 | 
						std	%r17,136(%r1)
 | 
				
			||||||
 | 
						std	%r18,144(%r1)
 | 
				
			||||||
 | 
						std	%r19,152(%r1)
 | 
				
			||||||
 | 
						std	%r20,160(%r1)
 | 
				
			||||||
 | 
						std	%r21,168(%r1)
 | 
				
			||||||
 | 
						std	%r22,176(%r1)
 | 
				
			||||||
 | 
						std	%r23,184(%r1)
 | 
				
			||||||
 | 
						std	%r24,192(%r1)
 | 
				
			||||||
 | 
						std	%r25,200(%r1)
 | 
				
			||||||
 | 
						std	%r26,208(%r1)
 | 
				
			||||||
 | 
						std	%r27,216(%r1)
 | 
				
			||||||
 | 
						std	%r28,224(%r1)
 | 
				
			||||||
 | 
						std	%r29,232(%r1)
 | 
				
			||||||
 | 
						std	%r30,240(%r1)
 | 
				
			||||||
 | 
						std	%r31,248(%r1)
 | 
				
			||||||
 | 
						li	%r0,restore@l
 | 
				
			||||||
 | 
						mtsprg0	%r0
 | 
				
			||||||
 | 
						mtsprg1	%r1
 | 
				
			||||||
 | 
						mtsprg2	%r2
 | 
				
			||||||
 | 
						mfmsr	%r9
 | 
				
			||||||
 | 
						mtsprg3	%r9
 | 
				
			||||||
 | 
						li	%r10,call_ret@l
 | 
				
			||||||
 | 
						mtlr	%r10
 | 
				
			||||||
 | 
						mtsrr0	%r5
 | 
				
			||||||
 | 
						mtsrr1	%r6
 | 
				
			||||||
 | 
						mr	%r12,%r5
 | 
				
			||||||
 | 
						rfid
 | 
				
			||||||
 | 
					call_ret:
 | 
				
			||||||
 | 
						tdi	0,%r0,0x48	/* b .+8 if wrong endian */
 | 
				
			||||||
 | 
						b	2f		/* if endian OK */
 | 
				
			||||||
 | 
						/* reverse-endian version of instructions from 2: on */
 | 
				
			||||||
 | 
						.long	0xa642107c
 | 
				
			||||||
 | 
						.long	0xa642937c
 | 
				
			||||||
 | 
						.long	0xa602ba7c
 | 
				
			||||||
 | 
						.long	0xa602db7c
 | 
				
			||||||
 | 
						.long	0xa643b07c
 | 
				
			||||||
 | 
						.long	0xa643d37c
 | 
				
			||||||
 | 
						.long	0xa6031a7c
 | 
				
			||||||
 | 
						.long	0xa6039b7c
 | 
				
			||||||
 | 
						.long	0x2400004c
 | 
				
			||||||
 | 
					2:	mfsprg0	%r0
 | 
				
			||||||
 | 
						mfsprg3	%r4
 | 
				
			||||||
 | 
						mfsrr0	%r5
 | 
				
			||||||
 | 
						mfsrr1	%r6
 | 
				
			||||||
 | 
						mtsprg0	%r5
 | 
				
			||||||
 | 
						mtsprg3	%r6
 | 
				
			||||||
 | 
						mtsrr0	%r0
 | 
				
			||||||
 | 
						mtsrr1	%r4
 | 
				
			||||||
 | 
						rfid
 | 
				
			||||||
 | 
					restore:
 | 
				
			||||||
 | 
						mfsprg1	%r1
 | 
				
			||||||
 | 
						mfsprg2	%r2
 | 
				
			||||||
 | 
						li	%r7,0
 | 
				
			||||||
 | 
						mtsprg2	%r7
 | 
				
			||||||
 | 
						lwz	%r8,100(%r1)
 | 
				
			||||||
 | 
						mtcr	%r8
 | 
				
			||||||
 | 
						ld	%r13,104(%r1)
 | 
				
			||||||
 | 
						ld	%r14,112(%r1)
 | 
				
			||||||
 | 
						ld	%r15,120(%r1)
 | 
				
			||||||
 | 
						ld	%r16,128(%r1)
 | 
				
			||||||
 | 
						ld	%r17,136(%r1)
 | 
				
			||||||
 | 
						ld	%r18,144(%r1)
 | 
				
			||||||
 | 
						ld	%r19,152(%r1)
 | 
				
			||||||
 | 
						ld	%r20,160(%r1)
 | 
				
			||||||
 | 
						ld	%r21,168(%r1)
 | 
				
			||||||
 | 
						ld	%r22,176(%r1)
 | 
				
			||||||
 | 
						ld	%r23,184(%r1)
 | 
				
			||||||
 | 
						ld	%r24,192(%r1)
 | 
				
			||||||
 | 
						ld	%r25,200(%r1)
 | 
				
			||||||
 | 
						ld	%r26,208(%r1)
 | 
				
			||||||
 | 
						ld	%r27,216(%r1)
 | 
				
			||||||
 | 
						ld	%r28,224(%r1)
 | 
				
			||||||
 | 
						ld	%r29,232(%r1)
 | 
				
			||||||
 | 
						ld	%r30,240(%r1)
 | 
				
			||||||
 | 
						ld	%r31,248(%r1)
 | 
				
			||||||
 | 
						addi	%r1,%r1,256
 | 
				
			||||||
 | 
						ld	%r0,16(%r1)
 | 
				
			||||||
 | 
						mtlr	%r0
 | 
				
			||||||
 | 
						blr
 | 
				
			||||||
@ -0,0 +1,339 @@
 | 
				
			|||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "console.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MSR_LE	0x1
 | 
				
			||||||
 | 
					#define MSR_DR	0x10
 | 
				
			||||||
 | 
					#define MSR_IR	0x20
 | 
				
			||||||
 | 
					#define MSR_SF	0x8000000000000000ul
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern unsigned long callit(unsigned long arg1, unsigned long arg2,
 | 
				
			||||||
 | 
								    unsigned long fn, unsigned long msr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void do_tlbie(unsigned long rb, unsigned long rs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__asm__ volatile("tlbie %0,%1" : : "r" (rb), "r" (rs) : "memory");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DSISR	18
 | 
				
			||||||
 | 
					#define DAR	19
 | 
				
			||||||
 | 
					#define SRR0	26
 | 
				
			||||||
 | 
					#define SRR1	27
 | 
				
			||||||
 | 
					#define PID	48
 | 
				
			||||||
 | 
					#define SPRG0	272
 | 
				
			||||||
 | 
					#define SPRG1	273
 | 
				
			||||||
 | 
					#define PRTBL	720
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned long mfspr(int sprnum)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						long val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__asm__ volatile("mfspr %0,%1" : "=r" (val) : "i" (sprnum));
 | 
				
			||||||
 | 
						return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void mtspr(int sprnum, unsigned long val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__asm__ volatile("mtspr %0,%1" : : "i" (sprnum), "r" (val));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void store_pte(unsigned long *p, unsigned long pte)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__asm__ volatile("stdbrx %1,0,%0" : : "r" (p), "r" (pte) : "memory");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void print_string(const char *str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						for (; *str; ++str)
 | 
				
			||||||
 | 
							putchar(*str);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void print_hex(unsigned long val, int ndigit)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = (ndigit - 1) * 4; i >= 0; i -= 4) {
 | 
				
			||||||
 | 
							x = (val >> i) & 0xf;
 | 
				
			||||||
 | 
							if (x >= 10)
 | 
				
			||||||
 | 
								putchar(x + 'a' - 10);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								putchar(x + '0');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// i < 100
 | 
				
			||||||
 | 
					void print_test_number(int i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						print_string("test ");
 | 
				
			||||||
 | 
						putchar(48 + i/10);
 | 
				
			||||||
 | 
						putchar(48 + i%10);
 | 
				
			||||||
 | 
						putchar(':');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CACHE_LINE_SIZE	64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void zero_memory(void *ptr, unsigned long nbytes)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long nb, i, nl;
 | 
				
			||||||
 | 
						void *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (; nbytes != 0; nbytes -= nb, ptr += nb) {
 | 
				
			||||||
 | 
							nb = -((unsigned long)ptr) & (CACHE_LINE_SIZE - 1);
 | 
				
			||||||
 | 
							if (nb == 0 && nbytes >= CACHE_LINE_SIZE) {
 | 
				
			||||||
 | 
								nl = nbytes / CACHE_LINE_SIZE;
 | 
				
			||||||
 | 
								p = ptr;
 | 
				
			||||||
 | 
								for (i = 0; i < nl; ++i) {
 | 
				
			||||||
 | 
									__asm__ volatile("dcbz 0,%0" : : "r" (p) : "memory");
 | 
				
			||||||
 | 
									p += CACHE_LINE_SIZE;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								nb = nl * CACHE_LINE_SIZE;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (nb > nbytes)
 | 
				
			||||||
 | 
									nb = nbytes;
 | 
				
			||||||
 | 
								for (i = 0; i < nb; ++i)
 | 
				
			||||||
 | 
									((unsigned char *)ptr)[i] = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PERM_EX		0x001
 | 
				
			||||||
 | 
					#define PERM_WR		0x002
 | 
				
			||||||
 | 
					#define PERM_RD		0x004
 | 
				
			||||||
 | 
					#define PERM_PRIV	0x008
 | 
				
			||||||
 | 
					#define ATTR_NC		0x020
 | 
				
			||||||
 | 
					#define CHG		0x080
 | 
				
			||||||
 | 
					#define REF		0x100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DFLT_PERM	(PERM_EX | PERM_WR | PERM_RD | REF | CHG)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Set up an MMU translation tree using memory starting at the 64k point.
 | 
				
			||||||
 | 
					 * We use 3 levels, mapping 512GB, with 4kB PGD/PMD/PTE pages.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					unsigned long *proc_tbl = (unsigned long *) 0x10000;
 | 
				
			||||||
 | 
					unsigned long *pgdir = (unsigned long *) 0x11000;
 | 
				
			||||||
 | 
					unsigned long free_ptr = 0x12000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_mmu(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* set up process table */
 | 
				
			||||||
 | 
						zero_memory(proc_tbl, 512 * sizeof(unsigned long));
 | 
				
			||||||
 | 
						mtspr(PRTBL, (unsigned long)proc_tbl);
 | 
				
			||||||
 | 
						mtspr(PID, 1);
 | 
				
			||||||
 | 
						zero_memory(pgdir, 512 * sizeof(unsigned long));
 | 
				
			||||||
 | 
						/* RTS = 8 (512GB address space), RPDS = 9 (512-entry top level) */
 | 
				
			||||||
 | 
						store_pte(&proc_tbl[2 * 1], (unsigned long) pgdir | 0x2000000000000009);
 | 
				
			||||||
 | 
						do_tlbie(0xc00, 0);	/* invalidate all TLB entries */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned long *read_pd(unsigned long *pdp, unsigned long i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__asm__ volatile("ldbrx %0,%1,%2" : "=r" (ret) : "b" (pdp),
 | 
				
			||||||
 | 
								 "r" (i * sizeof(unsigned long)));
 | 
				
			||||||
 | 
						return (unsigned long *) (ret & 0x00ffffffffffff00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void map(unsigned long ea, unsigned long pa, unsigned long perm_attr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long epn = ea >> 12;
 | 
				
			||||||
 | 
						unsigned long h, i, j;
 | 
				
			||||||
 | 
						unsigned long *ptep;
 | 
				
			||||||
 | 
						unsigned long *pmdp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h = (epn >> 18) & 0x1ff;
 | 
				
			||||||
 | 
						i = (epn >> 9) & 0x1ff;
 | 
				
			||||||
 | 
						j = epn & 0x1ff;
 | 
				
			||||||
 | 
						if (pgdir[h] == 0) {
 | 
				
			||||||
 | 
							zero_memory((void *)free_ptr, 512 * sizeof(unsigned long));
 | 
				
			||||||
 | 
							store_pte(&pgdir[h], 0x8000000000000000 | free_ptr | 9);
 | 
				
			||||||
 | 
							free_ptr += 512 * sizeof(unsigned long);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pmdp = read_pd(pgdir, h);
 | 
				
			||||||
 | 
						if (pmdp[i] == 0) {
 | 
				
			||||||
 | 
							zero_memory((void *)free_ptr, 512 * sizeof(unsigned long));
 | 
				
			||||||
 | 
							store_pte(&pmdp[i], 0x8000000000000000 | free_ptr | 9);
 | 
				
			||||||
 | 
							free_ptr += 512 * sizeof(unsigned long);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ptep = read_pd(pmdp, i);
 | 
				
			||||||
 | 
						if (ptep[j]) {
 | 
				
			||||||
 | 
							ptep[j] = 0;
 | 
				
			||||||
 | 
							do_tlbie(ea & ~0xfff, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						store_pte(&ptep[j], 0xc000000000000000 | (pa & 0x00fffffffffff000) |
 | 
				
			||||||
 | 
							  perm_attr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void unmap(void *ea)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long epn = (unsigned long) ea >> 12;
 | 
				
			||||||
 | 
						unsigned long h, i, j;
 | 
				
			||||||
 | 
						unsigned long *ptep, *pmdp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h = (epn >> 18) & 0x1ff;
 | 
				
			||||||
 | 
						i = (epn >> 9) & 0x1ff;
 | 
				
			||||||
 | 
						j = epn & 0x1ff;
 | 
				
			||||||
 | 
						if (pgdir[h] == 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						pmdp = read_pd(pgdir, h);
 | 
				
			||||||
 | 
						if (pmdp[i] == 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						ptep = read_pd(pmdp, i);
 | 
				
			||||||
 | 
						ptep[j] = 0;
 | 
				
			||||||
 | 
						do_tlbie(((unsigned long)ea & ~0xfff), 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern unsigned long test_code(unsigned long sel, unsigned long addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned long bits = 0x0102030405060708ul;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mode_test_1(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long ret, msr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msr = MSR_SF | MSR_IR | MSR_DR | MSR_LE;
 | 
				
			||||||
 | 
						ret = callit(1, (unsigned long)&bits, (unsigned long)&test_code, msr);
 | 
				
			||||||
 | 
						if (ret != bits)
 | 
				
			||||||
 | 
							return ret? ret: 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned long be_test_code;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mode_test_2(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long i;
 | 
				
			||||||
 | 
						unsigned int *src, *dst;
 | 
				
			||||||
 | 
						unsigned long ret, msr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* copy and byte-swap the page containing test_code */
 | 
				
			||||||
 | 
						be_test_code = free_ptr;
 | 
				
			||||||
 | 
						free_ptr += 0x1000;
 | 
				
			||||||
 | 
						src = (unsigned int *) &test_code;
 | 
				
			||||||
 | 
						dst = (unsigned int *) be_test_code;
 | 
				
			||||||
 | 
						for (i = 0; i < 0x1000 / sizeof(unsigned int); ++i)
 | 
				
			||||||
 | 
							dst[i] = __builtin_bswap32(src[i]);
 | 
				
			||||||
 | 
						__asm__ volatile("isync; icbi 0,%0" : : "r" (be_test_code));
 | 
				
			||||||
 | 
						map(be_test_code, be_test_code, DFLT_PERM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msr = MSR_SF | MSR_IR | MSR_DR;
 | 
				
			||||||
 | 
						ret = callit(1, (unsigned long)&bits, be_test_code, msr);
 | 
				
			||||||
 | 
						if (ret != __builtin_bswap64(bits))
 | 
				
			||||||
 | 
							return ret? ret: 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mode_test_3(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long ret, msr;
 | 
				
			||||||
 | 
						unsigned long addr = (unsigned long) &bits;
 | 
				
			||||||
 | 
						unsigned long code = (unsigned long) &test_code;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msr = MSR_IR | MSR_DR | MSR_LE;
 | 
				
			||||||
 | 
						ret = callit(1, addr, code, msr);
 | 
				
			||||||
 | 
						if (ret != bits)
 | 
				
			||||||
 | 
							return ret? ret: 1;
 | 
				
			||||||
 | 
						ret = callit(1, addr + 0x5555555500000000ul,
 | 
				
			||||||
 | 
							     code + 0x9999999900000000ul, msr);
 | 
				
			||||||
 | 
						if (ret != bits)
 | 
				
			||||||
 | 
							return ret? ret: 2;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mode_test_4(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long ret, msr;
 | 
				
			||||||
 | 
						unsigned long addr = (unsigned long) &bits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msr = MSR_IR | MSR_DR;
 | 
				
			||||||
 | 
						ret = callit(1, addr, be_test_code, msr);
 | 
				
			||||||
 | 
						if (ret != __builtin_bswap64(bits))
 | 
				
			||||||
 | 
							return ret? ret: 1;
 | 
				
			||||||
 | 
						ret = callit(1, addr + 0x5555555500000000ul,
 | 
				
			||||||
 | 
							     be_test_code + 0x9999999900000000ul, msr);
 | 
				
			||||||
 | 
						if (ret != __builtin_bswap64(bits))
 | 
				
			||||||
 | 
							return ret? ret: 2;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mode_test_5(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long ret, msr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Try branching from the page at fffff000
 | 
				
			||||||
 | 
						 * to the page at 0 in 32-bit mode.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						map(0xfffff000, (unsigned long) &test_code, DFLT_PERM);
 | 
				
			||||||
 | 
						map(0, (unsigned long) &test_code, DFLT_PERM);
 | 
				
			||||||
 | 
						msr = MSR_IR | MSR_DR | MSR_LE;
 | 
				
			||||||
 | 
						ret = callit(2, 0, 0xfffff000, msr);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mode_test_6(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long ret, msr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Try a bl from address fffffffc in 32-bit mode.
 | 
				
			||||||
 | 
						 * We expect LR to be set to 100000000, though the
 | 
				
			||||||
 | 
						 * arch says the value is undefined.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						msr = MSR_IR | MSR_DR | MSR_LE;
 | 
				
			||||||
 | 
						ret = callit(3, 0, 0xfffff000, msr);
 | 
				
			||||||
 | 
						if (ret != 0x100000000ul)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int fail = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void do_test(int num, int (*test)(void))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print_test_number(num);
 | 
				
			||||||
 | 
						ret = test();
 | 
				
			||||||
 | 
						if (ret == 0) {
 | 
				
			||||||
 | 
							print_string("PASS\r\n");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fail = 1;
 | 
				
			||||||
 | 
							print_string("FAIL ");
 | 
				
			||||||
 | 
							print_hex(ret, 16);
 | 
				
			||||||
 | 
							if (ret != 0 && (ret & ~0xfe0ul) == 0) {
 | 
				
			||||||
 | 
								print_string(" SRR0=");
 | 
				
			||||||
 | 
								print_hex(mfspr(SPRG0), 16);
 | 
				
			||||||
 | 
								print_string(" SRR1=");
 | 
				
			||||||
 | 
								print_hex(mfspr(SPRG1), 16);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							print_string("\r\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long addr;
 | 
				
			||||||
 | 
						extern unsigned char __stack_top[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						console_init();
 | 
				
			||||||
 | 
						init_mmu();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Map test code and stack 1-1
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						for (addr = 0; addr < (unsigned long)&__stack_top; addr += 0x1000)
 | 
				
			||||||
 | 
							map(addr, addr, DFLT_PERM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do_test(1, mode_test_1);
 | 
				
			||||||
 | 
						do_test(2, mode_test_2);
 | 
				
			||||||
 | 
						do_test(3, mode_test_3);
 | 
				
			||||||
 | 
						do_test(4, mode_test_4);
 | 
				
			||||||
 | 
						do_test(5, mode_test_5);
 | 
				
			||||||
 | 
						do_test(6, mode_test_6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fail;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					SECTIONS
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						. = 0;
 | 
				
			||||||
 | 
						_start = .;
 | 
				
			||||||
 | 
						.head : {
 | 
				
			||||||
 | 
							KEEP(*(.head))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						. = ALIGN(0x1000);
 | 
				
			||||||
 | 
						.text : { *(.text) *(.text.*) *(.rodata) *(.rodata.*) }
 | 
				
			||||||
 | 
						. = ALIGN(0x1000);
 | 
				
			||||||
 | 
						.data : { *(.data) *(.data.*) *(.got) *(.toc) }
 | 
				
			||||||
 | 
						. = ALIGN(0x80);
 | 
				
			||||||
 | 
						__bss_start = .;
 | 
				
			||||||
 | 
						.bss : {
 | 
				
			||||||
 | 
							*(.dynsbss)
 | 
				
			||||||
 | 
							*(.sbss)
 | 
				
			||||||
 | 
							*(.scommon)
 | 
				
			||||||
 | 
							*(.dynbss)
 | 
				
			||||||
 | 
							*(.bss)
 | 
				
			||||||
 | 
							*(.common)
 | 
				
			||||||
 | 
							*(.bss.*)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						. = ALIGN(0x80);
 | 
				
			||||||
 | 
						__bss_end = .;
 | 
				
			||||||
 | 
						. = . + 0x4000;
 | 
				
			||||||
 | 
						__stack_top = .;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					TEST=reservation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include ../Makefile.test
 | 
				
			||||||
@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					/* Copyright 2013-2014 IBM Corp.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
				
			||||||
 | 
					 * implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Load an immediate 64-bit value into a register */
 | 
				
			||||||
 | 
					#define LOAD_IMM64(r, e)			\
 | 
				
			||||||
 | 
						lis     r,(e)@highest;			\
 | 
				
			||||||
 | 
						ori     r,r,(e)@higher;			\
 | 
				
			||||||
 | 
						rldicr  r,r, 32, 31;			\
 | 
				
			||||||
 | 
						oris    r,r, (e)@h;			\
 | 
				
			||||||
 | 
						ori     r,r, (e)@l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.section ".head","ax"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Microwatt currently enters in LE mode at 0x0, so we don't need to
 | 
				
			||||||
 | 
						 * do any endian fix ups
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						. = 0
 | 
				
			||||||
 | 
					.global _start
 | 
				
			||||||
 | 
					_start:
 | 
				
			||||||
 | 
						LOAD_IMM64(%r10,__bss_start)
 | 
				
			||||||
 | 
						LOAD_IMM64(%r11,__bss_end)
 | 
				
			||||||
 | 
						subf	%r11,%r10,%r11
 | 
				
			||||||
 | 
						addi	%r11,%r11,63
 | 
				
			||||||
 | 
						srdi.	%r11,%r11,6
 | 
				
			||||||
 | 
						beq	2f
 | 
				
			||||||
 | 
						mtctr	%r11
 | 
				
			||||||
 | 
					1:	dcbz	0,%r10
 | 
				
			||||||
 | 
						addi	%r10,%r10,64
 | 
				
			||||||
 | 
						bdnz	1b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2:	LOAD_IMM64(%r1,__stack_top)
 | 
				
			||||||
 | 
						li	%r0,0
 | 
				
			||||||
 | 
						stdu	%r0,-16(%r1)
 | 
				
			||||||
 | 
						mtsprg2	%r0
 | 
				
			||||||
 | 
						LOAD_IMM64(%r12, main)
 | 
				
			||||||
 | 
						mtctr	%r12
 | 
				
			||||||
 | 
						bctrl
 | 
				
			||||||
 | 
						attn // terminate on exit
 | 
				
			||||||
 | 
						b .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exception:
 | 
				
			||||||
 | 
						mfsprg2	%r0
 | 
				
			||||||
 | 
						cmpdi	%r0,0
 | 
				
			||||||
 | 
						bne	call_ret
 | 
				
			||||||
 | 
						attn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EXCEPTION(nr)		\
 | 
				
			||||||
 | 
						.= nr			;\
 | 
				
			||||||
 | 
						li	%r3,nr		;\
 | 
				
			||||||
 | 
						b	exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						EXCEPTION(0x300)
 | 
				
			||||||
 | 
						EXCEPTION(0x380)
 | 
				
			||||||
 | 
						EXCEPTION(0x400)
 | 
				
			||||||
 | 
						EXCEPTION(0x480)
 | 
				
			||||||
 | 
						EXCEPTION(0x500)
 | 
				
			||||||
 | 
						EXCEPTION(0x600)
 | 
				
			||||||
 | 
						EXCEPTION(0x700)
 | 
				
			||||||
 | 
						EXCEPTION(0x800)
 | 
				
			||||||
 | 
						EXCEPTION(0x900)
 | 
				
			||||||
 | 
						EXCEPTION(0x980)
 | 
				
			||||||
 | 
						EXCEPTION(0xa00)
 | 
				
			||||||
 | 
						EXCEPTION(0xb00)
 | 
				
			||||||
 | 
						EXCEPTION(0xc00)
 | 
				
			||||||
 | 
						EXCEPTION(0xd00)
 | 
				
			||||||
 | 
						EXCEPTION(0xe00)
 | 
				
			||||||
 | 
						EXCEPTION(0xe20)
 | 
				
			||||||
 | 
						EXCEPTION(0xe40)
 | 
				
			||||||
 | 
						EXCEPTION(0xe60)
 | 
				
			||||||
 | 
						EXCEPTION(0xe80)
 | 
				
			||||||
 | 
						EXCEPTION(0xf00)
 | 
				
			||||||
 | 
						EXCEPTION(0xf20)
 | 
				
			||||||
 | 
						EXCEPTION(0xf40)
 | 
				
			||||||
 | 
						EXCEPTION(0xf60)
 | 
				
			||||||
 | 
						EXCEPTION(0xf80)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						. = 0x1000
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Call a function in a context with a given MSR value.
 | 
				
			||||||
 | 
						 * r3, r4 = args; r5 = function
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						.globl	callit
 | 
				
			||||||
 | 
					callit:
 | 
				
			||||||
 | 
						mflr	%r0
 | 
				
			||||||
 | 
						std	%r0,16(%r1)
 | 
				
			||||||
 | 
						stdu	%r1,-256(%r1)
 | 
				
			||||||
 | 
						mfcr	%r8
 | 
				
			||||||
 | 
						stw	%r8,100(%r1)
 | 
				
			||||||
 | 
						std	%r13,104(%r1)
 | 
				
			||||||
 | 
						std	%r14,112(%r1)
 | 
				
			||||||
 | 
						std	%r15,120(%r1)
 | 
				
			||||||
 | 
						std	%r16,128(%r1)
 | 
				
			||||||
 | 
						std	%r17,136(%r1)
 | 
				
			||||||
 | 
						std	%r18,144(%r1)
 | 
				
			||||||
 | 
						std	%r19,152(%r1)
 | 
				
			||||||
 | 
						std	%r20,160(%r1)
 | 
				
			||||||
 | 
						std	%r21,168(%r1)
 | 
				
			||||||
 | 
						std	%r22,176(%r1)
 | 
				
			||||||
 | 
						std	%r23,184(%r1)
 | 
				
			||||||
 | 
						std	%r24,192(%r1)
 | 
				
			||||||
 | 
						std	%r25,200(%r1)
 | 
				
			||||||
 | 
						std	%r26,208(%r1)
 | 
				
			||||||
 | 
						std	%r27,216(%r1)
 | 
				
			||||||
 | 
						std	%r28,224(%r1)
 | 
				
			||||||
 | 
						std	%r29,232(%r1)
 | 
				
			||||||
 | 
						std	%r30,240(%r1)
 | 
				
			||||||
 | 
						std	%r31,248(%r1)
 | 
				
			||||||
 | 
						mtsprg0	%r0
 | 
				
			||||||
 | 
						mtsprg1	%r1
 | 
				
			||||||
 | 
						mtsprg2	%r2
 | 
				
			||||||
 | 
						mtctr	%r5
 | 
				
			||||||
 | 
						mr	%r12,%r5
 | 
				
			||||||
 | 
						bctrl
 | 
				
			||||||
 | 
					call_ret:
 | 
				
			||||||
 | 
						mfsprg0	%r0		/* restore regs in case of trap */
 | 
				
			||||||
 | 
						mfsprg1	%r1
 | 
				
			||||||
 | 
						mfsprg2	%r2
 | 
				
			||||||
 | 
						li	%r7,0
 | 
				
			||||||
 | 
						mtsprg2	%r7
 | 
				
			||||||
 | 
						mtlr	%r0
 | 
				
			||||||
 | 
						lwz	%r8,100(%r1)
 | 
				
			||||||
 | 
						mtcr	%r8
 | 
				
			||||||
 | 
						ld	%r13,104(%r1)
 | 
				
			||||||
 | 
						ld	%r14,112(%r1)
 | 
				
			||||||
 | 
						ld	%r15,120(%r1)
 | 
				
			||||||
 | 
						ld	%r16,128(%r1)
 | 
				
			||||||
 | 
						ld	%r17,136(%r1)
 | 
				
			||||||
 | 
						ld	%r18,144(%r1)
 | 
				
			||||||
 | 
						ld	%r19,152(%r1)
 | 
				
			||||||
 | 
						ld	%r20,160(%r1)
 | 
				
			||||||
 | 
						ld	%r21,168(%r1)
 | 
				
			||||||
 | 
						ld	%r22,176(%r1)
 | 
				
			||||||
 | 
						ld	%r23,184(%r1)
 | 
				
			||||||
 | 
						ld	%r24,192(%r1)
 | 
				
			||||||
 | 
						ld	%r25,200(%r1)
 | 
				
			||||||
 | 
						ld	%r26,208(%r1)
 | 
				
			||||||
 | 
						ld	%r27,216(%r1)
 | 
				
			||||||
 | 
						ld	%r28,224(%r1)
 | 
				
			||||||
 | 
						ld	%r29,232(%r1)
 | 
				
			||||||
 | 
						ld	%r30,240(%r1)
 | 
				
			||||||
 | 
						ld	%r31,248(%r1)
 | 
				
			||||||
 | 
						addi	%r1,%r1,256
 | 
				
			||||||
 | 
						blr
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					SECTIONS
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						. = 0;
 | 
				
			||||||
 | 
						_start = .;
 | 
				
			||||||
 | 
						.head : {
 | 
				
			||||||
 | 
							KEEP(*(.head))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						. = ALIGN(0x1000);
 | 
				
			||||||
 | 
						.text : { *(.text) *(.text.*) *(.rodata) *(.rodata.*) }
 | 
				
			||||||
 | 
						. = ALIGN(0x1000);
 | 
				
			||||||
 | 
						.data : { *(.data) *(.data.*) *(.got) *(.toc) }
 | 
				
			||||||
 | 
						. = ALIGN(0x80);
 | 
				
			||||||
 | 
						__bss_start = .;
 | 
				
			||||||
 | 
						.bss : {
 | 
				
			||||||
 | 
							*(.dynsbss)
 | 
				
			||||||
 | 
							*(.sbss)
 | 
				
			||||||
 | 
							*(.scommon)
 | 
				
			||||||
 | 
							*(.dynbss)
 | 
				
			||||||
 | 
							*(.bss)
 | 
				
			||||||
 | 
							*(.common)
 | 
				
			||||||
 | 
							*(.bss.*)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						. = ALIGN(0x80);
 | 
				
			||||||
 | 
						__bss_end = .;
 | 
				
			||||||
 | 
						. = . + 0x4000;
 | 
				
			||||||
 | 
						__stack_top = .;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,210 @@
 | 
				
			|||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "console.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern unsigned long callit(unsigned long arg1, unsigned long arg2,
 | 
				
			||||||
 | 
								    unsigned long (*fn)(unsigned long, unsigned long));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DSISR	18
 | 
				
			||||||
 | 
					#define DAR	19
 | 
				
			||||||
 | 
					#define SRR0	26
 | 
				
			||||||
 | 
					#define SRR1	27
 | 
				
			||||||
 | 
					#define PID	48
 | 
				
			||||||
 | 
					#define SPRG0	272
 | 
				
			||||||
 | 
					#define SPRG1	273
 | 
				
			||||||
 | 
					#define PRTBL	720
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned long mfspr(int sprnum)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						long val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__asm__ volatile("mfspr %0,%1" : "=r" (val) : "i" (sprnum));
 | 
				
			||||||
 | 
						return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void mtspr(int sprnum, unsigned long val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__asm__ volatile("mtspr %0,%1" : : "i" (sprnum), "r" (val));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void store_pte(unsigned long *p, unsigned long pte)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__asm__ volatile("stdbrx %1,0,%0" : : "r" (p), "r" (pte) : "memory");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void print_string(const char *str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						for (; *str; ++str)
 | 
				
			||||||
 | 
							putchar(*str);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void print_hex(unsigned long val, int ndigits)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = (ndigits - 1) * 4; i >= 0; i -= 4) {
 | 
				
			||||||
 | 
							x = (val >> i) & 0xf;
 | 
				
			||||||
 | 
							if (x >= 10)
 | 
				
			||||||
 | 
								putchar(x + 'a' - 10);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								putchar(x + '0');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// i < 100
 | 
				
			||||||
 | 
					void print_test_number(int i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						print_string("test ");
 | 
				
			||||||
 | 
						putchar(48 + i/10);
 | 
				
			||||||
 | 
						putchar(48 + i%10);
 | 
				
			||||||
 | 
						putchar(':');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DO_LARX(instr, addr, val)	__asm__ volatile(instr " %0,0,%1" : "=r" (val) : "r" (addr))
 | 
				
			||||||
 | 
					#define DO_STCX(instr, addr, val, cc)	__asm__ volatile(instr " %2,0,%1; mfcr %0" : "=r" (cc) \
 | 
				
			||||||
 | 
					                                                         : "r" (addr), "r" (val) : "cr0", "memory");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int resv_test_1(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long x, val, cc = 0;
 | 
				
			||||||
 | 
						int count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x = 1234;
 | 
				
			||||||
 | 
						for (count = 0; count < 1000; ++count) {
 | 
				
			||||||
 | 
							DO_LARX("ldarx", &x, val);
 | 
				
			||||||
 | 
							DO_STCX("stdcx.", &x, 5678, cc);
 | 
				
			||||||
 | 
							if (cc & 0x20000000)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* ldarx/stdcx. should succeed eventually */
 | 
				
			||||||
 | 
						if (count == 1000)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (x != 5678)
 | 
				
			||||||
 | 
							return 2;
 | 
				
			||||||
 | 
						for (count = 0; count < 1000; ++count) {
 | 
				
			||||||
 | 
							DO_LARX("lwarx", &x, val);
 | 
				
			||||||
 | 
							DO_STCX("stwcx.", &x, 9876, cc);
 | 
				
			||||||
 | 
							if (cc & 0x20000000)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* lwarx/stwcx. should succeed eventually */
 | 
				
			||||||
 | 
						if (count == 1000)
 | 
				
			||||||
 | 
							return 3;
 | 
				
			||||||
 | 
						if (x != 9876)
 | 
				
			||||||
 | 
							return 4;
 | 
				
			||||||
 | 
						for (count = 0; count < 1000; ++count) {
 | 
				
			||||||
 | 
							DO_LARX("lharx", &x, val);
 | 
				
			||||||
 | 
							DO_STCX("sthcx.", &x, 3210, cc);
 | 
				
			||||||
 | 
							if (cc & 0x20000000)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* lharx/sthcx. should succeed eventually */
 | 
				
			||||||
 | 
						if (count == 1000)
 | 
				
			||||||
 | 
							return 5;
 | 
				
			||||||
 | 
						if (x != 3210)
 | 
				
			||||||
 | 
							return 6;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned long do_larx(unsigned long size, unsigned long addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (size) {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							DO_LARX("lbarx", addr, val);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							DO_LARX("lharx", addr, val);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 4:
 | 
				
			||||||
 | 
							DO_LARX("lwarx", addr, val);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 8:
 | 
				
			||||||
 | 
							DO_LARX("ldarx", addr, val);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned long do_stcx(unsigned long size, unsigned long addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long val = 0, cc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (size) {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							DO_STCX("stbcx.", addr, val, cc);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							DO_STCX("sthcx.", addr, val, cc);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 4:
 | 
				
			||||||
 | 
							DO_STCX("stwcx.", addr, val, cc);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 8:
 | 
				
			||||||
 | 
							DO_STCX("stdcx.", addr, val, cc);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int resv_test_2(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long x[3];
 | 
				
			||||||
 | 
						unsigned long offset, j, size, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x[0] = 1234;
 | 
				
			||||||
 | 
						x[1] = x[2] = 0;
 | 
				
			||||||
 | 
						for (j = 0; j <= 3; ++j) {
 | 
				
			||||||
 | 
							size = 1 << j;
 | 
				
			||||||
 | 
							for (offset = 0; offset < 16; ++offset) {
 | 
				
			||||||
 | 
								ret = callit(size, (unsigned long)&x[0] + offset, do_larx);
 | 
				
			||||||
 | 
								if (0 && ret == 0 && (offset & (size - 1)) != 0)
 | 
				
			||||||
 | 
									return j + 1;
 | 
				
			||||||
 | 
								if (ret == 0x600) {
 | 
				
			||||||
 | 
									if ((offset & (size - 1)) == 0)
 | 
				
			||||||
 | 
										return j + 0x10;
 | 
				
			||||||
 | 
								} else if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
								ret = callit(size, (unsigned long)&x[0] + offset, do_stcx);
 | 
				
			||||||
 | 
								if (ret == 0 && (offset & (size - 1)) != 0)
 | 
				
			||||||
 | 
									return j + 0x20;
 | 
				
			||||||
 | 
								if (ret == 0x600) {
 | 
				
			||||||
 | 
									if ((offset & (size - 1)) == 0)
 | 
				
			||||||
 | 
										return j + 0x30;
 | 
				
			||||||
 | 
								} else if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int fail = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void do_test(int num, int (*test)(void))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print_test_number(num);
 | 
				
			||||||
 | 
						ret = test();
 | 
				
			||||||
 | 
						if (ret == 0) {
 | 
				
			||||||
 | 
							print_string("PASS\r\n");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fail = 1;
 | 
				
			||||||
 | 
							print_string("FAIL ");
 | 
				
			||||||
 | 
							print_hex(ret, 4);
 | 
				
			||||||
 | 
							print_string("\r\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						console_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do_test(1, resv_test_1);
 | 
				
			||||||
 | 
						do_test(2, resv_test_2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fail;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
											
												Binary file not shown.
											
										
									
								
											
												Binary file not shown.
											
										
									
								@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					test 01:PASS
 | 
				
			||||||
 | 
					test 02:PASS
 | 
				
			||||||
 | 
					test 03:PASS
 | 
				
			||||||
 | 
					test 04:PASS
 | 
				
			||||||
 | 
					test 05:PASS
 | 
				
			||||||
 | 
					test 06:PASS
 | 
				
			||||||
											
												Binary file not shown.
											
										
									
								@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					test 01:PASS
 | 
				
			||||||
 | 
					test 02:PASS
 | 
				
			||||||
					Loading…
					
					
				
		Reference in New Issue