diff --git a/Makefile.am b/Makefile.am index 4e595a78..c2807025 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,13 +46,13 @@ nobase_include_HEADERS += \ metal/drivers/sifive_fe310-g000_lfrosc.h \ metal/drivers/sifive_fe310-g000_pll.h \ metal/drivers/sifive_fe310-g000_prci.h \ - metal/drivers/sifive_fu540-c000_l2.h \ metal/drivers/sifive_global-external-interrupts0.h \ metal/drivers/sifive_gpio-buttons.h \ metal/drivers/sifive_gpio-leds.h \ metal/drivers/sifive_gpio-switches.h \ metal/drivers/sifive_gpio0.h \ metal/drivers/sifive_i2c0.h \ + metal/drivers/sifive_l2pf0.h \ metal/drivers/sifive_local-external-interrupts0.h \ metal/drivers/sifive_pwm0.h \ metal/drivers/sifive_rtc0.h \ @@ -84,6 +84,7 @@ nobase_include_HEADERS += \ metal/pwm.h\ metal/rtc.h \ metal/shutdown.h \ + metal/scrub.h \ metal/spi.h \ metal/switch.h \ metal/timer.h \ @@ -113,13 +114,13 @@ libmetal_a_SOURCES = \ src/drivers/sifive_fe310-g000_lfrosc.c \ src/drivers/sifive_fe310-g000_pll.c \ src/drivers/sifive_fe310-g000_prci.c \ - src/drivers/sifive_fu540-c000_l2.c \ src/drivers/sifive_global-external-interrupts0.c \ src/drivers/sifive_gpio-buttons.c \ src/drivers/sifive_gpio-leds.c \ src/drivers/sifive_gpio-switches.c \ src/drivers/sifive_gpio0.c \ src/drivers/sifive_i2c0.c \ + src/drivers/sifive_l2pf0.c \ src/drivers/sifive_local-external-interrupts0.c \ src/drivers/sifive_pwm0.c \ src/drivers/sifive_rtc0.c \ diff --git a/Makefile.in b/Makefile.in index c1e13369..b25e33ca 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2017 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -242,13 +242,13 @@ am_libmetal_a_OBJECTS = src/drivers/fixed-clock.$(OBJEXT) \ src/drivers/sifive_fe310-g000_lfrosc.$(OBJEXT) \ src/drivers/sifive_fe310-g000_pll.$(OBJEXT) \ src/drivers/sifive_fe310-g000_prci.$(OBJEXT) \ - src/drivers/sifive_fu540-c000_l2.$(OBJEXT) \ src/drivers/sifive_global-external-interrupts0.$(OBJEXT) \ src/drivers/sifive_gpio-buttons.$(OBJEXT) \ src/drivers/sifive_gpio-leds.$(OBJEXT) \ src/drivers/sifive_gpio-switches.$(OBJEXT) \ src/drivers/sifive_gpio0.$(OBJEXT) \ src/drivers/sifive_i2c0.$(OBJEXT) \ + src/drivers/sifive_l2pf0.$(OBJEXT) \ src/drivers/sifive_local-external-interrupts0.$(OBJEXT) \ src/drivers/sifive_pwm0.$(OBJEXT) \ src/drivers/sifive_rtc0.$(OBJEXT) \ @@ -472,12 +472,12 @@ nobase_include_HEADERS = metal/machine.h metal/machine/inline.h \ metal/drivers/sifive_fe310-g000_lfrosc.h \ metal/drivers/sifive_fe310-g000_pll.h \ metal/drivers/sifive_fe310-g000_prci.h \ - metal/drivers/sifive_fu540-c000_l2.h \ metal/drivers/sifive_global-external-interrupts0.h \ metal/drivers/sifive_gpio-buttons.h \ metal/drivers/sifive_gpio-leds.h \ metal/drivers/sifive_gpio-switches.h \ metal/drivers/sifive_gpio0.h metal/drivers/sifive_i2c0.h \ + metal/drivers/sifive_l2pf0.h \ metal/drivers/sifive_local-external-interrupts0.h \ metal/drivers/sifive_pwm0.h metal/drivers/sifive_rtc0.h \ metal/drivers/sifive_spi0.h metal/drivers/sifive_test0.h \ @@ -488,9 +488,9 @@ nobase_include_HEADERS = metal/machine.h metal/machine/inline.h \ metal/hpm.h metal/i2c.h metal/init.h metal/interrupt.h \ metal/io.h metal/itim.h metal/led.h metal/lock.h \ metal/memory.h metal/pmp.h metal/privilege.h metal/pwm.h \ - metal/rtc.h metal/shutdown.h metal/spi.h metal/switch.h \ - metal/timer.h metal/time.h metal/tty.h metal/uart.h \ - metal/watchdog.h + metal/rtc.h metal/shutdown.h metal/scrub.h metal/spi.h \ + metal/switch.h metal/timer.h metal/time.h metal/tty.h \ + metal/uart.h metal/watchdog.h # This will generate these sources before the compilation step BUILT_SOURCES = \ @@ -518,13 +518,13 @@ libmetal_a_SOURCES = \ src/drivers/sifive_fe310-g000_lfrosc.c \ src/drivers/sifive_fe310-g000_pll.c \ src/drivers/sifive_fe310-g000_prci.c \ - src/drivers/sifive_fu540-c000_l2.c \ src/drivers/sifive_global-external-interrupts0.c \ src/drivers/sifive_gpio-buttons.c \ src/drivers/sifive_gpio-leds.c \ src/drivers/sifive_gpio-switches.c \ src/drivers/sifive_gpio0.c \ src/drivers/sifive_i2c0.c \ + src/drivers/sifive_l2pf0.c \ src/drivers/sifive_local-external-interrupts0.c \ src/drivers/sifive_pwm0.c \ src/drivers/sifive_rtc0.c \ @@ -813,9 +813,6 @@ src/drivers/sifive_fe310-g000_pll.$(OBJEXT): \ src/drivers/sifive_fe310-g000_prci.$(OBJEXT): \ src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) -src/drivers/sifive_fu540-c000_l2.$(OBJEXT): \ - src/drivers/$(am__dirstamp) \ - src/drivers/$(DEPDIR)/$(am__dirstamp) src/drivers/sifive_global-external-interrupts0.$(OBJEXT): \ src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) @@ -831,6 +828,8 @@ src/drivers/sifive_gpio0.$(OBJEXT): src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) src/drivers/sifive_i2c0.$(OBJEXT): src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) +src/drivers/sifive_l2pf0.$(OBJEXT): src/drivers/$(am__dirstamp) \ + src/drivers/$(DEPDIR)/$(am__dirstamp) src/drivers/sifive_local-external-interrupts0.$(OBJEXT): \ src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) @@ -991,13 +990,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_fe310-g000_lfrosc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_fe310-g000_pll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_fe310-g000_prci.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_fu540-c000_l2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_global-external-interrupts0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_gpio-buttons.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_gpio-leds.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_gpio-switches.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_gpio0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_i2c0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_l2pf0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_local-external-interrupts0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_pwm0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/sifive_rtc0.Po@am__quote@ @@ -1163,7 +1162,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -1189,7 +1188,7 @@ dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -1207,7 +1206,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -1217,7 +1216,7 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac diff --git a/aclocal.m4 b/aclocal.m4 index 2e4e7235..42ec7eed 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15.1 -*- Autoconf -*- +# generated automatically by aclocal 1.15 -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,7 +20,7 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# Copyright (C) 2002-2017 Free Software Foundation, Inc. +# Copyright (C) 2002-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -35,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.15.1], [], +m4_if([$1], [1.15], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -51,12 +51,12 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.15.1])dnl +[AM_AUTOMAKE_VERSION([1.15])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) -# Copyright (C) 2011-2017 Free Software Foundation, Inc. +# Copyright (C) 2011-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -118,7 +118,7 @@ AC_SUBST([AR])dnl # Figure out how to run the assembler. -*- Autoconf -*- -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -138,7 +138,7 @@ _AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -190,7 +190,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd` # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -221,7 +221,7 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -412,7 +412,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -488,7 +488,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -685,7 +685,7 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -706,7 +706,7 @@ if test x"${install_sh+set}" != xset; then fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2017 Free Software Foundation, Inc. +# Copyright (C) 2003-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -728,7 +728,7 @@ AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -763,7 +763,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -813,7 +813,7 @@ rm -f confinc confmf # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -852,7 +852,7 @@ fi # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -881,7 +881,7 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -928,7 +928,7 @@ AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -947,7 +947,7 @@ AC_DEFUN([AM_RUN_LOG], # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1028,7 +1028,7 @@ AC_CONFIG_COMMANDS_PRE( rm -f conftest.file ]) -# Copyright (C) 2009-2017 Free Software Foundation, Inc. +# Copyright (C) 2009-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1088,7 +1088,7 @@ AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1116,7 +1116,7 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2017 Free Software Foundation, Inc. +# Copyright (C) 2006-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1135,7 +1135,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2017 Free Software Foundation, Inc. +# Copyright (C) 2004-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/gloss/sys_sbrk.c b/gloss/sys_sbrk.c index a1b14b21..9cb42aec 100644 --- a/gloss/sys_sbrk.c +++ b/gloss/sys_sbrk.c @@ -1,3 +1,4 @@ +#include #include /* brk is handled entirely within the C library. This limits METAL programs @@ -35,6 +36,8 @@ char *_sbrk(ptrdiff_t incr) { __brk = &metal_segment_heap_target_end; return (void *)-1; } + /* Scrub out allocated memory to avoid spurious ECC errors */ + metal_mem_scrub(old, incr); return old; } diff --git a/metal/cache.h b/metal/cache.h index 6e676870..673a8b13 100644 --- a/metal/cache.h +++ b/metal/cache.h @@ -1,4 +1,4 @@ -/* Copyright 2018 SiFive, Inc */ +/* Copyright 2020 SiFive, Inc */ /* SPDX-License-Identifier: Apache-2.0 */ #ifndef METAL__CACHE_H @@ -11,39 +11,56 @@ */ #include -struct metal_cache; - -struct __metal_cache_vtable { - void (*init)(struct metal_cache *cache, int ways); - int (*get_enabled_ways)(struct metal_cache *cache); - int (*set_enabled_ways)(struct metal_cache *cache, int ways); -}; - /*! * @brief a handle for a cache + * Note: To be deprecated in next release. */ struct metal_cache { - const struct __metal_cache_vtable *vtable; + uint8_t __no_empty_structs; }; +/*! + * @brief Initialize L2 cache controller. + * Enables all available cache ways. + * @param None + * @return 0 If no error + */ +int metal_l2cache_init(void); + +/*! + * @brief Get the current number of enabled L2 cache ways + * @param None + * @return The current number of enabled L2 cache ways + */ +int metal_l2cache_get_enabled_ways(void); + +/*! + * @brief Enable the requested number of L2 cache ways + * @param ways Number of ways to enable + * @return 0 if the ways are successfully enabled + */ +int metal_l2cache_set_enabled_ways(int ways); + /*! * @brief Initialize a cache * @param cache The handle for the cache to initialize * @param ways The number of ways to enable * * Initializes a cache with the requested number of ways enabled. + * Note: API to be deprecated in next release. */ __inline__ void metal_cache_init(struct metal_cache *cache, int ways) { - cache->vtable->init(cache, ways); + metal_l2cache_init(); } /*! * @brief Get the current number of enabled cache ways * @param cache The handle for the cache * @return The current number of enabled cache ways + * Note: API to be deprecated in next release. */ __inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache) { - return cache->vtable->get_enabled_ways(cache); + return metal_l2cache_get_enabled_ways(); } /*! @@ -51,10 +68,11 @@ __inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache) { * @param cache The handle for the cache * @param ways The number of ways to enabled * @return 0 if the ways are successfully enabled + * Note: API to be deprecated in next release. */ __inline__ int metal_cache_set_enabled_ways(struct metal_cache *cache, int ways) { - return cache->vtable->set_enabled_ways(cache, ways); + return metal_l2cache_set_enabled_ways(ways); } /*! diff --git a/metal/drivers/sifive_ccache0.h b/metal/drivers/sifive_ccache0.h index b2038637..9af1cb3f 100644 --- a/metal/drivers/sifive_ccache0.h +++ b/metal/drivers/sifive_ccache0.h @@ -1,22 +1,139 @@ -/* Copyright 2019 SiFive, Inc */ +/* Copyright 2020 SiFive, Inc */ /* SPDX-License-Identifier: Apache-2.0 */ #ifndef METAL__DRIVERS__SIFIVE_CCACHE0_H #define METAL__DRIVERS__SIFIVE_CCACHE0_H -#include -#include +/*! + * @file sifive_ccache0.h + * + * @brief API for configuring the SiFive L2 cache controller + */ -struct __metal_driver_vtable_sifive_ccache0 { - struct __metal_cache_vtable cache; -}; +#include +#include -struct __metal_driver_sifive_ccache0; +/*! @brief Cache configuration data */ +typedef struct { + uint32_t num_bank; + uint32_t num_ways; + uint32_t num_sets; + uint32_t block_size; +} sifive_ccache0_config; -__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_ccache0) +/*! @brief Set of values for ECC error type */ +typedef enum { + SIFIVE_CCACHE0_DATA = 0, + SIFIVE_CCACHE0_DIR = 1, +} sifive_ccache0_ecc_errtype_t; -struct __metal_driver_sifive_ccache0 { - struct metal_cache cache; -}; +/*! @brief Initialize cache controller, enables all available + * cache-ways. + * @param None. + * @return 0 If no error.*/ +int sifive_ccache0_init(void); + +/*! @brief Get cache configuration data. + * @param config User specified data buffer. + * @return None.*/ +void sifive_ccache0_get_config(sifive_ccache0_config *config); + +/*! @brief Get currently active cache ways. + * @param None. + * @return Number of cache ways enabled.*/ +uint32_t sifive_ccache0_get_enabled_ways(void); + +/*! @brief Enable specified cache ways. + * @param ways Number of ways to be enabled. + * @return 0 If no error.*/ +int sifive_ccache0_set_enabled_ways(uint32_t ways); + +/*! @brief Inject ECC error into data or meta-data. + * @param bitindex Bit index to be corrupted on next cache operation. + * @param type ECC error target location. + * @return None.*/ +void sifive_ccache0_inject_ecc_error(uint32_t bitindex, + sifive_ccache0_ecc_errtype_t type); + +/*! @brief Flush out entire cache block containing given address. + * @param flush_addr Address for the cache block to be flushed. + * @return None.*/ +void sifive_ccache0_flush(uintptr_t flush_addr); + +/*! @brief Get most recently ECC corrected address. + * @param type ECC error target location. + * @return Last corrected ECC address.*/ +uintptr_t sifive_ccache0_get_ecc_fix_addr(sifive_ccache0_ecc_errtype_t type); + +/*! @brief Get number of times ECC errors were corrected. + * Clears related ECC interrupt signals. + * @param type ECC error target location. + * @return Corrected ECC error count.*/ +uint32_t sifive_ccache0_get_ecc_fix_count(sifive_ccache0_ecc_errtype_t type); + +/*! @brief Get address location of most recent uncorrected ECC error. + * @param type ECC error target location. + * @return Last uncorrected ECC address.*/ +uintptr_t sifive_ccache0_get_ecc_fail_addr(sifive_ccache0_ecc_errtype_t type); + +/*! @brief Get number of times ECC errors were not corrected. + * Clears related ECC interrupt signals. + * @param type ECC error target location. + * @return Uncorrected ECC error count.*/ +uint32_t sifive_ccache0_get_ecc_fail_count(sifive_ccache0_ecc_errtype_t type); + +/*! @brief Get currently active way enable mask value for the given master ID. + * @param master_id Cache controller master ID. + * @return Way enable mask. */ +uint64_t sifive_ccache0_get_way_mask(uint32_t master_id); + +/*! @brief Set way enable mask for the given master ID. + * @param master_id Cache controller master ID. + * @param waymask Specify ways to be enabled. + * @return 0 If no error.*/ +int sifive_ccache0_set_way_mask(uint32_t master_id, uint64_t waymask); + +/*! @brief Select cache performance events to be counted. + * @param counter Cache performance monitor counter index. + * @param mask Event selection mask. + * @return None.*/ +void sifive_ccache0_set_pmevent_selector(uint32_t counter, uint64_t mask); + +/*! @brief Get currently set events for the given counter index. + * @param counter Cache performance monitor counter index. + * @return Event selection mask.*/ +uint64_t sifive_ccache0_get_pmevent_selector(uint32_t counter); + +/*! @brief Clears specified cache performance counter. + * @param counter Cache performance monitor counter index. + * @return None.*/ +void sifive_ccache0_clr_pmevent_counter(uint32_t counter); + +/*! @brief Reads specified cache performance counter. + * @param counter Cache performance monitor counter index. + * @return Counter value.*/ +uint64_t sifive_ccache0_get_pmevent_counter(uint32_t counter); + +/*! @brief Select cache clients to be excluded from performance monitoring. + * @param mask Client disable mask. + * @return None.*/ +void sifive_ccache0_set_client_filter(uint64_t mask); + +/*! @brief Get currently set cache client disable mask. + * @param None. + * @return Client disable mask.*/ +uint64_t sifive_ccache0_get_client_filter(void); + +/*! @brief Get interrupt IDs for the cache controller. + * @param src Interrupt trigger source index. + * @return Interrupt id.*/ +int sifive_ccache0_get_interrupt_id(uint32_t src); + +/*! @brief Get interrupt controller of the cache. + * The interrupt controller must be initialized before any interrupts can be + * registered or enabled with it. + * @param None. + * @return Handle for the interrupt controller.*/ +struct metal_interrupt *sifive_ccache0_interrupt_controller(void); #endif diff --git a/metal/drivers/sifive_fu540-c000_l2.h b/metal/drivers/sifive_fu540-c000_l2.h deleted file mode 100644 index 08992024..00000000 --- a/metal/drivers/sifive_fu540-c000_l2.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2018 SiFive, Inc */ -/* SPDX-License-Identifier: Apache-2.0 */ - -#ifndef METAL__DRIVERS__SIFIVE_FU540_C000_L2_H -#define METAL__DRIVERS__SIFIVE_FU540_C000_L2_H - -#include -#include - -struct __metal_driver_vtable_sifive_fu540_c000_l2 { - struct __metal_cache_vtable cache; -}; - -struct __metal_driver_sifive_fu540_c000_l2; - -__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2) - -struct __metal_driver_sifive_fu540_c000_l2 { - struct metal_cache cache; -}; - -#endif diff --git a/metal/drivers/sifive_l2pf0.h b/metal/drivers/sifive_l2pf0.h new file mode 100644 index 00000000..63c8e653 --- /dev/null +++ b/metal/drivers/sifive_l2pf0.h @@ -0,0 +1,78 @@ +/* Copyright 2020 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_L2PF0_H +#define METAL__DRIVERS__SIFIVE_L2PF0_H + +/*! + * @file sifive_l2pf0.h + * + * @brief API for configuring the SiFive L2 prefetcher. + */ + +#include + +/*! @brief L2 prefetcher configuration */ +typedef struct { + /* Enable L2 hardware prefetcher */ + uint8_t HwPrefetchEnable; + + /* Only works when CrossPageEn === 0. + Cross Page optimization disable: + 0 -> Entry goes into Pause state while crossing Page boundary. + Next time when the demand miss happens on the same page, it doesn’t need + to train again. 1 -> The entry is invalidated in case of a cross page. */ + uint8_t CrossPageOptmDisable; + + /* Enable prefetches to cross pages */ + uint8_t CrossPageEn; + + /* Age-out mechanism enable */ + uint8_t AgeOutEn; + + uint32_t PrefetchDistance; + + uint32_t MaxAllowedDistance; + + /* Linear to exponential threshold */ + uint32_t LinToExpThreshold; + + /* No. of non-matching loads to edge out an entry */ + uint32_t NumLdsToAgeOut; + + /* Threshold no. of Fullness (L2 MSHRs used/ total available) to stop + * sending hits */ + uint32_t QFullnessThreshold; + + /* Threshold no. of CacheHits for evicting SPF entry */ + uint32_t HitCacheThreshold; + + /* Threshold no. of MSHR hits for increasing SPF distance */ + uint32_t hitMSHRThreshold; + + /* Size of the comparison window for address matching */ + uint32_t Window; + +} sifive_l2pf0_config; + +/*! @brief Enable L2 hardware prefetcher unit. + * @param None. + * @return None.*/ +void sifive_l2pf0_enable(void); + +/*! @brief Disable L2 hardware prefetcher unit. + * @param None. + * @return None.*/ +void sifive_l2pf0_disable(void); + +/*! @brief Get currently active L2 prefetcher configuration. + * @param config Pointer to user specified configuration structure. + * @return None.*/ +void sifive_l2pf0_get_config(sifive_l2pf0_config *config); + +/*! @brief Enables fine grain access to L2 prefetcher configuration. + * @param config Pointer to user structure with values to be set. + * @return None.*/ +void sifive_l2pf0_set_config(sifive_l2pf0_config *config); + +#endif diff --git a/metal/scrub.h b/metal/scrub.h new file mode 100644 index 00000000..51683cc7 --- /dev/null +++ b/metal/scrub.h @@ -0,0 +1,13 @@ +/* Copyright 2020 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__SCRUB_H +#define METAL__SCRUB_H + +/*! @brief Writes specified memory region with zeros. + * @param address Start memory address for zero-scrub. + * @param size Memory region size in bytes. + * @return None.*/ +void metal_mem_scrub(void *address, int size); + +#endif diff --git a/metal/tty.h b/metal/tty.h index fe4c000d..5d41783a 100644 --- a/metal/tty.h +++ b/metal/tty.h @@ -15,28 +15,11 @@ * Write a character to the default output device, which for most * targets is the UART serial port. * - * putc() does CR/LF mapping. - * putc_raw() does not. - * * @param c The character to write to the terminal * @return 0 on success, or -1 on failure. */ int metal_tty_putc(int c); -/*! - * @brief Write a raw character to the default output device - * - * Write a character to the default output device, which for most - * targets is the UART serial port. - * - * putc() does CR/LF mapping. - * putc_raw() does not. - * - * @param c The character to write to the terminal - * @return 0 on success, or -1 on failure. - */ -int metal_tty_putc_raw(int c); - /*! * @brief Get a byte from the default output device * diff --git a/src/cache.c b/src/cache.c index f1e09c37..09c270e4 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1,14 +1,45 @@ -/* Copyright 2018 SiFive, Inc */ +/* Copyright 2020 SiFive, Inc */ /* SPDX-License-Identifier: Apache-2.0 */ #include #include +/* Macros to generate driver prefix string */ +#ifdef METAL_CACHE_DRIVER_PREFIX +#define METAL_FUNC_STR(a, b) a##_##b +#define METAL_FUNC_STR_(a, b) METAL_FUNC_STR(a, b) +#define METAL_FUNC(x) METAL_FUNC_STR_(METAL_CACHE_DRIVER_PREFIX, x) +#endif + extern __inline__ void metal_cache_init(struct metal_cache *cache, int ways); extern __inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache); extern __inline__ int metal_cache_set_enabled_ways(struct metal_cache *cache, int ways); +int metal_l2cache_init(void) { +#ifdef METAL_CACHE_DRIVER_PREFIX + return METAL_FUNC(init)(); +#else + return -1; +#endif +} + +int metal_l2cache_get_enabled_ways(void) { +#ifdef METAL_CACHE_DRIVER_PREFIX + return METAL_FUNC(get_enabled_ways)(); +#else + return -1; +#endif +} + +int metal_l2cache_set_enabled_ways(int ways) { +#ifdef METAL_CACHE_DRIVER_PREFIX + return METAL_FUNC(set_enabled_ways)(ways); +#else + return -1; +#endif +} + int metal_dcache_l1_available(int hartid) { switch (hartid) { case 0: diff --git a/src/drivers/sifive_ccache0.c b/src/drivers/sifive_ccache0.c index f6461c5e..50847e71 100644 --- a/src/drivers/sifive_ccache0.c +++ b/src/drivers/sifive_ccache0.c @@ -1,4 +1,4 @@ -/* Copyright 2019 SiFive, Inc */ +/* Copyright 2020 SiFive, Inc */ /* SPDX-License-Identifier: Apache-2.0 */ #include @@ -7,80 +7,293 @@ #include #include -#include #include #include -#define L2_CONFIG_WAYS_SHIFT 8 -#define L2_CONFIG_WAYS_MASK (0xFF << L2_CONFIG_WAYS_SHIFT) +/* Macros to access memory mapped registers */ +#define REGW(x) *(volatile uint32_t *)(METAL_SIFIVE_CCACHE0_0_BASE_ADDRESS + x) -void __metal_driver_sifive_ccache0_init(struct metal_cache *l2, int ways); +#define REGD(x) *(volatile uint64_t *)(METAL_SIFIVE_CCACHE0_0_BASE_ADDRESS + x) -METAL_CONSTRUCTOR(metal_driver_sifive_ccache0_init) { -#ifdef __METAL_DT_SIFIVE_CCACHE0_HANDLE - /* Get the handle for the L2 cache controller */ - struct metal_cache *l2 = __METAL_DT_SIFIVE_CCACHE0_HANDLE; - if (!l2) { - return; +/* Macros to specify register bit shift */ +#define REG_SHIFT_4 4 +#define REG_SHIFT_8 8 +#define REG_SHIFT_16 16 +#define REG_SHIFT_24 24 + +#define SIFIVE_CCACHE0_BYTE_MASK 0xFFUL + +static int sifive_ccache0_interrupts[] = METAL_SIFIVE_CCACHE0_INTERRUPTS; + +/* Initialize cache at start-up via metal constructors */ +METAL_CONSTRUCTOR(_sifive_ccache0_init) { sifive_ccache0_init(); } + +int sifive_ccache0_init(void) { + int ret; + + sifive_ccache0_config config; + + /* Get cache configuration data */ + sifive_ccache0_get_config(&config); + + /* Enable ways */ + ret = sifive_ccache0_set_enabled_ways(config.num_ways); + + return ret; +} + +void sifive_ccache0_get_config(sifive_ccache0_config *config) { + uint32_t val; + + if (config) /* Check for NULL */ + { + val = REGW(METAL_SIFIVE_CCACHE0_CONFIG); + + /* Populate cache configuration data */ + config->num_bank = (val & SIFIVE_CCACHE0_BYTE_MASK); + config->num_ways = ((val >> REG_SHIFT_8) & SIFIVE_CCACHE0_BYTE_MASK); + /* no. of sets, block size is 2's power of register value + (2 << (value-1)) */ + config->num_sets = + 2 << (((val >> REG_SHIFT_16) & SIFIVE_CCACHE0_BYTE_MASK) - 1); + config->block_size = + 2 << (((val >> REG_SHIFT_24) & SIFIVE_CCACHE0_BYTE_MASK) - 1); + } +} + +uint32_t sifive_ccache0_get_enabled_ways(void) { + + uint32_t val = 0; + + val = SIFIVE_CCACHE0_BYTE_MASK & REGW(METAL_SIFIVE_CCACHE0_WAYENABLE); + + /* The stored number is the way index, so increment by 1 */ + val++; + + return val; +} + +int sifive_ccache0_set_enabled_ways(uint32_t ways) { + + int ret = 0; + + /* We can't decrease the number of enabled ways */ + if (sifive_ccache0_get_enabled_ways() > ways) { + ret = -1; + } else { + /* The stored value is the index, so subtract one */ + uint32_t value = 0xFF & (ways - 1); + + /* Set the number of enabled ways */ + REGW(METAL_SIFIVE_CCACHE0_WAYENABLE) = value; + + /* Make sure the number of ways was set correctly */ + if (sifive_ccache0_get_enabled_ways() != ways) { + ret = -2; + } } - /* Get the number of available ways per bank */ - unsigned long control_base = __metal_driver_sifive_ccache0_control_base(l2); - uint32_t ways = __METAL_ACCESS_ONCE( - (__metal_io_u32 *)(control_base + METAL_SIFIVE_CCACHE0_CONFIG)); - ways = ((ways & L2_CONFIG_WAYS_MASK) >> L2_CONFIG_WAYS_SHIFT); + return ret; +} - /* Enable all the ways */ - __metal_driver_sifive_ccache0_init(l2, ways); +void sifive_ccache0_inject_ecc_error(uint32_t bitindex, + sifive_ccache0_ecc_errtype_t type) { + /* Induce ECC error at given bit index and location */ + REGW(METAL_SIFIVE_CCACHE0_ECCINJECTERROR) = + (uint32_t)(((type & 0x01) << REG_SHIFT_16) | (bitindex & 0xFF)); +} + +void sifive_ccache0_flush(uintptr_t flush_addr) { + /* Block memory access until operation completed */ + __asm volatile("fence rw, io" : : : "memory"); + +#if __riscv_xlen == 32 + REGW(METAL_SIFIVE_CCACHE0_FLUSH32) = flush_addr >> REG_SHIFT_4; +#else + REGD(METAL_SIFIVE_CCACHE0_FLUSH64) = flush_addr; #endif + + __asm volatile("fence io, rw" : : : "memory"); } -void __metal_driver_sifive_ccache0_init(struct metal_cache *l2, int ways) { - metal_cache_set_enabled_ways(l2, ways); +uintptr_t sifive_ccache0_get_ecc_fix_addr(sifive_ccache0_ecc_errtype_t type) { + uintptr_t addr = 0; + + switch (type) { + /* Get most recently ECC corrected address */ + case SIFIVE_CCACHE0_DATA: + addr = (uintptr_t)REGD(METAL_SIFIVE_CCACHE0_DATECCFIXLOW); + break; + + case SIFIVE_CCACHE0_DIR: + addr = (uintptr_t)REGD(METAL_SIFIVE_CCACHE0_DIRECCFIXLOW); + break; + } + + return addr; } -int __metal_driver_sifive_ccache0_get_enabled_ways(struct metal_cache *cache) { - unsigned long control_base = - __metal_driver_sifive_ccache0_control_base(cache); +uint32_t sifive_ccache0_get_ecc_fix_count(sifive_ccache0_ecc_errtype_t type) { + uint32_t count = 0; + + switch (type) { + /* Get number of times ECC errors were corrected */ + case SIFIVE_CCACHE0_DATA: + count = REGW(METAL_SIFIVE_CCACHE0_DATECCFIXCOUNT); + break; - uint32_t way_enable = __METAL_ACCESS_ONCE( - (__metal_io_u32 *)(control_base + METAL_SIFIVE_CCACHE0_WAYENABLE)); + case SIFIVE_CCACHE0_DIR: + count = REGW(METAL_SIFIVE_CCACHE0_DIRECCFIXCOUNT); + break; + } - /* The stored number is the index, so add one */ - return (0xFF & way_enable) + 1; + return count; } -int __metal_driver_sifive_ccache0_set_enabled_ways(struct metal_cache *cache, - int ways) { - unsigned long control_base = - __metal_driver_sifive_ccache0_control_base(cache); +uintptr_t sifive_ccache0_get_ecc_fail_addr(sifive_ccache0_ecc_errtype_t type) { + uintptr_t addr = 0; - /* We can't decrease the number of enabled ways */ - if (metal_cache_get_enabled_ways(cache) > ways) { - return -2; + switch (type) { + /* Get address location of most recent uncorrected ECC error */ + case SIFIVE_CCACHE0_DATA: + addr = (uintptr_t)REGD(METAL_SIFIVE_CCACHE0_DATECCFAILLOW); + break; + + case SIFIVE_CCACHE0_DIR: + addr = (uintptr_t)REGD(METAL_SIFIVE_CCACHE0_DIRECCFAILLOW); + break; } - /* The stored value is the index, so subtract one */ - uint32_t value = 0xFF & (ways - 1); + return addr; +} + +uint32_t sifive_ccache0_get_ecc_fail_count(sifive_ccache0_ecc_errtype_t type) { + uint32_t count = 0; - /* Set the number of enabled ways */ - __METAL_ACCESS_ONCE( - (__metal_io_u32 *)(control_base + METAL_SIFIVE_CCACHE0_WAYENABLE)) = - value; + switch (type) { + /* Get number of times ECC errors were not corrected */ + case SIFIVE_CCACHE0_DATA: + count = REGW(METAL_SIFIVE_CCACHE0_DATECCFAILCOUNT); + break; - /* Make sure the number of ways was set correctly */ - if (metal_cache_get_enabled_ways(cache) != ways) { - return -3; + case SIFIVE_CCACHE0_DIR: + count = REGW(METAL_SIFIVE_CCACHE0_DIRECCFAILCOUNT); + break; } + return count; +} + +uint64_t sifive_ccache0_get_way_mask(uint32_t master_id) { + uint64_t val = 0; + + /* Get way mask for given master ID */ + val = REGD(METAL_SIFIVE_CCACHE0_WAYMASK0 + master_id * 8); + + return val; +} + +int sifive_ccache0_set_way_mask(uint32_t master_id, uint64_t waymask) { + + /* Set way mask for given master ID */ + REGD(METAL_SIFIVE_CCACHE0_WAYMASK0 + master_id * 8) = waymask; + return 0; } -__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_ccache0) = { - .cache.init = __metal_driver_sifive_ccache0_init, - .cache.get_enabled_ways = __metal_driver_sifive_ccache0_get_enabled_ways, - .cache.set_enabled_ways = __metal_driver_sifive_ccache0_set_enabled_ways, -}; +void sifive_ccache0_set_pmevent_selector(uint32_t counter, uint64_t mask) { + +#if METAL_SIFIVE_CCACHE0_PERFMON_COUNTERS > 0 + if (counter < METAL_SIFIVE_CCACHE0_PERFMON_COUNTERS) { + + /* Set event selector for specified L2 event counter */ + REGD(METAL_SIFIVE_CCACHE0_PMEVENTSELECT0 + counter * 8) = mask; + } +#endif + return; +} + +uint64_t sifive_ccache0_get_pmevent_selector(uint32_t counter) { + uint64_t val = 0; + +#if METAL_SIFIVE_CCACHE0_PERFMON_COUNTERS > 0 + if (counter < METAL_SIFIVE_CCACHE0_PERFMON_COUNTERS) { + + /* Get event selector for specified L2 event counter */ + val = REGD(METAL_SIFIVE_CCACHE0_PMEVENTSELECT0 + counter * 8); + } +#endif + return val; +} + +void sifive_ccache0_clr_pmevent_counter(uint32_t counter) { + +#if METAL_SIFIVE_CCACHE0_PERFMON_COUNTERS > 0 + if (counter < METAL_SIFIVE_CCACHE0_PERFMON_COUNTERS) { + /* Clear specified L2 event counter */ + REGD(METAL_SIFIVE_CCACHE0_PMEVENTCOUNTER0 + counter * 8) = 0; + } +#endif + return; +} + +uint64_t sifive_ccache0_get_pmevent_counter(uint32_t counter) { +#if __riscv_xlen == 32 + uint32_t vh = 0, vh1 = 0, vl = 0; +#else + uint64_t val = 0; +#endif +#if METAL_SIFIVE_CCACHE0_PERFMON_COUNTERS > 0 + if (counter < METAL_SIFIVE_CCACHE0_PERFMON_COUNTERS) { + /* Set counter register offset */ + counter *= 8; + +#if __riscv_xlen == 32 + do { + vh = REGW(METAL_SIFIVE_CCACHE0_PMEVENTCOUNTER0 + counter + 4); + vl = REGW(METAL_SIFIVE_CCACHE0_PMEVENTCOUNTER0 + counter); + vh1 = REGW(METAL_SIFIVE_CCACHE0_PMEVENTCOUNTER0 + counter + 4); + } while (vh != vh1); +#else + val = REGD(METAL_SIFIVE_CCACHE0_PMEVENTCOUNTER0 + counter); +#endif + } +#endif +#if __riscv_xlen == 32 + return ((((unsigned long long)vh) << 32) | vl); +#else + return val; +#endif +} + +void sifive_ccache0_set_client_filter(uint64_t mask) { + + /* Set clients to be excluded from performance monitoring */ + REGD(METAL_SIFIVE_CCACHE0_PMCLIENTFILTER) = mask; +} + +uint64_t sifive_ccache0_get_client_filter(void) { + uint64_t val = 0; + + /* Get currently active client filter mask */ + val = REGD(METAL_SIFIVE_CCACHE0_PMCLIENTFILTER); + + return val; +} + +int sifive_ccache0_get_interrupt_id(uint32_t src) { + int ret = 0; + + if (src < (uint32_t)sizeof(sifive_ccache0_interrupts) / sizeof(int)) { + ret = sifive_ccache0_interrupts[src]; + } + + return ret; +} + +struct metal_interrupt *sifive_ccache0_interrupt_controller(void) { + return METAL_SIFIVE_CCACHE0_INTERRUPT_PARENT; +} #endif diff --git a/src/drivers/sifive_fu540-c000_l2.c b/src/drivers/sifive_fu540-c000_l2.c deleted file mode 100644 index 1227ac83..00000000 --- a/src/drivers/sifive_fu540-c000_l2.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright 2018 SiFive, Inc */ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include - -#ifdef METAL_SIFIVE_FU540_C000_L2 - -#include -#include -#include -#include -#include - -#define L2_CONFIG_WAYS_SHIFT 8 -#define L2_CONFIG_WAYS_MASK (0xFF << L2_CONFIG_WAYS_SHIFT) - -void __metal_driver_sifive_fu540_c000_l2_init(struct metal_cache *l2, int ways); - -METAL_CONSTRUCTOR(metal_driver_sifive_fu540_c000_l2_init) { -#ifdef __METAL_DT_SIFIVE_FU540_C000_L2_HANDLE - /* Get the handle for the L2 cache controller */ - struct metal_cache *l2 = __METAL_DT_SIFIVE_FU540_C000_L2_HANDLE; - if (!l2) { - return; - } - - /* Get the number of available ways per bank */ - unsigned long control_base = - __metal_driver_sifive_fu540_c000_l2_control_base(l2); - uint32_t ways = __METAL_ACCESS_ONCE( - (__metal_io_u32 *)(control_base + METAL_SIFIVE_FU540_C000_L2_CONFIG)); - ways = ((ways & L2_CONFIG_WAYS_MASK) >> L2_CONFIG_WAYS_SHIFT); - - /* Enable all the ways */ - __metal_driver_sifive_fu540_c000_l2_init(l2, ways); -#endif -} - -void __metal_driver_sifive_fu540_c000_l2_init(struct metal_cache *l2, - int ways) { - metal_cache_set_enabled_ways(l2, ways); -} - -int __metal_driver_sifive_fu540_c000_l2_get_enabled_ways( - struct metal_cache *cache) { - unsigned long control_base = - __metal_driver_sifive_fu540_c000_l2_control_base(cache); - - uint32_t way_enable = __METAL_ACCESS_ONCE(( - __metal_io_u32 *)(control_base + METAL_SIFIVE_FU540_C000_L2_WAYENABLE)); - - /* The stored number is the index, so add one */ - return (0xFF & way_enable) + 1; -} - -int __metal_driver_sifive_fu540_c000_l2_set_enabled_ways( - struct metal_cache *cache, int ways) { - unsigned long control_base = - __metal_driver_sifive_fu540_c000_l2_control_base(cache); - - /* We can't decrease the number of enabled ways */ - if (metal_cache_get_enabled_ways(cache) > ways) { - return -2; - } - - /* The stored value is the index, so subtract one */ - uint32_t value = 0xFF & (ways - 1); - - /* Set the number of enabled ways */ - __METAL_ACCESS_ONCE( - (__metal_io_u32 *)(control_base + - METAL_SIFIVE_FU540_C000_L2_WAYENABLE)) = value; - - /* Make sure the number of ways was set correctly */ - if (metal_cache_get_enabled_ways(cache) != ways) { - return -3; - } - - return 0; -} - -__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2) = { - .cache.init = __metal_driver_sifive_fu540_c000_l2_init, - .cache.get_enabled_ways = - __metal_driver_sifive_fu540_c000_l2_get_enabled_ways, - .cache.set_enabled_ways = - __metal_driver_sifive_fu540_c000_l2_set_enabled_ways, -}; - -#endif - -typedef int no_empty_translation_units; diff --git a/src/drivers/sifive_l2pf0.c b/src/drivers/sifive_l2pf0.c new file mode 100644 index 00000000..63690fa3 --- /dev/null +++ b/src/drivers/sifive_l2pf0.c @@ -0,0 +1,164 @@ +/* Copyright 2020 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#ifdef METAL_SIFIVE_L2PF0 + +#include +#include + +/* Macros to access memory mapped registers */ +#define REGW(x) \ + *(volatile uint32_t *)(METAL_SIFIVE_L2PF0_0_BASE_ADDRESS + \ + hartid * 0x2000 + x) + +/* Macros for register bit masks */ +#define REG_MASK_BITWIDTH1 0x01 +#define REG_MASK_BITWIDTH4 0x0F +#define REG_MASK_BITWIDTH5 0x1F +#define REG_MASK_BITWIDTH6 0x3F +#define REG_MASK_BITWIDTH7 0x7F + +/* Macros to specify register bit shift */ +#define REG_BITSHIFT_1 1 +#define REG_BITSHIFT_2 2 +#define REG_BITSHIFT_4 4 +#define REG_BITSHIFT_8 8 +#define REG_BITSHIFT_9 9 +#define REG_BITSHIFT_13 13 +#define REG_BITSHIFT_14 14 +#define REG_BITSHIFT_20 20 +#define REG_BITSHIFT_21 21 +#define REG_BITSHIFT_28 28 + +/* Macros to capture trap, if L2PF does not exist for a hart id. */ +#define SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec) \ + __asm__ __volatile__("la %0, 1f \n\t" \ + "csrr %1, mtvec \n\t" \ + "csrw mtvec, %0 \n\t" \ + : "+r"(exit), "+r"(mtvec)) + +#define SIFIVE_L2PF0_TRAP_RESTORE(mtvec) \ + __asm__ __volatile__(".align 2 \n\t" \ + "1: \n\t" \ + "csrw mtvec, %0 \n\t" \ + : "+r"(mtvec)) + +void sifive_l2pf0_enable(void) { + volatile uintptr_t exit = 0, mtvec = 0; + int hartid; + __asm__ volatile("csrr %0, mhartid" : "=r"(hartid)); + + SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec); + + uint32_t val = REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL); + + /* Enable L2 prefetch unit for current hart */ + val |= REG_MASK_BITWIDTH1; + + REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL) = val; + + SIFIVE_L2PF0_TRAP_RESTORE(mtvec); +} + +void sifive_l2pf0_disable(void) { + volatile uintptr_t exit = 0, mtvec = 0; + int hartid; + __asm__ volatile("csrr %0, mhartid" : "=r"(hartid)); + + SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec); + + uint32_t val = REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL); + + /* Disable L2 prefetch unit for current hart */ + val &= ~REG_MASK_BITWIDTH1; + + REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL) = val; + + SIFIVE_L2PF0_TRAP_RESTORE(mtvec); +} + +void sifive_l2pf0_get_config(sifive_l2pf0_config *config) { + volatile uintptr_t exit = 0, mtvec = 0; + int hartid; + __asm__ volatile("csrr %0, mhartid" : "=r"(hartid)); + uint32_t val; + + SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec); + + if (config) /* Check for NULL */ + { + /* Get currently active L2 prefetch configuration values */ + val = REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL); + + config->HwPrefetchEnable = (val & REG_MASK_BITWIDTH1); + config->CrossPageOptmDisable = + ((val >> REG_BITSHIFT_1) & REG_MASK_BITWIDTH1); + config->PrefetchDistance = + ((val >> REG_BITSHIFT_2) & REG_MASK_BITWIDTH6); + config->MaxAllowedDistance = + ((val >> REG_BITSHIFT_8) & REG_MASK_BITWIDTH6); + config->LinToExpThreshold = + ((val >> REG_BITSHIFT_14) & REG_MASK_BITWIDTH6); + config->AgeOutEn = ((val >> REG_BITSHIFT_20) & REG_MASK_BITWIDTH1); + config->NumLdsToAgeOut = + ((val >> REG_BITSHIFT_21) & REG_MASK_BITWIDTH7); + config->CrossPageEn = ((val >> REG_BITSHIFT_28) & REG_MASK_BITWIDTH1); + + val = REGW(METAL_SIFIVE_L2PF0_USER_CONTROL); + + config->QFullnessThreshold = (val & REG_MASK_BITWIDTH4); + config->HitCacheThreshold = + ((val >> REG_BITSHIFT_4) & REG_MASK_BITWIDTH5); + config->hitMSHRThreshold = + ((val >> REG_BITSHIFT_9) & REG_MASK_BITWIDTH4); + config->Window = ((val >> REG_BITSHIFT_13) & REG_MASK_BITWIDTH6); + } + SIFIVE_L2PF0_TRAP_RESTORE(mtvec); +} + +void sifive_l2pf0_set_config(sifive_l2pf0_config *config) { + volatile uintptr_t exit = 0, mtvec = 0; + int hartid; + __asm__ volatile("csrr %0, mhartid" : "=r"(hartid)); + uint32_t val; + + SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec); + + if (config) /* Check for NULL */ + { + /* Get values from configuration to write into register */ + val = (uint32_t)( + (config->HwPrefetchEnable & REG_MASK_BITWIDTH1) | + ((config->CrossPageOptmDisable & REG_MASK_BITWIDTH1) + << REG_BITSHIFT_1) | + ((config->PrefetchDistance & REG_MASK_BITWIDTH6) + << REG_BITSHIFT_2) | + ((config->MaxAllowedDistance & REG_MASK_BITWIDTH6) + << REG_BITSHIFT_8) | + ((config->LinToExpThreshold & REG_MASK_BITWIDTH6) + << REG_BITSHIFT_14) | + ((config->AgeOutEn & REG_MASK_BITWIDTH1) << REG_BITSHIFT_20) | + ((config->NumLdsToAgeOut & REG_MASK_BITWIDTH7) << REG_BITSHIFT_21) | + ((config->CrossPageEn & REG_MASK_BITWIDTH1) << REG_BITSHIFT_28)); + + /* Set user specified L2 prefetch configuration values */ + REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL) = val; + + val = (uint32_t)( + (config->QFullnessThreshold & REG_MASK_BITWIDTH4) | + ((config->HitCacheThreshold & REG_MASK_BITWIDTH5) + << REG_BITSHIFT_4) | + ((config->hitMSHRThreshold & REG_MASK_BITWIDTH4) + << REG_BITSHIFT_9) | + ((config->Window & REG_MASK_BITWIDTH6) << REG_BITSHIFT_13)); + + REGW(METAL_SIFIVE_L2PF0_USER_CONTROL) = val; + } + SIFIVE_L2PF0_TRAP_RESTORE(mtvec); +} + +#endif + +typedef int no_empty_translation_units; diff --git a/src/scrub.S b/src/scrub.S index cb856910..08b4a73d 100644 --- a/src/scrub.S +++ b/src/scrub.S @@ -2,7 +2,7 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* - * Scrub memory with zero + * Scrub memory with zeroes */ /* Keep it in metal.init section with _enter */ @@ -11,9 +11,64 @@ .option push .option norelax -.type _metal_memory_scrub, @function -_metal_memory_scrub: - /* Zero out memory */ +/* Function to zero-scrub specified memory + * a0 : start address for zero-scrub + * a1 : size memory region size in bytes + */ +.global metal_mem_scrub +.type metal_mem_scrub, @function +metal_mem_scrub: + + /* Disable machine interrupts, + restore previous mstatus value at exit */ + li a3, 8 + csrrc t1, mstatus, a3 + +#if __riscv_xlen == 32 + addi t0, x0, 4 +1: + blt a1, t0, 2f + andi a2, a0, 3 + beqz a2, 3f +2: + sb x0, 0(a0) + addi a0, a0, 1 + addi a1, a1, -1 + bgtz a1, 1b + csrw mstatus, t1 + ret +3: + sw x0, 0(a0) + addi a0, a0, 4 + addi a1, a1, -4 + bgtz a1, 1b + csrw mstatus, t1 + ret +#else + addi t0, x0, 8 +1: + blt a1, t0, 2f + andi a2, a0, 7 + beqz a2, 3f +2: + sb x0, 0(a0) + addi a0, a0, 1 + addi a1, a1, -1 + bgtz a1, 1b + csrw mstatus, t1 + ret +3: + sd x0, 0(a0) + addi a0, a0, 8 + addi a1, a1, -8 + bgtz a1, 1b + csrw mstatus, t1 + ret +#endif + +.type __metal_memory_scrub, @function +__metal_memory_scrub: +/* Zero out specified memory regions */ 1: #if __riscv_xlen == 32 sw x0, 0(t1) @@ -27,9 +82,10 @@ _metal_memory_scrub: ret /* - * Initialize all memories available to zero - * This must be call before seting up any stack(s) + * Initialize memories to zero + * This must be called before setting up any stack(s) */ +.weak __metal_eccscrub_bit .weak __metal_before_start .global __metal_before_start .type __metal_before_start, @function @@ -42,81 +98,31 @@ __metal_before_start: la t0, __metal_boot_hart csrr a5, mhartid + /* Disable machine interrupts to be safe */ li a3, 8 csrc mstatus, a3 - bne a5, t0, wait_scrub - - /* Zero out itim memory. */ - .weak metal_itim_0_memory_start - .weak metal_itim_0_memory_end - la t1, metal_itim_0_memory_start - la t2, metal_itim_0_memory_end - beq t1, t2, dtim_scrub - jal _metal_memory_scrub - .weak metal_itim_1_memory_start - .weak metal_itim_1_memory_end - la t1, metal_itim_1_memory_start - la t2, metal_itim_1_memory_end - beq t1, t2, dtim_scrub - jal _metal_memory_scrub - -dtim_scrub: - /* Zero out dtim memory. */ - .weak metal_dtim_0_memory_start - .weak metal_dtim_0_memory_end - la t1, metal_dtim_0_memory_start - la t2, metal_dtim_0_memory_end - beq t1, t2, ils_scrub - jal _metal_memory_scrub - -ils_scrub: - /* Zero out ils memory. */ - .weak metal_ils_0_memory_start - .weak metal_ils_0_memory_end - la t1, metal_ils_0_memory_start - la t2, metal_ils_0_memory_end - beq t1, t2, dls_scrub - jal _metal_memory_scrub -dls_scrub: - /* Zero out dls memory. */ - .weak metal_dls_0_memory_start - .weak metal_dls_0_memory_end - la t1, metal_dls_0_memory_start - la t2, metal_dls_0_memory_end - beq t1, t2, sram_scrub - jal _metal_memory_scrub - -sram_scrub: - /* Zero out sram memory. */ - .weak metal_sys_sram_0_memory_start - .weak metal_sys_sram_0_memory_end - la t1, metal_sys_sram_0_memory_start - la t2, metal_sys_sram_0_memory_end - beq t1, t2, memory_scrub - jal _metal_memory_scrub - -memory_scrub: - /* Zero out main memory. */ - .weak metal_memory_0_memory_start - .weak metal_memory_0_memory_end - la t1, metal_memory_0_memory_start - la t2, metal_memory_0_memory_end - beq t1, t2, done_scrub - jal _metal_memory_scrub - -done_scrub: - lui a4, 0x2000 - li a5,1 - sw a5,0(a4) - fence w,rw - j skip_scrub + /* Zero out per hart stack */ + mv t1, sp + la t2, __stack_size + add t2, t2, sp + beq t1, t2, 1f + jal __metal_memory_scrub +1: + bne a5, t0, skip_scrub -wait_scrub: - lui a4, 0x2000 - lw a5, 0(a4) - beqz a5, wait_scrub + /* Zero out data segment */ + la t1, metal_segment_data_target_start + la t2, metal_segment_data_target_end + beq t1, t2, 1f + jal __metal_memory_scrub +1: + /* Zero out itim memory */ + la t1, metal_segment_itim_target_start + la t2, metal_segment_itim_target_end + beq t1, t2, skip_scrub + jal __metal_memory_scrub skip_scrub: /* Restore caller ra */ diff --git a/src/tty.c b/src/tty.c index c81bd273..62102b82 100644 --- a/src/tty.c +++ b/src/tty.c @@ -10,13 +10,6 @@ /* This implementation serves as a small shim that interfaces with the first * UART on a system. */ int metal_tty_putc(int c) { - if (c == '\n') { - metal_tty_putc_raw('\r'); - } - return metal_tty_putc_raw(c); -} - -int metal_tty_putc_raw(int c) { return metal_uart_putc(__METAL_DT_STDOUT_UART_HANDLE, c); }