MFC 300572

hyperv/vmbus: Use busdma(9) for messages and event flags

    And
    - Move message and event flags to vmbus_softc per-cpu data.
    - Get rid of hv_setup_arg, which serves no purpose now.

    MFC after:  1 week
    Sponsored by:       Microsoft OSTC
    Differential Revision:      https://reviews.freebsd.org/D6502
This commit is contained in:
sephe 2016-06-23 05:51:57 +00:00
parent e07e2994d0
commit de6f1cad7b
4 changed files with 74 additions and 60 deletions

View File

@ -336,13 +336,11 @@ vmbus_event_proc(struct vmbus_softc *sc, int cpu)
{
hv_vmbus_synic_event_flags *event;
event = hv_vmbus_g_context.syn_ic_event_page[cpu] +
HV_VMBUS_MESSAGE_SINT;
/*
* On Host with Win8 or above, the event page can be checked directly
* to get the id of the channel that has the pending interrupt.
*/
event = VMBUS_SC_PCPU_GET(sc, event_flag, cpu) + HV_VMBUS_MESSAGE_SINT;
vmbus_event_flags_proc(event->flagsul,
VMBUS_SC_PCPU_GET(sc, event_flag_cnt, cpu));
}
@ -352,9 +350,7 @@ vmbus_event_proc_compat(struct vmbus_softc *sc __unused, int cpu)
{
hv_vmbus_synic_event_flags *event;
event = hv_vmbus_g_context.syn_ic_event_page[cpu] +
HV_VMBUS_MESSAGE_SINT;
event = VMBUS_SC_PCPU_GET(sc, event_flag, cpu) + HV_VMBUS_MESSAGE_SINT;
if (atomic_testandclear_int(&event->flags32[0], 0)) {
vmbus_event_flags_proc(
hv_vmbus_g_connection.recv_interrupt_page,

View File

@ -69,18 +69,16 @@ __FBSDID("$FreeBSD$");
struct vmbus_softc *vmbus_sc;
static int vmbus_inited;
static hv_setup_args setup_args; /* only CPU 0 supported at this time */
static char *vmbus_ids[] = { "VMBUS", NULL };
static void
vmbus_msg_task(void *arg __unused, int pending __unused)
vmbus_msg_task(void *xsc, int pending __unused)
{
struct vmbus_softc *sc = xsc;
hv_vmbus_message *msg;
msg = hv_vmbus_g_context.syn_ic_msg_page[curcpu] +
HV_VMBUS_MESSAGE_SINT;
msg = VMBUS_SC_PCPU_GET(sc, message, curcpu) + HV_VMBUS_MESSAGE_SINT;
for (;;) {
const hv_vmbus_channel_msg_table_entry *entry;
hv_vmbus_channel_msg_header *hdr;
@ -143,7 +141,7 @@ hv_vmbus_isr(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
sc->vmbus_event_proc(sc, cpu);
/* Check if there are actual msgs to be process */
msg_base = hv_vmbus_g_context.syn_ic_msg_page[cpu];
msg_base = VMBUS_SC_PCPU_GET(sc, message, cpu);
msg = msg_base + HV_VMBUS_TIMER_SINT;
/* we call eventtimer process the message */
@ -209,7 +207,7 @@ hv_vector_handler(struct trapframe *trap_frame)
}
static void
vmbus_synic_setup(void *arg)
vmbus_synic_setup(void *arg __unused)
{
struct vmbus_softc *sc = vmbus_get_softc();
int cpu;
@ -219,7 +217,6 @@ vmbus_synic_setup(void *arg)
hv_vmbus_synic_scontrol sctrl;
hv_vmbus_synic_sint shared_sint;
uint64_t version;
hv_setup_args* setup_args = (hv_setup_args *)arg;
cpu = PCPU_GET(cpuid);
@ -228,19 +225,13 @@ vmbus_synic_setup(void *arg)
*/
version = rdmsr(HV_X64_MSR_SVERSION);
hv_vmbus_g_context.syn_ic_msg_page[cpu] =
setup_args->page_buffers[2 * cpu];
hv_vmbus_g_context.syn_ic_event_page[cpu] =
setup_args->page_buffers[2 * cpu + 1];
/*
* Setup the Synic's message page
*/
simp.as_uint64_t = rdmsr(HV_X64_MSR_SIMP);
simp.u.simp_enabled = 1;
simp.u.base_simp_gpa = ((hv_get_phys_addr(
hv_vmbus_g_context.syn_ic_msg_page[cpu])) >> PAGE_SHIFT);
simp.u.base_simp_gpa =
VMBUS_SC_PCPU_GET(sc, message_dma.hv_paddr, cpu) >> PAGE_SHIFT;
wrmsr(HV_X64_MSR_SIMP, simp.as_uint64_t);
@ -249,8 +240,8 @@ vmbus_synic_setup(void *arg)
*/
siefp.as_uint64_t = rdmsr(HV_X64_MSR_SIEFP);
siefp.u.siefp_enabled = 1;
siefp.u.base_siefp_gpa = ((hv_get_phys_addr(
hv_vmbus_g_context.syn_ic_event_page[cpu])) >> PAGE_SHIFT);
siefp.u.base_siefp_gpa =
VMBUS_SC_PCPU_GET(sc, event_flag_dma.hv_paddr, cpu) >> PAGE_SHIFT;
wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
@ -328,6 +319,47 @@ vmbus_synic_teardown(void *arg)
wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
}
static void
vmbus_dma_alloc(struct vmbus_softc *sc)
{
int cpu;
CPU_FOREACH(cpu) {
/*
* Per-cpu messages and event flags.
*/
VMBUS_SC_PCPU_GET(sc, message, cpu) = hyperv_dmamem_alloc(
bus_get_dma_tag(sc->vmbus_dev), PAGE_SIZE, 0, PAGE_SIZE,
VMBUS_SC_PCPU_PTR(sc, message_dma, cpu),
BUS_DMA_WAITOK | BUS_DMA_ZERO);
VMBUS_SC_PCPU_GET(sc, event_flag, cpu) = hyperv_dmamem_alloc(
bus_get_dma_tag(sc->vmbus_dev), PAGE_SIZE, 0, PAGE_SIZE,
VMBUS_SC_PCPU_PTR(sc, event_flag_dma, cpu),
BUS_DMA_WAITOK | BUS_DMA_ZERO);
}
}
static void
vmbus_dma_free(struct vmbus_softc *sc)
{
int cpu;
CPU_FOREACH(cpu) {
if (VMBUS_SC_PCPU_GET(sc, message, cpu) != NULL) {
hyperv_dmamem_free(
VMBUS_SC_PCPU_PTR(sc, message_dma, cpu),
VMBUS_SC_PCPU_GET(sc, message, cpu));
VMBUS_SC_PCPU_GET(sc, message, cpu) = NULL;
}
if (VMBUS_SC_PCPU_GET(sc, event_flag, cpu) != NULL) {
hyperv_dmamem_free(
VMBUS_SC_PCPU_PTR(sc, event_flag_dma, cpu),
VMBUS_SC_PCPU_GET(sc, event_flag, cpu));
VMBUS_SC_PCPU_GET(sc, event_flag, cpu) = NULL;
}
}
}
static int
vmbus_read_ivar(
device_t dev,
@ -560,7 +592,7 @@ static int
vmbus_bus_init(void)
{
struct vmbus_softc *sc;
int i, n, ret, cpu;
int ret, cpu;
char buf[MAXCOMLEN + 1];
cpuset_t cpu_mask;
@ -587,9 +619,6 @@ vmbus_bus_init(void)
CPU_FOREACH(cpu) {
snprintf(buf, sizeof(buf), "cpu%d:hyperv", cpu);
intrcnt_add(buf, VMBUS_SC_PCPU_PTR(sc, intr_cnt, cpu));
for (i = 0; i < 2; i++)
setup_args.page_buffers[2 * cpu + i] = NULL;
}
/*
@ -623,9 +652,9 @@ vmbus_bus_init(void)
"hyperv msg", M_WAITOK, taskqueue_thread_enqueue,
&hv_vmbus_g_context.hv_msg_tq[cpu]);
taskqueue_start_threads(&hv_vmbus_g_context.hv_msg_tq[cpu], 1,
PI_NET, "hvmsg%d", cpu);
PI_NET, "hvmsg%d", cpu);
TASK_INIT(&hv_vmbus_g_context.hv_msg_task[cpu], 0,
vmbus_msg_task, NULL);
vmbus_msg_task, sc);
CPU_SETOF(cpu, &cpu_mask);
TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
@ -634,22 +663,17 @@ vmbus_bus_init(void)
&cpuset_task);
taskqueue_drain(hv_vmbus_g_context.hv_msg_tq[cpu],
&cpuset_task);
/*
* Prepare the per cpu msg and event pages to be called on
* each cpu.
*/
for(i = 0; i < 2; i++) {
setup_args.page_buffers[2 * cpu + i] =
malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
}
}
/*
* Allocate vmbus DMA stuffs.
*/
vmbus_dma_alloc(sc);
if (bootverbose)
printf("VMBUS: Calling smp_rendezvous, smp_started = %d\n",
smp_started);
smp_rendezvous(NULL, vmbus_synic_setup, NULL, &setup_args);
smp_rendezvous(NULL, vmbus_synic_setup, NULL, NULL);
/*
* Connect to VMBus in the root partition
@ -673,13 +697,8 @@ vmbus_bus_init(void)
return (ret);
cleanup1:
/*
* Free pages alloc'ed
*/
for (n = 0; n < 2 * MAXCPU; n++)
if (setup_args.page_buffers[n] != NULL)
free(setup_args.page_buffers[n], M_DEVBUF);
cleanup1:
vmbus_dma_free(sc);
/*
* remove swi and vmbus callback vector;
@ -755,10 +774,7 @@ vmbus_detach(device_t dev)
smp_rendezvous(NULL, vmbus_synic_teardown, NULL, NULL);
for(i = 0; i < 2 * MAXCPU; i++) {
if (setup_args.page_buffers[i] != NULL)
free(setup_args.page_buffers[i], M_DEVBUF);
}
vmbus_dma_free(sc);
/* remove swi */
CPU_FOREACH(i) {

View File

@ -203,8 +203,6 @@ union vmbus_event_flags;
typedef struct {
hv_bool_uint8_t syn_ic_initialized;
struct vmbus_message *syn_ic_msg_page[MAXCPU];
union vmbus_event_flags *syn_ic_event_page[MAXCPU];
/*
* For FreeBSD cpuid to Hyper-V vcpuid mapping.
*/
@ -755,8 +753,4 @@ void hv_et_intr(struct trapframe*);
/* Wait for device creation */
void vmbus_scan(void);
typedef struct {
void *page_buffers[2 * MAXCPU];
} hv_setup_args;
#endif /* __HYPERV_PRIV_H__ */

View File

@ -30,10 +30,18 @@
#define _VMBUS_VAR_H_
#include <sys/param.h>
#include <sys/bus_dma.h>
#include <dev/hyperv/include/hyperv_busdma.h>
struct vmbus_pcpu_data {
int event_flag_cnt; /* # of event flags */
u_long *intr_cnt;
u_long *intr_cnt; /* Hyper-V interrupt counter */
struct vmbus_message *message; /* shared messages */
int event_flag_cnt; /* # of event flags */
union vmbus_event_flags *event_flag; /* shared event flags */
/* Rarely used fields */
struct hyperv_dma message_dma; /* busdma glue */
struct hyperv_dma event_flag_dma; /* busdma glue */
} __aligned(CACHE_LINE_SIZE);
struct vmbus_softc {