[PATCH 1/3] score/sparc: Add support for paravirtualization

Christian Mauderer christian.mauderer at embedded-brains.de
Mon Jun 2 14:31:51 UTC 2014


From: Christian Mauderer <Christian.Mauderer at embedded-brains.de>

Guest systems in paravirtualization environments run usually in user
mode.  Thus it is not possible to directly access the PSR and TBR
registers.  Use functions instead of inline assembler to access these
registers if RTEMS_PARAVIRT is defined.
---
 c/src/lib/libbsp/sparc/erc32/Makefile.am      |  1 +
 c/src/lib/libbsp/sparc/leon2/Makefile.am      |  1 +
 c/src/lib/libbsp/sparc/leon3/Makefile.am      |  1 +
 c/src/lib/libbsp/sparc/leon3/startup/bspsmp.c |  2 +-
 c/src/lib/libbsp/sparc/shared/cpu.c           | 36 ++++++++++++++++++++++
 c/src/lib/libcpu/sparc/syscall/syscall.S      | 36 ++++++++++++++++++++++
 cpukit/score/cpu/sparc/cpu.c                  | 17 -----------
 cpukit/score/cpu/sparc/rtems/score/cpu.h      |  2 +-
 cpukit/score/cpu/sparc/rtems/score/sparc.h    | 44 +++++++++++++++++++++++++++
 9 files changed, 121 insertions(+), 19 deletions(-)
 create mode 100644 c/src/lib/libbsp/sparc/shared/cpu.c

diff --git a/c/src/lib/libbsp/sparc/erc32/Makefile.am b/c/src/lib/libbsp/sparc/erc32/Makefile.am
index abf8eca..d5de377 100644
--- a/c/src/lib/libbsp/sparc/erc32/Makefile.am
+++ b/c/src/lib/libbsp/sparc/erc32/Makefile.am
@@ -46,6 +46,7 @@ libbsp_a_SOURCES += startup/bspidle.c
 libbsp_a_SOURCES += startup/bspdelay.c
 libbsp_a_SOURCES += ../../sparc/shared/startup/early_malloc.c
 # ISR Handler
+libbsp_a_SOURCES += ../../sparc/shared/cpu.c
 libbsp_a_SOURCES += ../../sparc/shared/irq_asm.S
 # gnatsupp
 libbsp_a_SOURCES += gnatsupp/gnatsupp.c ../../sparc/shared/gnatcommon.c
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index f913462..e808b33 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -62,6 +62,7 @@ libbsp_a_SOURCES += startup/bspdelay.c
 libbsp_a_SOURCES += ../../sparc/shared/startup/early_malloc.c
 
 # ISR Handler
+libbsp_a_SOURCES += ../../sparc/shared/cpu.c
 libbsp_a_SOURCES += ../../sparc/shared/irq_asm.S
 # gnatsupp
 libbsp_a_SOURCES += gnatsupp/gnatsupp.c ../../sparc/shared/gnatcommon.c
diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index 789c3d0..5dd43c3 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -43,6 +43,7 @@ libbsp_a_SOURCES += startup/bspreset.c
 libbsp_a_SOURCES += startup/cpucounter.c
 
 # ISR Handler
+libbsp_a_SOURCES += ../../sparc/shared/cpu.c
 libbsp_a_SOURCES += ../../sparc/shared/irq_asm.S
 # gnatsupp
 libbsp_a_SOURCES += gnatsupp/gnatsupp.c ../../sparc/shared/gnatcommon.c
diff --git a/c/src/lib/libbsp/sparc/leon3/startup/bspsmp.c b/c/src/lib/libbsp/sparc/leon3/startup/bspsmp.c
index 6eec341..567eecc 100644
--- a/c/src/lib/libbsp/sparc/leon3/startup/bspsmp.c
+++ b/c/src/lib/libbsp/sparc/leon3/startup/bspsmp.c
@@ -20,7 +20,7 @@
 #include <rtems/score/smpimpl.h>
 #include <stdlib.h>
 
-#if !defined(__leon__)
+#if !defined(__leon__) || defined(RTEMS_PARAVIRT)
 uint32_t _CPU_SMP_Get_current_processor( void )
 {
   return _LEON3_Get_current_processor();
diff --git a/c/src/lib/libbsp/sparc/shared/cpu.c b/c/src/lib/libbsp/sparc/shared/cpu.c
new file mode 100644
index 0000000..12d3475
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/cpu.c
@@ -0,0 +1,36 @@
+/**
+ *  @file
+ *
+ *  @brief SPARC CPU Dependent Source
+ */
+
+/*
+ *  COPYRIGHT (c) 1989-2007.
+ *  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.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/cpu.h>
+
+/*
+ *  This initializes the set of opcodes placed in each trap
+ *  table entry.  The routine which installs a handler is responsible
+ *  for filling in the fields for the _handler address and the _vector
+ *  trap type.
+ *
+ *  The constants following this structure are masks for the fields which
+ *  must be filled in when the handler is installed.
+ *
+ *  This table is defined here to allow BSP specific versions, e.g. for guest
+ *  systems under paravirtualization.
+ */
+
+const CPU_Trap_table_entry _CPU_Trap_slot_template = {
+  0xa1480000,      /* mov   %psr, %l0           */
+  0x29000000,      /* sethi %hi(_handler), %l4  */
+  0x81c52000,      /* jmp   %l4 + %lo(_handler) */
+  0xa6102000       /* mov   _vector, %l3        */
+};
diff --git a/c/src/lib/libcpu/sparc/syscall/syscall.S b/c/src/lib/libcpu/sparc/syscall/syscall.S
index a36ffaf..9ce7fa5 100644
--- a/c/src/lib/libcpu/sparc/syscall/syscall.S
+++ b/c/src/lib/libcpu/sparc/syscall/syscall.S
@@ -83,4 +83,40 @@ SYM(sparc_syscall_exit):
 	mov	%o1, %g3	! Additional exit code 2
 	ta	0
 
+#if defined(RTEMS_PARAVIRT)
+
+        PUBLIC(_SPARC_Get_PSR)
+
+SYM(_SPARC_Get_PSR):
+
+	retl
+	 rd     %psr, %o0
+
+        PUBLIC(_SPARC_Set_PSR)
+
+SYM(_SPARC_Set_PSR):
+
+	mov     %o0, %psr
+	nop
+	nop
+	nop
+	retl
+	 nop
+
+        PUBLIC(_SPARC_Get_TBR)
+
+SYM(_SPARC_Get_TBR):
+
+	retl
+	 rd    %tbr, %o0
+
+        PUBLIC(_SPARC_Set_TBR)
+
+SYM(_SPARC_Set_TBR):
+
+	retl
+	 wr    %o0, 0, %tbr
+
+#endif /* defined(RTEMS_PARAVIRT) */
+
 /* end of file */
diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c
index ee0d622..c616de4 100644
--- a/cpukit/score/cpu/sparc/cpu.c
+++ b/cpukit/score/cpu/sparc/cpu.c
@@ -72,23 +72,6 @@ SPARC_ASSERT_OFFSET(is_executing, SPARC_CONTEXT_CONTROL_IS_EXECUTING);
 #endif
 
 /*
- *  This initializes the set of opcodes placed in each trap
- *  table entry.  The routine which installs a handler is responsible
- *  for filling in the fields for the _handler address and the _vector
- *  trap type.
- *
- *  The constants following this structure are masks for the fields which
- *  must be filled in when the handler is installed.
- */
-
-const CPU_Trap_table_entry _CPU_Trap_slot_template = {
-  0xa1480000,      /* mov   %psr, %l0           */
-  0x29000000,      /* sethi %hi(_handler), %l4  */
-  0x81c52000,      /* jmp   %l4 + %lo(_handler) */
-  0xa6102000       /* mov   _vector, %l3        */
-};
-
-/*
  *  _CPU_Initialize
  *
  *  This routine performs processor dependent initialization.
diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h
index 532d882..c010005 100644
--- a/cpukit/score/cpu/sparc/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h
@@ -1192,7 +1192,7 @@ register struct Per_CPU_Control *_SPARC_Per_CPU_current __asm__( "g6" );
 
   void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
 
-  #if defined(__leon__)
+  #if defined(__leon__) && !defined(RTEMS_PARAVIRT)
     static inline uint32_t _CPU_SMP_Get_current_processor( void )
     {
       return _LEON3_Get_current_processor();
diff --git a/cpukit/score/cpu/sparc/rtems/score/sparc.h b/cpukit/score/cpu/sparc/rtems/score/sparc.h
index 75f6d96..abd0f8b 100644
--- a/cpukit/score/cpu/sparc/rtems/score/sparc.h
+++ b/cpukit/score/cpu/sparc/rtems/score/sparc.h
@@ -164,17 +164,37 @@ extern "C" {
  *
  * This macro returns the current contents of the PSR register in @a _psr.
  */
+#if defined(RTEMS_PARAVIRT)
+
+uint32_t _SPARC_Get_PSR( void );
+
+#define sparc_get_psr( _psr ) \
+  (_psr) = _SPARC_Get_PSR()
+
+#else /* RTEMS_PARAVIRT */
+
 #define sparc_get_psr( _psr ) \
   do { \
      (_psr) = 0; \
      __asm__ volatile( "rd %%psr, %0" :  "=r" (_psr) : "0" (_psr) ); \
   } while ( 0 )
 
+#endif /* RTEMS_PARAVIRT */
+
 /**
  * @brief Macro to set the PSR.
  *
  * This macro sets the PSR register to the value in @a _psr.
  */
+#if defined(RTEMS_PARAVIRT)
+
+void _SPARC_Set_PSR( uint32_t new_psr );
+
+#define sparc_set_psr( _psr ) \
+  _SPARC_Set_PSR( _psr )
+
+#else /* RTEMS_PARAVIRT */
+
 #define sparc_set_psr( _psr ) \
   do { \
     __asm__ volatile ( "mov  %0, %%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \
@@ -183,27 +203,51 @@ extern "C" {
     nop(); \
   } while ( 0 )
 
+#endif /* RTEMS_PARAVIRT */
+
 /**
  * @brief Macro to obtain the TBR.
  *
  * This macro returns the current contents of the TBR register in @a _tbr.
  */
+#if defined(RTEMS_PARAVIRT)
+
+uint32_t _SPARC_Get_TBR( void );
+
+#define sparc_get_tbr( _tbr ) \
+  (_tbr) = _SPARC_Get_TBR()
+
+#else /* RTEMS_PARAVIRT */
+
 #define sparc_get_tbr( _tbr ) \
   do { \
      (_tbr) = 0; /* to avoid unitialized warnings */ \
      __asm__ volatile( "rd %%tbr, %0" :  "=r" (_tbr) : "0" (_tbr) ); \
   } while ( 0 )
 
+#endif /* RTEMS_PARAVIRT */
+
 /**
  * @brief Macro to set the TBR.
  *
  * This macro sets the TBR register to the value in @a _tbr.
  */
+#if defined(RTEMS_PARAVIRT)
+
+void _SPARC_Set_TBR( uint32_t new_tbr );
+
+#define sparc_set_tbr( _tbr ) \
+  _SPARC_Set_TBR((_tbr))
+
+#else /* RTEMS_PARAVIRT */
+
 #define sparc_set_tbr( _tbr ) \
   do { \
      __asm__ volatile( "wr %0, 0, %%tbr" :  "=r" (_tbr) : "0" (_tbr) ); \
   } while ( 0 )
 
+#endif /* RTEMS_PARAVIRT */
+
 /**
  * @brief Macro to obtain the WIM.
  *
-- 
1.8.4.5




More information about the devel mailing list