Changeset d1e414c in mainline


Ignore:
Timestamp:
2006-03-15T00:51:25Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
91d5ad6
Parents:
51cc6bf6
Message:

More lightweighed TLB shootdown implementation.

Location:
generic
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • generic/include/cpu.h

    r51cc6bf6 rd1e414c  
    3939#include <config.h>
    4040#include <adt/list.h>
     41#include <mm/tlb.h>
    4142
    4243#define CPU_STACK_SIZE  STACK_SIZE
     
    4950        SPINLOCK_DECLARE(lock);
    5051
     52        tlb_shootdown_msg_t tlb_messages[TLB_MESSAGE_QUEUE_LEN];
     53        count_t tlb_messages_count;
     54       
    5155        context_t saved_context;
    5256
  • generic/include/mm/tlb.h

    r51cc6bf6 rd1e414c  
    3434#include <typedefs.h>
    3535
     36/**
     37 * Number of TLB shootdown messages that can be queued in processor
     38 * tlb_messages queue.
     39 */
     40#define TLB_MESSAGE_QUEUE_LEN   10
     41
    3642/** Type of TLB shootdown message. */
    3743enum tlb_invalidate_type {
     
    4147        TLB_INVL_PAGES                  /**< Invalidate specified page range belonging to one address space. */
    4248};
    43 
    4449typedef enum tlb_invalidate_type tlb_invalidate_type_t;
    4550
     
    4954        asid_t asid;                    /**< Address space identifier. */
    5055        __address page;                 /**< Page address. */
     56        count_t count;                  /**< Number of pages to invalidate. */
    5157};
    52 
    5358typedef struct tlb_shootdown_msg tlb_shootdown_msg_t;
    5459
     
    5661
    5762#ifdef CONFIG_SMP
    58 extern void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t cnt);
     63extern void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t count);
    5964extern void tlb_shootdown_finalize(void);
    6065extern void tlb_shootdown_ipi_recv(void);
  • generic/src/mm/tlb.c

    r51cc6bf6 rd1e414c  
    2828
    2929#include <mm/tlb.h>
     30#include <mm/asid.h>
    3031#include <arch/mm/tlb.h>
    3132#include <smp/ipi.h>
     
    3738#include <arch.h>
    3839#include <panic.h>
     40#include <debug.h>
    3941
     42/**
     43 * This lock is used for synchronisation between sender and
     44 * recipients of TLB shootdown message. It must be acquired
     45 * before CPU structure lock.
     46 */
    4047SPINLOCK_INITIALIZE(tlblock);
    4148
     
    4653
    4754#ifdef CONFIG_SMP
    48 /* must be called with interrupts disabled */
    49 void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t cnt)
     55
     56/** Send TLB shootdown message.
     57 *
     58 * This function attempts to deliver TLB shootdown message
     59 * to all other processors.
     60 *
     61 * This function must be called with interrupts disabled.
     62 *
     63 * @param type Type describing scope of shootdown.
     64 * @param asid Address space, if required by type.
     65 * @param page Virtual page address, if required by type.
     66 * @param count Number of pages, if required by type.
     67 */
     68void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t count)
    5069{
    5170        int i;
     
    5473        spinlock_lock(&tlblock);
    5574       
    56         /*
    57          * TODO: wrap parameters into a message and
    58          * dispatch it to all CPUs excluding this one.
    59          */
     75        for (i = 0; i < config.cpu_count; i++) {
     76                cpu_t *cpu;
     77               
     78                if (i == CPU->id)
     79                        continue;
     80
     81                cpu = &cpus[i];
     82                spinlock_lock(&cpu->lock);
     83                if (cpu->tlb_messages_count == TLB_MESSAGE_QUEUE_LEN) {
     84                        /*
     85                         * The message queue is full.
     86                         * Erase the queue and store one TLB_INVL_ALL message.
     87                         */
     88                        cpu->tlb_messages_count = 1;
     89                        cpu->tlb_messages[0].type = TLB_INVL_ALL;
     90                        cpu->tlb_messages[0].asid = ASID_INVALID;
     91                        cpu->tlb_messages[0].page = 0;
     92                        cpu->tlb_messages[0].count = 0;
     93                } else {
     94                        /*
     95                         * Enqueue the message.
     96                         */
     97                        cpu->tlb_messages[cpu->tlb_messages_count].type = type;
     98                        cpu->tlb_messages[cpu->tlb_messages_count].asid = asid;
     99                        cpu->tlb_messages[cpu->tlb_messages_count].page = page;
     100                        cpu->tlb_messages[cpu->tlb_messages_count].count = count;
     101                        cpu->tlb_messages_count++;
     102                }
     103                spinlock_unlock(&cpu->lock);
     104        }
    60105       
    61106        tlb_shootdown_ipi_send();
    62107
    63108busy_wait:     
    64         for (i = 0; i<config.cpu_count; i++)
     109        for (i = 0; i < config.cpu_count; i++)
    65110                if (cpus[i].tlb_active)
    66111                        goto busy_wait;
    67112}
    68113
     114/** Finish TLB shootdown sequence. */
    69115void tlb_shootdown_finalize(void)
    70116{
     
    78124}
    79125
     126/** Receive TLB shootdown message. */
    80127void tlb_shootdown_ipi_recv(void)
    81128{
     129        tlb_invalidate_type_t type;
     130        asid_t asid;
     131        __address page;
     132        count_t count;
     133        int i;
     134       
    82135        CPU->tlb_active = 0;
    83136        spinlock_lock(&tlblock);
    84137        spinlock_unlock(&tlblock);
    85         tlb_invalidate_all();   /* TODO: be more finer-grained in what to invalidate */
     138       
     139        spinlock_lock(&CPU->lock);
     140        ASSERT(CPU->tlb_messages_count <= TLB_MESSAGE_QUEUE_LEN);
     141
     142        for (i = 0; i < CPU->tlb_messages_count; CPU->tlb_messages_count--) {
     143                type = CPU->tlb_messages[i].type;
     144                asid = CPU->tlb_messages[i].asid;
     145                page = CPU->tlb_messages[i].page;
     146                count = CPU->tlb_messages[i].count;
     147
     148                switch (type) {
     149                    case TLB_INVL_ALL:
     150                        tlb_invalidate_all();
     151                        break;
     152                    case TLB_INVL_ASID:
     153                        tlb_invalidate_asid(asid);
     154                        break;
     155                    case TLB_INVL_PAGES:
     156                        ASSERT(count);
     157                        tlb_invalidate_pages(asid, page, count);
     158                        break;
     159                    default:
     160                        panic("unknown type (%d)\n", type);
     161                        break;
     162                }
     163                if (type == TLB_INVL_ALL)
     164                        break;
     165        }
     166       
     167        spinlock_unlock(&CPU->lock);
    86168        CPU->tlb_active = 1;
    87169}
     170
    88171#endif /* CONFIG_SMP */
Note: See TracChangeset for help on using the changeset viewer.