Skip to content

Commit

Permalink
Blackfin arch: Faster C implementation of no-MPU CPLB handler
Browse files Browse the repository at this point in the history
This is a mixture ofcMichael McTernan's patch and the existing cplb-mpu code.

We ditch the old cplb-nompu implementation, which is a good example of
why a good algorithm in a HLL is preferrable to a bad algorithm written in
assembly.  Rather than try to construct a table of all posible CPLBs and
search it, we just create a (smaller) table of memory regions and
their attributes.  Some of the data structures are now unified for both
the mpu and nompu cases.  A lot of needless complexity in cplbinit.c is
removed.

Further optimizations:
  * compile cplbmgr.c with a lot of -ffixed-reg options, and omit saving
    these registers on the stack when entering a CPLB exception.
  * lose cli/nop/nop/sti sequences for some workarounds - these don't
  * make
    sense in an exception context

Additional code unification should be possible after this.

[Mike Frysinger <vapier.adi@gmail.com>:
 - convert CPP if statements to C if statements
 - remove redundant statements
 - use a do...while loop rather than a for loop to get slightly better
   optimization and to avoid gcc "may be used uninitialized" warnings ...
   we know that the [id]cplb_nr_bounds variables will never be 0, so this
   is OK
 - the no-mpu code was the last user of MAX_MEM_SIZE and with that rewritten,
   we can punt it
 - add some BUG_ON() checks to make sure we dont overflow the small
   cplb_bounds array
 - add i/d cplb entries for the bootrom because there is functions/data in
   there we want to access
 - we do not need a NULL trailing entry as any time we access the bounds
   arrays, we use the nr_bounds variable
]

Signed-off-by: Michael McTernan <mmcternan@airvana.com>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bernd Schmidt <bernds_cb1@t-online.de>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
  • Loading branch information
Bernd Schmidt authored and Bryan Wu committed Jan 7, 2009
1 parent 6651ece commit dbdf20d
Show file tree
Hide file tree
Showing 19 changed files with 515 additions and 1,442 deletions.
8 changes: 0 additions & 8 deletions arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -524,14 +524,6 @@ config MEM_SDGCTL
default 0x0
endmenu

config MAX_MEM_SIZE
int "Max SDRAM Memory Size in MBytes"
depends on !MPU
default 512
help
This is the max memory size that the kernel will create CPLB
tables for. Your system will not be able to handle any more.

#
# Max & Min Speeds for various Chips
#
Expand Down
39 changes: 39 additions & 0 deletions arch/blackfin/include/asm/context.S
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,42 @@
SYSCFG = [sp++];
csync;
.endm

.macro save_context_cplb
[--sp] = (R7:0, P5:0);
[--sp] = fp;

[--sp] = a0.x;
[--sp] = a0.w;
[--sp] = a1.x;
[--sp] = a1.w;

[--sp] = LC0;
[--sp] = LC1;
[--sp] = LT0;
[--sp] = LT1;
[--sp] = LB0;
[--sp] = LB1;

[--sp] = RETS;
.endm

.macro restore_context_cplb
RETS = [sp++];

LB1 = [sp++];
LB0 = [sp++];
LT1 = [sp++];
LT0 = [sp++];
LC1 = [sp++];
LC0 = [sp++];

a1.w = [sp++];
a1.x = [sp++];
a0.w = [sp++];
a0.x = [sp++];

fp = [sp++];

(R7:0, P5:0) = [SP++];
.endm
62 changes: 0 additions & 62 deletions arch/blackfin/include/asm/cplb-mpu.h

This file was deleted.

4 changes: 4 additions & 0 deletions arch/blackfin/include/asm/cplb.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,8 @@
#define CPLB_INOCACHE CPLB_USER_RD | CPLB_VALID
#define CPLB_IDOCACHE CPLB_INOCACHE | CPLB_L1_CHBL

#define FAULT_RW (1 << 16)
#define FAULT_USERSUPV (1 << 17)
#define FAULT_CPLBBITS 0x0000ffff

#endif /* _CPLB_H */
108 changes: 34 additions & 74 deletions arch/blackfin/include/asm/cplbinit.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,96 +32,56 @@

#include <asm/blackfin.h>
#include <asm/cplb.h>
#include <linux/threads.h>

#ifdef CONFIG_MPU

#include <asm/cplb-mpu.h>
extern void bfin_icache_init(struct cplb_entry *icplb_tbl);
extern void bfin_dcache_init(struct cplb_entry *icplb_tbl);

#ifdef CONFIG_CPLB_SWITCH_TAB_L1
# define PDT_ATTR __attribute__((l1_data))
#else
# define PDT_ATTR
#endif

#define INITIAL_T 0x1
#define SWITCH_T 0x2
#define I_CPLB 0x4
#define D_CPLB 0x8
struct cplb_entry {
unsigned long data, addr;
};

#define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M)
struct cplb_boundary {
unsigned long eaddr; /* End of this region. */
unsigned long data; /* CPLB data value. */
};

#define CPLB_MEM CONFIG_MAX_MEM_SIZE
extern struct cplb_boundary dcplb_bounds[];
extern struct cplb_boundary icplb_bounds[];
extern int dcplb_nr_bounds, icplb_nr_bounds;

/*
* Number of required data CPLB switchtable entries
* MEMSIZE / 4 (we mostly install 4M page size CPLBs
* approx 16 for smaller 1MB page size CPLBs for allignment purposes
* 1 for L1 Data Memory
* possibly 1 for L2 Data Memory
* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
* 1 for ASYNC Memory
*/
#define MAX_SWITCH_D_CPLBS (((CPLB_MEM / 4) + 16 + 1 + 1 + 1 \
+ ASYNC_MEMORY_CPLB_COVERAGE) * 2)
extern struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS];
extern struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS];
extern int first_switched_icplb;
extern int first_switched_dcplb;

/*
* Number of required instruction CPLB switchtable entries
* MEMSIZE / 4 (we mostly install 4M page size CPLBs
* approx 12 for smaller 1MB page size CPLBs for allignment purposes
* 1 for L1 Instruction Memory
* possibly 1 for L2 Instruction Memory
* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
*/
#define MAX_SWITCH_I_CPLBS (((CPLB_MEM / 4) + 12 + 1 + 1 + 1) * 2)

/* Number of CPLB table entries, used for cplb-nompu. */
#define CPLB_TBL_ENTRIES (16 * 4)

enum {
ZERO_P, L1I_MEM, L1D_MEM, L2_MEM, SDRAM_KERN, SDRAM_RAM_MTD, SDRAM_DMAZ,
RES_MEM, ASYNC_MEM, OCB_ROM
};
extern int nr_dcplb_miss[], nr_icplb_miss[], nr_icplb_supv_miss[];
extern int nr_dcplb_prot[], nr_cplb_flush[];

struct cplb_desc {
u32 start; /* start address */
u32 end; /* end address */
u32 psize; /* prefered size if any otherwise 1MB or 4MB*/
u16 attr;/* attributes */
u16 i_conf;/* I-CPLB DATA */
u16 d_conf;/* D-CPLB DATA */
u16 valid;/* valid */
const s8 name[30];/* name */
};
#ifdef CONFIG_MPU

struct cplb_tab {
u_long *tab;
u16 pos;
u16 size;
};
extern int first_mask_dcplb;

extern u_long icplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1];
extern u_long dcplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1];
extern int page_mask_order;
extern int page_mask_nelts;

/* Till here we are discussing about the static memory management model.
* However, the operating envoronments commonly define more CPLB
* descriptors to cover the entire addressable memory than will fit into
* the available on-chip 16 CPLB MMRs. When this happens, the below table
* will be used which will hold all the potentially required CPLB descriptors
*
* This is how Page descriptor Table is implemented in uClinux/Blackfin.
*/
extern unsigned long *current_rwx_mask[NR_CPUS];

extern u_long ipdt_tables[NR_CPUS][MAX_SWITCH_I_CPLBS+1];
extern u_long dpdt_tables[NR_CPUS][MAX_SWITCH_D_CPLBS+1];
#ifdef CONFIG_CPLB_INFO
extern u_long ipdt_swapcount_tables[NR_CPUS][MAX_SWITCH_I_CPLBS];
extern u_long dpdt_swapcount_tables[NR_CPUS][MAX_SWITCH_D_CPLBS];
#endif
extern void bfin_icache_init(u_long icplbs[]);
extern void bfin_dcache_init(u_long dcplbs[]);
extern void flush_switched_cplbs(unsigned int);
extern void set_mask_dcplbs(unsigned long *, unsigned int);

extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *);

#endif /* CONFIG_MPU */

extern void bfin_icache_init(struct cplb_entry *icplb_tbl);
extern void bfin_dcache_init(struct cplb_entry *icplb_tbl);

#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
extern void generate_cplb_tables_all(void);
extern void generate_cplb_tables_cpu(unsigned int cpu);
#endif
#endif
2 changes: 2 additions & 0 deletions arch/blackfin/include/asm/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@
/* This one pushes RETI without using CLI. Interrupts are enabled. */
#define SAVE_CONTEXT_SYSCALL save_context_syscall
#define SAVE_CONTEXT save_context_with_interrupts
#define SAVE_CONTEXT_CPLB save_context_cplb

#define RESTORE_ALL_SYS restore_context_no_interrupts
#define RESTORE_CONTEXT restore_context_with_interrupts
#define RESTORE_CONTEXT_CPLB restore_context_cplb

#endif /* __ASSEMBLY__ */
#endif /* __BFIN_ENTRY_H */
5 changes: 5 additions & 0 deletions arch/blackfin/kernel/cplb-mpu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@
#

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

CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
-ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \
-ffixed-M0 -ffixed-M1 -ffixed-M2 -ffixed-M3 \
-ffixed-B0 -ffixed-B1 -ffixed-B2 -ffixed-B3
4 changes: 4 additions & 0 deletions arch/blackfin/kernel/cplb-mpu/cplbinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,7 @@ void __init generate_cplb_tables_cpu(unsigned int cpu)
while (i_i < MAX_CPLBS)
icplb_tbl[cpu][i_i++].data = 0;
}

void generate_cplb_tables_all(void)
{
}
9 changes: 7 additions & 2 deletions arch/blackfin/kernel/cplb-mpu/cplbmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@
#include <asm/cplbinit.h>
#include <asm/mmu_context.h>

#define FAULT_RW (1 << 16)
#define FAULT_USERSUPV (1 << 17)
/*
* WARNING
*
* This file is compiled with certain -ffixed-reg options. We have to
* make sure not to call any functions here that could clobber these
* registers.
*/

int page_mask_nelts;
int page_mask_order;
Expand Down
7 changes: 6 additions & 1 deletion arch/blackfin/kernel/cplb-nompu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@
# arch/blackfin/kernel/cplb-nompu/Makefile
#

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

CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
-ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \
-ffixed-M0 -ffixed-M1 -ffixed-M2 -ffixed-M3 \
-ffixed-B0 -ffixed-B1 -ffixed-B2 -ffixed-B3
26 changes: 9 additions & 17 deletions arch/blackfin/kernel/cplb-nompu/cacheinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,15 @@
#include <asm/cplbinit.h>

#if defined(CONFIG_BFIN_ICACHE)
void __cpuinit bfin_icache_init(u_long icplb[])
void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl)
{
unsigned long *table = icplb;
unsigned long ctrl;
int i;

SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
unsigned long addr = *table++;
unsigned long data = *table++;
if (addr == (unsigned long)-1)
break;
bfin_write32(ICPLB_ADDR0 + i * 4, addr);
bfin_write32(ICPLB_DATA0 + i * 4, data);
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;
Expand All @@ -47,24 +43,20 @@ void __cpuinit bfin_icache_init(u_long icplb[])
#endif

#if defined(CONFIG_BFIN_DCACHE)
void __cpuinit bfin_dcache_init(u_long dcplb[])
void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl)
{
unsigned long *table = dcplb;
unsigned long ctrl;
int i;

SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
unsigned long addr = *table++;
unsigned long data = *table++;
if (addr == (unsigned long)-1)
break;
bfin_write32(DCPLB_ADDR0 + i * 4, addr);
bfin_write32(DCPLB_DATA0 + i * 4, data);
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
Loading

0 comments on commit dbdf20d

Please sign in to comment.