This is the mail archive of the frysk@sources.redhat.com mailing list for the frysk project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

one frysk-core patch to add PPC64 testcases.


hi,

There's no any case for us to test register and memory modification in
PPC64 in frysk. So we write two cases for above purpose. During the
test, we found the PPC64's worksize(got from IsaPPC64.java) should be
8bytes but not 4 bytes. Here is the patch to add PPC64 tests.

2006-08-18  Yong Zheng  <zhengyo@cn.ibm.com>

	* frysk/proc/TestPPC64Regs.java: New file for PPC64 test
	* frysk/proc/TestPPC64Modify.java: New file for PPC64 test
	* frysk/pkglibexecdir/funit-ppc64-regs.S: New file for PPC64
	* frysk/pkglibexecdir/funit-ppc64-modify.S: Ditto
	* frysk/Makefile.am: Add PPC64Regs/PPC64Modify tests

	* frysk/proc/IsaPPC64.java (getWordSize): Edit return value
	from 4 to 8

Rebuild frysk on X86-64/PPC64 based on the cvs head(08-18) and tested.

Best regards
Yong Zheng

Index: frysk-core/Makefile.am
===================================================================
RCS file: /cvs/frysk/frysk-core/Makefile.am,v
retrieving revision 1.61
diff -u -r1.61 Makefile.am
--- frysk-core/Makefile.am	17 Aug 2006 01:54:27 -0000	1.61
+++ frysk-core/Makefile.am	18 Aug 2006 05:34:20 -0000
@@ -102,6 +102,11 @@
 frysk_pkglibexecdir_funit_x8664_modify_SOURCES = frysk/pkglibexecdir/funit-x8664-modify.S
 pkglibexec_PROGRAMS += frysk/pkglibexecdir/funit-x8664-modify
 
+frysk_pkglibexecdir_funit_ppc64_regs_SOURCES = frysk/pkglibexecdir/funit-ppc64-regs.S
+pkglibexec_PROGRAMS += frysk/pkglibexecdir/funit-ppc64-regs
+frysk_pkglibexecdir_funit_ppc64_modify_SOURCES = frysk/pkglibexecdir/funit-ppc64-modify.S
+pkglibexec_PROGRAMS += frysk/pkglibexecdir/funit-ppc64-modify
+
 # For TestExec.java
 pkglibexec_PROGRAMS += frysk/pkglibexecdir/funit-child-alias
 frysk_pkglibexecdir_funit_child_alias_SOURCES =
Index: frysk-core/frysk/proc/IsaPPC64.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/IsaPPC64.java,v
retrieving revision 1.1
diff -u -r1.1 IsaPPC64.java
--- frysk-core/frysk/proc/IsaPPC64.java	4 Aug 2006 09:07:42 -0000	1.1
+++ frysk-core/frysk/proc/IsaPPC64.java	18 Aug 2006 05:35:12 -0000
@@ -84,7 +84,7 @@
 
   public int getWordSize ()
   {
-    return 4;
+    return 8;
   }
 
   public ByteOrder getByteOrder ()
--- /dev/null	2006-08-17 19:07:50.484771500 +0800
+++ frysk-core/frysk/proc/TestPPC64Regs.java	2006-08-18 13:47:28.000000000 +0800
@@ -0,0 +1,177 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2006, IBM Co.
+//
+// FRYSK is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// FRYSK is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+// 
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved Interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved Interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+package frysk.proc;
+
+import java.util.Observable;
+
+import frysk.sys.SyscallNum;
+
+/**
+ * Check that PPC64 registers can be accessed.
+ */
+public class TestPPC64Regs
+  extends SyscallExaminer
+{
+  class TestPPC64RegsInternals extends SyscallExaminer.Tester
+  {
+    long gpr0;
+    long gpr3;
+    long gpr4;
+    long gpr5;
+	
+    int syscallNum;
+    boolean isPPC64Isa;
+    
+    // Need to add task observers to the process the moment it is
+    // created, otherwize the creation of the very first task is
+    // missed (giving a mismatch of task created and deleted
+    // notifications.)
+	
+    class TaskEventObserver
+      extends SyscallExaminer.Tester.TaskEventObserver
+    {
+      public Action updateSyscallEnter (Task task)
+      {
+        LinuxPPC64 isaPPC64;
+        SyscallEventInfo syscall;
+        
+        super.updateSyscallEnter(task);
+        
+        try
+          {
+            syscall = task.getSyscallEventInfo ();
+            isaPPC64 = (LinuxPPC64)task.getIsa ();
+          }
+        catch (TaskException e)
+          {
+            fail("got task exception " + e);
+            return Action.CONTINUE; // not reached
+          }
+        
+        // The low-level assembler code performs an exit syscall
+        // and sets up the registers with simple values.  We want
+        // to verify that all the registers are as expected.
+        syscallNum = syscall.number (task);
+        
+        if (syscallNum == SyscallNum.SYSexit)
+        {
+          gpr0 = isaPPC64.getRegisterByName ("gpr0").get (task);
+          gpr3 = isaPPC64.getRegisterByName ("gpr3").get (task);
+          gpr4 = isaPPC64.getRegisterByName ("gpr4").get (task);
+          gpr5 = isaPPC64.getRegisterByName ("gpr5").get (task);
+        }
+        
+        return Action.CONTINUE;
+      }
+    }
+
+    class RegsTestObserver 
+      extends SyscallExaminer.TaskAddedObserver 
+    {
+      public void update(Observable o, Object obj)
+      {
+        super.update(o, obj);
+        Task task = (Task)obj;
+        
+        if (!isChildOfMine(task.proc))
+          return;
+        
+        Isa isa;
+        TaskEventObserver taskEventObserver = new TaskEventObserver();
+        
+        try 
+          {
+            isa = task.getIsa();
+          }
+        catch (TaskException e) 
+          {
+            isa = null;
+          }
+        
+        if (isa instanceof LinuxPPC64) 
+        {
+          isPPC64Isa = true;
+          task.requestAddSyscallObserver(taskEventObserver);
+          task.requestAddSignaledObserver(taskEventObserver);
+        }
+        else 
+        {
+          //If not PPC64, stop immediately
+          isPPC64Isa = false;
+          Manager.eventLoop.requestStop();
+        }
+      }
+    }
+
+    TestPPC64RegsInternals ()
+    {
+      super();
+      addTaskAddedObserver(new RegsTestObserver());
+    }
+  }
+  
+  public void testPPC64Regs ()
+  {
+    if (MachineType.getMachineType() != MachineType.PPC64)
+      return;
+    
+    TestPPC64RegsInternals t = new TestPPC64RegsInternals();
+    // Create program making an exit syscall");
+    AttachedDaemonProcess child = new AttachedDaemonProcess (new String[]
+    {
+	  getExecPrefix () + "funit-ppc64-regs"
+	});
+    logger.finest("About to resume funit-ppc64-regs");
+    child.resume();
+    assertRunUntilStop ("run \"ppc64regs\" until exit");
+
+    if (t.isPPC64Isa)
+    {
+      assertEquals ("syscall", 1, t.syscallNum);
+      assertEquals ("gpr0 register", 1, t.gpr0);
+      assertEquals ("gpr3 register", 1, t.gpr3);
+      assertEquals ("gpr4 register", 4, t.gpr4);
+      // Left shift 36bits from 0x1
+      assertEquals ("gpr5 register", 0x1000000000L, t.gpr5);
+      
+      assertTrue ("exited", t.exited);
+    }
+  }
+}
--- /dev/null	2006-08-17 19:07:50.484771500 +0800
+++ frysk-core/frysk/proc/TestPPC64Modify.java	2006-08-18 13:44:12.000000000 +0800
@@ -0,0 +1,251 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2006, IBM Co.
+//
+// FRYSK is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// FRYSK is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+// 
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved Interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved Interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+package frysk.proc;
+
+import java.util.Observer;
+import java.util.Observable;
+
+import frysk.sys.SyscallNum;
+
+/**
+ * Check that registers and memory can be modified for PPC64.
+ * 
+ * This test case runs an assembler program that will terminate successfully 
+ * if left to run untouched. The test adds a syscall observer and modifies 
+ * a register which is used as a jump location when the test returns. This causes 
+ * an alternate code path which issues an exit syscall. The test also modifies 
+ * other registers as well as a data word in the program being run.  The alternate 
+ * code path in the program being run will verify the new register values and 
+ * will not issue the exit syscall unless everything is correct.
+ * 
+ * You can read this testsuite and the assembler program.
+ */
+public class TestPPC64Modify
+  extends TestLib
+{
+  class TestPPC64ModifyInternals
+  {
+    volatile int stoppedTaskEventCount;
+    volatile int syscallTaskEventCount;
+    volatile int syscallState;
+    volatile boolean exited;
+    volatile int exitedTaskEventStatus;
+    
+    long gpr0;
+    long gpr3;
+    
+    // Test the following registers' value
+    long gpr4;
+    long gpr5;
+    
+    long gpr6; 
+    long gpr7;
+    long gpr8;
+    
+    int syscallNum;
+    boolean isPPC64Isa;
+    boolean exitSyscall;
+    
+    // Need to add task observers to the process the moment it is
+    // created, otherwize the creation of the very first task is
+    // missed (giving a mismatch of task created and deleted
+    // notifications.)
+
+    class TaskEventObserver
+      extends TaskObserverBase
+      implements TaskObserver.Syscall, TaskObserver.Signaled
+    {
+      public Action updateSyscallEnter (Task task)
+      {
+        syscallState = 1;
+        SyscallEventInfo syscall;
+        LinuxPPC64 isa;
+        
+        try 
+          {
+            syscall = task.getSyscallEventInfo();
+            isa = (LinuxPPC64)task.getIsa();             
+          }
+        catch (TaskException e)
+          {
+            fail("Got task exception " + e);
+            return Action.CONTINUE; // not reached
+          }
+        
+        // The low-level assembler code performs an exit syscall
+        // and sets up the registers with simple values.  We want
+        // to verify that all the registers are as expected.
+        syscallNum = syscall.number (task);
+        if (syscallNum == SyscallNum.SYSgetpid)
+        {
+          // In the assembler program, we store 21 to gpr3, 22 to gpr4
+          // and 23 to gpr5 before syscalling
+          gpr3 = isa.getRegisterByName ("gpr3").get (task);
+          assertEquals ("gpr3 register", 21, gpr3);
+          
+          gpr4 = isa.getRegisterByName ("gpr4").get (task);
+          assertEquals ("rsi register", 22, gpr4);
+          
+          gpr5 = isa.getRegisterByName ("gpr5").get (task);
+          assertEquals ("rdx register", 23, gpr5);
+          
+          gpr6 = isa.getRegisterByName ("gpr6").get (task);
+          int mem = task.memory.getInt (gpr6);
+          
+          // gpr6 store the value 3 first and then we will modify it to 8
+          assertEquals ("old mem value", 3, mem);
+          task.memory.putInt (gpr6, 8);
+          mem = task.memory.getInt (gpr6);
+          assertEquals ("new mem value", 8, mem);
+
+          gpr7 = isa.getRegisterByName ("gpr7").get (task);
+          isa.getRegisterByName ("gpr8").put (task, gpr7);
+
+          // Set a number of the registers as expected.
+          // Then check them in assembly
+          isa.getRegisterByName ("gpr3").put (task, 3);
+          isa.getRegisterByName ("gpr4").put (task, 4);
+          isa.getRegisterByName ("gpr5").put (task, 5);
+          isa.getRegisterByName ("gpr7").put (task, 7);
+          
+          // After this, the assembler program will be executed.
+          // If all is ok, it will call 'exit' syscall to exit.
+        }
+        else if (syscallNum == SyscallNum.SYSexit)
+        {
+          gpr3 = isa.getRegisterByName ("gpr3").get (task);
+          assertEquals ("exit code", 3, gpr3);
+          exitSyscall = true;
+        }
+        return Action.CONTINUE;
+      }
+      
+      public Action updateSyscallExit (Task task)
+      {
+        syscallState = 0;
+        return Action.CONTINUE;
+      }
+      
+      public Action updateSignaled (Task task, int sig)
+      {
+        //fail ("unexpected signal " + sig);
+        return Action.CONTINUE; // not reached
+      }
+    }
+    
+    TaskEventObserver taskEventObserver = new TaskEventObserver ();
+  
+    class ProcRemovedObserver
+      implements Observer
+    {
+      volatile int count;
+      
+      public void update (Observable o, Object obj)
+      {
+        Proc process = (Proc) obj;
+        if (isChildOfMine (process))
+        {
+          syscallState ^= 1;  // we won't return from exit syscall
+          exited = true;
+          Manager.eventLoop.requestStop ();
+        }
+      }
+    }
+
+    TestPPC64ModifyInternals ()
+    {
+      host.observableTaskAddedXXX.addObserver (new Observer ()
+      {
+        public void update (Observable o, Object obj)
+        {
+          Task task = (Task) obj;
+          if (!isChildOfMine (task.proc))
+            return;
+          killDuringTearDown (task.getTid ());
+          
+          Isa isa;
+          try
+            {
+              isa = task.getIsa();
+            }
+          catch (TaskException e)
+            {
+              isa = null;
+            }
+          
+          if (isa instanceof LinuxPPC64)
+          {
+            isPPC64Isa = true;
+            task.requestAddSyscallObserver (taskEventObserver);
+            task.requestAddSignaledObserver (taskEventObserver);
+          }
+          else
+          {
+            //If not PPC64, stop immediately
+            isPPC64Isa = false;
+            Manager.eventLoop.requestStop ();
+          }
+        }
+      });
+      
+      host.observableProcRemovedXXX.addObserver(new ProcRemovedObserver ());
+    }
+  }
+
+  public void testPPC64Modify ()
+  {
+    if (MachineType.getMachineType() != MachineType.PPC64)
+      return;
+    TestPPC64ModifyInternals t = new TestPPC64ModifyInternals ();
+    
+    // Call assembler program making syscalls
+    new AttachedDaemonProcess (new String[]
+    {
+      getExecPrefix () + "funit-ppc64-modify"
+    }).resume ();
+    assertRunUntilStop ("run \"ppc64modify\" to exit");
+    
+    if (t.isPPC64Isa)
+    {
+      assertTrue ("proc exited", t.exited);
+      assertTrue ("exit syscall found", t.exitSyscall);
+    }
+  }
+}
--- /dev/null	2006-08-17 19:07:50.484771500 +0800
+++ frysk-core/frysk/pkglibexecdir/funit-ppc64-regs.S	2006-08-11 14:42:49.000000000 +0800
@@ -0,0 +1,31 @@
+.text                       # section declaration - begin code
+
+	.global main
+#ifdef	__powerpc64__
+	.section        ".opd","aw"
+	.align 3
+#endif
+
+main:
+
+#ifdef __powerpc64__
+	.quad   ._main,.TOC.@tocbase,0
+	.previous
+
+	.global  ._main
+._main:
+
+	li      0,1         # syscall number (sys_exit)
+	li      3,1         # first argument: exit code
+	li      4,4         # gpr4=4
+
+	# shift left 36-bits for the value: 0x1
+	# test whether the low 32-bits and high 32-bits can be accessed right	
+	li      5,1         # gpr5=1
+	sldi    5,5,36
+	sc                  # call kernel
+
+#endif
+
+.section        .note.GNU-stack,"",@progbits
+
--- /dev/null	2006-08-17 19:07:50.484771500 +0800
+++ frysk-core/frysk/pkglibexecdir/funit-ppc64-modify.S	2006-08-14 10:08:29.000000000 +0800
@@ -0,0 +1,103 @@
+.text                       # section declaration - begin code
+
+	.global main
+#ifdef	__powerpc64__
+	.section        ".opd","aw"
+	.align 3
+#endif
+
+main:
+
+#ifdef __powerpc64__
+	.quad   ._main,.TOC.@tocbase,0
+	.previous
+
+	.global  ._main
+._main:
+
+        mflr    0               # move the value of LR to gpr0
+        std     31,-8(1)
+        std     0,16(1)         # store the LR to 16(1)
+        stdu    1,-144(1)       # store the stack frame pointer value to -144(1)
+        mr      31,1            # copy the value gpr1 to gpr31
+
+        li      0,20            # syscall number(sys_write)
+        li      3,21            # values for TestPPC64Modify.java to inspect. gpr3=21
+        li      4,22            # gpr4=22
+        li      5,23            # gpr5=23
+
+        # load the data's address
+        lis     6,data_value@highest
+        ori     6,6,data_value@higher # load data bits 32-47 into gpr6 bits 0-15
+
+        rldicr  6,6,32,31       # rotate gpr6's low word(0-31)into 32-63
+
+        oris    6,6,data_value@h
+        ori     6,6,data_value@l
+
+        #load the .L0's address
+        lis     7,.L0@highest
+        ori     7,7,.L0@higher # load data bits 32-47 into gpr6 bits 0-15
+
+        rldicr  7,7,32,31       # rotate gpr6's low word(0-31)into 32-63
+
+        oris    7,7,.L0@h
+        ori     7,7,.L0@l
+
+        # load the .L1's address
+        lis     8,.L1@highest
+        ori     8,8,.L1@higher # load data bits 32-47 into gpr6 bits 0-15
+
+        rldicr  8,8,32,31       # rotate gpr6's low word(0-31)into 32-63
+
+        oris    8,8,.L1@h
+        ori     8,8,.L1@l
+
+        sc
+        #mtctr  8
+        #bctr
+.L0:
+        # Check the value of variables is right or not
+        cmpdi   cr7,4,4
+        bne     cr7,.L2
+        cmpdi   cr7,5,5
+        bne     cr7,.L2
+
+        # check the value of gpr6
+        # load the variable's value
+        lis     6,data_value@highest  # load data bits 48-63 into gpr6 bits 16-31
+        ori     6,6,data_value@higher # load data bits 32-47 into gpr6 bits 0-15
+
+        rldicr  6,6,32,31       # rotate gpr6's low word(0-31)into 32-63
+
+        oris    6,6,data_value@h
+        ori     6,6,data_value@l
+
+        lwa     10,0(6)
+        cmpdi   cr7,10,8
+        bne     cr7,.L2
+        cmpwi   cr7,7,7
+        bne     cr7,.L2
+
+        li      0,1
+        li      3,3
+        sc
+        b .L1
+
+.L2:    b .L1                   # failure
+.L1:
+        ld      1,0(1)          # restore the stack frame pointer value
+        # restore the LR register
+        ld      0,16(1)
+        mtlr    0
+
+        ld      31,-8(1)
+        blr                   # Not really supposed to get here
+
+        .data
+data_value:     .long  3
+
+#endif
+
+.section        .note.GNU-stack,"",@progbits
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]