Subversion Repositories HelenOS

Rev

Rev 2071 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2006 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup sparc64mm  
  30.  * @{
  31.  */
  32. /**
  33.  * @file
  34.  * @brief   D-cache shootdown algorithm.
  35.  */
  36.  
  37. #include <arch/mm/cache.h>
  38.  
  39. #ifdef CONFIG_SMP
  40. #ifdef CONFIG_VIRT_IDX_DCACHE
  41.  
  42. #include <smp/ipi.h>
  43. #include <arch/interrupt.h>
  44. #include <synch/spinlock.h>
  45. #include <arch.h>
  46. #include <debug.h>
  47.  
  48. /**
  49.  * This spinlock is used by the processors to synchronize during the D-cache
  50.  * shootdown.
  51.  */
  52. SPINLOCK_INITIALIZE(dcachelock);
  53.  
  54. /** Initialize the D-cache shootdown sequence.
  55.  *
  56.  * Start the shootdown sequence by sending out an IPI and wait until all
  57.  * processors spin on the dcachelock spinlock.
  58.  *
  59.  * @param type  Scope of the D-cache shootdown.
  60.  * @param color Color to be invalidated; applicable only for DCACHE_INVL_COLOR
  61.  *      and DCACHE_INVL_FRAME invalidation types.
  62.  * @param frame Frame to be invalidated; applicable only for DCACHE_INVL_FRAME
  63.  *      invalidation types.
  64.  */
  65. void dcache_shootdown_start(dcache_invalidate_type_t type, int color,
  66.     uintptr_t frame)
  67. {
  68.     int i;
  69.  
  70.     CPU->arch.dcache_active = 0;
  71.     spinlock_lock(&dcachelock);
  72.  
  73.     for (i = 0; i < config.cpu_count; i++) {
  74.         cpu_t *cpu;
  75.  
  76.         if (i == CPU->id)
  77.             continue;
  78.  
  79.         cpu = &cpus[i];
  80.         spinlock_lock(&cpu->lock);
  81.         if (cpu->arch.dcache_message_count ==
  82.             DCACHE_MSG_QUEUE_LEN) {
  83.             /*
  84.              * The queue is full, flush the cache entirely.
  85.              */
  86.             cpu->arch.dcache_message_count = 1;
  87.             cpu->arch.dcache_messages[0].type = DCACHE_INVL_ALL;
  88.             cpu->arch.dcache_messages[0].color = 0; /* ignored */
  89.             cpu->arch.dcache_messages[0].frame = 0; /* ignored */
  90.         } else {
  91.             index_t idx = cpu->arch.dcache_message_count++;
  92.             cpu->arch.dcache_messages[idx].type = type;
  93.             cpu->arch.dcache_messages[idx].color = color;
  94.             cpu->arch.dcache_messages[idx].frame = frame;
  95.         }
  96.         spinlock_unlock(&cpu->lock);
  97.     }
  98.  
  99.     ipi_broadcast(IPI_DCACHE_SHOOTDOWN);   
  100.  
  101. busy_wait:
  102.     for (i = 0; i < config.cpu_count; i++)
  103.         if (cpus[i].arch.dcache_active)
  104.             goto busy_wait;
  105. }
  106.  
  107. /** Finish the D-cache shootdown sequence. */
  108. void dcache_shootdown_finalize(void)
  109. {
  110.     spinlock_unlock(&dcachelock);
  111.     CPU->arch.dcache_active = 1;
  112. }
  113.  
  114. /** Process the D-cache shootdown IPI. */
  115. void dcache_shootdown_ipi_recv(void)
  116. {
  117.     int i;
  118.  
  119.     ASSERT(CPU);
  120.  
  121.     CPU->arch.dcache_active = 0;
  122.     spinlock_lock(&dcachelock);
  123.     spinlock_unlock(&dcachelock);
  124.    
  125.     spinlock_lock(&CPU->lock);
  126.     ASSERT(CPU->arch.dcache_message_count < DCACHE_MSG_QUEUE_LEN);
  127.     for (i = 0; i < CPU->arch.dcache_message_count; i++) {
  128.         switch (CPU->arch.dcache_messages[i].type) {
  129.         case DCACHE_INVL_ALL:
  130.             dcache_flush();
  131.             goto flushed;
  132.             break;
  133.         case DCACHE_INVL_COLOR:
  134.             dcache_flush_color(CPU->arch.dcache_messages[i].color);
  135.             break;
  136.         case DCACHE_INVL_FRAME:
  137.             dcache_flush_frame(CPU->arch.dcache_messages[i].color,
  138.                 CPU->arch.dcache_messages[i].frame);
  139.             break;
  140.         default:
  141.             panic("unknown type (%d)\n",
  142.                 CPU->arch.dcache_messages[i].type);
  143.         }
  144.     }
  145. flushed:
  146.     CPU->arch.dcache_message_count = 0;
  147.     spinlock_unlock(&CPU->lock);
  148.  
  149.     CPU->arch.dcache_active = 1;
  150. }
  151.  
  152. #endif /* CONFIG_VIRT_IDX_DCACHE */
  153. #endif /* CONFIG_SMP */
  154.  
  155. /** @}
  156.  */
  157.  
  158.