[PATCH v2] cpukit/cpu/i386: RTEMS_PARAVIRT guards, functionality and virt.layer

Joel Sherrill joel.sherrill at oarcorp.com
Tue Jul 22 18:29:52 UTC 2014


On 7/22/2014 12:37 PM, Gedare Bloom wrote:
> At a high-level, I think it best to avoid calls to unlinked library
> functions. Instead implement them in the BSP where possible. We can
> refactor score code to support such call-outs, but I would rather not
> be using symbols in score that are not defined anywhere in RTEMS.
>
> The way to do this will be to change CPU_PROVIDES_IDLE_THREAD_BODY to
> FALSE in i386/rtems/score/cpu.h, and move the Thread_Idle_body to the
> pc386 bsp.
>
> The tricky part is para-virtualizing the interrupt enable/disable
> code. Historically speaking, Joel has been against having this code be
> changed into a function call, but I wonder if the simplification here
> is worth the cost. If you post a patch with the isr enable/disable
> also refactored into the BSP layer, we could test it out at least.
I am traditionally against this because the function overhead call adds
to the
interrupt latency overhead. Plus a lot of the architectures we deal with are
really not that fast to begin with. With that said, the x86 is a special
case IMO.
A slow embedded x86 is still likely at least 400Mhz.

At Gedare's request, I dug out an old i386 paper manual (1986)[1] for the
instructions times in cycles. Nothing can be worse that these for an x86.
There are a TON of instruction mode variants for timing. I am assuming
these are all near (in the same segment)

call - 7 + m
ret -  10 + m

m = number of components in destination instruction to decode
   Looks like most instructions are 2-3 components.

http://www.agner.org/optimize/instruction_tables.pdf has tables
for the K8. I think this has dropped to 2 cycles impact for call and ret
has 3 if I am reading the table correctly.

Please check me on some instruction tables but I really don't see
this as mattering on a modern x86.

NOTE: GCC has discussed dropping support for older x86 CPUs in
the past -- especially those without FPUs. This would make a i486
at least the minimum target for code generation. If they do this,
we would be forced to drop i386 completely. So more ammunition
not to worry about the oldest cores.

Make is a subroutine. :)


[1] Prior to RTEMS, I worked at a company that made UNIX computers.
We have 80186, 286 and 386 based computers. The "big" development
computer supported about 5 developers. It was a 20Mhz 386 w/387,
4 full size 5.25" 300 MB CDC HDs, and (I think) 16 MB RAM. No graphics,
all serial TTYs running AT&T SVR3. Wow!
> Gedare
>
> On Fri, Jul 18, 2014 at 12:34 PM, Philipp Eppelt
> <philipp.eppelt at mailbox.tu-dresden.de> wrote:
>> ---
>> This is an updated version of an earlier unmerged patch, which extends the
>> cpukit/score/cpu/i386/ model with guards to distinguish between
>> paravirtualized (--enable-paravirt) and native environments.
>>
>>  cpukit/score/cpu/i386/Makefile.am                  |  1 +
>>  cpukit/score/cpu/i386/cpu.c                        | 18 +++++
>>  cpukit/score/cpu/i386/preinstall.am                |  3 +
>>  cpukit/score/cpu/i386/rtems/score/cpu.h            | 48 +++++++++---
>>  cpukit/score/cpu/i386/rtems/score/interrupts.h     | 38 ++++++++-
>>  .../cpu/i386/rtems/score/virtualizationlayercpu.h  | 91 ++++++++++++++++++++++
>>  6 files changed, 185 insertions(+), 14 deletions(-)
>>  create mode 100644 cpukit/score/cpu/i386/rtems/score/virtualizationlayercpu.h
>>
>> diff --git a/cpukit/score/cpu/i386/Makefile.am b/cpukit/score/cpu/i386/Makefile.am
>> index 494cd67..2293a3b 100644
>> --- a/cpukit/score/cpu/i386/Makefile.am
>> +++ b/cpukit/score/cpu/i386/Makefile.am
>> @@ -11,6 +11,7 @@ include_rtems_score_HEADERS += rtems/score/interrupts.h
>>  include_rtems_score_HEADERS += rtems/score/registers.h
>>  include_rtems_score_HEADERS += rtems/score/idtr.h
>>  include_rtems_score_HEADERS += rtems/score/cpuatomic.h
>> +include_rtems_score_HEADERS += rtems/score/virtualizationlayercpu.h
>>
>>  noinst_LIBRARIES = libscorecpu.a
>>  libscorecpu_a_SOURCES = cpu.c cpu_asm.S
>> diff --git a/cpukit/score/cpu/i386/cpu.c b/cpukit/score/cpu/i386/cpu.c
>> index 38b84e6..fb89df1 100644
>> --- a/cpukit/score/cpu/i386/cpu.c
>> +++ b/cpukit/score/cpu/i386/cpu.c
>> @@ -26,6 +26,8 @@
>>  #include <rtems/bspIo.h>
>>  #include <rtems/score/thread.h>
>>
>> +#include <rtems/score/virtualizationlayercpu.h>
>> +
>>  #define I386_ASSERT_OFFSET(field, off) \
>>    RTEMS_STATIC_ASSERT( \
>>      offsetof(Context_Control, field) \
>> @@ -115,6 +117,19 @@ uint32_t   _CPU_ISR_Get_level( void )
>>    return level;
>>  }
>>
>> +#if defined(RTEMS_PARAVIRT)
>> +
>> +void *_CPU_Thread_Idle_body( uintptr_t ignored )
>> +{
>> +  while(1)
>> +  {
>> +    _CPU_Virtual_Idle_thread();
>> +  }
>> +  return NULL;
>> +}
>> +
>> +#else
>> +
>>  void *_CPU_Thread_Idle_body( uintptr_t ignored )
>>  {
>>    while(1){
>> @@ -123,6 +139,8 @@ void *_CPU_Thread_Idle_body( uintptr_t ignored )
>>    return NULL;
>>  }
>>
>> +#endif /*RTEMS_PARAVIRT*/
>> +
>>  struct Frame_ {
>>         struct Frame_  *up;
>>         uintptr_t               pc;
>> diff --git a/cpukit/score/cpu/i386/preinstall.am b/cpukit/score/cpu/i386/preinstall.am
>> index 060176b..4fd8533 100644
>> --- a/cpukit/score/cpu/i386/preinstall.am
>> +++ b/cpukit/score/cpu/i386/preinstall.am
>> @@ -55,3 +55,6 @@ $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h: rtems/score/cpuatomic.h $(PROJECT_IN
>>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h
>>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h
>>
>> +$(PROJECT_INCLUDE)/rtems/score/virtualizationlayercpu.h: rtems/score/virtualizationlayercpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
>> +       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/virtualizationlayercpu.h
>> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/virtualizationlayercpu.h
>> diff --git a/cpukit/score/cpu/i386/rtems/score/cpu.h b/cpukit/score/cpu/i386/rtems/score/cpu.h
>> index 2d1472d..7567777 100644
>> --- a/cpukit/score/cpu/i386/rtems/score/cpu.h
>> +++ b/cpukit/score/cpu/i386/rtems/score/cpu.h
>> @@ -35,6 +35,8 @@ extern "C" {
>>  #include <rtems/score/registers.h>     /* formerly part of libcpu */
>>  #endif
>>
>> +#include <rtems/score/virtualizationlayercpu.h>
>> +
>>  /* conditional compilation parameters */
>>
>>  #define CPU_INLINE_ENABLE_DISPATCH       TRUE
>> @@ -400,11 +402,22 @@ SCORE_EXTERN Context_Control_fp  _CPU_Null_fp_context;
>>
>>  #define _CPU_ISR_Flash( _level )   i386_flash_interrupts( _level )
>>
>> -#define _CPU_ISR_Set_level( _new_level ) \
>> -  { \
>> -    if ( _new_level ) __asm__ volatile ( "cli" ); \
>> -    else              __asm__ volatile ( "sti" ); \
>> -  }
>> +#if defined(RTEMS_PARAVIRT)
>> +  #define _CPU_ISR_Set_level( _new_level ) \
>> +    { \
>> +      if( _new_level )  _CPU_Virtual_Interrupts_close(); \
>> +      else             _CPU_Virtual_Interrupts_open(); \
>> +    }
>> +
>> +#else
>> +
>> +  #define _CPU_ISR_Set_level( _new_level ) \
>> +    { \
>> +      if ( _new_level ) __asm__ volatile ( "cli" ); \
>> +      else              __asm__ volatile ( "sti" ); \
>> +    }
>> +
>> +#endif /*RTEMS_PARAVIRT*/
>>
>>  uint32_t   _CPU_ISR_Get_level( void );
>>
>> @@ -525,16 +538,27 @@ uint32_t   _CPU_ISR_Get_level( void );
>>   *    + disable interrupts and halt the CPU
>>   */
>>
>> -#define _CPU_Fatal_halt( _error ) \
>> +#if defined(RTEMS_PARAVIRT)
>> +  #define _CPU_Fatal_halt( _error ) \
>>    { \
>> -    uint32_t _error_lvalue = ( _error ); \
>> -    __asm__ volatile ( "cli ; \
>> -                    movl %0,%%eax ; \
>> -                    hlt" \
>> -                    : "=r" ((_error_lvalue)) : "0" ((_error_lvalue)) \
>> -    ); \
>> +    _CPU_Virtual_Interrupts_close(); \
>> +    _CPU_Virtual_Stop_with_error( _error ); \
>>    }
>>
>> +#else
>> +
>> +  #define _CPU_Fatal_halt( _error ) \
>> +    { \
>> +      uint32_t _error_lvalue = ( _error ); \
>> +      __asm__ volatile ( "cli ; \
>> +                      movl %0,%%eax ; \
>> +                      hlt" \
>> +                      : "=r" ((_error_lvalue)) : "0" ((_error_lvalue)) \
>> +      ); \
>> +    }
>> +
>> +#endif /*RTEMS_PARAVIRT*/
>> +
>>  #endif /* ASM */
>>
>>  /* end of Fatal Error manager macros */
>> diff --git a/cpukit/score/cpu/i386/rtems/score/interrupts.h b/cpukit/score/cpu/i386/rtems/score/interrupts.h
>> index 5ae172a..4233a34 100644
>> --- a/cpukit/score/cpu/i386/rtems/score/interrupts.h
>> +++ b/cpukit/score/cpu/i386/rtems/score/interrupts.h
>> @@ -8,6 +8,8 @@
>>
>>  /*
>>   *  COPYRIGHT (c) 1998 valette at crf.canon.fr
>> + *  COPYRIGHT (c) 2014 Philipp Eppelt.
>> + *     philipp.eppelt at mailbox.tu-dresden.de
>>   *
>>   *  The license and distribution terms for this file may be
>>   *  found in the file LICENSE in this distribution or at
>> @@ -19,6 +21,8 @@
>>  #ifndef _RTEMS_SCORE_INTERRUPTS_H
>>  #define _RTEMS_SCORE_INTERRUPTS_H
>>
>> +#include <rtems/score/virtualizationlayercpu.h>
>> +
>>  #ifndef ASM
>>
>>  struct         __rtems_raw_irq_connect_data__;
>> @@ -33,6 +37,35 @@ typedef int  (*rtems_raw_irq_is_enabled)     (const struct __rtems_raw_irq_connect_d
>>   *
>>   */
>>  /**@{**/
>> +#if defined(RTEMS_PARAVIRT)
>> +
>> +#define i386_disable_interrupts( _level ) \
>> +  { \
>> +    _CPU_Virtual_Interrupts_disable( _level ); \
>> +  }
>> +
>> +#define i386_enable_interrupts( _level )  \
>> +  { \
>> +    _CPU_Virtual_Interrupts_enable( _level ); \
>> +  }
>> +
>> +#define i386_flash_interrupts( _level ) \
>> +  { \
>> +    _CPU_Virtual_Interrupts_enable(_level); \
>> +    _CPU_Virtual_Interrupts_disable(_level); \
>> +  }
>> +
>> +#define i386_get_interrupt_level( _level ) \
>> +  { \
>> +    _CPU_Virtual_Interrupts_get_level( _level ); \
>> +  }
>> +
>> +#define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
>> +#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
>> +
>> +
>> +#else /*RTEMS_PARAVIRT*/
>> +
>>
>>  #define i386_disable_interrupts( _level ) \
>>    { \
>> @@ -75,7 +108,8 @@ typedef int  (*rtems_raw_irq_is_enabled)     (const struct __rtems_raw_irq_connect_d
>>  #define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
>>  #define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
>>
>> +#endif /*RTEMS_PARAVIRT*/
>>  /** @} */
>>
>> -#endif
>> -#endif
>> +#endif /* ASM */
>> +#endif /* _RTEMS_SCORE_INTERRUPTS_H */
>> diff --git a/cpukit/score/cpu/i386/rtems/score/virtualizationlayercpu.h b/cpukit/score/cpu/i386/rtems/score/virtualizationlayercpu.h
>> new file mode 100644
>> index 0000000..9834f82
>> --- /dev/null
>> +++ b/cpukit/score/cpu/i386/rtems/score/virtualizationlayercpu.h
>> @@ -0,0 +1,91 @@
>> +/*
>> + *
>> + * COPYRIGHT (c) 2013 Philipp Eppelt.
>> + *    philipp.eppelt at mailbox.tu-dresden.de
>> + *
>> + *  Purpose:   CPU part of the virtualization layer.
>> + *
>> + *  The license and distribution terms for this file may be
>> + *  found in the file LICENSE in this distribution or at
>> + *  http://www.rtems.com/license/LICENSE.
>> + */
>> +
>> +#if defined(RTEMS_PARAVIRT)
>> +
>> +#ifndef RTEMS_VIRT_LAYER_CPU_H
>> +#define RTEMS_VIRT_LAYER_CPU_H
>> +
>> +#ifndef ASM
>> +
>> +/* Interrupts */
>> +
>> +/**
>> + * \brief Requests an interrupt vector.
>> + */
>> +int
>> +_CPU_Virtual_Irq_request( int vector );
>> +
>> +/**
>> + * \brief Releases an interrupt vector.
>> + */
>> +void
>> +_CPU_Virtual_Irq_detach( int vector );
>> +
>> +/**
>> + * \brief Enables interrupt delivery or sets it to the specified level.
>> + *
>> + * Use this function in collaboration with _CPU_Virtual_Interrupts_disable and
>> + * use its returned _level as argument to this function to assure proper
>> + * behaviour.
>> + */
>> +void
>> +_CPU_Virtual_Interrupts_enable( int _level );
>> +
>> +/**
>> + * \brief Disables interrupt delivery and returns the previous level.
>> + *
>> + */
>> +void
>> +_CPU_Virtual_Interrupts_disable( int _level );
>> +
>> +/**
>> + * \brief Enables and directly disables interrupt delivery.
>> + */
>> +void
>> +_CPU_Virtual_Interrupts_flash( int _level );
>> +
>> +/**
>> + * \brief Requests the current interrupt level.
>> + */
>> +int
>> +_CPU_Virtual_Interrupts_get_level( int _level );
>> +
>> +
>> +void
>> +_CPU_Virtual_Interrupts_open(void);
>> +void
>> +_CPU_Virtual_Interrupts_close( void );
>> +
>> +/* Idle Thread */
>> +
>> +/**
>> + * \brief Lowest priority thread, doing nothing, never returns;
>> + */
>> +
>> +void
>> +_CPU_Virtual_Idle_thread( void );
>> +
>> +
>> +/* Error handling */
>> +
>> +/**
>> + * \brief Handlers execution errors.
>> + */
>> +void
>> +_CPU_Virtual_Stop_with_error( int _error );
>> +
>> +#endif /* ASM */
>> +
>> +#endif /* RTEMS_VIRT_LAYER_CPU_H */
>> +
>> +#endif /*RTEMS_PARAVIRT*/
>> --
>> 1.9.3
>>
>> _______________________________________________
>> devel mailing list
>> devel at rtems.org
>> http://lists.rtems.org/mailman/listinfo/devel

-- 
Joel Sherrill, Ph.D.             Director of Research & Development
joel.sherrill at OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
Support Available                (256) 722-9985



More information about the devel mailing list