self-documenting source code doesn't need comments / commit messages? ;) On Tue, Dec 08, 2015 at 12:48:07PM -0700, Mike Belopuhov wrote: > CVSROOT: /cvs > Module name: src > Changes by: [email protected] 2015/12/08 12:48:06 > > Modified files: > sys/dev/pv : xenvar.h > > Log message: > /* > * Copyright (c) 2015 Mike Belopuhov > * > * Permission to use, copy, modify, and distribute this software for any > * purpose with or without fee is hereby granted, provided that the above > * copyright notice and this permission notice appear in all copies. > * > * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > */ > > #include <sys/param.h> > #include <sys/systm.h> > #include <sys/atomic.h> > #include <sys/malloc.h> > #include <sys/kernel.h> > #include <sys/device.h> > > #include <machine/bus.h> > #include <machine/cpu.h> > #include <machine/cpufunc.h> > > #include <uvm/uvm_extern.h> > > #include <machine/i82489var.h> > > #include <dev/pv/pvvar.h> > #include <dev/pv/xenreg.h> > #include <dev/pv/xenvar.h> > > struct xen_softc *xen_sc; > > int xen_init_hypercall(struct xen_softc *); > int xen_getversion(struct xen_softc *); > int xen_getfeatures(struct xen_softc *); > int xen_init_info_page(struct xen_softc *); > int xen_init_cbvec(struct xen_softc *); > > int xen_match(struct device *, void *, void *); > void xen_attach(struct device *, struct device *, void *); > void xen_resume(struct device *); > int xen_activate(struct device *, int); > > const struct cfdriver xen_cd = { > NULL, "xen", DV_DULL > }; > > const struct cfattach xen_ca = { > sizeof(struct xen_softc), xen_match, xen_attach, NULL, xen_activate > }; > > int > xen_match(struct device *parent, void *match, void *aux) > { > struct pv_attach_args *pva = aux; > struct pvbus_hv *hv = &pva->pva_hv[PVBUS_XEN]; > > if (hv->hv_base == 0) > return (0); > > return (1); > } > > void > xen_attach(struct device *parent, struct device *self, void *aux) > { > struct pv_attach_args *pva = (struct pv_attach_args *)aux; > struct pvbus_hv *hv = &pva->pva_hv[PVBUS_XEN]; > struct xen_softc *sc = (struct xen_softc *)self; > > sc->sc_base = hv->hv_base; > > printf("\n"); > > if (xen_init_hypercall(sc)) > return; > > /* Wire it up to the global */ > xen_sc = sc; > > if (xen_getversion(sc)) > return; > if (xen_getfeatures(sc)) > return; > > if (xen_init_info_page(sc)) > return; > > xen_init_cbvec(sc); > } > > void > xen_resume(struct device *self) > { > } > > int > xen_activate(struct device *self, int act) > { > int rv = 0; > > switch (act) { > case DVACT_RESUME: > xen_resume(self); > break; > } > return (rv); > } > > int > xen_init_hypercall(struct xen_softc *sc) > { > extern void *xen_hypercall_page; > uint32_t regs[4]; > paddr_t pa; > > /* Get hypercall page configuration MSR */ > CPUID(sc->sc_base + CPUID_OFFSET_XEN_HYPERCALL, > regs[0], regs[1], regs[2], regs[3]); > > /* We don't support more than one hypercall page */ > if (regs[0] != 1) { > printf("%s: requested %d hypercall pages\n", > sc->sc_dev.dv_xname, regs[0]); > return (-1); > } > > sc->sc_hc = &xen_hypercall_page; > > if (!pmap_extract(pmap_kernel(), (vaddr_t)sc->sc_hc, &pa)) { > printf("%s: hypercall page PA extraction failed\n", > sc->sc_dev.dv_xname); > return (-1); > } > wrmsr(regs[1], pa); > > DPRINTF("%s: hypercall page at va %p pa %#lx\n", sc->sc_dev.dv_xname, > sc->sc_hc, pa); > > return (0); > } > > int > xen_hypercall(struct xen_softc *sc, int op, int argc, ...) > { > va_list ap; > ulong argv[5]; > int i; > > if (argc < 0 || argc > 5) > return (-1); > va_start(ap, argc); > for (i = 0; i < argc; i++) > argv[i] = (ulong)va_arg(ap, ulong); > return (xen_hypercallv(sc, op, argc, argv)); > } > > int > xen_hypercallv(struct xen_softc *sc, int op, int argc, ulong *argv) > { > ulong hcall; > int rv = 0; > > hcall = (ulong)sc->sc_hc + op * 32; > > #if defined(XEN_DEBUG) && disabled > { > int i; > > printf("hypercall %d", op); > if (argc > 0) { > printf(", args {"); > for (i = 0; i < argc; i++) > printf(" %#lx", argv[i]); > printf(" }\n"); > } else > printf("\n"); > } > #endif > > switch (argc) { > case 0: { > HYPERCALL_RES1; > __asm__ volatile ( \ > HYPERCALL_LABEL \ > : HYPERCALL_OUT1 \ > : HYPERCALL_PTR(hcall) \ > : HYPERCALL_CLOBBER \ > ); > HYPERCALL_RET(rv); > break; > } > case 1: { > HYPERCALL_RES1; HYPERCALL_RES2; > HYPERCALL_ARG1(argv[0]); > __asm__ volatile ( \ > HYPERCALL_LABEL \ > : HYPERCALL_OUT1 HYPERCALL_OUT2 \ > : HYPERCALL_IN1 \ > , HYPERCALL_PTR(hcall) \ > : HYPERCALL_CLOBBER \ > ); > HYPERCALL_RET(rv); > break; > } > case 2: { > HYPERCALL_RES1; HYPERCALL_RES2; HYPERCALL_RES3; > HYPERCALL_ARG1(argv[0]); HYPERCALL_ARG2(argv[1]); > __asm__ volatile ( \ > HYPERCALL_LABEL \ > : HYPERCALL_OUT1 HYPERCALL_OUT2 \ > HYPERCALL_OUT3 \ > : HYPERCALL_IN1 HYPERCALL_IN2 \ > , HYPERCALL_PTR(hcall) \ > : HYPERCALL_CLOBBER \ > ); > HYPERCALL_RET(rv); > break; > } > case 3: { > HYPERCALL_RES1; HYPERCALL_RES2; HYPERCALL_RES3; > HYPERCALL_RES4; > HYPERCALL_ARG1(argv[0]); HYPERCALL_ARG2(argv[1]); > HYPERCALL_ARG3(argv[2]); > __asm__ volatile ( \ > HYPERCALL_LABEL \ > : HYPERCALL_OUT1 HYPERCALL_OUT2 \ > HYPERCALL_OUT3 HYPERCALL_OUT4 \ > : HYPERCALL_IN1 HYPERCALL_IN2 \ > HYPERCALL_IN3 \ > , HYPERCALL_PTR(hcall) \ > : HYPERCALL_CLOBBER \ > ); > HYPERCALL_RET(rv); > break; > } > case 4: { > HYPERCALL_RES1; HYPERCALL_RES2; HYPERCALL_RES3; > HYPERCALL_RES4; HYPERCALL_RES5; > HYPERCALL_ARG1(argv[0]); HYPERCALL_ARG2(argv[1]); > HYPERCALL_ARG3(argv[2]); HYPERCALL_ARG4(argv[3]); > __asm__ volatile ( \ > HYPERCALL_LABEL \ > : HYPERCALL_OUT1 HYPERCALL_OUT2 \ > HYPERCALL_OUT3 HYPERCALL_OUT4 \ > HYPERCALL_OUT5 \ > : HYPERCALL_IN1 HYPERCALL_IN2 \ > HYPERCALL_IN3 HYPERCALL_IN4 \ > , HYPERCALL_PTR(hcall) \ > : HYPERCALL_CLOBBER \ > ); > HYPERCALL_RET(rv); > break; > } > case 5: { > HYPERCALL_RES1; HYPERCALL_RES2; HYPERCALL_RES3; > HYPERCALL_RES4; HYPERCALL_RES5; HYPERCALL_RES6; > HYPERCALL_ARG1(argv[0]); HYPERCALL_ARG2(argv[1]); > HYPERCALL_ARG3(argv[2]); HYPERCALL_ARG4(argv[3]); > HYPERCALL_ARG5(argv[4]); > __asm__ volatile ( \ > HYPERCALL_LABEL \ > : HYPERCALL_OUT1 HYPERCALL_OUT2 \ > HYPERCALL_OUT3 HYPERCALL_OUT4 \ > HYPERCALL_OUT5 HYPERCALL_OUT6 \ > : HYPERCALL_IN1 HYPERCALL_IN2 \ > HYPERCALL_IN3 HYPERCALL_IN4 \ > HYPERCALL_IN5 \ > , HYPERCALL_PTR(hcall) \ > : HYPERCALL_CLOBBER \ > ); > HYPERCALL_RET(rv); > break; > } > default: > DPRINTF("%s: wrong number of arguments: %d\n", __func__, argc); > rv = -1; > break; > } > return (rv); > } > > int > xen_getversion(struct xen_softc *sc) > { > char buf[16]; > int version; > ulong argv[2] = { XENVER_extraversion, (ulong)&buf[0] }; > int argc = 2; > > memset(buf, 0, sizeof(buf)); > if ((version = xen_hypercall(sc, xen_version, 1, XENVER_version)) < 0) { > printf("%s: failed to fetch version\n", sc->sc_dev.dv_xname); > return (-1); > } > if (xen_hypercallv(sc, xen_version, argc, argv) < 0) { > printf("%s: failed to fetch extended version\n", > sc->sc_dev.dv_xname); > return (-1); > } > printf("%s: version %d.%d%s\n", sc->sc_dev.dv_xname, > version >> 16, version & 0xffff, buf); > return (0); > } > > int > xen_getfeatures(struct xen_softc *sc) > { > struct xen_feature_info xfi; > ulong argv[2] = { XENVER_get_features, (ulong)&xfi }; > int argc = 2; > > memset(&xfi, 0, sizeof(xfi)); > if (xen_hypercallv(sc, xen_version, argc, argv) < 0) { > printf("%s: failed to fetch features\n", sc->sc_dev.dv_xname); > return (-1); > } > sc->sc_features = xfi.submap; > printf("%s: features %b\n", sc->sc_dev.dv_xname, sc->sc_features, > "\20\014DOM0\013PIRQ\012PVCLOCK\011CBVEC\010GNTFLAGS\007HMA" > "\006PTUPD\005PAE4G\004SUPERVISOR\003AUTOPMAP\002WDT\001WPT"); > return (0); > } > > #ifdef XEN_DEBUG > void > xen_print_info_page(void) > { > struct xen_softc *sc = xen_sc; > struct shared_info *s = sc->sc_ipg; > struct vcpu_info *v; > int i; > > membar_sync(); > for (i = 0; i < XEN_LEGACY_MAX_VCPUS; i++) { > v = &s->vcpu_info[i]; > if (!v->evtchn_upcall_pending && !v->evtchn_upcall_mask && > !v->evtchn_pending_sel && !v->time.version && > !v->time.tsc_timestamp && !v->time.system_time && > !v->time.tsc_to_system_mul && !v->time.tsc_shift) > continue; > printf("vcpu%d:\n" > " upcall_pending=%02x upcall_mask=%02x pending_sel=%#lx\n" > " time version=%u tsc=%llu system=%llu\n" > " time mul=%u shift=%d\n" > , i, v->evtchn_upcall_pending, v->evtchn_upcall_mask, > v->evtchn_pending_sel, v->time.version, > v->time.tsc_timestamp, v->time.system_time, > v->time.tsc_to_system_mul, v->time.tsc_shift); > } > printf("pending events: "); > for (i = 0; i < nitems(s->evtchn_pending); i++) { > if (s->evtchn_pending[i] == 0) > continue; > printf(" %d:%#lx", i, s->evtchn_pending[i]); > } > printf("\nmasked events: "); > for (i = 0; i < nitems(s->evtchn_mask); i++) { > if (s->evtchn_mask[i] == 0xffffffffffffffffULL) > continue; > printf(" %d:%#lx", i, s->evtchn_mask[i]); > } > printf("\nwc ver=%u sec=%u nsec=%u\n", s->wc_version, s->wc_sec, > s->wc_nsec); > printf("arch maxpfn=%lu framelist=%lu nmi=%lu\n", s->arch.max_pfn, > s->arch.pfn_to_mfn_frame_list, s->arch.nmi_reason); > } > #endif /* XEN_DEBUG */ > > int > xen_init_info_page(struct xen_softc *sc) > { > struct xen_add_to_physmap xatp; > paddr_t pa; > > sc->sc_ipg = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); > if (sc->sc_ipg == NULL) { > printf("%s: failed to allocate shared info page\n", > sc->sc_dev.dv_xname); > return (-1); > } > if (!pmap_extract(pmap_kernel(), (vaddr_t)sc->sc_ipg, &pa)) { > printf("%s: shared info page PA extraction failed\n", > sc->sc_dev.dv_xname); > free(sc->sc_ipg, M_DEVBUF, PAGE_SIZE); > return (-1); > } > xatp.domid = DOMID_SELF; > xatp.idx = 0; > xatp.space = XENMAPSPACE_shared_info; > xatp.gpfn = atop(pa); > if (xen_hypercall(sc, memory_op, 2, XENMEM_add_to_physmap, &xatp)) { > printf("%s: failed to register shared info page\n", > sc->sc_dev.dv_xname); > free(sc->sc_ipg, M_DEVBUF, PAGE_SIZE); > return (-1); > } > DPRINTF("%s: shared info page at va %p pa %#lx\n", sc->sc_dev.dv_xname, > sc->sc_ipg, pa); > return (0); > } > > int > xen_init_cbvec(struct xen_softc *sc) > { > struct xen_hvm_param xhp; > > if ((sc->sc_features & XENFEAT_CBVEC) == 0) > return (ENOENT); > > xhp.domid = DOMID_SELF; > xhp.index = HVM_PARAM_CALLBACK_IRQ; > xhp.value = HVM_CALLBACK_VECTOR(LAPIC_XEN_VECTOR); > if (xen_hypercall(sc, hvm_op, 2, HVMOP_set_param, &xhp)) { > /* Will retry with the xspd(4) PCI interrupt */ > return (ENOENT); > } > DPRINTF("%s: registered callback IDT vector %d\n", > sc->sc_dev.dv_xname, LAPIC_XEN_VECTOR); > > sc->sc_cbvec = 1; > > return (0); > } > > void > xen_intr(void) > { > /* stub */ > } >
--
