1240912Sneel/*-
2240912Sneel * Copyright (c) 2012 NetApp, Inc.
3240912Sneel * All rights reserved.
4240912Sneel *
5240912Sneel * Redistribution and use in source and binary forms, with or without
6240912Sneel * modification, are permitted provided that the following conditions
7240912Sneel * are met:
8240912Sneel * 1. Redistributions of source code must retain the above copyright
9240912Sneel *    notice, this list of conditions and the following disclaimer.
10240912Sneel * 2. Redistributions in binary form must reproduce the above copyright
11240912Sneel *    notice, this list of conditions and the following disclaimer in the
12240912Sneel *    documentation and/or other materials provided with the distribution.
13240912Sneel *
14240912Sneel * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15240912Sneel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16240912Sneel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17240912Sneel * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18240912Sneel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19240912Sneel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20240912Sneel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21240912Sneel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22240912Sneel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23240912Sneel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24240912Sneel * SUCH DAMAGE.
25240912Sneel *
26240912Sneel * $FreeBSD: releng/11.0/usr.sbin/bhyve/spinup_ap.c 263432 2014-03-20 18:15:37Z neel $
27240912Sneel */
28240912Sneel
29240912Sneel#include <sys/cdefs.h>
30240912Sneel__FBSDID("$FreeBSD: releng/11.0/usr.sbin/bhyve/spinup_ap.c 263432 2014-03-20 18:15:37Z neel $");
31240912Sneel
32240912Sneel#include <sys/param.h>
33240912Sneel#include <sys/types.h>
34240912Sneel
35240912Sneel#include <machine/vmm.h>
36240912Sneel#include <vmmapi.h>
37240912Sneel
38240912Sneel#include <stdio.h>
39240912Sneel#include <stdlib.h>
40240912Sneel#include <assert.h>
41240912Sneel
42244167Sgrehan#include "bhyverun.h"
43240912Sneel#include "spinup_ap.h"
44240912Sneel
45240912Sneelstatic void
46240912Sneelspinup_ap_realmode(struct vmctx *ctx, int newcpu, uint64_t *rip)
47240912Sneel{
48240912Sneel	int vector, error;
49240912Sneel	uint16_t cs;
50240912Sneel	uint64_t desc_base;
51240912Sneel	uint32_t desc_limit, desc_access;
52240912Sneel
53240912Sneel	vector = *rip >> PAGE_SHIFT;
54240912Sneel	*rip = 0;
55240912Sneel
56240912Sneel	/*
57240912Sneel	 * Update the %cs and %rip of the guest so that it starts
58240912Sneel	 * executing real mode code at at 'vector << 12'.
59240912Sneel	 */
60240912Sneel	error = vm_set_register(ctx, newcpu, VM_REG_GUEST_RIP, *rip);
61240912Sneel	assert(error == 0);
62240912Sneel
63240912Sneel	error = vm_get_desc(ctx, newcpu, VM_REG_GUEST_CS, &desc_base,
64240912Sneel			    &desc_limit, &desc_access);
65240912Sneel	assert(error == 0);
66240912Sneel
67240912Sneel	desc_base = vector << PAGE_SHIFT;
68240912Sneel	error = vm_set_desc(ctx, newcpu, VM_REG_GUEST_CS,
69240912Sneel			    desc_base, desc_limit, desc_access);
70240912Sneel	assert(error == 0);
71240912Sneel
72240912Sneel	cs = (vector << PAGE_SHIFT) >> 4;
73240912Sneel	error = vm_set_register(ctx, newcpu, VM_REG_GUEST_CS, cs);
74240912Sneel	assert(error == 0);
75240912Sneel}
76240912Sneel
77240912Sneelint
78240912Sneelspinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip)
79240912Sneel{
80240912Sneel	int error;
81240912Sneel
82240912Sneel	assert(newcpu != 0);
83240912Sneel	assert(newcpu < guest_ncpus);
84240912Sneel
85240912Sneel	error = vcpu_reset(ctx, newcpu);
86240912Sneel	assert(error == 0);
87240912Sneel
88256645Sneel	fbsdrun_set_capabilities(ctx, newcpu);
89240912Sneel
90240912Sneel	/*
91245020Sneel	 * Enable the 'unrestricted guest' mode for 'newcpu'.
92245020Sneel	 *
93245020Sneel	 * Set up the processor state in power-on 16-bit mode, with the CS:IP
94245020Sneel	 * init'd to the specified low-mem 4K page.
95240912Sneel	 */
96240912Sneel	error = vm_set_capability(ctx, newcpu, VM_CAP_UNRESTRICTED_GUEST, 1);
97245020Sneel	assert(error == 0);
98240912Sneel
99245020Sneel	spinup_ap_realmode(ctx, newcpu, &rip);
100245020Sneel
101263432Sneel	fbsdrun_addcpu(ctx, vcpu, newcpu, rip);
102240912Sneel
103240912Sneel	return (newcpu);
104240912Sneel}
105