From cf1f72ea339287cf6f780b2e34b8092ce08da6b0 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 13 Jun 2000 21:53:38 +0000 Subject: Moved i386 and m68k cache management code to libcpu. Everything now is an implementation of the prototypes in rtems/rtems/cache.h. The libcpu/i386/wrapup directory is no longer needed. The PowerPC needs this done to it. --- c/src/lib/libcpu/i386/Makefile.am | 28 +- c/src/lib/libcpu/i386/cache.c | 99 +++++++ c/src/lib/libcpu/i386/cache_.h | 16 ++ c/src/lib/libcpu/i386/cpu_asm.S | 117 --------- c/src/lib/libcpu/i386/idtr.S | 117 +++++++++ c/src/lib/libcpu/m68k/Makefile.am | 10 +- c/src/lib/libcpu/m68k/configure.in | 9 + c/src/lib/libcpu/m68k/shared/Makefile.am | 10 + c/src/lib/libcpu/m68k/shared/cache/Makefile.am | 38 +++ c/src/lib/libcpu/m68k/shared/cache/cache.c | 192 ++++++++++++++ c/src/lib/libcpu/m68k/shared/cache/cache_.h | 29 ++ c/src/lib/libcpu/shared/include/cache.h | 32 +++ c/src/lib/libcpu/shared/src/cache_aligned_malloc.c | 43 +++ c/src/lib/libcpu/shared/src/cache_manager.c | 292 +++++++++++++++++++++ 14 files changed, 898 insertions(+), 134 deletions(-) create mode 100644 c/src/lib/libcpu/i386/cache.c create mode 100644 c/src/lib/libcpu/i386/cache_.h delete mode 100644 c/src/lib/libcpu/i386/cpu_asm.S create mode 100644 c/src/lib/libcpu/i386/idtr.S create mode 100644 c/src/lib/libcpu/m68k/shared/Makefile.am create mode 100644 c/src/lib/libcpu/m68k/shared/cache/Makefile.am create mode 100644 c/src/lib/libcpu/m68k/shared/cache/cache.c create mode 100644 c/src/lib/libcpu/m68k/shared/cache/cache_.h create mode 100644 c/src/lib/libcpu/shared/include/cache.h create mode 100644 c/src/lib/libcpu/shared/src/cache_aligned_malloc.c create mode 100644 c/src/lib/libcpu/shared/src/cache_manager.c (limited to 'c/src/lib/libcpu') diff --git a/c/src/lib/libcpu/i386/Makefile.am b/c/src/lib/libcpu/i386/Makefile.am index 90e2d0bc8b..361711a181 100644 --- a/c/src/lib/libcpu/i386/Makefile.am +++ b/c/src/lib/libcpu/i386/Makefile.am @@ -5,15 +5,15 @@ AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal -LIBNAME = libcpu -LIB = $(ARCH)/$(LIBNAME).a +VPATH = @srcdir@:@srcdir@/../shared/src -C_FILES = cpu.c displayCpu.c page.c +C_FILES = cache.c cache_aligned_malloc.c cache_manager.c displayCpu.c idt.c page.c C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) -H_FILES = cpu.h registers.h cpuModel.h +H_FILES = cache_.h +INSTALLED_H_FILES = cpu.h registers.h cpuModel.h -S_FILES = cpu_asm.S cpuModel.S +S_FILES = cpuModel.S idtr.S S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o) OBJS = $(C_O_FILES) $(S_O_FILES) @@ -21,8 +21,7 @@ OBJS = $(C_O_FILES) $(S_O_FILES) include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../../../../../automake/lib.am -$(LIB): $(OBJS) - $(make-library) +AM_CPPFLAGS += -I$(srcdir) $(PROJECT_INCLUDE)/libcpu: $(mkinstalldirs) $@ @@ -30,19 +29,16 @@ $(PROJECT_INCLUDE)/libcpu: $(PROJECT_INCLUDE)/libcpu/%.h: %.h $(INSTALL_DATA) $< $@ -$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) +$(PROJECT_INCLUDE)/libcpu/cache.h: $(top_srcdir)/../shared/include/cache.h $(INSTALL_DATA) $< $@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu \ - $(H_FILES:%=$(PROJECT_INCLUDE)/libcpu/%) + $(PROJECT_INCLUDE)/libcpu/cache.h \ + $(INSTALLED_H_FILES:%=$(PROJECT_INCLUDE)/libcpu/%) -TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a +all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) -all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) $(LIB) $(TMPINSTALL_FILES) - -.PRECIOUS: $(LIB) - -EXTRA_DIST = cpu.c cpu.h cpuModel.S cpuModel.h cpu_asm.S displayCpu.c page.c \ - registers.h +EXTRA_DIST = cache.c cache_.h cpu.h cpuModel.S cpuModel.h \ + displayCpu.c idt.c idtr.S page.c registers.h include $(top_srcdir)/../../../../../automake/local.am diff --git a/c/src/lib/libcpu/i386/cache.c b/c/src/lib/libcpu/i386/cache.c new file mode 100644 index 0000000000..f462b58a1b --- /dev/null +++ b/c/src/lib/libcpu/i386/cache.c @@ -0,0 +1,99 @@ +/* + * Cache Management Support Routines for the i386 + * + * $Id$ + */ + +#include +#include +#include "cache_.h" + +void _CPU_disable_cache() { + cr0 regCr0; + + regCr0.i = i386_get_cr0(); + regCr0.cr0.page_level_cache_disable = 1; + regCr0.cr0.no_write_through = 1; + i386_set_cr0( regCr0.i ); + rtems_flush_entire_data_cache(); +} + +/* + * Enable the entire cache + */ + +void _CPU_enable_cache() { + cr0 regCr0; + + regCr0.i = i386_get_cr0(); + regCr0.cr0.page_level_cache_disable = 0; + regCr0.cr0.no_write_through = 0; + i386_set_cr0( regCr0.i ); + /*rtems_flush_entire_data_cache();*/ +} + +/* + * CACHE MANAGER: The following functions are CPU-specific. + * They provide the basic implementation for the rtems_* cache + * management routines. If a given function has no meaning for the CPU, + * it does nothing by default. + * + * FIXME: Definitions for I386_CACHE_ALIGNMENT are missing above for + * each CPU. The routines below should be implemented per CPU, + * to accomodate the capabilities of each. + */ + +/* FIXME: I don't belong here. */ +#define I386_CACHE_ALIGNMENT 16 + +#if defined(I386_CACHE_ALIGNMENT) +#define _CPU_DATA_CACHE_ALIGNMENT I386_CACHE_ALIGNMENT +#define _CPU_INST_CACHE_ALIGNEMNT I386_CACHE_ALIGNMENT + +void _CPU_flush_1_data_cache_line(const void *d_addr) {} +void _CPU_invalidate_1_data_cache_line(const void *d_addr) {} +void _CPU_freeze_data_cache(void) {} +void _CPU_unfreeze_data_cache(void) {} +void _CPU_invalidate_1_inst_cache_line ( const void *d_addr ) {} +void _CPU_freeze_inst_cache(void) {} +void _CPU_unfreeze_inst_cache(void) {} + +void _CPU_flush_entire_data_cache( + const void * d_addr +) +{ + asm volatile ("wbinvd"); +} +void _CPU_invalidate_entire_data_cache( + const void * d_addr +) +{ + asm volatile ("invd"); +} + +void _CPU_enable_data_cache(void) +{ + _CPU_enable_cache(); +} + +void _CPU_disable_data_cache(void) +{ + _CPU_disable_cache(); +} + +void _CPU_invalidate_entire_inst_cache(void) +{ + asm volatile ("invd"); +} + +void _CPU_enable_inst_cache(void) +{ + _CPU_enable_cache(); +} + +void _CPU_disable_inst_cache( void ) +{ + _CPU_disable_cache(); +} +#endif + diff --git a/c/src/lib/libcpu/i386/cache_.h b/c/src/lib/libcpu/i386/cache_.h new file mode 100644 index 0000000000..03ad537025 --- /dev/null +++ b/c/src/lib/libcpu/i386/cache_.h @@ -0,0 +1,16 @@ +/* + * i386 Cache Manager Wrapper + */ + +#ifndef __i386_CACHE_h +#define __i386_CACHE_h + +#define I386_CACHE_ALIGNMENT 16 +#define _CPU_DATA_CACHE_ALIGNMENT I386_CACHE_ALIGNMENT +#define _CPU_INST_CACHE_ALIGNEMNT I386_CACHE_ALIGNMENT + +#include + +#endif +/* end of include file */ + diff --git a/c/src/lib/libcpu/i386/cpu_asm.S b/c/src/lib/libcpu/i386/cpu_asm.S deleted file mode 100644 index 38dc7318ae..0000000000 --- a/c/src/lib/libcpu/i386/cpu_asm.S +++ /dev/null @@ -1,117 +0,0 @@ -/* cpu_asm.S - * - * This file contains all assembly code for the Intel i386 IDT - * manipulation. - * - * COPYRIGHT (c) 1998 valette@crf.canon.fr - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.OARcorp.com/rtems/license.html. - * - * $Id$ - */ - -#include - -BEGIN_CODE -/* - * C callable function enabling to get easilly usable info from - * the actual value of IDT register. - * -extern void i386_get_info_from_IDTR (interrupt_gate_descriptor** table, - unsigned* limit); - */ -PUBLIC (i386_get_info_from_IDTR) -PUBLIC (i386_set_IDTR) -PUBLIC (i386_get_info_from_GDTR) -PUBLIC (i386_set_GDTR) - -SYM (i386_get_info_from_IDTR): - movl 4(esp), ecx /* get location where table address */ - /* must be stored */ - movl 8(esp), edx /* get location table size must be stored */ - - subl $6, esp /* let room to prepare 48 bit IDTR */ - - sidt (esp) /* get 48 bit IDTR value */ - - movl 2(esp), eax /* get base */ - movl eax, (ecx) - - movzwl (esp), eax /* get limit */ - movl eax, (edx) - - addl $6, esp /* restore %esp */ - ret - -/* - * C callable function enabling to change the value of IDT register. Must be called - * with inmterrupt masked at processor level!!!. - * -extern void i386_set_IDTR (interrupt_gate_descriptor* table, - unsigned limit); - */ -SYM (i386_set_IDTR): - - leal 4(esp), edx /* load in edx address of input */ - /* parameter "table" */ - - movl (edx), eax /* load base into eax */ - movl 4(edx), ecx /* load limit into ecx */ - - movw cx, (edx) /* prepare 48 bit pointer */ - movl eax, 2(edx) - - lidt (edx) - - ret -/* - * - * C callable function enabling to get easilly usable info from - * the actual value of GDT register. -extern void i386_get_info_from_GDTR (segment_descriptors** table, - unsigned* limit); - */ - -SYM (i386_get_info_from_GDTR): - movl 4(esp), ecx /* get location where table address */ - /* must be stored */ - movl 8(esp), edx /* get location table size must be stored */ - - subl $6, esp /* let room to prepare 48 bit GDTR */ - - sgdt (esp) /* get 48 bit GDTR value */ - - movl 2(esp), eax /* get base */ - movl eax, (ecx) - - movzwl (esp), eax /* get limit */ - movl eax, (edx) - - addl $6, esp /* restore %esp */ - ret - -/* - * C callable function enabling to change the value of GDT register. - * Must be called with interrupts masked at processor level!!!. - * extern void i386_set_GDTR (segment_descriptors*, unsigned limit); - */ -SYM (i386_set_GDTR): - - leal 4(esp), edx /* load in edx address of input */ - /* parameter "table" */ - - movl (edx), eax /* load base into eax */ - movl 4(edx), ecx /* load limit into ecx */ - - movw cx, (edx) /* prepare 48 bit pointer */ - movl eax, 2(edx) - - lgdt (edx) - - ret - -END_CODE - -END diff --git a/c/src/lib/libcpu/i386/idtr.S b/c/src/lib/libcpu/i386/idtr.S new file mode 100644 index 0000000000..38dc7318ae --- /dev/null +++ b/c/src/lib/libcpu/i386/idtr.S @@ -0,0 +1,117 @@ +/* cpu_asm.S + * + * This file contains all assembly code for the Intel i386 IDT + * manipulation. + * + * COPYRIGHT (c) 1998 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include + +BEGIN_CODE +/* + * C callable function enabling to get easilly usable info from + * the actual value of IDT register. + * +extern void i386_get_info_from_IDTR (interrupt_gate_descriptor** table, + unsigned* limit); + */ +PUBLIC (i386_get_info_from_IDTR) +PUBLIC (i386_set_IDTR) +PUBLIC (i386_get_info_from_GDTR) +PUBLIC (i386_set_GDTR) + +SYM (i386_get_info_from_IDTR): + movl 4(esp), ecx /* get location where table address */ + /* must be stored */ + movl 8(esp), edx /* get location table size must be stored */ + + subl $6, esp /* let room to prepare 48 bit IDTR */ + + sidt (esp) /* get 48 bit IDTR value */ + + movl 2(esp), eax /* get base */ + movl eax, (ecx) + + movzwl (esp), eax /* get limit */ + movl eax, (edx) + + addl $6, esp /* restore %esp */ + ret + +/* + * C callable function enabling to change the value of IDT register. Must be called + * with inmterrupt masked at processor level!!!. + * +extern void i386_set_IDTR (interrupt_gate_descriptor* table, + unsigned limit); + */ +SYM (i386_set_IDTR): + + leal 4(esp), edx /* load in edx address of input */ + /* parameter "table" */ + + movl (edx), eax /* load base into eax */ + movl 4(edx), ecx /* load limit into ecx */ + + movw cx, (edx) /* prepare 48 bit pointer */ + movl eax, 2(edx) + + lidt (edx) + + ret +/* + * + * C callable function enabling to get easilly usable info from + * the actual value of GDT register. +extern void i386_get_info_from_GDTR (segment_descriptors** table, + unsigned* limit); + */ + +SYM (i386_get_info_from_GDTR): + movl 4(esp), ecx /* get location where table address */ + /* must be stored */ + movl 8(esp), edx /* get location table size must be stored */ + + subl $6, esp /* let room to prepare 48 bit GDTR */ + + sgdt (esp) /* get 48 bit GDTR value */ + + movl 2(esp), eax /* get base */ + movl eax, (ecx) + + movzwl (esp), eax /* get limit */ + movl eax, (edx) + + addl $6, esp /* restore %esp */ + ret + +/* + * C callable function enabling to change the value of GDT register. + * Must be called with interrupts masked at processor level!!!. + * extern void i386_set_GDTR (segment_descriptors*, unsigned limit); + */ +SYM (i386_set_GDTR): + + leal 4(esp), edx /* load in edx address of input */ + /* parameter "table" */ + + movl (edx), eax /* load base into eax */ + movl 4(edx), ecx /* load limit into ecx */ + + movw cx, (edx) /* prepare 48 bit pointer */ + movl eax, 2(edx) + + lgdt (edx) + + ret + +END_CODE + +END diff --git a/c/src/lib/libcpu/m68k/Makefile.am b/c/src/lib/libcpu/m68k/Makefile.am index 6e9cd33d32..7db5310a4b 100644 --- a/c/src/lib/libcpu/m68k/Makefile.am +++ b/c/src/lib/libcpu/m68k/Makefile.am @@ -5,7 +5,15 @@ AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal -SUBDIRS = m68040 +if shared +SHARED_LIB = shared +endif + +if m68040 +CPU_SUBDIR = m68040 +endif + +SUBDIRS = $(SHARED_LIB) $(CPU_SUBDIR) include $(top_srcdir)/../../../../../automake/subdirs.am include $(top_srcdir)/../../../../../automake/local.am diff --git a/c/src/lib/libcpu/m68k/configure.in b/c/src/lib/libcpu/m68k/configure.in index efcd7c5b7e..808e02c0ba 100644 --- a/c/src/lib/libcpu/m68k/configure.in +++ b/c/src/lib/libcpu/m68k/configure.in @@ -26,10 +26,19 @@ RTEMS_CANONICALIZE_TOOLS RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP) RTEMS_CHECK_BSP_CACHE(RTEMS_BSP) +AM_CONDITIONAL(shared, test "$RTEMS_CPU_MODEL" = "m68020" \ +|| test "$RTEMS_CPU_MODEL" = "m68020" \ +|| test "$RTEMS_CPU_MODEL" = "m68030" \ +|| test "$RTEMS_CPU_MODEL" = "m68lc040" \ +|| test "$RTEMS_CPU_MODEL" = "m68040" \ +|| test "$RTEMS_CPU_MODEL" = "m68060" ) + AM_CONDITIONAL(m68040, test "$RTEMS_CPU_MODEL" = "m68040") # Explicitly list all Makefiles here AC_OUTPUT( Makefile +shared/Makefile +shared/cache/Makefile m68040/Makefile m68040/fpsp/Makefile) diff --git a/c/src/lib/libcpu/m68k/shared/Makefile.am b/c/src/lib/libcpu/m68k/shared/Makefile.am new file mode 100644 index 0000000000..3f7ad1d7a6 --- /dev/null +++ b/c/src/lib/libcpu/m68k/shared/Makefile.am @@ -0,0 +1,10 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +SUBDIRS = cache + +include $(top_srcdir)/../../../../../automake/subdirs.am +include $(top_srcdir)/../../../../../automake/local.am diff --git a/c/src/lib/libcpu/m68k/shared/cache/Makefile.am b/c/src/lib/libcpu/m68k/shared/cache/Makefile.am new file mode 100644 index 0000000000..d94c4388c9 --- /dev/null +++ b/c/src/lib/libcpu/m68k/shared/cache/Makefile.am @@ -0,0 +1,38 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 +ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal + +VPATH = @srcdir@:@srcdir@/../../../shared/src + +C_FILES = cache.c cache_aligned_malloc.c cache_manager.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +H_FILES = cache_.h +INSTALLED_H_FILES = + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../automake/lib.am + +AM_CPPFLAGS += -I$(srcdir) + +$(PROJECT_INCLUDE)/libcpu: + $(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/libcpu/%.h: %.h + $(INSTALL_DATA) $< $@ + +$(PROJECT_INCLUDE)/libcpu/cache.h: $(top_srcdir)/../shared/include/cache.h + $(INSTALL_DATA) $< $@ + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu $(PROJECT_INCLUDE)/libcpu/cache.h + +all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) + +EXTRA_DIST = cache.c cache_.h + +include $(top_srcdir)/../../../../../automake/local.am diff --git a/c/src/lib/libcpu/m68k/shared/cache/cache.c b/c/src/lib/libcpu/m68k/shared/cache/cache.c new file mode 100644 index 0000000000..ce98f006c6 --- /dev/null +++ b/c/src/lib/libcpu/m68k/shared/cache/cache.c @@ -0,0 +1,192 @@ +/* + * Cache Management Support Routines for the MC68040 + * + * $Id$ + */ + +#include +#include "cache_.h" + +/* + * Since the cacr is common to all mc680x0, provide macros + * for masking values in that register. + */ + +/* + * Used to clear bits in the cacr. + */ +#define _CPU_CACR_AND(mask) \ + { \ + register unsigned long _value = mask; \ + register unsigned long _ctl = 0; \ + asm volatile ( "movec %%cacr, %0; /* read the cacr */ \ + andl %2, %0; /* and with _val */ \ + movec %1, %%cacr" /* write the cacr */ \ + : "=d" (_ctl) : "0" (_ctl), "d" (_value) : "%%cc" ); \ + } + + +/* + * Used to set bits in the cacr. + */ +#define _CPU_CACR_OR(mask) \ + { \ + register unsigned long _value = mask; \ + register unsigned long _ctl = 0; \ + asm volatile ( "movec %%cacr, %0; /* read the cacr */ \ + orl %2, %0; /* or with _val */ \ + movec %1, %%cacr" /* write the cacr */ \ + : "=d" (_ctl) : "0" (_ctl), "d" (_value) : "%%cc" ); \ + } + + +/* + * CACHE MANAGER: The following functions are CPU-specific. + * They provide the basic implementation for the rtems_* cache + * management routines. If a given function has no meaning for the CPU, + * it does nothing by default. + */ +#if ( defined(__mc68020__) || defined(__mc68030__) ) + +#if defined(__mc68030__) + +/* Only the mc68030 has a data cache; it is writethrough only. */ + +void _CPU_flush_1_data_cache_line ( const void * d_addr ) {} +void _CPU_flush_entire_data_cache ( const void * d_addr ) {} + +void _CPU_invalidate_1_data_cache_line ( + const void * d_addr ) +{ + void * p_address = (void *) _CPU_virtual_to_physical( d_addr ); + asm volatile ( "movec %0, %%caar" :: "a" (p_address) ); /* write caar */ + _CPU_CACR_OR(0x00000400); +} + +void _CPU_invalidate_entire_data_cache ( void ) +{ + _CPU_CACR_OR( 0x00000800 ); +} + +void _CPU_freeze_data_cache ( void ) +{ + _CPU_CACR_OR( 0x00000200 ); +} + +void _CPU_unfreeze_data_cache ( void ) +{ + _CPU_CACR_AND( 0xFFFFFDFF ); +} + +void _CPU_enable_data_cache ( void ) +{ + _CPU_CACR_OR( 0x00000100 ); +} +void _CPU_disable_data_cache ( void ) +{ + _CPU_CACR_AND( 0xFFFFFEFF ); +} +#endif + + +/* Both the 68020 and 68030 have instruction caches */ + +void _CPU_invalidate_1_inst_cache_line ( + const void * d_addr ) +{ + void * p_address = (void *) _CPU_virtual_to_physical( d_addr ); + asm volatile ( "movec %0, %%caar" :: "a" (p_address) ); /* write caar */ + _CPU_CACR_OR( 0x00000004 ); +} + +void _CPU_invalidate_entire_inst_cache ( void ) +{ + _CPU_CACR_OR( 0x00000008 ); +} + +void _CPU_freeze_inst_cache ( void ) +{ + _CPU_CACR_OR( 0x00000002); +} + +void _CPU_unfreeze_inst_cache ( void ) +{ + _CPU_CACR_AND( 0xFFFFFFFD ); +} + +void _CPU_enable_inst_cache ( void ) +{ + _CPU_CACR_OR( 0x00000001 ); +} + +void _CPU_disable_inst_cache ( void ) +{ + _CPU_CACR_AND( 0xFFFFFFFE ); +} + + +#elif ( defined(__mc68040__) || defined (__mc68060__) ) + +/* Cannot be frozen */ +void _CPU_freeze_data_cache ( void ) {} +void _CPU_unfreeze_data_cache ( void ) {} +void _CPU_freeze_inst_cache ( void ) {} +void _CPU_unfreeze_inst_cache ( void ) {} + +void _CPU_flush_1_data_cache_line ( + const void * d_addr ) +{ + void * p_address = (void *) _CPU_virtual_to_physical( d_addr ); + asm volatile ( "cpushl %%dc,(%0)" :: "a" (p_address) ); +} + +void _CPU_invalidate_1_data_cache_line ( + const void * d_addr ) +{ + void * p_address = (void *) _CPU_virtual_to_physical( d_addr ); + asm volatile ( "cinvl %%dc,(%0)" :: "a" (p_address) ); +} + +void _CPU_flush_entire_data_cache ( void ) +{ + asm volatile ( "cpusha %%dc" :: ); +} + +void _CPU_invalidate_entire_data_cache ( void ) +{ + asm volatile ( "cinva %%dc" :: ); +} + +void _CPU_enable_data_cache ( void ) +{ + _CPU_CACR_OR( 0x80000000 ); +} + +void _CPU_disable_data_cache ( void ) +{ + _CPU_CACR_AND( 0x7FFFFFFF ); +} + +void _CPU_invalidate_1_inst_cache_line ( + const void * i_addr ) +{ + void * p_address = (void *) _CPU_virtual_to_physical( i_addr ); + asm volatile ( "cinvl %%ic,(%0)" :: "a" (p_address) ); +} + +void _CPU_invalidate_entire_inst_cache ( void ) +{ + asm volatile ( "cinva %%ic" :: ); +} + +void _CPU_enable_inst_cache ( void ) +{ + _CPU_CACR_OR( 0x00008000 ); +} + +void _CPU_disable_inst_cache ( void ) +{ + _CPU_CACR_AND( 0xFFFF7FFF ); +} +#endif +/* end of file */ diff --git a/c/src/lib/libcpu/m68k/shared/cache/cache_.h b/c/src/lib/libcpu/m68k/shared/cache/cache_.h new file mode 100644 index 0000000000..13406b3c49 --- /dev/null +++ b/c/src/lib/libcpu/m68k/shared/cache/cache_.h @@ -0,0 +1,29 @@ +/* + * M68K Cache Manager Support + */ + +#ifndef __M68K_CACHE_h +#define __M68K_CACHE_h + +#if defined(__mc68020__) +#define M68K_INST_CACHE_ALIGNMENT 16 +#elif defined(__mc68030__) +#define M68K_INST_CACHE_ALIGNMENT 16 +#define M68K_DATA_CACHE_ALIGNMENT 16 +#elif ( defined(__mc68040__) || defined (__mc68060__) ) +#define M68K_INST_CACHE_ALIGNMENT 16 +#define M68K_DATA_CACHE_ALIGNMENT 16 +#endif + +#if defined(M68K_DATA_CACHE_ALIGNMENT) +#define _CPU_DATA_CACHE_ALIGNMENT M68K_DATA_CACHE_ALIGNMENT +#endif + +#if defined(M68K_INST_CACHE_ALIGNMENT) +#define _CPU_INST_CACHE_ALIGNMENT M68K_INST_CACHE_ALIGNMENT +#endif + +#include + +#endif +/* end of include file */ diff --git a/c/src/lib/libcpu/shared/include/cache.h b/c/src/lib/libcpu/shared/include/cache.h new file mode 100644 index 0000000000..d2ec92686d --- /dev/null +++ b/c/src/lib/libcpu/shared/include/cache.h @@ -0,0 +1,32 @@ +/* + * libcpu Cache Manager Support + * + * $Id$ + */ + +#ifndef __LIBCPU_CACHE_h +#define __LIBCPU_CACHE_h + +#include + +void _CPU_disable_cache(); +void _CPU_enable_cache(); + +void _CPU_flush_1_data_cache_line(const void *d_addr); +void _CPU_invalidate_1_data_cache_line(const void *d_addr); +void _CPU_freeze_data_cache(void); +void _CPU_unfreeze_data_cache(void); +void _CPU_invalidate_1_inst_cache_line(const void *d_addr); +void _CPU_freeze_inst_cache(void); +void _CPU_unfreeze_inst_cache(void); + +void _CPU_flush_entire_data_cache(void); +void _CPU_invalidate_entire_data_cache(void); +void _CPU_enable_data_cache(void); +void _CPU_disable_data_cache(void); +void _CPU_invalidate_entire_inst_cache(void); +void _CPU_enable_inst_cache(void); +void _CPU_disable_inst_cache(void); + +#endif +/* end of include file */ diff --git a/c/src/lib/libcpu/shared/src/cache_aligned_malloc.c b/c/src/lib/libcpu/shared/src/cache_aligned_malloc.c new file mode 100644 index 0000000000..3289317132 --- /dev/null +++ b/c/src/lib/libcpu/shared/src/cache_aligned_malloc.c @@ -0,0 +1,43 @@ +/* + * RTEMS Cache Aligned Malloc + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include + +/* + * rtems_cache_aligned_malloc + * + * DESCRIPTION: + * + * This function is used to allocate storage that spans an + * integral number of cache blocks. + */ + +void *rtems_cache_aligned_malloc ( + size_t nbytes +) +{ + /* + * Arrange to have the user storage start on the first cache + * block beyond the header. + */ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + return (void *) ((((unsigned long) + malloc( nbytes + _CPU_DATA_CACHE_ALIGNMENT - 1 )) + + _CPU_DATA_CACHE_ALIGNMENT - 1 ) &(~(_CPU_DATA_CACHE_ALIGNMENT - 1)) ); +#else + return malloc( nbytes ); +#endif +} + diff --git a/c/src/lib/libcpu/shared/src/cache_manager.c b/c/src/lib/libcpu/shared/src/cache_manager.c new file mode 100644 index 0000000000..e55cf7ea05 --- /dev/null +++ b/c/src/lib/libcpu/shared/src/cache_manager.c @@ -0,0 +1,292 @@ +/* + * Cache Manager + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * + * The functions in this file implement the API to the RTEMS Cache Manager and + * are divided into data cache and instruction cache functions. Data cache + * functions are only declared if a data cache is supported. Instruction + * cache functions are only declared if an instruction cache is supported. + * Support for a particular cache exists only if _CPU_x_CACHE_ALIGNMENT is + * defined, where x E {DATA, INST}. These definitions are found in the CPU + * dependent source files in the supercore, often + * + * rtems/c/src/exec/score/cpu/CPU/rtems/score/CPU.h + * + * The functions below are implemented with CPU dependent inline routines + * also found in the above file. In the event that a CPU does not support a + * specific function, the CPU dependent routine does nothing (but does exist). + * + * At this point, the Cache Manager makes no considerations, and provides no + * support for BSP specific issues such as a secondary cache. In such a system, + * the CPU dependent routines would have to be modified, or a BSP layer added + * to this Manager. + */ + +#include +#include +#include +#include "cache_.h" + + +/* + * THESE FUNCTIONS ONLY HAVE BODIES IF WE HAVE A DATA CACHE + */ + +/* + * This function is called to flush the data cache by performing cache + * copybacks. It must determine how many cache lines need to be copied + * back and then perform the copybacks. + */ +void +rtems_flush_multiple_data_cache_lines( const void * d_addr, size_t n_bytes ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + const void * final_address; + + /* + * Set d_addr to the beginning of the cache line; final_address indicates + * the last address_t which needs to be pushed. Increment d_addr and push + * the resulting line until final_address is passed. + */ + + final_address = (void *)((size_t)d_addr + n_bytes - 1); + d_addr = (void *)((size_t)d_addr & ~(_CPU_DATA_CACHE_ALIGNMENT - 1)); + while( d_addr <= final_address ) { + _CPU_flush_1_data_cache_line( d_addr ); + d_addr = (void *)((size_t)d_addr + _CPU_DATA_CACHE_ALIGNMENT); + } +#endif +} + + +/* + * This function is responsible for performing a data cache invalidate. + * It must determine how many cache lines need to be invalidated and then + * perform the invalidations. + */ + +void +rtems_invalidate_multiple_data_cache_lines( const void * d_addr, size_t n_bytes ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + const void * final_address; + + /* + * Set d_addr to the beginning of the cache line; final_address indicates + * the last address_t which needs to be invalidated. Increment d_addr and + * invalidate the resulting line until final_address is passed. + */ + + final_address = (void *)((size_t)d_addr + n_bytes - 1); + d_addr = (void *)((size_t)d_addr & ~(_CPU_DATA_CACHE_ALIGNMENT - 1)); + while( final_address > d_addr ) { + _CPU_invalidate_1_data_cache_line( d_addr ); + d_addr = (void *)((size_t)d_addr + _CPU_DATA_CACHE_ALIGNMENT); + } +#endif +} + + +/* + * This function is responsible for performing a data cache flush. + * It flushes the entire cache. + */ +void +rtems_flush_entire_data_cache( void ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + /* + * Call the CPU-specific routine + */ + _CPU_flush_entire_data_cache(); +#endif +} + + +/* + * This function is responsible for performing a data cache + * invalidate. It invalidates the entire cache. + */ +void +rtems_invalidate_entire_data_cache( void ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + /* + * Call the CPU-specific routine + */ + + _CPU_invalidate_entire_data_cache(); +#endif +} + + +/* + * This function returns the data cache granularity. + */ +int +rtems_get_data_cache_line_size( void ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + return _CPU_DATA_CACHE_ALIGNMENT; +#else + return 0; +#endif +} + + +/* + * This function freezes the data cache; cache lines + * are not replaced. + */ +void +rtems_freeze_data_cache( void ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + _CPU_freeze_data_cache(); +#endif +} + + +/* + * This function unfreezes the instruction cache. + */ +void rtems_unfreeze_data_cache( void ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + _CPU_unfreeze_data_cache(); +#endif +} + + +/* Turn on the data cache. */ +void +rtems_enable_data_cache( void ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + _CPU_enable_data_cache(); +#endif +} + + +/* Turn off the data cache. */ +void +rtems_disable_data_cache( void ) +{ +#if defined(_CPU_DATA_CACHE_ALIGNMENT) + _CPU_disable_data_cache(); +#endif +} + + + +/* + * THESE FUNCTIONS ONLY HAVE BODIES IF WE HAVE AN INSTRUCTION CACHE + */ + +/* + * This function is responsible for performing an instruction cache + * invalidate. It must determine how many cache lines need to be invalidated + * and then perform the invalidations. + */ +void +rtems_invalidate_multiple_inst_cache_lines( const void * i_addr, size_t n_bytes ) +{ +#if defined(_CPU_INST_CACHE_ALIGNMENT) + const void * final_address; + + /* + * Set i_addr to the beginning of the cache line; final_address indicates + * the last address_t which needs to be invalidated. Increment i_addr and + * invalidate the resulting line until final_address is passed. + */ + + final_address = (void *)((size_t)i_addr + n_bytes - 1); + i_addr = (void *)((size_t)i_addr & ~(_CPU_INST_CACHE_ALIGNMENT - 1)); + while( final_address > i_addr ) { + _CPU_invalidate_1_inst_cache_line( i_addr ); + i_addr = (void *)((size_t)i_addr + _CPU_INST_CACHE_ALIGNMENT); + } +#endif +} + + +/* + * This function is responsible for performing an instruction cache + * invalidate. It invalidates the entire cache. + */ +void +rtems_invalidate_entire_inst_cache( void ) +{ +#if defined(_CPU_INST_CACHE_ALIGNMENT) + /* + * Call the CPU-specific routine + */ + + _CPU_invalidate_entire_inst_cache(); +#endif +} + + +/* + * This function returns the instruction cache granularity. + */ +int +rtems_get_inst_cache_line_size( void ) +{ +#if defined(_CPU_INST_CACHE_ALIGNMENT) + return _CPU_INST_CACHE_ALIGNMENT; +#else + return 0; +#endif +} + + +/* + * This function freezes the instruction cache; cache lines + * are not replaced. + */ +void +rtems_freeze_inst_cache( void ) +{ +#if defined(_CPU_INST_CACHE_ALIGNMENT) + _CPU_freeze_inst_cache(); +#endif +} + + +/* + * This function unfreezes the instruction cache. + */ +void rtems_unfreeze_inst_cache( void ) +{ +#if defined(_CPU_INST_CACHE_ALIGNMENT) + _CPU_unfreeze_inst_cache(); +#endif +} + + +/* Turn on the instruction cache. */ +void +rtems_enable_inst_cache( void ) +{ +#if defined(_CPU_INST_CACHE_ALIGNMENT) + _CPU_enable_inst_cache(); +#endif +} + + +/* Turn off the instruction cache. */ +void +rtems_disable_inst_cache( void ) +{ +#if defined(_CPU_INST_CACHE_ALIGNMENT) + _CPU_disable_inst_cache(); +#endif +} -- cgit v1.2.3