Changeset 4512d7e in mainline


Ignore:
Timestamp:
2006-01-19T22:17:47Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6461d67c
Parents:
64c44e8
Message:

New ASID management subsystem (initial work, more is required).
Some TLB invalidation changes.

Files:
1 added
22 edited

Legend:

Unmodified
Added
Removed
  • arch/amd64/include/mm/asid.h

    • Property mode changed from 100644 to 120000
    r64c44e8 r4512d7e  
    1 /*
    2  * Copyright (C) 2005 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 #ifndef __amd64_ASID_H__
    30 #define __amd64_ASID_H__
    31 
    32 typedef int asid_t;
    33 
    34 #define asid_get()      0
    35 
    36 #endif
     1../../../ia32/include/mm/asid.h
  • arch/ia32/include/mm/asid.h

    r64c44e8 r4512d7e  
    2727 */
    2828
     29/*
     30 * ia32 has no hardware support for address space identifiers.
     31 * This file is provided to do nop-implementation of mm/asid.h
     32 * interface.
     33 */
     34
    2935#ifndef __ia32_ASID_H__
    3036#define __ia32_ASID_H__
     
    3238typedef int asid_t;
    3339
    34 #define asid_get()      0
     40#define ASID_MAX_ARCH           0
     41
     42#define asid_install(as)
    3543
    3644#endif
  • arch/ia32/src/mm/tlb.c

    r64c44e8 r4512d7e  
    3232#include <arch/types.h>
    3333
    34 /** Invalidate all TLB entries
    35  *
    36  * Invalidate all TLB entries.
    37  *
    38  * @param asid This argument is ignored.
    39  */
    40 void tlb_invalidate(asid_t asid)
    41 {
    42         write_cr3(read_cr3());
    43 }
    44 
    4534/** Invalidate all entries in TLB. */
    4635void tlb_invalidate_all(void)
     
    5847}
    5948
    60 /** Invalidate TLB entry for specified page belongs to specified address space.
     49/** Invalidate TLB entry for specified page range belonging to specified address space.
    6150 *
    6251 * @param asid This parameter is ignored as the architecture doesn't support it.
    63  * @param page Address of the page whose entry is to be invalidated.
     52 * @param page Address of the first page whose entry is to be invalidated.
     53 * @param cnt Number of entries to invalidate.
    6454 */
    65 void tlb_invalidate_page(asid_t asid, __address page)
     55void tlb_invalidate_pages(asid_t asid, __address page, count_t cnt)
    6656{
    67         invlpg(page);
     57        int i;
     58
     59        for (i = 0; i < cnt; i++)
     60                invlpg(page + i * PAGE_SIZE);
    6861}
  • arch/ia64/Makefile.inc

    r64c44e8 r4512d7e  
    4848CONFIG_PAGE_HT = y
    4949
     50## Compile with support for address space identifiers.
     51#
     52
     53CONFIG_ASID = y
     54
     55
    5056ARCH_SOURCES = \
    5157        arch/$(ARCH)/src/start.S \
  • arch/ia64/include/mm/asid.h

    r64c44e8 r4512d7e  
    3030#define __ia64_ASID_H__
    3131
    32 typedef int asid_t;
     32#include <arch/types.h>
    3333
    34 #define asid_get()      0
     34typedef __u32 asid_t;
     35
     36/*
     37 * ASID_MAX can range from 2^18 - 1 to 2^24 - ,
     38 * depending on architecture implementation.
     39 */
     40#define ASID_MAX_ARCH   16777215        /* 2^24 - 1 */
    3541
    3642#endif
  • arch/mips32/Makefile.inc

    r64c44e8 r4512d7e  
    5151
    5252CONFIG_PAGE_PT = y
     53
     54## Compile with support for address space identifiers.
     55#
     56
     57CONFIG_ASID = y
    5358
    5459
  • arch/mips32/include/mm/asid.h

    r64c44e8 r4512d7e  
    3131
    3232#include <arch/types.h>
    33 #include <typedefs.h>
    3433
    35 #define ASIDS           256
    36 #define ASID_INVALID    0
    37 #define ASID_START      1
     34#define ASID_MAX_ARCH   255
    3835
    3936typedef __u8 asid_t;
    4037
    41 extern asid_t asid_get(void);
    42 extern void asid_put(asid_t asid);
    43 extern bool asid_has_conflicts(asid_t asid);
    44 
    4538#endif
  • arch/mips32/src/mm/as.c

    r64c44e8 r4512d7e  
    3636/** Install address space.
    3737 *
    38  * Install ASID and if necessary, purge TLB.
     38 * Install ASID.
    3939 *
    4040 * @param as Address space structure.
     
    4444        entry_hi_t hi;
    4545        ipl_t ipl;
    46 
    47         /*
    48          * If necessary, purge TLB.
    49          */
    50         tlb_invalidate_asid(as->asid);  /* TODO: do it only if necessary */
    5146
    5247        /*
  • arch/mips32/src/mm/asid.c

    r64c44e8 r4512d7e  
    2929
    3030#include <arch/mm/asid.h>
    31 #include <synch/spinlock.h>
    32 #include <arch.h>
    33 #include <debug.h>
    3431#include <typedefs.h>
    3532
    36 SPINLOCK_INITIALIZE(asid_usage_lock);
    37 static count_t asid_usage[ASIDS];       /**< Usage tracking array for ASIDs */
    38 
    39 /** Get ASID
    40  *
    41  * Get the least used ASID.
    42  *
    43  * @return ASID
    44  */
    45 asid_t asid_get(void)
    46 {
    47         ipl_t ipl;
    48         int i, j;
    49         count_t min;
    50        
    51         min = (unsigned) -1;
    52        
    53         ipl = interrupts_disable();
    54         spinlock_lock(&asid_usage_lock);
    55        
    56         for (i = ASID_START, j = ASID_START; i < ASIDS; i++) {
    57                 if (asid_usage[i] < min) {
    58                         j = i;
    59                         min = asid_usage[i];
    60                         if (!min)
    61                                 break;
    62                 }
    63         }
    64 
    65         asid_usage[j]++;
    66 
    67         spinlock_unlock(&asid_usage_lock);
    68         interrupts_restore(ipl);
    69 
    70         return i;
    71 }
    72 
    73 /** Release ASID
    74  *
    75  * Release ASID by decrementing its usage count.
    76  *
    77  * @param asid ASID.
    78  */
    79 void asid_put(asid_t asid)
    80 {
    81         ipl_t ipl;
    82 
    83         ipl = interrupts_disable();
    84         spinlock_lock(&asid_usage_lock);
    85 
    86         ASSERT(asid != ASID_INVALID);
    87        
    88         ASSERT(asid_usage[asid] > 0);
    89         asid_usage[asid]--;
    90 
    91         spinlock_unlock(&asid_usage_lock);
    92         interrupts_restore(ipl);
    93 }
    94 
    95 /** Find out whether ASID is used by more address spaces
    96  *
    97  * Find out whether ASID is used by more address spaces.
    98  *
    99  * @param asid ASID in question.
    100  *
    101  * @return True if 'asid' is used by more address spaces, false otherwise.
    102  */
    103 bool asid_has_conflicts(asid_t asid)
    104 {
    105         bool has_conflicts = false;
    106         ipl_t ipl;
    107 
    108         ASSERT(asid != ASID_INVALID);
    109 
    110         ipl = interrupts_disable();
    111         spinlock_lock(&asid_usage_lock);
    112 
    113         if (asid_usage[asid] > 1)
    114                 has_conflicts = true;
    115 
    116         spinlock_unlock(&asid_usage_lock);
    117         interrupts_restore(ipl);
    118 
    119         return has_conflicts;
    120 }
  • arch/mips32/src/mm/tlb.c

    r64c44e8 r4512d7e  
    2828
    2929#include <arch/mm/tlb.h>
    30 #include <arch/mm/asid.h>
     30#include <mm/asid.h>
    3131#include <mm/tlb.h>
    3232#include <mm/page.h>
     
    495495}
    496496
    497 /** Invalidate TLB entry for specified page belonging to specified address space.
     497/** Invalidate TLB entries for specified page range belonging to specified address space.
    498498 *
    499499 * @param asid Address space identifier.
    500  * @param page Page whose TLB entry is to be invalidated.
    501  */
    502 void tlb_invalidate_page(asid_t asid, __address page)
    503 {
     500 * @param page First page whose TLB entry is to be invalidated.
     501 * @param cnt Number of entries to invalidate.
     502 */
     503void tlb_invalidate_pages(asid_t asid, __address page, count_t cnt)
     504{
     505        int i;
    504506        ipl_t ipl;
    505507        entry_lo_t lo0, lo1;
     
    512514        ipl = interrupts_disable();
    513515
    514         hi.value = 0;
    515         prepare_entry_hi(&hi, asid, page);
    516         cp0_entry_hi_write(hi.value);
    517 
    518         tlbp();
    519         index.value = cp0_index_read();
    520 
    521         if (!index.p) {
    522                 /* Entry was found, index register contains valid index. */
    523                 tlbr();
    524 
    525                 lo0.value = cp0_entry_lo0_read();
    526                 lo1.value = cp0_entry_lo1_read();
    527 
    528                 lo0.v = 0;
    529                 lo1.v = 0;
    530 
    531                 cp0_entry_lo0_write(lo0.value);
    532                 cp0_entry_lo1_write(lo1.value);
    533 
    534                 tlbwi();
     516        for (i = 0; i < cnt; i++) {
     517                hi.value = 0;
     518                prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE);
     519                cp0_entry_hi_write(hi.value);
     520
     521                tlbp();
     522                index.value = cp0_index_read();
     523
     524                if (!index.p) {
     525                        /* Entry was found, index register contains valid index. */
     526                        tlbr();
     527
     528                        lo0.value = cp0_entry_lo0_read();
     529                        lo1.value = cp0_entry_lo1_read();
     530
     531                        lo0.v = 0;
     532                        lo1.v = 0;
     533
     534                        cp0_entry_lo0_write(lo0.value);
     535                        cp0_entry_lo1_write(lo1.value);
     536
     537                        tlbwi();
     538                }
    535539        }
    536540       
  • arch/ppc32/include/mm/asid.h

    r64c44e8 r4512d7e  
    3232typedef int asid_t;
    3333
    34 #define asid_get()      0
     34#define ASID_MAX_ARCH   0
     35
     36#define asid_install(as)
    3537
    3638#endif
  • arch/sparc64/Makefile.inc

    r64c44e8 r4512d7e  
    5252CONFIG_PAGE_HT = y
    5353
     54## Compile with support for address space identifiers.
     55#
     56
     57CONFIG_ASID = y
     58
     59
    5460ARCH_SOURCES = \
    5561        arch/$(ARCH)/src/cpu/cpu.c \
  • arch/sparc64/include/mm/asid.h

    r64c44e8 r4512d7e  
    3737typedef __u16 asid_t;
    3838
    39 #define asid_get()      0
     39#define ASID_MAX_ARCH   0x4095  /* 2^12 - 1 */
    4040
    4141#endif
  • arch/sparc64/src/mm/tlb.c

    r64c44e8 r4512d7e  
    166166}
    167167
    168 /** Invalidate all ITLB and DLTB entries for specified page in specified address space.
     168/** Invalidate all ITLB and DTLB entries for specified page range in specified address space.
    169169 *
    170170 * @param asid Address Space ID.
    171  * @param page Page which to sweep out from ITLB and DTLB.
     171 * @param page First page which to sweep out from ITLB and DTLB.
     172 * @param cnt Number of ITLB and DTLB entries to invalidate.
    172173 */
    173 void tlb_invalidate_page(asid_t asid, __address page)
     174void tlb_invalidate_pages(asid_t asid, __address page, count_t cnt)
    174175{
    175         /* TODO: write asid to some Context register and encode the register in second parameter below. */
    176         itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, page);
    177         dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, page);
     176        int i;
     177       
     178        for (i = 0; i < cnt; i++) {
     179                /* TODO: write asid to some Context register and encode the register in second parameter below. */
     180                itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, page + i * PAGE_SIZE);
     181                dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, page + i * PAGE_SIZE);
     182        }
    178183}
  • genarch/Makefile.inc

    r64c44e8 r4512d7e  
    4646                genarch/src/mm/page_ht.c
    4747endif
     48ifeq ($(CONFIG_ASID),y)
     49        GENARCH_SOURCES += \
     50                genarch/src/mm/asid.c
     51endif
  • generic/include/mm/as.h

    r64c44e8 r4512d7e  
    4949#define UDATA_ADDRESS   UDATA_ADDRESS_ARCH
    5050
     51#define AS_KERNEL       (1<<0)          /**< Kernel address space. */
     52
    5153enum as_area_type {
    5254        AS_AREA_TEXT = 1, AS_AREA_DATA, AS_AREA_STACK
     
    6264        link_t link;
    6365        as_area_type_t type;
    64         size_t size;            /**< Size of this area. */
     66        size_t size;            /**< Size of this area in multiples of PAGE_SIZE. */
    6567        __address base;         /**< Base address of this area. */
    6668        index_t *mapping;       /**< Map of physical frame numbers mapped to virtual page numbers in this area. */
     
    7577 */
    7678struct as {
     79        /** Protected by asidlock. Must be acquired before as-> lock. */
     80        link_t as_with_asid_link;
     81
    7782        SPINLOCK_DECLARE(lock);
    7883        link_t as_area_head;
     
    8186};
    8287
    83 extern as_t * as_create(pte_t *ptl0);
     88extern as_t * as_create(pte_t *ptl0, int flags);
    8489extern as_area_t *as_area_create(as_t *as, as_area_type_t type, size_t size, __address base);
    8590extern void as_area_set_mapping(as_area_t *a, index_t vpn, index_t pfn);
     
    8792extern void as_install(as_t *m);
    8893
    89 /*
    90  * Each architecture should implement this function.
    91  * Its main purpose is to do TLB purges according
    92  * to architecture's requirements. Note that
    93  * some architectures invalidate their TLB automatically
    94  * on hardware address space switch (e.g. ia32 and
    95  * amd64).
    96  */
     94/* Interface to be implemented by architectures. */
    9795#ifndef as_install_arch
    9896extern void as_install_arch(as_t *as);
  • generic/include/mm/asid.h

    r64c44e8 r4512d7e  
    2727 */
    2828
     29/*
     30 * This is generic interface for managing
     31 * Address Space IDentifiers (ASIDs).
     32 */
     33
    2934#ifndef __ASID_H__
    3035#define __ASID_H__
    3136
     37#include <arch/mm/asid.h>
     38#include <typedefs.h>
     39
    3240#define ASID_KERNEL     0
     41#define ASID_INVALID    1
     42#define ASID_START      2
     43#define ASID_MAX        ASID_MAX_ARCH
     44
     45#define ASIDS_ALLOCABLE ((ASID_MAX+1)-ASID_START)
     46
     47extern spinlock_t asidlock;
     48extern link_t as_with_asid_head;
     49
     50extern asid_t asid_get(void);
     51extern void asid_put(asid_t asid);
     52
     53#ifndef asid_install
     54extern void asid_install(as_t *as);
     55#endif /* !def asid_install */
     56
     57#define asid_find_free()        ASID_START
     58#define asid_put_arch(x)
    3359
    3460#endif
  • generic/include/mm/tlb.h

    r64c44e8 r4512d7e  
    3232#include <arch/mm/asid.h>
    3333#include <arch/types.h>
    34 
    35 extern void tlb_init(void);
    36 
    37 #ifdef CONFIG_SMP
    38 extern void tlb_shootdown_start(void);
    39 extern void tlb_shootdown_finalize(void);
    40 extern void tlb_shootdown_ipi_recv(void);
    41 #else
    42 #  define tlb_shootdown_start() ;
    43 #  define tlb_shootdown_finalize()      ;
    44 #  define tlb_shootdown_ipi_recv() ;
    45 #endif /* CONFIG_SMP */
     34#include <typedefs.h>
    4635
    4736/** Type of TLB shootdown message. */
     
    5039        TLB_INVL_ALL,                   /**< Invalidate all entries in TLB. */
    5140        TLB_INVL_ASID,                  /**< Invalidate all entries belonging to one address space. */
    52         TLB_INVL_PAGE                   /**< Invalidate one entry for specified page. */
     41        TLB_INVL_PAGES                  /**< Invalidate specified page range belonging to one address space. */
    5342};
    5443
     
    6453typedef struct tlb_shootdown_msg tlb_shootdown_msg_t;
    6554
     55extern void tlb_init(void);
     56
     57#ifdef CONFIG_SMP
     58extern void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t cnt);
     59extern void tlb_shootdown_finalize(void);
     60extern void tlb_shootdown_ipi_recv(void);
     61#else
     62#  define tlb_shootdown_start(w, x, y, z)
     63#  define tlb_shootdown_finalize()
     64#  define tlb_shootdown_ipi_recv()
     65#endif /* CONFIG_SMP */
     66
     67
    6668/* Export TLB interface that each architecture must implement. */
    6769extern void tlb_arch_init(void);
    6870extern void tlb_print(void);
    69 extern void tlb_invalidate(asid_t asid);
    7071extern void tlb_shootdown_ipi_send(void);
    7172
    7273extern void tlb_invalidate_all(void);
    7374extern void tlb_invalidate_asid(asid_t asid);
    74 extern void tlb_invalidate_page(asid_t asid, __address page);
    75 
     75extern void tlb_invalidate_pages(asid_t asid, __address page, count_t cnt);
    7676#endif
  • generic/src/main/kinit.c

    r64c44e8 r4512d7e  
    147147                        panic("config.init_addr is not frame aligned");
    148148               
    149                 as = as_create(NULL);
     149                as = as_create(NULL, 0);
    150150                if (!as)
    151151                        panic("as_create\n");
  • generic/src/main/main.c

    r64c44e8 r4512d7e  
    186186         * Create kernel address space.
    187187         */
    188         as = as_create(GET_PTL0_ADDRESS());
     188        as = as_create(GET_PTL0_ADDRESS(), AS_KERNEL);
    189189        if (!as)
    190190                panic("can't create kernel address space\n");
  • generic/src/mm/as.c

    r64c44e8 r4512d7e  
    3434
    3535#include <mm/as.h>
     36#include <mm/asid.h>
    3637#include <mm/page.h>
    3738#include <mm/frame.h>
     
    4041#include <arch/mm/page.h>
    4142#include <genarch/mm/page_pt.h>
     43#include <mm/asid.h>
    4244#include <arch/mm/asid.h>
    4345#include <arch/mm/as.h>
     
    7173 *        (Virtual Address Translation) mechanisms.
    7274 */
    73 as_t *as_create(pte_t *ptl0)
     75as_t *as_create(pte_t *ptl0, int flags)
    7476{
    7577        as_t *as;
     
    7779        as = (as_t *) malloc(sizeof(as_t));
    7880        if (as) {
     81                list_initialize(&as->as_with_asid_link);
    7982                spinlock_initialize(&as->lock, "as_lock");
    8083                list_initialize(&as->as_area_head);
    8184
    82                 as->asid = asid_get();
     85                if (flags & AS_KERNEL)
     86                        as->asid = ASID_KERNEL;
     87                else
     88                        as->asid = ASID_INVALID;
    8389
    8490                as->ptl0 = ptl0;
     
    290296        ipl_t ipl;
    291297       
     298        asid_install(as);
     299       
    292300        ipl = interrupts_disable();
    293301        spinlock_lock(&as->lock);
     
    299307        /*
    300308         * Perform architecture-specific steps.
    301          * (e.g. invalidate TLB, install ASID etc.)
     309         * (e.g. write ASID to hardware register etc.)
    302310         */
    303311        as_install_arch(as);
  • generic/src/mm/tlb.c

    r64c44e8 r4512d7e  
    4747#ifdef CONFIG_SMP
    4848/* must be called with interrupts disabled */
    49 void tlb_shootdown_start(void)
     49void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t cnt)
    5050{
    5151        int i;
     
    5353        CPU->tlb_active = 0;
    5454        spinlock_lock(&tlblock);
     55       
     56        /*
     57         * TODO: assemble shootdown message.
     58         */
    5559        tlb_shootdown_ipi_send();
    56         tlb_invalidate(0); /* TODO: use valid ASID */
     60
     61        switch (type) {
     62            case TLB_INVL_ALL:
     63                tlb_invalidate_all();
     64                break;
     65            case TLB_INVL_ASID:
     66                tlb_invalidate_asid(asid);
     67                break;
     68            case TLB_INVL_PAGES:
     69                tlb_invalidate_pages(asid, page, cnt);
     70                break;
     71            default:
     72                panic("unknown tlb_invalidate_type_t value: %d\n", type);
     73                break;
     74        }
    5775       
    5876busy_wait:     
     
    7896        spinlock_lock(&tlblock);
    7997        spinlock_unlock(&tlblock);
    80         tlb_invalidate(0);      /* TODO: use valid ASID */
     98        tlb_invalidate_all();   /* TODO: use valid ASID */
    8199        CPU->tlb_active = 1;
    82100}
Note: See TracChangeset for help on using the changeset viewer.