Subject: Re: build aborts in regress/lib/libpthread/sem
To: None <marcus@mc.pp.se, cpg@aladdin.de>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-dreamcast
Date: 02/15/2003 02:12:26
In article <yf9znp0uv6g.fsf@mc.pp.se>
marcus@mc.pp.se wrote:

> > Hmm, but is it really Ok to block all exceptions?
> > I don't think TLB miss or illegal instruction could be blocked.
> > (Then exception during _cpu_exception_suspend() would cause reboot?)
> 
> If there is an illegal instruction of TLB miss in the code contained
> in the critical section, then that code has to be fixed. It's true
> that exception suspension means reboot if an exception is triggered
> anyway, but then at least we'll notice that the exception is there and
> needs to be fixed.

Of cource any illegal instruction exception should never happen,
but I think TLB miss exceptions could occur even on kernel mode
though no page fault should happen on it.

On g2bus bus_space implementation, the requirement
for g2bus is "G2 bus cycles must not be interrupted,"
but TLB miss would never happen on g2bus access
because all g2bus space is mapped on P2SEG addresses
(TLB miss could happen on accessing buffers though),
so we don't have to use _cpu_exception_suspend()
and _cpu_intr_suspend() is enough.

How about the attached patch?
(anyway it isn't good thing to disable all interrupts
 during multi or region ops for large buffers..)
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp

Index: dev/g2/g2bus_bus_mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/dreamcast/dev/g2/g2bus_bus_mem.c,v
retrieving revision 1.6
diff -u -r1.6 g2bus_bus_mem.c
--- dev/g2/g2bus_bus_mem.c	2002/12/27 11:34:05	1.6
+++ dev/g2/g2bus_bus_mem.c	2003/02/14 16:54:28
@@ -144,33 +144,22 @@
 
 /*
  * G2 bus cycles must not be interrupted by IRQs or G2 DMA.
- * The following paired macros will take the necessary precautions.
  */
 
-#define G2_LOCK								\
-	do {								\
-		_cpu_exception_suspend();				\
-		/* suspend any G2 DMA here... */			\
-		while((*(volatile unsigned int *)0xa05f688c) & 32);	\
-	} while(/*CONSTCOND*/0)
-
-#define G2_UNLOCK							\
-	do {								\
-		/* resume any G2 DMA here... */				\
-		_cpu_exception_resume(0);				\
-	} while(/*CONSTCOND*/0)
+#define WAIT_G2DMA while ((*(volatile unsigned int *)0xa05f688c) & 0x20)
 
-
 u_int8_t
 g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	int s;
 	u_int8_t rv;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	rv = *(__volatile u_int8_t *)(sh + off);
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 
 	return (rv);
 }
@@ -178,13 +167,15 @@
 u_int16_t
 g2bus_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	int s;
 	u_int16_t rv;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	rv = *(__volatile u_int16_t *)(sh + off);
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 
 	return (rv);
 }
@@ -192,13 +183,15 @@
 u_int32_t
 g2bus_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	int s;
 	u_int32_t rv;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	rv = *(__volatile u_int32_t *)(sh + off);
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 
 	return (rv);
 }
@@ -207,64 +200,74 @@
 g2bus_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int8_t val)
 {
+	int s;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	*(__volatile u_int8_t *)(sh + off) = val;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int16_t val)
 {
+	int s;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	*(__volatile u_int16_t *)(sh + off) = val;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int32_t val)
 {
+	int s;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	*(__volatile u_int32_t *)(sh + off) = val;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_bus_mem_read_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int8_t *addr, bus_size_t len)
 {
+	int s;
 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + off);
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	while (len--)
 		*addr++ = *baddr++;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_bus_mem_write_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
     const u_int8_t *addr, bus_size_t len)
 {
+	int s;
 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + off);
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	while (len--)
 		*baddr++ = *addr++;
 
-	G2_UNLOCK;
+	_cpu_intr_suspend();
 }
 
 void
@@ -291,13 +294,15 @@
 u_int8_t
 g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	int s;
 	u_int8_t rv;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	rv = *(__volatile u_int8_t *)(sh + (off * 4));
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 
 	return (rv);
 }
@@ -305,13 +310,15 @@
 u_int16_t
 g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	int s;
 	u_int16_t rv;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	rv = *(__volatile u_int16_t *)(sh + (off * 4));
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 
 	return (rv);
 }
@@ -319,13 +326,15 @@
 u_int32_t
 g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	int s;
 	u_int32_t rv;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	rv = *(__volatile u_int32_t *)(sh + (off * 4));
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 
 	return (rv);
 }
@@ -334,94 +343,108 @@
 g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int8_t val)
 {
+	int s;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	*(__volatile u_int8_t *)(sh + (off * 4)) = val;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int16_t val)
 {
+	int s;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	*(__volatile u_int16_t *)(sh + (off * 4)) = val;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int32_t val)
 {
+	int s;
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	*(__volatile u_int32_t *)(sh + (off * 4)) = val;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh,
     bus_size_t off, u_int8_t *addr, bus_size_t len)
 {
+	int s;
 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	while (len--) {
 		*addr++ = *baddr;
 		baddr += 4;
 	}
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh,
     bus_size_t off, const u_int8_t *addr, bus_size_t len)
 {
+	int s;
 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	while (len--) {
 		*baddr = *addr++;
 		baddr += 4;
 	}
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh,
     bus_size_t off, u_int8_t *addr, bus_size_t len)
 {
+	int s;
 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	while (len--)
 		*addr++ = *baddr;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }
 
 void
 g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh,
     bus_size_t off, const u_int8_t *addr, bus_size_t len)
 {
+	int s;
 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
 
-	G2_LOCK;
+	s = _cpu_intr_suspend();
+	WAIT_G2DMA;
 
 	while (len--)
 		*baddr = *addr++;
 
-	G2_UNLOCK;
+	_cpu_intr_resume(s);
 }