Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / include / arch-x86_64 / pda.h
1 #ifndef _X86_64_PDA_H
2 #define _X86_64_PDA_H
3
4 #ifndef __ASSEMBLY__
5 #include <lwk/stddef.h>
6 #include <lwk/types.h>
7 #include <lwk/cache.h>
8 #include <arch/page.h>
9
10 /* Per processor datastructure. %gs points to it while the kernel runs */ 
11 struct x8664_pda {
12         struct task_struct *pcurrent;   /* Current process */
13         unsigned long data_offset;      /* Per cpu data offset from linker address */
14         unsigned long kernelstack;  /* top of kernel stack for current */ 
15         unsigned long oldrsp;       /* user rsp for system call */
16 #if DEBUG_STKSZ > EXCEPTION_STKSZ
17         unsigned long debugstack;   /* #DB/#BP stack. */
18 #endif
19         int irqcount;               /* Irq nesting counter. Starts with -1 */   
20         int cpunumber;              /* Logical CPU number */
21         char *irqstackptr;      /* top of irqstack */
22         int nodenumber;             /* number of current node */
23         unsigned int __softirq_pending;
24         unsigned int __nmi_count;       /* number of NMI on this CPUs */
25         int mmu_state;     
26         struct aspace *active_aspace;
27         unsigned apic_timer_irqs;
28 } ____cacheline_aligned_in_smp;
29
30 extern struct x8664_pda *_cpu_pda[];
31 extern struct x8664_pda boot_cpu_pda[];
32
33 void pda_init(unsigned int cpu, struct task_struct *task);
34
35 #define cpu_pda(i) (_cpu_pda[i])
36
37 /* 
38  * There is no fast way to get the base address of the PDA, all the accesses
39  * have to mention %fs/%gs.  So it needs to be done this Torvaldian way.
40  */ 
41 #define sizeof_field(type,field)  (sizeof(((type *)0)->field))
42 #define typeof_field(type,field)  typeof(((type *)0)->field)
43
44 extern void __bad_pda_field(void);
45
46 #define pda_offset(field) offsetof(struct x8664_pda, field)
47
48 #define pda_to_op(op,field,val) do { \
49         typedef typeof_field(struct x8664_pda, field) T__; \
50        switch (sizeof_field(struct x8664_pda, field)) {                 \
51 case 2: \
52 asm volatile(op "w %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
53 case 4: \
54 asm volatile(op "l %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
55 case 8: \
56 asm volatile(op "q %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
57        default: __bad_pda_field();                                      \
58        } \
59        } while (0)
60
61 /* 
62  * AK: PDA read accesses should be neither volatile nor have an memory clobber.
63  * Unfortunately removing them causes all hell to break lose currently.
64  */
65 #define pda_from_op(op,field) ({ \
66        typeof_field(struct x8664_pda, field) ret__; \
67        switch (sizeof_field(struct x8664_pda, field)) {                 \
68 case 2: \
69 asm volatile(op "w %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
70 case 4: \
71 asm volatile(op "l %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
72 case 8: \
73 asm volatile(op "q %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
74        default: __bad_pda_field();                                      \
75        } \
76        ret__; })
77
78
79 #define read_pda(field) pda_from_op("mov",field)
80 #define write_pda(field,val) pda_to_op("mov",field,val)
81 #define add_pda(field,val) pda_to_op("add",field,val)
82 #define sub_pda(field,val) pda_to_op("sub",field,val)
83 #define or_pda(field,val) pda_to_op("or",field,val)
84
85 #endif
86
87 #define PDA_STACKOFFSET (5*8)
88
89 #endif