All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [parisc-linux] 720 - some progress
@ 2001-10-01 16:06 Michael S. Zick
  0 siblings, 0 replies; 28+ messages in thread
From: Michael S. Zick @ 2001-10-01 16:06 UTC (permalink / raw)
  To: John Marvin; +Cc: parisc-linux



John;

Thanks a lot for the explanation - I am not surprised that the hardware
is more complex in its operation than the documentation tries to describe.
I have left the full text of your explanation attached so that future
readers of the mailing list archives don't get "half the story".

The ability to NOT EXECUTE the instruction returned to from a fault handler
might come in handy to somebody, someday.

What I was concerned about was the chance that the instruction addressed
by iaoq[1] was a branch (or taken conditional branch) instruction.  

Which, as you point out, could only happen if the MFCTL instruction was 
in the delay slot of a branch instruction.  (Has the compiler been told to
prohibit MFCTL in the delay slot? Not relavent here.)

With the description given in the documentation, then the queue state 
returned would have to be:

regs->iaoq[0] == branch instruction address
regs->iaoq[1] == target instruction address

I.E: That the hardware instruction address prediction was done prior to the
point in the hardware the address queue snapshot is taken on a fault.

The point you make describes instruction address prediction being done
after the point in the hardware flow that the address queue snapshot is
taken.

I.E:
regs->iaoq[0] == branch instruction address
regs->iaoq[1] == branch instruction address + 4

Is a just fine thing to do - the branch instruction will be executed with
the result that whatever was pointed to by iaoq[1] would be replaced by the 
target address (or ignored) in the process.

Certainly a complexity beyond printed documentation.
Anywho - its in the mail archives now for anyone that needs the
information.

Again, Thanks for the extra effort on these details.
Mike

> Date: Sunday, September 30, 2001 2:12 AM
> 
> > It looks (reads) as if it possible to return to the faulting instruction
> > (MFCTL in this case) without executing it.  If so, then adjusting the
> > instruction (and space) queues within the fault handler can be avoided;
> > also avoiding problems with finding the correct "following instruction"
> > address.
> 
> Using the nullify method you talk about does work, but the normal
> convention is to advance the pc queue (there are some performance
> advantages, particularly in the case where the instruction we are
> emulating is in the delay slot of a branch).  The problem you describe
> finding the following instruction doesn't exist.  You are correct about
> the space queue though, but only in the case for a delay slot in the
> branch to the gateway page.  The correct method of advancing the queue is
> the one that has been proposed in the various patches, i.e.:
> 
> 	regs->iaoq[0] = regs->iaoq[1];
> 	regs->iaoq[1] += 4;
> 
> To be perfectly correct, this should be added:
> 
> 	regs->iasq[0] = regs->iasq[1];
> 
> But, again, that last is only necessary if someone actually puts a mfctl
> in the delay slot of the branch to the gateway page (a kernel call) and
> since kernel calls are already provided, we know that no such thing
> actually happens, nor is it likely to happen unless someone handcodes
> their own kernel call. I would put the line in though.
> 
> Here is why there is not a problem advancing the queue as above:
> the only way that "regs->iaoq[1] += 4" would do the wrong thing would
> be if we were emulating a branch instruction. Since we know we are
> emulating a mfctl instruction, this is not the case. Note that if
> someone needs to emulate a branch instruction, computing the new
> value of iaoq[1] would be part of that emulation.
> 
> John Marvin
> jsm@fc.hp.com
> 
> 
> _______________________________________________
> parisc-linux mailing list
> parisc-linux@lists.parisc-linux.org
> http://lists.parisc-linux.org/cgi-bin/mailman/listinfo/parisc-linux

^ permalink raw reply	[flat|nested] 28+ messages in thread
* Re: [parisc-linux] 720 - some progress
@ 2001-09-30  7:12 John Marvin
  0 siblings, 0 replies; 28+ messages in thread
From: John Marvin @ 2001-09-30  7:12 UTC (permalink / raw)
  To: parisc-linux

> It looks (reads) as if it possible to return to the faulting instruction
> (MFCTL in this case) without executing it.  If so, then adjusting the
> instruction (and space) queues within the fault handler can be avoided;
> also avoiding problems with finding the correct "following instruction"
> address.

Using the nullify method you talk about does work, but the normal
convention is to advance the pc queue (there are some performance
advantages, particularly in the case where the instruction we are
emulating is in the delay slot of a branch).  The problem you describe
finding the following instruction doesn't exist.  You are correct about
the space queue though, but only in the case for a delay slot in the
branch to the gateway page.  The correct method of advancing the queue is
the one that has been proposed in the various patches, i.e.:

	regs->iaoq[0] = regs->iaoq[1];
	regs->iaoq[1] += 4;

To be perfectly correct, this should be added:

	regs->iasq[0] = regs->iasq[1];

But, again, that last is only necessary if someone actually puts a mfctl
in the delay slot of the branch to the gateway page (a kernel call) and
since kernel calls are already provided, we know that no such thing
actually happens, nor is it likely to happen unless someone handcodes
their own kernel call. I would put the line in though.

Here is why there is not a problem advancing the queue as above:
the only way that "regs->iaoq[1] += 4" would do the wrong thing would
be if we were emulating a branch instruction. Since we know we are
emulating a mfctl instruction, this is not the case. Note that if
someone needs to emulate a branch instruction, computing the new
value of iaoq[1] would be part of that emulation.

John Marvin
jsm@fc.hp.com

^ permalink raw reply	[flat|nested] 28+ messages in thread
* Re: [parisc-linux] 720 - some progress
@ 2001-09-27 16:32 Jurij Smakov
  2001-09-27 19:18 ` Albert Strasheim
  0 siblings, 1 reply; 28+ messages in thread
From: Jurij Smakov @ 2001-09-27 16:32 UTC (permalink / raw)
  To: parisc-linux

> A quick glance at arch/parisc/hardware/inventory.c reveiled the
> following:
> 
> long status;
> unsigned int bus_id;
> ...
> status = pdc_model_info(&model);
> bus_id = (model.hversion >> (4 + 7)) & 0x1f;
> 
> switch (bus_id) {
> case 0x4:               /* 720, 730, 750, 735, 755 */
> 
> I don't know if all these models have the same CPU. I'm guessing not.
> 
> I also see a parisc_get_cpu_type(...) in arch/parisc/kernnel/hardware.c.
> This is probably what you want.
> 
> Regards,
> 
> Albert

Hi Albert!

As Matthew pointed out, it is not neccessary to determine the CPU type.
"Normal" (newer) CPU's do not consider reading from cr26 and cr27 to
be privileged operations, so the condition, which is checked in the
patch will just never occur for them. Actually, did you try it? I'm
very interested in the results.

Cheers,

Jurij.

^ permalink raw reply	[flat|nested] 28+ messages in thread
* Re: [parisc-linux] 720 - some progress
@ 2001-09-27 14:42 Jurij Smakov
  2001-09-28  8:49 ` Jochen Friedrich
  2001-09-28  8:54 ` Matthew Wilcox
  0 siblings, 2 replies; 28+ messages in thread
From: Jurij Smakov @ 2001-09-27 14:42 UTC (permalink / raw)
  To: parisc-linux

Hi!

I hope I've got it right. It only emulates MFCTL and only when the
source control register is 27. It turns out, that pt_regs does not
have a member for cr26 and adding one does not look like an easy
task. 

Jurij.

--- linux-2.4.9-pa24/arch/parisc/kernel/traps.c Wed Sep 19 12:02:30 2001
+++ linux/arch/parisc/kernel/traps.c    Thu Sep 27 16:16:54 2001
@@ -273,6 +273,7 @@
 {
        unsigned long fault_address = 0;
        unsigned long fault_space = 0;
+       int fromcr,togr;
        struct siginfo si;
 #ifdef CONFIG_KWDB
        struct save_state ssp;
@@ -363,6 +364,17 @@
                si.si_code = ILL_PRVOPC;
                goto give_sigill;
        case 11:
+               if(!(regs->iir & 0xfc000000) && (((regs->iir & 0x1fe0)>>5) == 0x45)) {
+                 /* This is MFCTL instruction */
+                 fromcr = (regs->iir & 0x03e00000)>>21;
+                 togr = (regs->iir & 0x1f);
+                 /* Emulate the instruction if the read is from cr27 */
+                 if(fromcr == 27) {
+                   regs->gr[togr] = regs->cr27;
+                   return;
+                 }
+               }
+               /* Something else is wrong */
                die_if_kernel("Privileged register - shouldn't happen!", regs, code);
                si.si_code = ILL_PRVREG;
        give_sigill:

^ permalink raw reply	[flat|nested] 28+ messages in thread
* Re: [parisc-linux] 720 - some progress
@ 2001-09-27 12:23 Jurij Smakov
  2001-09-27 13:04 ` Albert Strasheim
  2001-09-27 13:45 ` Matthew Wilcox
  0 siblings, 2 replies; 28+ messages in thread
From: Jurij Smakov @ 2001-09-27 12:23 UTC (permalink / raw)
  To: parisc-linux

> The CPU in the 720 will treat this as a priviledged instruction. The
> changes "signal 18 -> signal 26, signal 27, signal 28" and "allow read
> access to CR26 and CR27 for non-priviledged access" are documented as new
> for the PA7100LC processor, so they are not available in the 720.
> 
> Another thing to emulate on the old 720/50 platform...
> 
> Cheers,
> Jochen

It does not seem so complicated... Even with my rudimentary C programming
skills :-). I'll try to put something together. Is there a way to check
if we are running on a 720?

Jurij.

^ permalink raw reply	[flat|nested] 28+ messages in thread
* Re: [parisc-linux] 720 - some progress
@ 2001-09-27 10:03 Jurij Smakov
  2001-09-27 11:15 ` Jochen Friedrich
  0 siblings, 1 reply; 28+ messages in thread
From: Jurij Smakov @ 2001-09-27 10:03 UTC (permalink / raw)
  To: parisc-linux

And another (very weird) thing... I've manually decoded the instruction
(036008A4), which produces the trap 11 (hopefully, correctly :-). 
It turns out to be an MFCTL instruction to load contents of control 
register 27 into a general register 4. According to the docs for this
command ("PA-RISC 1.1 Architecture and Instruction Set Reference Manual",
Third edition, page 5-151):

"CR11, CR26 and CR 27 may be read at ANY privilege level."

So, unless I am missing something, this instruction SHOULD NOT produce
trap 11. Is it some hardware feature of 720 or my manual disassembling
skills must be improved? ;-).

Best regards,

Jurij

^ permalink raw reply	[flat|nested] 28+ messages in thread
* Re: [parisc-linux] 720 - some progress
@ 2001-09-27  9:09 Jurij Smakov
  2001-09-27 11:11 ` Jochen Friedrich
  0 siblings, 1 reply; 28+ messages in thread
From: Jurij Smakov @ 2001-09-27  9:09 UTC (permalink / raw)
  To: parisc-linux

[skipped]
> !!die_if_kernel: ls.x(22): Privileged register - shouldn't happen! 11
>      YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
> PSW: 00000000000001001111111100001111
> r0-3     00000000 4019e57c 4008648f 401a057c
> r4-7     401a057c 40199140 401a057c faf00318
> r8-11    00000000 0001bb24 0002df58 faf000e8
> r12-15   0002df58 0002df58 000c41b0 0002df58
> r16-19   00000000 00000000 10350000 401cf930
> r20-23   40029122 401b33f8 4019b0a0 4019fd7c
> r24-27   00000000 faf00318 40199140 0002df58
> r28-31   4017722c 0002f048 faf00440 40083393
> sr0-3    0000002c 0000002c 00000000 0000002c
> sr4-7    0000002c 0000002c 0000002c 0000002c
> 
> IASQ: 0000002c 0000002c IAOQ: 401b340f 401b3413
>  IIR: 036008a4    ISR: 0000002c  IOR: 0002df58
>  CPU:        0   CR30: 11b68000 CR31: 10358000
>  ORIG_R28: 0002f000
> 
> Does anyone know what the cause 11 means?
[skipped]

Hi!

^ permalink raw reply	[flat|nested] 28+ messages in thread
* [parisc-linux] 720 - some progress
@ 2001-09-26 22:26 Jochen Friedrich
  2001-09-27  0:07 ` Albert Strasheim
  0 siblings, 1 reply; 28+ messages in thread
From: Jochen Friedrich @ 2001-09-26 22:26 UTC (permalink / raw)
  To: parisc-linux

Hi,

i created this patch for the cause 18 on the 720. Without the patch and 
fallthrough to case 26, the following program will just hang:

#include <stdio.h>

int main()
{
  int i,j,k;
  char *p;

  i=0;
  j=1;
  k=0;

  p = (char *) &j;
  p++;
  i = *(int *) p;

  printf("%d\n",i);
}

With the patch, the output is:

sh-2.05# ./unaligned
unaligned(20): unaligned access to 0xfaf002cd at ip=0x0001050f
256
                  
So the patch appears to work correctly at least for this case...

However, the user space tools ls, tar, sleep still crash for me.
This is the dmesg output:

!!die_if_kernel: ls.x(22): Privileged register - shouldn't happen! 11
     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
PSW: 00000000000001001111111100001111
r0-3     00000000 4019e57c 4008648f 401a057c
r4-7     401a057c 40199140 401a057c faf00318
r8-11    00000000 0001bb24 0002df58 faf000e8
r12-15   0002df58 0002df58 000c41b0 0002df58
r16-19   00000000 00000000 10350000 401cf930
r20-23   40029122 401b33f8 4019b0a0 4019fd7c
r24-27   00000000 faf00318 40199140 0002df58
r28-31   4017722c 0002f048 faf00440 40083393
sr0-3    0000002c 0000002c 00000000 0000002c
sr4-7    0000002c 0000002c 0000002c 0000002c

IASQ: 0000002c 0000002c IAOQ: 401b340f 401b3413
 IIR: 036008a4    ISR: 0000002c  IOR: 0002df58
 CPU:        0   CR30: 11b68000 CR31: 10358000
 ORIG_R28: 0002f000

Does anyone know what the cause 11 means?

Cheers,
Jochen
--- linux.orig/arch/parisc/kernel/traps.c	Wed Sep 19 12:02:30 2001
+++ linux/arch/parisc/kernel/traps.c	Thu Sep 27 00:02:23 2001
@@ -46,8 +46,12 @@
 #define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
 			 /*  dumped to the console via printk)          */
 
+#define DEBUG_CASE18
+
 void handle_unaligned(struct pt_regs *regs);
 
+unsigned long parisc_acctyp(unsigned long code, unsigned int inst);
+
 static int printbinary(char *buf, unsigned long x, int nbits)
 {
 	unsigned long mask = 1UL << (nbits - 1);
@@ -274,6 +278,11 @@
 	unsigned long fault_address = 0;
 	unsigned long fault_space = 0;
 	struct siginfo si;
+	unsigned long acc_type;
+	pte_t * pte;
+	pgd_t * pgd;
+	pmd_t * pmd;
+
 #ifdef CONFIG_KWDB
 	struct save_state ssp;
 #endif /* CONFIG_KWDB */   
@@ -322,12 +331,15 @@
 		fault_address = regs->ior;
 		parisc_terminate("Non access data tlb fault!",regs,code,fault_address);
 
+	pagefault:
+#ifdef DEBUG_CASE18
+		printk("to pagefault\n");
+#endif
 	case 15:
 	case 26:
 		fault_address = regs->ior;
 		fault_space   = regs->isr;
 		break;
-
 	case 19:
 		regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
 		/* fall thru */
@@ -416,6 +428,57 @@
 		force_sig_info(SIGSEGV, &si, current);
 		return;
 
+	case 18:
+#ifdef DEBUG_CASE18
+		printk(KERN_DEBUG "got case18 -");
+#endif
+		fault_address = regs->iaoq[0];
+		fault_space = regs->iasq[0];
+
+		if (in_interrupt() || !(current->mm))
+			goto pagefault; /* shouldn't happen */
+		/* FIXME: do propper locking here */
+
+		/* page directory */
+		pgd = pgd_offset(current->mm, fault_address);
+		if (pgd_none(*pgd) || pgd_bad(*pgd))
+			goto pagefault; /* expandable stack etc */
+
+		/* middle page directory */
+		pmd = pmd_offset(pgd, fault_address);
+		if (pmd_none(*pmd) || pmd_bad(*pmd))
+		        goto pagefault; /* expandable stack etc */
+
+		/* page table entry */
+		pte = pte_offset(pmd, fault_address);
+		if (pte_none(*pte))
+		        goto pagefault; /* expandable stack etc */
+
+		if (!pte_present(*pte)) /* is this test sufficient? */
+		        goto pagefault; /* page not loaded */
+
+		acc_type = parisc_acctyp(code,regs->iir);
+
+		if ((acc_type & VM_WRITE) && (!(pte_write(*pte))))
+		        goto pagefault; /* Write protected access */
+
+		if ((acc_type & VM_READ) && (!(pte_read(*pte))))
+			goto pagefault; /* Read protected access */
+
+		if ((acc_type & VM_EXEC) && (!(pte_read(*pte))))
+		        goto pagefault; /* Exec protected access */
+
+		if (!(regs->ior & 3)) {
+#ifdef DEBUG_CASE18
+			printk("spurious? -");
+#endif
+			goto pagefault;
+		}
+		/* fall through to case 28 */
+#ifdef DEBUG_CASE18
+		printk("to unaligned\n");
+		show_regs(regs);
+#endif
 	case 28:  /* Unaligned just causes SIGBUS for now */
 		handle_unaligned(regs);
 #if 0
diff -u -r linux.orig/arch/parisc/mm/fault.c linux/arch/parisc/mm/fault.c
--- linux.orig/arch/parisc/mm/fault.c	Wed Aug 29 12:02:07 2001
+++ linux/arch/parisc/mm/fault.c	Wed Sep 26 22:54:46 2001
@@ -49,7 +49,7 @@
  *   VM_WRITE if write operation
  *   VM_EXEC  if execute operation
  */
-static unsigned long
+unsigned long
 parisc_acctyp(unsigned long code, unsigned int inst)
 {
 	if (code == 6 || code == 16)

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2001-10-01 16:06 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <200109280925.FAA18777@mail.lokmail.net>
2001-09-28 16:24 ` [parisc-linux] 720 - some progress Albert Strasheim
2001-09-28 18:48   ` Jochen Friedrich
2001-09-29 17:48     ` Carlos O'Donell Jr.
2001-10-01 16:06 Michael S. Zick
  -- strict thread matches above, loose matches on Subject: below --
2001-09-30  7:12 John Marvin
2001-09-27 16:32 Jurij Smakov
2001-09-27 19:18 ` Albert Strasheim
2001-09-27 14:42 Jurij Smakov
2001-09-28  8:49 ` Jochen Friedrich
2001-09-28  9:19   ` Matthew Wilcox
2001-09-28  8:54 ` Matthew Wilcox
2001-09-29  6:00   ` Albert Strasheim
2001-09-29  8:30     ` Albert Strasheim
2001-09-29 10:01       ` Albert Strasheim
2001-09-29 11:17     ` Jochen Friedrich
2001-09-29 11:45       ` Albert Strasheim
2001-09-29 13:23         ` Jochen Friedrich
2001-09-29 18:36     ` Michael S.Zick
2001-09-29 22:19       ` Michael S.Zick
2001-09-27 12:23 Jurij Smakov
2001-09-27 13:04 ` Albert Strasheim
2001-09-27 13:45 ` Matthew Wilcox
2001-09-27 10:03 Jurij Smakov
2001-09-27 11:15 ` Jochen Friedrich
2001-09-27  9:09 Jurij Smakov
2001-09-27 11:11 ` Jochen Friedrich
2001-09-26 22:26 Jochen Friedrich
2001-09-27  0:07 ` Albert Strasheim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.