1 // QEMU VMWARE Paravirtualized SCSI boot support.
2 //
3 // Copyright (c) 2013 Ravello Systems LTD (http://ravellosystems.com)
4 //
5 // Authors:
6 //  Evgeny Budilovsky <evgeny.budilovsky@ravellosystems.com>
7 //
8 // This file may be distributed under the terms of the GNU LGPLv3 license.
9 
10 #include "block.h" // struct drive_s
11 #include "blockcmd.h" // scsi_drive_setup
12 #include "config.h" // CONFIG_*
13 #include "malloc.h" // free
14 #include "memmap.h" // PAGE_SHIFT, virt_to_phys
15 #include "output.h" // dprintf
16 #include "pcidevice.h" // foreachpci
17 #include "pci_ids.h" // PCI_DEVICE_ID_VMWARE_PVSCSI
18 #include "pci_regs.h" // PCI_VENDOR_ID
19 #include "pvscsi.h" // pvscsi_setup
20 #include "stacks.h" // run_thread
21 #include "std/disk.h" // DISK_RET_SUCCESS
22 #include "string.h" // memset
23 #include "util.h" // usleep
24 #include "x86.h" // writel
25 
26 #define MASK(n) ((1 << (n)) - 1)
27 
28 #define SIMPLE_QUEUE_TAG 0x20
29 
30 #define PVSCSI_INTR_CMPL_0                 (1 << 0)
31 #define PVSCSI_INTR_CMPL_1                 (1 << 1)
32 #define PVSCSI_INTR_CMPL_MASK              MASK(2)
33 
34 #define PVSCSI_INTR_MSG_0                  (1 << 2)
35 #define PVSCSI_INTR_MSG_1                  (1 << 3)
36 #define PVSCSI_INTR_MSG_MASK               (MASK(2) << 2)
37 #define PVSCSI_INTR_ALL_SUPPORTED          MASK(4)
38 
39 #define PVSCSI_FLAG_CMD_WITH_SG_LIST       (1 << 0)
40 #define PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB    (1 << 1)
41 #define PVSCSI_FLAG_CMD_DIR_NONE           (1 << 2)
42 #define PVSCSI_FLAG_CMD_DIR_TOHOST         (1 << 3)
43 #define PVSCSI_FLAG_CMD_DIR_TODEVICE       (1 << 4)
44 
45 enum PVSCSIRegOffset {
46     PVSCSI_REG_OFFSET_COMMAND        =    0x0,
47     PVSCSI_REG_OFFSET_COMMAND_DATA   =    0x4,
48     PVSCSI_REG_OFFSET_COMMAND_STATUS =    0x8,
49     PVSCSI_REG_OFFSET_LAST_STS_0     =  0x100,
50     PVSCSI_REG_OFFSET_LAST_STS_1     =  0x104,
51     PVSCSI_REG_OFFSET_LAST_STS_2     =  0x108,
52     PVSCSI_REG_OFFSET_LAST_STS_3     =  0x10c,
53     PVSCSI_REG_OFFSET_INTR_STATUS    = 0x100c,
54     PVSCSI_REG_OFFSET_INTR_MASK      = 0x2010,
55     PVSCSI_REG_OFFSET_KICK_NON_RW_IO = 0x3014,
56     PVSCSI_REG_OFFSET_DEBUG          = 0x3018,
57     PVSCSI_REG_OFFSET_KICK_RW_IO     = 0x4018,
58 };
59 
60 enum PVSCSICommands {
61     PVSCSI_CMD_FIRST             = 0,
62     PVSCSI_CMD_ADAPTER_RESET     = 1,
63     PVSCSI_CMD_ISSUE_SCSI        = 2,
64     PVSCSI_CMD_SETUP_RINGS       = 3,
65     PVSCSI_CMD_RESET_BUS         = 4,
66     PVSCSI_CMD_RESET_DEVICE      = 5,
67     PVSCSI_CMD_ABORT_CMD         = 6,
68     PVSCSI_CMD_CONFIG            = 7,
69     PVSCSI_CMD_SETUP_MSG_RING    = 8,
70     PVSCSI_CMD_DEVICE_UNPLUG     = 9,
71     PVSCSI_CMD_LAST              = 10
72 };
73 
74 #define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES        32
75 struct PVSCSICmdDescSetupRings {
76     u32    reqRingNumPages;
77     u32    cmpRingNumPages;
78     u64    ringsStatePPN;
79     u64    reqRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
80     u64    cmpRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
81 } PACKED;
82 
83 struct PVSCSIRingCmpDesc {
84     u64    context;
85     u64    dataLen;
86     u32    senseLen;
87     u16    hostStatus;
88     u16    scsiStatus;
89     u32    pad[2];
90 } PACKED;
91 
92 struct PVSCSIRingsState {
93     u32    reqProdIdx;
94     u32    reqConsIdx;
95     u32    reqNumEntriesLog2;
96 
97     u32    cmpProdIdx;
98     u32    cmpConsIdx;
99     u32    cmpNumEntriesLog2;
100 
101     u8     pad[104];
102 
103     u32    msgProdIdx;
104     u32    msgConsIdx;
105     u32    msgNumEntriesLog2;
106 } PACKED;
107 
108 struct PVSCSIRingReqDesc {
109     u64    context;
110     u64    dataAddr;
111     u64    dataLen;
112     u64    senseAddr;
113     u32    senseLen;
114     u32    flags;
115     u8     cdb[16];
116     u8     cdbLen;
117     u8     lun[8];
118     u8     tag;
119     u8     bus;
120     u8     target;
121     u8     vcpuHint;
122     u8     unused[59];
123 } PACKED;
124 
125 struct pvscsi_ring_dsc_s {
126     struct PVSCSIRingsState *ring_state;
127     struct PVSCSIRingReqDesc *ring_reqs;
128     struct PVSCSIRingCmpDesc *ring_cmps;
129 };
130 
131 struct pvscsi_lun_s {
132     struct drive_s drive;
133     void *iobase;
134     u8 target;
135     u8 lun;
136     struct pvscsi_ring_dsc_s *ring_dsc;
137 };
138 
139 static void
pvscsi_write_cmd_desc(void * iobase,u32 cmd,const void * desc,size_t len)140 pvscsi_write_cmd_desc(void *iobase, u32 cmd, const void *desc, size_t len)
141 {
142     const u32 *ptr = desc;
143     size_t i;
144 
145     len /= sizeof(*ptr);
146     writel(iobase + PVSCSI_REG_OFFSET_COMMAND, cmd);
147     for (i = 0; i < len; i++)
148         writel(iobase + PVSCSI_REG_OFFSET_COMMAND_DATA, ptr[i]);
149 }
150 
151 static void
pvscsi_kick_rw_io(void * iobase)152 pvscsi_kick_rw_io(void *iobase)
153 {
154     writel(iobase + PVSCSI_REG_OFFSET_KICK_RW_IO, 0);
155 }
156 
157 static void
pvscsi_wait_intr_cmpl(void * iobase)158 pvscsi_wait_intr_cmpl(void *iobase)
159 {
160     while (!(readl(iobase + PVSCSI_REG_OFFSET_INTR_STATUS) & PVSCSI_INTR_CMPL_MASK))
161         usleep(5);
162     writel(iobase + PVSCSI_REG_OFFSET_INTR_STATUS, PVSCSI_INTR_CMPL_MASK);
163 }
164 
165 static void
pvscsi_init_rings(void * iobase,struct pvscsi_ring_dsc_s ** ring_dsc)166 pvscsi_init_rings(void *iobase, struct pvscsi_ring_dsc_s **ring_dsc)
167 {
168     struct PVSCSICmdDescSetupRings cmd = {0,};
169 
170     struct pvscsi_ring_dsc_s *dsc = malloc_high(sizeof(*dsc));
171     if (!dsc) {
172         warn_noalloc();
173         return;
174     }
175 
176     dsc->ring_state =
177         (struct PVSCSIRingsState *)memalign_high(PAGE_SIZE, PAGE_SIZE);
178     dsc->ring_reqs =
179         (struct PVSCSIRingReqDesc *)memalign_high(PAGE_SIZE, PAGE_SIZE);
180     dsc->ring_cmps =
181         (struct PVSCSIRingCmpDesc *)memalign_high(PAGE_SIZE, PAGE_SIZE);
182     if (!dsc->ring_state || !dsc->ring_reqs || !dsc->ring_cmps) {
183         warn_noalloc();
184         return;
185     }
186     memset(dsc->ring_state, 0, PAGE_SIZE);
187     memset(dsc->ring_reqs, 0, PAGE_SIZE);
188     memset(dsc->ring_cmps, 0, PAGE_SIZE);
189 
190     cmd.reqRingNumPages = 1;
191     cmd.cmpRingNumPages = 1;
192     cmd.ringsStatePPN = virt_to_phys(dsc->ring_state) >> PAGE_SHIFT;
193     cmd.reqRingPPNs[0] = virt_to_phys(dsc->ring_reqs) >> PAGE_SHIFT;
194     cmd.cmpRingPPNs[0] = virt_to_phys(dsc->ring_cmps) >> PAGE_SHIFT;
195 
196     pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_SETUP_RINGS,
197                           &cmd, sizeof(cmd));
198     *ring_dsc = dsc;
199 }
200 
201 static u32
pvscsi_get_rsp(struct PVSCSIRingsState * s,struct PVSCSIRingCmpDesc * rsp)202 pvscsi_get_rsp(struct PVSCSIRingsState *s,
203                struct PVSCSIRingCmpDesc *rsp)
204 {
205     u32 status = rsp->hostStatus;
206     s->cmpConsIdx = s->cmpConsIdx + 1;
207     return status;
208 }
209 
210 int
pvscsi_process_op(struct disk_op_s * op)211 pvscsi_process_op(struct disk_op_s *op)
212 {
213     if (!CONFIG_PVSCSI)
214         return DISK_RET_EBADTRACK;
215     struct pvscsi_lun_s *plun =
216         container_of(op->drive_fl, struct pvscsi_lun_s, drive);
217     struct pvscsi_ring_dsc_s *ring_dsc = plun->ring_dsc;
218     struct PVSCSIRingsState *s = ring_dsc->ring_state;
219     u32 req_entries = s->reqNumEntriesLog2;
220     u32 cmp_entries = s->cmpNumEntriesLog2;
221     struct PVSCSIRingReqDesc *req;
222     struct PVSCSIRingCmpDesc *rsp;
223     u32 status;
224 
225     if (s->reqProdIdx - s->cmpConsIdx >= 1 << req_entries) {
226         dprintf(1, "pvscsi: ring full: reqProdIdx=%d cmpConsIdx=%d\n",
227                 s->reqProdIdx, s->cmpConsIdx);
228         return DISK_RET_EBADTRACK;
229     }
230 
231     req = ring_dsc->ring_reqs + (s->reqProdIdx & MASK(req_entries));
232     int blocksize = scsi_fill_cmd(op, req->cdb, 16);
233     if (blocksize < 0)
234         return default_process_op(op);
235     req->bus = 0;
236     req->target = plun->target;
237     memset(req->lun, 0, sizeof(req->lun));
238     req->lun[1] = plun->lun;
239     req->senseLen = 0;
240     req->senseAddr = 0;
241     req->cdbLen = 16;
242     req->vcpuHint = 0;
243     req->tag = SIMPLE_QUEUE_TAG;
244     req->flags = scsi_is_read(op) ?
245         PVSCSI_FLAG_CMD_DIR_TOHOST : PVSCSI_FLAG_CMD_DIR_TODEVICE;
246     req->dataLen = op->count * blocksize;
247     req->dataAddr = (u32)op->buf_fl;
248     s->reqProdIdx = s->reqProdIdx + 1;
249 
250     pvscsi_kick_rw_io(plun->iobase);
251     pvscsi_wait_intr_cmpl(plun->iobase);
252 
253     rsp = ring_dsc->ring_cmps + (s->cmpConsIdx & MASK(cmp_entries));
254     status = pvscsi_get_rsp(s, rsp);
255 
256     return status == 0 ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
257 }
258 
259 static int
pvscsi_add_lun(struct pci_device * pci,void * iobase,struct pvscsi_ring_dsc_s * ring_dsc,u8 target,u8 lun)260 pvscsi_add_lun(struct pci_device *pci, void *iobase,
261                struct pvscsi_ring_dsc_s *ring_dsc, u8 target, u8 lun)
262 {
263     struct pvscsi_lun_s *plun = malloc_fseg(sizeof(*plun));
264     if (!plun) {
265         warn_noalloc();
266         return -1;
267     }
268     memset(plun, 0, sizeof(*plun));
269     plun->drive.type = DTYPE_PVSCSI;
270     plun->drive.cntl_id = pci->bdf;
271     plun->target = target;
272     plun->lun = lun;
273     plun->iobase = iobase;
274     plun->ring_dsc = ring_dsc;
275 
276     boot_lchs_find_scsi_device(pci, target, lun, &(plun->drive.lchs));
277     char *name = znprintf(MAXDESCSIZE, "pvscsi %pP %d:%d", pci, target, lun);
278     int prio = bootprio_find_scsi_device(pci, target, lun);
279     int ret = scsi_drive_setup(&plun->drive, name, prio, target, lun);
280     free(name);
281     if (ret)
282         goto fail;
283     return 0;
284 
285 fail:
286     free(plun);
287     return -1;
288 }
289 
290 static void
pvscsi_scan_target(struct pci_device * pci,void * iobase,struct pvscsi_ring_dsc_s * ring_dsc,u8 target)291 pvscsi_scan_target(struct pci_device *pci, void *iobase,
292                    struct pvscsi_ring_dsc_s *ring_dsc, u8 target)
293 {
294     /* pvscsi has no more than a single lun per target */
295     pvscsi_add_lun(pci, iobase, ring_dsc, target, 0);
296 }
297 
298 static void
init_pvscsi(void * data)299 init_pvscsi(void *data)
300 {
301     struct pci_device *pci = data;
302     void *iobase = pci_enable_membar(pci, PCI_BASE_ADDRESS_0);
303     if (!iobase)
304         return;
305     pci_enable_busmaster(pci);
306 
307     dprintf(1, "found pvscsi at %pP, io @ %p\n", pci, iobase);
308 
309     pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_ADAPTER_RESET, NULL, 0);
310 
311     struct pvscsi_ring_dsc_s *ring_dsc = NULL;
312     pvscsi_init_rings(iobase, &ring_dsc);
313     int i;
314     for (i = 0; i < 64; i++)
315         pvscsi_scan_target(pci, iobase, ring_dsc, i);
316 }
317 
318 void
pvscsi_setup(void)319 pvscsi_setup(void)
320 {
321     ASSERT32FLAT();
322     if (! CONFIG_PVSCSI)
323         return;
324 
325     dprintf(3, "init pvscsi\n");
326 
327     struct pci_device *pci;
328     foreachpci(pci) {
329         if (pci->vendor != PCI_VENDOR_ID_VMWARE
330             || pci->device != PCI_DEVICE_ID_VMWARE_PVSCSI)
331             continue;
332         run_thread(init_pvscsi, pci);
333     }
334 }
335