#include <asm/cplbinit.h>
#include <asm/mmu_context.h>
-#ifdef CONFIG_BFIN_ICACHE
-
#define FAULT_RW (1 << 16)
#define FAULT_USERSUPV (1 << 17)
unsigned long d_data;
nr_dcplb_miss++;
- if (addr >= _ramend)
- return CPLB_PROT_VIOL;
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
#ifdef CONFIG_BFIN_DCACHE
- d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
-#ifdef CONFIG_BLKFIN_WT
- d_data |= CPLB_L1_AOW | CPLB_WT;
-#endif
+ if (addr < _ramend - DMA_UNCACHED_REGION ||
+ (reserved_mem_dcache_on && addr >= _ramend &&
+ addr < physical_mem_end)) {
+ d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+#ifdef CONFIG_BFIN_WT
+ d_data |= CPLB_L1_AOW | CPLB_WT;
#endif
- mask = current_rwx_mask;
- if (mask) {
- int page = addr >> PAGE_SHIFT;
- int offs = page >> 5;
- int bit = 1 << (page & 31);
-
- if (mask[offs] & bit)
- d_data |= CPLB_USER_RD;
-
- mask += page_mask_nelts;
- if (mask[offs] & bit)
- d_data |= CPLB_USER_WR;
}
+#endif
+ if (addr >= physical_mem_end) {
+ if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE
+ && (status & FAULT_USERSUPV)) {
+ addr &= ~0x3fffff;
+ d_data &= ~PAGE_SIZE_4KB;
+ d_data |= PAGE_SIZE_4MB;
+ } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
+ && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) {
+ addr &= ~(1 * 1024 * 1024 - 1);
+ d_data &= ~PAGE_SIZE_4KB;
+ d_data |= PAGE_SIZE_1MB;
+ } else
+ return CPLB_PROT_VIOL;
+ } else if (addr >= _ramend) {
+ d_data |= CPLB_USER_RD | CPLB_USER_WR;
+ } else {
+ mask = current_rwx_mask;
+ if (mask) {
+ int page = addr >> PAGE_SHIFT;
+ int offs = page >> 5;
+ int bit = 1 << (page & 31);
+
+ if (mask[offs] & bit)
+ d_data |= CPLB_USER_RD;
+ mask += page_mask_nelts;
+ if (mask[offs] & bit)
+ d_data |= CPLB_USER_WR;
+ }
+ }
idx = evict_one_dcplb();
addr &= PAGE_MASK;
unsigned long i_data;
nr_icplb_miss++;
- if (status & FAULT_USERSUPV)
- nr_icplb_supv_miss++;
- if (addr >= _ramend)
+ /* If inside the uncached DMA region, fault. */
+ if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend)
return CPLB_PROT_VIOL;
+ if (status & FAULT_USERSUPV)
+ nr_icplb_supv_miss++;
+
/*
* First, try to find a CPLB that matches this address. If we
* find one, then the fact that we're in the miss handler means
}
i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB;
-#ifdef CONFIG_BFIN_ICACHE
- i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
-#endif
+#ifdef CONFIG_BFIN_ICACHE
/*
- * Two cases to distinguish - a supervisor access must necessarily
- * be for a module page; we grant it unconditionally (could do better
- * here in the future). Otherwise, check the x bitmap of the current
- * process.
+ * Normal RAM, and possibly the reserved memory area, are
+ * cacheable.
*/
- if (!(status & FAULT_USERSUPV)) {
- unsigned long *mask = current_rwx_mask;
-
- if (mask) {
- int page = addr >> PAGE_SHIFT;
- int offs = page >> 5;
- int bit = 1 << (page & 31);
+ if (addr < _ramend ||
+ (addr < physical_mem_end && reserved_mem_icache_on))
+ i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+#endif
- mask += 2 * page_mask_nelts;
- if (mask[offs] & bit)
- i_data |= CPLB_USER_RD;
+ if (addr >= physical_mem_end) {
+ if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
+ && (status & FAULT_USERSUPV)) {
+ addr &= ~(1 * 1024 * 1024 - 1);
+ i_data &= ~PAGE_SIZE_4KB;
+ i_data |= PAGE_SIZE_1MB;
+ } else
+ return CPLB_PROT_VIOL;
+ } else if (addr >= _ramend) {
+ i_data |= CPLB_USER_RD;
+ } else {
+ /*
+ * Two cases to distinguish - a supervisor access must
+ * necessarily be for a module page; we grant it
+ * unconditionally (could do better here in the future).
+ * Otherwise, check the x bitmap of the current process.
+ */
+ if (!(status & FAULT_USERSUPV)) {
+ unsigned long *mask = current_rwx_mask;
+
+ if (mask) {
+ int page = addr >> PAGE_SHIFT;
+ int offs = page >> 5;
+ int bit = 1 << (page & 31);
+
+ mask += 2 * page_mask_nelts;
+ if (mask[offs] & bit)
+ i_data |= CPLB_USER_RD;
+ }
}
}
-
idx = evict_one_icplb();
addr &= PAGE_MASK;
icplb_tbl[idx].addr = addr;
static noinline int dcplb_protection_fault(void)
{
- unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
int status = bfin_read_DCPLB_STATUS();
nr_dcplb_prot++;
case 0x26:
return dcplb_miss();
default:
- return 1;
- panic_cplb_error(seqstat, regs);
+ return 1;
}
}
enable_icplb();
disable_dcplb();
- for (i = first_mask_dcplb; i < MAX_CPLBS; i++) {
+ for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
dcplb_tbl[i].data = 0;
bfin_write32(DCPLB_DATA0 + i * 4, 0);
}
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
#ifdef CONFIG_BFIN_DCACHE
d_data |= CPLB_L1_CHBL;
-#ifdef CONFIG_BLKFIN_WT
+#ifdef CONFIG_BFIN_WT
d_data |= CPLB_L1_AOW | CPLB_WT;
#endif
#endif
}
enable_dcplb();
}
-
-#endif