4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
6 * This work is licensed under the terms of the GNU GPL, version 2 or (at
7 * your option) any later version. See the COPYING file in the top-level
16 static long kvm_hypercall(unsigned long nr
, unsigned long param1
,
19 register ulong r_nr
asm("1") = nr
;
20 register ulong r_param1
asm("2") = param1
;
21 register ulong r_param2
asm("3") = param2
;
22 register long retval
asm("2");
24 asm volatile ("diag 2,4,0x500"
26 : "d" (r_nr
), "0" (r_param1
), "r"(r_param2
)
32 static void virtio_notify(struct subchannel_id schid
)
34 kvm_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY
, *(u32
*)&schid
, 0);
37 /***********************************************
39 ***********************************************/
41 static void drain_irqs(struct subchannel_id schid
)
45 if (tsch(schid
, &irb
)) {
51 static int run_ccw(struct subchannel_id schid
, int cmd
, void *ptr
, int len
)
54 struct cmd_orb orb
= {};
58 /* start command processing */
59 stsch_err(schid
, &schib
);
60 schib
.scsw
.ctrl
= SCSW_FCTL_START_FUNC
;
63 /* start subchannel command */
65 orb
.cpa
= (u32
)(long)&ccw
;
72 r
= ssch(schid
, &orb
);
74 * XXX Wait until device is done processing the CCW. For now we can
75 * assume that a simple tsch will have finished the CCW processing,
76 * but the architecture allows for asynchronous operation
82 static void virtio_set_status(struct subchannel_id schid
,
83 unsigned long dev_addr
)
85 unsigned char status
= dev_addr
;
86 run_ccw(schid
, CCW_CMD_WRITE_STATUS
, &status
, sizeof(status
));
89 static void virtio_reset(struct subchannel_id schid
)
91 run_ccw(schid
, CCW_CMD_VDEV_RESET
, NULL
, 0);
94 static void vring_init(struct vring
*vr
, unsigned int num
, void *p
,
97 debug_print_addr("init p", p
);
100 vr
->avail
= p
+ num
*sizeof(struct vring_desc
);
101 vr
->used
= (void *)(((unsigned long)&vr
->avail
->ring
[num
] + align
-1)
104 /* We're running with interrupts off anyways, so don't bother */
105 vr
->used
->flags
= VRING_USED_F_NO_NOTIFY
;
107 debug_print_addr("init vr", vr
);
110 static void vring_notify(struct subchannel_id schid
)
112 virtio_notify(schid
);
115 static void vring_send_buf(struct vring
*vr
, void *p
, int len
, int flags
)
117 /* For follow-up chains we need to keep the first entry point */
118 if (!(flags
& VRING_HIDDEN_IS_CHAIN
)) {
119 vr
->avail
->ring
[vr
->avail
->idx
% vr
->num
] = vr
->next_idx
;
122 vr
->desc
[vr
->next_idx
].addr
= (ulong
)p
;
123 vr
->desc
[vr
->next_idx
].len
= len
;
124 vr
->desc
[vr
->next_idx
].flags
= flags
& ~VRING_HIDDEN_IS_CHAIN
;
125 vr
->desc
[vr
->next_idx
].next
= ++vr
->next_idx
;
127 /* Chains only have a single ID */
128 if (!(flags
& VRING_DESC_F_NEXT
)) {
132 vr
->used
->idx
= vr
->next_idx
;
135 static u64
get_clock(void)
139 asm volatile("stck %0" : "=Q" (r
) : : "cc");
143 static ulong
get_second(void)
145 return (get_clock() >> 12) / 1000000;
149 * Wait for the host to reply.
151 * timeout is in seconds if > 0.
153 * Returns 0 on success, 1 on timeout.
155 static int vring_wait_reply(struct vring
*vr
, int timeout
)
157 ulong target_second
= get_second() + timeout
;
158 struct subchannel_id schid
= vr
->schid
;
161 while (vr
->used
->idx
== vr
->next_idx
) {
163 if (timeout
&& (get_second() >= target_second
)) {
172 vr
->desc
[0].flags
= 0;
177 /***********************************************
179 ***********************************************/
181 static int virtio_read_many(ulong sector
, void *load_addr
, int sec_num
)
183 struct virtio_blk_outhdr out_hdr
;
186 /* Tell the host we want to read */
187 out_hdr
.type
= VIRTIO_BLK_T_IN
;
189 out_hdr
.sector
= sector
;
191 vring_send_buf(&block
, &out_hdr
, sizeof(out_hdr
), VRING_DESC_F_NEXT
);
193 /* This is where we want to receive data */
194 vring_send_buf(&block
, load_addr
, SECTOR_SIZE
* sec_num
,
195 VRING_DESC_F_WRITE
| VRING_HIDDEN_IS_CHAIN
|
199 vring_send_buf(&block
, &status
, sizeof(u8
), VRING_DESC_F_WRITE
|
200 VRING_HIDDEN_IS_CHAIN
);
202 /* Now we can tell the host to read */
203 vring_wait_reply(&block
, 0);
205 drain_irqs(block
.schid
);
210 unsigned long virtio_load_direct(ulong rec_list1
, ulong rec_list2
,
211 ulong subchan_id
, void *load_addr
)
215 int sec_num
= (((rec_list2
>> 32)+ 1) & 0xffff);
216 int sec_len
= rec_list2
>> 48;
217 ulong addr
= (ulong
)load_addr
;
219 if (sec_len
!= SECTOR_SIZE
) {
224 status
= virtio_read_many(sec
, (void*)addr
, sec_num
);
226 virtio_panic("I/O Error");
228 addr
+= sec_num
* SECTOR_SIZE
;
233 int virtio_read(ulong sector
, void *load_addr
)
235 return virtio_read_many(sector
, load_addr
, 1);
238 void virtio_setup_block(struct subchannel_id schid
)
240 struct vq_info_block info
;
244 /* XXX need to fetch the 128 from host */
245 vring_init(&block
, 128, (void*)(100 * 1024 * 1024),
246 KVM_S390_VIRTIO_RING_ALIGN
);
248 info
.queue
= (100ULL * 1024ULL* 1024ULL);
249 info
.align
= KVM_S390_VIRTIO_RING_ALIGN
;
254 run_ccw(schid
, CCW_CMD_SET_VQ
, &info
, sizeof(info
));
255 virtio_set_status(schid
, VIRTIO_CONFIG_S_DRIVER_OK
);
258 bool virtio_is_blk(struct subchannel_id schid
)
261 struct senseid senseid
= {};
263 /* run sense id command */
264 r
= run_ccw(schid
, CCW_CMD_SENSE_ID
, &senseid
, sizeof(senseid
));
268 if ((senseid
.cu_type
!= 0x3832) || (senseid
.cu_model
!= VIRTIO_ID_BLOCK
)) {