Changeset e12ccc5 in mainline


Ignore:
Timestamp:
2006-08-01T17:27:11Z (18 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0fbfa0d
Parents:
e386cbf
Message:

xen32: use writable page tables, cleanup mm

Location:
kernel/arch/xen32
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/xen32/include/boot/boot.h

    re386cbf re12ccc5  
    3737
    3838#define GUEST_CMDLINE   1024
     39#define VIRT_CPUS               32
    3940#define START_INFO_SIZE 1104
     41
    4042#define BOOT_OFFSET             0x0000
     43#define XEN_VIRT_START  0xFC000000
     44
     45#define TEMP_STACK_SIZE 0x1000
    4146
    4247#ifndef __ASM__
    4348
     49#define mp_map ((pfn_t *) XEN_VIRT_START)
     50
    4451#include <arch/types.h>
     52
     53typedef uint32_t evtchn_t;
     54
     55typedef struct {
     56        uint32_t version;
     57        uint32_t pad0;
     58        uint64_t tsc_timestamp;   /**< TSC at last update of time vals */
     59        uint64_t system_time;     /**< Time, in nanosecs, since boot */
     60        uint32_t tsc_to_system_mul;
     61        int8_t tsc_shift;
     62        int8_t pad1[3];
     63} vcpu_time_info_t;
     64
     65typedef struct {
     66        uint32_t cr2;
     67        uint32_t pad[5];
     68} arch_vcpu_info_t;
     69
     70typedef struct arch_shared_info {
     71        pfn_t max_pfn;                  /**< max pfn that appears in table */
     72        uint32_t pfn_to_mfn_frame_list_list;
     73    uint32_t nmi_reason;
     74} arch_shared_info_t;
     75
     76typedef struct {
     77        uint8_t evtchn_upcall_pending;
     78        uint8_t evtchn_upcall_mask;
     79        evtchn_t evtchn_pending_sel;
     80        arch_vcpu_info_t arch;
     81        vcpu_time_info_t time;
     82} vcpu_info_t;
     83
     84typedef struct {
     85        vcpu_info_t vcpu_info[VIRT_CPUS];
     86        evtchn_t evtchn_pending[32];
     87        evtchn_t evtchn_mask[32];
     88       
     89        uint32_t wc_version;                  /**< Version counter */
     90        uint32_t wc_sec;                      /**< Secs  00:00:00 UTC, Jan 1, 1970 */
     91        uint32_t wc_nsec;                     /**< Nsecs 00:00:00 UTC, Jan 1, 1970 */
     92       
     93        arch_shared_info_t arch;
     94} shared_info_t;
    4595
    4696typedef struct {
    4797        int8_t magic[32];           /**< "xen-<version>-<platform>" */
    4898        uint32_t frames;            /**< Available frames */
    49         void *shared_info;          /**< Shared info structure (machine address) */
     99        shared_info_t *shared_info; /**< Shared info structure (machine address) */
    50100        uint32_t flags;             /**< SIF_xxx flags */
    51101        pfn_t store_mfn;            /**< Shared page (machine page) */
    52         uint32_t store_evtchn;      /**< Event channel for store communication */
     102        evtchn_t store_evtchn;      /**< Event channel for store communication */
    53103        void *console_mfn;          /**< Console page (machine address) */
    54         uint32_t console_evtchn;    /**< Event channel for console messages */
     104        evtchn_t console_evtchn;    /**< Event channel for console messages */
    55105        pte_t *ptl0;                /**< Boot PTL0 (kernel address) */
    56106        uint32_t pt_frames;         /**< Number of bootstrap page table frames */
     
    61111} start_info_t;
    62112
     113typedef struct {
     114        pfn_t start;
     115        pfn_t size;
     116        pfn_t reserved;
     117} memzone_t;
     118
    63119extern start_info_t start_info;
     120extern shared_info_t shared_info;
     121extern memzone_t meminfo;
    64122
    65123#endif
  • kernel/arch/xen32/include/hypercall.h

    re386cbf re12ccc5  
    3636typedef uint16_t domid_t;
    3737
    38 typedef struct {
    39     uint64_t ptr;  /**< Machine address of PTE */
    40     uint64_t val;  /**< New contents of PTE */
    41 } mmu_update_t;
    42 
    43 typedef struct {
    44     unsigned int cmd;
    45     union {
    46         unsigned long mfn;
    47         unsigned long linear_addr;
    48     } arg1;
    49     union {
    50         unsigned int nr_ents;
    51         void *vcpumask;
    52     } arg2;
    53 } mmuext_op_t;
    54 
    55 
    56 #define XEN_MMU_UPDATE  1
    57 #define XEN_CONSOLE_IO  18
    58 #define XEN_MMUEXT_OP   26
     38
     39#define XEN_MMU_UPDATE                  1
     40#define XEN_UPDATE_VA_MAPPING   14
     41#define XEN_CONSOLE_IO                  18
     42#define XEN_VM_ASSIST                   21
     43#define XEN_MMUEXT_OP                   26
    5944
    6045
     
    8368
    8469
     70#define UVMF_NONE                               0        /**< No flushing at all */
     71#define UVMF_TLB_FLUSH                  1        /**< Flush entire TLB(s) */
     72#define UVMF_INVLPG                             2        /**< Flush only one entry */
     73#define UVMF_FLUSHTYPE_MASK             3
     74#define UVMF_MULTI                              0        /**< Flush subset of TLBs */
     75#define UVMF_LOCAL                              0        /**< Flush local TLB */
     76#define UVMF_ALL                                (1 << 2) /**< Flush all TLBs */
     77
     78
     79/*
     80 * Commands to XEN_VM_ASSIST
     81 */
     82#define VMASST_CMD_ENABLE                               0
     83#define VMASST_CMD_DISABLE                              1
     84#define VMASST_TYPE_4GB_SEGMENTS                0
     85#define VMASST_TYPE_4GB_SEGMENTS_NOTIFY 1
     86#define VMASST_TYPE_WRITABLE_PAGETABLES 2
     87
     88
    8589#define DOMID_SELF (0x7FF0U)
    8690#define DOMID_IO   (0x7FF1U)
     
    190194}
    191195
    192 static inline int xen_mmu_update(const mmu_update_t *req, const unsigned int count, unsigned int *success_count, domid_t domid)
     196static inline int xen_vm_assist(const unsigned int cmd, const unsigned int type)
    193197{
    194         return hypercall4(XEN_MMU_UPDATE, req, count, success_count, domid);
     198    return hypercall2(XEN_VM_ASSIST, cmd, type);
    195199}
    196200
    197 static inline int xen_mmuext_op(const mmuext_op_t *op, const unsigned int count, unsigned int *success_count, domid_t domid)
    198 {
    199         return hypercall4(XEN_MMUEXT_OP, op, count, success_count, domid);
    200 }
    201 
    202201#endif
  • kernel/arch/xen32/include/mm/frame.h

    re386cbf re12ccc5  
    4747
    4848#define PA2MA(x)        ((start_info.pm_map[((uintptr_t) (x)) >> 12] << 12) + (((uintptr_t) (x)) & 0xfff))
    49 
    50 extern uintptr_t last_frame;
     49#define MA2PA(x)        ((mp_map[((uintptr_t) (x)) >> 12] << 12) + (((uintptr_t) (x)) & 0xfff))
    5150
    5251extern void frame_arch_init(void);
  • kernel/arch/xen32/include/mm/page.h

    re386cbf re12ccc5  
    4444
    4545#ifndef __ASM__
    46 #       include <arch/hypercall.h>
    4746#       define KA2PA(x) (((uintptr_t) (x)) - 0x80000000)
    4847#       define PA2KA(x) (((uintptr_t) (x)) + 0x80000000)
     
    6665#define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 12) & 0x3ff)
    6766
    68 #define GET_PTL1_ADDRESS_ARCH(ptl0, i)          ((pte_t *)((((pte_t *)(ptl0))[(i)].frame_address) << 12))
     67#define GET_PTL1_ADDRESS_ARCH(ptl0, i)          ((pte_t *) MA2PA((((pte_t *) (ptl0))[(i)].frame_address) << 12))
    6968#define GET_PTL2_ADDRESS_ARCH(ptl1, i)          (ptl1)
    7069#define GET_PTL3_ADDRESS_ARCH(ptl2, i)          (ptl2)
    71 #define GET_FRAME_ADDRESS_ARCH(ptl3, i)         ((uintptr_t)((((pte_t *)(ptl3))[(i)].frame_address) << 12))
     70#define GET_FRAME_ADDRESS_ARCH(ptl3, i)         ((uintptr_t) MA2PA((((pte_t *) (ptl3))[(i)].frame_address) << 12))
    7271
    7372#define SET_PTL0_ADDRESS_ARCH(ptl0) { \
    7473        mmuext_op_t mmu_ext; \
     74        \
    7575        mmu_ext.cmd = MMUEXT_NEW_BASEPTR; \
    76         mmu_ext.arg1.mfn = ADDR2PFN(PA2MA(ptl0)); \
     76        mmu_ext.mfn = ADDR2PFN(PA2MA(ptl0)); \
    7777        xen_mmuext_op(&mmu_ext, 1, NULL, DOMID_SELF); \
    7878}
     79
    7980#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) { \
    8081        mmu_update_t update; \
     82        \
    8183        update.ptr = PA2MA(KA2PA(&((pte_t *) (ptl0))[(i)])); \
    82         update.val = PA2MA(a); \
     84        update.val = PA2MA(a) | 0x0003; \
    8385        xen_mmu_update(&update, 1, NULL, DOMID_SELF); \
    8486}
    8587#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
    8688#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
    87 #define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) { \
    88         mmu_update_t update; \
    89         update.ptr = PA2MA(KA2PA(&((pte_t *) (ptl3))[(i)])); \
    90         update.val = PA2MA(a); \
    91         xen_mmu_update(&update, 1, NULL, DOMID_SELF); \
    92 }
    93 
    94 #define GET_PTL1_FLAGS_ARCH(ptl0, i)            get_pt_flags((pte_t *)(ptl0), (index_t)(i))
     89#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a)      (((pte_t *) (ptl3))[(i)].frame_address = PA2MA(a) >> 12)
     90
     91#define GET_PTL1_FLAGS_ARCH(ptl0, i)            get_pt_flags((pte_t *) (ptl0), (index_t)(i))
    9592#define GET_PTL2_FLAGS_ARCH(ptl1, i)            PAGE_PRESENT
    9693#define GET_PTL3_FLAGS_ARCH(ptl2, i)            PAGE_PRESENT
    97 #define GET_FRAME_FLAGS_ARCH(ptl3, i)           get_pt_flags((pte_t *)(ptl3), (index_t)(i))
    98 
    99 #define SET_PTL1_FLAGS_ARCH(ptl0, i, x)         set_pt_flags((pte_t *)(ptl0), (index_t)(i), (x))
     94#define GET_FRAME_FLAGS_ARCH(ptl3, i)           get_pt_flags((pte_t *) (ptl3), (index_t)(i))
     95
     96#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)         set_pt_flags((pte_t *) (ptl0), (index_t)(i), (x))
    10097#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
    10198#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
    102 #define SET_FRAME_FLAGS_ARCH(ptl3, i, x)        set_pt_flags((pte_t *)(ptl3), (index_t)(i), (x))
     99#define SET_FRAME_FLAGS_ARCH(ptl3, i, x)                set_pt_flags((pte_t *) (ptl3), (index_t)(i), (x))
    103100
    104101#define PTE_VALID_ARCH(p)                       (*((uint32_t *) (p)) != 0)
     
    114111#include <arch/mm/frame.h>
    115112#include <typedefs.h>
     113#include <arch/hypercall.h>
    116114
    117115/* Page fault error codes. */
     
    145143} __attribute__ ((packed));
    146144
     145typedef struct {
     146        uint64_t ptr;      /**< Machine address of PTE */
     147        union {            /**< New contents of PTE */
     148                uint64_t val;
     149                pte_t pte;
     150        };
     151} mmu_update_t;
     152
     153typedef struct {
     154        unsigned int cmd;
     155        union {
     156                unsigned long mfn;
     157                unsigned long linear_addr;
     158        };
     159        union {
     160                unsigned int nr_ents;
     161                void *vcpumask;
     162        };
     163} mmuext_op_t;
     164
     165static inline int xen_update_va_mapping(const void *va, const pte_t pte, const unsigned int flags)
     166{
     167        return hypercall4(XEN_UPDATE_VA_MAPPING, va, pte, 0, flags);
     168}
     169
     170static inline int xen_mmu_update(const mmu_update_t *req, const unsigned int count, unsigned int *success_count, domid_t domid)
     171{
     172        return hypercall4(XEN_MMU_UPDATE, req, count, success_count, domid);
     173}
     174
     175static inline int xen_mmuext_op(const mmuext_op_t *op, const unsigned int count, unsigned int *success_count, domid_t domid)
     176{
     177        return hypercall4(XEN_MMUEXT_OP, op, count, success_count, domid);
     178}
     179
    147180static inline int get_pt_flags(pte_t *pt, index_t i)
    148181{
  • kernel/arch/xen32/src/boot/boot.S

    re386cbf re12ccc5  
    3333
    3434.section __xen_guest
    35         .ascii  "GUEST_OS=HelenOS,"
    36         .ascii  "XEN_VER=xen-3.0,"
    37         .ascii  "HYPERCALL_PAGE=0x0000,"
    38         .ascii  "LOADER=generic"
     35        .ascii "GUEST_OS=HelenOS,"
     36        .ascii "XEN_VER=xen-3.0,"
     37        .ascii "HYPERCALL_PAGE=0x0000,"
     38        .ascii "LOADER=generic,"
     39        .ascii "FEATURES=writable_page_tables"
    3940        .byte   0
    4041
     
    5253        cld
    5354        rep movsb
    54 
     55       
     56        # switch to temporal kernel stack
     57       
     58        movl $kernel_stack, %esp
     59       
     60        call arch_pre_main
    5561        call main_bsp                                                           # never returns
    5662
    5763        cli
    5864        hlt
     65
     66kernel_stack_bottom:
     67        .space TEMP_STACK_SIZE
     68kernel_stack:
    5969
    6070.section K_TEXT_START, "aw", @progbits
     
    6373hypercall_page:
    6474        .space PAGE_SIZE
     75
     76.global shared_info
     77.org 0x1000
     78shared_info:
     79        .space PAGE_SIZE
  • kernel/arch/xen32/src/mm/frame.c

    re386cbf re12ccc5  
    3535
    3636#include <mm/frame.h>
    37 #include <arch/mm/frame.h>
    38 #include <mm/as.h>
    3937#include <config.h>
    40 #include <arch/boot/boot.h>
    41 #include <arch/hypercall.h>
    42 #include <panic.h>
    43 #include <debug.h>
    44 #include <align.h>
    45 #include <macros.h>
    46 
    47 #include <console/cmd.h>
    48 #include <console/kconsole.h>
    49 
    50 uintptr_t last_frame = 0;
    51 
    52 #define L0_PT_SHIFT     10
    53 #define L3_PT_SHIFT     0
    54 
    55 #define L0_PT_ENTRIES   1024
    56 #define L3_PT_ENTRIES   1024
    57 
    58 #define L0_INDEX_MASK                   (L0_PT_ENTRIES - 1)
    59 #define L3_INDEX_MASK                   (L3_PT_ENTRIES - 1)
    60 
    61 #define PFN2PTL0_INDEX(pfn)     ((pfn >> L0_PT_SHIFT) & L0_INDEX_MASK)
    62 #define PFN2PTL3_INDEX(pfn)     ((pfn >> L3_PT_SHIFT) & L3_INDEX_MASK)
    63 
    64 #define PAGE_MASK       (~(PAGE_SIZE - 1))
    65 
    66 #define _PAGE_PRESENT   0x001UL
    67 #define _PAGE_RW                0x002UL
    68 #define _PAGE_USER              0x004UL
    69 #define _PAGE_PWT               0x008UL
    70 #define _PAGE_PCD               0x010UL
    71 #define _PAGE_ACCESSED  0x020UL
    72 #define _PAGE_DIRTY             0x040UL
    73 #define _PAGE_PAT               0x080UL
    74 #define _PAGE_PSE               0x080UL
    75 #define _PAGE_GLOBAL    0x100UL
    76 
    77 #define L0_PROT (_PAGE_PRESENT | _PAGE_ACCESSED)
    78 #define L3_PROT (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED)
    7938
    8039void frame_arch_init(void)
    8140{
    8241        if (config.cpu_active == 1) {
    83                 /* The only memory zone starts just after page table */
    84                 pfn_t start = ADDR2PFN(ALIGN_UP(KA2PA(start_info.ptl0), PAGE_SIZE)) + start_info.pt_frames;
    85                 size_t size = start_info.frames - start;
    86                
    87                 /* Create identity mapping */
    88                 pfn_t phys;
    89                 count_t count = 0;
    90                 for (phys = start; phys < start + size; phys++) {
    91                         mmu_update_t updates[L3_PT_ENTRIES];
    92                         pfn_t virt = ADDR2PFN(PA2KA(PFN2ADDR(phys)));
    93                        
    94                         size_t ptl0_index = PFN2PTL0_INDEX(virt);
    95                         size_t ptl3_index = PFN2PTL3_INDEX(virt);
    96                        
    97                         pte_t *ptl3 = (pte_t *) PFN2ADDR(start_info.ptl0[ptl0_index].frame_address);
    98                        
    99                         if (ptl3 == 0) {
    100                                 mmuext_op_t mmu_ext;
    101                                
    102                                 pfn_t virt2 = ADDR2PFN(PA2KA(PFN2ADDR(start)));
    103                                
    104                                 /* New L1 page table entry needed */
    105                                 memsetb(PFN2ADDR(virt2), PAGE_SIZE, 0);
    106                                
    107                                 size_t ptl0_index2 = PFN2PTL0_INDEX(virt2);
    108                                 size_t ptl3_index2 = PFN2PTL3_INDEX(virt2);
    109                                 pte_t *ptl3_2 = (pte_t *) PFN2ADDR(start_info.ptl0[ptl0_index2].frame_address);
    110                                
    111                                 if (ptl3_2 == 0)
    112                                         panic("Unable to find page table reference");
    113                                
    114                                 updates[count].ptr = (uintptr_t) &ptl3_2[ptl3_index2];
    115                                 updates[count].val = PA2MA(PFN2ADDR(start)) | L0_PROT;
    116                                 if (xen_mmu_update(updates, count + 1, NULL, DOMID_SELF) < 0)
    117                                         panic("Unable to map new page table");
    118                                 count = 0;
    119                                
    120                                 mmu_ext.cmd = MMUEXT_PIN_L1_TABLE;
    121                                 mmu_ext.arg1.mfn = ADDR2PFN(PA2MA(PFN2ADDR(start)));
    122                                 if (xen_mmuext_op(&mmu_ext, 1, NULL, DOMID_SELF) < 0)
    123                                         panic("Error pinning new page table");
    124                                
    125                                 pte_t *ptl0 = (pte_t *) PA2MA(KA2PA(start_info.ptl0));
    126                                
    127                                 updates[count].ptr = (uintptr_t) &ptl0[ptl0_index];
    128                                 updates[count].val = PA2MA(PFN2ADDR(start)) | L3_PROT;
    129                                 if (xen_mmu_update(updates, count + 1, NULL, DOMID_SELF) < 0)
    130                                         panic("Unable to update PTE for page table");
    131                                 count = 0;
    132                                
    133                                 ptl3 = (pte_t *) PFN2ADDR(start_info.ptl0[ptl0_index].frame_address);
    134                                 start++;
    135                                 size--;
    136                         }
    137                        
    138                         updates[count].ptr = (uintptr_t) &ptl3[ptl3_index];
    139                         updates[count].val = PA2MA(PFN2ADDR(phys)) | L3_PROT;
    140                         count++;
    141                        
    142                         if ((count == L3_PT_ENTRIES) || (phys + 1 == start + size)) {
    143                                 if (xen_mmu_update(updates, count, NULL, DOMID_SELF) < 0)
    144                                         panic("Unable to update PTE");
    145                                 count = 0;
    146                         }
    147                 }
    148                
    149                 zone_create(start, size, start, 0);
    150                 last_frame = start + size;
     42                /* The only memory zone */
     43                zone_create(meminfo.start, meminfo.size, meminfo.start + meminfo.reserved, 0);
     44                frame_mark_unavailable(meminfo.start, meminfo.reserved);
    15145        }
    15246}
  • kernel/arch/xen32/src/xen32.c

    re386cbf re12ccc5  
    3737#include <arch/types.h>
    3838#include <typedefs.h>
     39#include <align.h>
    3940
    4041#include <arch/pm.h>
    4142
    4243#include <arch/drivers/xconsole.h>
     44#include <arch/mm/page.h>
    4345
    4446#include <arch/context.h>
     
    6163
    6264start_info_t start_info;
     65memzone_t meminfo;
     66
     67void arch_pre_main(void)
     68{
     69        xen_vm_assist(VMASST_CMD_ENABLE, VMASST_TYPE_WRITABLE_PAGETABLES);
     70       
     71        pte_t pte;
     72        memsetb((uintptr_t) &pte, sizeof(pte), 0);
     73       
     74        pte.present = 1;
     75        pte.writeable = 1;
     76        pte.frame_address = ADDR2PFN((uintptr_t) start_info.shared_info);
     77        xen_update_va_mapping(&shared_info, pte, UVMF_INVLPG);
     78       
     79        /* Create identity mapping */
     80       
     81        meminfo.start = ADDR2PFN(ALIGN_UP(KA2PA(start_info.ptl0), PAGE_SIZE)) + start_info.pt_frames;
     82        meminfo.size = start_info.frames - meminfo.start;
     83        meminfo.reserved = 0;
     84       
     85        uintptr_t pa;
     86        index_t last_ptl0 = 0;
     87        for (pa = PFN2ADDR(meminfo.start); pa < PFN2ADDR(meminfo.start + meminfo.size); pa += FRAME_SIZE) {
     88                uintptr_t va = PA2KA(pa);
     89               
     90                if ((PTL0_INDEX(va) != last_ptl0) && (GET_PTL1_FLAGS(start_info.ptl0, PTL0_INDEX(va)) & PAGE_NOT_PRESENT)) {
     91                        /* New page directory entry needed */
     92                        uintptr_t tpa = PFN2ADDR(meminfo.start + meminfo.reserved);
     93                        uintptr_t tva = PA2KA(tpa);
     94                       
     95                        memsetb(tva, PAGE_SIZE, 0);
     96                       
     97                        pte_t *tptl3 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(start_info.ptl0, PTL0_INDEX(tva)));
     98                        SET_FRAME_FLAGS(tptl3, PTL3_INDEX(tva), PAGE_PRESENT);
     99                        SET_PTL1_ADDRESS(start_info.ptl0, PTL0_INDEX(va), tpa);
     100                       
     101                        last_ptl0 = PTL0_INDEX(va);
     102                        meminfo.reserved++;
     103                }
     104               
     105                pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(start_info.ptl0, PTL0_INDEX(va)));
     106               
     107                SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(va), pa);
     108                SET_FRAME_FLAGS(ptl3, PTL3_INDEX(va), PAGE_PRESENT | PAGE_WRITE);
     109        }
     110}
    63111
    64112void arch_pre_mm_init(void)
Note: See TracChangeset for help on using the changeset viewer.