Skip to content

Commit

Permalink
[Blackfin] arch: Initial checkin of the memory protection support.
Browse files Browse the repository at this point in the history
Enable it with CONFIG_MPU.

Signed-off-by: Bernd Schmidt <bernd.schmidt@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
  • Loading branch information
Bernd Schmidt authored and Bryan Wu committed Jan 27, 2008
1 parent 2047e40 commit b97b8a9
Show file tree
Hide file tree
Showing 15 changed files with 822 additions and 8 deletions.
9 changes: 9 additions & 0 deletions arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,15 @@ config L1_MAX_PIECE
Set the max memory pieces for the L1 SRAM allocation algorithm.
Min value is 16. Max value is 1024.


config MPU
bool "Enable the memory protection unit (EXPERIMENTAL)"
default n
help
Use the processor's MPU to protect applications from accessing
memory they do not own. This comes at a performance penalty
and is recommended only for debugging.

comment "Asynchonous Memory Configuration"

menu "EBIU_AMGCTL Global Control"
Expand Down
6 changes: 5 additions & 1 deletion arch/blackfin/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ core-y += arch/$(ARCH)/mach-$(MACHINE)/
core-y += arch/$(ARCH)/mach-$(MACHINE)/boards/
endif

core-y += arch/$(ARCH)/kernel/cplb-nompu/
ifeq ($(CONFIG_MPU),y)
core-y += arch/$(ARCH)/kernel/cplb-mpu/
else
core-y += arch/$(ARCH)/kernel/cplb-nompu/
endif

libs-y += arch/$(ARCH)/lib/

Expand Down
8 changes: 8 additions & 0 deletions arch/blackfin/kernel/cplb-mpu/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# arch/blackfin/kernel/cplb-nompu/Makefile
#

obj-y := cplbinit.o cacheinit.o cplbmgr.o

obj-$(CONFIG_CPLB_INFO) += cplbinfo.o

62 changes: 62 additions & 0 deletions arch/blackfin/kernel/cplb-mpu/cacheinit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2004-2007 Analog Devices Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <linux/cpu.h>

#include <asm/cacheflush.h>
#include <asm/blackfin.h>
#include <asm/cplb.h>
#include <asm/cplbinit.h>

#if defined(CONFIG_BFIN_ICACHE)
void bfin_icache_init(void)
{
unsigned long ctrl;
int i;

SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr);
bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data);
}
ctrl = bfin_read_IMEM_CONTROL();
ctrl |= IMC | ENICPLB;
bfin_write_IMEM_CONTROL(ctrl);
SSYNC();
}
#endif

#if defined(CONFIG_BFIN_DCACHE)
void bfin_dcache_init(void)
{
unsigned long ctrl;
int i;

SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr);
bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data);
}

ctrl = bfin_read_DMEM_CONTROL();
ctrl |= DMEM_CNTR;
bfin_write_DMEM_CONTROL(ctrl);
SSYNC();
}
#endif
144 changes: 144 additions & 0 deletions arch/blackfin/kernel/cplb-mpu/cplbinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* File: arch/blackfin/mach-common/cplbinfo.c
* Based on:
* Author: Sonic Zhang <sonic.zhang@analog.com>
*
* Created: Jan. 2005
* Description: Display CPLB status
*
* Modified:
* Copyright 2004-2006 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>

#include <asm/current.h>
#include <asm/system.h>
#include <asm/cplb.h>
#include <asm/cplbinit.h>
#include <asm/blackfin.h>

#define CPLB_I 1
#define CPLB_D 2

#define SYNC_SYS SSYNC()
#define SYNC_CORE CSYNC()

#define CPLB_BIT_PAGESIZE 0x30000

static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };

static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched)
{
int i;
buf += sprintf(buf, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n");
for (i = 0; i < MAX_CPLBS; i++) {
unsigned long data = tbl[i].data;
unsigned long addr = tbl[i].addr;
if (!(data & CPLB_VALID))
continue;

buf +=
sprintf(buf,
"%d\t0x%08lx\t%06lx\t%s\t%c\t%c\t%c\t%c\n",
i, addr, data,
page_size_string_table[(data & 0x30000) >> 16],
(data & CPLB_USER_RD) ? 'Y' : 'N',
(data & CPLB_USER_WR) ? 'Y' : 'N',
(data & CPLB_SUPV_WR) ? 'Y' : 'N',
i < switched ? 'N' : 'Y');
}
buf += sprintf(buf, "\n");

return buf;
}

int cplbinfo_proc_output(char *buf)
{
char *p;

p = buf;

p += sprintf(p, "------------------ CPLB Information ------------------\n\n");

if (bfin_read_IMEM_CONTROL() & ENICPLB) {
p += sprintf(p, "Instruction CPLB entry:\n");
p = cplb_print_entry(p, icplb_tbl, first_switched_icplb);
} else
p += sprintf(p, "Instruction CPLB is disabled.\n\n");

if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) {
p += sprintf(p, "Data CPLB entry:\n");
p = cplb_print_entry(p, dcplb_tbl, first_switched_dcplb);
} else
p += sprintf(p, "Data CPLB is disabled.\n");

p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n",
nr_icplb_miss, nr_icplb_supv_miss);
p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n",
nr_dcplb_miss, nr_dcplb_prot);
p += sprintf(p, "CPLB flushes: %d\n",
nr_cplb_flush);

return p - buf;
}

static int cplbinfo_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;

len = cplbinfo_proc_output(page);
if (len <= off + count)
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
}

static int __init cplbinfo_init(void)
{
struct proc_dir_entry *entry;

entry = create_proc_entry("cplbinfo", 0, NULL);
if (!entry)
return -ENOMEM;

entry->read_proc = cplbinfo_read_proc;
entry->data = NULL;

return 0;
}

static void __exit cplbinfo_exit(void)
{
remove_proc_entry("cplbinfo", NULL);
}

module_init(cplbinfo_init);
module_exit(cplbinfo_exit);
91 changes: 91 additions & 0 deletions arch/blackfin/kernel/cplb-mpu/cplbinit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Blackfin CPLB initialization
*
* Copyright 2004-2007 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/module.h>

#include <asm/blackfin.h>
#include <asm/cplb.h>
#include <asm/cplbinit.h>

struct cplb_entry icplb_tbl[MAX_CPLBS];
struct cplb_entry dcplb_tbl[MAX_CPLBS];

int first_switched_icplb, first_switched_dcplb;
int first_mask_dcplb;

void __init generate_cpl_tables(void)
{
int i_d, i_i;
unsigned long addr;
unsigned long d_data, i_data;
unsigned long d_cache = 0, i_cache = 0;

#ifdef CONFIG_BFIN_ICACHE
i_cache = CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
#endif

#ifdef CONFIG_BFIN_DCACHE
d_cache = CPLB_L1_CHBL;
#ifdef CONFIG_BLKFIN_WT
d_cache |= CPLB_L1_AOW | CPLB_WT;
#endif
#endif
i_d = i_i = 0;

/* Set up the zero page. */
dcplb_tbl[i_d].addr = 0;
dcplb_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;

#if 0
icplb_tbl[i_i].addr = 0;
icplb_tbl[i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB;
#endif

/* Cover kernel memory with 4M pages. */
addr = 0;
d_data = d_cache | CPLB_SUPV_WR | CPLB_VALID | PAGE_SIZE_4MB | CPLB_DIRTY;
i_data = i_cache | CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4MB;

for (; addr < memory_start; addr += 4 * 1024 * 1024) {
dcplb_tbl[i_d].addr = addr;
dcplb_tbl[i_d++].data = d_data;
icplb_tbl[i_i].addr = addr;
icplb_tbl[i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0);
}

/* Cover L1 memory. One 4M area for code and data each is enough. */
#if L1_DATA_A_LENGTH > 0 || L1_DATA_B_LENGTH > 0
dcplb_tbl[i_d].addr = L1_DATA_A_START;
dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
#endif
icplb_tbl[i_i].addr = L1_CODE_START;
icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;

first_mask_dcplb = i_d;
first_switched_dcplb = i_d + (1 << page_mask_order);
first_switched_icplb = i_i;

while (i_d < MAX_CPLBS)
dcplb_tbl[i_d++].data = 0;
while (i_i < MAX_CPLBS)
icplb_tbl[i_i++].data = 0;
}
Loading

0 comments on commit b97b8a9

Please sign in to comment.