|
|
1.1 ! root 1: #ifndef LIBKIR_H ! 2: #define LIBKIR_H ! 3: ! 4: #include "realmode.h" ! 5: ! 6: #ifndef ASSEMBLY ! 7: ! 8: /* ! 9: * Full API documentation for these functions is in realmode.h. ! 10: * ! 11: */ ! 12: ! 13: /* Access to variables in .data16 and .text16 in a way compatible with librm */ ! 14: #define __data16( variable ) variable ! 15: #define __data16_array( variable, array ) variable array ! 16: #define __bss16( variable ) variable ! 17: #define __bss16_array( variable, array ) variable array ! 18: #define __text16( variable ) variable ! 19: #define __text16_array( variable,array ) variable array ! 20: #define __use_data16( variable ) variable ! 21: #define __use_text16( variable ) variable ! 22: #define __from_data16( pointer ) pointer ! 23: #define __from_text16( pointer ) pointer ! 24: ! 25: /* Real-mode data and code segments */ ! 26: static inline __attribute__ (( always_inline )) unsigned int _rm_cs ( void ) { ! 27: uint16_t cs; ! 28: __asm__ __volatile__ ( "movw %%cs, %w0" : "=r" ( cs ) ); ! 29: return cs; ! 30: } ! 31: ! 32: static inline __attribute__ (( always_inline )) unsigned int _rm_ds ( void ) { ! 33: uint16_t ds; ! 34: __asm__ __volatile__ ( "movw %%ds, %w0" : "=r" ( ds ) ); ! 35: return ds; ! 36: } ! 37: ! 38: #define rm_cs ( _rm_cs() ) ! 39: #define rm_ds ( _rm_ds() ) ! 40: ! 41: /* Copy to/from base memory */ ! 42: ! 43: static inline void copy_to_real_libkir ( unsigned int dest_seg, ! 44: unsigned int dest_off, ! 45: const void *src, size_t n ) { ! 46: unsigned int discard_D, discard_S, discard_c; ! 47: ! 48: __asm__ __volatile__ ( "pushw %%es\n\t" ! 49: "movw %3, %%es\n\t" ! 50: "rep movsb\n\t" ! 51: "popw %%es\n\t" ! 52: : "=D" ( discard_D ), "=S" ( discard_S ), ! 53: "=c" ( discard_c ) ! 54: : "r" ( dest_seg ), "D" ( dest_off ), ! 55: "S" ( src ), ! 56: "c" ( n ) ! 57: : "memory" ); ! 58: } ! 59: ! 60: static inline void copy_from_real_libkir ( void *dest, ! 61: unsigned int src_seg, ! 62: unsigned int src_off, ! 63: size_t n ) { ! 64: unsigned int discard_D, discard_S, discard_c; ! 65: ! 66: __asm__ __volatile__ ( "pushw %%ds\n\t" ! 67: "movw %4, %%ds\n\t" ! 68: "rep movsb\n\t" ! 69: "popw %%ds\n\t" ! 70: : "=D" ( discard_D ), "=S" ( discard_S ), ! 71: "=c" ( discard_c ) ! 72: : "D" ( dest ), ! 73: "r" ( src_seg ), "S" ( src_off ), ! 74: "c" ( n ) ! 75: : "memory" ); ! 76: } ! 77: ! 78: #define copy_to_real copy_to_real_libkir ! 79: #define copy_from_real copy_from_real_libkir ! 80: ! 81: /* ! 82: * Transfer individual values to/from base memory. There may well be ! 83: * a neater way to do this. We have two versions: one for constant ! 84: * offsets (where the mov instruction must be of the form "mov ! 85: * %es:123, %xx") and one for non-constant offsets (where the mov ! 86: * instruction must be of the form "mov %es:(%xx), %yx". If it's ! 87: * possible to incorporate both forms into one __asm__ instruction, I ! 88: * don't know how to do it. ! 89: * ! 90: * Ideally, the mov instruction should be "mov%z0"; the "%z0" is meant ! 91: * to expand to either "b", "w" or "l" depending on the size of ! 92: * operand 0. This would remove the (minor) ambiguity in the mov ! 93: * instruction. However, gcc on at least my system barfs with an ! 94: * "internal compiler error" when confronted with %z0. ! 95: * ! 96: */ ! 97: ! 98: #define put_real_kir_const_off( var, seg, off ) \ ! 99: __asm__ ( "movw %w1, %%es\n\t" \ ! 100: "mov %0, %%es:%c2\n\t" \ ! 101: "pushw %%ds\n\t" /* restore %es */ \ ! 102: "popw %%es\n\t" \ ! 103: : \ ! 104: : "r,r" ( var ), "rm,rm" ( seg ), "i,!r" ( off ) \ ! 105: ) ! 106: ! 107: #define put_real_kir_nonconst_off( var, seg, off ) \ ! 108: __asm__ ( "movw %w1, %%es\n\t" \ ! 109: "mov %0, %%es:(%2)\n\t" \ ! 110: "pushw %%ds\n\t" /* restore %es */ \ ! 111: "popw %%es\n\t" \ ! 112: : \ ! 113: : "r" ( var ), "rm" ( seg ), "r" ( off ) \ ! 114: ) ! 115: ! 116: #define put_real_kir( var, seg, off ) \ ! 117: do { \ ! 118: if ( __builtin_constant_p ( off ) ) \ ! 119: put_real_kir_const_off ( var, seg, off ); \ ! 120: else \ ! 121: put_real_kir_nonconst_off ( var, seg, off ); \ ! 122: } while ( 0 ) ! 123: ! 124: #define get_real_kir_const_off( var, seg, off ) \ ! 125: __asm__ ( "movw %w1, %%es\n\t" \ ! 126: "mov %%es:%c2, %0\n\t" \ ! 127: "pushw %%ds\n\t" /* restore %es */ \ ! 128: "popw %%es\n\t" \ ! 129: : "=r,r" ( var ) \ ! 130: : "rm,rm" ( seg ), "i,!r" ( off ) \ ! 131: ) ! 132: ! 133: #define get_real_kir_nonconst_off( var, seg, off ) \ ! 134: __asm__ ( "movw %w1, %%es\n\t" \ ! 135: "mov %%es:(%2), %0\n\t" \ ! 136: "pushw %%ds\n\t" /* restore %es */ \ ! 137: "popw %%es\n\t" \ ! 138: : "=r" ( var ) \ ! 139: : "rm" ( seg ), "r" ( off ) \ ! 140: ) ! 141: ! 142: #define get_real_kir( var, seg, off ) \ ! 143: do { \ ! 144: if ( __builtin_constant_p ( off ) ) \ ! 145: get_real_kir_const_off ( var, seg, off ); \ ! 146: else \ ! 147: get_real_kir_nonconst_off ( var, seg, off ); \ ! 148: } while ( 0 ) ! 149: ! 150: #define put_real put_real_kir ! 151: #define get_real get_real_kir ! 152: ! 153: /** ! 154: * A pointer to a user buffer ! 155: * ! 156: * This is actually a struct segoff, but encoded as a uint32_t to ! 157: * ensure that gcc passes it around efficiently. ! 158: */ ! 159: typedef uint32_t userptr_t; ! 160: ! 161: /** ! 162: * Copy data to user buffer ! 163: * ! 164: * @v buffer User buffer ! 165: * @v offset Offset within user buffer ! 166: * @v src Source ! 167: * @v len Length ! 168: */ ! 169: static inline __attribute__ (( always_inline )) void ! 170: copy_to_user ( userptr_t buffer, off_t offset, const void *src, size_t len ) { ! 171: copy_to_real ( ( buffer >> 16 ), ( ( buffer & 0xffff ) + offset ), ! 172: src, len ); ! 173: } ! 174: ! 175: /** ! 176: * Copy data from user buffer ! 177: * ! 178: * @v dest Destination ! 179: * @v buffer User buffer ! 180: * @v offset Offset within user buffer ! 181: * @v len Length ! 182: */ ! 183: static inline __attribute__ (( always_inline )) void ! 184: copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) { ! 185: copy_from_real ( dest, ( buffer >> 16 ), ! 186: ( ( buffer & 0xffff ) + offset ), len ); ! 187: } ! 188: ! 189: /** ! 190: * Convert segment:offset address to user buffer ! 191: * ! 192: * @v segment Real-mode segment ! 193: * @v offset Real-mode offset ! 194: * @ret buffer User buffer ! 195: */ ! 196: static inline __attribute__ (( always_inline )) userptr_t ! 197: real_to_user ( unsigned int segment, unsigned int offset ) { ! 198: return ( ( segment << 16 ) | offset ); ! 199: } ! 200: ! 201: /** ! 202: * Convert virtual address to user buffer ! 203: * ! 204: * @v virtual Virtual address ! 205: * @ret buffer User buffer ! 206: * ! 207: * This constructs a user buffer from an ordinary pointer. Use it ! 208: * when you need to pass a pointer to an internal buffer to a function ! 209: * that expects a @c userptr_t. ! 210: */ ! 211: static inline __attribute__ (( always_inline )) userptr_t ! 212: virt_to_user ( void * virtual ) { ! 213: return real_to_user ( rm_ds, ( intptr_t ) virtual ); ! 214: } ! 215: ! 216: /* TEXT16_CODE: declare a fragment of code that resides in .text16 */ ! 217: #define TEXT16_CODE( asm_code_str ) \ ! 218: ".section \".text16\", \"ax\", @progbits\n\t" \ ! 219: ".code16\n\t" \ ! 220: ".arch i386\n\t" \ ! 221: asm_code_str "\n\t" \ ! 222: ".code16gcc\n\t" \ ! 223: ".previous\n\t" ! 224: ! 225: /* REAL_CODE: declare a fragment of code that executes in real mode */ ! 226: #define REAL_CODE( asm_code_str ) \ ! 227: ".code16\n\t" \ ! 228: asm_code_str "\n\t" \ ! 229: ".code16gcc\n\t" ! 230: ! 231: #endif /* ASSEMBLY */ ! 232: ! 233: #endif /* LIBKIR_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.