Changeset ff9f858 in mainline


Ignore:
Timestamp:
2005-06-30T23:27:02Z (20 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a1a03f9
Parents:
992bbb97
Message:

Generic 4-level page tables interface & implementation (review & test).
Implement more architecture dependant macros on IA-32.
Provide fake implementation on IA-64 and MIPS.
Convert map_page_to_frame() to use the new interface.
Move adjusted map_page_to_frame() from IA-32's arch/mm/page.c to the generic mm/page.c.

Files:
9 edited

Legend:

Unmodified
Added
Removed
  • arch/ia32/include/mm/page.h

    r992bbb97 rff9f858  
    3030#define __ia32_PAGE_H__
    3131
     32#include <mm/page.h>
    3233#include <arch/types.h>
    3334#include <arch/mm/frame.h>
     35#include <typedefs.h>
    3436
    3537#define PAGE_SIZE       FRAME_SIZE
     
    4749#define PTL3_INDEX_ARCH(vaddr)  (((vaddr)>>12)&0x3ff)
    4850
     51#define GET_PTL0_ADDRESS_ARCH()                 ((pte_t *) read_cr3())
    4952#define GET_PTL1_ADDRESS_ARCH(ptl0, i)          ((pte_t *)((((pte_t *)(ptl0))[(i)].frame_address)<<12))
    5053#define GET_PTL2_ADDRESS_ARCH(ptl1, i)          (ptl1)
     
    5255#define GET_FRAME_ADDRESS_ARCH(ptl3, i)         ((__address)((((pte_t *)(ptl3))[(i)].frame_address)<<12))
    5356
     57#define SET_PTL0_ADDRESS_ARCH(ptl0)             (write_cr3((__address) (ptl0)))
     58#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)       (((pte_t *)(ptl0))[(i)].frame_address = (a)>>12)
     59#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
     60#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
     61#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a)      (((pte_t *)(ptl3))[(i)].frame_address = (a)>>12)
     62
     63#define GET_PTL1_FLAGS_ARCH(ptl0, i)            get_pt_flags((pte_t *)(ptl0), (index_t)(i))
     64#define GET_PTL2_FLAGS_ARCH(ptl1, i)            PAGE_PRESENT
     65#define GET_PTL3_FLAGS_ARCH(ptl2, i)            PAGE_PRESENT
     66#define GET_FRAME_FLAGS_ARCH(ptl3, i)           get_pt_flags((pte_t *)(ptl3), (index_t)(i))
     67
     68#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)         set_pt_flags((pte_t *)(ptl0), (index_t)(i), (x))
     69#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
     70#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
     71#define SET_FRAME_FLAGS_ARCH(ptl3, i, x)        set_pt_flags((pte_t *)(ptl3), (index_t)(i), (x))
    5472
    5573struct page_specifier {
     
    6684} __attribute__ ((packed));
    6785
    68 typedef struct page_specifier   pte_t;
     86typedef struct page_specifier pte_t;
     87
     88static inline int get_pt_flags(pte_t *pt, index_t i)
     89{
     90        pte_t *p = &pt[i];
     91       
     92        return (
     93                (!p->page_cache_disable)<<PAGE_CACHEABLE_SHIFT |
     94                (!p->present)<<PAGE_PRESENT_SHIFT |
     95                p->uaccessible<<PAGE_USER_SHIFT |
     96                1<<PAGE_READ_SHIFT |
     97                p->writeable<<PAGE_WRITE_SHIFT |
     98                1<<PAGE_EXEC_SHIFT
     99        );
     100}
     101
     102static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
     103{
     104        pte_t *p = &pt[i];
     105       
     106        p->page_cache_disable = !(flags & PAGE_CACHEABLE);
     107        p->present = !(flags & PAGE_NOT_PRESENT);
     108        p->uaccessible = flags & PAGE_USER;
     109        p->writeable = flags & PAGE_WRITE;
     110}
    69111
    70112extern void page_arch_init(void);
  • arch/ia32/src/mm/page.c

    r992bbb97 rff9f858  
    8787        paging_on();
    8888}
    89 
    90 /*
    91  * Besides mapping pages to frames, this function also sets the present bit of
    92  * the page's specifier in both page directory and respective page table. If
    93  * the page table for this page has not been allocated so far, it will take
    94  * care of it and allocate the necessary frame.
    95  *
    96  * PAGE_CACHEABLE flag: when set, it turns caches for that page on
    97  * PAGE_NOT_PRESENT flag: when set, it marks the page not present
    98  * PAGE_USER flag: when set, the page is accessible from userspace
    99  *
    100  * When the root parameter is non-zero, it is used as the page directory address.
    101  * Otherwise, the page directory address is read from CPU.
    102  */
    103 void map_page_to_frame(__address page, __address frame, int flags, __address root)
    104 {
    105         struct page_specifier *pd, *pt;
    106         __address dba, newpt;
    107         int pde, pte;
    108 
    109         if (root) dba = root;
    110         else dba = read_cr3();
    111 
    112         pde = page >> 22;               /* page directory entry */
    113         pte = (page >> 12) & 0x3ff;     /* page table entry */
    114        
    115         pd = (struct page_specifier *) PA2KA(dba);
    116        
    117         if (!pd[pde].present) {
    118                 /*
    119                  * There is currently no page table for this address. Allocate
    120                  * frame for the page table and clean it.
    121                  */
    122                 newpt = frame_alloc(FRAME_KA);
    123                 pd[pde].frame_address = KA2PA(newpt) >> 12;
    124                 memsetb(newpt, PAGE_SIZE, 0);
    125                 pd[pde].present = 1;
    126                 pd[pde].uaccessible = 1;
    127         }
    128        
    129         pt = (struct page_specifier *) PA2KA((pd[pde].frame_address << 12));
    130 
    131         pt[pte].frame_address = frame >> 12;
    132         pt[pte].present = !(flags & PAGE_NOT_PRESENT);
    133         pt[pte].page_cache_disable = !(flags & PAGE_CACHEABLE);
    134         pt[pte].uaccessible = (flags & PAGE_USER) != 0;
    135         pt[pte].writeable = (flags & PAGE_WRITE) != 0; 
    136 }
  • arch/ia64/include/mm/page.h

    r992bbb97 rff9f858  
    3939#define page_arch_init()        ;
    4040
     41/*
     42 * Implementation of generic 4-level page table interface.
     43 * TODO: this is a fake implementation provided to satisfy the compiler
     44 */
     45#define PTL0_INDEX_ARCH(vaddr)  0
     46#define PTL1_INDEX_ARCH(vaddr)  0
     47#define PTL2_INDEX_ARCH(vaddr)  0
     48#define PTL3_INDEX_ARCH(vaddr)  0
     49
     50#define GET_PTL0_ADDRESS_ARCH()                 ((pte_t *) 0)
     51#define GET_PTL1_ADDRESS_ARCH(ptl0, i)          ((pte_t *) 0)
     52#define GET_PTL2_ADDRESS_ARCH(ptl1, i)          ((pte_t *) 0)
     53#define GET_PTL3_ADDRESS_ARCH(ptl2, i)          ((pte_t *) 0)
     54#define GET_FRAME_ADDRESS_ARCH(ptl3, i)         ((pte_t *) 0)
     55
     56#define SET_PTL0_ADDRESS_ARCH(ptl0)
     57#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)
     58#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
     59#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
     60#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a)
     61
     62#define GET_PTL1_FLAGS_ARCH(ptl0, i)            0
     63#define GET_PTL2_FLAGS_ARCH(ptl1, i)            0
     64#define GET_PTL3_FLAGS_ARCH(ptl2, i)            0
     65#define GET_FRAME_FLAGS_ARCH(ptl3, i)           0
     66
     67#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)
     68#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
     69#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
     70#define SET_FRAME_FLAGS_ARCH(ptl3, i, x)
     71
     72typedef __u64 pte_t;
     73
    4174#endif
  • arch/ia64/src/fake.s

    r992bbb97 rff9f858  
    4343.global cpu_sleep
    4444.global frame_arch_init
    45 .global map_page_to_frame
    4645
    4746before_thread_runs_arch:
     
    5958cpu_sleep:
    6059frame_arch_init:
    61 map_page_to_frame:
    6260        br.ret.sptk.many b0
    6361
  • arch/mips/include/mm/page.h

    r992bbb97 rff9f858  
    3131
    3232#include <arch/mm/frame.h>
     33#include <arch/types.h>
    3334
    3435#define PAGE_SIZE       FRAME_SIZE
     
    3940#define page_arch_init()        ;
    4041
     42/*
     43 * Implementation of generic 4-level page table interface.
     44 * TODO: this is a fake implementation provided to satisfy the compiler
     45 */
     46#define PTL0_INDEX_ARCH(vaddr)  0
     47#define PTL1_INDEX_ARCH(vaddr)  0
     48#define PTL2_INDEX_ARCH(vaddr)  0
     49#define PTL3_INDEX_ARCH(vaddr)  0
     50
     51#define GET_PTL0_ADDRESS_ARCH()                 ((pte_t *) 0)
     52#define GET_PTL1_ADDRESS_ARCH(ptl0, i)          ((pte_t *) 0)
     53#define GET_PTL2_ADDRESS_ARCH(ptl1, i)          ((pte_t *) 0)
     54#define GET_PTL3_ADDRESS_ARCH(ptl2, i)          ((pte_t *) 0)
     55#define GET_FRAME_ADDRESS_ARCH(ptl3, i)         ((pte_t *) 0)
     56
     57#define SET_PTL0_ADDRESS_ARCH(ptl0)
     58#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)
     59#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
     60#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
     61#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a)
     62
     63#define GET_PTL1_FLAGS_ARCH(ptl0, i)            0
     64#define GET_PTL2_FLAGS_ARCH(ptl1, i)            0
     65#define GET_PTL3_FLAGS_ARCH(ptl2, i)            0
     66#define GET_FRAME_FLAGS_ARCH(ptl3, i)           0
     67
     68#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)
     69#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
     70#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
     71#define SET_FRAME_FLAGS_ARCH(ptl3, i, x)
     72
     73typedef __u32 pte_t;
     74
    4175#endif
  • arch/mips/src/mm/page.c

    r992bbb97 rff9f858  
    2929#include <arch/types.h>
    3030#include <mm/page.h>
    31 
    32 void map_page_to_frame(__address page, __address frame, int flags, __address root)
    33 {
    34         /* TODO !!! */
    35 }
  • include/mm/page.h

    r992bbb97 rff9f858  
    3131
    3232#include <arch/types.h>
    33 #include <arch/mm/page.h>
    3433#include <typedefs.h>
    3534
    36 #define PAGE_NOT_CACHEABLE      (0<<0)
    37 #define PAGE_CACHEABLE          (1<<0)
     35#define PAGE_CACHEABLE_SHIFT            0
     36#define PAGE_NOT_CACHEABLE_SHIFT        PAGE_CACHEABLE_SHIFT
     37#define PAGE_PRESENT_SHIFT              1
     38#define PAGE_NOT_PRESENT_SHIFT          PAGE_PRESENT_SHIFT
     39#define PAGE_USER_SHIFT                 2
     40#define PAGE_KERNEL_SHIFT               PAGE_USER_SHIFT
     41#define PAGE_READ_SHIFT                 3
     42#define PAGE_WRITE_SHIFT                4
     43#define PAGE_EXEC_SHIFT                 5
    3844
    39 #define PAGE_PRESENT            (0<<1)
    40 #define PAGE_NOT_PRESENT        (1<<1)
     45#define PAGE_NOT_CACHEABLE      (0<<PAGE_CACHEABLE_SHIFT)
     46#define PAGE_CACHEABLE          (1<<PAGE_CACHEABLE_SHIFT)
    4147
    42 #define PAGE_USER               (1<<2)
    43 #define PAGE_KERNEL             (0<<2)
     48#define PAGE_PRESENT            (0<<PAGE_PRESENT_SHIFT)
     49#define PAGE_NOT_PRESENT        (1<<PAGE_PRESENT_SHIFT)
    4450
    45 #define PAGE_READ               (1<<3)
    46 #define PAGE_WRITE              (1<<4)
    47 #define PAGE_EXEC               (1<<5)
     51#define PAGE_USER               (1<<PAGE_USER_SHIFT)
     52#define PAGE_KERNEL             (0<<PAGE_USER_SHIFT)
     53
     54#define PAGE_READ               (1<<PAGE_READ_SHIFT)
     55#define PAGE_WRITE              (1<<PAGE_WRITE_SHIFT)
     56#define PAGE_EXEC               (1<<PAGE_EXEC_SHIFT)
    4857
    4958/*
     
    6170#define PTL3_INDEX(vaddr)               PTL3_INDEX_ARCH(vaddr)
    6271
     72#define GET_PTL0_ADDRESS()              GET_PTL0_ADDRESS_ARCH()
     73#define SET_PTL0_ADDRESS(ptl0)          SET_PTL0_ADDRESS_ARCH(ptl0)
     74
    6375/*
    6476 * These macros traverse the 4-level tree of page tables,
    6577 * each descending by one level.
    6678 */
     79#define GET_PTL0_ADDRESS()              GET_PTL0_ADDRESS_ARCH()
    6780#define GET_PTL1_ADDRESS(ptl0, i)       GET_PTL1_ADDRESS_ARCH(ptl0, i)
    6881#define GET_PTL2_ADDRESS(ptl1, i)       GET_PTL2_ADDRESS_ARCH(ptl1, i)
     
    7487 * tree of page tables on respective level.
    7588 */
     89#define SET_PTL0_ADDRESS(ptl0)          SET_PTL0_ADDRESS_ARCH(ptl0)
    7690#define SET_PTL1_ADDRESS(ptl0, i, a)    SET_PTL1_ADDRESS_ARCH(ptl0, i, a)
    7791#define SET_PTL2_ADDRESS(ptl1, i, a)    SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
    7892#define SET_PTL3_ADDRESS(ptl2, i, a)    SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
    7993#define SET_FRAME_ADDRESS(ptl3, i, a)   SET_FRAME_ADDRESS_ARCH(ptl3, i, a)
     94
     95/*
     96 * These macros are provided to query various flags within the page tables.
     97 */
     98#define GET_PTL1_FLAGS(ptl0, i)         GET_PTL1_FLAGS_ARCH(ptl0, i)
     99#define GET_PTL2_FLAGS(ptl1, i)         GET_PTL2_FLAGS_ARCH(ptl1, i)
     100#define GET_PTL3_FLAGS(ptl2, i)         GET_PTL3_FLAGS_ARCH(ptl2, i)
     101#define GET_FRAME_FLAGS(ptl3, i)        GET_FRAME_FLAGS_ARCH(ptl3, i)
    80102
    81103/*
     
    87109#define SET_FRAME_FLAGS(ptl3, i, x)     SET_FRAME_FLAGS_ARCH(ptl3, i, x)
    88110
     111#include <arch/mm/page.h>
    89112
    90113extern void page_init(void);
  • include/typedefs.h

    r992bbb97 rff9f858  
    3737typedef unsigned int size_t;
    3838typedef unsigned int count_t;
     39typedef unsigned int index_t;
    3940
    4041typedef struct config config_t;
  • src/mm/page.c

    r992bbb97 rff9f858  
    2828
    2929#include <mm/page.h>
     30#include <mm/frame.h>
    3031#include <arch/mm/page.h>
    3132#include <arch/types.h>
    3233#include <typedefs.h>
     34#include <arch/asm.h>
    3335
    3436void page_init(void)
     
    5961
    6062}
     63
     64/** Map page to frame
     65 *
     66 * Map virtual address 'page' to physical address 'frame'
     67 * using 'flags'. Allocate and setup any missing page tables.
     68 *
     69 * @param page Virtual address of the page to be mapped.
     70 * @param frame Physical address of memory frame to which the mapping is done.
     71 * @param flags Flags to be used for mapping.
     72 * @param root Explicit PTL0 address.
     73 */
     74void map_page_to_frame(__address page, __address frame, int flags, __address root)
     75{
     76        pte_t *ptl0, *ptl1, *ptl2, *ptl3;
     77        __address newpt;
     78
     79        ptl0 = (pte_t *) PA2KA(root ? root : (__address) GET_PTL0_ADDRESS());
     80
     81        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
     82                newpt = frame_alloc(FRAME_KA);
     83                memsetb(newpt, PAGE_SIZE, 0);
     84                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
     85                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER);
     86        }
     87
     88        ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
     89
     90        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
     91                newpt = frame_alloc(FRAME_KA);
     92                memsetb(newpt, PAGE_SIZE, 0);
     93                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
     94                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER);
     95        }
     96
     97        ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
     98
     99        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
     100                newpt = frame_alloc(FRAME_KA);
     101                memsetb(newpt, PAGE_SIZE, 0);
     102                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
     103                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER);
     104        }
     105
     106        ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     107
     108        SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
     109        SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
     110}
Note: See TracChangeset for help on using the changeset viewer.