cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

arch_memory_mapping.c (9838B)


      1/*
      2 * i386 memory mapping
      3 *
      4 * Copyright Fujitsu, Corp. 2011, 2012
      5 *
      6 * Authors:
      7 *     Wen Congyang <wency@cn.fujitsu.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10 * See the COPYING file in the top-level directory.
     11 *
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "cpu.h"
     16#include "sysemu/memory_mapping.h"
     17
     18/* PAE Paging or IA-32e Paging */
     19static void walk_pte(MemoryMappingList *list, AddressSpace *as,
     20                     hwaddr pte_start_addr,
     21                     int32_t a20_mask, target_ulong start_line_addr)
     22{
     23    hwaddr pte_addr, start_paddr;
     24    uint64_t pte;
     25    target_ulong start_vaddr;
     26    int i;
     27
     28    for (i = 0; i < 512; i++) {
     29        pte_addr = (pte_start_addr + i * 8) & a20_mask;
     30        pte = address_space_ldq(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
     31        if (!(pte & PG_PRESENT_MASK)) {
     32            /* not present */
     33            continue;
     34        }
     35
     36        start_paddr = (pte & ~0xfff) & ~(0x1ULL << 63);
     37        if (cpu_physical_memory_is_io(start_paddr)) {
     38            /* I/O region */
     39            continue;
     40        }
     41
     42        start_vaddr = start_line_addr | ((i & 0x1ff) << 12);
     43        memory_mapping_list_add_merge_sorted(list, start_paddr,
     44                                             start_vaddr, 1 << 12);
     45    }
     46}
     47
     48/* 32-bit Paging */
     49static void walk_pte2(MemoryMappingList *list, AddressSpace *as,
     50                      hwaddr pte_start_addr, int32_t a20_mask,
     51                      target_ulong start_line_addr)
     52{
     53    hwaddr pte_addr, start_paddr;
     54    uint32_t pte;
     55    target_ulong start_vaddr;
     56    int i;
     57
     58    for (i = 0; i < 1024; i++) {
     59        pte_addr = (pte_start_addr + i * 4) & a20_mask;
     60        pte = address_space_ldl(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
     61        if (!(pte & PG_PRESENT_MASK)) {
     62            /* not present */
     63            continue;
     64        }
     65
     66        start_paddr = pte & ~0xfff;
     67        if (cpu_physical_memory_is_io(start_paddr)) {
     68            /* I/O region */
     69            continue;
     70        }
     71
     72        start_vaddr = start_line_addr | ((i & 0x3ff) << 12);
     73        memory_mapping_list_add_merge_sorted(list, start_paddr,
     74                                             start_vaddr, 1 << 12);
     75    }
     76}
     77
     78/* PAE Paging or IA-32e Paging */
     79#define PLM4_ADDR_MASK 0xffffffffff000ULL /* selects bits 51:12 */
     80
     81static void walk_pde(MemoryMappingList *list, AddressSpace *as,
     82                     hwaddr pde_start_addr,
     83                     int32_t a20_mask, target_ulong start_line_addr)
     84{
     85    hwaddr pde_addr, pte_start_addr, start_paddr;
     86    uint64_t pde;
     87    target_ulong line_addr, start_vaddr;
     88    int i;
     89
     90    for (i = 0; i < 512; i++) {
     91        pde_addr = (pde_start_addr + i * 8) & a20_mask;
     92        pde = address_space_ldq(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
     93        if (!(pde & PG_PRESENT_MASK)) {
     94            /* not present */
     95            continue;
     96        }
     97
     98        line_addr = start_line_addr | ((i & 0x1ff) << 21);
     99        if (pde & PG_PSE_MASK) {
    100            /* 2 MB page */
    101            start_paddr = (pde & ~0x1fffff) & ~(0x1ULL << 63);
    102            if (cpu_physical_memory_is_io(start_paddr)) {
    103                /* I/O region */
    104                continue;
    105            }
    106            start_vaddr = line_addr;
    107            memory_mapping_list_add_merge_sorted(list, start_paddr,
    108                                                 start_vaddr, 1 << 21);
    109            continue;
    110        }
    111
    112        pte_start_addr = (pde & PLM4_ADDR_MASK) & a20_mask;
    113        walk_pte(list, as, pte_start_addr, a20_mask, line_addr);
    114    }
    115}
    116
    117/* 32-bit Paging */
    118static void walk_pde2(MemoryMappingList *list, AddressSpace *as,
    119                      hwaddr pde_start_addr, int32_t a20_mask,
    120                      bool pse)
    121{
    122    hwaddr pde_addr, pte_start_addr, start_paddr, high_paddr;
    123    uint32_t pde;
    124    target_ulong line_addr, start_vaddr;
    125    int i;
    126
    127    for (i = 0; i < 1024; i++) {
    128        pde_addr = (pde_start_addr + i * 4) & a20_mask;
    129        pde = address_space_ldl(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
    130        if (!(pde & PG_PRESENT_MASK)) {
    131            /* not present */
    132            continue;
    133        }
    134
    135        line_addr = (((unsigned int)i & 0x3ff) << 22);
    136        if ((pde & PG_PSE_MASK) && pse) {
    137            /*
    138             * 4 MB page:
    139             * bits 39:32 are bits 20:13 of the PDE
    140             * bit3 31:22 are bits 31:22 of the PDE
    141             */
    142            high_paddr = ((hwaddr)(pde & 0x1fe000) << 19);
    143            start_paddr = (pde & ~0x3fffff) | high_paddr;
    144            if (cpu_physical_memory_is_io(start_paddr)) {
    145                /* I/O region */
    146                continue;
    147            }
    148            start_vaddr = line_addr;
    149            memory_mapping_list_add_merge_sorted(list, start_paddr,
    150                                                 start_vaddr, 1 << 22);
    151            continue;
    152        }
    153
    154        pte_start_addr = (pde & ~0xfff) & a20_mask;
    155        walk_pte2(list, as, pte_start_addr, a20_mask, line_addr);
    156    }
    157}
    158
    159/* PAE Paging */
    160static void walk_pdpe2(MemoryMappingList *list, AddressSpace *as,
    161                       hwaddr pdpe_start_addr, int32_t a20_mask)
    162{
    163    hwaddr pdpe_addr, pde_start_addr;
    164    uint64_t pdpe;
    165    target_ulong line_addr;
    166    int i;
    167
    168    for (i = 0; i < 4; i++) {
    169        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
    170        pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
    171        if (!(pdpe & PG_PRESENT_MASK)) {
    172            /* not present */
    173            continue;
    174        }
    175
    176        line_addr = (((unsigned int)i & 0x3) << 30);
    177        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
    178        walk_pde(list, as, pde_start_addr, a20_mask, line_addr);
    179    }
    180}
    181
    182#ifdef TARGET_X86_64
    183/* IA-32e Paging */
    184static void walk_pdpe(MemoryMappingList *list, AddressSpace *as,
    185                      hwaddr pdpe_start_addr, int32_t a20_mask,
    186                      target_ulong start_line_addr)
    187{
    188    hwaddr pdpe_addr, pde_start_addr, start_paddr;
    189    uint64_t pdpe;
    190    target_ulong line_addr, start_vaddr;
    191    int i;
    192
    193    for (i = 0; i < 512; i++) {
    194        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
    195        pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
    196        if (!(pdpe & PG_PRESENT_MASK)) {
    197            /* not present */
    198            continue;
    199        }
    200
    201        line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
    202        if (pdpe & PG_PSE_MASK) {
    203            /* 1 GB page */
    204            start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
    205            if (cpu_physical_memory_is_io(start_paddr)) {
    206                /* I/O region */
    207                continue;
    208            }
    209            start_vaddr = line_addr;
    210            memory_mapping_list_add_merge_sorted(list, start_paddr,
    211                                                 start_vaddr, 1 << 30);
    212            continue;
    213        }
    214
    215        pde_start_addr = (pdpe & PLM4_ADDR_MASK) & a20_mask;
    216        walk_pde(list, as, pde_start_addr, a20_mask, line_addr);
    217    }
    218}
    219
    220/* IA-32e Paging */
    221static void walk_pml4e(MemoryMappingList *list, AddressSpace *as,
    222                       hwaddr pml4e_start_addr, int32_t a20_mask,
    223                       target_ulong start_line_addr)
    224{
    225    hwaddr pml4e_addr, pdpe_start_addr;
    226    uint64_t pml4e;
    227    target_ulong line_addr;
    228    int i;
    229
    230    for (i = 0; i < 512; i++) {
    231        pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
    232        pml4e = address_space_ldq(as, pml4e_addr, MEMTXATTRS_UNSPECIFIED,
    233                                  NULL);
    234        if (!(pml4e & PG_PRESENT_MASK)) {
    235            /* not present */
    236            continue;
    237        }
    238
    239        line_addr = start_line_addr | ((i & 0x1ffULL) << 39);
    240        pdpe_start_addr = (pml4e & PLM4_ADDR_MASK) & a20_mask;
    241        walk_pdpe(list, as, pdpe_start_addr, a20_mask, line_addr);
    242    }
    243}
    244
    245static void walk_pml5e(MemoryMappingList *list, AddressSpace *as,
    246                       hwaddr pml5e_start_addr, int32_t a20_mask)
    247{
    248    hwaddr pml5e_addr, pml4e_start_addr;
    249    uint64_t pml5e;
    250    target_ulong line_addr;
    251    int i;
    252
    253    for (i = 0; i < 512; i++) {
    254        pml5e_addr = (pml5e_start_addr + i * 8) & a20_mask;
    255        pml5e = address_space_ldq(as, pml5e_addr, MEMTXATTRS_UNSPECIFIED,
    256                                  NULL);
    257        if (!(pml5e & PG_PRESENT_MASK)) {
    258            /* not present */
    259            continue;
    260        }
    261
    262        line_addr = (0x7fULL << 57) | ((i & 0x1ffULL) << 48);
    263        pml4e_start_addr = (pml5e & PLM4_ADDR_MASK) & a20_mask;
    264        walk_pml4e(list, as, pml4e_start_addr, a20_mask, line_addr);
    265    }
    266}
    267#endif
    268
    269void x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list,
    270                                Error **errp)
    271{
    272    X86CPU *cpu = X86_CPU(cs);
    273    CPUX86State *env = &cpu->env;
    274    int32_t a20_mask;
    275
    276    if (!cpu_paging_enabled(cs)) {
    277        /* paging is disabled */
    278        return;
    279    }
    280
    281    a20_mask = x86_get_a20_mask(env);
    282    if (env->cr[4] & CR4_PAE_MASK) {
    283#ifdef TARGET_X86_64
    284        if (env->hflags & HF_LMA_MASK) {
    285            if (env->cr[4] & CR4_LA57_MASK) {
    286                hwaddr pml5e_addr;
    287
    288                pml5e_addr = (env->cr[3] & PLM4_ADDR_MASK) & a20_mask;
    289                walk_pml5e(list, cs->as, pml5e_addr, a20_mask);
    290            } else {
    291                hwaddr pml4e_addr;
    292
    293                pml4e_addr = (env->cr[3] & PLM4_ADDR_MASK) & a20_mask;
    294                walk_pml4e(list, cs->as, pml4e_addr, a20_mask,
    295                        0xffffULL << 48);
    296            }
    297        } else
    298#endif
    299        {
    300            hwaddr pdpe_addr;
    301
    302            pdpe_addr = (env->cr[3] & ~0x1f) & a20_mask;
    303            walk_pdpe2(list, cs->as, pdpe_addr, a20_mask);
    304        }
    305    } else {
    306        hwaddr pde_addr;
    307        bool pse;
    308
    309        pde_addr = (env->cr[3] & ~0xfff) & a20_mask;
    310        pse = !!(env->cr[4] & CR4_PSE_MASK);
    311        walk_pde2(list, cs->as, pde_addr, a20_mask, pse);
    312    }
    313}
    314