1 // Special assembly routines to access x86-specific 2 // hardware instructions. 3 4 static __inline uchar 5 inb(int port) 6 { 7 uchar data; 8 __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port)); 9 return data; 10 } 11 12 static __inline void 13 insl(int port, void *addr, int cnt) 14 { 15 __asm __volatile("cld\n\trepne\n\tinsl" : 16 "=D" (addr), "=c" (cnt) : 17 "d" (port), "0" (addr), "1" (cnt) : 18 "memory", "cc"); 19 } 20 21 static __inline void 22 outb(int port, uchar data) 23 { 24 __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port)); 25 } 26 27 static __inline void 28 outw(int port, ushort data) 29 { 30 __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port)); 31 } 32 33 static __inline void 34 outsl(int port, const void *addr, int cnt) 35 { 36 __asm __volatile("cld\n\trepne\n\toutsl" : 37 "=S" (addr), "=c" (cnt) : 38 "d" (port), "0" (addr), "1" (cnt) : 39 "cc"); 40 } 41 42 struct segdesc; 43 44 static __inline void 45 lgdt(struct segdesc *p, int size) 46 { 47 volatile ushort pd[3]; 48 49 pd[0] = size-1; 50 pd[1] = (uint)p; 51 pd[2] = (uint)p >> 16; 52 53 asm volatile("lgdt (%0)" : : "g" (pd)); 54 } 55 56 struct gatedesc; 57 58 static __inline void 59 lidt(struct gatedesc *p, int size) 60 { 61 volatile ushort pd[3]; 62 63 pd[0] = size-1; 64 pd[1] = (uint)p; 65 pd[2] = (uint)p >> 16; 66 67 asm volatile("lidt (%0)" : : "g" (pd)); 68 } 69 70 static __inline void 71 ltr(ushort sel) 72 { 73 __asm __volatile("ltr %0" : : "r" (sel)); 74 } 75 76 static __inline uint 77 read_eflags(void) 78 { 79 uint eflags; 80 __asm __volatile("pushfl; popl %0" : "=r" (eflags)); 81 return eflags; 82 } 83 84 static __inline void 85 write_eflags(uint eflags) 86 { 87 __asm __volatile("pushl %0; popfl" : : "r" (eflags)); 88 } 89 90 static __inline void 91 cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp) 92 { 93 uint eax, ebx, ecx, edx; 94 asm volatile("cpuid" : 95 "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : 96 "a" (info)); 97 if(eaxp) 98 *eaxp = eax; 99 if(ebxp) 100 *ebxp = ebx; 101 if(ecxp) 102 *ecxp = ecx; 103 if(edxp) 104 *edxp = edx; 105 } 106 107 static __inline uint 108 cmpxchg(uint oldval, uint newval, volatile uint* lock_addr) 109 { 110 uint result; 111 __asm__ __volatile__("lock; cmpxchgl %2, %0" : 112 "+m" (*lock_addr), "=a" (result) : 113 "r"(newval), "1"(oldval) : 114 "cc"); 115 return result; 116 } 117 118 static __inline void 119 cli(void) 120 { 121 __asm__ volatile("cli"); 122 } 123 124 static __inline void 125 sti(void) 126 { 127 __asm__ volatile("sti"); 128 } 129 130 // Layout of the trap frame on the stack upon entry to trap. 131 struct trapframe { 132 // registers as pushed by pusha 133 uint edi; 134 uint esi; 135 uint ebp; 136 uint oesp; // useless & ignored 137 uint ebx; 138 uint edx; 139 uint ecx; 140 uint eax; 141 142 // rest of trap frame 143 ushort es; 144 ushort padding1; 145 ushort ds; 146 ushort padding2; 147 uint trapno; 148 149 // below here defined by x86 hardware 150 uint err; 151 uint eip; 152 ushort cs; 153 ushort padding3; 154 uint eflags; 155 156 // below here only when crossing rings, such as from user to kernel 157 uint esp; 158 ushort ss; 159 ushort padding4; 160 }; 161