Page 2 of 3
Re: Integrated debugger inside kernel
Posted: Wed Jun 23, 2021 4:09 pm
by vvaltchev
Korona wrote:@vvaltchev: Do you have physical hardware where 0x3F8 does not work? On the machines that I tested on (even newer ones), COM1 is still at that port (but COM 2, 3, 4 might not be at their legacy addresses - I have not checked that).
Actually yes, I have an UDOO x86 with two UART controllers, none of them accessible thought the legacy interface. On Linux I also see hidden serial ports on my Lenovo laptop, still not accessible from 0x3f8. That, combined with the fact that hardware today is generally exposed thought enumerable interfaces and that serial ports are not built-in anymore in PCs, but require a PCI card or an USB adapter, made me assume that on almost all the machines in the last 10-15 years, the classic interface won’t work.
But, my perspective is biased by my own experience and can be incorrect in the general case, I don’t know.
Re: Integrated debugger inside kernel
Posted: Wed Jun 23, 2021 4:19 pm
by vvaltchev
Octocontrabass wrote:Well, there you go. Your serial port is using I/O port 0x3F8 and (ISA) IRQ 4.
If the serial port doesn't echo back the data you send when you short pins 2 and 3 together (with nothing else connected), the UART isn't programmed correctly.
Yeah, I’m totally surprised, but Bonfra’s serial port is really available using the classic interface.
Now it’s clear that the problem is either in the way the UART is programmed in his kernel, or in the way the receiver is configured.
@Bonfra, you could check if the receiver is configured correctly by using another OS instead of yours and making sure the communication works both ways. If that’s all OK, the problem is exclusively in your kernel. Let me just throw a theory: maybe you don’t wait the mandatory 2 microseconds in the right places? Such things don’t really matter in VMs, but on real hw, they do.
Re: Integrated debugger inside kernel
Posted: Wed Jun 23, 2021 4:23 pm
by pvc
Bonfra wrote:Do I need to connect together those two pins on their own or does the cable need to be plugged to the other end? it's a bit trivial to shorten them while it's connected. I tried to connect just these two pins without plugging the cable and nothing is sent back, maybe I need to do something else with the other pins?
Short the pins without connecting the other end. I often used metal tweezers to do that
. But it would be safer, for the hardware, to use some kind of resistor (maybe about 100 ohms). For simple 8N1 transmission, only these 2 pins need to be shorted. You would need others if you used hardware flow control. Also, it is possible that the port itself is toast or flaky.
Re: Integrated debugger inside kernel
Posted: Wed Jun 23, 2021 6:04 pm
by Bonfra
vvaltchev wrote:
Let me just throw a theory: maybe you don’t wait the mandatory 2 microseconds in the right places? Such things don’t really matter in VMs, but on real hw, they do.
I use a pause instruction to waste some time, maybe I should read to some blank port instead? This is all the code I use for uart I/O:
Code: Select all
uart_init:
push rax
push rdx
mov dx, 0x3f9
; IER int off
xor al, al
out dx, al
; LCR set divisor mode
mov al, 0x80
add dl, 2
out dx, al
; DLL divisor lo 115200
mov al, 1
sub dl, 3
out dx, al
; DLH divisor hi
xor al, al
inc dl
out dx, al
; FCR fifo off
inc dl
out dx, al
; LCR 8N1, break on
mov al, 0x43
inc dl
out dx, al
; MCR Aux out 2
mov al, 0x8
inc dl
out dx, al
; clear receiver/transmitter
xor al, al
sub dl, 4
in al, dx
pop rax
pop rdx
ret
; Param RDI[low8] => character to put
uart_putc:
push rax
push rcx
push rdx
mov ecx, 10000
mov dx, 0x3fd
.one:
in al, dx
pause
cmp al, 0xff
je .two
dec ecx
jz .two
and al, 0x20
jz .one
mov ax, di
sub dl, 5
out dx, al
.two:
pop rdx
pop rcx
pop rax
ret
uart_getc:
push rdx
xor rax, rax
mov dx, 0x3fd
.one:
pause
in al, dx
and al, 1
jz .one
sub dl, 5
in al, dx
cmp al, 13 ; '\r'
jne .done
mov al, 10 ; '\n'
.done:
pop rdx
ret
very "inspired" from bzt's.
vvaltchev wrote:
you could check if the receiver is configured correctly by using another OS instead of yours and making sure the communication works both ways. If that’s all OK, the problem is exclusively in your kernel.
Tomorrow I'll burn a small Linux distro to test this, anyway I'm going to set the baud rate of the port with `stty` and then just `cat` the port to read and `echo` to write. Is this enough?
Re: Integrated debugger inside kernel
Posted: Wed Jun 23, 2021 6:06 pm
by Bonfra
pvc wrote:
Short the pins without connecting the other end. I often used metal tweezers to do that
. But it would be safer, for the hardware, to use some kind of resistor (maybe about 100 ohms).
Uhm I used an Arduino cable, hope I didn't fry anything XD
Re: Integrated debugger inside kernel
Posted: Thu Jun 24, 2021 1:11 am
by rdos
I don't use ACPI to discover legacy COM-ports, simply because ACPI on older machines often is not available or not usable. It's easy enough to probe serial ports since they can generate interrupts that can be detected. Some BIOS doesn't configure the hardware correctly, so today I reprogram them completely. Legacy COM-ports have a limited number of IO-addresses (I check 3F8, 2F8, 3E8, 2E8, 2A0, and 2A8). For PCI-based COM ports, I check for specific PCI vendor & product combinations. I support two IO-based and one memory-based PCI COM adaptor. There are many PCI addons that require custom drivers, and you probably don't want to support these unless you need to.
The next issue is that practically no modern computer has serial ports, and so debugging using serial ports doesn't seem like a good idea. Sure, there are USB to serial converters, but using those requires a functions USB stack and a functional USB COM driver, and many problems with real hardware are connected to USB. You also need functional OHCI, UHCI, EHCI, XHCI and USB hub implementations to make use of it.
I think a far better method to debug an OS is to use the network interface. At least on many PCs there are real Ethernet connectors and many computers use the same network chipsets (often RTL8169 or compatible). However, this is changing too and today laptops typically don't have an Ethernet connector either, again needing functional USB drivers or Wifi driver (which often have no documentation).
As for kernel debugging, I don't think this should be done remotely at all, rather should be a device-driver integrated with the scheduler and a "sand-box" (panics).
Re: Integrated debugger inside kernel
Posted: Thu Jun 24, 2021 3:20 am
by Bonfra
rdos wrote:
The next issue is that practically no modern computer has serial ports, and so debugging using serial ports doesn't seem like a good idea. Sure, there are USB to serial converters, but using those requires a functions USB stack and a functional USB COM driver, and many problems with real hardware are connected to USB. You also need functional OHCI, UHCI, EHCI, XHCI and USB hub implementations to make use of it.
The computer with my os has the serial port, the other pc where I should receive data does not have it so I use a USB adapter, literally
this cable. could this be the issue?
rdos wrote:
I think a far better method to debug an OS is to use the network interface. At least on many PCs there are real Ethernet connectors and many computers use the same network chipsets (often RTL8169 or compatible).
Can you tell me more about this? Or link some resources I can read?
Re: Integrated debugger inside kernel
Posted: Thu Jun 24, 2021 3:39 am
by pvc
rdos wrote:The next issue is that practically no modern computer has serial ports, and so debugging using serial ports doesn't seem like a good idea.
I would like to disagree. Many modern, 'non-budget' motherboards still have physical serial ports. On server boards serial port is a norm. There are also many PCI/PCIe adapters. Most of these are usually compatible with good old 16550. So I think using serial port for debugging is perfectly good idea. Easy to program and require very little of the OS still functioning, even when most of the OS went kaput.
I use GDB over serial port for real machine debugging and it works just fine on my main, X570 machine (both ways, as debugger and as debugee).
Re: Integrated debugger inside kernel
Posted: Thu Jun 24, 2021 5:11 am
by vvaltchev
Bonfra wrote:I use a pause instruction to waste some time, maybe I should read to some blank port instead?
I believe "pause" is a sort of NOP designed to be used while spinning. I believe you would need (in general) a proper udelay(microseconds) function.
But, I'm not sure at all that's your problem here. After checking some code, it looks to me that you might need udelay() only during the initialization. That's different from the PS/2 controller case I was thinking about where delays are used in many more cases.
Note: I haven't checked your assembly code as I always used a C implementation, using:
https://wiki.osdev.org/Serial_Ports as a starting point.
Bonfra wrote:Tomorrow I'll burn a small Linux distro to test this, anyway I'm going to set the baud rate of the port with `stty` and then just `cat` the port to read and `echo` to write. Is this enough?
I'd would check using minicom at both sides.
Re: Integrated debugger inside kernel
Posted: Thu Jun 24, 2021 5:35 am
by vvaltchev
Bonfra wrote:The computer with my os has the serial port, the other pc where I should receive data does not have it so I use a USB adapter, literally
this cable. could this be the issue?
I don't think that could be the problem. Actually, your cable-adapter seems good to me, as it supports hardware control flow signals like RTS and DTR. I tested a serial-to-usb adapter worse (without HW control flow) than this between two Linux machines and worked great with minicom. Probably, there's a problem somewhere with your code.
Ah, oops, there's ONE MORE THING: on modern Linux kernels (from 4.11), it's not possible anymore from user space to directly write to serial ports (not talking to the usb-adapter side). See:
https://youtu.be/wIQPb1NkZbQ
So, to make the test between the "primary" machine with the USB and the "secondary" machine with the COM port, I believe you'd need, on the secondary machine, to either re-build the Linux kernel without serdev or to use an older Linux kernel or somehow to enable serdev-ttydev (not sure how to do that).
Re: Integrated debugger inside kernel
Posted: Thu Jun 24, 2021 7:12 am
by rdos
pvc wrote:rdos wrote:The next issue is that practically no modern computer has serial ports, and so debugging using serial ports doesn't seem like a good idea.
I would like to disagree. Many modern, 'non-budget' motherboards still have physical serial ports. On server boards serial port is a norm. There are also many PCI/PCIe adapters. Most of these are usually compatible with good old 16550. So I think using serial port for debugging is perfectly good idea. Easy to program and require very little of the OS still functioning, even when most of the OS went kaput.
I use GDB over serial port for real machine debugging and it works just fine on my main, X570 machine (both ways, as debugger and as debugee).
Maybe if we talk about stationary computers, particularly if you can build them yourself then you can always find a motherboard with a real serial port (and a PS/2 port). However, if you prefer portable computers, then basically none have real serial ports.
I also disagree that a serial port can be used with GDB when the kernel goes kaput. In those cases, the IRQs might not work, and you might not have a scheduler that is running, and so the stub in your OS is likely to be out of order too.
I have an option to link a serial port to the panic monitor and that way simulate a keyboard, but that's the only case when I use this. In this case, I actually poll the serial port since I cannot rely on IRQs working in the panic monitor. OTOH, it would be possible to add support for attaching the Watcom debugger through a serial port to get symbolic information for the currently running code and even trace it. However, this is post-mortem debugging and cannot be used for more normal debugging as the kernel is no longer running.
I could build a trap for debugging over a serial port using Watcom's wdw debugger, but that will slow down things considerably compared to using the network. I don't support attaching the debugger to the kernel, but an application could step into kernel space and debug C-based device drivers that way. However, my application debugger doesn't freeze the complete application when debugging, rather only stops debugged threads. That's also why it can step into the kernel without freezing the kernel.
Re: Integrated debugger inside kernel
Posted: Fri Jun 25, 2021 3:58 am
by Bonfra
I tried the wiki's code for initialization and it returns error; that thing where it tries to write to the port and read back fails.
So I tried to boot a small Linux distro in that computer to test the serial port but it does not show up
vvaltchev wrote:Ah, oops, there's ONE MORE THING: on modern Linux kernels (from 4.11), it's not possible anymore from user space to directly write to serial ports (not talking to the usb-adapter side)
I think this is the reason.
But knowing the initialization piece of code from the wiki fails is something to work right?
Re: Integrated debugger inside kernel
Posted: Fri Jun 25, 2021 11:51 am
by vvaltchev
Bonfra wrote:But knowing the initialization piece of code from the wiki fails is something to work right?
Well, yeah.. but until you test that everything works using a well-known reliable implementation on both sides, there's always the risk that you might be focusing on the wrong problem. Just pick up an old Linux and try a two-way communication using minicom.
Re: Integrated debugger inside kernel
Posted: Fri Jun 25, 2021 12:30 pm
by nexos
vvaltchev wrote:Ah, oops, there's ONE MORE THING: on modern Linux kernels (from 4.11), it's not possible anymore from user space to directly write to serial ports
Why in the world did they do that? Some people still use serial ports! Anyway, @Bonfra, try testing the serial code in QEMU and see if anything gets sent to the serial monitor.
Re: Integrated debugger inside kernel
Posted: Fri Jun 25, 2021 3:44 pm
by vvaltchev
nexos wrote:Why in the world did they do that? Some people still use serial ports!
Watch this for the whole story:
https://youtu.be/wIQPb1NkZbQ
Briefly, there are uses cases of multiple applications using the serial port, so multiplexing must be done in user space but, at any moment, an "evil" program can always mess up everything by writing directly to the serial port (e.g. /dev/ttyS0). They wanted to clean that up, by treating the serial ports as buses, like USB. Now, you need custom driver to communicate with each kind of serial device at the other side. But, in theory, there is still a way to use the serial ports as TTY, just it's not as straightforward as it was before.
nexos wrote:Anyway, @Bonfra, try testing the serial code in QEMU and see if anything gets sent to the serial monitor.
In my understanding, his code already works on QEMU. The problem is only with real hardware.