Whatever the card reader supports. What EMV call a "kernel" is not what a Linux person would call a "kernel". EMV don't really care, what they care about is that the protocols are followed and that the CHD (Card Holder Data) is protected and that the transactions are properly encrypted at rest and in transit.
So you could write it in Visual Basic if you wanted, but your PCI auditor might have a problem with that. :)
As far as I understand it EMV has L1 and L2 "kernels", then there is an "L3" that is acquirer specific.
When a device is "PCI-PADSS" certified, the L1/L2 kernels are what are tested.
When a merchant is PCI-DSS audited, it is a combination of the PCI-PADSS certification for the device, as well as the L3 layer and other business processing rules around handling the CHD (Card Holder Data). The L3 is supplied by the merchant's acquirer (often with the terminal itself) and the acquirer has had the device validated as part of their PCI audit.
EMV L1 Kernel: The "app" that understands the EMV protocol and data exchanges ("APDUs") between the reader and the card. The equivalent of the PHY chip and ethernet frame handler in ethernet.
EMV L2 Kernel: The "app" that understands the EMV business rules and processing of transaction. The equivalent would be the IP layer in networking land.
EMV L3 Kernel: The specific "acquirer" rules, eg, there is a BIN (Bank Identification Number) accept/deny list that an acquirer will accept. It also has other rules about limits etc that the acquirer imposes. The equivalent would be IPTables in Linux.
PCI-PTS is another one we were concerned with as a terminal vendors, which involved a bunch of stuff around tamper-proofing and tamper-evidence, as well as vetting the cryptographic algorithms in use, some level of source code security evaluation etc. Complicated old business.
I was very proud when my security library, including implementations of all sorts of ANSI X.9 standards, derived-unique-keys-per-transaction, a keystore that was destroyed on tamper, secure program code update mechanisms etc etc passed certification, on a device with 128k of SRAM and 256k of program memory.
Shame it never made it to market. Stupid unicorn company taking on tens of millions in debt and then exploding... still, I got a few trips to China out of it.
So the 'kernel' I wrote was not the one running on the card. 'In the Industry' (which sounds so pretentious!) the core of the EMV logic that runs on a terminal is often referred to as the kernel. It's not much like a real OS kernel!
The kernel I wrote in about 2002/3 was in C and allowed a PC using a dumb reader (with secure PIN pad) to run the transaction, on Windows, Linux or (shudder) Unixware at the time.
Years later in 2014 when I worked on a terminal product the company had bought in a third party kernel, also written in C to run on an embedded MIPs board. There was a platform SDK and a custom gcc variant to build bare-metal executables. You bootstrapped the kernel by passing it a malloc implementation and a couple of hooks to other things like accelerated crypto functions etc, and it provided an API to run the transaction.
I also worked briefly on a contactless terminal product in 2012, which IIRC was C and C++ (old-skool C-like C++) on a proprietary OS of some sort, and they were moving to embedded linux on ARM at the time.
(edit - See also rswall's parallel answer, it's very good. I wrote an EMV L2 kernel in that parlance, and interacted with another.)