aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/asm-x86/processor.h
blob: f6951c0bc10682ac9ddecb4157d9826c5b55f112 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
/*
 * include/asm-x86/processor.h
 *
 * Copyright (C) 1994 Linus Torvalds
 */

#ifndef __ASM_X86_PROCESSOR_H
#define __ASM_X86_PROCESSOR_H

#include <asm/page.h>
#include <asm/types.h>
#include <asm/cpufeature.h>
#include <asm/desc.h>
#include <asm/flushtlb.h>
#include <asm/pdb.h>
#include <xen/config.h>
#include <xen/spinlock.h>
#include <hypervisor-ifs/hypervisor-if.h>

struct domain;

/*
 * Default implementation of macro that returns current
 * instruction pointer ("program counter").
 */
#ifdef __x86_64__
#define current_text_addr() ({ void *pc; asm volatile("leaq 1f(%%rip),%0\n1:":"=r"(pc)); pc; })
#else
#define current_text_addr() \
  ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
#endif

/*
 *  CPU type and hardware bug flags. Kept separately for each CPU.
 *  Members of this structure are referenced in head.S, so think twice
 *  before touching them. [mj]
 */

struct cpuinfo_x86 {
    __u8    x86;            /* CPU family */
    __u8    x86_vendor;     /* CPU vendor */
    __u8    x86_model;
    __u8    x86_mask;
    int     cpuid_level;    /* Maximum supported CPUID level, -1=no CPUID */
    __u32   x86_capability[NCAPINTS];
    char    x86_vendor_id[16];
    int     x86_cache_size;  /* in KB - for CPUS that support this call  */
    int	    x86_clflush_size;
    int	    x86_tlbsize;     /* number of 4K pages in DTLB/ITLB combined */
} __attribute__((__aligned__(SMP_CACHE_BYTES)));

#define X86_VENDOR_INTEL 0
#define X86_VENDOR_CYRIX 1
#define X86_VENDOR_AMD 2
#define X86_VENDOR_UMC 3
#define X86_VENDOR_NEXGEN 4
#define X86_VENDOR_CENTAUR 5
#define X86_VENDOR_RISE 6
#define X86_VENDOR_TRANSMETA 7
#define X86_VENDOR_NSC 8
#define X86_VENDOR_SIS 9
#define X86_VENDOR_UNKNOWN 0xff

/*
 * capabilities of CPUs
 */

extern struct cpuinfo_x86 boot_cpu_data;
extern struct tss_struct init_tss[NR_CPUS];

#ifdef CONFIG_SMP
extern struct cpuinfo_x86 cpu_data[];
#define current_cpu_data cpu_data[smp_processor_id()]
#else
#define cpu_data (&boot_cpu_data)
#define current_cpu_data boot_cpu_data
#endif

extern char ignore_irq13;

extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern void dodgy_tsc(void);

/*
 * EFLAGS bits
 */
#define X86_EFLAGS_CF	0x00000001 /* Carry Flag */
#define X86_EFLAGS_PF	0x00000004 /* Parity Flag */
#define X86_EFLAGS_AF	0x00000010 /* Auxillary carry Flag */
#define X86_EFLAGS_ZF	0x00000040 /* Zero Flag */
#define X86_EFLAGS_SF	0x00000080 /* Sign Flag */
#define X86_EFLAGS_TF	0x00000100 /* Trap Flag */
#define X86_EFLAGS_IF	0x00000200 /* Interrupt Flag */
#define X86_EFLAGS_DF	0x00000400 /* Direction Flag */
#define X86_EFLAGS_OF	0x00000800 /* Overflow Flag */
#define X86_EFLAGS_IOPL	0x00003000 /* IOPL mask */
#define X86_EFLAGS_NT	0x00004000 /* Nested Task */
#define X86_EFLAGS_RF	0x00010000 /* Resume Flag */
#define X86_EFLAGS_VM	0x00020000 /* Virtual Mode */
#define X86_EFLAGS_AC	0x00040000 /* Alignment Check */
#define X86_EFLAGS_VIF	0x00080000 /* Virtual Interrupt Flag */
#define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
#define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */

/*
 * Generic CPUID function
 */
static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
{
    __asm__("cpuid"
            : "=a" (*eax),
            "=b" (*ebx),
            "=c" (*ecx),
            "=d" (*edx)
            : "0" (op));
}

/*
 * CPUID functions returning a single datum
 */
static inline unsigned int cpuid_eax(unsigned int op)
{
    unsigned int eax;

    __asm__("cpuid"
            : "=a" (eax)
            : "0" (op)
            : "bx", "cx", "dx");
    return eax;
}
static inline unsigned int cpuid_ebx(unsigned int op)
{
    unsigned int eax, ebx;

    __asm__("cpuid"
            : "=a" (eax), "=b" (ebx)
            : "0" (op)
            : "cx", "dx" );
    return ebx;
}
static inline unsigned int cpuid_ecx(unsigned int op)
{
    unsigned int eax, ecx;

    __asm__("cpuid"
            : "=a" (eax), "=c" (ecx)
            : "0" (op)
            : "bx", "dx" );
    return ecx;
}
static inline unsigned int cpuid_edx(unsigned int op)
{
    unsigned int eax, edx;

    __asm__("cpuid"
            : "=a" (eax), "=d" (edx)
            : "0" (op)
            : "bx", "cx");
    return edx;
}


/*
 * Intel CPU flags in CR0
 */
#define X86_CR0_PE              0x00000001 /* Enable Protected Mode    (RW) */
#define X86_CR0_MP              0x00000002 /* Monitor Coprocessor      (RW) */
#define X86_CR0_EM              0x00000004 /* Require FPU Emulation    (RO) */
#define X86_CR0_TS              0x00000008 /* Task Switched            (RW) */
#define X86_CR0_NE              0x00000020 /* Numeric Error Reporting  (RW) */
#define X86_CR0_WP              0x00010000 /* Supervisor Write Protect (RW) */
#define X86_CR0_AM              0x00040000 /* Alignment Checking       (RW) */
#define X86_CR0_NW              0x20000000 /* Not Write-Through        (RW) */
#define X86_CR0_CD              0x40000000 /* Cache Disable            (RW) */
#define X86_CR0_PG              0x80000000 /* Paging                   (RW) */

#define read_cr0() ({ \
	unsigned long __dummy; \
	__asm__( \
		"mov"__OS" %%cr0,%0\n\t" \
		:"=r" (__dummy)); \
	__dummy; \
})

#define write_cr0(x) \
	__asm__("mov"__OS" %0,%%cr0": :"r" (x));


/*
 * Intel CPU features in CR4
 */
#define X86_CR4_VME		0x0001	/* enable vm86 extensions */
#define X86_CR4_PVI		0x0002	/* virtual interrupts flag enable */
#define X86_CR4_TSD		0x0004	/* disable time stamp at ipl 3 */
#define X86_CR4_DE		0x0008	/* enable debugging extensions */
#define X86_CR4_PSE		0x0010	/* enable page size extensions */
#define X86_CR4_PAE		0x0020	/* enable physical address extensions */
#define X86_CR4_MCE		0x0040	/* Machine check enable */
#define X86_CR4_PGE		0x0080	/* enable global pages */
#define X86_CR4_PCE		0x0100	/* enable performance counters at ipl 3 */
#define X86_CR4_OSFXSR		0x0200	/* enable fast FPU save and restore */
#define X86_CR4_OSXMMEXCPT	0x0400	/* enable unmasked SSE exceptions */

/*
 * Save the cr4 feature set we're using (ie
 * Pentium 4MB enable and PPro Global page
 * enable), so that any CPU's that boot up
 * after us can get the correct flags.
 */
extern unsigned long mmu_cr4_features;

static inline void set_in_cr4 (unsigned long mask)
{
    mmu_cr4_features |= mask;
    __asm__("mov"__OS" %%cr4,%%"__OP"ax\n\t"
            "or"__OS" %0,%%"__OP"ax\n\t"
            "mov"__OS" %%"__OP"ax,%%cr4\n"
            : : "irg" (mask)
            :"ax");
}

static inline void clear_in_cr4 (unsigned long mask)
{
    mmu_cr4_features &= ~mask;
    __asm__("mov"__OS" %%cr4,%%"__OP"ax\n\t"
            "and"__OS" %0,%%"__OP"ax\n\t"
            "movl"__OS" %%"__OP"ax,%%cr4\n"
            : : "irg" (~mask)
            :"ax");
}

/*
 * Size of io_bitmap in longwords:
 * For Xen we support the full 8kbyte IO bitmap but use the io_bitmap_sel field
 * to avoid a full 8kbyte copy when switching to domains with bits cleared.
 */
#define IO_BITMAP_SIZE	2048
#define IO_BITMAP_BYTES (IO_BITMAP_SIZE * 4)
#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
#define INVALID_IO_BITMAP_OFFSET 0x8000

struct i387_state {
    u8 state[512]; /* big enough for FXSAVE */
} __attribute__ ((aligned (16)));

struct tss_struct {
    unsigned short	back_link,__blh;
#ifdef __x86_64__
    u64 rsp0;
    u64 rsp1;
    u64 rsp2;
    u64 reserved1;
    u64 ist[7];
    u64 reserved2;
    u16 reserved3;
#else
    u32 esp0;
    u16 ss0,__ss0h;
    u32 esp1;
    u16 ss1,__ss1h;
    u32 esp2;
    u16 ss2,__ss2h;
    u32 __cr3;
    u32 eip;
    u32 eflags;
    u32 eax,ecx,edx,ebx;
    u32 esp;
    u32 ebp;
    u32 esi;
    u32 edi;
    u16 es, __esh;
    u16 cs, __csh;
    u16 ss, __ssh;
    u16 ds, __dsh;
    u16 fs, __fsh;
    u16 gs, __gsh;
    u16 ldt, __ldth;
    u16 trace;
#endif
    u16 bitmap;
    u32 io_bitmap[IO_BITMAP_SIZE+1];
    /* Pads the TSS to be cacheline-aligned (total size is 0x2080). */
    u32 __cacheline_filler[5];
};

struct thread_struct {
    unsigned long      guestos_sp;
    unsigned long      guestos_ss;
/* Hardware debugging registers */
    unsigned long      debugreg[8];  /* %%db0-7 debug registers */
/* floating point info */
    struct i387_state  i387;
/* general user-visible register state */
    execution_context_t user_ctxt;
/* Trap info. */
#ifdef __i386__
    int                fast_trap_idx;
    struct desc_struct fast_trap_desc;
#endif
    trap_info_t        traps[256];
};

#define IDT_ENTRIES 256
extern struct desc_struct idt_table[];
extern struct desc_struct *idt_tables[];

#if defined(__i386__)

#define SET_DEFAULT_FAST_TRAP(_p) \
    (_p)->fast_trap_idx = 0x20;   \
    (_p)->fast_trap_desc.a = 0;   \
    (_p)->fast_trap_desc.b = 0;

#define CLEAR_FAST_TRAP(_p) \
    (memset(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \
     0, 8))

#ifdef XEN_DEBUGGER
#define SET_FAST_TRAP(_p)   \
    (pdb_initialized ? (void *) 0 : \
       (memcpy(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \
               &((_p)->fast_trap_desc), 8)))
#else
#define SET_FAST_TRAP(_p)   \
    (memcpy(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \
            &((_p)->fast_trap_desc), 8))
#endif

long set_fast_trap(struct domain *p, int idx);

#define INIT_THREAD  {						\
	0, 0,		      		       			\
	{ [0 ... 7] = 0 },	/* debugging registers */	\
	{ { 0, }, },		/* 387 state */			\
	{ 0 },							\
	0x20, { 0, 0 },		/* DEFAULT_FAST_TRAP */		\
	{ {0} }			/* io permissions */		\
}

#elif defined(__x86_64__)

#define INIT_THREAD { 0 }

#endif /* __x86_64__ */

#define GTBF_TRAP        1
#define GTBF_TRAP_NOCODE 2
#define GTBF_TRAP_CR2    4
struct guest_trap_bounce {
    unsigned long  error_code;        /*   0 */
    unsigned long  cr2;               /*   4 */
    unsigned short flags;             /*   8 */
    unsigned short cs;                /*  10 */
    unsigned long  eip;               /*  12 */
};
extern struct guest_trap_bounce guest_trap_bounce[];

extern int gpf_emulate_4gb(struct pt_regs *regs);

struct mm_struct {
    /*
     * Every domain has a L1 pagetable of its own. Per-domain mappings
     * are put in this table (eg. the current GDT is mapped here).
     */
    l1_pgentry_t *perdomain_pt;
    pagetable_t  pagetable;

    /* shadow mode status and controls */
    unsigned int shadow_mode;  /* flags to control shadow table operation */
    pagetable_t  shadow_table;
    spinlock_t   shadow_lock;
    unsigned int shadow_max_page_count; // currently unused

    /* shadow hashtable */
    struct shadow_status *shadow_ht;
    struct shadow_status *shadow_ht_free;
    struct shadow_status *shadow_ht_extras; /* extra allocation units */
    unsigned int shadow_extras_count;

    /* shadow dirty bitmap */
    unsigned long *shadow_dirty_bitmap;
    unsigned int shadow_dirty_bitmap_size;  /* in pages, bit per page */

    /* shadow mode stats */
    unsigned int shadow_page_count;     
    unsigned int shadow_fault_count;     
    unsigned int shadow_dirty_count;     
    unsigned int shadow_dirty_net_count;     
    unsigned int shadow_dirty_block_count;     

    /* Current LDT details. */
    unsigned long ldt_base, ldt_ents, shadow_ldt_mapcnt;
    /* Next entry is passed to LGDT on domain switch. */
    char gdt[10]; /* NB. 10 bytes needed for x86_64. Use 6 bytes for x86_32. */
};

static inline void write_ptbase(struct mm_struct *mm)
{
    unsigned long pa;

    if ( unlikely(mm->shadow_mode) )
        pa = pagetable_val(mm->shadow_table);
    else
        pa = pagetable_val(mm->pagetable);

    write_cr3(pa);
}

#define IDLE0_MM                                                    \
{                                                                   \
    perdomain_pt: 0,                                                \
    pagetable:   mk_pagetable(__pa(idle_pg_table))                  \
}

/* Convenient accessor for mm.gdt. */
#define SET_GDT_ENTRIES(_p, _e) ((*(u16 *)((_p)->mm.gdt + 0)) = (((_e)<<3)-1))
#define SET_GDT_ADDRESS(_p, _a) ((*(unsigned long *)((_p)->mm.gdt + 2)) = (_a))
#define GET_GDT_ENTRIES(_p)     (((*(u16 *)((_p)->mm.gdt + 0))+1)>>3)
#define GET_GDT_ADDRESS(_p)     (*(unsigned long *)((_p)->mm.gdt + 2))

void destroy_gdt(struct domain *d);
long set_gdt(struct domain *d, 
             unsigned long *frames, 
             unsigned int entries);

long set_debugreg(struct domain *p, int reg, unsigned long value);

struct microcode {
    unsigned int hdrver;
    unsigned int rev;
    unsigned int date;
    unsigned int sig;
    unsigned int cksum;
    unsigned int ldrver;
    unsigned int pf;
    unsigned int reserved[5];
    unsigned int bits[500];
};

/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
#define MICROCODE_IOCFREE	_IO('6',0)

/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
static inline void rep_nop(void)
{
    __asm__ __volatile__("rep;nop");
}

#define cpu_relax()	rep_nop()

/* Prefetch instructions for Pentium III and AMD Athlon */
#ifdef 	CONFIG_MPENTIUMIII

#define ARCH_HAS_PREFETCH
extern inline void prefetch(const void *x)
{
    __asm__ __volatile__ ("prefetchnta (%0)" : : "r"(x));
}

#elif CONFIG_X86_USE_3DNOW

#define ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCHW
#define ARCH_HAS_SPINLOCK_PREFETCH

extern inline void prefetch(const void *x)
{
    __asm__ __volatile__ ("prefetch (%0)" : : "r"(x));
}

extern inline void prefetchw(const void *x)
{
    __asm__ __volatile__ ("prefetchw (%0)" : : "r"(x));
}
#define spin_lock_prefetch(x)	prefetchw(x)

#endif

#endif /* __ASM_X86_PROCESSOR_H */