1221828Sgrehan/*- 2221828Sgrehan * Copyright (c) 2011 NetApp, Inc. 3221828Sgrehan * All rights reserved. 4221828Sgrehan * 5221828Sgrehan * Redistribution and use in source and binary forms, with or without 6221828Sgrehan * modification, are permitted provided that the following conditions 7221828Sgrehan * are met: 8221828Sgrehan * 1. Redistributions of source code must retain the above copyright 9221828Sgrehan * notice, this list of conditions and the following disclaimer. 10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer in the 12221828Sgrehan * documentation and/or other materials provided with the distribution. 13221828Sgrehan * 14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17221828Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24221828Sgrehan * SUCH DAMAGE. 25221828Sgrehan * 26221828Sgrehan * $FreeBSD$ 27221828Sgrehan */ 28221828Sgrehan 29221828Sgrehan#include <sys/cdefs.h> 30221828Sgrehan__FBSDID("$FreeBSD$"); 31221828Sgrehan 32221828Sgrehan#include <sys/param.h> 33221828Sgrehan#include <sys/systm.h> 34223621Sgrehan#include <sys/smp.h> 35221828Sgrehan 36240772Sneel#include <x86/specialreg.h> 37243640Sneel#include <x86/apicreg.h> 38240772Sneel 39221828Sgrehan#include <machine/vmm.h> 40221828Sgrehan#include "vmm_ipi.h" 41221828Sgrehan#include "vmm_lapic.h" 42221828Sgrehan#include "vlapic.h" 43221828Sgrehan 44221828Sgrehanint 45221828Sgrehanlapic_pending_intr(struct vm *vm, int cpu) 46221828Sgrehan{ 47221828Sgrehan struct vlapic *vlapic; 48221828Sgrehan 49221828Sgrehan vlapic = vm_lapic(vm, cpu); 50221828Sgrehan 51221828Sgrehan return (vlapic_pending_intr(vlapic)); 52221828Sgrehan} 53221828Sgrehan 54221828Sgrehanvoid 55221828Sgrehanlapic_intr_accepted(struct vm *vm, int cpu, int vector) 56221828Sgrehan{ 57221828Sgrehan struct vlapic *vlapic; 58221828Sgrehan 59221828Sgrehan vlapic = vm_lapic(vm, cpu); 60221828Sgrehan 61221828Sgrehan vlapic_intr_accepted(vlapic, vector); 62221828Sgrehan} 63221828Sgrehan 64221828Sgrehanint 65221828Sgrehanlapic_set_intr(struct vm *vm, int cpu, int vector) 66221828Sgrehan{ 67221828Sgrehan struct vlapic *vlapic; 68221828Sgrehan 69221828Sgrehan if (cpu < 0 || cpu >= VM_MAXCPU) 70221828Sgrehan return (EINVAL); 71221828Sgrehan 72221828Sgrehan if (vector < 32 || vector > 255) 73221828Sgrehan return (EINVAL); 74221828Sgrehan 75221828Sgrehan vlapic = vm_lapic(vm, cpu); 76221828Sgrehan vlapic_set_intr_ready(vlapic, vector); 77221828Sgrehan 78221828Sgrehan vm_interrupt_hostcpu(vm, cpu); 79221828Sgrehan 80221828Sgrehan return (0); 81221828Sgrehan} 82221828Sgrehan 83241766Sneelint 84221828Sgrehanlapic_timer_tick(struct vm *vm, int cpu) 85221828Sgrehan{ 86221828Sgrehan struct vlapic *vlapic; 87221828Sgrehan 88221828Sgrehan vlapic = vm_lapic(vm, cpu); 89221828Sgrehan 90241766Sneel return (vlapic_timer_tick(vlapic)); 91221828Sgrehan} 92240772Sneel 93240772Sneelstatic boolean_t 94240772Sneelx2apic_msr(u_int msr) 95240772Sneel{ 96240772Sneel if (msr >= 0x800 && msr <= 0xBFF) 97240772Sneel return (TRUE); 98240772Sneel else 99240772Sneel return (FALSE); 100240772Sneel} 101240772Sneel 102240772Sneelstatic u_int 103240772Sneelx2apic_msr_to_regoff(u_int msr) 104240772Sneel{ 105240772Sneel 106240772Sneel return ((msr - 0x800) << 4); 107240772Sneel} 108240772Sneel 109240772Sneelboolean_t 110240772Sneellapic_msr(u_int msr) 111240772Sneel{ 112240772Sneel 113240772Sneel if (x2apic_msr(msr) || (msr == MSR_APICBASE)) 114240772Sneel return (TRUE); 115240772Sneel else 116240772Sneel return (FALSE); 117240772Sneel} 118240772Sneel 119240772Sneelint 120240772Sneellapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval) 121240772Sneel{ 122243650Sneel int error; 123243650Sneel u_int offset; 124240772Sneel struct vlapic *vlapic; 125240772Sneel 126240772Sneel vlapic = vm_lapic(vm, cpu); 127240772Sneel 128240772Sneel if (msr == MSR_APICBASE) { 129240772Sneel *rval = vlapic_get_apicbase(vlapic); 130243650Sneel error = 0; 131243650Sneel } else { 132243650Sneel offset = x2apic_msr_to_regoff(msr); 133243650Sneel error = vlapic_op_mem_read(vlapic, offset, DWORD, rval); 134243650Sneel } 135240772Sneel 136243650Sneel return (error); 137240772Sneel} 138240772Sneel 139240772Sneelint 140240772Sneellapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t val) 141240772Sneel{ 142243650Sneel int error; 143243650Sneel u_int offset; 144240772Sneel struct vlapic *vlapic; 145240772Sneel 146240772Sneel vlapic = vm_lapic(vm, cpu); 147240772Sneel 148240772Sneel if (msr == MSR_APICBASE) { 149240772Sneel vlapic_set_apicbase(vlapic, val); 150243650Sneel error = 0; 151243650Sneel } else { 152243650Sneel offset = x2apic_msr_to_regoff(msr); 153243650Sneel error = vlapic_op_mem_write(vlapic, offset, DWORD, val); 154243650Sneel } 155240772Sneel 156243650Sneel return (error); 157240772Sneel} 158240941Sneel 159240941Sneelint 160243640Sneellapic_mmio_write(void *vm, int cpu, uint64_t gpa, uint64_t wval, int size, 161243640Sneel void *arg) 162240941Sneel{ 163243640Sneel int error; 164243640Sneel uint64_t off; 165240941Sneel struct vlapic *vlapic; 166240941Sneel 167243640Sneel off = gpa - DEFAULT_APIC_BASE; 168240941Sneel 169240941Sneel /* 170243640Sneel * Memory mapped local apic accesses must be 4 bytes wide and 171243640Sneel * aligned on a 16-byte boundary. 172240941Sneel */ 173243640Sneel if (size != 4 || off & 0xf) 174243640Sneel return (EINVAL); 175240941Sneel 176243640Sneel vlapic = vm_lapic(vm, cpu); 177243640Sneel error = vlapic_op_mem_write(vlapic, off, DWORD, wval); 178243640Sneel return (error); 179243640Sneel} 180240941Sneel 181243640Sneelint 182243640Sneellapic_mmio_read(void *vm, int cpu, uint64_t gpa, uint64_t *rval, int size, 183243640Sneel void *arg) 184243640Sneel{ 185243640Sneel int error; 186243640Sneel uint64_t off; 187243640Sneel struct vlapic *vlapic; 188240941Sneel 189243640Sneel off = gpa - DEFAULT_APIC_BASE; 190240941Sneel 191243640Sneel /* 192243640Sneel * Memory mapped local apic accesses must be 4 bytes wide and 193243640Sneel * aligned on a 16-byte boundary. 194243640Sneel */ 195243640Sneel if (size != 4 || off & 0xf) 196243640Sneel return (EINVAL); 197240941Sneel 198243640Sneel vlapic = vm_lapic(vm, cpu); 199243640Sneel error = vlapic_op_mem_read(vlapic, off, DWORD, rval); 200243640Sneel return (error); 201240941Sneel} 202