Serial input on any CPU needs either polling (bad) or interrupts.
In good ARM type designs, the serial port "driver" software has a (ring) buffer, in RAM, that being software than has two indexes into the buffer: read and write.
When the hardware UART's receive FIFO buffer (typically 2-8 bytes), gets nearly full, it requests an interrupt from the CPU. A few microseconds later (see note below), the CPU saves the current state of registers and executes the interrupt handler (service routine, or ISR). The ISR (should) copy the bytes in the FIFO of the UART to the ring buffer in RAM. Then dismiss the interrupt and return to the executing program.
If the ISR finds that the ring buffer is full (i.e., the write index is (would be) equal to the read index), then the ISR has no choice but to discard the data from the UART, and set a buffer-overrun flag. This flag is sometimes not implemented or is ignored by the application.
When ISR(s) are not running, the application must read from the ring buffer to prevent overrun.
Typically, ISRs use on the order of < 1% of the CPU time.
Some common gotcha's here:
1. Some program somewhere turns off interrupts for too long, so that the FIFO in the hardware UART fills but cannot get the CPU to take the interrupt. One cannot have another I/O software or ISR loop and leave interrupts block too long. This happens only on really badly designed software or ISRs. Arduino's libraries have gotten better, but way back, they had bad code for this case. Misuse of the "noInterrupts()" function can cause this too.
2. The application might choose to always read just one byte at a time from the serial port. This causes a lot of overhead and reduces the net throughput of the data consumer (app). At lower baud rates, this not so much of an issue, as in the classic GPS "NMEA" data reader methods.
3. The producer streams bytes on the UART output, and if the reading side gets out of byte-boundary sync (start/stop bit detection), invalid data is put in the UART receive FIFO. This commonly happens if the incoming stream is uncontrolled and a constant blast, and the reading side starts up mid-stream and the UART cannot find the correct boundaries. The only cure I know of is to either tell the sender to stop for a bit (2 byte times or so), or ensure the sender always has no data flow for 2 byte times quite frequently (e.g., in between application layer "packets").
So interrupts are necessary because the FIFO in the hardware is small.
Fancier chips like the ARMs and bigboy chips can do direct memory access (DMA) for the UART (and other I/O). With DMA, data is moved by hardware from the (UART) to RAM without interrupts. But there are tradeoffs on when to interrupt the CPU, e.g., no data for x amount of time vs DMA complete for (e.g.) 1000 bytes, etc. Sometimes the 1000 byte method isn't what the app needs because of the app's data packet size and rate. So there are many scenarios.
But for UARTs with a FIFO, the interrupt rate is a fraction of the received byte rate, e.g., an 8 byte FIFO set to interrupt at 6 bytes-full, has an interrupt rate of 1/6th of the byte rate (and the bit rate is 8 times the byte rate, plus UART start/stop bytes, so a byte takes 10 bit times).
At 115200 baud and up, this is good.
Some badly designed ISR software does not enable use of FIFOs and gets an interrupt for every byte. OK at lower baud rates, but adds CPU overhead vs. the above 1/6th type reduction.
Cheap/old microprocessors have no FIFO.
BTW, there are FIFOs on the transmit side of the UART too.. so the interrupt rate is reduced for this case too, assuming the ISR uses the TX FIFO. Using DMA for transmit is easier because the ISR can know exactly how many bytes are in a buffer waiting to go.
But likely, DMA on typical low cost microprocessor UARTs isn't needed.
DMA is great for high speed transfers via SPI, e.g., for an SPI interface to an ethernet controller like the Wiz820 for the Teensy. That's because bytes/sec is really high at ethernet speeds.
I believe that the Teensy's all use the UARTs' FIFO if possible. The Teensy 3.0 had, IIRC, only one UART equipped with FIFOs and Teensy 3.1 has more (or all UARTS on T3.1 have FIFOs), and Paul's ISRs do use them properly.