[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: Event delivery and "domain blocking" on PVHv2
On Mon, Jun 15, 2020 at 04:25:57PM +0200, Martin Lucina wrote: > Hi, > > puzzle time: In my continuing explorations of the PVHv2 ABIs for the new > MirageOS Xen stack, I've run into some issues with what looks like missed > deliveries of events on event channels. That would be weird, as other OSes using PVHv2 seem to be fine. > While a simple unikernel that only uses the Xen console and effectively does > for (1..5) { printf("foo"); sleep(1); } works fine, once I plug in the > existing OCaml Xenstore and Netfront code, the behaviour I see is that the > unikernel hangs in random places, blocking as if an event that should have > been delivered has been missed. > > Multiple runs of the unikernel have it block at different places during > Netfront setup, and sometimes it will run as far as a fully setup Netfront, > and then wait for network packets. However, even if it gets that far, > packets are not actually being delivered: > > Solo5: Xen console: port 0x2, ring @0x00000000FEFFF000 > | ___| > __| _ \ | _ \ __ \ > \__ \ ( | | ( | ) | > ____/\___/ _|\___/____/ > Solo5: Bindings version v0.6.5-6-gf4b47d11 > Solo5: Memory map: 256 MB addressable: > Solo5: reserved @ (0x0 - 0xfffff) > Solo5: text @ (0x100000 - 0x28ffff) > Solo5: rodata @ (0x290000 - 0x2e0fff) > Solo5: data @ (0x2e1000 - 0x3fafff) > Solo5: heap >= 0x3fb000 < stack < 0x10000000 > gnttab_init(): pages=1 entries=256 > 2020-06-15 13:42:08 -00:00: INF [net-xen frontend] connect 0 > > > > > Sometimes we hang here > 2020-06-15 13:42:08 -00:00: INF [net-xen frontend] create: id=0 domid=0 > 2020-06-15 13:42:08 -00:00: INF [net-xen frontend] sg:true gso_tcpv4:true > rx_copy:true rx_flip:false smart_poll:false > 2020-06-15 13:42:08 -00:00: INF [net-xen frontend] MAC: 00:16:3e:30:49:52 > > > > > Or here > gnttab_grant_access(): ref=0x8, domid=0x0, addr=0x8f9000, readonly=0 > gnttab_grant_access(): ref=0x9, domid=0x0, addr=0x8fb000, readonly=0 > evtchn_alloc_unbound(remote=0x0) = 0x4 > 2020-06-15 13:42:08 -00:00: INF [ethernet] Connected Ethernet interface > 00:16:3e:30:49:52 > 2020-06-15 13:42:08 -00:00: INF [ARP] Sending gratuitous ARP for 10.0.0.2 > (00:16:3e:30:49:52) > gnttab_grant_access(): ref=0xa, domid=0x0, addr=0x8fd000, readonly=1 > 2020-06-15 13:42:08 -00:00: INF [udp] UDP interface connected on 10.0.0.2 > 2020-06-15 13:42:08 -00:00: INF [tcpip-stack-direct] stack assembled: > mac=00:16:3e:30:49:52,ip=10.0.0.2 > Gntref.get(): Waiting for free grant > Gntref.get(): Waiting for free grant > > > > > The above are also rather odd, but not related to event > > > > > channel delivery, so one problem at a time... > > > > > Once we get this far, packets should be flowing but aren't > > > > > (either way). However, Xenstore is obviously working, as we > > > > > wouldn't get through Netfront setup without it. > > Given that I've essentially re-written the low-level event channel C code, > I'd like to verify that the mechanisms I'm using for event delivery are > indeed the right thing to do on PVHv2. > > For event delivery, I'm registering the upcall with Xen as follows: > > uint64_t val = 32ULL; > val |= (uint64_t)HVM_PARAM_CALLBACK_TYPE_VECTOR << 56; > int rc = hypercall_hvm_set_param(HVM_PARAM_CALLBACK_IRQ, val); > assert(rc == 0); > > i.e. upcalls are to be delivered via IDT vector. This way of event channel injection is slitgly hackish, and I would recommend using HVMOP_set_evtchn_upcall_vector, that way vectors will be properly routed using the lapic. Using HVM_PARAM_CALLBACK_TYPE_VECTOR vectors are injected without setting the IRR/ISR bit in the lapic registers. > Questions: > > 1. Being based on the Solo5 virtio code, the low-level setup code is doing > the "usual" i8259 PIC setup, to remap the PIC IRQs to vectors 32 and above. > Should I be doing this initialisation for Xen PVH at all? Hm, there are no IO-APICs (or legacy PICs) on a PVH domU, so there's not much to route. If Solo5 is thinking it's somehow configuring them it's likely writing to some hole in memory, or to some RAM. IO-APIC presence is signaled on the ACPI MADT table on PVH domU. > I'm not interested > in using the PIC for anything, and all interrupts will be delivered via Xen > event channels. > > 2. Related to the above, the IRQ handler code is ACKing the interrupt after > the handler runs. Should I be doing that? Does ACKing "IRQ" 0 on the PIC > have any interactions with Xen's view of event channels/pending upcalls? Which kind of ACking it's doing? Is it writing to the lapic EOI register? If so that would be OK when using HVMOP_set_evtchn_upcall_vector. If using HVM_PARAM_CALLBACK_TYPE_VECTOR there's nothing to Ack I think. > Next, for a PVHv2, uniprocessor only guest, is the following flow sufficient > to unmask an event channel? > > struct shared_info *s = SHARED_INFO(); > int pending = 0; > > atomic_sync_btc(port, &s->evtchn_mask[0]); > pending = sync_bt(port, &s->evtchn_mask[0]); You should check for pending interrupts on evtchn_pending, not evtchn_mask. > if (pending) { > /* > * Slow path: > * > * If pending is set here, then there was a race, and we lost the > * upcall. Mask the port again and force an upcall via a call to > * hyperspace. > * > * This should be sufficient for HVM/PVHv2 based on my understanding > of > * Linux drivers/xen/events/events_2l.c. > */ > atomic_sync_bts(port, &s->evtchn_mask[0]); > hypercall_evtchn_unmask(port); > } FWIW, I use the hypercall unconditionally on FreeBSD because I didn't see a performance difference when compared to this method. > Lastly, the old PV-only Mini-OS based stack would do delays ("block the > domain") by doing a HYPERVISOR_set_timer_op(deadline) followed by a > HYPERVISOR_sched_op(SCHEDOP_block,0 ). In the new code, I'm doing the > following (based on what Mini-OS seems to be doing for HVM): > > solo5_time_t deadline = Int64_val(v_deadline); > > if (solo5_clock_monotonic() < deadline) { > hypercall_set_timer_op(deadline); > __asm__ __volatile__ ("hlt" : : : "memory"); > /* XXX: cancel timer_op here if woken up early? */ > } > > Again, is this the right thing to do for PVH? hlt will trap into the hypervisor, so it's fine to use. > As the comment says, do I need to cancel the timer_op? I'm not sure. Keep in mind that a new call to hypercall_set_timer_op will overwrite the previous timer, and hence should be fine I think as long as you are using the one-shot timer. > I understood the > semantics to be "fire once at/after the time deadline is reached", if that > is indeed the case then with my current VIRQ_TIMER handler which does > nothing in the interrupt context and has no side effects I should be fine. I have no idea how Solo5 works, maybe you should re-set the timer to the next deadline in the handler? Or that's fine because the timer is always set before blocking. > I can also post the code that does the actual demuxing of events from Xen > (i.e. the upcall handler), but I've read through that several times now and > I don't think the problem is there; adding diagnostic prints to both the > low-level C event channel code and higher-level OCaml Activations code > confirms that received events are being mapped to their ports correctly. I can take a look at the event channel handler if you want, as you wish. The only weird think I've noticed is the error in the unmask where you seem to use evtchn_mask instead of evtchn_pending. I would also recommend using HVMOP_set_evtchn_upcall_vector instead of HVM_PARAM_CALLBACK_TYPE_VECTOR. In order to make some tools happy just set HVM_PARAM_CALLBACK_TYPE_VECTOR to 1. You can take a look at how Xen does it when running as a guest: http://xenbits.xen.org/gitweb/?p=xen.git;a=blob;f=xen/arch/x86/guest/xen/xen.c;h=2ff63d370a8a12fef166677e2ded7ed82a628ce8;hb=HEAD#l205 Roger.
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |