From 9027aab0fb539636a6ae5e8deedab7fb6bf3d2fa Mon Sep 17 00:00:00 2001 From: mikeb Date: Wed, 17 Aug 2016 17:39:41 +0000 Subject: [PATCH] Sync up monitor trigger groups handling to the upstream Replace hand rolled atomic bit operations and use MI ones from DRM and convert event matrixes to arrays of longs. --- sys/dev/pv/hyperv.c | 33 ++++++++++++++++----------------- sys/dev/pv/hypervreg.h | 7 ++++++- sys/dev/pv/hypervvar.h | 39 ++++++++++++++++----------------------- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/sys/dev/pv/hyperv.c b/sys/dev/pv/hyperv.c index be9bc9747f2..2ebdfe83897 100644 --- a/sys/dev/pv/hyperv.c +++ b/sys/dev/pv/hyperv.c @@ -533,23 +533,24 @@ hv_event_intr(struct hv_softc *sc) struct vmbus_evtflags *evt; struct cpu_info *ci = curcpu(); int cpu = CPU_INFO_UNIT(ci); - int bit, dword, maxdword, chanid; + int bit, row, maxrow, chanid; struct hv_channel *ch; - uint32_t *revents, pending; + u_long *revents, pending; evt = (struct vmbus_evtflags *)sc->sc_siep[cpu] + VMBUS_SINT_MESSAGE; if ((sc->sc_proto == VMBUS_VERSION_WS2008) || (sc->sc_proto == VMBUS_VERSION_WIN7)) { - if (atomic_clearbit_ptr(&evt->evt_flags[0], 0) == 0) + if (!test_bit(0, &evt->evt_flags[0])) return; - maxdword = VMBUS_CHAN_MAX_COMPAT >> 5; + clear_bit(0, &evt->evt_flags[0]); + maxrow = VMBUS_CHAN_MAX_COMPAT / VMBUS_EVTFLAG_LEN; /* * receive size is 1/2 page and divide that by 4 bytes */ revents = sc->sc_revents; } else { - maxdword = nitems(evt->evt_flags); + maxrow = nitems(evt->evt_flags); /* * On Host with Win8 or above, the event page can be * checked directly to get the id of the channel @@ -558,14 +559,14 @@ hv_event_intr(struct hv_softc *sc) revents = &evt->evt_flags[0]; } - for (dword = 0; dword < maxdword; dword++) { - if (revents[dword] == 0) + for (row = 0; row < maxrow; row++) { + if (revents[row] == 0) continue; - pending = atomic_swap_uint(&revents[dword], 0); + pending = atomic_swap_ulong(&revents[row], 0); for (bit = 0; pending > 0; pending >>= 1, bit++) { if ((pending & 1) == 0) continue; - chanid = (dword << 5) + bit; + chanid = (row * LONG_BIT) + bit; /* vmbus channel protocol message */ if (chanid == 0) continue; @@ -695,9 +696,8 @@ hv_vmbus_connect(struct hv_softc *sc) goto errout; } - sc->sc_wevents = (uint32_t *)sc->sc_events; - sc->sc_revents = (uint32_t *)((caddr_t)sc->sc_events + - (PAGE_SIZE >> 1)); + sc->sc_wevents = (u_long *)sc->sc_events; + sc->sc_revents = (u_long *)((caddr_t)sc->sc_events + (PAGE_SIZE >> 1)); sc->sc_monitor[0] = km_alloc(PAGE_SIZE, &kv_any, &kp_zero, &kd_nowait); if (sc->sc_monitor == NULL) { @@ -1017,8 +1017,8 @@ hv_process_offer(struct hv_softc *sc, struct hv_offer *co) nch->ch_monprm.mp_connid = co->co_chan.chm_connid; if (co->co_chan.chm_flags1 & VMBUS_CHOFFER_FLAG1_HASMNF) { - nch->ch_mgroup = co->co_chan.chm_montrig >> 5; - nch->ch_mindex = co->co_chan.chm_montrig & 0x1f; + nch->ch_mgroup = co->co_chan.chm_montrig / VMBUS_MONTRIG_LEN; + nch->ch_mindex = co->co_chan.chm_montrig % VMBUS_MONTRIG_LEN; nch->ch_flags |= CHF_MONITOR; } @@ -1207,11 +1207,10 @@ hv_channel_setevent(struct hv_softc *sc, struct hv_channel *ch) struct vmbus_mon_trig *mtg; /* Each uint32_t represents 32 channels */ - atomic_setbit_ptr((uint32_t *)sc->sc_wevents + (ch->ch_id >> 5), - ch->ch_id & 31); + set_bit(ch->ch_id, sc->sc_wevents); if (ch->ch_flags & CHF_MONITOR) { mtg = &sc->sc_monitor[1]->mnf_trigs[ch->ch_mgroup]; - atomic_setbit_ptr((uint32_t *)&mtg->mt_pending, ch->ch_mindex); + set_bit(ch->ch_mindex, &mtg->mt_pending); } else hv_intr_signal(sc, &ch->ch_monprm); } diff --git a/sys/dev/pv/hypervreg.h b/sys/dev/pv/hypervreg.h index 93278db266c..70f1db5a17c 100644 --- a/sys/dev/pv/hypervreg.h +++ b/sys/dev/pv/hypervreg.h @@ -302,8 +302,13 @@ struct vmbus_message { * Hyper-V SynIC event flags */ +#define VMBUS_EVTFLAGS_SIZE 256 +#define VMBUS_EVTFLAGS_MAX ((VMBUS_EVTFLAGS_SIZE / LONG_BIT) * 8) +#define VMBUS_EVTFLAG_LEN LONG_BIT +#define VMBUS_EVTFLAG_MASK (LONG_BIT - 1) + struct vmbus_evtflags { - uint32_t evt_flags[64]; + ulong evt_flags[VMBUS_EVTFLAGS_MAX]; } __packed; /* diff --git a/sys/dev/pv/hypervvar.h b/sys/dev/pv/hypervvar.h index ebd23ba3ee5..fb0acbe591e 100644 --- a/sys/dev/pv/hypervvar.h +++ b/sys/dev/pv/hypervvar.h @@ -69,13 +69,10 @@ struct hv_channel { struct hv_guid ch_inst; char ch_ident[38]; - uint8_t ch_mgroup; - uint8_t ch_mindex; - void *ch_ring; uint32_t ch_ring_gpadl; uint32_t ch_ring_npg; - ulong ch_ring_size; + u_long ch_ring_size; struct hv_ring_data ch_wrd; struct hv_ring_data ch_rrd; @@ -92,6 +89,8 @@ struct hv_channel { #define CHF_BATCHED 0x0001 #define CHF_MONITOR 0x0002 + uint8_t ch_mgroup; + uint8_t ch_mindex; struct hv_mon_param ch_monprm __attribute__((aligned(8))); TAILQ_ENTRY(hv_channel) ch_entry; @@ -137,8 +136,8 @@ struct hv_softc { /* Channel port events page */ void *sc_events; - uint32_t *sc_wevents; /* Write events */ - uint32_t *sc_revents; /* Read events */ + u_long *sc_wevents; /* Write events */ + u_long *sc_revents; /* Read events */ /* Monitor pages for parent<->child notifications */ struct vmbus_mnf *sc_monitor[2]; @@ -165,28 +164,22 @@ struct hv_softc { struct ksensor sc_sensor; }; -static inline int -atomic_setbit_ptr(volatile void *ptr, int bit) +static __inline void +clear_bit(u_int b, volatile void *p) { - int obit; - - __asm__ __volatile__ ("lock btsl %2,%1; sbbl %0,%0" : - "=r" (obit), "=m" (*(volatile long *)ptr) : "Ir" (bit) : - "memory"); - - return (obit); + atomic_clearbits_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f)); } -static inline int -atomic_clearbit_ptr(volatile void *ptr, int bit) +static __inline void +set_bit(u_int b, volatile void *p) { - int obit; - - __asm__ __volatile__ ("lock btrl %2,%1; sbbl %0,%0" : - "=r" (obit), "=m" (*(volatile long *)ptr) : "Ir" (bit) : - "memory"); + atomic_setbits_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f)); +} - return (obit); +static __inline int +test_bit(u_int b, volatile void *p) +{ + return !!(((volatile u_int *)p)[b >> 5] & (1 << (b & 0x1f))); } int hv_handle_alloc(struct hv_channel *, void *, uint32_t, uint32_t *); -- 2.20.1