89#define _ASM_MAYBE_XEN_FEP _ASM_XEN_FEP
91#define _ASM_MAYBE_XEN_FEP
102 xtf_failure(
" Fail: Unexpected fault %#x, %pe\n", info,
_p(info));
104 regs->ip = ex->
fixup;
116 asm volatile (
"mov %[zero], 0x1000;\n\t"
117 "mov %[zero], 0x2000;\n\t"
118 "andb $~%c[ad], %[pte1];\n\t"
119 "andb $~%c[ad], %[pte2];\n\t"
121 "1: invlpg 0x1000; 2:\n\t"
123 "mov %[zero], 0x1000;\n\t"
124 "mov %[zero], 0x2000;\n\t"
128 [pte1]
"m" (pae_l1_identmap[1]),
129 [pte2]
"m" (pae_l1_identmap[2]),
133 return ((
test_ad(pae_l1_identmap[1]) << 0) |
134 (
test_ad(pae_l1_identmap[2]) << 1));
139 asm volatile (
"mov %[zero], 0x1000;\n\t"
140 "mov %[zero], 0x2000;\n\t"
141 "andb $~%c[ad], %[pte1];\n\t"
142 "andb $~%c[ad], %[pte2];\n\t"
144 "1: invlpg %%fs:0x1000; 2:\n\t"
146 "mov %[zero], 0x1000;\n\t"
147 "mov %[zero], 0x2000;\n\t"
151 [pte1]
"m" (pae_l1_identmap[1]),
152 [pte2]
"m" (pae_l1_identmap[2]),
156 return ((
test_ad(pae_l1_identmap[1]) << 0) |
157 (
test_ad(pae_l1_identmap[2]) << 1));
162 unsigned int ret, tries = 20;
173 }
while ( ret == 3 && --tries );
178 return xtf_failure(
" Fail: No TLB refill at all\n");
182 printk(
" TLB refill of %#x\n", ret * 0x1000);
185 xtf_failure(
" Fail: Expected mapping %#x to have been refilled\n",
190 printk(
" TLB refill of both 0x1000 and 0x2000\n");
194 return xtf_failure(
" Fail: Unexpected return value %u\n", ret);
207 INIT_GDTE_SYM(0, 0xfffff, P, S, G, A, DATA, DPL0, B, W),
210 {
"(base 0x0, limit 0x1)", 1,
214 {
"(base 0x1000)", 2,
215 INIT_GDTE_SYM(0x1000, 0xfffff, P, S, G, A, DATA, DPL0, B, W),
218 {
"(base 0x1000, limit 0x1001)", 2,
227 printk(
"Testing 'invlpg 0x1000' with segment bases\n");
229 printk(
" Test: No segment\n");
248 ::
"r" (linear), [hnd]
"p" (
ex_fail));
254 "1: invlpg %%fs:(%0); 2:"
256 ::
"r" (linear), [hnd]
"p" (
ex_fail));
261 printk(
"Testing 'invlpg' in normally-faulting conditions\n");
263 printk(
" Test: Mapped address\n");
266 printk(
" Test: Unmapped address\n");
269 printk(
" Test: NULL segment override\n");
273 printk(
" Test: Past segment limit\n");
278 printk(
" Test: Before expand-down segment limit\n");
283#if CONFIG_PAGING_LEVELS >= 4
284 printk(
" Test: Noncanonical address\n");
287 printk(
" Test: Noncanonical including segment base\n");
296 if ( CONFIG_PAGING_LEVELS > 0 )
static void write_fs(unsigned int fs)
static void update_desc(user_desc *ptr, const user_desc new)
Helper to update a live LDT/GDT entry.
void printk(const char *fmt,...)
void test_main(void)
To be implemented by each test, as its entry point.
const char test_title[]
The title of the test.
user_desc gdt[NR_GDT_ENTRIES]
unsigned int exinfo_t
Packed exception and error code information.
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
static void run_tlb_refill_test(unsigned int(*fn)(void), unsigned int expect)
static bool ex_fail(struct cpu_regs *regs, const struct extable_entry *ex)
Custom extable handler, linked to all invlpg instruction which are expected not to fault.
static bool test_ad(uint64_t pte)
Are both the Accessed and Dirty bits are set in a pagetable entry?
#define _ASM_MAYBE_XEN_FEP
static unsigned int invlpg_refill(void)
static void test_no_fault(void)
static const struct tlb_refill_fs_test tlb_refill_fs_tests[]
static void invlpg_checked(unsigned long linear)
static void test_tlb_refill(void)
static unsigned int invlpg_fs_refill(void)
static void invlpg_fs_checked(unsigned long linear)
static void wrmsr(uint32_t idx, uint64_t val)
Thin wrapper around an wrmsr instruction.
#define _p(v)
Express an abitrary integer v as void *.
#define _u(v)
Express an arbitrary value v as unsigned long.
void xtf_failure(const char *fmt,...)
Report a test failure.
void xtf_success(const char *fmt,...)
Report test success.
unsigned long fixup
Fixup address.
#define GDTE_SYM(base, limit,...)
As INIT_GDTE_SYM(), but creates a user_desc object.
#define INIT_GDTE_SYM(base, limit,...)
Initialiser for an LDT/GDT entry using SEG_ATTR_ mnemonics.