[PATCH 4 of 5] Improvement of portability

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

 This patch aims to improve portability to other platforms. With this
goal, there should not be any assembly code at the upper level
directories.

 This patch moves the "hard_reset_now" function, written entirely in
assembler, from the "kernel" directory, to the architecture dependent
file "arch/i86/kernel/system.c".

 The function init_task() in file init/main.c had an small assembly code
sequence to start the init task. The function run_init_process() was
defined in the arch dependent file "arch/i86/kernel/process.c" to be
similar to mainstream linux, and to include that assembly code. This
modification had the side effect of saving ~100 bytes of code.

 The last bit of assembly in init/main.c is the delay function. Both C
and assembly implementations existed in this file, as an example of how
inefficient is bcc, but used the assembly one. I replaced the C imple-
mentation of delay() with a more compact (but neither faster nor more
portable) code than any of the original versions, and removed the
assembly code.

 I found that bcc ignores the "register" keyword. Then, it's not possible
to write faster code in C. Also, it's safe to remove any "register"
keyword.

 The Image builded without errors. The kernel was tested with QEMU and
dioscuri emulators. Also in a PPro pc booting from floppy.

Greetings,

Juan

diff -Nurb elks.orig/arch/i86/kernel/process.c elks/arch/i86/kernel/process.c
--- elks.orig/arch/i86/kernel/process.c	2012-03-26 14:28:24.000000000 -0600
+++ elks/arch/i86/kernel/process.c	2012-05-03 17:27:44.000000000 -0500
@@ -372,6 +372,36 @@
 #endasm
 #endif

+int run_init_process(char *cmd, char *ar)
+{
+    int num;
+    unsigned short int *pip = (unsigned short int *)ar;
+
+    *pip++ = 0;
+    *pip++ = (unsigned short int) &ar[6];
+    *pip++ = 0;
+    if(num = sys_execve(cmd, ar, 18))
+	return num;
+#ifndef S_SPLINT_S
+    /* Brackets round the following code are required as a work around
+     * for a bug in the compiler which causes it to jump past the asm
+     * code if they are not there.
+     */
+    {
+#asm
+	cli
+	mov bx, _current
+	mov sp, 2[bx]		! user stack offset
+	mov ax, 4[bx]		! user stack segment
+	mov ss, ax
+	mov ds, ax
+	mov es, ax
+	iret			! reloads flags = >reenables interrupts
+#endasm
+    }
+#endif
+}
+
 /*
  * We only need to do this as long as we support old format binaries
  * that grow stack and heap towards each other
diff -Nurb elks.orig/arch/i86/kernel/system.c elks/arch/i86/kernel/system.c
--- elks.orig/arch/i86/kernel/system.c	2012-03-26 14:28:24.000000000 -0600
+++ elks/arch/i86/kernel/system.c	2012-05-03 17:27:44.000000000 -0500
@@ -11,6 +11,21 @@
 int arch_cpu;			/* Processor type */
 extern long int basmem;

+/* Stubs for functions needed elsewhere */
+
+void hard_reset_now(void)
+{
+#ifndef S_SPLINT_S
+#asm
+	mov ax,#0x40		! No memory check on reboot
+	mov ds, ax
+	mov [0x72],#0x1234
+	jmp #0xffff:0
+
+#endasm
+#endif
+}
+
 void setup_arch(seg_t *start, seg_t *end)
 {
     register __ptask taskp;
diff -Nurb elks.orig/init/main.c elks/init/main.c
--- elks.orig/init/main.c	2012-03-26 14:28:24.000000000 -0600
+++ elks/init/main.c	2012-05-04 15:01:03.000000000 -0500
@@ -27,6 +27,7 @@
 /**************************************/

 static void init_task(void);
+extern int run_init_process(char *, char *);

 extern __ptask _reglasttask, _regnexttask;

@@ -92,14 +93,7 @@
 {
     int num;

-    /* Make sure the correct exec stack is in place for init. */
-
-    unsigned short int *pip = (unsigned short int *) args;
-
-    *++pip = (unsigned short int) &args[5];
-
     mount_root();
-
     printk("Loading init\n");

     /* The Linux kernel traditionally attempts to start init from 4 locations,
@@ -113,149 +107,43 @@
      * So, I've modified the ELKS kernel to follow this tradition.
      */

-    if ((num = sys_execve("/sbin/init", args, 18))) {
-
+    num = run_init_process("/sbin/init", args);
 	printk("sys_execve(\"/sbin/init\",args,18) => %d.\n",num);
-
-	if ((num = sys_execve("/etc/init", args, 18))) {
-
+    num = run_init_process("/etc/init", args);
 	    printk("sys_execve(\"/etc/init\",args,18) => %d.\n",num);
-
-	    if ((num = sys_execve("/bin/init", args, 18))) {
-
+    num = run_init_process("/bin/init", args);
 		printk("sys_execve(\"/bin/init\",args,18) => %d.\n",num);

-
 #ifdef CONFIG_CONSOLE_SERIAL
 		num = sys_open("/dev/ttyS0", 2, 0);
 #else
 		num = sys_open("/dev/tty1", 2, 0);
 #endif
-
 		if (num < 0)
 		    printk("Unable to open /dev/tty (error %u)\n", -num);

 		if (sys_dup(0) != 1)
 	    	printk("dup failed\n");
-
 		sys_dup(0);
-
 		printk("No init - running /bin/sh\n");

-		if (sys_execve("/bin/sh", args, 0))
+    num = run_init_process("/bin/sh", args);
+    printk("sys_execve(\"/bin/sh\",args,18) => %d.\n",num);
 	    	    panic("No init or sh found");
-    	    }
-	}
-    }
-
-
-#ifndef S_SPLINT_S
-
-    /* Brackets round the following code are required as a work around
-     * for a bug in the compiler which causes it to jump past the asm
-     * code if they are not there.
-     *
-     * This kludge is here because we called sys_execve directly, rather
-     * than via syscall_int (a BIOS interrupt). So we simulate the last
-     * part of syscall_int, which restores context back to the user process.
-     */
-    {
-#asm
-	cli
-	mov bx, _current
-	mov sp, 2[bx]		! user stack offset
-	mov ax, 4[bx]		! user stack segment
-	mov ss, ax
-	mov ds, ax
-	mov es, ax
-	iret			! reloads flags = >reenables interrupts
-#endasm
-    }
-#endif
-
-    panic("iret failed!");
 }

 /*
  *	Yes its the good old bogomip counter
  */

-#ifdef USE_C
-
 static void delay(jiff_t loops)
 {
-    jiff_t i;
-    for (i = loops; i >= 0; i--)
-	/* Do nothing */ ;
+    do {
+	do {
+	} while((*((unsigned int *)(&loops)))--);
+    } while((*(((unsigned int *)(&loops))+1))--);
 }

-#else
-
-static void delay(jiff_t loops);
-
-#ifndef S_SPLINT_S
-
-/*
- *	The C one just shows bcc isnt always[often] a very good
- *	compiler. This is a non optimal but fairly passable assembler
- *	bogomips that should be constant over compilers.
- */
-
-#asm
-    .text
-
-_delay:
-
-! Create the stack frame
-
-	push bp
-	mov bp,sp
-
-! Get the high word
-
-	mov ax,6[bp]
-
-! Delay the higher word
-
-	or ax,ax
-	jz  dellow
-
-axlp:
-	xor bx,bx
-
-! Delay a complete low word loop time
-
-bxlp:
-	dec bx
-	jnz bxlp
-
-! Now back around for the next high word
-
-	dec ax
-	jnz axlp
-
-! Delay for the low part of the time
-
-dellow:
-	mov ax,4[bp]
-	or ax,bx
-	jz deldone
-
-dellp:
-	dec ax
-	jnz dellp
-
-! Recover stack frame and return
-
-deldone:
-	pop bp
-	ret
-#endasm
-
-#endif
-
-#endif
-
 int calibrate_delay(void)
 {
     jiff_t ticks, bogo, sub;
diff -Nurb elks.orig/kernel/Makefile elks/kernel/Makefile
--- elks.orig/kernel/Makefile	2012-03-26 14:28:24.000000000 -0600
+++ elks/kernel/Makefile	2012-05-04 15:09:34.000000000 -0500
@@ -25,7 +25,7 @@

 DISTFILES	=

-NOINDENT	= memdumpk.c stubs.c
+NOINDENT	= memdumpk.c

 #########################################################################
 # Include standard commands.
@@ -35,7 +35,7 @@
 #########################################################################
 # Objects to compile.

-OBJS  = sched.o printk.o sleepwake.o dma.o version.o sys.o stubs.o fork.o \
+OBJS  = sched.o printk.o sleepwake.o dma.o version.o sys.o fork.o \
 	exit.o time.o signal.o

 #########################################################################
diff -Nurb elks.orig/kernel/stubs.c elks/kernel/stubs.c
--- elks.orig/kernel/stubs.c	2012-03-26 14:28:24.000000000 -0600
+++ elks/kernel/stubs.c	2012-05-03 17:27:44.000000000 -0500
@@ -1,14 +0,0 @@
-/* Stubs for functions needed elsewhere */
-
-void hard_reset_now(void)
-{
-#ifndef S_SPLINT_S
-#asm
-	mov ax,#0x40		! No memory check on reboot
-	mov ds, ax
-	mov [0x72],#0x1234
-	jmp #0xffff:0
-
-#endasm
-#endif
-}
--
To unsubscribe from this list: send the line "unsubscribe linux-8086" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Kernel]     [Linux ia64]     [DCCP]     [Linux for ARM]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux