mips memory sizing in libgloss

Jeff Johnston jjohnstn@redhat.com
Fri Jun 1 21:59:00 GMT 2007


I haven't the mips expertise to review this.  I might suggest you run it 
past one or more of the previous maintainers of cma101.c if you are 
looking for any potential oversights in your logic.  Assuming you have 
tested the change and there are no other objections, consider this 
approval to apply.

-- Jeff J.

DJ Delorie wrote:
> libgloss/mips/cma101.c has a function called __sizemem() that cleverly
> switches to non-cached kseg1 to size memory.  However, our vr9721
> boards seem to have some cache still enabled even in kseg1, so we end
> up with the wrong $sp at startup.
> 
> I wrote a new function __destructive_mem_top() that tests for the top
> of memory in a way that flushes the cache anyway.  It returns the
> correct value, but can't replace __sizemem() for other purposes
> (sbrk() calls it) because it's destructive, although it does set
> __sizemem_default to avoid duplicate work.
> 
> Comments?  Problems?  Approval? ;-)
> 
> DJ
> 
> 	* mips/cma101.c (__destructive_mem_top): New.
> 	* mips/crt0.S: Use it.
> 
> Index: cma101.c
> ===================================================================
> RCS file: /cvs/src/src/libgloss/mips/cma101.c,v
> retrieving revision 1.5
> diff -p -U3 -r1.5 cma101.c
> --- cma101.c	2 May 2003 20:06:52 -0000	1.5
> +++ cma101.c	1 Jun 2007 21:05:12 -0000
> @@ -258,6 +258,68 @@ __sizemem ()
>    return((probe - base) * sizeof(unsigned int));
>  }
>  
> +/* Similar to the above, but destructively tests in case the cache is
> +   partially enabled (vr9721).  Used only by crt0.  */
> +void *
> +__destructive_mem_top ()
> +{
> +  volatile unsigned int *base;
> +  volatile unsigned int *probe, *maxtop;
> +  unsigned int baseorig;
> +  unsigned int sr;
> +  extern char end[];
> +  char *endptr = (char *)&end;
> +  int extra, offset;
> +
> +  /* Max of 2Gb RAM.  */
> +  maxtop = 0x80000000;
> +  offset = 0;
> +
> +  /* If we are running in kernel segment 0 (possibly cached), try sizing memory
> +     in kernel segment 1 (uncached) to avoid some problems with monitors.  */
> +  if (endptr >= K0BASE_ADDR && endptr < K1BASE_ADDR)
> +    {
> +      endptr = (endptr - K0BASE_ADDR) + K1BASE_ADDR;
> +      /* Should be 0xB0000000 - 512M RAM.  */
> +      maxtop = K1BASE_ADDR + (K1BASE_ADDR - K0BASE_ADDR);
> +      offset = K1BASE_ADDR - K0BASE_ADDR;
> +    }
> +
> +  INTDISABLE(sr,baseorig); /* disable all interrupt masks */
> +
> +  __default_buserr_handler();
> +  __cpu_flush();
> +
> +  DOSYNC();
> +
> +  /* Align to our step, so that the first failing step is just after
> +     the last byte of memory.  */
> +  extra = ((int) endptr & (SM_INCR - 1));
> +  base = ((void *) endptr + SM_INCR - extra);
> +  baseorig = *base;
> +
> +  for (probe = base; probe < maxtop; probe += SM_INCR)
> +    *probe = (unsigned int)probe;
> +  DOSYNC();
> +  for (probe = base; probe < maxtop; probe += SM_INCR)
> +    if (*probe != (unsigned int)probe)
> +      break;
> +
> +  probe -= (SM_INCR / sizeof(*probe));
> +
> +  *base = baseorig;
> +  __restore_buserr_handler();
> +  __cpu_flush();
> +
> +  DOSYNC();
> +
> +  INTRESTORE(sr); /* restore interrupt mask to entry state */
> +
> +  __sizemem_default = ((probe - base) * sizeof(unsigned int));
> +
> +  return (char *)probe - offset;
> +}
> +
>  /* Provided as a function, so as to avoid reading the I/O location
>     multiple times: */
>  static int
> Index: crt0.S
> ===================================================================
> RCS file: /cvs/src/src/libgloss/mips/crt0.S,v
> retrieving revision 1.11
> diff -p -U3 -r1.11 crt0.S
> --- crt0.S	27 Nov 2006 16:12:51 -0000	1.11
> +++ crt0.S	1 Jun 2007 21:05:12 -0000
> @@ -161,12 +161,11 @@ zerobss:
>  	bne	t0,zero,4f
>  	nop
>  
> -	/* NOTE: a0[0] contains the amount of memory available, and
> -	         not the last memory address. */
> -	la	a0, __memsize
> -	lw	t0,0(a0)			# last address of memory available
> -	la	t1,K0BASE			# cached kernel memory
> -	addu	t0,t0,t1			# get the end of memory address
> +	jal	__destructive_mem_top
> +	nop
> +	/* NOTE: v0 now contains a pointer to the first invalid memory location. */
> +
> +	move	t0,v0
>  	/* Allocate 32 bytes for the register parameters.  Allocate 16
>  	   bytes for a null argv and envp.  Round the result up to 64
>  	   bytes to preserve alignment.  */



More information about the Newlib mailing list