aboutsummaryrefslogtreecommitdiff
path: root/xen/include/asm-arm/arm32/page.h
blob: a07e2170d98440c136df9b572eced3719a12423c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#ifndef __ARM_ARM32_PAGE_H__
#define __ARM_ARM32_PAGE_H__

#ifndef __ASSEMBLY__

/* Write a pagetable entry.
 *
 * If the table entry is changing a text mapping, it is responsibility
 * of the caller to issue an ISB after write_pte.
 */
static inline void write_pte(lpae_t *p, lpae_t pte)
{
    asm volatile (
        /* Ensure any writes have completed with the old mappings. */
        "dsb;"
        /* Safely write the entry (STRD is atomic on CPUs that support LPAE) */
        "strd %0, %H0, [%1];"
        "dsb;"
        : : "r" (pte.bits), "r" (p) : "memory");
}

/* Inline ASM to invalidate dcache on register R (may be an inline asm operand) */
#define __invalidate_dcache_one(R) STORE_CP32(R, DCIMVAC)

/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
#define __clean_dcache_one(R) STORE_CP32(R, DCCMVAC)

/* Inline ASM to clean and invalidate dcache on register R (may be an
 * inline asm operand) */
#define __clean_and_invalidate_dcache_one(R) STORE_CP32(R, DCCIMVAC)

/*
 * Flush all hypervisor mappings from the TLB and branch predictor of
 * the local processor.
 *
 * This is needed after changing Xen code mappings.
 *
 * The caller needs to issue the necessary DSB and D-cache flushes
 * before calling flush_xen_text_tlb.
 */
static inline void flush_xen_text_tlb_local(void)
{
    asm volatile (
        "isb;"                        /* Ensure synchronization with previous changes to text */
        CMD_CP32(TLBIALLH)            /* Flush hypervisor TLB */
        CMD_CP32(ICIALLU)             /* Flush I-cache */
        CMD_CP32(BPIALL)              /* Flush branch predictor */
        "dsb;"                        /* Ensure completion of TLB+BP flush */
        "isb;"
        : : : "memory");
}

/*
 * Flush all hypervisor mappings from the data TLB of the local
 * processor. This is not sufficient when changing code mappings or
 * for self modifying code.
 */
static inline void flush_xen_data_tlb_local(void)
{
    asm volatile("dsb;" /* Ensure preceding are visible */
                 CMD_CP32(TLBIALLH)
                 "dsb;" /* Ensure completion of the TLB flush */
                 "isb;"
                 : : : "memory");
}

/* Flush TLB of local processor for address va. */
static inline void __flush_xen_data_tlb_one_local(vaddr_t va)
{
    asm volatile(STORE_CP32(0, TLBIMVAH) : : "r" (va) : "memory");
}

/* Flush TLB of all processors in the inner-shareable domain for
 * address va. */
static inline void __flush_xen_data_tlb_one(vaddr_t va)
{
    asm volatile(STORE_CP32(0, TLBIMVAHIS) : : "r" (va) : "memory");
}

/* Ask the MMU to translate a VA for us */
static inline uint64_t __va_to_par(vaddr_t va)
{
    uint64_t par, tmp;
    tmp = READ_CP64(PAR);
    WRITE_CP32(va, ATS1HR);
    isb(); /* Ensure result is available. */
    par = READ_CP64(PAR);
    WRITE_CP64(tmp, PAR);
    return par;
}

/* Ask the MMU to translate a Guest VA for us */
static inline uint64_t gva_to_ma_par(vaddr_t va, unsigned int flags)
{
    uint64_t par, tmp;
    tmp = READ_CP64(PAR);
    if ( (flags & GV2M_WRITE) == GV2M_WRITE )
        WRITE_CP32(va, ATS12NSOPW);
    else
        WRITE_CP32(va, ATS12NSOPR);
    isb(); /* Ensure result is available. */
    par = READ_CP64(PAR);
    WRITE_CP64(tmp, PAR);
    return par;
}
static inline uint64_t gva_to_ipa_par(vaddr_t va)
{
    uint64_t par, tmp;
    tmp = READ_CP64(PAR);
    WRITE_CP32(va, ATS1CPR);
    isb(); /* Ensure result is available. */
    par = READ_CP64(PAR);
    WRITE_CP64(tmp, PAR);
    return par;
}

#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)

#endif /* __ASSEMBLY__ */

#endif /* __ARM_ARM32_PAGE_H__ */

/*
 * Local variables:
 * mode: C
 * c-file-style: "BSD"
 * c-basic-offset: 4
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 */