blob: e278595d68e2a238d93a739569a37ad042590db2 [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;
David Kershnerd79f56b2016-03-11 17:01:40 -0500362 struct parser_context *ctx;
Erik Arfvidson46168812015-05-05 18:36:14 -0400363
364 if (retry)
365 *retry = false;
Jes Sorensencc55b5c2015-05-05 18:37:13 -0400366
367 /*
368 * alloc an 0 extra byte to ensure payload is
369 * '\0'-terminated
370 */
371 allocbytes++;
Erik Arfvidson46168812015-05-05 18:36:14 -0400372 if ((controlvm_payload_bytes_buffered + bytes)
373 > MAX_CONTROLVM_PAYLOAD_BYTES) {
374 if (retry)
375 *retry = true;
David Kershnerd79f56b2016-03-11 17:01:40 -0500376 return NULL;
Erik Arfvidson46168812015-05-05 18:36:14 -0400377 }
Erik Arfvidson8c395e72016-02-08 10:41:45 -0500378 ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY);
Erik Arfvidson46168812015-05-05 18:36:14 -0400379 if (!ctx) {
380 if (retry)
381 *retry = true;
David Kershnerd79f56b2016-03-11 17:01:40 -0500382 return NULL;
Erik Arfvidson46168812015-05-05 18:36:14 -0400383 }
384
385 ctx->allocbytes = allocbytes;
386 ctx->param_bytes = bytes;
387 ctx->curr = NULL;
388 ctx->bytes_remaining = 0;
389 ctx->byte_stream = false;
390 if (local) {
391 void *p;
392
David Kershnerd79f56b2016-03-11 17:01:40 -0500393 if (addr > virt_to_phys(high_memory - 1))
394 goto err_finish_ctx;
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500395 p = __va((unsigned long)(addr));
Erik Arfvidson46168812015-05-05 18:36:14 -0400396 memcpy(ctx->data, p, bytes);
397 } else {
Tim Sella8deaef2016-03-01 19:45:02 -0500398 void *mapping = memremap(addr, bytes, MEMREMAP_WB);
Jes Sorensen712c03d2015-05-05 18:36:25 -0400399
David Kershnerd79f56b2016-03-11 17:01:40 -0500400 if (!mapping)
401 goto err_finish_ctx;
Dan Williams3103dc02015-08-10 23:07:06 -0400402 memcpy(ctx->data, mapping, bytes);
Dan Williams3103dc02015-08-10 23:07:06 -0400403 memunmap(mapping);
Erik Arfvidson46168812015-05-05 18:36:14 -0400404 }
Erik Arfvidson46168812015-05-05 18:36:14 -0400405
Jes Sorensencc55b5c2015-05-05 18:37:13 -0400406 ctx->byte_stream = true;
David Kershnerd79f56b2016-03-11 17:01:40 -0500407 controlvm_payload_bytes_buffered += ctx->param_bytes;
408
409 return ctx;
410
411err_finish_ctx:
412 parser_done(ctx);
413 return NULL;
Erik Arfvidson46168812015-05-05 18:36:14 -0400414}
415
Jes Sorensen464129e2015-05-05 18:37:12 -0400416static uuid_le
Erik Arfvidson46168812015-05-05 18:36:14 -0400417parser_id_get(struct parser_context *ctx)
418{
419 struct spar_controlvm_parameters_header *phdr = NULL;
420
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500421 if (!ctx)
Erik Arfvidson46168812015-05-05 18:36:14 -0400422 return NULL_UUID_LE;
423 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
424 return phdr->id;
425}
426
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400427/** Describes the state from the perspective of which controlvm messages have
428 * been received for a bus or device.
429 */
430
431enum PARSER_WHICH_STRING {
432 PARSERSTRING_INITIATOR,
433 PARSERSTRING_TARGET,
434 PARSERSTRING_CONNECTION,
435 PARSERSTRING_NAME, /* TODO: only PARSERSTRING_NAME is used ? */
436};
437
Jes Sorensen464129e2015-05-05 18:37:12 -0400438static void
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400439parser_param_start(struct parser_context *ctx,
440 enum PARSER_WHICH_STRING which_string)
Erik Arfvidson46168812015-05-05 18:36:14 -0400441{
442 struct spar_controlvm_parameters_header *phdr = NULL;
443
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500444 if (!ctx)
Benjamin Romerb4d4dfb2016-02-08 10:41:53 -0500445 return;
446
Erik Arfvidson46168812015-05-05 18:36:14 -0400447 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
448 switch (which_string) {
449 case PARSERSTRING_INITIATOR:
450 ctx->curr = ctx->data + phdr->initiator_offset;
451 ctx->bytes_remaining = phdr->initiator_length;
452 break;
453 case PARSERSTRING_TARGET:
454 ctx->curr = ctx->data + phdr->target_offset;
455 ctx->bytes_remaining = phdr->target_length;
456 break;
457 case PARSERSTRING_CONNECTION:
458 ctx->curr = ctx->data + phdr->connection_offset;
459 ctx->bytes_remaining = phdr->connection_length;
460 break;
461 case PARSERSTRING_NAME:
462 ctx->curr = ctx->data + phdr->name_offset;
463 ctx->bytes_remaining = phdr->name_length;
464 break;
465 default:
466 break;
467 }
Erik Arfvidson46168812015-05-05 18:36:14 -0400468}
469
Jes Sorensen464129e2015-05-05 18:37:12 -0400470static void parser_done(struct parser_context *ctx)
Erik Arfvidson46168812015-05-05 18:36:14 -0400471{
472 if (!ctx)
473 return;
474 controlvm_payload_bytes_buffered -= ctx->param_bytes;
475 kfree(ctx);
476}
477
Jes Sorensen464129e2015-05-05 18:37:12 -0400478static void *
Erik Arfvidson46168812015-05-05 18:36:14 -0400479parser_string_get(struct parser_context *ctx)
480{
481 u8 *pscan;
482 unsigned long nscan;
483 int value_length = -1;
484 void *value = NULL;
485 int i;
486
487 if (!ctx)
488 return NULL;
489 pscan = ctx->curr;
490 nscan = ctx->bytes_remaining;
491 if (nscan == 0)
492 return NULL;
493 if (!pscan)
494 return NULL;
495 for (i = 0, value_length = -1; i < nscan; i++)
496 if (pscan[i] == '\0') {
497 value_length = i;
498 break;
499 }
500 if (value_length < 0) /* '\0' was not included in the length */
501 value_length = nscan;
Erik Arfvidson8c395e72016-02-08 10:41:45 -0500502 value = kmalloc(value_length + 1, GFP_KERNEL | __GFP_NORETRY);
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500503 if (!value)
Erik Arfvidson46168812015-05-05 18:36:14 -0400504 return NULL;
505 if (value_length > 0)
506 memcpy(value, pscan, value_length);
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500507 ((u8 *)(value))[value_length] = '\0';
Erik Arfvidson46168812015-05-05 18:36:14 -0400508 return value;
509}
510
Vincent Bernatd746cb52014-08-01 10:29:30 +0200511static ssize_t toolaction_show(struct device *dev,
512 struct device_attribute *attr,
513 char *buf)
Benjamin Romer19f66342014-07-22 09:56:25 -0400514{
Benjamin Romer01f4d852015-03-16 13:58:48 -0400515 u8 tool_action;
Benjamin Romer19f66342014-07-22 09:56:25 -0400516
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400517 visorchannel_read(controlvm_channel,
Benjamin Romer6bb871b2015-12-07 10:58:37 -0500518 offsetof(struct spar_controlvm_channel_protocol,
519 tool_action), &tool_action, sizeof(u8));
Benjamin Romer01f4d852015-03-16 13:58:48 -0400520 return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action);
Benjamin Romer19f66342014-07-22 09:56:25 -0400521}
522
Vincent Bernatd746cb52014-08-01 10:29:30 +0200523static ssize_t toolaction_store(struct device *dev,
524 struct device_attribute *attr,
525 const char *buf, size_t count)
Benjamin Romer19f66342014-07-22 09:56:25 -0400526{
Benjamin Romer01f4d852015-03-16 13:58:48 -0400527 u8 tool_action;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400528 int ret;
Benjamin Romer19f66342014-07-22 09:56:25 -0400529
Jes Sorensenebec8962015-05-05 18:35:57 -0400530 if (kstrtou8(buf, 10, &tool_action))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400531 return -EINVAL;
532
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400533 ret = visorchannel_write(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400534 offsetof(struct spar_controlvm_channel_protocol,
535 tool_action),
Benjamin Romer01f4d852015-03-16 13:58:48 -0400536 &tool_action, sizeof(u8));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400537
538 if (ret)
539 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400540 return count;
Benjamin Romer19f66342014-07-22 09:56:25 -0400541}
542
Vincent Bernatd746cb52014-08-01 10:29:30 +0200543static ssize_t boottotool_show(struct device *dev,
544 struct device_attribute *attr,
545 char *buf)
Benjamin Romer54b31222014-07-22 09:56:26 -0400546{
Benjamin Romer365522d2015-03-16 13:58:49 -0400547 struct efi_spar_indication efi_spar_indication;
Benjamin Romer54b31222014-07-22 09:56:26 -0400548
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400549 visorchannel_read(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400550 offsetof(struct spar_controlvm_channel_protocol,
551 efi_spar_ind), &efi_spar_indication,
552 sizeof(struct efi_spar_indication));
Benjamin Romer54b31222014-07-22 09:56:26 -0400553 return scnprintf(buf, PAGE_SIZE, "%u\n",
Benjamin Romer8e76e692015-03-16 13:58:52 -0400554 efi_spar_indication.boot_to_tool);
Benjamin Romer54b31222014-07-22 09:56:26 -0400555}
556
Vincent Bernatd746cb52014-08-01 10:29:30 +0200557static ssize_t boottotool_store(struct device *dev,
558 struct device_attribute *attr,
559 const char *buf, size_t count)
Benjamin Romer54b31222014-07-22 09:56:26 -0400560{
Benjamin Romer66e24b72014-07-25 13:55:10 -0400561 int val, ret;
Benjamin Romer365522d2015-03-16 13:58:49 -0400562 struct efi_spar_indication efi_spar_indication;
Benjamin Romer54b31222014-07-22 09:56:26 -0400563
Jes Sorensenebec8962015-05-05 18:35:57 -0400564 if (kstrtoint(buf, 10, &val))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400565 return -EINVAL;
566
Benjamin Romer365522d2015-03-16 13:58:49 -0400567 efi_spar_indication.boot_to_tool = val;
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400568 ret = visorchannel_write(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -0400569 offsetof(struct spar_controlvm_channel_protocol,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400570 efi_spar_ind), &(efi_spar_indication),
571 sizeof(struct efi_spar_indication));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400572
573 if (ret)
574 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400575 return count;
Benjamin Romer54b31222014-07-22 09:56:26 -0400576}
Benjamin Romer422af172014-07-24 14:08:42 -0400577
578static ssize_t error_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400579 char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400580{
581 u32 error;
582
Benjamin Romer8e76e692015-03-16 13:58:52 -0400583 visorchannel_read(controlvm_channel,
584 offsetof(struct spar_controlvm_channel_protocol,
585 installation_error),
586 &error, sizeof(u32));
Benjamin Romer422af172014-07-24 14:08:42 -0400587 return scnprintf(buf, PAGE_SIZE, "%i\n", error);
588}
589
590static ssize_t error_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400591 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400592{
593 u32 error;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400594 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400595
Jes Sorensenebec8962015-05-05 18:35:57 -0400596 if (kstrtou32(buf, 10, &error))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400597 return -EINVAL;
598
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400599 ret = visorchannel_write(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400600 offsetof(struct spar_controlvm_channel_protocol,
601 installation_error),
602 &error, sizeof(u32));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400603 if (ret)
604 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400605 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400606}
607
608static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400609 char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400610{
Benjamin Romer10dbf0e2015-03-16 13:58:50 -0400611 u32 text_id;
Benjamin Romer422af172014-07-24 14:08:42 -0400612
Benjamin Romer8e76e692015-03-16 13:58:52 -0400613 visorchannel_read(controlvm_channel,
614 offsetof(struct spar_controlvm_channel_protocol,
615 installation_text_id),
616 &text_id, sizeof(u32));
Benjamin Romer10dbf0e2015-03-16 13:58:50 -0400617 return scnprintf(buf, PAGE_SIZE, "%i\n", text_id);
Benjamin Romer422af172014-07-24 14:08:42 -0400618}
619
620static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400621 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400622{
Benjamin Romer10dbf0e2015-03-16 13:58:50 -0400623 u32 text_id;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400624 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400625
Jes Sorensenebec8962015-05-05 18:35:57 -0400626 if (kstrtou32(buf, 10, &text_id))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400627 return -EINVAL;
628
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400629 ret = visorchannel_write(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400630 offsetof(struct spar_controlvm_channel_protocol,
631 installation_text_id),
632 &text_id, sizeof(u32));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400633 if (ret)
634 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400635 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400636}
637
Benjamin Romer422af172014-07-24 14:08:42 -0400638static ssize_t remaining_steps_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400639 struct device_attribute *attr, char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400640{
Benjamin Romeree8da292015-03-16 13:58:51 -0400641 u16 remaining_steps;
Benjamin Romer422af172014-07-24 14:08:42 -0400642
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400643 visorchannel_read(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400644 offsetof(struct spar_controlvm_channel_protocol,
645 installation_remaining_steps),
646 &remaining_steps, sizeof(u16));
Benjamin Romeree8da292015-03-16 13:58:51 -0400647 return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps);
Benjamin Romer422af172014-07-24 14:08:42 -0400648}
649
650static ssize_t remaining_steps_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400651 struct device_attribute *attr,
652 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400653{
Benjamin Romeree8da292015-03-16 13:58:51 -0400654 u16 remaining_steps;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400655 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400656
Jes Sorensenebec8962015-05-05 18:35:57 -0400657 if (kstrtou16(buf, 10, &remaining_steps))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400658 return -EINVAL;
659
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400660 ret = visorchannel_write(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400661 offsetof(struct spar_controlvm_channel_protocol,
662 installation_remaining_steps),
663 &remaining_steps, sizeof(u16));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400664 if (ret)
665 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400666 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400667}
668
Don Zickusab0592b2015-05-13 13:22:19 -0400669struct visor_busdev {
670 u32 bus_no;
671 u32 dev_no;
672};
673
674static int match_visorbus_dev_by_id(struct device *dev, void *data)
675{
676 struct visor_device *vdev = to_visor_device(dev);
Shraddha Barke7f445822015-10-15 00:58:23 +0530677 struct visor_busdev *id = data;
Don Zickusab0592b2015-05-13 13:22:19 -0400678 u32 bus_no = id->bus_no;
679 u32 dev_no = id->dev_no;
680
Don Zickus65bd6e42015-06-04 09:22:40 -0400681 if ((vdev->chipset_bus_no == bus_no) &&
682 (vdev->chipset_dev_no == dev_no))
Don Zickusab0592b2015-05-13 13:22:19 -0400683 return 1;
684
685 return 0;
686}
Erik Arfvidsond1e08632016-02-08 10:41:47 -0500687
Don Zickusab0592b2015-05-13 13:22:19 -0400688struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
689 struct visor_device *from)
690{
691 struct device *dev;
692 struct device *dev_start = NULL;
693 struct visor_device *vdev = NULL;
694 struct visor_busdev id = {
695 .bus_no = bus_no,
696 .dev_no = dev_no
697 };
698
699 if (from)
700 dev_start = &from->device;
701 dev = bus_find_device(&visorbus_type, dev_start, (void *)&id,
702 match_visorbus_dev_by_id);
703 if (dev)
704 vdev = to_visor_device(dev);
705 return vdev;
706}
707EXPORT_SYMBOL(visorbus_get_device_by_id);
708
Benjamin Romerc2422332014-07-29 15:09:40 -0400709static u8
Ken Cox12e364b2014-03-04 07:58:07 -0600710check_chipset_events(void)
711{
712 int i;
Benjamin Romerc2422332014-07-29 15:09:40 -0400713 u8 send_msg = 1;
Ken Cox12e364b2014-03-04 07:58:07 -0600714 /* Check events to determine if response should be sent */
715 for (i = 0; i < MAX_CHIPSET_EVENTS; i++)
716 send_msg &= chipset_events[i];
717 return send_msg;
718}
719
720static void
721clear_chipset_events(void)
722{
723 int i;
724 /* Clear chipset_events */
725 for (i = 0; i < MAX_CHIPSET_EVENTS; i++)
726 chipset_events[i] = 0;
727}
728
729void
David Kershner4da33362015-05-05 18:36:39 -0400730visorchipset_register_busdev(
Benjamin Romerfe90d892014-10-31 09:57:32 -0400731 struct visorchipset_busdev_notifiers *notifiers,
Benjamin Romer929aa8a2014-10-31 09:57:33 -0400732 struct visorchipset_busdev_responders *responders,
Benjamin Romer1e7a59c2014-10-31 09:57:35 -0400733 struct ultra_vbus_deviceinfo *driver_info)
Ken Cox12e364b2014-03-04 07:58:07 -0600734{
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400735 down(&notifier_lock);
Benjamin Romer38f736e2015-03-16 13:58:13 -0400736 if (!notifiers) {
David Kershner4da33362015-05-05 18:36:39 -0400737 memset(&busdev_notifiers, 0,
738 sizeof(busdev_notifiers));
739 visorbusregistered = 0; /* clear flag */
Ken Cox12e364b2014-03-04 07:58:07 -0600740 } else {
David Kershner4da33362015-05-05 18:36:39 -0400741 busdev_notifiers = *notifiers;
742 visorbusregistered = 1; /* set flag */
Ken Cox12e364b2014-03-04 07:58:07 -0600743 }
744 if (responders)
Benjamin Romer8e3fedd2015-03-16 13:58:43 -0400745 *responders = busdev_responders;
Benjamin Romer1e7a59c2014-10-31 09:57:35 -0400746 if (driver_info)
747 bus_device_info_init(driver_info, "chipset", "visorchipset",
Benjamin Romer8e76e692015-03-16 13:58:52 -0400748 VERSION, NULL);
Ken Cox12e364b2014-03-04 07:58:07 -0600749
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400750 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -0600751}
David Kershner4da33362015-05-05 18:36:39 -0400752EXPORT_SYMBOL_GPL(visorchipset_register_busdev);
Ken Cox12e364b2014-03-04 07:58:07 -0600753
754static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400755chipset_init(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600756{
757 static int chipset_inited;
Benjamin Romerb9b141e2014-10-23 14:30:24 -0400758 enum ultra_chipset_feature features = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600759 int rc = CONTROLVM_RESP_SUCCESS;
760
761 POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
762 if (chipset_inited) {
Ken Cox22ad57b2014-03-19 13:06:25 -0500763 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
David Kershner5233d1e2016-03-11 17:01:41 -0500764 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600765 }
766 chipset_inited = 1;
767 POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
768
769 /* Set features to indicate we support parahotplug (if Command
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500770 * also supports it).
771 */
Ken Cox12e364b2014-03-04 07:58:07 -0600772 features =
Benjamin Romer2ea51172014-10-23 14:30:25 -0400773 inmsg->cmd.init_chipset.
Ken Cox12e364b2014-03-04 07:58:07 -0600774 features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
775
776 /* Set the "reply" bit so Command knows this is a
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500777 * features-aware driver.
778 */
Ken Cox12e364b2014-03-04 07:58:07 -0600779 features |= ULTRA_CHIPSET_FEATURE_REPLY;
780
David Kershner5233d1e2016-03-11 17:01:41 -0500781out_respond:
Benjamin Romer98d7b592014-10-23 14:30:26 -0400782 if (inmsg->hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -0600783 controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
784}
785
786static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400787controlvm_init_response(struct controlvm_message *msg,
Benjamin Romerb3168c72015-03-16 13:58:46 -0400788 struct controlvm_message_header *msg_hdr, int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600789{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400790 memset(msg, 0, sizeof(struct controlvm_message));
Benjamin Romerb3168c72015-03-16 13:58:46 -0400791 memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
Benjamin Romer98d7b592014-10-23 14:30:26 -0400792 msg->hdr.payload_bytes = 0;
793 msg->hdr.payload_vm_offset = 0;
794 msg->hdr.payload_max_bytes = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600795 if (response < 0) {
Benjamin Romer98d7b592014-10-23 14:30:26 -0400796 msg->hdr.flags.failed = 1;
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500797 msg->hdr.completion_status = (u32)(-response);
Ken Cox12e364b2014-03-04 07:58:07 -0600798 }
799}
800
801static void
Benjamin Romerb3168c72015-03-16 13:58:46 -0400802controlvm_respond(struct controlvm_message_header *msg_hdr, int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600803{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400804 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400805
Benjamin Romerb3168c72015-03-16 13:58:46 -0400806 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500807 if (outmsg.hdr.flags.test_message == 1)
Ken Cox12e364b2014-03-04 07:58:07 -0600808 return;
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500809
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400810 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600811 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600812 return;
813 }
814}
815
816static void
Benjamin Romerb3168c72015-03-16 13:58:46 -0400817controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400818 int response,
Benjamin Romerb9b141e2014-10-23 14:30:24 -0400819 enum ultra_chipset_feature features)
Ken Cox12e364b2014-03-04 07:58:07 -0600820{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400821 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400822
Benjamin Romerb3168c72015-03-16 13:58:46 -0400823 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2ea51172014-10-23 14:30:25 -0400824 outmsg.cmd.init_chipset.features = features;
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400825 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600826 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600827 return;
828 }
829}
830
Benjamin Romer98d7b592014-10-23 14:30:26 -0400831static void controlvm_respond_physdev_changestate(
Benjamin Romerb3168c72015-03-16 13:58:46 -0400832 struct controlvm_message_header *msg_hdr, int response,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400833 struct spar_segment_state state)
Ken Cox12e364b2014-03-04 07:58:07 -0600834{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400835 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400836
Benjamin Romerb3168c72015-03-16 13:58:46 -0400837 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2ea51172014-10-23 14:30:25 -0400838 outmsg.cmd.device_change_state.state = state;
839 outmsg.cmd.device_change_state.flags.phys_device = 1;
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400840 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600841 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600842 return;
843 }
844}
845
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400846enum crash_obj_type {
847 CRASH_DEV,
848 CRASH_BUS,
849};
850
Ken Cox12e364b2014-03-04 07:58:07 -0600851static void
Tim Sell12c957d2016-03-01 19:45:04 -0500852save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
853{
854 u32 local_crash_msg_offset;
855 u16 local_crash_msg_count;
856
857 if (visorchannel_read(controlvm_channel,
858 offsetof(struct spar_controlvm_channel_protocol,
859 saved_crash_message_count),
860 &local_crash_msg_count, sizeof(u16)) < 0) {
861 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
862 POSTCODE_SEVERITY_ERR);
863 return;
864 }
865
866 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
867 POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
868 local_crash_msg_count,
869 POSTCODE_SEVERITY_ERR);
870 return;
871 }
872
873 if (visorchannel_read(controlvm_channel,
874 offsetof(struct spar_controlvm_channel_protocol,
875 saved_crash_message_offset),
876 &local_crash_msg_offset, sizeof(u32)) < 0) {
877 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
878 POSTCODE_SEVERITY_ERR);
879 return;
880 }
881
882 if (typ == CRASH_BUS) {
883 if (visorchannel_write(controlvm_channel,
884 local_crash_msg_offset,
885 msg,
886 sizeof(struct controlvm_message)) < 0) {
887 POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
888 POSTCODE_SEVERITY_ERR);
889 return;
890 }
891 } else {
892 local_crash_msg_offset += sizeof(struct controlvm_message);
893 if (visorchannel_write(controlvm_channel,
894 local_crash_msg_offset,
895 msg,
896 sizeof(struct controlvm_message)) < 0) {
897 POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
898 POSTCODE_SEVERITY_ERR);
899 return;
900 }
901 }
902}
903
904static void
Don Zickus0274b5a2015-06-01 13:00:27 -0400905bus_responder(enum controlvm_id cmd_id,
906 struct controlvm_message_header *pending_msg_hdr,
Don Zickus3032aed2015-05-13 13:22:24 -0400907 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600908{
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500909 if (!pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600910 return; /* no controlvm response needed */
Don Zickus0274b5a2015-06-01 13:00:27 -0400911
912 if (pending_msg_hdr->id != (u32)cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600913 return;
Don Zickus0274b5a2015-06-01 13:00:27 -0400914
915 controlvm_respond(pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600916}
917
918static void
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400919device_changestate_responder(enum controlvm_id cmd_id,
Don Zickusa298bc02015-06-04 09:22:42 -0400920 struct visor_device *p, int response,
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400921 struct spar_segment_state response_state)
Ken Cox12e364b2014-03-04 07:58:07 -0600922{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400923 struct controlvm_message outmsg;
Don Zickusa298bc02015-06-04 09:22:42 -0400924 u32 bus_no = p->chipset_bus_no;
925 u32 dev_no = p->chipset_dev_no;
Ken Cox12e364b2014-03-04 07:58:07 -0600926
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500927 if (!p->pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600928 return; /* no controlvm response needed */
Don Zickus0274b5a2015-06-01 13:00:27 -0400929 if (p->pending_msg_hdr->id != cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600930 return;
Ken Cox12e364b2014-03-04 07:58:07 -0600931
Don Zickus0274b5a2015-06-01 13:00:27 -0400932 controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600933
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400934 outmsg.cmd.device_change_state.bus_no = bus_no;
935 outmsg.cmd.device_change_state.dev_no = dev_no;
936 outmsg.cmd.device_change_state.state = response_state;
Ken Cox12e364b2014-03-04 07:58:07 -0600937
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400938 if (!visorchannel_signalinsert(controlvm_channel,
Benjamin Romer0aca78442015-03-04 12:14:25 -0500939 CONTROLVM_QUEUE_REQUEST, &outmsg))
Ken Cox12e364b2014-03-04 07:58:07 -0600940 return;
Ken Cox12e364b2014-03-04 07:58:07 -0600941}
942
943static void
Don Zickus0274b5a2015-06-01 13:00:27 -0400944device_responder(enum controlvm_id cmd_id,
945 struct controlvm_message_header *pending_msg_hdr,
Don Zickusb4b598f2015-05-13 13:22:25 -0400946 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600947{
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500948 if (!pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600949 return; /* no controlvm response needed */
Benjamin Romer0aca78442015-03-04 12:14:25 -0500950
Don Zickus0274b5a2015-06-01 13:00:27 -0400951 if (pending_msg_hdr->id != (u32)cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600952 return;
Benjamin Romer0aca78442015-03-04 12:14:25 -0500953
Don Zickus0274b5a2015-06-01 13:00:27 -0400954 controlvm_respond(pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600955}
956
957static void
Don Zickusd32517e2015-06-04 09:22:41 -0400958bus_epilog(struct visor_device *bus_info,
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400959 u32 cmd, struct controlvm_message_header *msg_hdr,
Jes Sorensenf4c11552015-04-13 10:28:40 -0400960 int response, bool need_response)
Ken Cox12e364b2014-03-04 07:58:07 -0600961{
Jes Sorensenf4c11552015-04-13 10:28:40 -0400962 bool notified = false;
Don Zickus0274b5a2015-06-01 13:00:27 -0400963 struct controlvm_message_header *pmsg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -0600964
Don Zickus0274b5a2015-06-01 13:00:27 -0400965 if (!bus_info) {
966 /* relying on a valid passed in response code */
967 /* be lazy and re-use msg_hdr for this failure, is this ok?? */
968 pmsg_hdr = msg_hdr;
969 goto away;
970 }
971
972 if (bus_info->pending_msg_hdr) {
973 /* only non-NULL if dev is still waiting on a response */
974 response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
975 pmsg_hdr = bus_info->pending_msg_hdr;
976 goto away;
977 }
Benjamin Romer0aca78442015-03-04 12:14:25 -0500978
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400979 if (need_response) {
Don Zickus0274b5a2015-06-01 13:00:27 -0400980 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
981 if (!pmsg_hdr) {
982 response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
983 goto away;
984 }
985
986 memcpy(pmsg_hdr, msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400987 sizeof(struct controlvm_message_header));
Don Zickus0274b5a2015-06-01 13:00:27 -0400988 bus_info->pending_msg_hdr = pmsg_hdr;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -0400989 }
Ken Cox12e364b2014-03-04 07:58:07 -0600990
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400991 down(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -0600992 if (response == CONTROLVM_RESP_SUCCESS) {
993 switch (cmd) {
994 case CONTROLVM_BUS_CREATE:
David Kershner4da33362015-05-05 18:36:39 -0400995 if (busdev_notifiers.bus_create) {
Don Zickus3032aed2015-05-13 13:22:24 -0400996 (*busdev_notifiers.bus_create) (bus_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -0400997 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -0600998 }
999 break;
1000 case CONTROLVM_BUS_DESTROY:
David Kershner4da33362015-05-05 18:36:39 -04001001 if (busdev_notifiers.bus_destroy) {
Don Zickus3032aed2015-05-13 13:22:24 -04001002 (*busdev_notifiers.bus_destroy) (bus_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001003 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001004 }
1005 break;
1006 }
1007 }
Don Zickus0274b5a2015-06-01 13:00:27 -04001008away:
Ken Cox12e364b2014-03-04 07:58:07 -06001009 if (notified)
1010 /* The callback function just called above is responsible
Benjamin Romer929aa8a2014-10-31 09:57:33 -04001011 * for calling the appropriate visorchipset_busdev_responders
Ken Cox12e364b2014-03-04 07:58:07 -06001012 * function, which will call bus_responder()
1013 */
1014 ;
1015 else
Don Zickus0274b5a2015-06-01 13:00:27 -04001016 /*
1017 * Do not kfree(pmsg_hdr) as this is the failure path.
1018 * The success path ('notified') will call the responder
1019 * directly and kfree() there.
1020 */
1021 bus_responder(cmd, pmsg_hdr, response);
Benjamin Romer8f1947a2015-03-16 13:57:59 -04001022 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001023}
1024
1025static void
Don Zickusa298bc02015-06-04 09:22:42 -04001026device_epilog(struct visor_device *dev_info,
Don Zickusb4b598f2015-05-13 13:22:25 -04001027 struct spar_segment_state state, u32 cmd,
Benjamin Romer2836c6a2015-03-16 13:58:17 -04001028 struct controlvm_message_header *msg_hdr, int response,
Jes Sorensenf4c11552015-04-13 10:28:40 -04001029 bool need_response, bool for_visorbus)
Ken Cox12e364b2014-03-04 07:58:07 -06001030{
Jes Sorensene82ba622015-05-05 18:35:45 -04001031 struct visorchipset_busdev_notifiers *notifiers;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001032 bool notified = false;
Don Zickus0274b5a2015-06-01 13:00:27 -04001033 struct controlvm_message_header *pmsg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001034
David Kershner4da33362015-05-05 18:36:39 -04001035 notifiers = &busdev_notifiers;
1036
Don Zickus0274b5a2015-06-01 13:00:27 -04001037 if (!dev_info) {
1038 /* relying on a valid passed in response code */
1039 /* be lazy and re-use msg_hdr for this failure, is this ok?? */
1040 pmsg_hdr = msg_hdr;
1041 goto away;
1042 }
1043
1044 if (dev_info->pending_msg_hdr) {
1045 /* only non-NULL if dev is still waiting on a response */
1046 response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
1047 pmsg_hdr = dev_info->pending_msg_hdr;
1048 goto away;
1049 }
1050
Benjamin Romer2836c6a2015-03-16 13:58:17 -04001051 if (need_response) {
Don Zickus0274b5a2015-06-01 13:00:27 -04001052 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
1053 if (!pmsg_hdr) {
1054 response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
1055 goto away;
1056 }
1057
1058 memcpy(pmsg_hdr, msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001059 sizeof(struct controlvm_message_header));
Don Zickus0274b5a2015-06-01 13:00:27 -04001060 dev_info->pending_msg_hdr = pmsg_hdr;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001061 }
Ken Cox12e364b2014-03-04 07:58:07 -06001062
Benjamin Romer8f1947a2015-03-16 13:57:59 -04001063 down(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001064 if (response >= 0) {
1065 switch (cmd) {
1066 case CONTROLVM_DEVICE_CREATE:
1067 if (notifiers->device_create) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001068 (*notifiers->device_create) (dev_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001069 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001070 }
1071 break;
1072 case CONTROLVM_DEVICE_CHANGESTATE:
1073 /* ServerReady / ServerRunning / SegmentStateRunning */
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001074 if (state.alive == segment_state_running.alive &&
1075 state.operating ==
1076 segment_state_running.operating) {
Ken Cox12e364b2014-03-04 07:58:07 -06001077 if (notifiers->device_resume) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001078 (*notifiers->device_resume) (dev_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001079 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001080 }
1081 }
1082 /* ServerNotReady / ServerLost / SegmentStateStandby */
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001083 else if (state.alive == segment_state_standby.alive &&
Benjamin Romer3f833b52014-10-23 14:30:12 -04001084 state.operating ==
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001085 segment_state_standby.operating) {
Ken Cox12e364b2014-03-04 07:58:07 -06001086 /* technically this is standby case
1087 * where server is lost
1088 */
1089 if (notifiers->device_pause) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001090 (*notifiers->device_pause) (dev_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001091 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001092 }
Ken Cox12e364b2014-03-04 07:58:07 -06001093 }
1094 break;
1095 case CONTROLVM_DEVICE_DESTROY:
1096 if (notifiers->device_destroy) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001097 (*notifiers->device_destroy) (dev_info);
Jes Sorensenf4c11552015-04-13 10:28:40 -04001098 notified = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001099 }
1100 break;
1101 }
1102 }
Don Zickus0274b5a2015-06-01 13:00:27 -04001103away:
Ken Cox12e364b2014-03-04 07:58:07 -06001104 if (notified)
1105 /* The callback function just called above is responsible
Benjamin Romer929aa8a2014-10-31 09:57:33 -04001106 * for calling the appropriate visorchipset_busdev_responders
Ken Cox12e364b2014-03-04 07:58:07 -06001107 * function, which will call device_responder()
1108 */
1109 ;
1110 else
Don Zickus0274b5a2015-06-01 13:00:27 -04001111 /*
1112 * Do not kfree(pmsg_hdr) as this is the failure path.
1113 * The success path ('notified') will call the responder
1114 * directly and kfree() there.
1115 */
1116 device_responder(cmd, pmsg_hdr, response);
Benjamin Romer8f1947a2015-03-16 13:57:59 -04001117 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001118}
1119
1120static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001121bus_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001122{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001123 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001124 u32 bus_no = cmd->create_bus.bus_no;
Ken Cox12e364b2014-03-04 07:58:07 -06001125 int rc = CONTROLVM_RESP_SUCCESS;
Don Zickusd32517e2015-06-04 09:22:41 -04001126 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -04001127 struct visorchannel *visorchannel;
Ken Cox12e364b2014-03-04 07:58:07 -06001128
Don Zickusd32517e2015-06-04 09:22:41 -04001129 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001130 if (bus_info && (bus_info->state.created == 1)) {
1131 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001132 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001133 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001134 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001135 }
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001136 bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
1137 if (!bus_info) {
1138 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001139 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001140 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001141 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001142 }
1143
David Kershner4abce832015-06-04 09:22:49 -04001144 INIT_LIST_HEAD(&bus_info->list_all);
Don Zickusd32517e2015-06-04 09:22:41 -04001145 bus_info->chipset_bus_no = bus_no;
1146 bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
Ken Cox12e364b2014-03-04 07:58:07 -06001147
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001148 POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001149
Don Zickusb32c4992015-06-01 13:00:26 -04001150 visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
1151 cmd->create_bus.channel_bytes,
1152 GFP_KERNEL,
1153 cmd->create_bus.bus_data_type_uuid);
1154
1155 if (!visorchannel) {
1156 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
1157 POSTCODE_SEVERITY_ERR);
1158 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
1159 kfree(bus_info);
1160 bus_info = NULL;
1161 goto cleanup;
1162 }
1163 bus_info->visorchannel = visorchannel;
Tim Sell12c957d2016-03-01 19:45:04 -05001164 if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) {
1165 dump_vhba_bus = bus_no;
1166 save_crash_message(inmsg, CRASH_BUS);
1167 }
Ken Cox12e364b2014-03-04 07:58:07 -06001168
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001169 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001170
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001171cleanup:
Don Zickus3032aed2015-05-13 13:22:24 -04001172 bus_epilog(bus_info, CONTROLVM_BUS_CREATE, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001173 rc, inmsg->hdr.flags.response_expected == 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001174}
1175
1176static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001177bus_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001178{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001179 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001180 u32 bus_no = cmd->destroy_bus.bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -04001181 struct visor_device *bus_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001182 int rc = CONTROLVM_RESP_SUCCESS;
1183
Don Zickusd32517e2015-06-04 09:22:41 -04001184 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerdff54cd2015-03-16 13:58:21 -04001185 if (!bus_info)
Ken Cox22ad57b2014-03-19 13:06:25 -05001186 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romerdff54cd2015-03-16 13:58:21 -04001187 else if (bus_info->state.created == 0)
Ken Cox22ad57b2014-03-19 13:06:25 -05001188 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Ken Cox12e364b2014-03-04 07:58:07 -06001189
Don Zickus3032aed2015-05-13 13:22:24 -04001190 bus_epilog(bus_info, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001191 rc, inmsg->hdr.flags.response_expected == 1);
Don Zickusd32517e2015-06-04 09:22:41 -04001192
1193 /* bus_info is freed as part of the busdevice_release function */
Ken Cox12e364b2014-03-04 07:58:07 -06001194}
1195
1196static void
Benjamin Romer317d9612015-03-16 13:57:51 -04001197bus_configure(struct controlvm_message *inmsg,
1198 struct parser_context *parser_ctx)
Ken Cox12e364b2014-03-04 07:58:07 -06001199{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001200 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensene82ba622015-05-05 18:35:45 -04001201 u32 bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -04001202 struct visor_device *bus_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001203 int rc = CONTROLVM_RESP_SUCCESS;
Ken Cox12e364b2014-03-04 07:58:07 -06001204
Benjamin Romer654bada2015-03-16 13:58:22 -04001205 bus_no = cmd->configure_bus.bus_no;
1206 POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no,
1207 POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001208
Don Zickusd32517e2015-06-04 09:22:41 -04001209 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer654bada2015-03-16 13:58:22 -04001210 if (!bus_info) {
1211 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001212 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001213 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romer654bada2015-03-16 13:58:22 -04001214 } else if (bus_info->state.created == 0) {
1215 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001216 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001217 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -05001218 } else if (bus_info->pending_msg_hdr) {
Benjamin Romer654bada2015-03-16 13:58:22 -04001219 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001220 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001221 rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
Benjamin Romer654bada2015-03-16 13:58:22 -04001222 } else {
Don Zickusb32c4992015-06-01 13:00:26 -04001223 visorchannel_set_clientpartition(bus_info->visorchannel,
1224 cmd->configure_bus.guest_handle);
Benjamin Romer654bada2015-03-16 13:58:22 -04001225 bus_info->partition_uuid = parser_id_get(parser_ctx);
1226 parser_param_start(parser_ctx, PARSERSTRING_NAME);
1227 bus_info->name = parser_string_get(parser_ctx);
1228
Benjamin Romer654bada2015-03-16 13:58:22 -04001229 POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no,
1230 POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001231 }
Don Zickus3032aed2015-05-13 13:22:24 -04001232 bus_epilog(bus_info, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001233 rc, inmsg->hdr.flags.response_expected == 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001234}
1235
1236static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001237my_device_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001238{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001239 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001240 u32 bus_no = cmd->create_device.bus_no;
1241 u32 dev_no = cmd->create_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -04001242 struct visor_device *dev_info = NULL;
Don Zickusd32517e2015-06-04 09:22:41 -04001243 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -04001244 struct visorchannel *visorchannel;
Ken Cox12e364b2014-03-04 07:58:07 -06001245 int rc = CONTROLVM_RESP_SUCCESS;
1246
Don Zickusa298bc02015-06-04 09:22:42 -04001247 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001248 if (!bus_info) {
1249 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001250 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001251 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001252 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001253 }
Don Zickusa298bc02015-06-04 09:22:42 -04001254
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001255 if (bus_info->state.created == 0) {
1256 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001257 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001258 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001259 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001260 }
Don Zickusa298bc02015-06-04 09:22:42 -04001261
1262 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
1263 if (dev_info && (dev_info->state.created == 1)) {
1264 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
1265 POSTCODE_SEVERITY_ERR);
1266 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
1267 goto cleanup;
1268 }
1269
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001270 dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
1271 if (!dev_info) {
1272 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001273 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001274 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001275 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001276 }
Andreea-Cristina Bernat97a84f12014-03-14 04:20:06 +02001277
Don Zickusa298bc02015-06-04 09:22:42 -04001278 dev_info->chipset_bus_no = bus_no;
1279 dev_info->chipset_dev_no = dev_no;
1280 dev_info->inst = cmd->create_device.dev_inst_uuid;
1281
1282 /* not sure where the best place to set the 'parent' */
1283 dev_info->device.parent = &bus_info->device;
1284
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001285 POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001286 POSTCODE_SEVERITY_INFO);
1287
David Kershnera3ef1a82015-07-14 14:43:29 -04001288 visorchannel =
1289 visorchannel_create_with_lock(cmd->create_device.channel_addr,
1290 cmd->create_device.channel_bytes,
1291 GFP_KERNEL,
1292 cmd->create_device.data_type_uuid);
Don Zickusb32c4992015-06-01 13:00:26 -04001293
1294 if (!visorchannel) {
1295 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
1296 POSTCODE_SEVERITY_ERR);
1297 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
1298 kfree(dev_info);
1299 dev_info = NULL;
1300 goto cleanup;
1301 }
1302 dev_info->visorchannel = visorchannel;
1303 dev_info->channel_type_guid = cmd->create_device.data_type_uuid;
Tim Sell12c957d2016-03-01 19:45:04 -05001304 if (uuid_le_cmp(cmd->create_device.data_type_uuid,
1305 spar_vhba_channel_protocol_uuid) == 0)
1306 save_crash_message(inmsg, CRASH_DEV);
1307
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001308 POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001309 POSTCODE_SEVERITY_INFO);
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001310cleanup:
Don Zickusb4b598f2015-05-13 13:22:25 -04001311 device_epilog(dev_info, segment_state_running,
Ken Cox12e364b2014-03-04 07:58:07 -06001312 CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001313 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001314}
1315
1316static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001317my_device_changestate(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001318{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001319 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001320 u32 bus_no = cmd->device_change_state.bus_no;
1321 u32 dev_no = cmd->device_change_state.dev_no;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001322 struct spar_segment_state state = cmd->device_change_state.state;
Don Zickusa298bc02015-06-04 09:22:42 -04001323 struct visor_device *dev_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001324 int rc = CONTROLVM_RESP_SUCCESS;
1325
Don Zickusa298bc02015-06-04 09:22:42 -04001326 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer0278a902015-03-16 13:58:24 -04001327 if (!dev_info) {
1328 POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001329 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001330 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Benjamin Romer0278a902015-03-16 13:58:24 -04001331 } else if (dev_info->state.created == 0) {
1332 POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001333 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001334 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Ken Cox12e364b2014-03-04 07:58:07 -06001335 }
Benjamin Romer0278a902015-03-16 13:58:24 -04001336 if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
Don Zickusb4b598f2015-05-13 13:22:25 -04001337 device_epilog(dev_info, state,
Benjamin Romer0278a902015-03-16 13:58:24 -04001338 CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001339 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001340}
1341
1342static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001343my_device_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001344{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001345 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001346 u32 bus_no = cmd->destroy_device.bus_no;
1347 u32 dev_no = cmd->destroy_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -04001348 struct visor_device *dev_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001349 int rc = CONTROLVM_RESP_SUCCESS;
1350
Don Zickusa298bc02015-06-04 09:22:42 -04001351 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer61715c82015-03-16 13:58:25 -04001352 if (!dev_info)
Ken Cox22ad57b2014-03-19 13:06:25 -05001353 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Benjamin Romer61715c82015-03-16 13:58:25 -04001354 else if (dev_info->state.created == 0)
Ken Cox22ad57b2014-03-19 13:06:25 -05001355 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Ken Cox12e364b2014-03-04 07:58:07 -06001356
Benjamin Romer61715c82015-03-16 13:58:25 -04001357 if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
Don Zickusb4b598f2015-05-13 13:22:25 -04001358 device_epilog(dev_info, segment_state_running,
Ken Cox12e364b2014-03-04 07:58:07 -06001359 CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001360 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001361}
1362
1363/* When provided with the physical address of the controlvm channel
1364 * (phys_addr), the offset to the payload area we need to manage
1365 * (offset), and the size of this payload area (bytes), fills in the
Jes Sorensenf4c11552015-04-13 10:28:40 -04001366 * controlvm_payload_info struct. Returns true for success or false
Ken Cox12e364b2014-03-04 07:58:07 -06001367 * for failure.
1368 */
1369static int
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001370initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes,
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001371 struct visor_controlvm_payload_info *info)
Ken Cox12e364b2014-03-04 07:58:07 -06001372{
Dan Williams3103dc02015-08-10 23:07:06 -04001373 u8 *payload = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001374
David Kershnerdde29992016-03-11 17:01:39 -05001375 if (!info)
1376 return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
1377
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001378 memset(info, 0, sizeof(struct visor_controlvm_payload_info));
David Kershnerdde29992016-03-11 17:01:39 -05001379 if ((offset == 0) || (bytes == 0))
1380 return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
1381
Dan Williams3103dc02015-08-10 23:07:06 -04001382 payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB);
David Kershnerdde29992016-03-11 17:01:39 -05001383 if (!payload)
1384 return -CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
Ken Cox12e364b2014-03-04 07:58:07 -06001385
1386 info->offset = offset;
1387 info->bytes = bytes;
1388 info->ptr = payload;
Ken Cox12e364b2014-03-04 07:58:07 -06001389
David Kershnerdde29992016-03-11 17:01:39 -05001390 return CONTROLVM_RESP_SUCCESS;
Ken Cox12e364b2014-03-04 07:58:07 -06001391}
1392
1393static void
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001394destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info)
Ken Cox12e364b2014-03-04 07:58:07 -06001395{
Benjamin Romer597c3382015-03-16 13:58:27 -04001396 if (info->ptr) {
Dan Williams3103dc02015-08-10 23:07:06 -04001397 memunmap(info->ptr);
Ken Cox12e364b2014-03-04 07:58:07 -06001398 info->ptr = NULL;
1399 }
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001400 memset(info, 0, sizeof(struct visor_controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06001401}
1402
1403static void
1404initialize_controlvm_payload(void)
1405{
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001406 u64 phys_addr = visorchannel_get_physaddr(controlvm_channel);
Benjamin Romercafefc02015-03-16 13:58:28 -04001407 u64 payload_offset = 0;
1408 u32 payload_bytes = 0;
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001409
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001410 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001411 offsetof(struct spar_controlvm_channel_protocol,
1412 request_payload_offset),
Benjamin Romercafefc02015-03-16 13:58:28 -04001413 &payload_offset, sizeof(payload_offset)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001414 POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
1415 POSTCODE_SEVERITY_ERR);
1416 return;
1417 }
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001418 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001419 offsetof(struct spar_controlvm_channel_protocol,
1420 request_payload_bytes),
Benjamin Romercafefc02015-03-16 13:58:28 -04001421 &payload_bytes, sizeof(payload_bytes)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001422 POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
1423 POSTCODE_SEVERITY_ERR);
1424 return;
1425 }
1426 initialize_controlvm_payload_info(phys_addr,
Benjamin Romercafefc02015-03-16 13:58:28 -04001427 payload_offset, payload_bytes,
Benjamin Romer84982fb2015-03-16 13:58:07 -04001428 &controlvm_payload_info);
Ken Cox12e364b2014-03-04 07:58:07 -06001429}
1430
1431/* Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
1432 * Returns CONTROLVM_RESP_xxx code.
1433 */
Jes Sorensend3368a52015-05-13 13:21:57 -04001434static int
Ken Cox12e364b2014-03-04 07:58:07 -06001435visorchipset_chipset_ready(void)
1436{
Benjamin Romereb34e872015-03-16 13:58:45 -04001437 kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
Ken Cox12e364b2014-03-04 07:58:07 -06001438 return CONTROLVM_RESP_SUCCESS;
1439}
Ken Cox12e364b2014-03-04 07:58:07 -06001440
Jes Sorensend3368a52015-05-13 13:21:57 -04001441static int
Ken Cox12e364b2014-03-04 07:58:07 -06001442visorchipset_chipset_selftest(void)
1443{
1444 char env_selftest[20];
1445 char *envp[] = { env_selftest, NULL };
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001446
Ken Cox12e364b2014-03-04 07:58:07 -06001447 sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
Benjamin Romereb34e872015-03-16 13:58:45 -04001448 kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
Ken Cox12e364b2014-03-04 07:58:07 -06001449 envp);
1450 return CONTROLVM_RESP_SUCCESS;
1451}
Ken Cox12e364b2014-03-04 07:58:07 -06001452
1453/* Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
1454 * Returns CONTROLVM_RESP_xxx code.
1455 */
Jes Sorensend3368a52015-05-13 13:21:57 -04001456static int
Ken Cox12e364b2014-03-04 07:58:07 -06001457visorchipset_chipset_notready(void)
1458{
Benjamin Romereb34e872015-03-16 13:58:45 -04001459 kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
Ken Cox12e364b2014-03-04 07:58:07 -06001460 return CONTROLVM_RESP_SUCCESS;
1461}
Ken Cox12e364b2014-03-04 07:58:07 -06001462
1463static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001464chipset_ready(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001465{
1466 int rc = visorchipset_chipset_ready();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001467
Ken Cox12e364b2014-03-04 07:58:07 -06001468 if (rc != CONTROLVM_RESP_SUCCESS)
1469 rc = -rc;
Benjamin Romer77a04492015-03-16 13:58:47 -04001470 if (msg_hdr->flags.response_expected && !visorchipset_holdchipsetready)
1471 controlvm_respond(msg_hdr, rc);
1472 if (msg_hdr->flags.response_expected && visorchipset_holdchipsetready) {
Ken Cox12e364b2014-03-04 07:58:07 -06001473 /* Send CHIPSET_READY response when all modules have been loaded
1474 * and disks mounted for the partition
1475 */
Benjamin Romer77a04492015-03-16 13:58:47 -04001476 g_chipset_msg_hdr = *msg_hdr;
Ken Cox12e364b2014-03-04 07:58:07 -06001477 }
1478}
1479
1480static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001481chipset_selftest(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001482{
1483 int rc = visorchipset_chipset_selftest();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001484
Ken Cox12e364b2014-03-04 07:58:07 -06001485 if (rc != CONTROLVM_RESP_SUCCESS)
1486 rc = -rc;
Benjamin Romer77a04492015-03-16 13:58:47 -04001487 if (msg_hdr->flags.response_expected)
1488 controlvm_respond(msg_hdr, rc);
Ken Cox12e364b2014-03-04 07:58:07 -06001489}
1490
1491static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001492chipset_notready(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001493{
1494 int rc = visorchipset_chipset_notready();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001495
Ken Cox12e364b2014-03-04 07:58:07 -06001496 if (rc != CONTROLVM_RESP_SUCCESS)
1497 rc = -rc;
Benjamin Romer77a04492015-03-16 13:58:47 -04001498 if (msg_hdr->flags.response_expected)
1499 controlvm_respond(msg_hdr, rc);
Ken Cox12e364b2014-03-04 07:58:07 -06001500}
1501
1502/* This is your "one-stop" shop for grabbing the next message from the
1503 * CONTROLVM_QUEUE_EVENT queue in the controlvm channel.
1504 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001505static bool
Benjamin Romer3ab47702014-10-23 14:30:31 -04001506read_controlvm_event(struct controlvm_message *msg)
Ken Cox12e364b2014-03-04 07:58:07 -06001507{
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001508 if (visorchannel_signalremove(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -06001509 CONTROLVM_QUEUE_EVENT, msg)) {
1510 /* got a message */
Benjamin Romer0aca78442015-03-04 12:14:25 -05001511 if (msg->hdr.flags.test_message == 1)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001512 return false;
1513 return true;
Ken Cox12e364b2014-03-04 07:58:07 -06001514 }
Jes Sorensenf4c11552015-04-13 10:28:40 -04001515 return false;
Ken Cox12e364b2014-03-04 07:58:07 -06001516}
1517
1518/*
1519 * The general parahotplug flow works as follows. The visorchipset
1520 * driver receives a DEVICE_CHANGESTATE message from Command
1521 * specifying a physical device to enable or disable. The CONTROLVM
1522 * message handler calls parahotplug_process_message, which then adds
1523 * the message to a global list and kicks off a udev event which
1524 * causes a user level script to enable or disable the specified
1525 * device. The udev script then writes to
1526 * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write
1527 * to get called, at which point the appropriate CONTROLVM message is
1528 * retrieved from the list and responded to.
1529 */
1530
1531#define PARAHOTPLUG_TIMEOUT_MS 2000
1532
1533/*
1534 * Generate unique int to match an outstanding CONTROLVM message with a
1535 * udev script /proc response
1536 */
1537static int
1538parahotplug_next_id(void)
1539{
1540 static atomic_t id = ATOMIC_INIT(0);
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001541
Ken Cox12e364b2014-03-04 07:58:07 -06001542 return atomic_inc_return(&id);
1543}
1544
1545/*
1546 * Returns the time (in jiffies) when a CONTROLVM message on the list
1547 * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future
1548 */
1549static unsigned long
1550parahotplug_next_expiration(void)
1551{
Nicholas Mc Guire2cc1a1b2015-01-31 12:02:08 +01001552 return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
Ken Cox12e364b2014-03-04 07:58:07 -06001553}
1554
1555/*
1556 * Create a parahotplug_request, which is basically a wrapper for a
1557 * CONTROLVM_MESSAGE that we can stick on a list
1558 */
1559static struct parahotplug_request *
Benjamin Romer3ab47702014-10-23 14:30:31 -04001560parahotplug_request_create(struct controlvm_message *msg)
Ken Cox12e364b2014-03-04 07:58:07 -06001561{
Quentin Lambertea0dcfc2015-02-10 15:12:07 +01001562 struct parahotplug_request *req;
1563
Benjamin Romer6a55e3c2015-03-16 13:58:30 -04001564 req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY);
Benjamin Romer38f736e2015-03-16 13:58:13 -04001565 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -06001566 return NULL;
1567
1568 req->id = parahotplug_next_id();
1569 req->expiration = parahotplug_next_expiration();
1570 req->msg = *msg;
1571
1572 return req;
1573}
1574
1575/*
1576 * Free a parahotplug_request.
1577 */
1578static void
1579parahotplug_request_destroy(struct parahotplug_request *req)
1580{
1581 kfree(req);
1582}
1583
1584/*
1585 * Cause uevent to run the user level script to do the disable/enable
1586 * specified in (the CONTROLVM message in) the specified
1587 * parahotplug_request
1588 */
1589static void
1590parahotplug_request_kickoff(struct parahotplug_request *req)
1591{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001592 struct controlvm_message_packet *cmd = &req->msg.cmd;
Ken Cox12e364b2014-03-04 07:58:07 -06001593 char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
1594 env_func[40];
1595 char *envp[] = {
1596 env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL
1597 };
1598
1599 sprintf(env_cmd, "SPAR_PARAHOTPLUG=1");
1600 sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id);
1601 sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001602 cmd->device_change_state.state.active);
Ken Cox12e364b2014-03-04 07:58:07 -06001603 sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001604 cmd->device_change_state.bus_no);
Ken Cox12e364b2014-03-04 07:58:07 -06001605 sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001606 cmd->device_change_state.dev_no >> 3);
Ken Cox12e364b2014-03-04 07:58:07 -06001607 sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001608 cmd->device_change_state.dev_no & 0x7);
Ken Cox12e364b2014-03-04 07:58:07 -06001609
Benjamin Romereb34e872015-03-16 13:58:45 -04001610 kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
Ken Cox12e364b2014-03-04 07:58:07 -06001611 envp);
1612}
1613
1614/*
1615 * Remove any request from the list that's been on there too long and
1616 * respond with an error.
1617 */
1618static void
1619parahotplug_process_list(void)
1620{
Jes Sorensene82ba622015-05-05 18:35:45 -04001621 struct list_head *pos;
1622 struct list_head *tmp;
Ken Cox12e364b2014-03-04 07:58:07 -06001623
Benjamin Romerddf5de52015-03-16 13:58:41 -04001624 spin_lock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001625
Benjamin Romerddf5de52015-03-16 13:58:41 -04001626 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
Ken Cox12e364b2014-03-04 07:58:07 -06001627 struct parahotplug_request *req =
1628 list_entry(pos, struct parahotplug_request, list);
Benjamin Romer55b33412015-03-16 13:58:29 -04001629
1630 if (!time_after_eq(jiffies, req->expiration))
1631 continue;
1632
1633 list_del(pos);
1634 if (req->msg.hdr.flags.response_expected)
1635 controlvm_respond_physdev_changestate(
1636 &req->msg.hdr,
1637 CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
1638 req->msg.cmd.device_change_state.state);
1639 parahotplug_request_destroy(req);
Ken Cox12e364b2014-03-04 07:58:07 -06001640 }
1641
Benjamin Romerddf5de52015-03-16 13:58:41 -04001642 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001643}
1644
1645/*
1646 * Called from the /proc handler, which means the user script has
1647 * finished the enable/disable. Find the matching identifier, and
1648 * respond to the CONTROLVM message with success.
1649 */
1650static int
Benjamin Romerb06bdf72014-07-31 12:00:49 -04001651parahotplug_request_complete(int id, u16 active)
Ken Cox12e364b2014-03-04 07:58:07 -06001652{
Jes Sorensene82ba622015-05-05 18:35:45 -04001653 struct list_head *pos;
1654 struct list_head *tmp;
Ken Cox12e364b2014-03-04 07:58:07 -06001655
Benjamin Romerddf5de52015-03-16 13:58:41 -04001656 spin_lock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001657
1658 /* Look for a request matching "id". */
Benjamin Romerddf5de52015-03-16 13:58:41 -04001659 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
Ken Cox12e364b2014-03-04 07:58:07 -06001660 struct parahotplug_request *req =
1661 list_entry(pos, struct parahotplug_request, list);
1662 if (req->id == id) {
1663 /* Found a match. Remove it from the list and
1664 * respond.
1665 */
1666 list_del(pos);
Benjamin Romerddf5de52015-03-16 13:58:41 -04001667 spin_unlock(&parahotplug_request_list_lock);
Benjamin Romer2ea51172014-10-23 14:30:25 -04001668 req->msg.cmd.device_change_state.state.active = active;
Benjamin Romer98d7b592014-10-23 14:30:26 -04001669 if (req->msg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001670 controlvm_respond_physdev_changestate(
1671 &req->msg.hdr, CONTROLVM_RESP_SUCCESS,
Benjamin Romer2ea51172014-10-23 14:30:25 -04001672 req->msg.cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001673 parahotplug_request_destroy(req);
1674 return 0;
1675 }
1676 }
1677
Benjamin Romerddf5de52015-03-16 13:58:41 -04001678 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001679 return -1;
1680}
1681
1682/*
1683 * Enables or disables a PCI device by kicking off a udev script
1684 */
Ken Coxbd5b9b32014-03-13 15:39:22 -05001685static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001686parahotplug_process_message(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001687{
1688 struct parahotplug_request *req;
1689
1690 req = parahotplug_request_create(inmsg);
1691
Benjamin Romer38f736e2015-03-16 13:58:13 -04001692 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -06001693 return;
Ken Cox12e364b2014-03-04 07:58:07 -06001694
Benjamin Romer2ea51172014-10-23 14:30:25 -04001695 if (inmsg->cmd.device_change_state.state.active) {
Ken Cox12e364b2014-03-04 07:58:07 -06001696 /* For enable messages, just respond with success
1697 * right away. This is a bit of a hack, but there are
1698 * issues with the early enable messages we get (with
1699 * either the udev script not detecting that the device
1700 * is up, or not getting called at all). Fortunately
1701 * the messages that get lost don't matter anyway, as
1702 * devices are automatically enabled at
1703 * initialization.
1704 */
1705 parahotplug_request_kickoff(req);
1706 controlvm_respond_physdev_changestate(&inmsg->hdr,
Benjamin Romer8e76e692015-03-16 13:58:52 -04001707 CONTROLVM_RESP_SUCCESS,
1708 inmsg->cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001709 parahotplug_request_destroy(req);
1710 } else {
1711 /* For disable messages, add the request to the
1712 * request list before kicking off the udev script. It
1713 * won't get responded to until the script has
1714 * indicated it's done.
1715 */
Benjamin Romerddf5de52015-03-16 13:58:41 -04001716 spin_lock(&parahotplug_request_list_lock);
1717 list_add_tail(&req->list, &parahotplug_request_list);
1718 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001719
1720 parahotplug_request_kickoff(req);
1721 }
1722}
1723
Ken Cox12e364b2014-03-04 07:58:07 -06001724/* Process a controlvm message.
1725 * Return result:
Prarit Bhargava779d0752015-05-05 18:37:01 -04001726 * false - this function will return false only in the case where the
Ken Cox12e364b2014-03-04 07:58:07 -06001727 * controlvm message was NOT processed, but processing must be
1728 * retried before reading the next controlvm message; a
1729 * scenario where this can occur is when we need to throttle
1730 * the allocation of memory in which to copy out controlvm
1731 * payload data
Jes Sorensenf4c11552015-04-13 10:28:40 -04001732 * true - processing of the controlvm message completed,
Ken Cox12e364b2014-03-04 07:58:07 -06001733 * either successfully or with an error.
1734 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001735static bool
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001736handle_command(struct controlvm_message inmsg, u64 channel_addr)
Ken Cox12e364b2014-03-04 07:58:07 -06001737{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001738 struct controlvm_message_packet *cmd = &inmsg.cmd;
Jes Sorensene82ba622015-05-05 18:35:45 -04001739 u64 parm_addr;
1740 u32 parm_bytes;
Benjamin Romer317d9612015-03-16 13:57:51 -04001741 struct parser_context *parser_ctx = NULL;
Jes Sorensene82ba622015-05-05 18:35:45 -04001742 bool local_addr;
Benjamin Romer3ab47702014-10-23 14:30:31 -04001743 struct controlvm_message ackmsg;
Ken Cox12e364b2014-03-04 07:58:07 -06001744
1745 /* create parsing context if necessary */
Benjamin Romer818352a2015-03-16 13:58:31 -04001746 local_addr = (inmsg.hdr.flags.test_message == 1);
Benjamin Romer0aca78442015-03-04 12:14:25 -05001747 if (channel_addr == 0)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001748 return true;
Benjamin Romer818352a2015-03-16 13:58:31 -04001749 parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
1750 parm_bytes = inmsg.hdr.payload_bytes;
Ken Cox12e364b2014-03-04 07:58:07 -06001751
1752 /* Parameter and channel addresses within test messages actually lie
1753 * within our OS-controlled memory. We need to know that, because it
1754 * makes a difference in how we compute the virtual address.
1755 */
Jes Sorensenebec8962015-05-05 18:35:57 -04001756 if (parm_addr && parm_bytes) {
Jes Sorensenf4c11552015-04-13 10:28:40 -04001757 bool retry = false;
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001758
Ken Cox12e364b2014-03-04 07:58:07 -06001759 parser_ctx =
Benjamin Romer818352a2015-03-16 13:58:31 -04001760 parser_init_byte_stream(parm_addr, parm_bytes,
1761 local_addr, &retry);
Benjamin Romer1b088722015-03-04 12:14:26 -05001762 if (!parser_ctx && retry)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001763 return false;
Ken Cox12e364b2014-03-04 07:58:07 -06001764 }
1765
Benjamin Romer818352a2015-03-16 13:58:31 -04001766 if (!local_addr) {
Ken Cox12e364b2014-03-04 07:58:07 -06001767 controlvm_init_response(&ackmsg, &inmsg.hdr,
1768 CONTROLVM_RESP_SUCCESS);
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001769 if (controlvm_channel)
1770 visorchannel_signalinsert(controlvm_channel,
Benjamin Romer1b088722015-03-04 12:14:26 -05001771 CONTROLVM_QUEUE_ACK,
1772 &ackmsg);
Ken Cox12e364b2014-03-04 07:58:07 -06001773 }
Benjamin Romer98d7b592014-10-23 14:30:26 -04001774 switch (inmsg.hdr.id) {
Ken Cox12e364b2014-03-04 07:58:07 -06001775 case CONTROLVM_CHIPSET_INIT:
Ken Cox12e364b2014-03-04 07:58:07 -06001776 chipset_init(&inmsg);
1777 break;
1778 case CONTROLVM_BUS_CREATE:
Ken Cox12e364b2014-03-04 07:58:07 -06001779 bus_create(&inmsg);
1780 break;
1781 case CONTROLVM_BUS_DESTROY:
Ken Cox12e364b2014-03-04 07:58:07 -06001782 bus_destroy(&inmsg);
1783 break;
1784 case CONTROLVM_BUS_CONFIGURE:
Ken Cox12e364b2014-03-04 07:58:07 -06001785 bus_configure(&inmsg, parser_ctx);
1786 break;
1787 case CONTROLVM_DEVICE_CREATE:
Ken Cox12e364b2014-03-04 07:58:07 -06001788 my_device_create(&inmsg);
1789 break;
1790 case CONTROLVM_DEVICE_CHANGESTATE:
Benjamin Romer2ea51172014-10-23 14:30:25 -04001791 if (cmd->device_change_state.flags.phys_device) {
Ken Cox12e364b2014-03-04 07:58:07 -06001792 parahotplug_process_message(&inmsg);
1793 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06001794 /* save the hdr and cmd structures for later use */
1795 /* when sending back the response to Command */
1796 my_device_changestate(&inmsg);
Benjamin Romer4f44b722015-03-16 13:58:02 -04001797 g_devicechangestate_packet = inmsg.cmd;
Ken Cox12e364b2014-03-04 07:58:07 -06001798 break;
1799 }
1800 break;
1801 case CONTROLVM_DEVICE_DESTROY:
Ken Cox12e364b2014-03-04 07:58:07 -06001802 my_device_destroy(&inmsg);
1803 break;
1804 case CONTROLVM_DEVICE_CONFIGURE:
Ken Cox12e364b2014-03-04 07:58:07 -06001805 /* no op for now, just send a respond that we passed */
Benjamin Romer98d7b592014-10-23 14:30:26 -04001806 if (inmsg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001807 controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
1808 break;
1809 case CONTROLVM_CHIPSET_READY:
Ken Cox12e364b2014-03-04 07:58:07 -06001810 chipset_ready(&inmsg.hdr);
1811 break;
1812 case CONTROLVM_CHIPSET_SELFTEST:
Ken Cox12e364b2014-03-04 07:58:07 -06001813 chipset_selftest(&inmsg.hdr);
1814 break;
1815 case CONTROLVM_CHIPSET_STOP:
Ken Cox12e364b2014-03-04 07:58:07 -06001816 chipset_notready(&inmsg.hdr);
1817 break;
1818 default:
Benjamin Romer98d7b592014-10-23 14:30:26 -04001819 if (inmsg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001820 controlvm_respond(&inmsg.hdr,
Benjamin Romer818352a2015-03-16 13:58:31 -04001821 -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
Ken Cox12e364b2014-03-04 07:58:07 -06001822 break;
1823 }
1824
Benjamin Romer38f736e2015-03-16 13:58:13 -04001825 if (parser_ctx) {
Ken Cox12e364b2014-03-04 07:58:07 -06001826 parser_done(parser_ctx);
1827 parser_ctx = NULL;
1828 }
Jes Sorensenf4c11552015-04-13 10:28:40 -04001829 return true;
Ken Cox12e364b2014-03-04 07:58:07 -06001830}
1831
David Kershner5f3a7e32015-05-13 13:22:10 -04001832static inline unsigned int
1833issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes)
1834{
1835 struct vmcall_io_controlvm_addr_params params;
1836 int result = VMCALL_SUCCESS;
1837 u64 physaddr;
1838
1839 physaddr = virt_to_phys(&params);
1840 ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result);
1841 if (VMCALL_SUCCESSFUL(result)) {
1842 *control_addr = params.address;
1843 *control_bytes = params.channel_bytes;
1844 }
1845 return result;
1846}
1847
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001848static u64 controlvm_get_channel_address(void)
Benjamin Romer524b0b62014-07-17 12:39:57 -04001849{
Benjamin Romer5fc02292014-07-31 12:00:51 -04001850 u64 addr = 0;
Benjamin Romerb3c55b12014-07-31 12:00:50 -04001851 u32 size = 0;
Benjamin Romer524b0b62014-07-17 12:39:57 -04001852
Benjamin Romer0aca78442015-03-04 12:14:25 -05001853 if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size)))
Benjamin Romer524b0b62014-07-17 12:39:57 -04001854 return 0;
Benjamin Romer0aca78442015-03-04 12:14:25 -05001855
Benjamin Romer524b0b62014-07-17 12:39:57 -04001856 return addr;
1857}
1858
Ken Cox12e364b2014-03-04 07:58:07 -06001859static void
1860controlvm_periodic_work(struct work_struct *work)
1861{
Benjamin Romer3ab47702014-10-23 14:30:31 -04001862 struct controlvm_message inmsg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001863 bool got_command = false;
1864 bool handle_command_failed = false;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001865 static u64 poll_count;
Ken Cox12e364b2014-03-04 07:58:07 -06001866
1867 /* make sure visorbus server is registered for controlvm callbacks */
David Kershner4da33362015-05-05 18:36:39 -04001868 if (visorchipset_visorbusregwait && !visorbusregistered)
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001869 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001870
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001871 poll_count++;
1872 if (poll_count >= 250)
Ken Cox12e364b2014-03-04 07:58:07 -06001873 ; /* keep going */
1874 else
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001875 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001876
1877 /* Check events to determine if response to CHIPSET_READY
1878 * should be sent
1879 */
Benjamin Romer0639ba62015-03-16 13:58:04 -04001880 if (visorchipset_holdchipsetready &&
1881 (g_chipset_msg_hdr.id != CONTROLVM_INVALID)) {
Ken Cox12e364b2014-03-04 07:58:07 -06001882 if (check_chipset_events() == 1) {
Benjamin Romerda021f02015-03-16 13:57:58 -04001883 controlvm_respond(&g_chipset_msg_hdr, 0);
Ken Cox12e364b2014-03-04 07:58:07 -06001884 clear_chipset_events();
Benjamin Romerda021f02015-03-16 13:57:58 -04001885 memset(&g_chipset_msg_hdr, 0,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001886 sizeof(struct controlvm_message_header));
Ken Cox12e364b2014-03-04 07:58:07 -06001887 }
1888 }
1889
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001890 while (visorchannel_signalremove(controlvm_channel,
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001891 CONTROLVM_QUEUE_RESPONSE,
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001892 &inmsg))
1893 ;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001894 if (!got_command) {
Benjamin Romer7166ed12015-03-16 13:58:38 -04001895 if (controlvm_pending_msg_valid) {
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001896 /* we throttled processing of a prior
1897 * msg, so try to process it again
1898 * rather than reading a new one
1899 */
Benjamin Romer7166ed12015-03-16 13:58:38 -04001900 inmsg = controlvm_pending_msg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001901 controlvm_pending_msg_valid = false;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001902 got_command = true;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001903 } else {
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001904 got_command = read_controlvm_event(&inmsg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001905 }
Ken Cox12e364b2014-03-04 07:58:07 -06001906 }
1907
Jes Sorensenf4c11552015-04-13 10:28:40 -04001908 handle_command_failed = false;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001909 while (got_command && (!handle_command_failed)) {
Benjamin Romerb53e0e92015-03-16 13:57:56 -04001910 most_recent_message_jiffies = jiffies;
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001911 if (handle_command(inmsg,
1912 visorchannel_get_physaddr
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001913 (controlvm_channel)))
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001914 got_command = read_controlvm_event(&inmsg);
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001915 else {
1916 /* this is a scenario where throttling
1917 * is required, but probably NOT an
1918 * error...; we stash the current
1919 * controlvm msg so we will attempt to
1920 * reprocess it on our next loop
1921 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001922 handle_command_failed = true;
Benjamin Romer7166ed12015-03-16 13:58:38 -04001923 controlvm_pending_msg = inmsg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001924 controlvm_pending_msg_valid = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001925 }
1926 }
1927
1928 /* parahotplug_worker */
1929 parahotplug_process_list();
1930
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001931cleanup:
Ken Cox12e364b2014-03-04 07:58:07 -06001932
1933 if (time_after(jiffies,
Benjamin Romerb53e0e92015-03-16 13:57:56 -04001934 most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) {
Ken Cox12e364b2014-03-04 07:58:07 -06001935 /* it's been longer than MIN_IDLE_SECONDS since we
1936 * processed our last controlvm message; slow down the
1937 * polling
1938 */
Benjamin Romer911e2132015-03-16 13:57:47 -04001939 if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW)
1940 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
Ken Cox12e364b2014-03-04 07:58:07 -06001941 } else {
Benjamin Romer911e2132015-03-16 13:57:47 -04001942 if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST)
1943 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Ken Cox12e364b2014-03-04 07:58:07 -06001944 }
1945
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05301946 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
Ken Cox12e364b2014-03-04 07:58:07 -06001947}
1948
1949static void
1950setup_crash_devices_work_queue(struct work_struct *work)
1951{
Benjamin Romere6bdb902015-03-16 13:58:33 -04001952 struct controlvm_message local_crash_bus_msg;
1953 struct controlvm_message local_crash_dev_msg;
Benjamin Romer3ab47702014-10-23 14:30:31 -04001954 struct controlvm_message msg;
Benjamin Romere6bdb902015-03-16 13:58:33 -04001955 u32 local_crash_msg_offset;
1956 u16 local_crash_msg_count;
Ken Cox12e364b2014-03-04 07:58:07 -06001957
David Kershner4da33362015-05-05 18:36:39 -04001958 /* make sure visorbus is registered for controlvm callbacks */
David Kershnerb8999632016-03-11 17:01:38 -05001959 if (visorchipset_visorbusregwait && !visorbusregistered) {
1960 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
1961 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
1962 return;
1963 }
Ken Cox12e364b2014-03-04 07:58:07 -06001964
1965 POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
1966
1967 /* send init chipset msg */
Benjamin Romer98d7b592014-10-23 14:30:26 -04001968 msg.hdr.id = CONTROLVM_CHIPSET_INIT;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001969 msg.cmd.init_chipset.bus_count = 23;
1970 msg.cmd.init_chipset.switch_count = 0;
Ken Cox12e364b2014-03-04 07:58:07 -06001971
1972 chipset_init(&msg);
1973
Ken Cox12e364b2014-03-04 07:58:07 -06001974 /* get saved message count */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001975 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001976 offsetof(struct spar_controlvm_channel_protocol,
1977 saved_crash_message_count),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001978 &local_crash_msg_count, sizeof(u16)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001979 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
1980 POSTCODE_SEVERITY_ERR);
1981 return;
1982 }
1983
Benjamin Romere6bdb902015-03-16 13:58:33 -04001984 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
Ken Cox12e364b2014-03-04 07:58:07 -06001985 POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001986 local_crash_msg_count,
Ken Cox12e364b2014-03-04 07:58:07 -06001987 POSTCODE_SEVERITY_ERR);
1988 return;
1989 }
1990
1991 /* get saved crash message offset */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001992 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001993 offsetof(struct spar_controlvm_channel_protocol,
1994 saved_crash_message_offset),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001995 &local_crash_msg_offset, sizeof(u32)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001996 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
1997 POSTCODE_SEVERITY_ERR);
1998 return;
1999 }
2000
2001 /* read create device message for storage bus offset */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002002 if (visorchannel_read(controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04002003 local_crash_msg_offset,
2004 &local_crash_bus_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04002005 sizeof(struct controlvm_message)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06002006 POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC,
2007 POSTCODE_SEVERITY_ERR);
2008 return;
2009 }
2010
2011 /* read create device message for storage device */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002012 if (visorchannel_read(controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04002013 local_crash_msg_offset +
Benjamin Romer3ab47702014-10-23 14:30:31 -04002014 sizeof(struct controlvm_message),
Benjamin Romere6bdb902015-03-16 13:58:33 -04002015 &local_crash_dev_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04002016 sizeof(struct controlvm_message)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06002017 POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
2018 POSTCODE_SEVERITY_ERR);
2019 return;
2020 }
2021
2022 /* reuse IOVM create bus message */
Jes Sorensenebec8962015-05-05 18:35:57 -04002023 if (local_crash_bus_msg.cmd.create_bus.channel_addr) {
Benjamin Romere6bdb902015-03-16 13:58:33 -04002024 bus_create(&local_crash_bus_msg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04002025 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06002026 POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
2027 POSTCODE_SEVERITY_ERR);
2028 return;
2029 }
2030
2031 /* reuse create device message for storage device */
Jes Sorensenebec8962015-05-05 18:35:57 -04002032 if (local_crash_dev_msg.cmd.create_device.channel_addr) {
Benjamin Romere6bdb902015-03-16 13:58:33 -04002033 my_device_create(&local_crash_dev_msg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04002034 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06002035 POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
2036 POSTCODE_SEVERITY_ERR);
2037 return;
2038 }
Ken Cox12e364b2014-03-04 07:58:07 -06002039 POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06002040}
2041
2042static void
Don Zickusd32517e2015-06-04 09:22:41 -04002043bus_create_response(struct visor_device *bus_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002044{
Alessandro Parini4b4fd432015-06-13 17:40:48 +02002045 if (response >= 0)
Don Zickus0274b5a2015-06-01 13:00:27 -04002046 bus_info->state.created = 1;
Don Zickus0274b5a2015-06-01 13:00:27 -04002047
2048 bus_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr,
2049 response);
2050
2051 kfree(bus_info->pending_msg_hdr);
2052 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002053}
2054
2055static void
Don Zickusd32517e2015-06-04 09:22:41 -04002056bus_destroy_response(struct visor_device *bus_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002057{
Don Zickus0274b5a2015-06-01 13:00:27 -04002058 bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr,
2059 response);
2060
2061 kfree(bus_info->pending_msg_hdr);
2062 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002063}
2064
2065static void
Don Zickusa298bc02015-06-04 09:22:42 -04002066device_create_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002067{
Don Zickus0274b5a2015-06-01 13:00:27 -04002068 if (response >= 0)
2069 dev_info->state.created = 1;
2070
2071 device_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr,
2072 response);
2073
2074 kfree(dev_info->pending_msg_hdr);
Tim Selladdce192015-07-09 13:27:41 -04002075 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002076}
2077
2078static void
Don Zickusa298bc02015-06-04 09:22:42 -04002079device_destroy_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002080{
Don Zickus0274b5a2015-06-01 13:00:27 -04002081 device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr,
2082 response);
2083
2084 kfree(dev_info->pending_msg_hdr);
2085 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002086}
2087
Jes Sorensend3368a52015-05-13 13:21:57 -04002088static void
Don Zickusa298bc02015-06-04 09:22:42 -04002089visorchipset_device_pause_response(struct visor_device *dev_info,
Don Zickusb4b598f2015-05-13 13:22:25 -04002090 int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002091{
Ken Cox12e364b2014-03-04 07:58:07 -06002092 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
Don Zickusb4b598f2015-05-13 13:22:25 -04002093 dev_info, response,
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04002094 segment_state_standby);
Don Zickus0274b5a2015-06-01 13:00:27 -04002095
2096 kfree(dev_info->pending_msg_hdr);
2097 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002098}
Ken Cox12e364b2014-03-04 07:58:07 -06002099
2100static void
Don Zickusa298bc02015-06-04 09:22:42 -04002101device_resume_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002102{
2103 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
Don Zickusb4b598f2015-05-13 13:22:25 -04002104 dev_info, response,
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04002105 segment_state_running);
Don Zickus0274b5a2015-06-01 13:00:27 -04002106
2107 kfree(dev_info->pending_msg_hdr);
2108 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002109}
2110
Benjamin Romer18b87ed2014-07-24 14:08:43 -04002111static ssize_t chipsetready_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -04002112 struct device_attribute *attr,
2113 const char *buf, size_t count)
Ken Cox12e364b2014-03-04 07:58:07 -06002114{
Benjamin Romer18b87ed2014-07-24 14:08:43 -04002115 char msgtype[64];
Ken Cox12e364b2014-03-04 07:58:07 -06002116
Benjamin Romer66e24b72014-07-25 13:55:10 -04002117 if (sscanf(buf, "%63s", msgtype) != 1)
Ken Cox12e364b2014-03-04 07:58:07 -06002118 return -EINVAL;
Benjamin Romer66e24b72014-07-25 13:55:10 -04002119
Jes Sorensenebec8962015-05-05 18:35:57 -04002120 if (!strcmp(msgtype, "CALLHOMEDISK_MOUNTED")) {
Benjamin Romer66e24b72014-07-25 13:55:10 -04002121 chipset_events[0] = 1;
2122 return count;
Jes Sorensenebec8962015-05-05 18:35:57 -04002123 } else if (!strcmp(msgtype, "MODULES_LOADED")) {
Benjamin Romer66e24b72014-07-25 13:55:10 -04002124 chipset_events[1] = 1;
2125 return count;
Benjamin Romere22a4a02014-08-18 09:34:54 -04002126 }
2127 return -EINVAL;
Ken Cox12e364b2014-03-04 07:58:07 -06002128}
2129
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002130/* The parahotplug/devicedisabled interface gets called by our support script
2131 * when an SR-IOV device has been shut down. The ID is passed to the script
2132 * and then passed back when the device has been removed.
2133 */
2134static ssize_t devicedisabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -04002135 struct device_attribute *attr,
2136 const char *buf, size_t count)
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002137{
Jes Sorensen94217362015-05-05 18:35:46 -04002138 unsigned int id;
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002139
Jes Sorensenebec8962015-05-05 18:35:57 -04002140 if (kstrtouint(buf, 10, &id))
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002141 return -EINVAL;
2142
2143 parahotplug_request_complete(id, 0);
2144 return count;
2145}
2146
2147/* The parahotplug/deviceenabled interface gets called by our support script
2148 * when an SR-IOV device has been recovered. The ID is passed to the script
2149 * and then passed back when the device has been brought back up.
2150 */
2151static ssize_t deviceenabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -04002152 struct device_attribute *attr,
2153 const char *buf, size_t count)
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002154{
Jes Sorensen94217362015-05-05 18:35:46 -04002155 unsigned int id;
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002156
Jes Sorensenebec8962015-05-05 18:35:57 -04002157 if (kstrtouint(buf, 10, &id))
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002158 return -EINVAL;
2159
2160 parahotplug_request_complete(id, 1);
2161 return count;
2162}
2163
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002164static int
2165visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
2166{
2167 unsigned long physaddr = 0;
2168 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
Erik Arfvidson780fcad2015-05-05 18:36:35 -04002169 u64 addr = 0;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002170
2171 /* sv_enable_dfp(); */
2172 if (offset & (PAGE_SIZE - 1))
2173 return -ENXIO; /* need aligned offsets */
2174
2175 switch (offset) {
2176 case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
2177 vma->vm_flags |= VM_IO;
2178 if (!*file_controlvm_channel)
2179 return -ENXIO;
2180
2181 visorchannel_read(*file_controlvm_channel,
2182 offsetof(struct spar_controlvm_channel_protocol,
2183 gp_control_channel),
2184 &addr, sizeof(addr));
2185 if (!addr)
2186 return -ENXIO;
2187
2188 physaddr = (unsigned long)addr;
2189 if (remap_pfn_range(vma, vma->vm_start,
2190 physaddr >> PAGE_SHIFT,
2191 vma->vm_end - vma->vm_start,
2192 /*pgprot_noncached */
2193 (vma->vm_page_prot))) {
2194 return -EAGAIN;
2195 }
2196 break;
2197 default:
2198 return -ENXIO;
2199 }
2200 return 0;
2201}
2202
David Kershner5f3a7e32015-05-13 13:22:10 -04002203static inline s64 issue_vmcall_query_guest_virtual_time_offset(void)
2204{
2205 u64 result = VMCALL_SUCCESS;
2206 u64 physaddr = 0;
2207
2208 ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr,
2209 result);
2210 return result;
2211}
2212
2213static inline int issue_vmcall_update_physical_time(u64 adjustment)
2214{
2215 int result = VMCALL_SUCCESS;
2216
2217 ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result);
2218 return result;
2219}
2220
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002221static long visorchipset_ioctl(struct file *file, unsigned int cmd,
2222 unsigned long arg)
2223{
David Kershner25002762016-03-03 13:00:38 -05002224 u64 adjustment;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002225 s64 vrtc_offset;
2226
2227 switch (cmd) {
2228 case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET:
2229 /* get the physical rtc offset */
2230 vrtc_offset = issue_vmcall_query_guest_virtual_time_offset();
2231 if (copy_to_user((void __user *)arg, &vrtc_offset,
2232 sizeof(vrtc_offset))) {
2233 return -EFAULT;
2234 }
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002235 return 0;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002236 case VMCALL_UPDATE_PHYSICAL_TIME:
2237 if (copy_from_user(&adjustment, (void __user *)arg,
2238 sizeof(adjustment))) {
2239 return -EFAULT;
2240 }
2241 return issue_vmcall_update_physical_time(adjustment);
2242 default:
2243 return -EFAULT;
2244 }
2245}
2246
2247static const struct file_operations visorchipset_fops = {
2248 .owner = THIS_MODULE,
2249 .open = visorchipset_open,
2250 .read = NULL,
2251 .write = NULL,
2252 .unlocked_ioctl = visorchipset_ioctl,
2253 .release = visorchipset_release,
2254 .mmap = visorchipset_mmap,
2255};
2256
Jes Sorensen0f570fc2015-05-13 13:21:55 -04002257static int
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002258visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
2259{
2260 int rc = 0;
2261
2262 file_controlvm_channel = controlvm_channel;
2263 cdev_init(&file_cdev, &visorchipset_fops);
2264 file_cdev.owner = THIS_MODULE;
2265 if (MAJOR(major_dev) == 0) {
Erik Arfvidson46168812015-05-05 18:36:14 -04002266 rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset");
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002267 /* dynamic major device number registration required */
2268 if (rc < 0)
2269 return rc;
2270 } else {
2271 /* static major device number registration required */
Erik Arfvidson46168812015-05-05 18:36:14 -04002272 rc = register_chrdev_region(major_dev, 1, "visorchipset");
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002273 if (rc < 0)
2274 return rc;
2275 }
2276 rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1);
2277 if (rc < 0) {
2278 unregister_chrdev_region(major_dev, 1);
2279 return rc;
2280 }
2281 return 0;
2282}
2283
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002284static int
2285visorchipset_init(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06002286{
David Kershner33078252015-05-05 18:36:48 -04002287 int rc = 0;
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002288 u64 addr;
Jes Sorensend3368a52015-05-13 13:21:57 -04002289 uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID;
2290
2291 addr = controlvm_get_channel_address();
2292 if (!addr)
2293 return -ENODEV;
Ken Cox12e364b2014-03-04 07:58:07 -06002294
David Kershner4da33362015-05-05 18:36:39 -04002295 memset(&busdev_notifiers, 0, sizeof(busdev_notifiers));
Benjamin Romer84982fb2015-03-16 13:58:07 -04002296 memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06002297
Tim Sellc732623b2016-03-01 19:45:03 -05002298 controlvm_channel = visorchannel_create_with_lock(addr, 0,
Jes Sorensend3368a52015-05-13 13:21:57 -04002299 GFP_KERNEL, uuid);
Tim Sellc732623b2016-03-01 19:45:03 -05002300 if (!controlvm_channel)
2301 return -ENODEV;
Jes Sorensend3368a52015-05-13 13:21:57 -04002302 if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
2303 visorchannel_get_header(controlvm_channel))) {
2304 initialize_controlvm_payload();
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002305 } else {
Jes Sorensend3368a52015-05-13 13:21:57 -04002306 visorchannel_destroy(controlvm_channel);
2307 controlvm_channel = NULL;
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002308 return -ENODEV;
2309 }
2310
Benjamin Romer5aa8ae52015-03-16 13:58:44 -04002311 major_dev = MKDEV(visorchipset_major, 0);
2312 rc = visorchipset_file_init(major_dev, &controlvm_channel);
Ken Cox4cb005a2014-03-19 13:06:20 -05002313 if (rc < 0) {
Ken Cox4cb005a2014-03-19 13:06:20 -05002314 POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR);
Benjamin Romera6a39892015-03-16 13:58:34 -04002315 goto cleanup;
Ken Cox4cb005a2014-03-19 13:06:20 -05002316 }
Ken Cox9f8d0e82014-03-19 13:06:19 -05002317
Benjamin Romerda021f02015-03-16 13:57:58 -04002318 memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header));
Ken Cox12e364b2014-03-04 07:58:07 -06002319
David Kershner4da33362015-05-05 18:36:39 -04002320 /* if booting in a crash kernel */
2321 if (is_kdump_kernel())
2322 INIT_DELAYED_WORK(&periodic_controlvm_work,
2323 setup_crash_devices_work_queue);
2324 else
2325 INIT_DELAYED_WORK(&periodic_controlvm_work,
2326 controlvm_periodic_work);
Ken Cox12e364b2014-03-04 07:58:07 -06002327
David Kershner4da33362015-05-05 18:36:39 -04002328 most_recent_message_jiffies = jiffies;
2329 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302330 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
Ken Cox12e364b2014-03-04 07:58:07 -06002331
Benjamin Romereb34e872015-03-16 13:58:45 -04002332 visorchipset_platform_device.dev.devt = major_dev;
2333 if (platform_device_register(&visorchipset_platform_device) < 0) {
Ken Cox4cb005a2014-03-19 13:06:20 -05002334 POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR);
Benjamin Romerfbd91612016-02-23 10:01:55 -05002335 rc = -ENODEV;
Benjamin Romera6a39892015-03-16 13:58:34 -04002336 goto cleanup;
Ken Cox4cb005a2014-03-19 13:06:20 -05002337 }
Ken Cox12e364b2014-03-04 07:58:07 -06002338 POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04002339
2340 rc = visorbus_init();
Benjamin Romera6a39892015-03-16 13:58:34 -04002341cleanup:
Ken Cox12e364b2014-03-04 07:58:07 -06002342 if (rc) {
Ken Cox12e364b2014-03-04 07:58:07 -06002343 POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
2344 POSTCODE_SEVERITY_ERR);
2345 }
2346 return rc;
2347}
2348
Jes Sorensen0f570fc2015-05-13 13:21:55 -04002349static void
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002350visorchipset_file_cleanup(dev_t major_dev)
2351{
2352 if (file_cdev.ops)
2353 cdev_del(&file_cdev);
2354 file_cdev.ops = NULL;
2355 unregister_chrdev_region(major_dev, 1);
2356}
2357
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002358static int
2359visorchipset_exit(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06002360{
Ken Cox12e364b2014-03-04 07:58:07 -06002361 POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
2362
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04002363 visorbus_exit();
2364
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302365 cancel_delayed_work_sync(&periodic_controlvm_work);
David Kershner4da33362015-05-05 18:36:39 -04002366 destroy_controlvm_payload_info(&controlvm_payload_info);
Benjamin Romer17833192014-07-15 13:30:41 -04002367
Benjamin Romerda021f02015-03-16 13:57:58 -04002368 memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header));
Ken Cox12e364b2014-03-04 07:58:07 -06002369
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002370 visorchannel_destroy(controlvm_channel);
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002371
Sudip Mukherjeeaddceb12015-03-24 20:47:28 +05302372 visorchipset_file_cleanup(visorchipset_platform_device.dev.devt);
Don Zickus04dacac2015-06-04 09:22:48 -04002373 platform_device_unregister(&visorchipset_platform_device);
Ken Cox12e364b2014-03-04 07:58:07 -06002374 POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002375
2376 return 0;
2377}
2378
2379static const struct acpi_device_id unisys_device_ids[] = {
2380 {"PNP0A07", 0},
2381 {"", 0},
2382};
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002383
2384static struct acpi_driver unisys_acpi_driver = {
2385 .name = "unisys_acpi",
2386 .class = "unisys_acpi_class",
2387 .owner = THIS_MODULE,
2388 .ids = unisys_device_ids,
2389 .ops = {
2390 .add = visorchipset_init,
2391 .remove = visorchipset_exit,
2392 },
2393};
David Kershner1fc07f92015-07-09 13:27:53 -04002394
2395MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
2396
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002397static __init uint32_t visorutil_spar_detect(void)
2398{
2399 unsigned int eax, ebx, ecx, edx;
2400
2401 if (cpu_has_hypervisor) {
2402 /* check the ID */
2403 cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
2404 return (ebx == UNISYS_SPAR_ID_EBX) &&
2405 (ecx == UNISYS_SPAR_ID_ECX) &&
2406 (edx == UNISYS_SPAR_ID_EDX);
2407 } else {
2408 return 0;
2409 }
2410}
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002411
2412static int init_unisys(void)
2413{
2414 int result;
Alessandro Parini35e606d2015-06-13 17:40:49 +02002415
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002416 if (!visorutil_spar_detect())
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002417 return -ENODEV;
2418
2419 result = acpi_bus_register_driver(&unisys_acpi_driver);
2420 if (result)
2421 return -ENODEV;
2422
2423 pr_info("Unisys Visorchipset Driver Loaded.\n");
2424 return 0;
2425};
2426
2427static void exit_unisys(void)
2428{
2429 acpi_bus_unregister_driver(&unisys_acpi_driver);
Ken Cox12e364b2014-03-04 07:58:07 -06002430}
2431
Ken Cox12e364b2014-03-04 07:58:07 -06002432module_param_named(major, visorchipset_major, int, S_IRUGO);
Jes Sorensenb615d622015-05-05 18:35:38 -04002433MODULE_PARM_DESC(visorchipset_major,
2434 "major device number to use for the device node");
David Kershner4da33362015-05-05 18:36:39 -04002435module_param_named(visorbusregwait, visorchipset_visorbusregwait, int, S_IRUGO);
2436MODULE_PARM_DESC(visorchipset_visorbusreqwait,
Ken Cox12e364b2014-03-04 07:58:07 -06002437 "1 to have the module wait for the visor bus to register");
Ken Cox12e364b2014-03-04 07:58:07 -06002438module_param_named(holdchipsetready, visorchipset_holdchipsetready,
2439 int, S_IRUGO);
2440MODULE_PARM_DESC(visorchipset_holdchipsetready,
2441 "1 to hold response to CHIPSET_READY");
Jes Sorensenb615d622015-05-05 18:35:38 -04002442
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002443module_init(init_unisys);
2444module_exit(exit_unisys);
Ken Cox12e364b2014-03-04 07:58:07 -06002445
2446MODULE_AUTHOR("Unisys");
2447MODULE_LICENSE("GPL");
2448MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver "
2449 VERSION);
2450MODULE_VERSION(VERSION);