Browse Source

Removed REAL_FRAGMENT and REAL_CALL, and left just REAL_EXEC (which is

the only one we actually use).  This allows REAL_EXEC fragments to
contain proper references to constraints (e.g. "%w0"), rather than having
to force the use of specific registers.

Note that the "num_constraints" parameter is now completely obsolete, and
that we can probably reduce the syntax to something like
  __asm__ __volatile__ ( REAL_CODE ( "asm statements" )
                         : output constraints
                         : input constraints
                         : clobber );
which would look much more natural, and avoid the need to always specify
a clobber list.


Add userptr_t to libkir.h, to allow it to at least compile.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
3b525385af
2 changed files with 94 additions and 100 deletions
  1. 84
    65
      src/arch/i386/include/libkir.h
  2. 10
    35
      src/arch/i386/include/librm.h

+ 84
- 65
src/arch/i386/include/libkir.h View File

20
 #define __from_data16( variable ) variable
20
 #define __from_data16( variable ) variable
21
 #define __from_text16( variable ) variable
21
 #define __from_text16( variable ) variable
22
 
22
 
23
+/* Real-mode data and code segments */
24
+static inline __attribute__ (( always_inline )) unsigned int _rm_cs ( void ) {
25
+	uint16_t cs;
26
+	__asm__ __volatile__ ( "movw %%cs, %w0" : "=r" ( cs ) );
27
+	return cs;
28
+}
29
+
30
+static inline __attribute__ (( always_inline )) unsigned int _rm_ds ( void ) {
31
+	uint16_t ds;
32
+	__asm__ __volatile__ ( "movw %%ds, %w0" : "=r" ( ds ) );
33
+	return ds;
34
+}
35
+
36
+#define rm_cs ( _rm_cs() )
37
+#define rm_ds ( _rm_ds() )
38
+
23
 /* Copy to/from base memory */
39
 /* Copy to/from base memory */
24
 
40
 
25
 static inline void copy_to_real_libkir ( uint16_t dest_seg, uint16_t dest_off,
41
 static inline void copy_to_real_libkir ( uint16_t dest_seg, uint16_t dest_off,
26
-					 void *src, size_t n ) {
42
+					 const void *src, size_t n ) {
27
 	__asm__ __volatile__ ( "movw %4, %%es\n\t"
43
 	__asm__ __volatile__ ( "movw %4, %%es\n\t"
28
 			       "cld\n\t"
44
 			       "cld\n\t"
29
 			       "rep movsb\n\t"
45
 			       "rep movsb\n\t"
125
 #define put_real put_real_kir
141
 #define put_real put_real_kir
126
 #define get_real get_real_kir
142
 #define get_real get_real_kir
127
 
143
 
144
+/**
145
+ * A pointer to a user buffer
146
+ *
147
+ * This is actually a struct segoff, but encoded as a uint32_t to
148
+ * ensure that gcc passes it around efficiently.
149
+ */
150
+typedef uint32_t userptr_t;
151
+
152
+/**
153
+ * Copy data to user buffer
154
+ *
155
+ * @v buffer	User buffer
156
+ * @v offset	Offset within user buffer
157
+ * @v src	Source
158
+ * @v len	Length
159
+ */
160
+static inline __attribute__ (( always_inline )) void
161
+copy_to_user ( userptr_t buffer, off_t offset, const void *src, size_t len ) {
162
+	copy_to_real ( ( buffer >> 16 ), ( ( buffer & 0xffff ) + offset ),
163
+		       src, len );
164
+}
165
+
166
+/**
167
+ * Copy data from user buffer
168
+ *
169
+ * @v dest	Destination
170
+ * @v buffer	User buffer
171
+ * @v offset	Offset within user buffer
172
+ * @v len	Length
173
+ */
174
+static inline __attribute__ (( always_inline )) void
175
+copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) {
176
+	copy_from_real ( dest, ( buffer >> 16 ),
177
+			 ( ( buffer & 0xffff ) + offset ), len );
178
+}
179
+
180
+/**
181
+ * Convert segment:offset address to user buffer
182
+ *
183
+ * @v segment	Real-mode segment
184
+ * @v offset	Real-mode offset
185
+ * @ret buffer	User buffer
186
+ */
187
+static inline __attribute__ (( always_inline )) userptr_t
188
+real_to_user ( unsigned int segment, unsigned int offset ) {
189
+	return ( ( segment << 16 ) | offset );
190
+}
191
+
192
+/**
193
+ * Convert virtual address to user buffer
194
+ *
195
+ * @v virtual	Virtual address
196
+ * @ret buffer	User buffer
197
+ *
198
+ * This constructs a user buffer from an ordinary pointer.  Use it
199
+ * when you need to pass a pointer to an internal buffer to a function
200
+ * that expects a @c userptr_t.
201
+ */
202
+static inline __attribute__ (( always_inline )) userptr_t
203
+virt_to_user ( void * virtual ) {
204
+	return real_to_user ( rm_ds, ( intptr_t ) virtual );
205
+}
206
+
128
 /* Place/remove parameter on real-mode stack in a way that's
207
 /* Place/remove parameter on real-mode stack in a way that's
129
  * compatible with libkir
208
  * compatible with libkir
130
  */
209
  */
134
 #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBKIR
213
 #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBKIR
135
 #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBKIR
214
 #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBKIR
136
 
215
 
137
-/* REAL_FRAGMENT: Declare and define a real-mode code fragment in
138
- * .text16.  We don't need this for REAL_EXEC, since we can just
139
- * execute our real-mode code inline, but it's handy in case someone
140
- * genuinely wants to create a block of code that can be copied to a
141
- * specific location and then executed.
142
- *
143
- * Note that we put the code in the data segment, since otherwise we
144
- * can't (easily) access it in order to copy it to its target
145
- * location.  We should never be calling any REAL_FRAGMENT routines
146
- * directly anyway.
147
- */
148
-#define	REAL_FRAGMENT( name, asm_code_str )				\
149
-	extern void name ( void );					\
150
-	extern char name ## _size[];					\
151
-	__asm__ __volatile__ (						\
152
-		".section \".data.text16\"\n\t"				\
153
-		".code16\n\t"						\
154
-		".arch i386\n\t"					\
155
-		#name ":\n\t"						\
156
-		asm_code_str "\n\t"					\
157
-		"lret\n\t"						\
158
-		#name "_end:\n\t"					\
159
-		".equ " #name "_size, " #name "_end - " #name "\n\t"	\
160
-		".code16gcc\n\t"					\
161
-		".previous\n\t"						\
162
-		: :							\
163
-	)
164
-#define FRAGMENT_SIZE( fragment ) ( (size_t) fragment ## _size )
165
-
166
-/* REAL_CALL: call an external real-mode routine */
167
-#define OUT_CONSTRAINTS(...) __VA_ARGS__
168
-#define IN_CONSTRAINTS(...) "m" ( __routine ), ## __VA_ARGS__
169
-#define CLOBBER(...) __VA_ARGS__
170
-#define REAL_CALL( routine, num_out_constraints, out_constraints,	     \
171
-		   in_constraints, clobber )				     \
172
-	do {								     \
173
-		segoff_t __routine = routine;				     \
174
-		__asm__ __volatile__ (					     \
175
-			"pushl %" #num_out_constraints "\n\t"		     \
176
-			".code16\n\t"					     \
177
-			"pushw %%gs\n\t"	/* preserve segs */	     \
178
-			"pushw %%fs\n\t"				     \
179
-			"pushw %%es\n\t"				     \
180
-			"pushw %%ds\n\t"				     \
181
-			"pushw %%cs\n\t"	/* lcall to routine */	     \
182
-			"call 1f\n\t"					     \
183
-			"jmp 2f\n\t"					     \
184
-			"\n1:\n\t"					     \
185
-			"addr32 pushl 12(%%esp)\n\t"			     \
186
-			"lret\n\t"					     \
187
-			"\n2:\n\t"					     \
188
-			"popw %%ds\n\t"		/* restore segs */	     \
189
-			"popw %%es\n\t"					     \
190
-			"popw %%fs\n\t"					     \
191
-			"popw %%gs\n\t"					     \
192
-			"addw $4, %%sp\n\t"				     \
193
-			".code16gcc\n\t"				     \
194
-			: out_constraints : in_constraints : clobber  	     \
195
-		);							     \
196
-	} while ( 0 )
197
-
198
 /* REAL_EXEC: execute some inline assembly code in a way that matches
216
 /* REAL_EXEC: execute some inline assembly code in a way that matches
199
  * the interface of librm
217
  * the interface of librm
200
  */
218
  */
201
-
202
-#define IN_CONSTRAINTS_NO_ROUTINE( routine, ... ) __VA_ARGS__
219
+#define OUT_CONSTRAINTS(...) __VA_ARGS__
220
+#define IN_CONSTRAINTS(...)  __VA_ARGS__
221
+#define CLOBBER(...) __VA_ARGS__
203
 #define REAL_EXEC( name, asm_code_str, num_out_constraints, out_constraints, \
222
 #define REAL_EXEC( name, asm_code_str, num_out_constraints, out_constraints, \
204
 		   in_constraints, clobber )				     \
223
 		   in_constraints, clobber )				     \
205
 	__asm__ __volatile__ (						     \
224
 	__asm__ __volatile__ (						     \
216
 		"popw %%gs\n\t"						     \
235
 		"popw %%gs\n\t"						     \
217
 		".code16gcc\n\t"					     \
236
 		".code16gcc\n\t"					     \
218
 		: out_constraints					     \
237
 		: out_constraints					     \
219
-		: IN_CONSTRAINTS_NO_ROUTINE ( in_constraints )		     \
238
+		: in_constraints					     \
220
 		: clobber				   		     \
239
 		: clobber				   		     \
221
 		);
240
 		);
222
 
241
 

+ 10
- 35
src/arch/i386/include/librm.h View File

177
 #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBRM
177
 #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBRM
178
 #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBRM
178
 #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBRM
179
 
179
 
180
-/* REAL_FRAGMENT: Declare and define a real-mode code fragment in .text16 */
181
-#define	REAL_FRAGMENT( name, asm_code_str )				\
182
-	extern void name ( void );					\
180
+/* REAL_EXEC: execute a fragment of code in real mode */
181
+#define OUT_CONSTRAINTS(...) __VA_ARGS__
182
+#define IN_CONSTRAINTS(...) __VA_ARGS__
183
+#define CLOBBER(...) __VA_ARGS__
184
+#define REAL_EXEC( name, asm_code_str, num_out_constraints,		\
185
+		   out_constraints, in_constraints, clobber ) do {	\
183
 	__asm__ __volatile__ (						\
186
 	__asm__ __volatile__ (						\
184
 		".section \".text16\", \"ax\", @progbits\n\t"		\
187
 		".section \".text16\", \"ax\", @progbits\n\t"		\
185
 		".code16\n\t"						\
188
 		".code16\n\t"						\
190
 		".size " #name ", . - " #name "\n\t"			\
193
 		".size " #name ", . - " #name "\n\t"			\
191
 		".code32\n\t"						\
194
 		".code32\n\t"						\
192
 		".previous\n\t"						\
195
 		".previous\n\t"						\
193
-		: :							\
194
-	)
195
-#define FRAGMENT_SIZE( fragment ) ( (size_t) fragment ## _size )
196
-
197
-/* REAL_CALL: call a real-mode routine via librm */
198
-#define OUT_CONSTRAINTS(...) __VA_ARGS__
199
-#define IN_CONSTRAINTS(...) __VA_ARGS__
200
-#define CLOBBER(...) __VA_ARGS__
201
-#define REAL_CALL( routine, num_out_constraints, out_constraints,	\
202
-		   in_constraints, clobber )				\
203
-	do {								\
204
-		__asm__ __volatile__ (					\
205
-				      "pushl $" #routine "\n\t"		\
206
-				      "call real_call\n\t"		\
207
-				      "addl $4, %%esp\n\t"		\
208
-				      : out_constraints			\
209
-				      : in_constraints			\
210
-				      : clobber				\
211
-				      );				\
212
-	} while ( 0 )
213
-
214
-/* REAL_EXEC: combine RM_FRAGMENT and REAL_CALL into one handy unit */
215
-#define PASSTHRU(...) __VA_ARGS__
216
-#define REAL_EXEC( name, asm_code_str, num_out_constraints, out_constraints, \
217
-		   in_constraints, clobber )				     \
218
-	do {								     \
219
-		REAL_FRAGMENT ( name, asm_code_str );			     \
220
-									     \
221
-		REAL_CALL ( name, num_out_constraints,			     \
222
-			    PASSTHRU ( out_constraints ),		     \
223
-			    PASSTHRU ( in_constraints ),		     \
224
-			    PASSTHRU ( clobber ) );			     \
196
+		"pushl $" #name "\n\t"					\
197
+		"call real_call\n\t"					\
198
+		"addl $4, %%esp\n\t"					\
199
+		: out_constraints : in_constraints : clobber );		\
225
 	} while ( 0 )
200
 	} while ( 0 )
226
 
201
 
227
 #endif /* ASSEMBLY */
202
 #endif /* ASSEMBLY */

Loading…
Cancel
Save