vmm_lapic.c revision 240772
1/*-
2 * Copyright (c) 2011 NetApp, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/smp.h>
35
36#include <x86/specialreg.h>
37
38#include <machine/vmm.h>
39#include "vmm_ipi.h"
40#include "vmm_lapic.h"
41#include "vlapic.h"
42
43static int
44lapic_write(struct vlapic *vlapic, u_int offset, uint64_t val)
45{
46	int handled;
47
48	if (vlapic_op_mem_write(vlapic, offset, DWORD, val) == 0)
49		handled = 1;
50	else
51		handled = 0;
52
53	return (handled);
54}
55
56static int
57lapic_read(struct vlapic *vlapic, u_int offset, uint64_t *rv)
58{
59	int handled;
60
61	if (vlapic_op_mem_read(vlapic, offset, DWORD, rv) == 0)
62		handled = 1;
63	else
64		handled = 0;
65
66	return (handled);
67}
68
69int
70lapic_pending_intr(struct vm *vm, int cpu)
71{
72	struct vlapic *vlapic;
73
74	vlapic = vm_lapic(vm, cpu);
75
76	return (vlapic_pending_intr(vlapic));
77}
78
79void
80lapic_intr_accepted(struct vm *vm, int cpu, int vector)
81{
82	struct vlapic *vlapic;
83
84	vlapic = vm_lapic(vm, cpu);
85
86	vlapic_intr_accepted(vlapic, vector);
87}
88
89int
90lapic_set_intr(struct vm *vm, int cpu, int vector)
91{
92	struct vlapic *vlapic;
93
94	if (cpu < 0 || cpu >= VM_MAXCPU)
95		return (EINVAL);
96
97	if (vector < 32 || vector > 255)
98		return (EINVAL);
99
100	vlapic = vm_lapic(vm, cpu);
101	vlapic_set_intr_ready(vlapic, vector);
102
103	vm_interrupt_hostcpu(vm, cpu);
104
105	return (0);
106}
107
108void
109lapic_timer_tick(struct vm *vm, int cpu)
110{
111	struct vlapic *vlapic;
112
113	vlapic = vm_lapic(vm, cpu);
114
115	vlapic_timer_tick(vlapic);
116}
117
118static boolean_t
119x2apic_msr(u_int msr)
120{
121	if (msr >= 0x800 && msr <= 0xBFF)
122		return (TRUE);
123	else
124		return (FALSE);
125}
126
127static u_int
128x2apic_msr_to_regoff(u_int msr)
129{
130
131	return ((msr - 0x800) << 4);
132}
133
134boolean_t
135lapic_msr(u_int msr)
136{
137
138	if (x2apic_msr(msr) || (msr == MSR_APICBASE))
139		return (TRUE);
140	else
141		return (FALSE);
142}
143
144int
145lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval)
146{
147	int handled;
148	struct vlapic *vlapic;
149
150	vlapic = vm_lapic(vm, cpu);
151
152	if (msr == MSR_APICBASE) {
153		*rval = vlapic_get_apicbase(vlapic);
154		handled = 1;
155	} else
156		handled = lapic_read(vlapic, x2apic_msr_to_regoff(msr), rval);
157
158	return (handled);
159}
160
161int
162lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t val)
163{
164	int handled;
165	struct vlapic *vlapic;
166
167	vlapic = vm_lapic(vm, cpu);
168
169	if (msr == MSR_APICBASE) {
170		vlapic_set_apicbase(vlapic, val);
171		handled = 1;
172	} else
173		handled = lapic_write(vlapic, x2apic_msr_to_regoff(msr), val);
174
175	return (handled);
176}
177