extern void loadcam_entry(unsigned int index);
unsigned int tlbcam_index;
-static unsigned long cam[3];
+static unsigned long cam[CONFIG_LOWMEM_CAM_NUM];
#define NUM_TLBCAMS (16)
+#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
+#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
+#endif
+
struct tlbcam TLBCAM[NUM_TLBCAMS];
struct tlbcamrange {
/*
* Return PA for this VA if it is mapped by a CAM, or 0
*/
-unsigned long v_mapped_by_tlbcam(unsigned long va)
+phys_addr_t v_mapped_by_tlbcam(unsigned long va)
{
int b;
for (b = 0; b < tlbcam_index; ++b)
/*
* Return VA for a given PA or 0 if not mapped
*/
-unsigned long p_mapped_by_tlbcam(unsigned long pa)
+unsigned long p_mapped_by_tlbcam(phys_addr_t pa)
{
int b;
for (b = 0; b < tlbcam_index; ++b)
unsigned int tsize, lz;
asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size));
- tsize = (21 - lz) / 2;
+ tsize = 21 - lz;
#ifdef CONFIG_SMP
if ((flags & _PAGE_NO_CACHE) == 0)
adjust_total_lowmem(void)
{
phys_addr_t ram;
- unsigned int max_cam = 28; /* 2^28 = 256 Mb */
+ unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xff;
char buf[ARRAY_SIZE(cam) * 5 + 1], *p = buf;
int i;
+ unsigned long virt = PAGE_OFFSET & 0xffffffffUL;
+ unsigned long phys = memstart_addr & 0xffffffffUL;
+
+ /* Convert (4^max) kB to (2^max) bytes */
+ max_cam = max_cam * 2 + 10;
/* adjust lowmem size to __max_low_memory */
ram = min((phys_addr_t)__max_low_memory, (phys_addr_t)total_lowmem);
__max_low_memory = 0;
for (i = 0; ram && i < ARRAY_SIZE(cam); i++) {
unsigned int camsize = __ilog2(ram) & ~1U;
+ unsigned int align = __ffs(virt | phys) & ~1U;
+
+ if (camsize > align)
+ camsize = align;
if (camsize > max_cam)
camsize = max_cam;
+
cam[i] = 1UL << camsize;
ram -= cam[i];
__max_low_memory += cam[i];
+ virt += cam[i];
+ phys += cam[i];
p += sprintf(p, "%lu/", cam[i] >> 20);
}
p += sprintf(p, "0/");
p[-1] = '\0';
- pr_info("Memory CAM mapping: %s Mb, residual: %ldMb\n", buf,
- (total_lowmem - __max_low_memory) >> 20);
+ pr_info("Memory CAM mapping: %s Mb, residual: %dMb\n", buf,
+ (unsigned int)((total_lowmem - __max_low_memory) >> 20));
__initial_memory_limit_addr = memstart_addr + __max_low_memory;
}