blob: 9cf4f8463c4e6b141e69632cd67f2b24965c9757 [file] [log] [blame]
Ken Cox12e364b2014-03-04 07:58:07 -06001/* visorchipset_main.c
2 *
Benjamin Romer6f14cc12015-07-16 12:40:48 -04003 * Copyright (C) 2010 - 2015 UNISYS CORPORATION
Ken Cox12e364b2014-03-04 07:58:07 -06004 * All rights reserved.
5 *
Benjamin Romer6f14cc12015-07-16 12:40:48 -04006 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
Ken Cox12e364b2014-03-04 07:58:07 -06009 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13 * NON INFRINGEMENT. See the GNU General Public License for more
14 * details.
15 */
16
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040017#include <linux/acpi.h>
Erik Arfvidsonc0a14642015-05-05 18:37:06 -040018#include <linux/cdev.h>
Erik Arfvidson46168812015-05-05 18:36:14 -040019#include <linux/ctype.h>
Erik Arfvidsone3420ed2015-05-05 18:36:13 -040020#include <linux/fs.h>
21#include <linux/mm.h>
Ken Cox12e364b2014-03-04 07:58:07 -060022#include <linux/nls.h>
23#include <linux/netdevice.h>
24#include <linux/platform_device.h>
Benjamin Romer90addb02014-05-06 09:58:23 -040025#include <linux/uuid.h>
Benjamin Romer1ba00982015-04-06 10:27:40 -040026#include <linux/crash_dump.h>
Ken Cox12e364b2014-03-04 07:58:07 -060027
David Kershner5f3a7e32015-05-13 13:22:10 -040028#include "channel_guid.h"
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040029#include "controlvmchannel.h"
30#include "controlvmcompletionstatus.h"
31#include "guestlinuxdebug.h"
32#include "periodic_work.h"
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040033#include "version.h"
34#include "visorbus.h"
35#include "visorbus_private.h"
David Kershner5f3a7e32015-05-13 13:22:10 -040036#include "vmcallinterface.h"
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040037
Ken Cox12e364b2014-03-04 07:58:07 -060038#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c
Ken Cox12e364b2014-03-04 07:58:07 -060039
40#define MAX_NAME_SIZE 128
41#define MAX_IP_SIZE 50
42#define MAXOUTSTANDINGCHANNELCOMMAND 256
43#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1
44#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
45
Bhaktipriya Shridhar2c7e1d42015-12-09 20:57:05 +053046#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -040047
48#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000
49
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -040050#define UNISYS_SPAR_LEAF_ID 0x40000000
51
52/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
53#define UNISYS_SPAR_ID_EBX 0x73696e55
54#define UNISYS_SPAR_ID_ECX 0x70537379
55#define UNISYS_SPAR_ID_EDX 0x34367261
56
Jes Sorensenb615d622015-05-05 18:35:38 -040057/*
58 * Module parameters
59 */
Jes Sorensenb615d622015-05-05 18:35:38 -040060static int visorchipset_major;
David Kershner4da33362015-05-05 18:36:39 -040061static int visorchipset_visorbusregwait = 1; /* default is on */
Jes Sorensenb615d622015-05-05 18:35:38 -040062static int visorchipset_holdchipsetready;
Erik Arfvidson46168812015-05-05 18:36:14 -040063static unsigned long controlvm_payload_bytes_buffered;
Tim Sell12c957d2016-03-01 19:45:04 -050064static u32 dump_vhba_bus;
Jes Sorensenb615d622015-05-05 18:35:38 -040065
Erik Arfvidsone3420ed2015-05-05 18:36:13 -040066static int
67visorchipset_open(struct inode *inode, struct file *file)
68{
69 unsigned minor_number = iminor(inode);
70
71 if (minor_number)
72 return -ENODEV;
73 file->private_data = NULL;
74 return 0;
75}
76
77static int
78visorchipset_release(struct inode *inode, struct file *file)
79{
80 return 0;
81}
82
Ken Cox12e364b2014-03-04 07:58:07 -060083/* When the controlvm channel is idle for at least MIN_IDLE_SECONDS,
84* we switch to slow polling mode. As soon as we get a controlvm
85* message, we switch back to fast polling mode.
86*/
87#define MIN_IDLE_SECONDS 10
Jes Sorensen52063ec2015-04-13 10:28:41 -040088static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Erik Arfvidson2ee0d052016-02-08 10:41:44 -050089/* when we got our last controlvm message */
90static unsigned long most_recent_message_jiffies;
David Kershner4da33362015-05-05 18:36:39 -040091static int visorbusregistered;
Ken Cox12e364b2014-03-04 07:58:07 -060092
93#define MAX_CHIPSET_EVENTS 2
Benjamin Romerc2422332014-07-29 15:09:40 -040094static u8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 };
Ken Cox12e364b2014-03-04 07:58:07 -060095
Erik Arfvidson46168812015-05-05 18:36:14 -040096struct parser_context {
97 unsigned long allocbytes;
98 unsigned long param_bytes;
99 u8 *curr;
100 unsigned long bytes_remaining;
101 bool byte_stream;
102 char data[0];
103};
104
Benjamin Romer9232d2d2015-03-16 13:57:57 -0400105static struct delayed_work periodic_controlvm_work;
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400106static DEFINE_SEMAPHORE(notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -0600107
Erik Arfvidsone3420ed2015-05-05 18:36:13 -0400108static struct cdev file_cdev;
109static struct visorchannel **file_controlvm_channel;
Benjamin Romerda021f02015-03-16 13:57:58 -0400110static struct controlvm_message_header g_chipset_msg_hdr;
Benjamin Romer4f44b722015-03-16 13:58:02 -0400111static struct controlvm_message_packet g_devicechangestate_packet;
Ken Cox12e364b2014-03-04 07:58:07 -0600112
Benjamin Romer1390b882015-03-16 13:58:03 -0400113static LIST_HEAD(bus_info_list);
114static LIST_HEAD(dev_info_list);
Ken Cox12e364b2014-03-04 07:58:07 -0600115
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400116static struct visorchannel *controlvm_channel;
Ken Cox12e364b2014-03-04 07:58:07 -0600117
Benjamin Romer84982fb2015-03-16 13:58:07 -0400118/* Manages the request payload in the controlvm channel */
Jes Sorensenc1f834e2015-04-13 10:28:39 -0400119struct visor_controlvm_payload_info {
Dan Williams3103dc02015-08-10 23:07:06 -0400120 u8 *ptr; /* pointer to base address of payload pool */
Benjamin Romer5fc02292014-07-31 12:00:51 -0400121 u64 offset; /* offset from beginning of controlvm
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500122 * channel to beginning of payload * pool
123 */
Benjamin Romerb3c55b12014-07-31 12:00:50 -0400124 u32 bytes; /* number of bytes in payload pool */
Jes Sorensenc1f834e2015-04-13 10:28:39 -0400125};
126
127static struct visor_controlvm_payload_info controlvm_payload_info;
Ken Cox12e364b2014-03-04 07:58:07 -0600128
Ken Cox12e364b2014-03-04 07:58:07 -0600129/* The following globals are used to handle the scenario where we are unable to
130 * offload the payload from a controlvm message due to memory requirements. In
131 * this scenario, we simply stash the controlvm message, then attempt to
132 * process it again the next time controlvm_periodic_work() runs.
133 */
Benjamin Romer7166ed12015-03-16 13:58:38 -0400134static struct controlvm_message controlvm_pending_msg;
Prarit Bhargavac79b28f2015-05-05 18:36:15 -0400135static bool controlvm_pending_msg_valid;
Ken Cox12e364b2014-03-04 07:58:07 -0600136
Ken Cox12e364b2014-03-04 07:58:07 -0600137/* This identifies a data buffer that has been received via a controlvm messages
138 * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation.
139 */
140struct putfile_buffer_entry {
141 struct list_head next; /* putfile_buffer_entry list */
Benjamin Romer317d9612015-03-16 13:57:51 -0400142 struct parser_context *parser_ctx; /* points to input data buffer */
Ken Cox12e364b2014-03-04 07:58:07 -0600143};
144
145/* List of struct putfile_request *, via next_putfile_request member.
146 * Each entry in this list identifies an outstanding TRANSMIT_FILE
147 * conversation.
148 */
Benjamin Romer1eee0012015-03-16 13:58:39 -0400149static LIST_HEAD(putfile_request_list);
Ken Cox12e364b2014-03-04 07:58:07 -0600150
151/* This describes a buffer and its current state of transfer (e.g., how many
152 * bytes have already been supplied as putfile data, and how many bytes are
153 * remaining) for a putfile_request.
154 */
155struct putfile_active_buffer {
156 /* a payload from a controlvm message, containing a file data buffer */
Benjamin Romer317d9612015-03-16 13:57:51 -0400157 struct parser_context *parser_ctx;
Ken Cox12e364b2014-03-04 07:58:07 -0600158 /* points within data area of parser_ctx to next byte of data */
159 u8 *pnext;
160 /* # bytes left from <pnext> to the end of this data buffer */
161 size_t bytes_remaining;
162};
163
164#define PUTFILE_REQUEST_SIG 0x0906101302281211
165/* This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE
166 * conversation. Structs of this type are dynamically linked into
167 * <Putfile_request_list>.
168 */
169struct putfile_request {
170 u64 sig; /* PUTFILE_REQUEST_SIG */
171
172 /* header from original TransmitFile request */
Benjamin Romer98d7b592014-10-23 14:30:26 -0400173 struct controlvm_message_header controlvm_header;
Ken Cox12e364b2014-03-04 07:58:07 -0600174 u64 file_request_number; /* from original TransmitFile request */
175
176 /* link to next struct putfile_request */
177 struct list_head next_putfile_request;
178
179 /* most-recent sequence number supplied via a controlvm message */
180 u64 data_sequence_number;
181
182 /* head of putfile_buffer_entry list, which describes the data to be
183 * supplied as putfile data;
184 * - this list is added to when controlvm messages come in that supply
185 * file data
186 * - this list is removed from via the hotplug program that is actually
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500187 * consuming these buffers to write as file data
188 */
Ken Cox12e364b2014-03-04 07:58:07 -0600189 struct list_head input_buffer_list;
190 spinlock_t req_list_lock; /* lock for input_buffer_list */
191
192 /* waiters for input_buffer_list to go non-empty */
193 wait_queue_head_t input_buffer_wq;
194
195 /* data not yet read within current putfile_buffer_entry */
196 struct putfile_active_buffer active_buf;
197
198 /* <0 = failed, 0 = in-progress, >0 = successful; */
199 /* note that this must be set with req_list_lock, and if you set <0, */
200 /* it is your responsibility to also free up all of the other objects */
201 /* in this struct (like input_buffer_list, active_buf.parser_ctx) */
202 /* before releasing the lock */
203 int completion_status;
204};
205
Ken Cox12e364b2014-03-04 07:58:07 -0600206struct parahotplug_request {
207 struct list_head list;
208 int id;
209 unsigned long expiration;
Benjamin Romer3ab47702014-10-23 14:30:31 -0400210 struct controlvm_message msg;
Ken Cox12e364b2014-03-04 07:58:07 -0600211};
212
Benjamin Romerddf5de52015-03-16 13:58:41 -0400213static LIST_HEAD(parahotplug_request_list);
214static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */
Ken Cox12e364b2014-03-04 07:58:07 -0600215static void parahotplug_process_list(void);
216
217/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
218 * CONTROLVM_REPORTEVENT.
219 */
David Kershner4da33362015-05-05 18:36:39 -0400220static struct visorchipset_busdev_notifiers busdev_notifiers;
Ken Cox12e364b2014-03-04 07:58:07 -0600221
Don Zickusd32517e2015-06-04 09:22:41 -0400222static void bus_create_response(struct visor_device *p, int response);
223static void bus_destroy_response(struct visor_device *p, int response);
Don Zickusa298bc02015-06-04 09:22:42 -0400224static void device_create_response(struct visor_device *p, int response);
225static void device_destroy_response(struct visor_device *p, int response);
226static void device_resume_response(struct visor_device *p, int response);
Ken Cox12e364b2014-03-04 07:58:07 -0600227
Don Zickusa298bc02015-06-04 09:22:42 -0400228static void visorchipset_device_pause_response(struct visor_device *p,
229 int response);
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400230
Benjamin Romer8e3fedd2015-03-16 13:58:43 -0400231static struct visorchipset_busdev_responders busdev_responders = {
Ken Cox12e364b2014-03-04 07:58:07 -0600232 .bus_create = bus_create_response,
233 .bus_destroy = bus_destroy_response,
234 .device_create = device_create_response,
235 .device_destroy = device_destroy_response,
Ken Cox927c7922014-03-05 14:52:25 -0600236 .device_pause = visorchipset_device_pause_response,
Ken Cox12e364b2014-03-04 07:58:07 -0600237 .device_resume = device_resume_response,
238};
239
240/* info for /dev/visorchipset */
Benjamin Romer5aa8ae52015-03-16 13:58:44 -0400241static dev_t major_dev = -1; /**< indicates major num for device */
Ken Cox12e364b2014-03-04 07:58:07 -0600242
Benjamin Romer19f66342014-07-22 09:56:25 -0400243/* prototypes for attributes */
244static ssize_t toolaction_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400245 struct device_attribute *attr, char *buf);
Benjamin Romer19f66342014-07-22 09:56:25 -0400246static ssize_t toolaction_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400247 struct device_attribute *attr,
248 const char *buf, size_t count);
Benjamin Romer19f66342014-07-22 09:56:25 -0400249static DEVICE_ATTR_RW(toolaction);
250
Benjamin Romer54b31222014-07-22 09:56:26 -0400251static ssize_t boottotool_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400252 struct device_attribute *attr, char *buf);
Benjamin Romer54b31222014-07-22 09:56:26 -0400253static ssize_t boottotool_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400254 struct device_attribute *attr, const char *buf,
255 size_t count);
Benjamin Romer54b31222014-07-22 09:56:26 -0400256static DEVICE_ATTR_RW(boottotool);
257
Benjamin Romer422af172014-07-24 14:08:42 -0400258static ssize_t error_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400259 char *buf);
Benjamin Romer422af172014-07-24 14:08:42 -0400260static ssize_t error_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400261 const char *buf, size_t count);
Benjamin Romer422af172014-07-24 14:08:42 -0400262static DEVICE_ATTR_RW(error);
263
264static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400265 char *buf);
Benjamin Romer422af172014-07-24 14:08:42 -0400266static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400267 const char *buf, size_t count);
Benjamin Romer422af172014-07-24 14:08:42 -0400268static DEVICE_ATTR_RW(textid);
269
270static ssize_t remaining_steps_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400271 struct device_attribute *attr, char *buf);
Benjamin Romer422af172014-07-24 14:08:42 -0400272static ssize_t remaining_steps_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400273 struct device_attribute *attr,
274 const char *buf, size_t count);
Benjamin Romer422af172014-07-24 14:08:42 -0400275static DEVICE_ATTR_RW(remaining_steps);
276
Benjamin Romer18b87ed2014-07-24 14:08:43 -0400277static ssize_t chipsetready_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400278 struct device_attribute *attr,
279 const char *buf, size_t count);
Benjamin Romer18b87ed2014-07-24 14:08:43 -0400280static DEVICE_ATTR_WO(chipsetready);
281
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400282static ssize_t devicedisabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400283 struct device_attribute *attr,
284 const char *buf, size_t count);
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400285static DEVICE_ATTR_WO(devicedisabled);
286
287static ssize_t deviceenabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400288 struct device_attribute *attr,
289 const char *buf, size_t count);
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400290static DEVICE_ATTR_WO(deviceenabled);
291
Benjamin Romer19f66342014-07-22 09:56:25 -0400292static struct attribute *visorchipset_install_attrs[] = {
293 &dev_attr_toolaction.attr,
Benjamin Romer54b31222014-07-22 09:56:26 -0400294 &dev_attr_boottotool.attr,
Benjamin Romer422af172014-07-24 14:08:42 -0400295 &dev_attr_error.attr,
296 &dev_attr_textid.attr,
297 &dev_attr_remaining_steps.attr,
Benjamin Romer19f66342014-07-22 09:56:25 -0400298 NULL
299};
300
301static struct attribute_group visorchipset_install_group = {
302 .name = "install",
303 .attrs = visorchipset_install_attrs
304};
305
Benjamin Romer18b87ed2014-07-24 14:08:43 -0400306static struct attribute *visorchipset_guest_attrs[] = {
307 &dev_attr_chipsetready.attr,
308 NULL
309};
310
311static struct attribute_group visorchipset_guest_group = {
312 .name = "guest",
313 .attrs = visorchipset_guest_attrs
314};
315
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400316static struct attribute *visorchipset_parahotplug_attrs[] = {
317 &dev_attr_devicedisabled.attr,
318 &dev_attr_deviceenabled.attr,
319 NULL
320};
321
322static struct attribute_group visorchipset_parahotplug_group = {
323 .name = "parahotplug",
324 .attrs = visorchipset_parahotplug_attrs
325};
326
Benjamin Romer19f66342014-07-22 09:56:25 -0400327static const struct attribute_group *visorchipset_dev_groups[] = {
328 &visorchipset_install_group,
Benjamin Romer18b87ed2014-07-24 14:08:43 -0400329 &visorchipset_guest_group,
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400330 &visorchipset_parahotplug_group,
Benjamin Romer19f66342014-07-22 09:56:25 -0400331 NULL
332};
333
Don Zickus04dacac2015-06-04 09:22:48 -0400334static void visorchipset_dev_release(struct device *dev)
335{
336}
337
Ken Cox12e364b2014-03-04 07:58:07 -0600338/* /sys/devices/platform/visorchipset */
Benjamin Romereb34e872015-03-16 13:58:45 -0400339static struct platform_device visorchipset_platform_device = {
Ken Cox12e364b2014-03-04 07:58:07 -0600340 .name = "visorchipset",
341 .id = -1,
Benjamin Romer19f66342014-07-22 09:56:25 -0400342 .dev.groups = visorchipset_dev_groups,
Don Zickus04dacac2015-06-04 09:22:48 -0400343 .dev.release = visorchipset_dev_release,
Ken Cox12e364b2014-03-04 07:58:07 -0600344};
345
346/* Function prototypes */
Benjamin Romerb3168c72015-03-16 13:58:46 -0400347static void controlvm_respond(struct controlvm_message_header *msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400348 int response);
349static void controlvm_respond_chipset_init(
Benjamin Romerb3168c72015-03-16 13:58:46 -0400350 struct controlvm_message_header *msg_hdr, int response,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400351 enum ultra_chipset_feature features);
352static void controlvm_respond_physdev_changestate(
Benjamin Romerb3168c72015-03-16 13:58:46 -0400353 struct controlvm_message_header *msg_hdr, int response,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400354 struct spar_segment_state state);
Ken Cox12e364b2014-03-04 07:58:07 -0600355
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400356static void parser_done(struct parser_context *ctx);
357
Erik Arfvidson46168812015-05-05 18:36:14 -0400358static struct parser_context *
Jes Sorensenfbf35532015-05-05 18:37:14 -0400359parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
Erik Arfvidson46168812015-05-05 18:36:14 -0400360{
361 int allocbytes = sizeof(struct parser_context) + bytes;
362 struct parser_context *rc = NULL;
363 struct parser_context *ctx = NULL;
Erik Arfvidson46168812015-05-05 18:36:14 -0400364
365 if (retry)
366 *retry = false;
Jes Sorensencc55b5c2015-05-05 18:37:13 -0400367
368 /*
369 * alloc an 0 extra byte to ensure payload is
370 * '\0'-terminated
371 */
372 allocbytes++;
Erik Arfvidson46168812015-05-05 18:36:14 -0400373 if ((controlvm_payload_bytes_buffered + bytes)
374 > MAX_CONTROLVM_PAYLOAD_BYTES) {
375 if (retry)
376 *retry = true;
377 rc = NULL;
378 goto cleanup;
379 }
Erik Arfvidson8c395e72016-02-08 10:41:45 -0500380 ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY);
Erik Arfvidson46168812015-05-05 18:36:14 -0400381 if (!ctx) {
382 if (retry)
383 *retry = true;
384 rc = NULL;
385 goto cleanup;
386 }
387
388 ctx->allocbytes = allocbytes;
389 ctx->param_bytes = bytes;
390 ctx->curr = NULL;
391 ctx->bytes_remaining = 0;
392 ctx->byte_stream = false;
393 if (local) {
394 void *p;
395
396 if (addr > virt_to_phys(high_memory - 1)) {
397 rc = NULL;
398 goto cleanup;
399 }
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500400 p = __va((unsigned long)(addr));
Erik Arfvidson46168812015-05-05 18:36:14 -0400401 memcpy(ctx->data, p, bytes);
402 } else {
Tim Sella8deaef2016-03-01 19:45:02 -0500403 void *mapping = memremap(addr, bytes, MEMREMAP_WB);
Jes Sorensen712c03d2015-05-05 18:36:25 -0400404
Jes Sorensendd412752015-05-05 18:36:26 -0400405 if (!mapping) {
Jes Sorensendd412752015-05-05 18:36:26 -0400406 rc = NULL;
407 goto cleanup;
408 }
Dan Williams3103dc02015-08-10 23:07:06 -0400409 memcpy(ctx->data, mapping, bytes);
Dan Williams3103dc02015-08-10 23:07:06 -0400410 memunmap(mapping);
Erik Arfvidson46168812015-05-05 18:36:14 -0400411 }
Erik Arfvidson46168812015-05-05 18:36:14 -0400412
Jes Sorensencc55b5c2015-05-05 18:37:13 -0400413 ctx->byte_stream = true;
Erik Arfvidson46168812015-05-05 18:36:14 -0400414 rc = ctx;
415cleanup:
Erik Arfvidson46168812015-05-05 18:36:14 -0400416 if (rc) {
417 controlvm_payload_bytes_buffered += ctx->param_bytes;
418 } else {
419 if (ctx) {
420 parser_done(ctx);
421 ctx = NULL;
422 }
423 }
424 return rc;
425}
426
Jes Sorensen464129e2015-05-05 18:37:12 -0400427static uuid_le
Erik Arfvidson46168812015-05-05 18:36:14 -0400428parser_id_get(struct parser_context *ctx)
429{
430 struct spar_controlvm_parameters_header *phdr = NULL;
431
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500432 if (!ctx)
Erik Arfvidson46168812015-05-05 18:36:14 -0400433 return NULL_UUID_LE;
434 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
435 return phdr->id;
436}
437
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400438/** Describes the state from the perspective of which controlvm messages have
439 * been received for a bus or device.
440 */
441
442enum PARSER_WHICH_STRING {
443 PARSERSTRING_INITIATOR,
444 PARSERSTRING_TARGET,
445 PARSERSTRING_CONNECTION,
446 PARSERSTRING_NAME, /* TODO: only PARSERSTRING_NAME is used ? */
447};
448
Jes Sorensen464129e2015-05-05 18:37:12 -0400449static void
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400450parser_param_start(struct parser_context *ctx,
451 enum PARSER_WHICH_STRING which_string)
Erik Arfvidson46168812015-05-05 18:36:14 -0400452{
453 struct spar_controlvm_parameters_header *phdr = NULL;
454
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500455 if (!ctx)
Benjamin Romerb4d4dfb2016-02-08 10:41:53 -0500456 return;
457
Erik Arfvidson46168812015-05-05 18:36:14 -0400458 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
459 switch (which_string) {
460 case PARSERSTRING_INITIATOR:
461 ctx->curr = ctx->data + phdr->initiator_offset;
462 ctx->bytes_remaining = phdr->initiator_length;
463 break;
464 case PARSERSTRING_TARGET:
465 ctx->curr = ctx->data + phdr->target_offset;
466 ctx->bytes_remaining = phdr->target_length;
467 break;
468 case PARSERSTRING_CONNECTION:
469 ctx->curr = ctx->data + phdr->connection_offset;
470 ctx->bytes_remaining = phdr->connection_length;
471 break;
472 case PARSERSTRING_NAME:
473 ctx->curr = ctx->data + phdr->name_offset;
474 ctx->bytes_remaining = phdr->name_length;
475 break;
476 default:
477 break;
478 }
Erik Arfvidson46168812015-05-05 18:36:14 -0400479}
480
Jes Sorensen464129e2015-05-05 18:37:12 -0400481static void parser_done(struct parser_context *ctx)
Erik Arfvidson46168812015-05-05 18:36:14 -0400482{
483 if (!ctx)
484 return;
485 controlvm_payload_bytes_buffered -= ctx->param_bytes;
486 kfree(ctx);
487}
488
Jes Sorensen464129e2015-05-05 18:37:12 -0400489static void *
Erik Arfvidson46168812015-05-05 18:36:14 -0400490parser_string_get(struct parser_context *ctx)
491{
492 u8 *pscan;
493 unsigned long nscan;
494 int value_length = -1;
495 void *value = NULL;
496 int i;
497
498 if (!ctx)
499 return NULL;
500 pscan = ctx->curr;
501 nscan = ctx->bytes_remaining;
502 if (nscan == 0)
503 return NULL;
504 if (!pscan)
505 return NULL;
506 for (i = 0, value_length = -1; i < nscan; i++)
507 if (pscan[i] == '\0') {
508 value_length = i;
509 break;
510 }
511 if (value_length < 0) /* '\0' was not included in the length */
512 value_length = nscan;
Erik Arfvidson8c395e72016-02-08 10:41:45 -0500513 value = kmalloc(value_length + 1, GFP_KERNEL | __GFP_NORETRY);
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500514 if (!value)
Erik Arfvidson46168812015-05-05 18:36:14 -0400515 return NULL;
516 if (value_length > 0)
517 memcpy(value, pscan, value_length);
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500518 ((u8 *)(value))[value_length] = '\0';
Erik Arfvidson46168812015-05-05 18:36:14 -0400519 return value;
520}
521
Vincent Bernatd746cb52014-08-01 10:29:30 +0200522static ssize_t toolaction_show(struct device *dev,
523 struct device_attribute *attr,
524 char *buf)
Benjamin Romer19f66342014-07-22 09:56:25 -0400525{
Benjamin Romer01f4d852015-03-16 13:58:48 -0400526 u8 tool_action;
Benjamin Romer19f66342014-07-22 09:56:25 -0400527
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400528 visorchannel_read(controlvm_channel,
Benjamin Romer6bb871b2015-12-07 10:58:37 -0500529 offsetof(struct spar_controlvm_channel_protocol,
530 tool_action), &tool_action, sizeof(u8));
Benjamin Romer01f4d852015-03-16 13:58:48 -0400531 return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action);
Benjamin Romer19f66342014-07-22 09:56:25 -0400532}
533
Vincent Bernatd746cb52014-08-01 10:29:30 +0200534static ssize_t toolaction_store(struct device *dev,
535 struct device_attribute *attr,
536 const char *buf, size_t count)
Benjamin Romer19f66342014-07-22 09:56:25 -0400537{
Benjamin Romer01f4d852015-03-16 13:58:48 -0400538 u8 tool_action;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400539 int ret;
Benjamin Romer19f66342014-07-22 09:56:25 -0400540
Jes Sorensenebec8962015-05-05 18:35:57 -0400541 if (kstrtou8(buf, 10, &tool_action))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400542 return -EINVAL;
543
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400544 ret = visorchannel_write(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400545 offsetof(struct spar_controlvm_channel_protocol,
546 tool_action),
Benjamin Romer01f4d852015-03-16 13:58:48 -0400547 &tool_action, sizeof(u8));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400548
549 if (ret)
550 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400551 return count;
Benjamin Romer19f66342014-07-22 09:56:25 -0400552}
553
Vincent Bernatd746cb52014-08-01 10:29:30 +0200554static ssize_t boottotool_show(struct device *dev,
555 struct device_attribute *attr,
556 char *buf)
Benjamin Romer54b31222014-07-22 09:56:26 -0400557{
Benjamin Romer365522d2015-03-16 13:58:49 -0400558 struct efi_spar_indication efi_spar_indication;
Benjamin Romer54b31222014-07-22 09:56:26 -0400559
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400560 visorchannel_read(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400561 offsetof(struct spar_controlvm_channel_protocol,
562 efi_spar_ind), &efi_spar_indication,
563 sizeof(struct efi_spar_indication));
Benjamin Romer54b31222014-07-22 09:56:26 -0400564 return scnprintf(buf, PAGE_SIZE, "%u\n",
Benjamin Romer8e76e692015-03-16 13:58:52 -0400565 efi_spar_indication.boot_to_tool);
Benjamin Romer54b31222014-07-22 09:56:26 -0400566}
567
Vincent Bernatd746cb52014-08-01 10:29:30 +0200568static ssize_t boottotool_store(struct device *dev,
569 struct device_attribute *attr,
570 const char *buf, size_t count)
Benjamin Romer54b31222014-07-22 09:56:26 -0400571{
Benjamin Romer66e24b72014-07-25 13:55:10 -0400572 int val, ret;
Benjamin Romer365522d2015-03-16 13:58:49 -0400573 struct efi_spar_indication efi_spar_indication;
Benjamin Romer54b31222014-07-22 09:56:26 -0400574
Jes Sorensenebec8962015-05-05 18:35:57 -0400575 if (kstrtoint(buf, 10, &val))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400576 return -EINVAL;
577
Benjamin Romer365522d2015-03-16 13:58:49 -0400578 efi_spar_indication.boot_to_tool = val;
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400579 ret = visorchannel_write(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -0400580 offsetof(struct spar_controlvm_channel_protocol,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400581 efi_spar_ind), &(efi_spar_indication),
582 sizeof(struct efi_spar_indication));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400583
584 if (ret)
585 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400586 return count;
Benjamin Romer54b31222014-07-22 09:56:26 -0400587}
Benjamin Romer422af172014-07-24 14:08:42 -0400588
589static ssize_t error_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400590 char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400591{
592 u32 error;
593
Benjamin Romer8e76e692015-03-16 13:58:52 -0400594 visorchannel_read(controlvm_channel,
595 offsetof(struct spar_controlvm_channel_protocol,
596 installation_error),
597 &error, sizeof(u32));
Benjamin Romer422af172014-07-24 14:08:42 -0400598 return scnprintf(buf, PAGE_SIZE, "%i\n", error);
599}
600
601static ssize_t error_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400602 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400603{
604 u32 error;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400605 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400606
Jes Sorensenebec8962015-05-05 18:35:57 -0400607 if (kstrtou32(buf, 10, &error))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400608 return -EINVAL;
609
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400610 ret = visorchannel_write(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400611 offsetof(struct spar_controlvm_channel_protocol,
612 installation_error),
613 &error, sizeof(u32));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400614 if (ret)
615 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400616 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400617}
618
619static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400620 char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400621{
Benjamin Romer10dbf0e2015-03-16 13:58:50 -0400622 u32 text_id;
Benjamin Romer422af172014-07-24 14:08:42 -0400623
Benjamin Romer8e76e692015-03-16 13:58:52 -0400624 visorchannel_read(controlvm_channel,
625 offsetof(struct spar_controlvm_channel_protocol,
626 installation_text_id),
627 &text_id, sizeof(u32));
Benjamin Romer10dbf0e2015-03-16 13:58:50 -0400628 return scnprintf(buf, PAGE_SIZE, "%i\n", text_id);
Benjamin Romer422af172014-07-24 14:08:42 -0400629}
630
631static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400632 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400633{
Benjamin Romer10dbf0e2015-03-16 13:58:50 -0400634 u32 text_id;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400635 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400636
Jes Sorensenebec8962015-05-05 18:35:57 -0400637 if (kstrtou32(buf, 10, &text_id))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400638 return -EINVAL;
639
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400640 ret = visorchannel_write(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400641 offsetof(struct spar_controlvm_channel_protocol,
642 installation_text_id),
643 &text_id, sizeof(u32));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400644 if (ret)
645 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400646 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400647}
648
Benjamin Romer422af172014-07-24 14:08:42 -0400649static ssize_t remaining_steps_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400650 struct device_attribute *attr, char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400651{
Benjamin Romeree8da292015-03-16 13:58:51 -0400652 u16 remaining_steps;
Benjamin Romer422af172014-07-24 14:08:42 -0400653
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400654 visorchannel_read(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400655 offsetof(struct spar_controlvm_channel_protocol,
656 installation_remaining_steps),
657 &remaining_steps, sizeof(u16));
Benjamin Romeree8da292015-03-16 13:58:51 -0400658 return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps);
Benjamin Romer422af172014-07-24 14:08:42 -0400659}
660
661static ssize_t remaining_steps_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400662 struct device_attribute *attr,
663 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400664{
Benjamin Romeree8da292015-03-16 13:58:51 -0400665 u16 remaining_steps;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400666 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400667
Jes Sorensenebec8962015-05-05 18:35:57 -0400668 if (kstrtou16(buf, 10, &remaining_steps))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400669 return -EINVAL;
670
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400671 ret = visorchannel_write(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400672 offsetof(struct spar_controlvm_channel_protocol,
673 installation_remaining_steps),
674 &remaining_steps, sizeof(u16));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400675 if (ret)
676 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400677 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400678}
679
Don Zickusab0592b2015-05-13 13:22:19 -0400680struct visor_busdev {
681 u32 bus_no;
682 u32 dev_no;
683};
684
685static int match_visorbus_dev_by_id(struct device *dev, void *data)
686{
687 struct visor_device *vdev = to_visor_device(dev);
Shraddha Barke7f445822015-10-15 00:58:23 +0530688 struct visor_busdev *id = data;
Don Zickusab0592b2015-05-13 13:22:19 -0400689 u32 bus_no = id->bus_no;
690 u32 dev_no = id->dev_no;
691
Don Zickus65bd6e42015-06-04 09:22:40 -0400692 if ((vdev->chipset_bus_no == bus_no) &&
693 (vdev->chipset_dev_no == dev_no))
Don Zickusab0592b2015-05-13 13:22:19 -0400694 return 1;
695
696 return 0;
697}
Erik Arfvidsond1e08632016-02-08 10:41:47 -0500698
Don Zickusab0592b2015-05-13 13:22:19 -0400699struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
700 struct visor_device *from)
701{
702 struct device *dev;
703 struct device *dev_start = NULL;
704 struct visor_device *vdev = NULL;
705 struct visor_busdev id = {
706 .bus_no = bus_no,
707 .dev_no = dev_no
708 };
709
710 if (from)
711 dev_start = &from->device;
712 dev = bus_find_device(&visorbus_type, dev_start, (void *)&id,
713 match_visorbus_dev_by_id);
714 if (dev)
715 vdev = to_visor_device(dev);
716 return vdev;
717}
718EXPORT_SYMBOL(visorbus_get_device_by_id);
719
Benjamin Romerc2422332014-07-29 15:09:40 -0400720static u8
Ken Cox12e364b2014-03-04 07:58:07 -0600721check_chipset_events(void)
722{
723 int i;
Benjamin Romerc2422332014-07-29 15:09:40 -0400724 u8 send_msg = 1;
Ken Cox12e364b2014-03-04 07:58:07 -0600725 /* Check events to determine if response should be sent */
726 for (i = 0; i < MAX_CHIPSET_EVENTS; i++)
727 send_msg &= chipset_events[i];
728 return send_msg;
729}
730
731static void
732clear_chipset_events(void)
733{
734 int i;
735 /* Clear chipset_events */
736 for (i = 0; i < MAX_CHIPSET_EVENTS; i++)
737 chipset_events[i] = 0;
738}
739
740void
David Kershner4da33362015-05-05 18:36:39 -0400741visorchipset_register_busdev(
Benjamin Romerfe90d892014-10-31 09:57:32 -0400742 struct visorchipset_busdev_notifiers *notifiers,
Benjamin Romer929aa8a2014-10-31 09:57:33 -0400743 struct visorchipset_busdev_responders *responders,
Benjamin Romer1e7a59c2014-10-31 09:57:35 -0400744 struct ultra_vbus_deviceinfo *driver_info)
Ken Cox12e364b2014-03-04 07:58:07 -0600745{
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400746 down(&notifier_lock);
Benjamin Romer38f736e2015-03-16 13:58:13 -0400747 if (!notifiers) {
David Kershner4da33362015-05-05 18:36:39 -0400748 memset(&busdev_notifiers, 0,
749 sizeof(busdev_notifiers));
750 visorbusregistered = 0; /* clear flag */
Ken Cox12e364b2014-03-04 07:58:07 -0600751 } else {
David Kershner4da33362015-05-05 18:36:39 -0400752 busdev_notifiers = *notifiers;
753 visorbusregistered = 1; /* set flag */
Ken Cox12e364b2014-03-04 07:58:07 -0600754 }
755 if (responders)
Benjamin Romer8e3fedd2015-03-16 13:58:43 -0400756 *responders = busdev_responders;
Benjamin Romer1e7a59c2014-10-31 09:57:35 -0400757 if (driver_info)
758 bus_device_info_init(driver_info, "chipset", "visorchipset",
Benjamin Romer8e76e692015-03-16 13:58:52 -0400759 VERSION, NULL);
Ken Cox12e364b2014-03-04 07:58:07 -0600760
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400761 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -0600762}
David Kershner4da33362015-05-05 18:36:39 -0400763EXPORT_SYMBOL_GPL(visorchipset_register_busdev);
Ken Cox12e364b2014-03-04 07:58:07 -0600764
765static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400766chipset_init(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600767{
768 static int chipset_inited;
Benjamin Romerb9b141e2014-10-23 14:30:24 -0400769 enum ultra_chipset_feature features = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600770 int rc = CONTROLVM_RESP_SUCCESS;
771
772 POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
773 if (chipset_inited) {
Ken Cox22ad57b2014-03-19 13:06:25 -0500774 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Benjamin Romere3199b22015-03-16 13:58:14 -0400775 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -0600776 }
777 chipset_inited = 1;
778 POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
779
780 /* Set features to indicate we support parahotplug (if Command
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500781 * also supports it).
782 */
Ken Cox12e364b2014-03-04 07:58:07 -0600783 features =
Benjamin Romer2ea51172014-10-23 14:30:25 -0400784 inmsg->cmd.init_chipset.
Ken Cox12e364b2014-03-04 07:58:07 -0600785 features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
786
787 /* Set the "reply" bit so Command knows this is a
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500788 * features-aware driver.
789 */
Ken Cox12e364b2014-03-04 07:58:07 -0600790 features |= ULTRA_CHIPSET_FEATURE_REPLY;
791
Benjamin Romere3199b22015-03-16 13:58:14 -0400792cleanup:
Benjamin Romer98d7b592014-10-23 14:30:26 -0400793 if (inmsg->hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -0600794 controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
795}
796
797static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400798controlvm_init_response(struct controlvm_message *msg,
Benjamin Romerb3168c72015-03-16 13:58:46 -0400799 struct controlvm_message_header *msg_hdr, int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600800{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400801 memset(msg, 0, sizeof(struct controlvm_message));
Benjamin Romerb3168c72015-03-16 13:58:46 -0400802 memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
Benjamin Romer98d7b592014-10-23 14:30:26 -0400803 msg->hdr.payload_bytes = 0;
804 msg->hdr.payload_vm_offset = 0;
805 msg->hdr.payload_max_bytes = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600806 if (response < 0) {
Benjamin Romer98d7b592014-10-23 14:30:26 -0400807 msg->hdr.flags.failed = 1;
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500808 msg->hdr.completion_status = (u32)(-response);
Ken Cox12e364b2014-03-04 07:58:07 -0600809 }
810}
811
812static void
Benjamin Romerb3168c72015-03-16 13:58:46 -0400813controlvm_respond(struct controlvm_message_header *msg_hdr, int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600814{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400815 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400816
Benjamin Romerb3168c72015-03-16 13:58:46 -0400817 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500818 if (outmsg.hdr.flags.test_message == 1)
Ken Cox12e364b2014-03-04 07:58:07 -0600819 return;
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500820
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400821 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600822 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600823 return;
824 }
825}
826
827static void
Benjamin Romerb3168c72015-03-16 13:58:46 -0400828controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400829 int response,
Benjamin Romerb9b141e2014-10-23 14:30:24 -0400830 enum ultra_chipset_feature features)
Ken Cox12e364b2014-03-04 07:58:07 -0600831{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400832 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400833
Benjamin Romerb3168c72015-03-16 13:58:46 -0400834 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2ea51172014-10-23 14:30:25 -0400835 outmsg.cmd.init_chipset.features = features;
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400836 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600837 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600838 return;
839 }
840}
841
Benjamin Romer98d7b592014-10-23 14:30:26 -0400842static void controlvm_respond_physdev_changestate(
Benjamin Romerb3168c72015-03-16 13:58:46 -0400843 struct controlvm_message_header *msg_hdr, int response,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400844 struct spar_segment_state state)
Ken Cox12e364b2014-03-04 07:58:07 -0600845{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400846 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400847
Benjamin Romerb3168c72015-03-16 13:58:46 -0400848 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2ea51172014-10-23 14:30:25 -0400849 outmsg.cmd.device_change_state.state = state;
850 outmsg.cmd.device_change_state.flags.phys_device = 1;
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400851 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600852 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600853 return;
854 }
855}
856
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400857enum crash_obj_type {
858 CRASH_DEV,
859 CRASH_BUS,
860};
861
Ken Cox12e364b2014-03-04 07:58:07 -0600862static void
Tim Sell12c957d2016-03-01 19:45:04 -0500863save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
864{
865 u32 local_crash_msg_offset;
866 u16 local_crash_msg_count;
867
868 if (visorchannel_read(controlvm_channel,
869 offsetof(struct spar_controlvm_channel_protocol,
870 saved_crash_message_count),
871 &local_crash_msg_count, sizeof(u16)) < 0) {
872 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
873 POSTCODE_SEVERITY_ERR);
874 return;
875 }
876
877 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
878 POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
879 local_crash_msg_count,
880 POSTCODE_SEVERITY_ERR);
881 return;
882 }
883
884 if (visorchannel_read(controlvm_channel,
885 offsetof(struct spar_controlvm_channel_protocol,
886 saved_crash_message_offset),
887 &local_crash_msg_offset, sizeof(u32)) < 0) {
888 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
889 POSTCODE_SEVERITY_ERR);
890 return;
891 }
892
893 if (typ == CRASH_BUS) {
894 if (visorchannel_write(controlvm_channel,
895 local_crash_msg_offset,
896 msg,
897 sizeof(struct controlvm_message)) < 0) {
898 POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
899 POSTCODE_SEVERITY_ERR);
900 return;
901 }
902 } else {
903 local_crash_msg_offset += sizeof(struct controlvm_message);
904 if (visorchannel_write(controlvm_channel,
905 local_crash_msg_offset,
906 msg,
907 sizeof(struct controlvm_message)) < 0) {
908 POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
909 POSTCODE_SEVERITY_ERR);
910 return;
911 }
912 }
913}
914
915static void
Don Zickus0274b5a2015-06-01 13:00:27 -0400916bus_responder(enum controlvm_id cmd_id,
917 struct controlvm_message_header *pending_msg_hdr,
Don Zickus3032aed2015-05-13 13:22:24 -0400918 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600919{
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500920 if (!pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600921 return; /* no controlvm response needed */
Don Zickus0274b5a2015-06-01 13:00:27 -0400922
923 if (pending_msg_hdr->id != (u32)cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600924 return;
Don Zickus0274b5a2015-06-01 13:00:27 -0400925
926 controlvm_respond(pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600927}
928
929static void
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400930device_changestate_responder(enum controlvm_id cmd_id,
Don Zickusa298bc02015-06-04 09:22:42 -0400931 struct visor_device *p, int response,
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400932 struct spar_segment_state response_state)
Ken Cox12e364b2014-03-04 07:58:07 -0600933{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400934 struct controlvm_message outmsg;
Don Zickusa298bc02015-06-04 09:22:42 -0400935 u32 bus_no = p->chipset_bus_no;
936 u32 dev_no = p->chipset_dev_no;
Ken Cox12e364b2014-03-04 07:58:07 -0600937
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500938 if (!p->pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600939 return; /* no controlvm response needed */
Don Zickus0274b5a2015-06-01 13:00:27 -0400940 if (p->pending_msg_hdr->id != cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600941 return;
Ken Cox12e364b2014-03-04 07:58:07 -0600942
Don Zickus0274b5a2015-06-01 13:00:27 -0400943 controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600944
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400945 outmsg.cmd.device_change_state.bus_no = bus_no;
946 outmsg.cmd.device_change_state.dev_no = dev_no;
947 outmsg.cmd.device_change_state.state = response_state;
Ken Cox12e364b2014-03-04 07:58:07 -0600948
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400949 if (!visorchannel_signalinsert(controlvm_channel,
Benjamin Romer0aca78442015-03-04 12:14:25 -0500950 CONTROLVM_QUEUE_REQUEST, &outmsg))
Ken Cox12e364b2014-03-04 07:58:07 -0600951 return;
Ken Cox12e364b2014-03-04 07:58:07 -0600952}
953
954static void
Don Zickus0274b5a2015-06-01 13:00:27 -0400955device_responder(enum controlvm_id cmd_id,
956 struct controlvm_message_header *pending_msg_hdr,
Don Zickusb4b598f2015-05-13 13:22:25 -0400957 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600958{
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500959 if (!pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600960 return; /* no controlvm response needed */
Benjamin Romer0aca78442015-03-04 12:14:25 -0500961
Don Zickus0274b5a2015-06-01 13:00:27 -0400962 if (pending_msg_hdr->id != (u32)cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600963 return;
Benjamin Romer0aca78442015-03-04 12:14:25 -0500964
Don Zickus0274b5a2015-06-01 13:00:27 -0400965 controlvm_respond(pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600966}
967
968static void
Don Zickusd32517e2015-06-04 09:22:41 -0400969bus_epilog(struct visor_device *bus_info,
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400970 u32 cmd, struct controlvm_message_header *msg_hdr,
Jes Sorensenf4c11552015-04-13 10:28:40 -0400971 int response, bool need_response)
Ken Cox12e364b2014-03-04 07:58:07 -0600972{
Jes Sorensenf4c11552015-04-13 10:28:40 -0400973 bool notified = false;
Don Zickus0274b5a2015-06-01 13:00:27 -0400974 struct controlvm_message_header *pmsg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -0600975
Don Zickus0274b5a2015-06-01 13:00:27 -0400976 if (!bus_info) {
977 /* relying on a valid passed in response code */
978 /* be lazy and re-use msg_hdr for this failure, is this ok?? */
979 pmsg_hdr = msg_hdr;
980 goto away;
981 }
982
983 if (bus_info->pending_msg_hdr) {
984 /* only non-NULL if dev is still waiting on a response */
985 response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
986 pmsg_hdr = bus_info->pending_msg_hdr;
987 goto away;
988 }
Benjamin Romer0aca78442015-03-04 12:14:25 -0500989
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400990 if (need_response) {
Don Zickus0274b5a2015-06-01 13:00:27 -0400991 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
992 if (!pmsg_hdr) {
993 response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
994 goto away;
995 }
996
997 memcpy(pmsg_hdr, msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400998 sizeof(struct controlvm_message_header));
Don Zickus0274b5a2015-06-01 13:00:27 -0400999 bus_info->pending_msg_hdr = pmsg_hdr;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001000 }
Ken Cox12e364b2014-03-04 07:58:07 -06001001
Benjamin Romer8f1947a2015-03-16 13:57:59 -04001002 down(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001003 if (response == CONTROLVM_RESP_SUCCESS) {
1004 switch (cmd) {
1005 case CONTROLVM_BUS_CREATE:
David Kershner4da33362015-05-05 18:36:39 -04001006 if (busdev_notifiers.bus_create) {
Don Zickus3032aed2015-05-13 13:22:24 -04001007 (*busdev_notifiers.bus_create) (bus_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001008 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001009 }
1010 break;
1011 case CONTROLVM_BUS_DESTROY:
David Kershner4da33362015-05-05 18:36:39 -04001012 if (busdev_notifiers.bus_destroy) {
Don Zickus3032aed2015-05-13 13:22:24 -04001013 (*busdev_notifiers.bus_destroy) (bus_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001014 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001015 }
1016 break;
1017 }
1018 }
Don Zickus0274b5a2015-06-01 13:00:27 -04001019away:
Ken Cox12e364b2014-03-04 07:58:07 -06001020 if (notified)
1021 /* The callback function just called above is responsible
Benjamin Romer929aa8a2014-10-31 09:57:33 -04001022 * for calling the appropriate visorchipset_busdev_responders
Ken Cox12e364b2014-03-04 07:58:07 -06001023 * function, which will call bus_responder()
1024 */
1025 ;
1026 else
Don Zickus0274b5a2015-06-01 13:00:27 -04001027 /*
1028 * Do not kfree(pmsg_hdr) as this is the failure path.
1029 * The success path ('notified') will call the responder
1030 * directly and kfree() there.
1031 */
1032 bus_responder(cmd, pmsg_hdr, response);
Benjamin Romer8f1947a2015-03-16 13:57:59 -04001033 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001034}
1035
1036static void
Don Zickusa298bc02015-06-04 09:22:42 -04001037device_epilog(struct visor_device *dev_info,
Don Zickusb4b598f2015-05-13 13:22:25 -04001038 struct spar_segment_state state, u32 cmd,
Benjamin Romer2836c6a2015-03-16 13:58:17 -04001039 struct controlvm_message_header *msg_hdr, int response,
Jes Sorensenf4c11552015-04-13 10:28:40 -04001040 bool need_response, bool for_visorbus)
Ken Cox12e364b2014-03-04 07:58:07 -06001041{
Jes Sorensene82ba622015-05-05 18:35:45 -04001042 struct visorchipset_busdev_notifiers *notifiers;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001043 bool notified = false;
Don Zickus0274b5a2015-06-01 13:00:27 -04001044 struct controlvm_message_header *pmsg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001045
David Kershner4da33362015-05-05 18:36:39 -04001046 notifiers = &busdev_notifiers;
1047
Don Zickus0274b5a2015-06-01 13:00:27 -04001048 if (!dev_info) {
1049 /* relying on a valid passed in response code */
1050 /* be lazy and re-use msg_hdr for this failure, is this ok?? */
1051 pmsg_hdr = msg_hdr;
1052 goto away;
1053 }
1054
1055 if (dev_info->pending_msg_hdr) {
1056 /* only non-NULL if dev is still waiting on a response */
1057 response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
1058 pmsg_hdr = dev_info->pending_msg_hdr;
1059 goto away;
1060 }
1061
Benjamin Romer2836c6a2015-03-16 13:58:17 -04001062 if (need_response) {
Don Zickus0274b5a2015-06-01 13:00:27 -04001063 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
1064 if (!pmsg_hdr) {
1065 response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
1066 goto away;
1067 }
1068
1069 memcpy(pmsg_hdr, msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001070 sizeof(struct controlvm_message_header));
Don Zickus0274b5a2015-06-01 13:00:27 -04001071 dev_info->pending_msg_hdr = pmsg_hdr;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001072 }
Ken Cox12e364b2014-03-04 07:58:07 -06001073
Benjamin Romer8f1947a2015-03-16 13:57:59 -04001074 down(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001075 if (response >= 0) {
1076 switch (cmd) {
1077 case CONTROLVM_DEVICE_CREATE:
1078 if (notifiers->device_create) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001079 (*notifiers->device_create) (dev_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001080 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001081 }
1082 break;
1083 case CONTROLVM_DEVICE_CHANGESTATE:
1084 /* ServerReady / ServerRunning / SegmentStateRunning */
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001085 if (state.alive == segment_state_running.alive &&
1086 state.operating ==
1087 segment_state_running.operating) {
Ken Cox12e364b2014-03-04 07:58:07 -06001088 if (notifiers->device_resume) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001089 (*notifiers->device_resume) (dev_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001090 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001091 }
1092 }
1093 /* ServerNotReady / ServerLost / SegmentStateStandby */
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001094 else if (state.alive == segment_state_standby.alive &&
Benjamin Romer3f833b52014-10-23 14:30:12 -04001095 state.operating ==
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001096 segment_state_standby.operating) {
Ken Cox12e364b2014-03-04 07:58:07 -06001097 /* technically this is standby case
1098 * where server is lost
1099 */
1100 if (notifiers->device_pause) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001101 (*notifiers->device_pause) (dev_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001102 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001103 }
Ken Cox12e364b2014-03-04 07:58:07 -06001104 }
1105 break;
1106 case CONTROLVM_DEVICE_DESTROY:
1107 if (notifiers->device_destroy) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001108 (*notifiers->device_destroy) (dev_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001109 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001110 }
1111 break;
1112 }
1113 }
Don Zickus0274b5a2015-06-01 13:00:27 -04001114away:
Ken Cox12e364b2014-03-04 07:58:07 -06001115 if (notified)
1116 /* The callback function just called above is responsible
Benjamin Romer929aa8a2014-10-31 09:57:33 -04001117 * for calling the appropriate visorchipset_busdev_responders
Ken Cox12e364b2014-03-04 07:58:07 -06001118 * function, which will call device_responder()
1119 */
1120 ;
1121 else
Don Zickus0274b5a2015-06-01 13:00:27 -04001122 /*
1123 * Do not kfree(pmsg_hdr) as this is the failure path.
1124 * The success path ('notified') will call the responder
1125 * directly and kfree() there.
1126 */
1127 device_responder(cmd, pmsg_hdr, response);
Benjamin Romer8f1947a2015-03-16 13:57:59 -04001128 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001129}
1130
1131static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001132bus_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001133{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001134 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001135 u32 bus_no = cmd->create_bus.bus_no;
Ken Cox12e364b2014-03-04 07:58:07 -06001136 int rc = CONTROLVM_RESP_SUCCESS;
Don Zickusd32517e2015-06-04 09:22:41 -04001137 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -04001138 struct visorchannel *visorchannel;
Ken Cox12e364b2014-03-04 07:58:07 -06001139
Don Zickusd32517e2015-06-04 09:22:41 -04001140 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001141 if (bus_info && (bus_info->state.created == 1)) {
1142 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001143 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001144 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001145 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001146 }
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001147 bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
1148 if (!bus_info) {
1149 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001150 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001151 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001152 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001153 }
1154
David Kershner4abce832015-06-04 09:22:49 -04001155 INIT_LIST_HEAD(&bus_info->list_all);
Don Zickusd32517e2015-06-04 09:22:41 -04001156 bus_info->chipset_bus_no = bus_no;
1157 bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
Ken Cox12e364b2014-03-04 07:58:07 -06001158
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001159 POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001160
Don Zickusb32c4992015-06-01 13:00:26 -04001161 visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
1162 cmd->create_bus.channel_bytes,
1163 GFP_KERNEL,
1164 cmd->create_bus.bus_data_type_uuid);
1165
1166 if (!visorchannel) {
1167 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
1168 POSTCODE_SEVERITY_ERR);
1169 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
1170 kfree(bus_info);
1171 bus_info = NULL;
1172 goto cleanup;
1173 }
1174 bus_info->visorchannel = visorchannel;
Tim Sell12c957d2016-03-01 19:45:04 -05001175 if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) {
1176 dump_vhba_bus = bus_no;
1177 save_crash_message(inmsg, CRASH_BUS);
1178 }
Ken Cox12e364b2014-03-04 07:58:07 -06001179
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001180 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001181
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001182cleanup:
Don Zickus3032aed2015-05-13 13:22:24 -04001183 bus_epilog(bus_info, CONTROLVM_BUS_CREATE, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001184 rc, inmsg->hdr.flags.response_expected == 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001185}
1186
1187static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001188bus_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001189{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001190 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001191 u32 bus_no = cmd->destroy_bus.bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -04001192 struct visor_device *bus_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001193 int rc = CONTROLVM_RESP_SUCCESS;
1194
Don Zickusd32517e2015-06-04 09:22:41 -04001195 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerdff54cd2015-03-16 13:58:21 -04001196 if (!bus_info)
Ken Cox22ad57b2014-03-19 13:06:25 -05001197 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romerdff54cd2015-03-16 13:58:21 -04001198 else if (bus_info->state.created == 0)
Ken Cox22ad57b2014-03-19 13:06:25 -05001199 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Ken Cox12e364b2014-03-04 07:58:07 -06001200
Don Zickus3032aed2015-05-13 13:22:24 -04001201 bus_epilog(bus_info, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001202 rc, inmsg->hdr.flags.response_expected == 1);
Don Zickusd32517e2015-06-04 09:22:41 -04001203
1204 /* bus_info is freed as part of the busdevice_release function */
Ken Cox12e364b2014-03-04 07:58:07 -06001205}
1206
1207static void
Benjamin Romer317d9612015-03-16 13:57:51 -04001208bus_configure(struct controlvm_message *inmsg,
1209 struct parser_context *parser_ctx)
Ken Cox12e364b2014-03-04 07:58:07 -06001210{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001211 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensene82ba622015-05-05 18:35:45 -04001212 u32 bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -04001213 struct visor_device *bus_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001214 int rc = CONTROLVM_RESP_SUCCESS;
Ken Cox12e364b2014-03-04 07:58:07 -06001215
Benjamin Romer654bada2015-03-16 13:58:22 -04001216 bus_no = cmd->configure_bus.bus_no;
1217 POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no,
1218 POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001219
Don Zickusd32517e2015-06-04 09:22:41 -04001220 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer654bada2015-03-16 13:58:22 -04001221 if (!bus_info) {
1222 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001223 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001224 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romer654bada2015-03-16 13:58:22 -04001225 } else if (bus_info->state.created == 0) {
1226 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001227 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001228 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -05001229 } else if (bus_info->pending_msg_hdr) {
Benjamin Romer654bada2015-03-16 13:58:22 -04001230 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001231 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001232 rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
Benjamin Romer654bada2015-03-16 13:58:22 -04001233 } else {
Don Zickusb32c4992015-06-01 13:00:26 -04001234 visorchannel_set_clientpartition(bus_info->visorchannel,
1235 cmd->configure_bus.guest_handle);
Benjamin Romer654bada2015-03-16 13:58:22 -04001236 bus_info->partition_uuid = parser_id_get(parser_ctx);
1237 parser_param_start(parser_ctx, PARSERSTRING_NAME);
1238 bus_info->name = parser_string_get(parser_ctx);
1239
Benjamin Romer654bada2015-03-16 13:58:22 -04001240 POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no,
1241 POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001242 }
Don Zickus3032aed2015-05-13 13:22:24 -04001243 bus_epilog(bus_info, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001244 rc, inmsg->hdr.flags.response_expected == 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001245}
1246
1247static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001248my_device_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001249{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001250 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001251 u32 bus_no = cmd->create_device.bus_no;
1252 u32 dev_no = cmd->create_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -04001253 struct visor_device *dev_info = NULL;
Don Zickusd32517e2015-06-04 09:22:41 -04001254 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -04001255 struct visorchannel *visorchannel;
Ken Cox12e364b2014-03-04 07:58:07 -06001256 int rc = CONTROLVM_RESP_SUCCESS;
1257
Don Zickusa298bc02015-06-04 09:22:42 -04001258 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001259 if (!bus_info) {
1260 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001261 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001262 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001263 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001264 }
Don Zickusa298bc02015-06-04 09:22:42 -04001265
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001266 if (bus_info->state.created == 0) {
1267 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001268 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001269 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001270 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001271 }
Don Zickusa298bc02015-06-04 09:22:42 -04001272
1273 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
1274 if (dev_info && (dev_info->state.created == 1)) {
1275 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
1276 POSTCODE_SEVERITY_ERR);
1277 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
1278 goto cleanup;
1279 }
1280
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001281 dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
1282 if (!dev_info) {
1283 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001284 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001285 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001286 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001287 }
Andreea-Cristina Bernat97a84f12014-03-14 04:20:06 +02001288
Don Zickusa298bc02015-06-04 09:22:42 -04001289 dev_info->chipset_bus_no = bus_no;
1290 dev_info->chipset_dev_no = dev_no;
1291 dev_info->inst = cmd->create_device.dev_inst_uuid;
1292
1293 /* not sure where the best place to set the 'parent' */
1294 dev_info->device.parent = &bus_info->device;
1295
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001296 POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001297 POSTCODE_SEVERITY_INFO);
1298
David Kershnera3ef1a82015-07-14 14:43:29 -04001299 visorchannel =
1300 visorchannel_create_with_lock(cmd->create_device.channel_addr,
1301 cmd->create_device.channel_bytes,
1302 GFP_KERNEL,
1303 cmd->create_device.data_type_uuid);
Don Zickusb32c4992015-06-01 13:00:26 -04001304
1305 if (!visorchannel) {
1306 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
1307 POSTCODE_SEVERITY_ERR);
1308 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
1309 kfree(dev_info);
1310 dev_info = NULL;
1311 goto cleanup;
1312 }
1313 dev_info->visorchannel = visorchannel;
1314 dev_info->channel_type_guid = cmd->create_device.data_type_uuid;
Tim Sell12c957d2016-03-01 19:45:04 -05001315 if (uuid_le_cmp(cmd->create_device.data_type_uuid,
1316 spar_vhba_channel_protocol_uuid) == 0)
1317 save_crash_message(inmsg, CRASH_DEV);
1318
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001319 POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001320 POSTCODE_SEVERITY_INFO);
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001321cleanup:
Don Zickusb4b598f2015-05-13 13:22:25 -04001322 device_epilog(dev_info, segment_state_running,
Ken Cox12e364b2014-03-04 07:58:07 -06001323 CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001324 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001325}
1326
1327static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001328my_device_changestate(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001329{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001330 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001331 u32 bus_no = cmd->device_change_state.bus_no;
1332 u32 dev_no = cmd->device_change_state.dev_no;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001333 struct spar_segment_state state = cmd->device_change_state.state;
Don Zickusa298bc02015-06-04 09:22:42 -04001334 struct visor_device *dev_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001335 int rc = CONTROLVM_RESP_SUCCESS;
1336
Don Zickusa298bc02015-06-04 09:22:42 -04001337 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer0278a902015-03-16 13:58:24 -04001338 if (!dev_info) {
1339 POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001340 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001341 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Benjamin Romer0278a902015-03-16 13:58:24 -04001342 } else if (dev_info->state.created == 0) {
1343 POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001344 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001345 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Ken Cox12e364b2014-03-04 07:58:07 -06001346 }
Benjamin Romer0278a902015-03-16 13:58:24 -04001347 if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
Don Zickusb4b598f2015-05-13 13:22:25 -04001348 device_epilog(dev_info, state,
Benjamin Romer0278a902015-03-16 13:58:24 -04001349 CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001350 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001351}
1352
1353static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001354my_device_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001355{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001356 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001357 u32 bus_no = cmd->destroy_device.bus_no;
1358 u32 dev_no = cmd->destroy_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -04001359 struct visor_device *dev_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001360 int rc = CONTROLVM_RESP_SUCCESS;
1361
Don Zickusa298bc02015-06-04 09:22:42 -04001362 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer61715c82015-03-16 13:58:25 -04001363 if (!dev_info)
Ken Cox22ad57b2014-03-19 13:06:25 -05001364 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Benjamin Romer61715c82015-03-16 13:58:25 -04001365 else if (dev_info->state.created == 0)
Ken Cox22ad57b2014-03-19 13:06:25 -05001366 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Ken Cox12e364b2014-03-04 07:58:07 -06001367
Benjamin Romer61715c82015-03-16 13:58:25 -04001368 if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
Don Zickusb4b598f2015-05-13 13:22:25 -04001369 device_epilog(dev_info, segment_state_running,
Ken Cox12e364b2014-03-04 07:58:07 -06001370 CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001371 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001372}
1373
1374/* When provided with the physical address of the controlvm channel
1375 * (phys_addr), the offset to the payload area we need to manage
1376 * (offset), and the size of this payload area (bytes), fills in the
Jes Sorensenf4c11552015-04-13 10:28:40 -04001377 * controlvm_payload_info struct. Returns true for success or false
Ken Cox12e364b2014-03-04 07:58:07 -06001378 * for failure.
1379 */
1380static int
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001381initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes,
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001382 struct visor_controlvm_payload_info *info)
Ken Cox12e364b2014-03-04 07:58:07 -06001383{
Dan Williams3103dc02015-08-10 23:07:06 -04001384 u8 *payload = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001385 int rc = CONTROLVM_RESP_SUCCESS;
1386
Benjamin Romer38f736e2015-03-16 13:58:13 -04001387 if (!info) {
Ken Cox22ad57b2014-03-19 13:06:25 -05001388 rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
Benjamin Romerf118a392015-03-16 13:58:26 -04001389 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001390 }
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001391 memset(info, 0, sizeof(struct visor_controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06001392 if ((offset == 0) || (bytes == 0)) {
Ken Cox22ad57b2014-03-19 13:06:25 -05001393 rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
Benjamin Romerf118a392015-03-16 13:58:26 -04001394 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001395 }
Dan Williams3103dc02015-08-10 23:07:06 -04001396 payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB);
Benjamin Romer38f736e2015-03-16 13:58:13 -04001397 if (!payload) {
Ken Cox22ad57b2014-03-19 13:06:25 -05001398 rc = -CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
Benjamin Romerf118a392015-03-16 13:58:26 -04001399 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001400 }
1401
1402 info->offset = offset;
1403 info->bytes = bytes;
1404 info->ptr = payload;
Ken Cox12e364b2014-03-04 07:58:07 -06001405
Benjamin Romerf118a392015-03-16 13:58:26 -04001406cleanup:
Ken Cox12e364b2014-03-04 07:58:07 -06001407 if (rc < 0) {
Benjamin Romerf118a392015-03-16 13:58:26 -04001408 if (payload) {
Dan Williams3103dc02015-08-10 23:07:06 -04001409 memunmap(payload);
Ken Cox12e364b2014-03-04 07:58:07 -06001410 payload = NULL;
1411 }
1412 }
1413 return rc;
1414}
1415
1416static void
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001417destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info)
Ken Cox12e364b2014-03-04 07:58:07 -06001418{
Benjamin Romer597c3382015-03-16 13:58:27 -04001419 if (info->ptr) {
Dan Williams3103dc02015-08-10 23:07:06 -04001420 memunmap(info->ptr);
Ken Cox12e364b2014-03-04 07:58:07 -06001421 info->ptr = NULL;
1422 }
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001423 memset(info, 0, sizeof(struct visor_controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06001424}
1425
1426static void
1427initialize_controlvm_payload(void)
1428{
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001429 u64 phys_addr = visorchannel_get_physaddr(controlvm_channel);
Benjamin Romercafefc02015-03-16 13:58:28 -04001430 u64 payload_offset = 0;
1431 u32 payload_bytes = 0;
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001432
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001433 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001434 offsetof(struct spar_controlvm_channel_protocol,
1435 request_payload_offset),
Benjamin Romercafefc02015-03-16 13:58:28 -04001436 &payload_offset, sizeof(payload_offset)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001437 POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
1438 POSTCODE_SEVERITY_ERR);
1439 return;
1440 }
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001441 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001442 offsetof(struct spar_controlvm_channel_protocol,
1443 request_payload_bytes),
Benjamin Romercafefc02015-03-16 13:58:28 -04001444 &payload_bytes, sizeof(payload_bytes)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001445 POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
1446 POSTCODE_SEVERITY_ERR);
1447 return;
1448 }
1449 initialize_controlvm_payload_info(phys_addr,
Benjamin Romercafefc02015-03-16 13:58:28 -04001450 payload_offset, payload_bytes,
Benjamin Romer84982fb2015-03-16 13:58:07 -04001451 &controlvm_payload_info);
Ken Cox12e364b2014-03-04 07:58:07 -06001452}
1453
1454/* Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
1455 * Returns CONTROLVM_RESP_xxx code.
1456 */
Jes Sorensend3368a52015-05-13 13:21:57 -04001457static int
Ken Cox12e364b2014-03-04 07:58:07 -06001458visorchipset_chipset_ready(void)
1459{
Benjamin Romereb34e872015-03-16 13:58:45 -04001460 kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
Ken Cox12e364b2014-03-04 07:58:07 -06001461 return CONTROLVM_RESP_SUCCESS;
1462}
Ken Cox12e364b2014-03-04 07:58:07 -06001463
Jes Sorensend3368a52015-05-13 13:21:57 -04001464static int
Ken Cox12e364b2014-03-04 07:58:07 -06001465visorchipset_chipset_selftest(void)
1466{
1467 char env_selftest[20];
1468 char *envp[] = { env_selftest, NULL };
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001469
Ken Cox12e364b2014-03-04 07:58:07 -06001470 sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
Benjamin Romereb34e872015-03-16 13:58:45 -04001471 kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
Ken Cox12e364b2014-03-04 07:58:07 -06001472 envp);
1473 return CONTROLVM_RESP_SUCCESS;
1474}
Ken Cox12e364b2014-03-04 07:58:07 -06001475
1476/* Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
1477 * Returns CONTROLVM_RESP_xxx code.
1478 */
Jes Sorensend3368a52015-05-13 13:21:57 -04001479static int
Ken Cox12e364b2014-03-04 07:58:07 -06001480visorchipset_chipset_notready(void)
1481{
Benjamin Romereb34e872015-03-16 13:58:45 -04001482 kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
Ken Cox12e364b2014-03-04 07:58:07 -06001483 return CONTROLVM_RESP_SUCCESS;
1484}
Ken Cox12e364b2014-03-04 07:58:07 -06001485
1486static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001487chipset_ready(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001488{
1489 int rc = visorchipset_chipset_ready();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001490
Ken Cox12e364b2014-03-04 07:58:07 -06001491 if (rc != CONTROLVM_RESP_SUCCESS)
1492 rc = -rc;
Benjamin Romer77a04492015-03-16 13:58:47 -04001493 if (msg_hdr->flags.response_expected && !visorchipset_holdchipsetready)
1494 controlvm_respond(msg_hdr, rc);
1495 if (msg_hdr->flags.response_expected && visorchipset_holdchipsetready) {
Ken Cox12e364b2014-03-04 07:58:07 -06001496 /* Send CHIPSET_READY response when all modules have been loaded
1497 * and disks mounted for the partition
1498 */
Benjamin Romer77a04492015-03-16 13:58:47 -04001499 g_chipset_msg_hdr = *msg_hdr;
Ken Cox12e364b2014-03-04 07:58:07 -06001500 }
1501}
1502
1503static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001504chipset_selftest(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001505{
1506 int rc = visorchipset_chipset_selftest();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001507
Ken Cox12e364b2014-03-04 07:58:07 -06001508 if (rc != CONTROLVM_RESP_SUCCESS)
1509 rc = -rc;
Benjamin Romer77a04492015-03-16 13:58:47 -04001510 if (msg_hdr->flags.response_expected)
1511 controlvm_respond(msg_hdr, rc);
Ken Cox12e364b2014-03-04 07:58:07 -06001512}
1513
1514static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001515chipset_notready(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001516{
1517 int rc = visorchipset_chipset_notready();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001518
Ken Cox12e364b2014-03-04 07:58:07 -06001519 if (rc != CONTROLVM_RESP_SUCCESS)
1520 rc = -rc;
Benjamin Romer77a04492015-03-16 13:58:47 -04001521 if (msg_hdr->flags.response_expected)
1522 controlvm_respond(msg_hdr, rc);
Ken Cox12e364b2014-03-04 07:58:07 -06001523}
1524
1525/* This is your "one-stop" shop for grabbing the next message from the
1526 * CONTROLVM_QUEUE_EVENT queue in the controlvm channel.
1527 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001528static bool
Benjamin Romer3ab47702014-10-23 14:30:31 -04001529read_controlvm_event(struct controlvm_message *msg)
Ken Cox12e364b2014-03-04 07:58:07 -06001530{
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001531 if (visorchannel_signalremove(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -06001532 CONTROLVM_QUEUE_EVENT, msg)) {
1533 /* got a message */
Benjamin Romer0aca78442015-03-04 12:14:25 -05001534 if (msg->hdr.flags.test_message == 1)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001535 return false;
1536 return true;
Ken Cox12e364b2014-03-04 07:58:07 -06001537 }
Jes Sorensenf4c11552015-04-13 10:28:40 -04001538 return false;
Ken Cox12e364b2014-03-04 07:58:07 -06001539}
1540
1541/*
1542 * The general parahotplug flow works as follows. The visorchipset
1543 * driver receives a DEVICE_CHANGESTATE message from Command
1544 * specifying a physical device to enable or disable. The CONTROLVM
1545 * message handler calls parahotplug_process_message, which then adds
1546 * the message to a global list and kicks off a udev event which
1547 * causes a user level script to enable or disable the specified
1548 * device. The udev script then writes to
1549 * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write
1550 * to get called, at which point the appropriate CONTROLVM message is
1551 * retrieved from the list and responded to.
1552 */
1553
1554#define PARAHOTPLUG_TIMEOUT_MS 2000
1555
1556/*
1557 * Generate unique int to match an outstanding CONTROLVM message with a
1558 * udev script /proc response
1559 */
1560static int
1561parahotplug_next_id(void)
1562{
1563 static atomic_t id = ATOMIC_INIT(0);
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001564
Ken Cox12e364b2014-03-04 07:58:07 -06001565 return atomic_inc_return(&id);
1566}
1567
1568/*
1569 * Returns the time (in jiffies) when a CONTROLVM message on the list
1570 * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future
1571 */
1572static unsigned long
1573parahotplug_next_expiration(void)
1574{
Nicholas Mc Guire2cc1a1b2015-01-31 12:02:08 +01001575 return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
Ken Cox12e364b2014-03-04 07:58:07 -06001576}
1577
1578/*
1579 * Create a parahotplug_request, which is basically a wrapper for a
1580 * CONTROLVM_MESSAGE that we can stick on a list
1581 */
1582static struct parahotplug_request *
Benjamin Romer3ab47702014-10-23 14:30:31 -04001583parahotplug_request_create(struct controlvm_message *msg)
Ken Cox12e364b2014-03-04 07:58:07 -06001584{
Quentin Lambertea0dcfc2015-02-10 15:12:07 +01001585 struct parahotplug_request *req;
1586
Benjamin Romer6a55e3c2015-03-16 13:58:30 -04001587 req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY);
Benjamin Romer38f736e2015-03-16 13:58:13 -04001588 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -06001589 return NULL;
1590
1591 req->id = parahotplug_next_id();
1592 req->expiration = parahotplug_next_expiration();
1593 req->msg = *msg;
1594
1595 return req;
1596}
1597
1598/*
1599 * Free a parahotplug_request.
1600 */
1601static void
1602parahotplug_request_destroy(struct parahotplug_request *req)
1603{
1604 kfree(req);
1605}
1606
1607/*
1608 * Cause uevent to run the user level script to do the disable/enable
1609 * specified in (the CONTROLVM message in) the specified
1610 * parahotplug_request
1611 */
1612static void
1613parahotplug_request_kickoff(struct parahotplug_request *req)
1614{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001615 struct controlvm_message_packet *cmd = &req->msg.cmd;
Ken Cox12e364b2014-03-04 07:58:07 -06001616 char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
1617 env_func[40];
1618 char *envp[] = {
1619 env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL
1620 };
1621
1622 sprintf(env_cmd, "SPAR_PARAHOTPLUG=1");
1623 sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id);
1624 sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001625 cmd->device_change_state.state.active);
Ken Cox12e364b2014-03-04 07:58:07 -06001626 sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001627 cmd->device_change_state.bus_no);
Ken Cox12e364b2014-03-04 07:58:07 -06001628 sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001629 cmd->device_change_state.dev_no >> 3);
Ken Cox12e364b2014-03-04 07:58:07 -06001630 sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001631 cmd->device_change_state.dev_no & 0x7);
Ken Cox12e364b2014-03-04 07:58:07 -06001632
Benjamin Romereb34e872015-03-16 13:58:45 -04001633 kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
Ken Cox12e364b2014-03-04 07:58:07 -06001634 envp);
1635}
1636
1637/*
1638 * Remove any request from the list that's been on there too long and
1639 * respond with an error.
1640 */
1641static void
1642parahotplug_process_list(void)
1643{
Jes Sorensene82ba622015-05-05 18:35:45 -04001644 struct list_head *pos;
1645 struct list_head *tmp;
Ken Cox12e364b2014-03-04 07:58:07 -06001646
Benjamin Romerddf5de52015-03-16 13:58:41 -04001647 spin_lock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001648
Benjamin Romerddf5de52015-03-16 13:58:41 -04001649 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
Ken Cox12e364b2014-03-04 07:58:07 -06001650 struct parahotplug_request *req =
1651 list_entry(pos, struct parahotplug_request, list);
Benjamin Romer55b33412015-03-16 13:58:29 -04001652
1653 if (!time_after_eq(jiffies, req->expiration))
1654 continue;
1655
1656 list_del(pos);
1657 if (req->msg.hdr.flags.response_expected)
1658 controlvm_respond_physdev_changestate(
1659 &req->msg.hdr,
1660 CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
1661 req->msg.cmd.device_change_state.state);
1662 parahotplug_request_destroy(req);
Ken Cox12e364b2014-03-04 07:58:07 -06001663 }
1664
Benjamin Romerddf5de52015-03-16 13:58:41 -04001665 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001666}
1667
1668/*
1669 * Called from the /proc handler, which means the user script has
1670 * finished the enable/disable. Find the matching identifier, and
1671 * respond to the CONTROLVM message with success.
1672 */
1673static int
Benjamin Romerb06bdf72014-07-31 12:00:49 -04001674parahotplug_request_complete(int id, u16 active)
Ken Cox12e364b2014-03-04 07:58:07 -06001675{
Jes Sorensene82ba622015-05-05 18:35:45 -04001676 struct list_head *pos;
1677 struct list_head *tmp;
Ken Cox12e364b2014-03-04 07:58:07 -06001678
Benjamin Romerddf5de52015-03-16 13:58:41 -04001679 spin_lock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001680
1681 /* Look for a request matching "id". */
Benjamin Romerddf5de52015-03-16 13:58:41 -04001682 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
Ken Cox12e364b2014-03-04 07:58:07 -06001683 struct parahotplug_request *req =
1684 list_entry(pos, struct parahotplug_request, list);
1685 if (req->id == id) {
1686 /* Found a match. Remove it from the list and
1687 * respond.
1688 */
1689 list_del(pos);
Benjamin Romerddf5de52015-03-16 13:58:41 -04001690 spin_unlock(&parahotplug_request_list_lock);
Benjamin Romer2ea51172014-10-23 14:30:25 -04001691 req->msg.cmd.device_change_state.state.active = active;
Benjamin Romer98d7b592014-10-23 14:30:26 -04001692 if (req->msg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001693 controlvm_respond_physdev_changestate(
1694 &req->msg.hdr, CONTROLVM_RESP_SUCCESS,
Benjamin Romer2ea51172014-10-23 14:30:25 -04001695 req->msg.cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001696 parahotplug_request_destroy(req);
1697 return 0;
1698 }
1699 }
1700
Benjamin Romerddf5de52015-03-16 13:58:41 -04001701 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001702 return -1;
1703}
1704
1705/*
1706 * Enables or disables a PCI device by kicking off a udev script
1707 */
Ken Coxbd5b9b32014-03-13 15:39:22 -05001708static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001709parahotplug_process_message(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001710{
1711 struct parahotplug_request *req;
1712
1713 req = parahotplug_request_create(inmsg);
1714
Benjamin Romer38f736e2015-03-16 13:58:13 -04001715 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -06001716 return;
Ken Cox12e364b2014-03-04 07:58:07 -06001717
Benjamin Romer2ea51172014-10-23 14:30:25 -04001718 if (inmsg->cmd.device_change_state.state.active) {
Ken Cox12e364b2014-03-04 07:58:07 -06001719 /* For enable messages, just respond with success
1720 * right away. This is a bit of a hack, but there are
1721 * issues with the early enable messages we get (with
1722 * either the udev script not detecting that the device
1723 * is up, or not getting called at all). Fortunately
1724 * the messages that get lost don't matter anyway, as
1725 * devices are automatically enabled at
1726 * initialization.
1727 */
1728 parahotplug_request_kickoff(req);
1729 controlvm_respond_physdev_changestate(&inmsg->hdr,
Benjamin Romer8e76e692015-03-16 13:58:52 -04001730 CONTROLVM_RESP_SUCCESS,
1731 inmsg->cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001732 parahotplug_request_destroy(req);
1733 } else {
1734 /* For disable messages, add the request to the
1735 * request list before kicking off the udev script. It
1736 * won't get responded to until the script has
1737 * indicated it's done.
1738 */
Benjamin Romerddf5de52015-03-16 13:58:41 -04001739 spin_lock(&parahotplug_request_list_lock);
1740 list_add_tail(&req->list, &parahotplug_request_list);
1741 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001742
1743 parahotplug_request_kickoff(req);
1744 }
1745}
1746
Ken Cox12e364b2014-03-04 07:58:07 -06001747/* Process a controlvm message.
1748 * Return result:
Prarit Bhargava779d0752015-05-05 18:37:01 -04001749 * false - this function will return false only in the case where the
Ken Cox12e364b2014-03-04 07:58:07 -06001750 * controlvm message was NOT processed, but processing must be
1751 * retried before reading the next controlvm message; a
1752 * scenario where this can occur is when we need to throttle
1753 * the allocation of memory in which to copy out controlvm
1754 * payload data
Jes Sorensenf4c11552015-04-13 10:28:40 -04001755 * true - processing of the controlvm message completed,
Ken Cox12e364b2014-03-04 07:58:07 -06001756 * either successfully or with an error.
1757 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001758static bool
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001759handle_command(struct controlvm_message inmsg, u64 channel_addr)
Ken Cox12e364b2014-03-04 07:58:07 -06001760{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001761 struct controlvm_message_packet *cmd = &inmsg.cmd;
Jes Sorensene82ba622015-05-05 18:35:45 -04001762 u64 parm_addr;
1763 u32 parm_bytes;
Benjamin Romer317d9612015-03-16 13:57:51 -04001764 struct parser_context *parser_ctx = NULL;
Jes Sorensene82ba622015-05-05 18:35:45 -04001765 bool local_addr;
Benjamin Romer3ab47702014-10-23 14:30:31 -04001766 struct controlvm_message ackmsg;
Ken Cox12e364b2014-03-04 07:58:07 -06001767
1768 /* create parsing context if necessary */
Benjamin Romer818352a2015-03-16 13:58:31 -04001769 local_addr = (inmsg.hdr.flags.test_message == 1);
Benjamin Romer0aca78442015-03-04 12:14:25 -05001770 if (channel_addr == 0)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001771 return true;
Benjamin Romer818352a2015-03-16 13:58:31 -04001772 parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
1773 parm_bytes = inmsg.hdr.payload_bytes;
Ken Cox12e364b2014-03-04 07:58:07 -06001774
1775 /* Parameter and channel addresses within test messages actually lie
1776 * within our OS-controlled memory. We need to know that, because it
1777 * makes a difference in how we compute the virtual address.
1778 */
Jes Sorensenebec8962015-05-05 18:35:57 -04001779 if (parm_addr && parm_bytes) {
Jes Sorensenf4c11552015-04-13 10:28:40 -04001780 bool retry = false;
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001781
Ken Cox12e364b2014-03-04 07:58:07 -06001782 parser_ctx =
Benjamin Romer818352a2015-03-16 13:58:31 -04001783 parser_init_byte_stream(parm_addr, parm_bytes,
1784 local_addr, &retry);
Benjamin Romer1b088722015-03-04 12:14:26 -05001785 if (!parser_ctx && retry)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001786 return false;
Ken Cox12e364b2014-03-04 07:58:07 -06001787 }
1788
Benjamin Romer818352a2015-03-16 13:58:31 -04001789 if (!local_addr) {
Ken Cox12e364b2014-03-04 07:58:07 -06001790 controlvm_init_response(&ackmsg, &inmsg.hdr,
1791 CONTROLVM_RESP_SUCCESS);
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001792 if (controlvm_channel)
1793 visorchannel_signalinsert(controlvm_channel,
Benjamin Romer1b088722015-03-04 12:14:26 -05001794 CONTROLVM_QUEUE_ACK,
1795 &ackmsg);
Ken Cox12e364b2014-03-04 07:58:07 -06001796 }
Benjamin Romer98d7b592014-10-23 14:30:26 -04001797 switch (inmsg.hdr.id) {
Ken Cox12e364b2014-03-04 07:58:07 -06001798 case CONTROLVM_CHIPSET_INIT:
Ken Cox12e364b2014-03-04 07:58:07 -06001799 chipset_init(&inmsg);
1800 break;
1801 case CONTROLVM_BUS_CREATE:
Ken Cox12e364b2014-03-04 07:58:07 -06001802 bus_create(&inmsg);
1803 break;
1804 case CONTROLVM_BUS_DESTROY:
Ken Cox12e364b2014-03-04 07:58:07 -06001805 bus_destroy(&inmsg);
1806 break;
1807 case CONTROLVM_BUS_CONFIGURE:
Ken Cox12e364b2014-03-04 07:58:07 -06001808 bus_configure(&inmsg, parser_ctx);
1809 break;
1810 case CONTROLVM_DEVICE_CREATE:
Ken Cox12e364b2014-03-04 07:58:07 -06001811 my_device_create(&inmsg);
1812 break;
1813 case CONTROLVM_DEVICE_CHANGESTATE:
Benjamin Romer2ea51172014-10-23 14:30:25 -04001814 if (cmd->device_change_state.flags.phys_device) {
Ken Cox12e364b2014-03-04 07:58:07 -06001815 parahotplug_process_message(&inmsg);
1816 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06001817 /* save the hdr and cmd structures for later use */
1818 /* when sending back the response to Command */
1819 my_device_changestate(&inmsg);
Benjamin Romer4f44b722015-03-16 13:58:02 -04001820 g_devicechangestate_packet = inmsg.cmd;
Ken Cox12e364b2014-03-04 07:58:07 -06001821 break;
1822 }
1823 break;
1824 case CONTROLVM_DEVICE_DESTROY:
Ken Cox12e364b2014-03-04 07:58:07 -06001825 my_device_destroy(&inmsg);
1826 break;
1827 case CONTROLVM_DEVICE_CONFIGURE:
Ken Cox12e364b2014-03-04 07:58:07 -06001828 /* no op for now, just send a respond that we passed */
Benjamin Romer98d7b592014-10-23 14:30:26 -04001829 if (inmsg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001830 controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
1831 break;
1832 case CONTROLVM_CHIPSET_READY:
Ken Cox12e364b2014-03-04 07:58:07 -06001833 chipset_ready(&inmsg.hdr);
1834 break;
1835 case CONTROLVM_CHIPSET_SELFTEST:
Ken Cox12e364b2014-03-04 07:58:07 -06001836 chipset_selftest(&inmsg.hdr);
1837 break;
1838 case CONTROLVM_CHIPSET_STOP:
Ken Cox12e364b2014-03-04 07:58:07 -06001839 chipset_notready(&inmsg.hdr);
1840 break;
1841 default:
Benjamin Romer98d7b592014-10-23 14:30:26 -04001842 if (inmsg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001843 controlvm_respond(&inmsg.hdr,
Benjamin Romer818352a2015-03-16 13:58:31 -04001844 -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
Ken Cox12e364b2014-03-04 07:58:07 -06001845 break;
1846 }
1847
Benjamin Romer38f736e2015-03-16 13:58:13 -04001848 if (parser_ctx) {
Ken Cox12e364b2014-03-04 07:58:07 -06001849 parser_done(parser_ctx);
1850 parser_ctx = NULL;
1851 }
Jes Sorensenf4c11552015-04-13 10:28:40 -04001852 return true;
Ken Cox12e364b2014-03-04 07:58:07 -06001853}
1854
David Kershner5f3a7e32015-05-13 13:22:10 -04001855static inline unsigned int
1856issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes)
1857{
1858 struct vmcall_io_controlvm_addr_params params;
1859 int result = VMCALL_SUCCESS;
1860 u64 physaddr;
1861
1862 physaddr = virt_to_phys(&params);
1863 ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result);
1864 if (VMCALL_SUCCESSFUL(result)) {
1865 *control_addr = params.address;
1866 *control_bytes = params.channel_bytes;
1867 }
1868 return result;
1869}
1870
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001871static u64 controlvm_get_channel_address(void)
Benjamin Romer524b0b62014-07-17 12:39:57 -04001872{
Benjamin Romer5fc02292014-07-31 12:00:51 -04001873 u64 addr = 0;
Benjamin Romerb3c55b12014-07-31 12:00:50 -04001874 u32 size = 0;
Benjamin Romer524b0b62014-07-17 12:39:57 -04001875
Benjamin Romer0aca78442015-03-04 12:14:25 -05001876 if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size)))
Benjamin Romer524b0b62014-07-17 12:39:57 -04001877 return 0;
Benjamin Romer0aca78442015-03-04 12:14:25 -05001878
Benjamin Romer524b0b62014-07-17 12:39:57 -04001879 return addr;
1880}
1881
Ken Cox12e364b2014-03-04 07:58:07 -06001882static void
1883controlvm_periodic_work(struct work_struct *work)
1884{
Benjamin Romer3ab47702014-10-23 14:30:31 -04001885 struct controlvm_message inmsg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001886 bool got_command = false;
1887 bool handle_command_failed = false;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001888 static u64 poll_count;
Ken Cox12e364b2014-03-04 07:58:07 -06001889
1890 /* make sure visorbus server is registered for controlvm callbacks */
David Kershner4da33362015-05-05 18:36:39 -04001891 if (visorchipset_visorbusregwait && !visorbusregistered)
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001892 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001893
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001894 poll_count++;
1895 if (poll_count >= 250)
Ken Cox12e364b2014-03-04 07:58:07 -06001896 ; /* keep going */
1897 else
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001898 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001899
1900 /* Check events to determine if response to CHIPSET_READY
1901 * should be sent
1902 */
Benjamin Romer0639ba62015-03-16 13:58:04 -04001903 if (visorchipset_holdchipsetready &&
1904 (g_chipset_msg_hdr.id != CONTROLVM_INVALID)) {
Ken Cox12e364b2014-03-04 07:58:07 -06001905 if (check_chipset_events() == 1) {
Benjamin Romerda021f02015-03-16 13:57:58 -04001906 controlvm_respond(&g_chipset_msg_hdr, 0);
Ken Cox12e364b2014-03-04 07:58:07 -06001907 clear_chipset_events();
Benjamin Romerda021f02015-03-16 13:57:58 -04001908 memset(&g_chipset_msg_hdr, 0,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001909 sizeof(struct controlvm_message_header));
Ken Cox12e364b2014-03-04 07:58:07 -06001910 }
1911 }
1912
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001913 while (visorchannel_signalremove(controlvm_channel,
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001914 CONTROLVM_QUEUE_RESPONSE,
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001915 &inmsg))
1916 ;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001917 if (!got_command) {
Benjamin Romer7166ed12015-03-16 13:58:38 -04001918 if (controlvm_pending_msg_valid) {
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001919 /* we throttled processing of a prior
1920 * msg, so try to process it again
1921 * rather than reading a new one
1922 */
Benjamin Romer7166ed12015-03-16 13:58:38 -04001923 inmsg = controlvm_pending_msg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001924 controlvm_pending_msg_valid = false;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001925 got_command = true;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001926 } else {
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001927 got_command = read_controlvm_event(&inmsg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001928 }
Ken Cox12e364b2014-03-04 07:58:07 -06001929 }
1930
Jes Sorensenf4c11552015-04-13 10:28:40 -04001931 handle_command_failed = false;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001932 while (got_command && (!handle_command_failed)) {
Benjamin Romerb53e0e92015-03-16 13:57:56 -04001933 most_recent_message_jiffies = jiffies;
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001934 if (handle_command(inmsg,
1935 visorchannel_get_physaddr
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001936 (controlvm_channel)))
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001937 got_command = read_controlvm_event(&inmsg);
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001938 else {
1939 /* this is a scenario where throttling
1940 * is required, but probably NOT an
1941 * error...; we stash the current
1942 * controlvm msg so we will attempt to
1943 * reprocess it on our next loop
1944 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001945 handle_command_failed = true;
Benjamin Romer7166ed12015-03-16 13:58:38 -04001946 controlvm_pending_msg = inmsg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001947 controlvm_pending_msg_valid = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001948 }
1949 }
1950
1951 /* parahotplug_worker */
1952 parahotplug_process_list();
1953
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001954cleanup:
Ken Cox12e364b2014-03-04 07:58:07 -06001955
1956 if (time_after(jiffies,
Benjamin Romerb53e0e92015-03-16 13:57:56 -04001957 most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) {
Ken Cox12e364b2014-03-04 07:58:07 -06001958 /* it's been longer than MIN_IDLE_SECONDS since we
1959 * processed our last controlvm message; slow down the
1960 * polling
1961 */
Benjamin Romer911e2132015-03-16 13:57:47 -04001962 if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW)
1963 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
Ken Cox12e364b2014-03-04 07:58:07 -06001964 } else {
Benjamin Romer911e2132015-03-16 13:57:47 -04001965 if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST)
1966 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Ken Cox12e364b2014-03-04 07:58:07 -06001967 }
1968
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05301969 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
Ken Cox12e364b2014-03-04 07:58:07 -06001970}
1971
1972static void
1973setup_crash_devices_work_queue(struct work_struct *work)
1974{
Benjamin Romere6bdb902015-03-16 13:58:33 -04001975 struct controlvm_message local_crash_bus_msg;
1976 struct controlvm_message local_crash_dev_msg;
Benjamin Romer3ab47702014-10-23 14:30:31 -04001977 struct controlvm_message msg;
Benjamin Romere6bdb902015-03-16 13:58:33 -04001978 u32 local_crash_msg_offset;
1979 u16 local_crash_msg_count;
Ken Cox12e364b2014-03-04 07:58:07 -06001980
David Kershner4da33362015-05-05 18:36:39 -04001981 /* make sure visorbus is registered for controlvm callbacks */
1982 if (visorchipset_visorbusregwait && !visorbusregistered)
Benjamin Romere6bdb902015-03-16 13:58:33 -04001983 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001984
1985 POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
1986
1987 /* send init chipset msg */
Benjamin Romer98d7b592014-10-23 14:30:26 -04001988 msg.hdr.id = CONTROLVM_CHIPSET_INIT;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001989 msg.cmd.init_chipset.bus_count = 23;
1990 msg.cmd.init_chipset.switch_count = 0;
Ken Cox12e364b2014-03-04 07:58:07 -06001991
1992 chipset_init(&msg);
1993
Ken Cox12e364b2014-03-04 07:58:07 -06001994 /* get saved message count */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001995 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001996 offsetof(struct spar_controlvm_channel_protocol,
1997 saved_crash_message_count),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001998 &local_crash_msg_count, sizeof(u16)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001999 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
2000 POSTCODE_SEVERITY_ERR);
2001 return;
2002 }
2003
Benjamin Romere6bdb902015-03-16 13:58:33 -04002004 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
Ken Cox12e364b2014-03-04 07:58:07 -06002005 POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
Benjamin Romere6bdb902015-03-16 13:58:33 -04002006 local_crash_msg_count,
Ken Cox12e364b2014-03-04 07:58:07 -06002007 POSTCODE_SEVERITY_ERR);
2008 return;
2009 }
2010
2011 /* get saved crash message offset */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002012 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04002013 offsetof(struct spar_controlvm_channel_protocol,
2014 saved_crash_message_offset),
Benjamin Romere6bdb902015-03-16 13:58:33 -04002015 &local_crash_msg_offset, sizeof(u32)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06002016 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
2017 POSTCODE_SEVERITY_ERR);
2018 return;
2019 }
2020
2021 /* read create device message for storage bus offset */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002022 if (visorchannel_read(controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04002023 local_crash_msg_offset,
2024 &local_crash_bus_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04002025 sizeof(struct controlvm_message)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06002026 POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC,
2027 POSTCODE_SEVERITY_ERR);
2028 return;
2029 }
2030
2031 /* read create device message for storage device */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002032 if (visorchannel_read(controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04002033 local_crash_msg_offset +
Benjamin Romer3ab47702014-10-23 14:30:31 -04002034 sizeof(struct controlvm_message),
Benjamin Romere6bdb902015-03-16 13:58:33 -04002035 &local_crash_dev_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04002036 sizeof(struct controlvm_message)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06002037 POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
2038 POSTCODE_SEVERITY_ERR);
2039 return;
2040 }
2041
2042 /* reuse IOVM create bus message */
Jes Sorensenebec8962015-05-05 18:35:57 -04002043 if (local_crash_bus_msg.cmd.create_bus.channel_addr) {
Benjamin Romere6bdb902015-03-16 13:58:33 -04002044 bus_create(&local_crash_bus_msg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04002045 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06002046 POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
2047 POSTCODE_SEVERITY_ERR);
2048 return;
2049 }
2050
2051 /* reuse create device message for storage device */
Jes Sorensenebec8962015-05-05 18:35:57 -04002052 if (local_crash_dev_msg.cmd.create_device.channel_addr) {
Benjamin Romere6bdb902015-03-16 13:58:33 -04002053 my_device_create(&local_crash_dev_msg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04002054 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06002055 POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
2056 POSTCODE_SEVERITY_ERR);
2057 return;
2058 }
Ken Cox12e364b2014-03-04 07:58:07 -06002059 POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
2060 return;
2061
Benjamin Romere6bdb902015-03-16 13:58:33 -04002062cleanup:
Ken Cox12e364b2014-03-04 07:58:07 -06002063
Benjamin Romer911e2132015-03-16 13:57:47 -04002064 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
Ken Cox12e364b2014-03-04 07:58:07 -06002065
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302066 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
Ken Cox12e364b2014-03-04 07:58:07 -06002067}
2068
2069static void
Don Zickusd32517e2015-06-04 09:22:41 -04002070bus_create_response(struct visor_device *bus_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002071{
Alessandro Parini4b4fd432015-06-13 17:40:48 +02002072 if (response >= 0)
Don Zickus0274b5a2015-06-01 13:00:27 -04002073 bus_info->state.created = 1;
Don Zickus0274b5a2015-06-01 13:00:27 -04002074
2075 bus_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr,
2076 response);
2077
2078 kfree(bus_info->pending_msg_hdr);
2079 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002080}
2081
2082static void
Don Zickusd32517e2015-06-04 09:22:41 -04002083bus_destroy_response(struct visor_device *bus_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002084{
Don Zickus0274b5a2015-06-01 13:00:27 -04002085 bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr,
2086 response);
2087
2088 kfree(bus_info->pending_msg_hdr);
2089 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002090}
2091
2092static void
Don Zickusa298bc02015-06-04 09:22:42 -04002093device_create_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002094{
Don Zickus0274b5a2015-06-01 13:00:27 -04002095 if (response >= 0)
2096 dev_info->state.created = 1;
2097
2098 device_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr,
2099 response);
2100
2101 kfree(dev_info->pending_msg_hdr);
Tim Selladdce192015-07-09 13:27:41 -04002102 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002103}
2104
2105static void
Don Zickusa298bc02015-06-04 09:22:42 -04002106device_destroy_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002107{
Don Zickus0274b5a2015-06-01 13:00:27 -04002108 device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr,
2109 response);
2110
2111 kfree(dev_info->pending_msg_hdr);
2112 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002113}
2114
Jes Sorensend3368a52015-05-13 13:21:57 -04002115static void
Don Zickusa298bc02015-06-04 09:22:42 -04002116visorchipset_device_pause_response(struct visor_device *dev_info,
Don Zickusb4b598f2015-05-13 13:22:25 -04002117 int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002118{
Ken Cox12e364b2014-03-04 07:58:07 -06002119 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
Don Zickusb4b598f2015-05-13 13:22:25 -04002120 dev_info, response,
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04002121 segment_state_standby);
Don Zickus0274b5a2015-06-01 13:00:27 -04002122
2123 kfree(dev_info->pending_msg_hdr);
2124 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002125}
Ken Cox12e364b2014-03-04 07:58:07 -06002126
2127static void
Don Zickusa298bc02015-06-04 09:22:42 -04002128device_resume_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002129{
2130 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
Don Zickusb4b598f2015-05-13 13:22:25 -04002131 dev_info, response,
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04002132 segment_state_running);
Don Zickus0274b5a2015-06-01 13:00:27 -04002133
2134 kfree(dev_info->pending_msg_hdr);
2135 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002136}
2137
Benjamin Romer18b87ed2014-07-24 14:08:43 -04002138static ssize_t chipsetready_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -04002139 struct device_attribute *attr,
2140 const char *buf, size_t count)
Ken Cox12e364b2014-03-04 07:58:07 -06002141{
Benjamin Romer18b87ed2014-07-24 14:08:43 -04002142 char msgtype[64];
Ken Cox12e364b2014-03-04 07:58:07 -06002143
Benjamin Romer66e24b72014-07-25 13:55:10 -04002144 if (sscanf(buf, "%63s", msgtype) != 1)
Ken Cox12e364b2014-03-04 07:58:07 -06002145 return -EINVAL;
Benjamin Romer66e24b72014-07-25 13:55:10 -04002146
Jes Sorensenebec8962015-05-05 18:35:57 -04002147 if (!strcmp(msgtype, "CALLHOMEDISK_MOUNTED")) {
Benjamin Romer66e24b72014-07-25 13:55:10 -04002148 chipset_events[0] = 1;
2149 return count;
Jes Sorensenebec8962015-05-05 18:35:57 -04002150 } else if (!strcmp(msgtype, "MODULES_LOADED")) {
Benjamin Romer66e24b72014-07-25 13:55:10 -04002151 chipset_events[1] = 1;
2152 return count;
Benjamin Romere22a4a02014-08-18 09:34:54 -04002153 }
2154 return -EINVAL;
Ken Cox12e364b2014-03-04 07:58:07 -06002155}
2156
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002157/* The parahotplug/devicedisabled interface gets called by our support script
2158 * when an SR-IOV device has been shut down. The ID is passed to the script
2159 * and then passed back when the device has been removed.
2160 */
2161static ssize_t devicedisabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -04002162 struct device_attribute *attr,
2163 const char *buf, size_t count)
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002164{
Jes Sorensen94217362015-05-05 18:35:46 -04002165 unsigned int id;
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002166
Jes Sorensenebec8962015-05-05 18:35:57 -04002167 if (kstrtouint(buf, 10, &id))
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002168 return -EINVAL;
2169
2170 parahotplug_request_complete(id, 0);
2171 return count;
2172}
2173
2174/* The parahotplug/deviceenabled interface gets called by our support script
2175 * when an SR-IOV device has been recovered. The ID is passed to the script
2176 * and then passed back when the device has been brought back up.
2177 */
2178static ssize_t deviceenabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -04002179 struct device_attribute *attr,
2180 const char *buf, size_t count)
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002181{
Jes Sorensen94217362015-05-05 18:35:46 -04002182 unsigned int id;
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002183
Jes Sorensenebec8962015-05-05 18:35:57 -04002184 if (kstrtouint(buf, 10, &id))
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002185 return -EINVAL;
2186
2187 parahotplug_request_complete(id, 1);
2188 return count;
2189}
2190
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002191static int
2192visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
2193{
2194 unsigned long physaddr = 0;
2195 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
Erik Arfvidson780fcad2015-05-05 18:36:35 -04002196 u64 addr = 0;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002197
2198 /* sv_enable_dfp(); */
2199 if (offset & (PAGE_SIZE - 1))
2200 return -ENXIO; /* need aligned offsets */
2201
2202 switch (offset) {
2203 case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
2204 vma->vm_flags |= VM_IO;
2205 if (!*file_controlvm_channel)
2206 return -ENXIO;
2207
2208 visorchannel_read(*file_controlvm_channel,
2209 offsetof(struct spar_controlvm_channel_protocol,
2210 gp_control_channel),
2211 &addr, sizeof(addr));
2212 if (!addr)
2213 return -ENXIO;
2214
2215 physaddr = (unsigned long)addr;
2216 if (remap_pfn_range(vma, vma->vm_start,
2217 physaddr >> PAGE_SHIFT,
2218 vma->vm_end - vma->vm_start,
2219 /*pgprot_noncached */
2220 (vma->vm_page_prot))) {
2221 return -EAGAIN;
2222 }
2223 break;
2224 default:
2225 return -ENXIO;
2226 }
2227 return 0;
2228}
2229
David Kershner5f3a7e32015-05-13 13:22:10 -04002230static inline s64 issue_vmcall_query_guest_virtual_time_offset(void)
2231{
2232 u64 result = VMCALL_SUCCESS;
2233 u64 physaddr = 0;
2234
2235 ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr,
2236 result);
2237 return result;
2238}
2239
2240static inline int issue_vmcall_update_physical_time(u64 adjustment)
2241{
2242 int result = VMCALL_SUCCESS;
2243
2244 ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result);
2245 return result;
2246}
2247
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002248static long visorchipset_ioctl(struct file *file, unsigned int cmd,
2249 unsigned long arg)
2250{
David Kershner25002762016-03-03 13:00:38 -05002251 u64 adjustment;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002252 s64 vrtc_offset;
2253
2254 switch (cmd) {
2255 case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET:
2256 /* get the physical rtc offset */
2257 vrtc_offset = issue_vmcall_query_guest_virtual_time_offset();
2258 if (copy_to_user((void __user *)arg, &vrtc_offset,
2259 sizeof(vrtc_offset))) {
2260 return -EFAULT;
2261 }
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002262 return 0;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002263 case VMCALL_UPDATE_PHYSICAL_TIME:
2264 if (copy_from_user(&adjustment, (void __user *)arg,
2265 sizeof(adjustment))) {
2266 return -EFAULT;
2267 }
2268 return issue_vmcall_update_physical_time(adjustment);
2269 default:
2270 return -EFAULT;
2271 }
2272}
2273
2274static const struct file_operations visorchipset_fops = {
2275 .owner = THIS_MODULE,
2276 .open = visorchipset_open,
2277 .read = NULL,
2278 .write = NULL,
2279 .unlocked_ioctl = visorchipset_ioctl,
2280 .release = visorchipset_release,
2281 .mmap = visorchipset_mmap,
2282};
2283
Jes Sorensen0f570fc2015-05-13 13:21:55 -04002284static int
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002285visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
2286{
2287 int rc = 0;
2288
2289 file_controlvm_channel = controlvm_channel;
2290 cdev_init(&file_cdev, &visorchipset_fops);
2291 file_cdev.owner = THIS_MODULE;
2292 if (MAJOR(major_dev) == 0) {
Erik Arfvidson46168812015-05-05 18:36:14 -04002293 rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset");
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002294 /* dynamic major device number registration required */
2295 if (rc < 0)
2296 return rc;
2297 } else {
2298 /* static major device number registration required */
Erik Arfvidson46168812015-05-05 18:36:14 -04002299 rc = register_chrdev_region(major_dev, 1, "visorchipset");
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002300 if (rc < 0)
2301 return rc;
2302 }
2303 rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1);
2304 if (rc < 0) {
2305 unregister_chrdev_region(major_dev, 1);
2306 return rc;
2307 }
2308 return 0;
2309}
2310
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002311static int
2312visorchipset_init(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06002313{
David Kershner33078252015-05-05 18:36:48 -04002314 int rc = 0;
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002315 u64 addr;
Jes Sorensend3368a52015-05-13 13:21:57 -04002316 uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID;
2317
2318 addr = controlvm_get_channel_address();
2319 if (!addr)
2320 return -ENODEV;
Ken Cox12e364b2014-03-04 07:58:07 -06002321
David Kershner4da33362015-05-05 18:36:39 -04002322 memset(&busdev_notifiers, 0, sizeof(busdev_notifiers));
Benjamin Romer84982fb2015-03-16 13:58:07 -04002323 memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06002324
Tim Sellc732623b2016-03-01 19:45:03 -05002325 controlvm_channel = visorchannel_create_with_lock(addr, 0,
Jes Sorensend3368a52015-05-13 13:21:57 -04002326 GFP_KERNEL, uuid);
Tim Sellc732623b2016-03-01 19:45:03 -05002327 if (!controlvm_channel)
2328 return -ENODEV;
Jes Sorensend3368a52015-05-13 13:21:57 -04002329 if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
2330 visorchannel_get_header(controlvm_channel))) {
2331 initialize_controlvm_payload();
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002332 } else {
Jes Sorensend3368a52015-05-13 13:21:57 -04002333 visorchannel_destroy(controlvm_channel);
2334 controlvm_channel = NULL;
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002335 return -ENODEV;
2336 }
2337
Benjamin Romer5aa8ae52015-03-16 13:58:44 -04002338 major_dev = MKDEV(visorchipset_major, 0);
2339 rc = visorchipset_file_init(major_dev, &controlvm_channel);
Ken Cox4cb005a2014-03-19 13:06:20 -05002340 if (rc < 0) {
Ken Cox4cb005a2014-03-19 13:06:20 -05002341 POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR);
Benjamin Romera6a39892015-03-16 13:58:34 -04002342 goto cleanup;
Ken Cox4cb005a2014-03-19 13:06:20 -05002343 }
Ken Cox9f8d0e82014-03-19 13:06:19 -05002344
Benjamin Romerda021f02015-03-16 13:57:58 -04002345 memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header));
Ken Cox12e364b2014-03-04 07:58:07 -06002346
David Kershner4da33362015-05-05 18:36:39 -04002347 /* if booting in a crash kernel */
2348 if (is_kdump_kernel())
2349 INIT_DELAYED_WORK(&periodic_controlvm_work,
2350 setup_crash_devices_work_queue);
2351 else
2352 INIT_DELAYED_WORK(&periodic_controlvm_work,
2353 controlvm_periodic_work);
Ken Cox12e364b2014-03-04 07:58:07 -06002354
David Kershner4da33362015-05-05 18:36:39 -04002355 most_recent_message_jiffies = jiffies;
2356 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302357 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
Ken Cox12e364b2014-03-04 07:58:07 -06002358
Benjamin Romereb34e872015-03-16 13:58:45 -04002359 visorchipset_platform_device.dev.devt = major_dev;
2360 if (platform_device_register(&visorchipset_platform_device) < 0) {
Ken Cox4cb005a2014-03-19 13:06:20 -05002361 POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR);
Benjamin Romerfbd91612016-02-23 10:01:55 -05002362 rc = -ENODEV;
Benjamin Romera6a39892015-03-16 13:58:34 -04002363 goto cleanup;
Ken Cox4cb005a2014-03-19 13:06:20 -05002364 }
Ken Cox12e364b2014-03-04 07:58:07 -06002365 POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04002366
2367 rc = visorbus_init();
Benjamin Romera6a39892015-03-16 13:58:34 -04002368cleanup:
Ken Cox12e364b2014-03-04 07:58:07 -06002369 if (rc) {
Ken Cox12e364b2014-03-04 07:58:07 -06002370 POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
2371 POSTCODE_SEVERITY_ERR);
2372 }
2373 return rc;
2374}
2375
Jes Sorensen0f570fc2015-05-13 13:21:55 -04002376static void
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002377visorchipset_file_cleanup(dev_t major_dev)
2378{
2379 if (file_cdev.ops)
2380 cdev_del(&file_cdev);
2381 file_cdev.ops = NULL;
2382 unregister_chrdev_region(major_dev, 1);
2383}
2384
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002385static int
2386visorchipset_exit(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06002387{
Ken Cox12e364b2014-03-04 07:58:07 -06002388 POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
2389
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04002390 visorbus_exit();
2391
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302392 cancel_delayed_work_sync(&periodic_controlvm_work);
David Kershner4da33362015-05-05 18:36:39 -04002393 destroy_controlvm_payload_info(&controlvm_payload_info);
Benjamin Romer17833192014-07-15 13:30:41 -04002394
Benjamin Romerda021f02015-03-16 13:57:58 -04002395 memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header));
Ken Cox12e364b2014-03-04 07:58:07 -06002396
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002397 visorchannel_destroy(controlvm_channel);
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002398
Sudip Mukherjeeaddceb12015-03-24 20:47:28 +05302399 visorchipset_file_cleanup(visorchipset_platform_device.dev.devt);
Don Zickus04dacac2015-06-04 09:22:48 -04002400 platform_device_unregister(&visorchipset_platform_device);
Ken Cox12e364b2014-03-04 07:58:07 -06002401 POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002402
2403 return 0;
2404}
2405
2406static const struct acpi_device_id unisys_device_ids[] = {
2407 {"PNP0A07", 0},
2408 {"", 0},
2409};
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002410
2411static struct acpi_driver unisys_acpi_driver = {
2412 .name = "unisys_acpi",
2413 .class = "unisys_acpi_class",
2414 .owner = THIS_MODULE,
2415 .ids = unisys_device_ids,
2416 .ops = {
2417 .add = visorchipset_init,
2418 .remove = visorchipset_exit,
2419 },
2420};
David Kershner1fc07f92015-07-09 13:27:53 -04002421
2422MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
2423
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002424static __init uint32_t visorutil_spar_detect(void)
2425{
2426 unsigned int eax, ebx, ecx, edx;
2427
Borislav Petkov0c9f3532016-03-29 17:41:55 +02002428 if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002429 /* check the ID */
2430 cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
2431 return (ebx == UNISYS_SPAR_ID_EBX) &&
2432 (ecx == UNISYS_SPAR_ID_ECX) &&
2433 (edx == UNISYS_SPAR_ID_EDX);
2434 } else {
2435 return 0;
2436 }
2437}
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002438
2439static int init_unisys(void)
2440{
2441 int result;
Alessandro Parini35e606d2015-06-13 17:40:49 +02002442
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002443 if (!visorutil_spar_detect())
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002444 return -ENODEV;
2445
2446 result = acpi_bus_register_driver(&unisys_acpi_driver);
2447 if (result)
2448 return -ENODEV;
2449
2450 pr_info("Unisys Visorchipset Driver Loaded.\n");
2451 return 0;
2452};
2453
2454static void exit_unisys(void)
2455{
2456 acpi_bus_unregister_driver(&unisys_acpi_driver);
Ken Cox12e364b2014-03-04 07:58:07 -06002457}
2458
Ken Cox12e364b2014-03-04 07:58:07 -06002459module_param_named(major, visorchipset_major, int, S_IRUGO);
Jes Sorensenb615d622015-05-05 18:35:38 -04002460MODULE_PARM_DESC(visorchipset_major,
2461 "major device number to use for the device node");
David Kershner4da33362015-05-05 18:36:39 -04002462module_param_named(visorbusregwait, visorchipset_visorbusregwait, int, S_IRUGO);
2463MODULE_PARM_DESC(visorchipset_visorbusreqwait,
Ken Cox12e364b2014-03-04 07:58:07 -06002464 "1 to have the module wait for the visor bus to register");
Ken Cox12e364b2014-03-04 07:58:07 -06002465module_param_named(holdchipsetready, visorchipset_holdchipsetready,
2466 int, S_IRUGO);
2467MODULE_PARM_DESC(visorchipset_holdchipsetready,
2468 "1 to hold response to CHIPSET_READY");
Jes Sorensenb615d622015-05-05 18:35:38 -04002469
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002470module_init(init_unisys);
2471module_exit(exit_unisys);
Ken Cox12e364b2014-03-04 07:58:07 -06002472
2473MODULE_AUTHOR("Unisys");
2474MODULE_LICENSE("GPL");
2475MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver "
2476 VERSION);
2477MODULE_VERSION(VERSION);