Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 15 Mar 1997 20:00:55 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bakul@torrentnet.com, hackers@FreeBSD.org
Subject:   Re: kernel remote debugging using gdb
Message-ID:  <199703150900.UAA30485@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>- recompiled the boot program to always use COM1 as console and
>  installed it on the primary disk on the test machine (called TEST).
>
>- used the following options in the TEST config file:
>    options         COMCONSOLE
>    options         DDB
>    options         BREAK_TO_DEBUGGER

You probably don't want COMCONSOLE.  It forces a serial console.  This
is inflexible, and serial consoles don't work right in conjunction with
remote gdb.

>- started kermit on DEVEL and connected to TEST @ 9600 baud

9600 baud is very slow.  Paul Traina likes to use 115200.  This is sometimes
affected by initialization bugs (all instances of 9600 need to be changed
to 115200 to get consistent initialization), and the throughput is still
limited to one packet per clock tick on FreeBSD hosts running sio since
the protocol is non-streaming and sio input is delivered to applications
only every clock tick.

>There are two problems:
>
>- Sendind a break in multiuser mode (before or after attaching gdb)
>  does not seem to drop the kernel in the debugger.  This seems to
>  work occasionally but I haven't as yet figured out under what
>  conditions.

I don't use breaks, but I saw cases where ordinary breakpoints didn't
work (and screwed up everything) because of transmission errors.

>- In single user mode when gdb is attached, you can not type anything
>  on the console nor can you see any printf() output[1].

gdb and serial consoles don't mix well.  At best you can multiplex them
manually.

>[1] Note that passing console device IO `through gdb' would be
>    extremely useful as it will feel as if gdb is built in.  Not
>    sure if this works at all for the standard gdb remote protocol.
>    At any rate adding it would not be hard.

The driver's support for multiple serial consoles could be improved,
but it would still be useful to multiplex through one console, since
having multiple physical connections may be inconvenient.

Bruce

I now configure serial consoles using device flags.  Bit 0x20 does
the same thing as the current COMCONSOLE except it can be configured
at boot time.  Bit 0x40 reserves the console for specialized low level
use (e.g., for gdb, which currently just grabs port 0 without checking
it it is available).  Bit 0x10 must now be set to use a port for a
(high level) console.  Setting it for sio0 gives the current default.
Setting it for other sio ports makes the first enabled one the serial
console.  This will be standard if someone reviews it.

diff -c2 sio.c~ sio.c
*** sio.c~	Fri Jan 17 13:05:08 1997
--- sio.c	Fri Jan 17 19:56:35 1997
***************
*** 116,119 ****
--- 116,122 ----
  #endif /* COM_MULTIPORT */
  
+ #define	COM_CONSOLE(dev)	((dev)->id_flags & 0x10)
+ #define	COM_FORCECONSOLE(dev)	((dev)->id_flags & 0x20)
+ #define	COM_LLCONSOLE(dev)	((dev)->id_flags & 0x40)
  #define	COM_LOSESOUTINTS(dev)	((dev)->id_flags & 0x08)
  #define	COM_NOFIFO(dev)		((dev)->id_flags & 0x02)
***************
*** 341,346 ****
  
  static	int	comconsole = -1;
! static	speed_t	comdefaultrate = CONSPEED;
  static	u_int	com_events;	/* input chars + weighted output completions */
  static	int	sio_timeout;
  static	int	sio_timeouts_until_log;
--- 344,350 ----
  
  static	int	comconsole = -1;
! static	volatile speed_t	comdefaultrate = CONSPEED;
  static	u_int	com_events;	/* input chars + weighted output completions */
+ static	Port_t	siocniobase;
  static	int	sio_timeout;
  static	int	sio_timeouts_until_log;
***************
*** 531,534 ****
--- 536,544 ----
  	}
  
+ 	if (COM_LLCONSOLE(dev)) {
+ 		printf("sio%d: reserved for low-level i/o\n", dev->id_unit);
+ 		return (0);
+ 	}
+ 
  	/*
  	 * If the device is on a multiport card and has an AST/4
***************
*** 582,590 ****
  	 * We don't want to to wait long enough to drain at 2 bps.
  	 */
! 	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
! 	outb(iobase + com_dlbl, COMBRD(9600) & 0xff);
! 	outb(iobase + com_dlbh, (u_int) COMBRD(9600) >> 8);
! 	outb(iobase + com_cfcr, CFCR_8BITS);
! 	DELAY((16 + 1) * 1000000 / (9600 / 10));
  
  	/*
--- 592,604 ----
  	 * We don't want to to wait long enough to drain at 2 bps.
  	 */
! 	if (iobase == siocniobase)
! 		DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
! 	else {
! 		outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
! 		outb(iobase + com_dlbl, COMBRD(9600) & 0xff);
! 		outb(iobase + com_dlbh, (u_int) COMBRD(9600) >> 8);
! 		outb(iobase + com_cfcr, CFCR_8BITS);
! 		DELAY((16 + 1) * 1000000 / (9600 / 10));
! 	}
  
  	/*
***************
*** 2399,2404 ****
  };
  
- static	Port_t	siocniobase;
- 
  static void siocnclose	__P((struct siocnstate *sp));
  static void siocnopen	__P((struct siocnstate *sp));
--- 2447,2450 ----
***************
*** 2545,2563 ****
  	struct consdev	*cp;
  {
! 	int	unit;
! 
! 	/* XXX: ick */
! 	unit = DEV_TO_UNIT(CONUNIT);
! 	siocniobase = CONADDR;
! 
! 	/* make sure hardware exists?  XXX */
! 
! 	/* initialize required fields */
! 	cp->cn_dev = makedev(CDEV_MAJOR, unit);
! #ifdef COMCONSOLE
! 	cp->cn_pri = CN_REMOTE;		/* Force a serial port console */
! #else
! 	cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
! #endif
  }
  
--- 2591,2628 ----
  	struct consdev	*cp;
  {
! 	struct isa_device	*dvp;
! 	int	s;
! 	struct siocnstate	sp;
! 
! 	/*
! 	 * Find our first enabled console, if any.  If it is a high-level
! 	 * console device, then initialize it and return successfully.
! 	 * If it is a low-level console device, then initialize it and
! 	 * return unsuccessfully.  It must be initialized in both cases
! 	 * for early use by console drivers and debuggers.  Initializing
! 	 * the hardware is not necessary in all cases, since the i/o
! 	 * routines initialize it on the fly, but it is necessary if
! 	 * input might arrive while the hardware is switched back to an
! 	 * uninitialized state.  We can't handle multiple console devices
! 	 * yet because our low-level routines don't take a device arg.
! 	 * We trust the user to set the console flags properly so that we
! 	 * don't need to probe.
! 	 */
! 	cp->cn_pri = CN_DEAD;
! 	for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++)
! 		if (dvp->id_driver == &siodriver && dvp->id_enabled
! 		    && COM_CONSOLE(dvp)) {
! 			siocniobase = dvp->id_iobase;
! 			s = spltty();
! 			siocnopen(&sp);
! 			splx(s);
! 			if (!COM_LLCONSOLE(dvp)) {
! 				cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit);
! 				cp->cn_pri = COM_FORCECONSOLE(dvp)
! 					     || boothowto & RB_SERIAL
! 					     ? CN_REMOTE : CN_NORMAL;
! 			}
! 			break;
! 		}
  }
  



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199703150900.UAA30485>