Changeset 454f1da in mainline for kernel/generic/src/mm


Ignore:
Timestamp:
2007-03-26T19:35:28Z (18 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5d7daff
Parents:
4638401
Message:

Reworked handling of illegal virtual aliases caused by frame reuse.
We moved the incomplete handling from backend's frame method to
backend's page_fault method. The page_fault method is the one that
can create an illegal alias if it writes the userspace frame using
kernel address with a different page color than the page to which is
this frame mapped in userspace. When we detect this, we do D-cache
shootdown on all processors (!!!).

If we add code that accesses userspace memory from kernel address
space, we will have to check for illegal virtual aliases at all such
places.

I tested this on a 4-way simulated E6500 and a real-world Ultra 5,
which has unfortunatelly only one processor.

This solves ticket #26.

Location:
kernel/generic/src/mm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/mm/backend_anon.c

    r4638401 r454f1da  
    7979{
    8080        uintptr_t frame;
     81        bool dirty = false;
    8182
    8283        if (!as_area_check_access(area, access))
     
    9596                mutex_lock(&area->sh_info->lock);
    9697                frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
    97                         ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf);
     98                    ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf);
    9899                if (!frame) {
    99100                        bool allocate = true;
     
    114115                                frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
    115116                                memsetb(PA2KA(frame), FRAME_SIZE, 0);
     117                                dirty = true;
    116118                               
    117119                                /*
     
    144146                frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
    145147                memsetb(PA2KA(frame), FRAME_SIZE, 0);
     148                dirty = true;
    146149        }
    147150       
     
    155158                panic("Could not insert used space.\n");
    156159               
     160#ifdef CONFIG_VIRT_IDX_DCACHE
     161        if (dirty && PAGE_COLOR(PA2KA(frame)) != PAGE_COLOR(addr)) {
     162                /*
     163                 * By writing to the frame using kernel virtual address,
     164                 * we have created an illegal virtual alias. We now have to
     165                 * invalidate cachelines belonging to addr on all processors
     166                 * so that they will be reloaded with the new content on next
     167                 * read.
     168                 */
     169                dcache_flush_frame(addr, frame);
     170                dcache_shootdown_start(DCACHE_INVL_FRAME, PAGE_COLOR(addr), frame);
     171                dcache_shootdown_finalize();
     172        }
     173#endif
     174
    157175        return AS_PF_OK;
    158176}
     
    169187{
    170188        frame_free(frame);
    171 #ifdef CONFIG_VIRT_IDX_DCACHE
    172         dcache_flush_frame(page, frame);
    173 #endif
    174189}
    175190
     
    218233                                frame_reference_add(pfn);
    219234                        }
    220                                
     235
    221236                }
    222237        }
  • kernel/generic/src/mm/backend_elf.c

    r4638401 r454f1da  
    8282        uintptr_t base, frame;
    8383        index_t i;
     84        bool dirty = false;
    8485
    8586        if (!as_area_check_access(area, access))
     
    148149                        memcpy((void *) PA2KA(frame),
    149150                            (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
    150                        
     151                        dirty = true;
     152
    151153                        if (area->sh_info) {
    152154                                frame_reference_add(ADDR2PFN(frame));
     
    169171                frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
    170172                memsetb(PA2KA(frame), FRAME_SIZE, 0);
     173                dirty = true;
    171174
    172175                if (area->sh_info) {
     
    189192                memcpy((void *) PA2KA(frame), (void *) (base + i * FRAME_SIZE),
    190193                    size);
     194                dirty = true;
    191195
    192196                if (area->sh_info) {
     
    205209        if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
    206210                panic("Could not insert used space.\n");
     211
     212#ifdef CONFIG_VIRT_IDX_DCACHE
     213        if (dirty && PAGE_COLOR(PA2KA(frame)) != PAGE_COLOR(addr)) {
     214                /*
     215                 * By writing to the frame using kernel virtual address,
     216                 * we have created an illegal virtual alias. We now have to
     217                 * invalidate cachelines belonging to addr on all processors
     218                 * so that they will be reloaded with the new content on next
     219                 * read.
     220                 */
     221                dcache_flush_frame(addr, frame);
     222                dcache_shootdown_start(DCACHE_INVL_FRAME, PAGE_COLOR(addr), frame);
     223                dcache_shootdown_finalize();
     224        }
     225#endif
    207226
    208227        return AS_PF_OK;
     
    239258                         */
    240259                        frame_free(frame);
    241 #ifdef CONFIG_VIRT_IDX_DCACHE
    242                         dcache_flush_frame(page, frame);
    243 #endif
    244260                }
    245261        } else {
     
    248264                 * lower part is backed by the ELF image and the upper is
    249265                 * anonymous). In any case, a frame needs to be freed.
    250                  */
    251                 frame_free(frame);
    252 #ifdef CONFIG_VIRT_IDX_DCACHE
    253                 dcache_flush_frame(page, frame);
    254 #endif
     266                 */
     267                frame_free(frame);
    255268        }
    256269}
Note: See TracChangeset for help on using the changeset viewer.