Compare commits
190
Commits
v2.4.0-rc2
..
v2.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32d24131b2 | ||
|
|
fc63922556 | ||
|
|
36e1eee760 | ||
|
|
9137bd24c8 | ||
|
|
08231cbb76 | ||
|
|
70a4483abb | ||
|
|
39809852a7 | ||
|
|
db97d9d886 | ||
|
|
243b80c9c5 | ||
|
|
91232d98da | ||
|
|
d68ba3cab3 | ||
|
|
381a290266 | ||
|
|
696317f189 | ||
|
|
c2a550d3df | ||
|
|
a64d4cafa9 | ||
|
|
2f99c80963 | ||
|
|
f62c10bd20 | ||
|
|
8c4fa92d01 | ||
|
|
7c22dcdeb8 | ||
|
|
16514367ef | ||
|
|
55b4efb034 | ||
|
|
2874c6565e | ||
|
|
2d0583fc79 | ||
|
|
40161bf27b | ||
|
|
2935ae915a | ||
|
|
2f3c310818 | ||
|
|
1f21d3b8dc | ||
|
|
bac9ce97d3 | ||
|
|
33fca8589c | ||
|
|
a479b21c11 | ||
|
|
d11ff15fd5 | ||
|
|
1b8e1f7ad9 | ||
|
|
e00bf9ee70 | ||
|
|
78aeb6984c | ||
|
|
6d62d0e3dd | ||
|
|
5644f6f924 | ||
|
|
63d761388d | ||
|
|
c13b1c8314 | ||
|
|
052677b2c8 | ||
|
|
0fdf9f756f | ||
|
|
d077545dfe | ||
|
|
f6737604da | ||
|
|
d2b0f96fe2 | ||
|
|
a00431853f | ||
|
|
b51715e1c0 | ||
|
|
267bc47438 | ||
|
|
955ff148de | ||
|
|
71b685832d | ||
|
|
9a20ccaecd | ||
|
|
d9af73191c | ||
|
|
637dd0bb7c | ||
|
|
2ac9fa162e | ||
|
|
5b7d840e74 | ||
|
|
0de7d2b793 | ||
|
|
f399ea092e | ||
|
|
83c92b4514 | ||
|
|
5a1ccdfe44 | ||
|
|
7aa2bcad0c | ||
|
|
3a56af1fbc | ||
|
|
efec4dcd25 | ||
|
|
5c79ae3615 | ||
|
|
2d697366a1 | ||
|
|
0175409df4 | ||
|
|
e94867ed5f | ||
|
|
74aae7b22b | ||
|
|
2be4f242b5 | ||
|
|
27751aabd1 | ||
|
|
426d0e7b7e | ||
|
|
b7f26e5239 | ||
|
|
060ebfef1a | ||
|
|
260425ab40 | ||
|
|
e95edefbd0 | ||
|
|
8c6dc68f4c | ||
|
|
c69adea462 | ||
|
|
f60c87154a | ||
|
|
6cd387833d | ||
|
|
2a3612ccc1 | ||
|
|
8357946b15 | ||
|
|
4240be4563 | ||
|
|
c6296ea88d | ||
|
|
03247d43c5 | ||
|
|
e1c120a9c5 | ||
|
|
d6812d60e7 | ||
|
|
39b8e7dcaf | ||
|
|
bd80b5963f | ||
|
|
ff90f84e74 | ||
|
|
c99d69694a | ||
|
|
3c8691f568 | ||
|
|
4214a8cb7c | ||
|
|
e72c4fb81d | ||
|
|
91ced51446 | ||
|
|
0e826a061a | ||
|
|
cb48f67ad8 | ||
|
|
7008d580ac | ||
|
|
46739a2d7a | ||
|
|
ca96ac44dc | ||
|
|
a076972a4d | ||
|
|
fed105e275 | ||
|
|
b83d017d88 | ||
|
|
170f209d78 | ||
|
|
8b89b3a8df | ||
|
|
5e868d2e5e | ||
|
|
9f8c5b69c2 | ||
|
|
7bba83bf80 | ||
|
|
776f878451 | ||
|
|
ff1d2ac949 | ||
|
|
52579c681c | ||
|
|
30dfa9a46c | ||
|
|
f6351288b6 | ||
|
|
84a29c7efd | ||
|
|
da52a4dfcc | ||
|
|
8bcbb834a0 | ||
|
|
325e390421 | ||
|
|
6a55c82cec | ||
|
|
52c91dac6b | ||
|
|
55875fc4ca | ||
|
|
c147b5153e | ||
|
|
8ef3ea253b | ||
|
|
226d007dbd | ||
|
|
801db5ecda | ||
|
|
786f9ce203 | ||
|
|
7e71e111e0 | ||
|
|
7155f2ca9d | ||
|
|
f6288b9c88 | ||
|
|
ab60366308 | ||
|
|
cc47a16bcb | ||
|
|
f3c30aeaa7 | ||
|
|
be66680e83 | ||
|
|
f8787f8723 | ||
|
|
edec47cfef | ||
|
|
77c102c26e | ||
|
|
b15deac795 | ||
|
|
3737129917 | ||
|
|
c9b11f971c | ||
|
|
efb8206ca7 | ||
|
|
9d5b731dd2 | ||
|
|
27462695cd | ||
|
|
bbeb82395e | ||
|
|
7df69deadf | ||
|
|
122e7dab8a | ||
|
|
f9f7492ea4 | ||
|
|
4594f93a73 | ||
|
|
1ef4a6069f | ||
|
|
1dd58ae058 | ||
|
|
3b7031e960 | ||
|
|
e813f0d881 | ||
|
|
575bafd1f3 | ||
|
|
b6cb6610c2 | ||
|
|
913440249e | ||
|
|
363db4b249 | ||
|
|
b0ba0b9b6b | ||
|
|
8c8c460c5f | ||
|
|
491a1f494e | ||
|
|
299f7bec5a | ||
|
|
3634869b27 | ||
|
|
3e230569bf | ||
|
|
e40db4c6d3 | ||
|
|
019c2ab862 | ||
|
|
6775e2c429 | ||
|
|
09999a5f7f | ||
|
|
cd4bfbb20d | ||
|
|
7882080388 | ||
|
|
5f456073aa | ||
|
|
cb72cba830 | ||
|
|
03441c3a4a | ||
|
|
d2ff858545 | ||
|
|
f793d97e45 | ||
|
|
178846bdd9 | ||
|
|
d274e07c6d | ||
|
|
c1076c3e13 | ||
|
|
deb809edb8 | ||
|
|
fb43096959 | ||
|
|
7d99f4c1b5 | ||
|
|
ab28bd2312 | ||
|
|
c170aad8b0 | ||
|
|
60928458e5 | ||
|
|
30fdfae49d | ||
|
|
f75b709853 | ||
|
|
961521261a | ||
|
|
80adb8fcad | ||
|
|
ffc6372851 | ||
|
|
6c0f0c0f12 | ||
|
|
ee8ba9e4d8 | ||
|
|
12e21eb088 | ||
|
|
4bf1cb03fb | ||
|
|
9172f428af | ||
|
|
0b8e2c1002 | ||
|
|
759b484c5d | ||
|
|
69970fcef9 | ||
|
|
6b2699672d |
No files matched your search
@@ -17,6 +17,8 @@
|
|||||||
/trace/generated-tcg-tracers.h
|
/trace/generated-tcg-tracers.h
|
||||||
/trace/generated-ust-provider.h
|
/trace/generated-ust-provider.h
|
||||||
/trace/generated-ust.c
|
/trace/generated-ust.c
|
||||||
|
/ui/shader/texture-blit-frag.h
|
||||||
|
/ui/shader/texture-blit-vert.h
|
||||||
/libcacard/trace/generated-tracers.c
|
/libcacard/trace/generated-tracers.c
|
||||||
*-timestamp
|
*-timestamp
|
||||||
/*-softmmu
|
/*-softmmu
|
||||||
|
|||||||
@@ -79,8 +79,10 @@ int aio_bh_poll(AioContext *ctx)
|
|||||||
* aio_notify again if necessary.
|
* aio_notify again if necessary.
|
||||||
*/
|
*/
|
||||||
if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) {
|
if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) {
|
||||||
if (!bh->idle)
|
/* Idle BHs and the notify BH don't count as progress */
|
||||||
|
if (!bh->idle && bh != ctx->notify_dummy_bh) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
}
|
||||||
bh->idle = 0;
|
bh->idle = 0;
|
||||||
bh->cb(bh->opaque);
|
bh->cb(bh->opaque);
|
||||||
}
|
}
|
||||||
@@ -230,7 +232,21 @@ aio_ctx_finalize(GSource *source)
|
|||||||
{
|
{
|
||||||
AioContext *ctx = (AioContext *) source;
|
AioContext *ctx = (AioContext *) source;
|
||||||
|
|
||||||
|
qemu_bh_delete(ctx->notify_dummy_bh);
|
||||||
thread_pool_free(ctx->thread_pool);
|
thread_pool_free(ctx->thread_pool);
|
||||||
|
|
||||||
|
qemu_mutex_lock(&ctx->bh_lock);
|
||||||
|
while (ctx->first_bh) {
|
||||||
|
QEMUBH *next = ctx->first_bh->next;
|
||||||
|
|
||||||
|
/* qemu_bh_delete() must have been called on BHs in this AioContext */
|
||||||
|
assert(ctx->first_bh->deleted);
|
||||||
|
|
||||||
|
g_free(ctx->first_bh);
|
||||||
|
ctx->first_bh = next;
|
||||||
|
}
|
||||||
|
qemu_mutex_unlock(&ctx->bh_lock);
|
||||||
|
|
||||||
aio_set_event_notifier(ctx, &ctx->notifier, NULL);
|
aio_set_event_notifier(ctx, &ctx->notifier, NULL);
|
||||||
event_notifier_cleanup(&ctx->notifier);
|
event_notifier_cleanup(&ctx->notifier);
|
||||||
rfifolock_destroy(&ctx->lock);
|
rfifolock_destroy(&ctx->lock);
|
||||||
@@ -285,8 +301,15 @@ static void aio_timerlist_notify(void *opaque)
|
|||||||
|
|
||||||
static void aio_rfifolock_cb(void *opaque)
|
static void aio_rfifolock_cb(void *opaque)
|
||||||
{
|
{
|
||||||
|
AioContext *ctx = opaque;
|
||||||
|
|
||||||
/* Kick owner thread in case they are blocked in aio_poll() */
|
/* Kick owner thread in case they are blocked in aio_poll() */
|
||||||
aio_notify(opaque);
|
qemu_bh_schedule(ctx->notify_dummy_bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void notify_dummy_bh(void *opaque)
|
||||||
|
{
|
||||||
|
/* Do nothing, we were invoked just to force the event loop to iterate */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void event_notifier_dummy_cb(EventNotifier *e)
|
static void event_notifier_dummy_cb(EventNotifier *e)
|
||||||
@@ -313,6 +336,8 @@ AioContext *aio_context_new(Error **errp)
|
|||||||
rfifolock_init(&ctx->lock, aio_rfifolock_cb, ctx);
|
rfifolock_init(&ctx->lock, aio_rfifolock_cb, ctx);
|
||||||
timerlistgroup_init(&ctx->tlg, aio_timerlist_notify, ctx);
|
timerlistgroup_init(&ctx->tlg, aio_timerlist_notify, ctx);
|
||||||
|
|
||||||
|
ctx->notify_dummy_bh = aio_bh_new(ctx, notify_dummy_bh, NULL);
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -10,6 +10,7 @@
|
|||||||
* See the COPYING file in the top-level directory.
|
* See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
#include "sysemu/hostmem.h"
|
#include "sysemu/hostmem.h"
|
||||||
|
#include "hw/boards.h"
|
||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
#include "qapi-types.h"
|
#include "qapi-types.h"
|
||||||
#include "qapi-visit.h"
|
#include "qapi-visit.h"
|
||||||
@@ -222,11 +223,10 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
|
|||||||
static void host_memory_backend_init(Object *obj)
|
static void host_memory_backend_init(Object *obj)
|
||||||
{
|
{
|
||||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||||
|
MachineState *machine = MACHINE(qdev_get_machine());
|
||||||
|
|
||||||
backend->merge = qemu_opt_get_bool(qemu_get_machine_opts(),
|
backend->merge = machine_mem_merge(machine);
|
||||||
"mem-merge", true);
|
backend->dump = machine_dump_guest_core(machine);
|
||||||
backend->dump = qemu_opt_get_bool(qemu_get_machine_opts(),
|
|
||||||
"dump-guest-core", true);
|
|
||||||
backend->prealloc = mem_prealloc;
|
backend->prealloc = mem_prealloc;
|
||||||
|
|
||||||
object_property_add_bool(obj, "merge",
|
object_property_add_bool(obj, "merge",
|
||||||
|
|||||||
@@ -1214,6 +1214,10 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
|
|||||||
|
|
||||||
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
|
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
|
||||||
error_setg(errp, "iSCSI: failed to send readcapacity10 command.");
|
error_setg(errp, "iSCSI: failed to send readcapacity10 command.");
|
||||||
|
} else if (!iscsilun->block_size ||
|
||||||
|
iscsilun->block_size % BDRV_SECTOR_SIZE) {
|
||||||
|
error_setg(errp, "iSCSI: the target returned an invalid "
|
||||||
|
"block size of %d.", iscsilun->block_size);
|
||||||
}
|
}
|
||||||
if (task) {
|
if (task) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
|
|||||||
+10
-5
@@ -60,6 +60,7 @@ typedef struct MirrorBlockJob {
|
|||||||
int sectors_in_flight;
|
int sectors_in_flight;
|
||||||
int ret;
|
int ret;
|
||||||
bool unmap;
|
bool unmap;
|
||||||
|
bool waiting_for_io;
|
||||||
} MirrorBlockJob;
|
} MirrorBlockJob;
|
||||||
|
|
||||||
typedef struct MirrorOp {
|
typedef struct MirrorOp {
|
||||||
@@ -114,11 +115,7 @@ static void mirror_iteration_done(MirrorOp *op, int ret)
|
|||||||
qemu_iovec_destroy(&op->qiov);
|
qemu_iovec_destroy(&op->qiov);
|
||||||
g_slice_free(MirrorOp, op);
|
g_slice_free(MirrorOp, op);
|
||||||
|
|
||||||
/* Enter coroutine when it is not sleeping. The coroutine sleeps to
|
if (s->waiting_for_io) {
|
||||||
* rate-limit itself. The coroutine will eventually resume since there is
|
|
||||||
* a sleep timeout so don't wake it early.
|
|
||||||
*/
|
|
||||||
if (s->common.busy) {
|
|
||||||
qemu_coroutine_enter(s->common.co, NULL);
|
qemu_coroutine_enter(s->common.co, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,7 +200,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
|||||||
/* Wait for I/O to this cluster (from a previous iteration) to be done. */
|
/* Wait for I/O to this cluster (from a previous iteration) to be done. */
|
||||||
while (test_bit(next_chunk, s->in_flight_bitmap)) {
|
while (test_bit(next_chunk, s->in_flight_bitmap)) {
|
||||||
trace_mirror_yield_in_flight(s, sector_num, s->in_flight);
|
trace_mirror_yield_in_flight(s, sector_num, s->in_flight);
|
||||||
|
s->waiting_for_io = true;
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
|
s->waiting_for_io = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -239,7 +238,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
|||||||
*/
|
*/
|
||||||
while (nb_chunks == 0 && s->buf_free_count < added_chunks) {
|
while (nb_chunks == 0 && s->buf_free_count < added_chunks) {
|
||||||
trace_mirror_yield_buf_busy(s, nb_chunks, s->in_flight);
|
trace_mirror_yield_buf_busy(s, nb_chunks, s->in_flight);
|
||||||
|
s->waiting_for_io = true;
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
|
s->waiting_for_io = false;
|
||||||
}
|
}
|
||||||
if (s->buf_free_count < nb_chunks + added_chunks) {
|
if (s->buf_free_count < nb_chunks + added_chunks) {
|
||||||
trace_mirror_break_buf_busy(s, nb_chunks, s->in_flight);
|
trace_mirror_break_buf_busy(s, nb_chunks, s->in_flight);
|
||||||
@@ -333,7 +334,9 @@ static void mirror_free_init(MirrorBlockJob *s)
|
|||||||
static void mirror_drain(MirrorBlockJob *s)
|
static void mirror_drain(MirrorBlockJob *s)
|
||||||
{
|
{
|
||||||
while (s->in_flight > 0) {
|
while (s->in_flight > 0) {
|
||||||
|
s->waiting_for_io = true;
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
|
s->waiting_for_io = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,7 +509,9 @@ static void coroutine_fn mirror_run(void *opaque)
|
|||||||
if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 ||
|
if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 ||
|
||||||
(cnt == 0 && s->in_flight > 0)) {
|
(cnt == 0 && s->in_flight > 0)) {
|
||||||
trace_mirror_yield(s, s->in_flight, s->buf_free_count, cnt);
|
trace_mirror_yield(s, s->in_flight, s->buf_free_count, cnt);
|
||||||
|
s->waiting_for_io = true;
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
|
s->waiting_for_io = false;
|
||||||
continue;
|
continue;
|
||||||
} else if (cnt != 0) {
|
} else if (cnt != 0) {
|
||||||
delay_ns = mirror_iteration(s);
|
delay_ns = mirror_iteration(s);
|
||||||
|
|||||||
+1
-1
@@ -475,7 +475,7 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
|
|||||||
aio_poll(client->aio_context, true);
|
aio_poll(client->aio_context, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (task.ret < 0 ? task.ret : st.st_blocks * st.st_blksize);
|
return (task.ret < 0 ? task.ret : st.st_blocks * 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nfs_file_truncate(BlockDriverState *bs, int64_t offset)
|
static int nfs_file_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
|
|||||||
+18
-10
@@ -298,7 +298,7 @@ fail:
|
|||||||
* as contiguous. (This allows it, for example, to stop at the first compressed
|
* as contiguous. (This allows it, for example, to stop at the first compressed
|
||||||
* cluster which may require a different handling)
|
* cluster which may require a different handling)
|
||||||
*/
|
*/
|
||||||
static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
|
static int count_contiguous_clusters(int nb_clusters, int cluster_size,
|
||||||
uint64_t *l2_table, uint64_t stop_flags)
|
uint64_t *l2_table, uint64_t stop_flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -321,7 +321,7 @@ static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table)
|
static int count_contiguous_free_clusters(int nb_clusters, uint64_t *l2_table)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -495,6 +495,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
|||||||
if (nb_needed > nb_available) {
|
if (nb_needed > nb_available) {
|
||||||
nb_needed = nb_available;
|
nb_needed = nb_available;
|
||||||
}
|
}
|
||||||
|
assert(nb_needed <= INT_MAX);
|
||||||
|
|
||||||
*cluster_offset = 0;
|
*cluster_offset = 0;
|
||||||
|
|
||||||
@@ -530,6 +531,8 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
|||||||
|
|
||||||
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
|
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
|
||||||
*cluster_offset = be64_to_cpu(l2_table[l2_index]);
|
*cluster_offset = be64_to_cpu(l2_table[l2_index]);
|
||||||
|
|
||||||
|
/* nb_needed <= INT_MAX, thus nb_clusters <= INT_MAX, too */
|
||||||
nb_clusters = size_to_clusters(s, nb_needed << 9);
|
nb_clusters = size_to_clusters(s, nb_needed << 9);
|
||||||
|
|
||||||
ret = qcow2_get_cluster_type(*cluster_offset);
|
ret = qcow2_get_cluster_type(*cluster_offset);
|
||||||
@@ -960,7 +963,7 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
|
|||||||
int l2_index;
|
int l2_index;
|
||||||
uint64_t cluster_offset;
|
uint64_t cluster_offset;
|
||||||
uint64_t *l2_table;
|
uint64_t *l2_table;
|
||||||
unsigned int nb_clusters;
|
uint64_t nb_clusters;
|
||||||
unsigned int keep_clusters;
|
unsigned int keep_clusters;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -979,6 +982,7 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
|
|||||||
|
|
||||||
l2_index = offset_to_l2_index(s, guest_offset);
|
l2_index = offset_to_l2_index(s, guest_offset);
|
||||||
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
||||||
|
assert(nb_clusters <= INT_MAX);
|
||||||
|
|
||||||
/* Find L2 entry for the first involved cluster */
|
/* Find L2 entry for the first involved cluster */
|
||||||
ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
|
ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
|
||||||
@@ -1061,7 +1065,7 @@ out:
|
|||||||
* restarted, but the whole request should not be failed.
|
* restarted, but the whole request should not be failed.
|
||||||
*/
|
*/
|
||||||
static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
|
static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
|
||||||
uint64_t *host_offset, unsigned int *nb_clusters)
|
uint64_t *host_offset, uint64_t *nb_clusters)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
|
|
||||||
@@ -1079,7 +1083,7 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
|
|||||||
*host_offset = cluster_offset;
|
*host_offset = cluster_offset;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
|
int64_t ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1115,7 +1119,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
|
|||||||
int l2_index;
|
int l2_index;
|
||||||
uint64_t *l2_table;
|
uint64_t *l2_table;
|
||||||
uint64_t entry;
|
uint64_t entry;
|
||||||
unsigned int nb_clusters;
|
uint64_t nb_clusters;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
uint64_t alloc_cluster_offset;
|
uint64_t alloc_cluster_offset;
|
||||||
@@ -1133,6 +1137,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
|
|||||||
|
|
||||||
l2_index = offset_to_l2_index(s, guest_offset);
|
l2_index = offset_to_l2_index(s, guest_offset);
|
||||||
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
||||||
|
assert(nb_clusters <= INT_MAX);
|
||||||
|
|
||||||
/* Find L2 entry for the first involved cluster */
|
/* Find L2 entry for the first involved cluster */
|
||||||
ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
|
ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
|
||||||
@@ -1426,7 +1431,8 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
|
|||||||
* clusters.
|
* clusters.
|
||||||
*/
|
*/
|
||||||
static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
||||||
unsigned int nb_clusters, enum qcow2_discard_type type, bool full_discard)
|
uint64_t nb_clusters, enum qcow2_discard_type type,
|
||||||
|
bool full_discard)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
uint64_t *l2_table;
|
uint64_t *l2_table;
|
||||||
@@ -1441,6 +1447,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
|||||||
|
|
||||||
/* Limit nb_clusters to one L2 table */
|
/* Limit nb_clusters to one L2 table */
|
||||||
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
||||||
|
assert(nb_clusters <= INT_MAX);
|
||||||
|
|
||||||
for (i = 0; i < nb_clusters; i++) {
|
for (i = 0; i < nb_clusters; i++) {
|
||||||
uint64_t old_l2_entry;
|
uint64_t old_l2_entry;
|
||||||
@@ -1503,7 +1510,7 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
|
|||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
uint64_t end_offset;
|
uint64_t end_offset;
|
||||||
unsigned int nb_clusters;
|
uint64_t nb_clusters;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
|
end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
|
||||||
@@ -1545,7 +1552,7 @@ fail:
|
|||||||
* clusters.
|
* clusters.
|
||||||
*/
|
*/
|
||||||
static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
|
static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
|
||||||
unsigned int nb_clusters)
|
uint64_t nb_clusters)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
uint64_t *l2_table;
|
uint64_t *l2_table;
|
||||||
@@ -1560,6 +1567,7 @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
|
|||||||
|
|
||||||
/* Limit nb_clusters to one L2 table */
|
/* Limit nb_clusters to one L2 table */
|
||||||
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
||||||
|
assert(nb_clusters <= INT_MAX);
|
||||||
|
|
||||||
for (i = 0; i < nb_clusters; i++) {
|
for (i = 0; i < nb_clusters; i++) {
|
||||||
uint64_t old_offset;
|
uint64_t old_offset;
|
||||||
@@ -1584,7 +1592,7 @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
|
|||||||
int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors)
|
int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
unsigned int nb_clusters;
|
uint64_t nb_clusters;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* The zero flag is only supported by version 3 and newer */
|
/* The zero flag is only supported by version 3 and newer */
|
||||||
|
|||||||
@@ -875,8 +875,8 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size)
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
|
int64_t qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
|
||||||
int nb_clusters)
|
int64_t nb_clusters)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
uint64_t cluster_index, refcount;
|
uint64_t cluster_index, refcount;
|
||||||
@@ -1259,7 +1259,7 @@ static size_t refcount_array_byte_size(BDRVQcowState *s, uint64_t entries)
|
|||||||
static int realloc_refcount_array(BDRVQcowState *s, void **array,
|
static int realloc_refcount_array(BDRVQcowState *s, void **array,
|
||||||
int64_t *size, int64_t new_size)
|
int64_t *size, int64_t new_size)
|
||||||
{
|
{
|
||||||
size_t old_byte_size, new_byte_size;
|
int64_t old_byte_size, new_byte_size;
|
||||||
void *new_ptr;
|
void *new_ptr;
|
||||||
|
|
||||||
/* Round to clusters so the array can be directly written to disk */
|
/* Round to clusters so the array can be directly written to disk */
|
||||||
@@ -1275,13 +1275,17 @@ static int realloc_refcount_array(BDRVQcowState *s, void **array,
|
|||||||
|
|
||||||
assert(new_byte_size > 0);
|
assert(new_byte_size > 0);
|
||||||
|
|
||||||
|
if (new_byte_size > SIZE_MAX) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
new_ptr = g_try_realloc(*array, new_byte_size);
|
new_ptr = g_try_realloc(*array, new_byte_size);
|
||||||
if (!new_ptr) {
|
if (!new_ptr) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_byte_size > old_byte_size) {
|
if (new_byte_size > old_byte_size) {
|
||||||
memset((void *)((uintptr_t)new_ptr + old_byte_size), 0,
|
memset((char *)new_ptr + old_byte_size, 0,
|
||||||
new_byte_size - old_byte_size);
|
new_byte_size - old_byte_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -412,7 +412,7 @@ static inline int64_t offset_into_cluster(BDRVQcowState *s, int64_t offset)
|
|||||||
return offset & (s->cluster_size - 1);
|
return offset & (s->cluster_size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
|
static inline uint64_t size_to_clusters(BDRVQcowState *s, uint64_t size)
|
||||||
{
|
{
|
||||||
return (size + (s->cluster_size - 1)) >> s->cluster_bits;
|
return (size + (s->cluster_size - 1)) >> s->cluster_bits;
|
||||||
}
|
}
|
||||||
@@ -506,8 +506,8 @@ int qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
|
|||||||
enum qcow2_discard_type type);
|
enum qcow2_discard_type type);
|
||||||
|
|
||||||
int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
|
int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
|
||||||
int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
|
int64_t qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
|
||||||
int nb_clusters);
|
int64_t nb_clusters);
|
||||||
int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size);
|
int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size);
|
||||||
void qcow2_free_clusters(BlockDriverState *bs,
|
void qcow2_free_clusters(BlockDriverState *bs,
|
||||||
int64_t offset, int64_t size,
|
int64_t offset, int64_t size,
|
||||||
|
|||||||
+4
-6
@@ -865,12 +865,6 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA256)) {
|
|
||||||
error_setg(errp,
|
|
||||||
"SHA256 hash support is required for quorum device");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
qdict_flatten(options);
|
qdict_flatten(options);
|
||||||
|
|
||||||
/* count how many different children are present */
|
/* count how many different children are present */
|
||||||
@@ -1061,6 +1055,10 @@ static BlockDriver bdrv_quorum = {
|
|||||||
|
|
||||||
static void bdrv_quorum_init(void)
|
static void bdrv_quorum_init(void)
|
||||||
{
|
{
|
||||||
|
if (!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA256)) {
|
||||||
|
/* SHA256 hash support is required for quorum device */
|
||||||
|
return;
|
||||||
|
}
|
||||||
bdrv_register(&bdrv_quorum);
|
bdrv_register(&bdrv_quorum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+71
-81
@@ -318,6 +318,10 @@ enum AIOCBState {
|
|||||||
AIOCB_DISCARD_OBJ,
|
AIOCB_DISCARD_OBJ,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define AIOCBOverwrapping(x, y) \
|
||||||
|
(!(x->max_affect_data_idx < y->min_affect_data_idx \
|
||||||
|
|| y->max_affect_data_idx < x->min_affect_data_idx))
|
||||||
|
|
||||||
struct SheepdogAIOCB {
|
struct SheepdogAIOCB {
|
||||||
BlockAIOCB common;
|
BlockAIOCB common;
|
||||||
|
|
||||||
@@ -334,6 +338,11 @@ struct SheepdogAIOCB {
|
|||||||
|
|
||||||
bool cancelable;
|
bool cancelable;
|
||||||
int nr_pending;
|
int nr_pending;
|
||||||
|
|
||||||
|
uint32_t min_affect_data_idx;
|
||||||
|
uint32_t max_affect_data_idx;
|
||||||
|
|
||||||
|
QLIST_ENTRY(SheepdogAIOCB) aiocb_siblings;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct BDRVSheepdogState {
|
typedef struct BDRVSheepdogState {
|
||||||
@@ -362,8 +371,10 @@ typedef struct BDRVSheepdogState {
|
|||||||
|
|
||||||
/* Every aio request must be linked to either of these queues. */
|
/* Every aio request must be linked to either of these queues. */
|
||||||
QLIST_HEAD(inflight_aio_head, AIOReq) inflight_aio_head;
|
QLIST_HEAD(inflight_aio_head, AIOReq) inflight_aio_head;
|
||||||
QLIST_HEAD(pending_aio_head, AIOReq) pending_aio_head;
|
|
||||||
QLIST_HEAD(failed_aio_head, AIOReq) failed_aio_head;
|
QLIST_HEAD(failed_aio_head, AIOReq) failed_aio_head;
|
||||||
|
|
||||||
|
CoQueue overwrapping_queue;
|
||||||
|
QLIST_HEAD(inflight_aiocb_head, SheepdogAIOCB) inflight_aiocb_head;
|
||||||
} BDRVSheepdogState;
|
} BDRVSheepdogState;
|
||||||
|
|
||||||
static const char * sd_strerror(int err)
|
static const char * sd_strerror(int err)
|
||||||
@@ -498,13 +509,7 @@ static void sd_aio_cancel(BlockAIOCB *blockacb)
|
|||||||
AIOReq *aioreq, *next;
|
AIOReq *aioreq, *next;
|
||||||
|
|
||||||
if (sd_acb_cancelable(acb)) {
|
if (sd_acb_cancelable(acb)) {
|
||||||
/* Remove outstanding requests from pending and failed queues. */
|
/* Remove outstanding requests from failed queue. */
|
||||||
QLIST_FOREACH_SAFE(aioreq, &s->pending_aio_head, aio_siblings,
|
|
||||||
next) {
|
|
||||||
if (aioreq->aiocb == acb) {
|
|
||||||
free_aio_req(s, aioreq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QLIST_FOREACH_SAFE(aioreq, &s->failed_aio_head, aio_siblings,
|
QLIST_FOREACH_SAFE(aioreq, &s->failed_aio_head, aio_siblings,
|
||||||
next) {
|
next) {
|
||||||
if (aioreq->aiocb == acb) {
|
if (aioreq->aiocb == acb) {
|
||||||
@@ -529,6 +534,10 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
|
|||||||
int64_t sector_num, int nb_sectors)
|
int64_t sector_num, int nb_sectors)
|
||||||
{
|
{
|
||||||
SheepdogAIOCB *acb;
|
SheepdogAIOCB *acb;
|
||||||
|
uint32_t object_size;
|
||||||
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
|
|
||||||
|
object_size = (UINT32_C(1) << s->inode.block_size_shift);
|
||||||
|
|
||||||
acb = qemu_aio_get(&sd_aiocb_info, bs, NULL, NULL);
|
acb = qemu_aio_get(&sd_aiocb_info, bs, NULL, NULL);
|
||||||
|
|
||||||
@@ -542,6 +551,11 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
|
|||||||
acb->coroutine = qemu_coroutine_self();
|
acb->coroutine = qemu_coroutine_self();
|
||||||
acb->ret = 0;
|
acb->ret = 0;
|
||||||
acb->nr_pending = 0;
|
acb->nr_pending = 0;
|
||||||
|
|
||||||
|
acb->min_affect_data_idx = acb->sector_num * BDRV_SECTOR_SIZE / object_size;
|
||||||
|
acb->max_affect_data_idx = (acb->sector_num * BDRV_SECTOR_SIZE +
|
||||||
|
acb->nb_sectors * BDRV_SECTOR_SIZE) / object_size;
|
||||||
|
|
||||||
return acb;
|
return acb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,38 +717,6 @@ static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag);
|
|||||||
static int get_sheep_fd(BDRVSheepdogState *s, Error **errp);
|
static int get_sheep_fd(BDRVSheepdogState *s, Error **errp);
|
||||||
static void co_write_request(void *opaque);
|
static void co_write_request(void *opaque);
|
||||||
|
|
||||||
static AIOReq *find_pending_req(BDRVSheepdogState *s, uint64_t oid)
|
|
||||||
{
|
|
||||||
AIOReq *aio_req;
|
|
||||||
|
|
||||||
QLIST_FOREACH(aio_req, &s->pending_aio_head, aio_siblings) {
|
|
||||||
if (aio_req->oid == oid) {
|
|
||||||
return aio_req;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function searchs pending requests to the object `oid', and
|
|
||||||
* sends them.
|
|
||||||
*/
|
|
||||||
static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid)
|
|
||||||
{
|
|
||||||
AIOReq *aio_req;
|
|
||||||
SheepdogAIOCB *acb;
|
|
||||||
|
|
||||||
while ((aio_req = find_pending_req(s, oid)) != NULL) {
|
|
||||||
acb = aio_req->aiocb;
|
|
||||||
/* move aio_req from pending list to inflight one */
|
|
||||||
QLIST_REMOVE(aio_req, aio_siblings);
|
|
||||||
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
|
|
||||||
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
|
|
||||||
acb->aiocb_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static coroutine_fn void reconnect_to_sdog(void *opaque)
|
static coroutine_fn void reconnect_to_sdog(void *opaque)
|
||||||
{
|
{
|
||||||
BDRVSheepdogState *s = opaque;
|
BDRVSheepdogState *s = opaque;
|
||||||
@@ -840,12 +822,6 @@ static void coroutine_fn aio_read_response(void *opaque)
|
|||||||
s->max_dirty_data_idx = MAX(idx, s->max_dirty_data_idx);
|
s->max_dirty_data_idx = MAX(idx, s->max_dirty_data_idx);
|
||||||
s->min_dirty_data_idx = MIN(idx, s->min_dirty_data_idx);
|
s->min_dirty_data_idx = MIN(idx, s->min_dirty_data_idx);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Some requests may be blocked because simultaneous
|
|
||||||
* create requests are not allowed, so we search the
|
|
||||||
* pending requests here.
|
|
||||||
*/
|
|
||||||
send_pending_req(s, aio_req->oid);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AIOCB_READ_UDATA:
|
case AIOCB_READ_UDATA:
|
||||||
@@ -1341,30 +1317,6 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if the specified request is linked to the pending list. */
|
|
||||||
static bool check_simultaneous_create(BDRVSheepdogState *s, AIOReq *aio_req)
|
|
||||||
{
|
|
||||||
AIOReq *areq;
|
|
||||||
QLIST_FOREACH(areq, &s->inflight_aio_head, aio_siblings) {
|
|
||||||
if (areq != aio_req && areq->oid == aio_req->oid) {
|
|
||||||
/*
|
|
||||||
* Sheepdog cannot handle simultaneous create requests to the same
|
|
||||||
* object, so we cannot send the request until the previous request
|
|
||||||
* finishes.
|
|
||||||
*/
|
|
||||||
DPRINTF("simultaneous create to %" PRIx64 "\n", aio_req->oid);
|
|
||||||
aio_req->flags = 0;
|
|
||||||
aio_req->base_oid = 0;
|
|
||||||
aio_req->create = false;
|
|
||||||
QLIST_REMOVE(aio_req, aio_siblings);
|
|
||||||
QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req, aio_siblings);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
|
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
|
||||||
{
|
{
|
||||||
SheepdogAIOCB *acb = aio_req->aiocb;
|
SheepdogAIOCB *acb = aio_req->aiocb;
|
||||||
@@ -1379,10 +1331,6 @@ static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_simultaneous_create(s, aio_req)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->inode.data_vdi_id[idx]) {
|
if (s->inode.data_vdi_id[idx]) {
|
||||||
aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);
|
aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);
|
||||||
aio_req->flags |= SD_FLAG_CMD_COW;
|
aio_req->flags |= SD_FLAG_CMD_COW;
|
||||||
@@ -1458,8 +1406,8 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
filename = qemu_opt_get(opts, "filename");
|
filename = qemu_opt_get(opts, "filename");
|
||||||
|
|
||||||
QLIST_INIT(&s->inflight_aio_head);
|
QLIST_INIT(&s->inflight_aio_head);
|
||||||
QLIST_INIT(&s->pending_aio_head);
|
|
||||||
QLIST_INIT(&s->failed_aio_head);
|
QLIST_INIT(&s->failed_aio_head);
|
||||||
|
QLIST_INIT(&s->inflight_aiocb_head);
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
|
|
||||||
memset(vdi, 0, sizeof(vdi));
|
memset(vdi, 0, sizeof(vdi));
|
||||||
@@ -1524,6 +1472,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
bs->total_sectors = s->inode.vdi_size / BDRV_SECTOR_SIZE;
|
bs->total_sectors = s->inode.vdi_size / BDRV_SECTOR_SIZE;
|
||||||
pstrcpy(s->name, sizeof(s->name), vdi);
|
pstrcpy(s->name, sizeof(s->name), vdi);
|
||||||
qemu_co_mutex_init(&s->lock);
|
qemu_co_mutex_init(&s->lock);
|
||||||
|
qemu_co_queue_init(&s->overwrapping_queue);
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2195,12 +2144,6 @@ static int coroutine_fn sd_co_rw_vector(void *p)
|
|||||||
old_oid, done);
|
old_oid, done);
|
||||||
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
|
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
|
||||||
|
|
||||||
if (create) {
|
|
||||||
if (check_simultaneous_create(s, aio_req)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
|
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
|
||||||
acb->aiocb_type);
|
acb->aiocb_type);
|
||||||
done:
|
done:
|
||||||
@@ -2215,6 +2158,20 @@ out:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool check_overwrapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *aiocb)
|
||||||
|
{
|
||||||
|
SheepdogAIOCB *cb;
|
||||||
|
|
||||||
|
QLIST_FOREACH(cb, &s->inflight_aiocb_head, aiocb_siblings) {
|
||||||
|
if (AIOCBOverwrapping(aiocb, cb)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QLIST_INSERT_HEAD(&s->inflight_aiocb_head, aiocb, aiocb_siblings);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
|
static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||||
int nb_sectors, QEMUIOVector *qiov)
|
int nb_sectors, QEMUIOVector *qiov)
|
||||||
{
|
{
|
||||||
@@ -2234,14 +2191,25 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
|
|||||||
acb->aio_done_func = sd_write_done;
|
acb->aio_done_func = sd_write_done;
|
||||||
acb->aiocb_type = AIOCB_WRITE_UDATA;
|
acb->aiocb_type = AIOCB_WRITE_UDATA;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (check_overwrapping_aiocb(s, acb)) {
|
||||||
|
qemu_co_queue_wait(&s->overwrapping_queue);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
ret = sd_co_rw_vector(acb);
|
ret = sd_co_rw_vector(acb);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
|
QLIST_REMOVE(acb, aiocb_siblings);
|
||||||
|
qemu_co_queue_restart_all(&s->overwrapping_queue);
|
||||||
qemu_aio_unref(acb);
|
qemu_aio_unref(acb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
|
|
||||||
|
QLIST_REMOVE(acb, aiocb_siblings);
|
||||||
|
qemu_co_queue_restart_all(&s->overwrapping_queue);
|
||||||
|
|
||||||
return acb->ret;
|
return acb->ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2250,19 +2218,30 @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
|
|||||||
{
|
{
|
||||||
SheepdogAIOCB *acb;
|
SheepdogAIOCB *acb;
|
||||||
int ret;
|
int ret;
|
||||||
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
|
|
||||||
acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
|
acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
|
||||||
acb->aiocb_type = AIOCB_READ_UDATA;
|
acb->aiocb_type = AIOCB_READ_UDATA;
|
||||||
acb->aio_done_func = sd_finish_aiocb;
|
acb->aio_done_func = sd_finish_aiocb;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (check_overwrapping_aiocb(s, acb)) {
|
||||||
|
qemu_co_queue_wait(&s->overwrapping_queue);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
ret = sd_co_rw_vector(acb);
|
ret = sd_co_rw_vector(acb);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
|
QLIST_REMOVE(acb, aiocb_siblings);
|
||||||
|
qemu_co_queue_restart_all(&s->overwrapping_queue);
|
||||||
qemu_aio_unref(acb);
|
qemu_aio_unref(acb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
|
|
||||||
|
QLIST_REMOVE(acb, aiocb_siblings);
|
||||||
|
qemu_co_queue_restart_all(&s->overwrapping_queue);
|
||||||
return acb->ret;
|
return acb->ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2610,14 +2589,25 @@ static coroutine_fn int sd_co_discard(BlockDriverState *bs, int64_t sector_num,
|
|||||||
acb->aiocb_type = AIOCB_DISCARD_OBJ;
|
acb->aiocb_type = AIOCB_DISCARD_OBJ;
|
||||||
acb->aio_done_func = sd_finish_aiocb;
|
acb->aio_done_func = sd_finish_aiocb;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (check_overwrapping_aiocb(s, acb)) {
|
||||||
|
qemu_co_queue_wait(&s->overwrapping_queue);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
ret = sd_co_rw_vector(acb);
|
ret = sd_co_rw_vector(acb);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
|
QLIST_REMOVE(acb, aiocb_siblings);
|
||||||
|
qemu_co_queue_restart_all(&s->overwrapping_queue);
|
||||||
qemu_aio_unref(acb);
|
qemu_aio_unref(acb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
|
|
||||||
|
QLIST_REMOVE(acb, aiocb_siblings);
|
||||||
|
qemu_co_queue_restart_all(&s->overwrapping_queue);
|
||||||
|
|
||||||
return acb->ret;
|
return acb->ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -563,7 +563,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
|||||||
/* Open the socket and connect. */
|
/* Open the socket and connect. */
|
||||||
s->sock = inet_connect(s->hostport, errp);
|
s->sock = inet_connect(s->hostport, errp);
|
||||||
if (s->sock < 0) {
|
if (s->sock < 0) {
|
||||||
ret = -errno;
|
ret = -EIO;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-4
@@ -168,6 +168,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
uint8_t buf[HEADER_SIZE];
|
uint8_t buf[HEADER_SIZE];
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
uint64_t computed_size;
|
uint64_t computed_size;
|
||||||
|
uint64_t pagetable_size;
|
||||||
int disk_type = VHD_DYNAMIC;
|
int disk_type = VHD_DYNAMIC;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -269,7 +270,17 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->pagetable = qemu_try_blockalign(bs->file, s->max_table_entries * 4);
|
if (s->max_table_entries > SIZE_MAX / 4 ||
|
||||||
|
s->max_table_entries > (int) INT_MAX / 4) {
|
||||||
|
error_setg(errp, "Max Table Entries too large (%" PRId32 ")",
|
||||||
|
s->max_table_entries);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
pagetable_size = (uint64_t) s->max_table_entries * 4;
|
||||||
|
|
||||||
|
s->pagetable = qemu_try_blockalign(bs->file, pagetable_size);
|
||||||
if (s->pagetable == NULL) {
|
if (s->pagetable == NULL) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -277,14 +288,13 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
|
|
||||||
s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
|
s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
|
||||||
|
|
||||||
ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
|
ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable, pagetable_size);
|
||||||
s->max_table_entries * 4);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->free_data_block_offset =
|
s->free_data_block_offset =
|
||||||
(s->bat_offset + (s->max_table_entries * 4) + 511) & ~511;
|
ROUND_UP(s->bat_offset + pagetable_size, 512);
|
||||||
|
|
||||||
for (i = 0; i < s->max_table_entries; i++) {
|
for (i = 0; i < s->max_table_entries; i++) {
|
||||||
be32_to_cpus(&s->pagetable[i]);
|
be32_to_cpus(&s->pagetable[i]);
|
||||||
|
|||||||
+1
-1
@@ -173,7 +173,7 @@ void cpu_loop(CPUX86State *env)
|
|||||||
//target_siginfo_t info;
|
//target_siginfo_t info;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
trapnr = cpu_x86_exec(env);
|
trapnr = cpu_x86_exec(cs);
|
||||||
switch(trapnr) {
|
switch(trapnr) {
|
||||||
case 0x80:
|
case 0x80:
|
||||||
/* syscall from int $0x80 */
|
/* syscall from int $0x80 */
|
||||||
|
|||||||
@@ -1337,7 +1337,6 @@ disabled with --disable-FEATURE, default is enabled if available:
|
|||||||
vnc-sasl SASL encryption for VNC server
|
vnc-sasl SASL encryption for VNC server
|
||||||
vnc-jpeg JPEG lossy compression for VNC server
|
vnc-jpeg JPEG lossy compression for VNC server
|
||||||
vnc-png PNG compression for VNC server
|
vnc-png PNG compression for VNC server
|
||||||
vnc-ws Websockets support for VNC server
|
|
||||||
cocoa Cocoa UI (Mac OS X only)
|
cocoa Cocoa UI (Mac OS X only)
|
||||||
virtfs VirtFS
|
virtfs VirtFS
|
||||||
xen xen backend driver support
|
xen xen backend driver support
|
||||||
@@ -2116,10 +2115,26 @@ fi
|
|||||||
##########################################
|
##########################################
|
||||||
# GNUTLS probe
|
# GNUTLS probe
|
||||||
|
|
||||||
|
gnutls_works() {
|
||||||
|
# Unfortunately some distros have bad pkg-config information for gnutls
|
||||||
|
# such that it claims to exist but you get a compiler error if you try
|
||||||
|
# to use the options returned by --libs. Specifically, Ubuntu for --static
|
||||||
|
# builds doesn't work:
|
||||||
|
# https://bugs.launchpad.net/ubuntu/+source/gnutls26/+bug/1478035
|
||||||
|
#
|
||||||
|
# So sanity check the cflags/libs before assuming gnutls can be used.
|
||||||
|
if ! $pkg_config --exists "gnutls"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_c_skeleton
|
||||||
|
compile_prog "$($pkg_config --cflags gnutls)" "$($pkg_config --libs gnutls)"
|
||||||
|
}
|
||||||
|
|
||||||
gnutls_gcrypt=no
|
gnutls_gcrypt=no
|
||||||
gnutls_nettle=no
|
gnutls_nettle=no
|
||||||
if test "$gnutls" != "no"; then
|
if test "$gnutls" != "no"; then
|
||||||
if $pkg_config --exists "gnutls"; then
|
if gnutls_works; then
|
||||||
gnutls_cflags=`$pkg_config --cflags gnutls`
|
gnutls_cflags=`$pkg_config --cflags gnutls`
|
||||||
gnutls_libs=`$pkg_config --libs gnutls`
|
gnutls_libs=`$pkg_config --libs gnutls`
|
||||||
libs_softmmu="$gnutls_libs $libs_softmmu"
|
libs_softmmu="$gnutls_libs $libs_softmmu"
|
||||||
|
|||||||
@@ -954,6 +954,8 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
|
|||||||
CPUState *cpu = arg;
|
CPUState *cpu = arg;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
rcu_register_thread();
|
||||||
|
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
qemu_thread_get_self(cpu->thread);
|
qemu_thread_get_self(cpu->thread);
|
||||||
cpu->thread_id = qemu_get_thread_id();
|
cpu->thread_id = qemu_get_thread_id();
|
||||||
@@ -995,6 +997,8 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
|
|||||||
sigset_t waitset;
|
sigset_t waitset;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
rcu_register_thread();
|
||||||
|
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
qemu_thread_get_self(cpu->thread);
|
qemu_thread_get_self(cpu->thread);
|
||||||
cpu->thread_id = qemu_get_thread_id();
|
cpu->thread_id = qemu_get_thread_id();
|
||||||
@@ -1034,6 +1038,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
|
|||||||
{
|
{
|
||||||
CPUState *cpu = arg;
|
CPUState *cpu = arg;
|
||||||
|
|
||||||
|
rcu_register_thread();
|
||||||
|
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
qemu_tcg_init_cpu_signals();
|
qemu_tcg_init_cpu_signals();
|
||||||
qemu_thread_get_self(cpu->thread);
|
qemu_thread_get_self(cpu->thread);
|
||||||
@@ -1160,7 +1166,7 @@ void qemu_mutex_lock_iothread(void)
|
|||||||
* TCG code execution.
|
* TCG code execution.
|
||||||
*/
|
*/
|
||||||
if (!tcg_enabled() || qemu_in_vcpu_thread() ||
|
if (!tcg_enabled() || qemu_in_vcpu_thread() ||
|
||||||
!first_cpu || !first_cpu->thread) {
|
!first_cpu || !first_cpu->created) {
|
||||||
qemu_mutex_lock(&qemu_global_mutex);
|
qemu_mutex_lock(&qemu_global_mutex);
|
||||||
atomic_dec(&iothread_requesting_mutex);
|
atomic_dec(&iothread_requesting_mutex);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher,
|
|||||||
uint8_t *outptr = out;
|
uint8_t *outptr = out;
|
||||||
while (len) {
|
while (len) {
|
||||||
if (len > AES_BLOCK_SIZE) {
|
if (len > AES_BLOCK_SIZE) {
|
||||||
AES_decrypt(inptr, outptr, &ctxt->state.aes.encrypt_key);
|
AES_decrypt(inptr, outptr, &ctxt->state.aes.decrypt_key);
|
||||||
inptr += AES_BLOCK_SIZE;
|
inptr += AES_BLOCK_SIZE;
|
||||||
outptr += AES_BLOCK_SIZE;
|
outptr += AES_BLOCK_SIZE;
|
||||||
len -= AES_BLOCK_SIZE;
|
len -= AES_BLOCK_SIZE;
|
||||||
@@ -126,15 +126,15 @@ static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher,
|
|||||||
memcpy(tmp1, inptr, len);
|
memcpy(tmp1, inptr, len);
|
||||||
/* Fill with 0 to avoid valgrind uninitialized reads */
|
/* Fill with 0 to avoid valgrind uninitialized reads */
|
||||||
memset(tmp1 + len, 0, sizeof(tmp1) - len);
|
memset(tmp1 + len, 0, sizeof(tmp1) - len);
|
||||||
AES_decrypt(tmp1, tmp2, &ctxt->state.aes.encrypt_key);
|
AES_decrypt(tmp1, tmp2, &ctxt->state.aes.decrypt_key);
|
||||||
memcpy(outptr, tmp2, len);
|
memcpy(outptr, tmp2, len);
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AES_cbc_encrypt(in, out, len,
|
AES_cbc_encrypt(in, out, len,
|
||||||
&ctxt->state.aes.encrypt_key,
|
&ctxt->state.aes.decrypt_key,
|
||||||
ctxt->state.aes.iv, 1);
|
ctxt->state.aes.iv, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+1
-1
@@ -241,7 +241,7 @@ uint32_t qemu_fdt_alloc_phandle(void *fdt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to find out if the user gave us special instruction at
|
* We need to find out if the user gave us special instruction at
|
||||||
* which phandle id to start allocting phandles.
|
* which phandle id to start allocating phandles.
|
||||||
*/
|
*/
|
||||||
if (!phandle) {
|
if (!phandle) {
|
||||||
phandle = machine_phandle_start(current_machine);
|
phandle = machine_phandle_start(current_machine);
|
||||||
|
|||||||
@@ -954,7 +954,10 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
|
|||||||
iotlb |= PHYS_SECTION_ROM;
|
iotlb |= PHYS_SECTION_ROM;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iotlb = section - section->address_space->dispatch->map.sections;
|
AddressSpaceDispatch *d;
|
||||||
|
|
||||||
|
d = atomic_rcu_read(§ion->address_space->dispatch);
|
||||||
|
iotlb = section - d->map.sections;
|
||||||
iotlb += xlat;
|
iotlb += xlat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1285,6 +1285,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
|
|||||||
ret = GDB_SIGNAL_UNKNOWN;
|
ret = GDB_SIGNAL_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
gdb_set_stop_cpu(cpu);
|
||||||
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu));
|
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu));
|
||||||
|
|
||||||
send_packet:
|
send_packet:
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
#include "virtio-9p-coth.h"
|
#include "virtio-9p-coth.h"
|
||||||
#include "hw/virtio/virtio-access.h"
|
#include "hw/virtio/virtio-access.h"
|
||||||
|
|
||||||
static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features)
|
static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
|
virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
|
||||||
return features;
|
return features;
|
||||||
|
|||||||
+17
-6
@@ -14,6 +14,7 @@
|
|||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "qemu/iov.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
#include "virtio-9p.h"
|
#include "virtio-9p.h"
|
||||||
#include "fsdev/qemu-fsdev.h"
|
#include "fsdev/qemu-fsdev.h"
|
||||||
@@ -3261,16 +3262,26 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
|
|
||||||
while ((pdu = alloc_pdu(s)) &&
|
while ((pdu = alloc_pdu(s)) &&
|
||||||
(len = virtqueue_pop(vq, &pdu->elem)) != 0) {
|
(len = virtqueue_pop(vq, &pdu->elem)) != 0) {
|
||||||
uint8_t *ptr;
|
struct {
|
||||||
|
uint32_t size_le;
|
||||||
|
uint8_t id;
|
||||||
|
uint16_t tag_le;
|
||||||
|
} QEMU_PACKED out;
|
||||||
|
int len;
|
||||||
|
|
||||||
pdu->s = s;
|
pdu->s = s;
|
||||||
BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0);
|
BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0);
|
||||||
BUG_ON(pdu->elem.out_sg[0].iov_len < 7);
|
QEMU_BUILD_BUG_ON(sizeof out != 7);
|
||||||
|
|
||||||
ptr = pdu->elem.out_sg[0].iov_base;
|
len = iov_to_buf(pdu->elem.out_sg, pdu->elem.out_num, 0,
|
||||||
|
&out, sizeof out);
|
||||||
|
BUG_ON(len != sizeof out);
|
||||||
|
|
||||||
|
pdu->size = le32_to_cpu(out.size_le);
|
||||||
|
|
||||||
|
pdu->id = out.id;
|
||||||
|
pdu->tag = le16_to_cpu(out.tag_le);
|
||||||
|
|
||||||
pdu->size = le32_to_cpu(*(uint32_t *)ptr);
|
|
||||||
pdu->id = ptr[4];
|
|
||||||
pdu->tag = le16_to_cpu(*(uint16_t *)(ptr + 5));
|
|
||||||
qemu_co_queue_init(&pdu->complete);
|
qemu_co_queue_init(&pdu->complete);
|
||||||
submit_pdu(s, pdu);
|
submit_pdu(s, pdu);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -221,9 +221,9 @@ static void pm_reset(void *opaque)
|
|||||||
acpi_pm_tmr_reset(&pm->acpi_regs);
|
acpi_pm_tmr_reset(&pm->acpi_regs);
|
||||||
acpi_gpe_reset(&pm->acpi_regs);
|
acpi_gpe_reset(&pm->acpi_regs);
|
||||||
|
|
||||||
|
pm->smi_en = 0;
|
||||||
if (!pm->smm_enabled) {
|
if (!pm->smm_enabled) {
|
||||||
/* Mark SMM as already inited to prevent SMM from running. KVM does not
|
/* Mark SMM as already inited to prevent SMM from running. */
|
||||||
* support SMM mode. */
|
|
||||||
pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
|
pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
|
||||||
}
|
}
|
||||||
pm->smi_en_wmask = ~0;
|
pm->smi_en_wmask = ~0;
|
||||||
|
|||||||
@@ -103,6 +103,12 @@ static void aw_a10_class_init(ObjectClass *oc, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||||
|
|
||||||
dc->realize = aw_a10_realize;
|
dc->realize = aw_a10_realize;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reason: creates an ARM CPU, thus use after free(), see
|
||||||
|
* arm_cpu_class_init()
|
||||||
|
*/
|
||||||
|
dc->cannot_destroy_with_object_finalize_yet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo aw_a10_type_info = {
|
static const TypeInfo aw_a10_type_info = {
|
||||||
|
|||||||
@@ -97,6 +97,12 @@ static void digic_class_init(ObjectClass *oc, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||||
|
|
||||||
dc->realize = digic_realize;
|
dc->realize = digic_realize;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reason: creates an ARM CPU, thus use after free(), see
|
||||||
|
* arm_cpu_class_init()
|
||||||
|
*/
|
||||||
|
dc->cannot_destroy_with_object_finalize_yet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo digic_type_info = {
|
static const TypeInfo digic_type_info = {
|
||||||
|
|||||||
+1
-1
@@ -1959,7 +1959,7 @@ static void pxa2xx_fir_instance_init(Object *obj)
|
|||||||
PXA2xxFIrState *s = PXA2XX_FIR(obj);
|
PXA2xxFIrState *s = PXA2XX_FIR(obj);
|
||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
|
|
||||||
memory_region_init_io(&s->iomem, NULL, &pxa2xx_fir_ops, s,
|
memory_region_init_io(&s->iomem, obj, &pxa2xx_fir_ops, s,
|
||||||
"pxa2xx-fir", 0x1000);
|
"pxa2xx-fir", 0x1000);
|
||||||
sysbus_init_mmio(sbd, &s->iomem);
|
sysbus_init_mmio(sbd, &s->iomem);
|
||||||
sysbus_init_irq(sbd, &s->irq);
|
sysbus_init_irq(sbd, &s->irq);
|
||||||
|
|||||||
@@ -248,6 +248,12 @@ static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
|
|||||||
|
|
||||||
dc->props = xlnx_zynqmp_props;
|
dc->props = xlnx_zynqmp_props;
|
||||||
dc->realize = xlnx_zynqmp_realize;
|
dc->realize = xlnx_zynqmp_realize;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reason: creates an ARM CPU, thus use after free(), see
|
||||||
|
* arm_cpu_class_init()
|
||||||
|
*/
|
||||||
|
dc->cannot_destroy_with_object_finalize_yet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo xlnx_zynqmp_type_info = {
|
static const TypeInfo xlnx_zynqmp_type_info = {
|
||||||
|
|||||||
@@ -223,8 +223,8 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
|||||||
virtio_blk_data_plane_stop(s);
|
virtio_blk_data_plane_stop(s);
|
||||||
blk_op_unblock_all(s->conf->conf.blk, s->blocker);
|
blk_op_unblock_all(s->conf->conf.blk, s->blocker);
|
||||||
error_free(s->blocker);
|
error_free(s->blocker);
|
||||||
object_unref(OBJECT(s->iothread));
|
|
||||||
qemu_bh_delete(s->bh);
|
qemu_bh_delete(s->bh);
|
||||||
|
object_unref(OBJECT(s->iothread));
|
||||||
g_free(s);
|
g_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-3
@@ -722,7 +722,8 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
|
|||||||
aio_context_release(blk_get_aio_context(s->blk));
|
aio_context_release(blk_get_aio_context(s->blk));
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
|
static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOBlock *s = VIRTIO_BLK(vdev);
|
VirtIOBlock *s = VIRTIO_BLK(vdev);
|
||||||
|
|
||||||
@@ -730,7 +731,15 @@ static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
|
|||||||
virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
|
virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
|
||||||
virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
|
virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
|
||||||
virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
|
virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
|
||||||
|
if (virtio_has_feature(features, VIRTIO_F_VERSION_1)) {
|
||||||
|
if (s->conf.scsi) {
|
||||||
|
error_setg(errp, "Please set scsi=off for virtio-blk devices in order to use virtio 1.0");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
virtio_clear_feature(&features, VIRTIO_F_ANY_LAYOUT);
|
||||||
virtio_add_feature(&features, VIRTIO_BLK_F_SCSI);
|
virtio_add_feature(&features, VIRTIO_BLK_F_SCSI);
|
||||||
|
}
|
||||||
|
|
||||||
if (s->conf.config_wce) {
|
if (s->conf.config_wce) {
|
||||||
virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
|
virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
|
||||||
@@ -773,10 +782,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
|
|||||||
*
|
*
|
||||||
* s->blk would erroneously be placed in writethrough mode.
|
* s->blk would erroneously be placed in writethrough mode.
|
||||||
*/
|
*/
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) {
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) {
|
||||||
aio_context_acquire(blk_get_aio_context(s->blk));
|
aio_context_acquire(blk_get_aio_context(s->blk));
|
||||||
blk_set_enable_write_cache(s->blk,
|
blk_set_enable_write_cache(s->blk,
|
||||||
virtio_has_feature(vdev, VIRTIO_BLK_F_WCE));
|
virtio_vdev_has_feature(vdev,
|
||||||
|
VIRTIO_BLK_F_WCE));
|
||||||
aio_context_release(blk_get_aio_context(s->blk));
|
aio_context_release(blk_get_aio_context(s->blk));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -784,6 +794,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
|
|||||||
static void virtio_blk_save(QEMUFile *f, void *opaque)
|
static void virtio_blk_save(QEMUFile *f, void *opaque)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
||||||
|
VirtIOBlock *s = VIRTIO_BLK(vdev);
|
||||||
|
|
||||||
|
if (s->dataplane) {
|
||||||
|
virtio_blk_data_plane_stop(s->dataplane);
|
||||||
|
}
|
||||||
|
|
||||||
virtio_save(vdev, f);
|
virtio_save(vdev, f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ static VirtIOSerialPort *find_port_by_name(char *name)
|
|||||||
static bool use_multiport(VirtIOSerial *vser)
|
static bool use_multiport(VirtIOSerial *vser)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(vser);
|
VirtIODevice *vdev = VIRTIO_DEVICE(vser);
|
||||||
return virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
|
return virtio_vdev_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t write_to_port(VirtIOSerialPort *port,
|
static size_t write_to_port(VirtIOSerialPort *port,
|
||||||
@@ -195,7 +195,8 @@ static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(elem.in_sg[0].iov_base, buf, len);
|
/* TODO: detect a buffer that's too short, set NEEDS_RESET */
|
||||||
|
iov_from_buf(elem.in_sg, elem.in_num, 0, buf, len);
|
||||||
|
|
||||||
virtqueue_push(vq, &elem, len);
|
virtqueue_push(vq, &elem, len);
|
||||||
virtio_notify(VIRTIO_DEVICE(vser), vq);
|
virtio_notify(VIRTIO_DEVICE(vser), vq);
|
||||||
@@ -499,7 +500,8 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t get_features(VirtIODevice *vdev, uint64_t features)
|
static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOSerial *vser;
|
VirtIOSerial *vser;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -280,12 +280,12 @@ static void cg3_initfn(Object *obj)
|
|||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
CG3State *s = CG3(obj);
|
CG3State *s = CG3(obj);
|
||||||
|
|
||||||
memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE,
|
memory_region_init_ram(&s->rom, obj, "cg3.prom", FCODE_MAX_ROM_SIZE,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
memory_region_set_readonly(&s->rom, true);
|
memory_region_set_readonly(&s->rom, true);
|
||||||
sysbus_init_mmio(sbd, &s->rom);
|
sysbus_init_mmio(sbd, &s->rom);
|
||||||
|
|
||||||
memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
|
memory_region_init_io(&s->reg, obj, &cg3_reg_ops, s, "cg3.reg",
|
||||||
CG3_REG_SIZE);
|
CG3_REG_SIZE);
|
||||||
sysbus_init_mmio(sbd, &s->reg);
|
sysbus_init_mmio(sbd, &s->reg);
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-34
@@ -21,12 +21,40 @@
|
|||||||
#include "ui/console.h"
|
#include "ui/console.h"
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
|
|
||||||
/* Render an image from a shared memory framebuffer. */
|
void framebuffer_update_memory_section(
|
||||||
|
MemoryRegionSection *mem_section,
|
||||||
|
MemoryRegion *root,
|
||||||
|
hwaddr base,
|
||||||
|
unsigned rows,
|
||||||
|
unsigned src_width)
|
||||||
|
{
|
||||||
|
hwaddr src_len = (hwaddr)rows * src_width;
|
||||||
|
|
||||||
|
if (mem_section->mr) {
|
||||||
|
memory_region_set_log(mem_section->mr, false, DIRTY_MEMORY_VGA);
|
||||||
|
memory_region_unref(mem_section->mr);
|
||||||
|
mem_section->mr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*mem_section = memory_region_find(root, base, src_len);
|
||||||
|
if (!mem_section->mr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int128_get64(mem_section->size) < src_len ||
|
||||||
|
!memory_region_is_ram(mem_section->mr)) {
|
||||||
|
memory_region_unref(mem_section->mr);
|
||||||
|
mem_section->mr = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_region_set_log(mem_section->mr, true, DIRTY_MEMORY_VGA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Render an image from a shared memory framebuffer. */
|
||||||
void framebuffer_update_display(
|
void framebuffer_update_display(
|
||||||
DisplaySurface *ds,
|
DisplaySurface *ds,
|
||||||
MemoryRegion *address_space,
|
MemoryRegionSection *mem_section,
|
||||||
hwaddr base,
|
|
||||||
int cols, /* Width in pixels. */
|
int cols, /* Width in pixels. */
|
||||||
int rows, /* Height in pixels. */
|
int rows, /* Height in pixels. */
|
||||||
int src_width, /* Length of source line, in bytes. */
|
int src_width, /* Length of source line, in bytes. */
|
||||||
@@ -41,51 +69,33 @@ void framebuffer_update_display(
|
|||||||
hwaddr src_len;
|
hwaddr src_len;
|
||||||
uint8_t *dest;
|
uint8_t *dest;
|
||||||
uint8_t *src;
|
uint8_t *src;
|
||||||
uint8_t *src_base;
|
|
||||||
int first, last = 0;
|
int first, last = 0;
|
||||||
int dirty;
|
int dirty;
|
||||||
int i;
|
int i;
|
||||||
ram_addr_t addr;
|
ram_addr_t addr;
|
||||||
MemoryRegionSection mem_section;
|
|
||||||
MemoryRegion *mem;
|
MemoryRegion *mem;
|
||||||
|
|
||||||
i = *first_row;
|
i = *first_row;
|
||||||
*first_row = -1;
|
*first_row = -1;
|
||||||
src_len = src_width * rows;
|
src_len = src_width * rows;
|
||||||
|
|
||||||
mem_section = memory_region_find(address_space, base, src_len);
|
mem = mem_section->mr;
|
||||||
mem = mem_section.mr;
|
if (!mem) {
|
||||||
if (int128_get64(mem_section.size) != src_len ||
|
return;
|
||||||
!memory_region_is_ram(mem_section.mr)) {
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
assert(mem);
|
|
||||||
assert(mem_section.offset_within_address_space == base);
|
|
||||||
|
|
||||||
memory_region_sync_dirty_bitmap(mem);
|
memory_region_sync_dirty_bitmap(mem);
|
||||||
if (!memory_region_is_logging(mem, DIRTY_MEMORY_VGA)) {
|
|
||||||
invalidate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
src_base = cpu_physical_memory_map(base, &src_len, 0);
|
addr = mem_section->offset_within_region;
|
||||||
/* If we can't map the framebuffer then bail. We could try harder,
|
src = memory_region_get_ram_ptr(mem) + addr;
|
||||||
but it's not really worth it as dirty flag tracking will probably
|
|
||||||
already have failed above. */
|
|
||||||
if (!src_base)
|
|
||||||
goto out;
|
|
||||||
if (src_len != src_width * rows) {
|
|
||||||
cpu_physical_memory_unmap(src_base, src_len, 0, 0);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
src = src_base;
|
|
||||||
dest = surface_data(ds);
|
dest = surface_data(ds);
|
||||||
if (dest_col_pitch < 0)
|
if (dest_col_pitch < 0) {
|
||||||
dest -= dest_col_pitch * (cols - 1);
|
dest -= dest_col_pitch * (cols - 1);
|
||||||
|
}
|
||||||
if (dest_row_pitch < 0) {
|
if (dest_row_pitch < 0) {
|
||||||
dest -= dest_row_pitch * (rows - 1);
|
dest -= dest_row_pitch * (rows - 1);
|
||||||
}
|
}
|
||||||
first = -1;
|
first = -1;
|
||||||
addr = mem_section.offset_within_region;
|
|
||||||
|
|
||||||
addr += i * src_width;
|
addr += i * src_width;
|
||||||
src += i * src_width;
|
src += i * src_width;
|
||||||
@@ -104,14 +114,11 @@ void framebuffer_update_display(
|
|||||||
src += src_width;
|
src += src_width;
|
||||||
dest += dest_row_pitch;
|
dest += dest_row_pitch;
|
||||||
}
|
}
|
||||||
cpu_physical_memory_unmap(src_base, src_len, 0, 0);
|
|
||||||
if (first < 0) {
|
if (first < 0) {
|
||||||
goto out;
|
return;
|
||||||
}
|
}
|
||||||
memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len,
|
memory_region_reset_dirty(mem, mem_section->offset_within_region, src_len,
|
||||||
DIRTY_MEMORY_VGA);
|
DIRTY_MEMORY_VGA);
|
||||||
*first_row = first;
|
*first_row = first;
|
||||||
*last_row = last;
|
*last_row = last;
|
||||||
out:
|
|
||||||
memory_region_unref(mem);
|
|
||||||
}
|
}
|
||||||
@@ -7,10 +7,50 @@
|
|||||||
|
|
||||||
typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int);
|
typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int);
|
||||||
|
|
||||||
|
/* framebuffer_update_memory_section: Update framebuffer
|
||||||
|
* #MemoryRegionSection, for example if the framebuffer is switched to
|
||||||
|
* a different memory area.
|
||||||
|
*
|
||||||
|
* @mem_section: Output #MemoryRegionSection, to be passed to
|
||||||
|
* framebuffer_update_display().
|
||||||
|
* @root: #MemoryRegion within which the framebuffer lies
|
||||||
|
* @base: Base address of the framebuffer within @root.
|
||||||
|
* @rows: Height of the screen.
|
||||||
|
* @src_width: Number of bytes in framebuffer memory between two rows.
|
||||||
|
*/
|
||||||
|
void framebuffer_update_memory_section(
|
||||||
|
MemoryRegionSection *mem_section,
|
||||||
|
MemoryRegion *root,
|
||||||
|
hwaddr base,
|
||||||
|
unsigned rows,
|
||||||
|
unsigned src_width);
|
||||||
|
|
||||||
|
/* framebuffer_update_display: Draw the framebuffer on a surface.
|
||||||
|
*
|
||||||
|
* @ds: #DisplaySurface to draw to.
|
||||||
|
* @mem_section: #MemoryRegionSection provided by
|
||||||
|
* framebuffer_update_memory_section().
|
||||||
|
* @cols: Width the screen.
|
||||||
|
* @rows: Height of the screen.
|
||||||
|
* @src_width: Number of bytes in framebuffer memory between two rows.
|
||||||
|
* @dest_row_pitch: Number of bytes in the surface data between two rows.
|
||||||
|
* Negative if the framebuffer is stored in the opposite order (e.g.
|
||||||
|
* bottom-to-top) compared to the framebuffer.
|
||||||
|
* @dest_col_pitch: Number of bytes in the surface data between two pixels.
|
||||||
|
* Negative if the framebuffer is stored in the opposite order (e.g.
|
||||||
|
* right-to-left) compared to the framebuffer.
|
||||||
|
* @invalidate: True if the function should redraw the whole screen
|
||||||
|
* without checking the DIRTY_MEMORY_VGA dirty bitmap.
|
||||||
|
* @fn: Drawing function to be called for each row that has to be drawn.
|
||||||
|
* @opaque: Opaque pointer passed to @fn.
|
||||||
|
* @first_row: Pointer to an integer, receives the number of the first row
|
||||||
|
* that was drawn (either the first dirty row, or 0 if @invalidate is true).
|
||||||
|
* @last_row: Pointer to an integer, receives the number of the last row that
|
||||||
|
* was drawn (either the last dirty row, or @rows-1 if @invalidate is true).
|
||||||
|
*/
|
||||||
void framebuffer_update_display(
|
void framebuffer_update_display(
|
||||||
DisplaySurface *ds,
|
DisplaySurface *ds,
|
||||||
MemoryRegion *address_space,
|
MemoryRegionSection *mem_section,
|
||||||
hwaddr base,
|
|
||||||
int cols,
|
int cols,
|
||||||
int rows,
|
int rows,
|
||||||
int src_width,
|
int src_width,
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ struct MilkymistVgafbState {
|
|||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
|
|
||||||
MemoryRegion regs_region;
|
MemoryRegion regs_region;
|
||||||
|
MemoryRegionSection fbsection;
|
||||||
QemuConsole *con;
|
QemuConsole *con;
|
||||||
|
|
||||||
int invalidate;
|
int invalidate;
|
||||||
@@ -91,6 +92,7 @@ static void vgafb_update_display(void *opaque)
|
|||||||
MilkymistVgafbState *s = opaque;
|
MilkymistVgafbState *s = opaque;
|
||||||
SysBusDevice *sbd;
|
SysBusDevice *sbd;
|
||||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||||
|
int src_width;
|
||||||
int first = 0;
|
int first = 0;
|
||||||
int last = 0;
|
int last = 0;
|
||||||
drawfn fn;
|
drawfn fn;
|
||||||
@@ -129,11 +131,18 @@ static void vgafb_update_display(void *opaque)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
framebuffer_update_display(surface, sysbus_address_space(sbd),
|
src_width = s->regs[R_HRES] * 2;
|
||||||
|
if (s->invalidate) {
|
||||||
|
framebuffer_update_memory_section(&s->fbsection,
|
||||||
|
sysbus_address_space(sbd),
|
||||||
s->regs[R_BASEADDRESS] + s->fb_offset,
|
s->regs[R_BASEADDRESS] + s->fb_offset,
|
||||||
|
s->regs[R_VRES], src_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
framebuffer_update_display(surface, &s->fbsection,
|
||||||
s->regs[R_HRES],
|
s->regs[R_HRES],
|
||||||
s->regs[R_VRES],
|
s->regs[R_VRES],
|
||||||
s->regs[R_HRES] * 2,
|
src_width,
|
||||||
dest_width,
|
dest_width,
|
||||||
0,
|
0,
|
||||||
s->invalidate,
|
s->invalidate,
|
||||||
|
|||||||
+10
-2
@@ -25,6 +25,7 @@
|
|||||||
struct omap_lcd_panel_s {
|
struct omap_lcd_panel_s {
|
||||||
MemoryRegion *sysmem;
|
MemoryRegion *sysmem;
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
|
MemoryRegionSection fbsection;
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
QemuConsole *con;
|
QemuConsole *con;
|
||||||
|
|
||||||
@@ -215,12 +216,19 @@ static void omap_update_display(void *opaque)
|
|||||||
|
|
||||||
step = width * bpp >> 3;
|
step = width * bpp >> 3;
|
||||||
linesize = surface_stride(surface);
|
linesize = surface_stride(surface);
|
||||||
framebuffer_update_display(surface, omap_lcd->sysmem,
|
if (omap_lcd->invalidate) {
|
||||||
frame_base, width, height,
|
framebuffer_update_memory_section(&omap_lcd->fbsection,
|
||||||
|
omap_lcd->sysmem, frame_base,
|
||||||
|
height, step);
|
||||||
|
}
|
||||||
|
|
||||||
|
framebuffer_update_display(surface, &omap_lcd->fbsection,
|
||||||
|
width, height,
|
||||||
step, linesize, 0,
|
step, linesize, 0,
|
||||||
omap_lcd->invalidate,
|
omap_lcd->invalidate,
|
||||||
draw_line, omap_lcd->palette,
|
draw_line, omap_lcd->palette,
|
||||||
&first, &last);
|
&first, &last);
|
||||||
|
|
||||||
if (first >= 0) {
|
if (first >= 0) {
|
||||||
dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1);
|
dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-2
@@ -46,6 +46,7 @@ typedef struct PL110State {
|
|||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
|
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
|
MemoryRegionSection fbsection;
|
||||||
QemuConsole *con;
|
QemuConsole *con;
|
||||||
|
|
||||||
int version;
|
int version;
|
||||||
@@ -238,12 +239,20 @@ static void pl110_update_display(void *opaque)
|
|||||||
}
|
}
|
||||||
dest_width *= s->cols;
|
dest_width *= s->cols;
|
||||||
first = 0;
|
first = 0;
|
||||||
framebuffer_update_display(surface, sysbus_address_space(sbd),
|
if (s->invalidate) {
|
||||||
s->upbase, s->cols, s->rows,
|
framebuffer_update_memory_section(&s->fbsection,
|
||||||
|
sysbus_address_space(sbd),
|
||||||
|
s->upbase,
|
||||||
|
s->rows, src_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
framebuffer_update_display(surface, &s->fbsection,
|
||||||
|
s->cols, s->rows,
|
||||||
src_width, dest_width, 0,
|
src_width, dest_width, 0,
|
||||||
s->invalidate,
|
s->invalidate,
|
||||||
fn, s->palette,
|
fn, s->palette,
|
||||||
&first, &last);
|
&first, &last);
|
||||||
|
|
||||||
if (first >= 0) {
|
if (first >= 0) {
|
||||||
dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1);
|
dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-8
@@ -35,6 +35,7 @@ struct DMAChannel {
|
|||||||
struct PXA2xxLCDState {
|
struct PXA2xxLCDState {
|
||||||
MemoryRegion *sysmem;
|
MemoryRegion *sysmem;
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
|
MemoryRegionSection fbsection;
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
int irqlevel;
|
int irqlevel;
|
||||||
|
|
||||||
@@ -687,8 +688,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
|
|||||||
|
|
||||||
dest_width = s->xres * s->dest_width;
|
dest_width = s->xres * s->dest_width;
|
||||||
*miny = 0;
|
*miny = 0;
|
||||||
framebuffer_update_display(surface, s->sysmem,
|
if (s->invalidated) {
|
||||||
addr, s->xres, s->yres,
|
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
|
||||||
|
addr, s->yres, src_width);
|
||||||
|
}
|
||||||
|
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
|
||||||
src_width, dest_width, s->dest_width,
|
src_width, dest_width, s->dest_width,
|
||||||
s->invalidated,
|
s->invalidated,
|
||||||
fn, s->dma_ch[0].palette, miny, maxy);
|
fn, s->dma_ch[0].palette, miny, maxy);
|
||||||
@@ -715,8 +719,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
|
|||||||
|
|
||||||
dest_width = s->yres * s->dest_width;
|
dest_width = s->yres * s->dest_width;
|
||||||
*miny = 0;
|
*miny = 0;
|
||||||
framebuffer_update_display(surface, s->sysmem,
|
if (s->invalidated) {
|
||||||
addr, s->xres, s->yres,
|
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
|
||||||
|
addr, s->yres, src_width);
|
||||||
|
}
|
||||||
|
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
|
||||||
src_width, s->dest_width, -dest_width,
|
src_width, s->dest_width, -dest_width,
|
||||||
s->invalidated,
|
s->invalidated,
|
||||||
fn, s->dma_ch[0].palette,
|
fn, s->dma_ch[0].palette,
|
||||||
@@ -747,8 +754,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
|
|||||||
|
|
||||||
dest_width = s->xres * s->dest_width;
|
dest_width = s->xres * s->dest_width;
|
||||||
*miny = 0;
|
*miny = 0;
|
||||||
framebuffer_update_display(surface, s->sysmem,
|
if (s->invalidated) {
|
||||||
addr, s->xres, s->yres,
|
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
|
||||||
|
addr, s->yres, src_width);
|
||||||
|
}
|
||||||
|
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
|
||||||
src_width, -dest_width, -s->dest_width,
|
src_width, -dest_width, -s->dest_width,
|
||||||
s->invalidated,
|
s->invalidated,
|
||||||
fn, s->dma_ch[0].palette, miny, maxy);
|
fn, s->dma_ch[0].palette, miny, maxy);
|
||||||
@@ -778,8 +788,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
|
|||||||
|
|
||||||
dest_width = s->yres * s->dest_width;
|
dest_width = s->yres * s->dest_width;
|
||||||
*miny = 0;
|
*miny = 0;
|
||||||
framebuffer_update_display(surface, s->sysmem,
|
if (s->invalidated) {
|
||||||
addr, s->xres, s->yres,
|
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
|
||||||
|
addr, s->yres, src_width);
|
||||||
|
}
|
||||||
|
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
|
||||||
src_width, -s->dest_width, dest_width,
|
src_width, -s->dest_width, dest_width,
|
||||||
s->invalidated,
|
s->invalidated,
|
||||||
fn, s->dma_ch[0].palette,
|
fn, s->dma_ch[0].palette,
|
||||||
|
|||||||
+1
-1
@@ -944,7 +944,7 @@ static void tcx_initfn(Object *obj)
|
|||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
TCXState *s = TCX(obj);
|
TCXState *s = TCX(obj);
|
||||||
|
|
||||||
memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE,
|
memory_region_init_ram(&s->rom, OBJECT(s), "tcx.prom", FCODE_MAX_ROM_SIZE,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
memory_region_set_readonly(&s->rom, true);
|
memory_region_set_readonly(&s->rom, true);
|
||||||
sysbus_init_mmio(sbd, &s->rom);
|
sysbus_init_mmio(sbd, &s->rom);
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ static void virtio_gpu_set_config(VirtIODevice *vdev, const uint8_t *config)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t virtio_gpu_get_features(VirtIODevice *vdev, uint64_t features)
|
static uint64_t virtio_gpu_get_features(VirtIODevice *vdev, uint64_t features,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1108,8 +1108,8 @@ build_ssdt(GArray *table_data, GArray *linker,
|
|||||||
aml_append(field, aml_named_field("PEPT", 8));
|
aml_append(field, aml_named_field("PEPT", 8));
|
||||||
aml_append(dev, field);
|
aml_append(dev, field);
|
||||||
|
|
||||||
/* device present, functioning, decoding, not shown in UI */
|
/* device present, functioning, decoding, shown in UI */
|
||||||
aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
|
aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
|
||||||
|
|
||||||
method = aml_method("RDPT", 0);
|
method = aml_method("RDPT", 0);
|
||||||
aml_append(method, aml_store(aml_name("PEPT"), aml_local(0)));
|
aml_append(method, aml_store(aml_name("PEPT"), aml_local(0)));
|
||||||
|
|||||||
+7
-15
@@ -50,7 +50,6 @@ static void ahci_reset_port(AHCIState *s, int port);
|
|||||||
static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis);
|
static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis);
|
||||||
static void ahci_init_d2h(AHCIDevice *ad);
|
static void ahci_init_d2h(AHCIDevice *ad);
|
||||||
static int ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit);
|
static int ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit);
|
||||||
static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes);
|
|
||||||
static bool ahci_map_clb_address(AHCIDevice *ad);
|
static bool ahci_map_clb_address(AHCIDevice *ad);
|
||||||
static bool ahci_map_fis_address(AHCIDevice *ad);
|
static bool ahci_map_fis_address(AHCIDevice *ad);
|
||||||
static void ahci_unmap_clb_address(AHCIDevice *ad);
|
static void ahci_unmap_clb_address(AHCIDevice *ad);
|
||||||
@@ -1290,7 +1289,7 @@ out:
|
|||||||
s->data_ptr = s->data_end;
|
s->data_ptr = s->data_end;
|
||||||
|
|
||||||
/* Update number of transferred bytes, destroy sglist */
|
/* Update number of transferred bytes, destroy sglist */
|
||||||
ahci_commit_buf(dma, size);
|
dma_buf_commit(s, size);
|
||||||
|
|
||||||
s->end_transfer_func(s);
|
s->end_transfer_func(s);
|
||||||
|
|
||||||
@@ -1332,9 +1331,8 @@ static void ahci_restart(IDEDMA *dma)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called in DMA R/W chains to read the PRDT, utilizing ahci_populate_sglist.
|
* Called in DMA and PIO R/W chains to read the PRDT.
|
||||||
* Not currently invoked by PIO R/W chains,
|
* Not shared with NCQ pathways.
|
||||||
* which invoke ahci_populate_sglist via ahci_start_transfer.
|
|
||||||
*/
|
*/
|
||||||
static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit)
|
static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit)
|
||||||
{
|
{
|
||||||
@@ -1353,21 +1351,16 @@ static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the scatter-gather list,
|
* Updates the command header with a bytes-read value.
|
||||||
* and updates the command header with a bytes-read value.
|
* Called via dma_buf_commit, for both DMA and PIO paths.
|
||||||
* called explicitly via ahci_dma_rw_buf (ATAPI DMA),
|
* sglist destruction is handled within dma_buf_commit.
|
||||||
* and ahci_start_transfer (PIO R/W),
|
|
||||||
* and called via callback from ide_dma_cb for DMA R/W paths.
|
|
||||||
*/
|
*/
|
||||||
static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes)
|
static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes)
|
||||||
{
|
{
|
||||||
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
||||||
IDEState *s = &ad->port.ifs[0];
|
|
||||||
|
|
||||||
tx_bytes += le32_to_cpu(ad->cur_cmd->status);
|
tx_bytes += le32_to_cpu(ad->cur_cmd->status);
|
||||||
ad->cur_cmd->status = cpu_to_le32(tx_bytes);
|
ad->cur_cmd->status = cpu_to_le32(tx_bytes);
|
||||||
|
|
||||||
qemu_sglist_destroy(&s->sg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
|
static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
|
||||||
@@ -1388,10 +1381,9 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* free sglist, update byte count */
|
/* free sglist, update byte count */
|
||||||
ahci_commit_buf(dma, l);
|
dma_buf_commit(s, l);
|
||||||
|
|
||||||
s->io_buffer_index += l;
|
s->io_buffer_index += l;
|
||||||
s->io_buffer_offset += l;
|
|
||||||
|
|
||||||
DPRINTF(ad->port_no, "len=%#x\n", l);
|
DPRINTF(ad->port_no, "len=%#x\n", l);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -127,7 +127,7 @@
|
|||||||
#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */
|
#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */
|
||||||
#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */
|
#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */
|
||||||
|
|
||||||
#define PORT_CMD_ICC_MASK (0xf << 28) /* i/f ICC state mask */
|
#define PORT_CMD_ICC_MASK (0xfU << 28) /* i/f ICC state mask */
|
||||||
#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */
|
#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */
|
||||||
#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */
|
#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */
|
||||||
#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */
|
#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */
|
||||||
|
|||||||
@@ -983,6 +983,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
|
|||||||
|
|
||||||
if (pwrcnd) {
|
if (pwrcnd) {
|
||||||
/* eject/load only happens for power condition == 0 */
|
/* eject/load only happens for power condition == 0 */
|
||||||
|
ide_atapi_cmd_ok(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+45
-22
@@ -591,7 +591,6 @@ static void ide_sector_read_cb(void *opaque, int ret)
|
|||||||
s->nsector -= n;
|
s->nsector -= n;
|
||||||
/* Allow the guest to read the io_buffer */
|
/* Allow the guest to read the io_buffer */
|
||||||
ide_transfer_start(s, s->io_buffer, n * BDRV_SECTOR_SIZE, ide_sector_read);
|
ide_transfer_start(s, s->io_buffer, n * BDRV_SECTOR_SIZE, ide_sector_read);
|
||||||
s->io_buffer_offset += 512 * n;
|
|
||||||
ide_set_irq(s->bus);
|
ide_set_irq(s->bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,11 +634,12 @@ static void ide_sector_read(IDEState *s)
|
|||||||
ide_sector_read_cb, s);
|
ide_sector_read_cb, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dma_buf_commit(IDEState *s, uint32_t tx_bytes)
|
void dma_buf_commit(IDEState *s, uint32_t tx_bytes)
|
||||||
{
|
{
|
||||||
if (s->bus->dma->ops->commit_buf) {
|
if (s->bus->dma->ops->commit_buf) {
|
||||||
s->bus->dma->ops->commit_buf(s->bus->dma, tx_bytes);
|
s->bus->dma->ops->commit_buf(s->bus->dma, tx_bytes);
|
||||||
}
|
}
|
||||||
|
s->io_buffer_offset += tx_bytes;
|
||||||
qemu_sglist_destroy(&s->sg);
|
qemu_sglist_destroy(&s->sg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -842,7 +842,6 @@ static void ide_sector_write_cb(void *opaque, int ret)
|
|||||||
n = s->req_nb_sectors;
|
n = s->req_nb_sectors;
|
||||||
}
|
}
|
||||||
s->nsector -= n;
|
s->nsector -= n;
|
||||||
s->io_buffer_offset += 512 * n;
|
|
||||||
|
|
||||||
ide_set_sector(s, ide_get_sector(s) + n);
|
ide_set_sector(s, ide_get_sector(s) + n);
|
||||||
if (s->nsector == 0) {
|
if (s->nsector == 0) {
|
||||||
@@ -1747,11 +1746,11 @@ static const struct {
|
|||||||
} ide_cmd_table[0x100] = {
|
} ide_cmd_table[0x100] = {
|
||||||
/* NOP not implemented, mandatory for CD */
|
/* NOP not implemented, mandatory for CD */
|
||||||
[CFA_REQ_EXT_ERROR_CODE] = { cmd_cfa_req_ext_error_code, CFA_OK },
|
[CFA_REQ_EXT_ERROR_CODE] = { cmd_cfa_req_ext_error_code, CFA_OK },
|
||||||
[WIN_DSM] = { cmd_data_set_management, ALL_OK },
|
[WIN_DSM] = { cmd_data_set_management, HD_CFA_OK },
|
||||||
[WIN_DEVICE_RESET] = { cmd_device_reset, CD_OK },
|
[WIN_DEVICE_RESET] = { cmd_device_reset, CD_OK },
|
||||||
[WIN_RECAL] = { cmd_nop, HD_CFA_OK | SET_DSC},
|
[WIN_RECAL] = { cmd_nop, HD_CFA_OK | SET_DSC},
|
||||||
[WIN_READ] = { cmd_read_pio, ALL_OK },
|
[WIN_READ] = { cmd_read_pio, ALL_OK },
|
||||||
[WIN_READ_ONCE] = { cmd_read_pio, ALL_OK },
|
[WIN_READ_ONCE] = { cmd_read_pio, HD_CFA_OK },
|
||||||
[WIN_READ_EXT] = { cmd_read_pio, HD_CFA_OK },
|
[WIN_READ_EXT] = { cmd_read_pio, HD_CFA_OK },
|
||||||
[WIN_READDMA_EXT] = { cmd_read_dma, HD_CFA_OK },
|
[WIN_READDMA_EXT] = { cmd_read_dma, HD_CFA_OK },
|
||||||
[WIN_READ_NATIVE_MAX_EXT] = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
|
[WIN_READ_NATIVE_MAX_EXT] = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
|
||||||
@@ -1770,12 +1769,12 @@ static const struct {
|
|||||||
[CFA_TRANSLATE_SECTOR] = { cmd_cfa_translate_sector, CFA_OK },
|
[CFA_TRANSLATE_SECTOR] = { cmd_cfa_translate_sector, CFA_OK },
|
||||||
[WIN_DIAGNOSE] = { cmd_exec_dev_diagnostic, ALL_OK },
|
[WIN_DIAGNOSE] = { cmd_exec_dev_diagnostic, ALL_OK },
|
||||||
[WIN_SPECIFY] = { cmd_nop, HD_CFA_OK | SET_DSC },
|
[WIN_SPECIFY] = { cmd_nop, HD_CFA_OK | SET_DSC },
|
||||||
[WIN_STANDBYNOW2] = { cmd_nop, ALL_OK },
|
[WIN_STANDBYNOW2] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_IDLEIMMEDIATE2] = { cmd_nop, ALL_OK },
|
[WIN_IDLEIMMEDIATE2] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_STANDBY2] = { cmd_nop, ALL_OK },
|
[WIN_STANDBY2] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_SETIDLE2] = { cmd_nop, ALL_OK },
|
[WIN_SETIDLE2] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_CHECKPOWERMODE2] = { cmd_check_power_mode, ALL_OK | SET_DSC },
|
[WIN_CHECKPOWERMODE2] = { cmd_check_power_mode, HD_CFA_OK | SET_DSC },
|
||||||
[WIN_SLEEPNOW2] = { cmd_nop, ALL_OK },
|
[WIN_SLEEPNOW2] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_PACKETCMD] = { cmd_packet, CD_OK },
|
[WIN_PACKETCMD] = { cmd_packet, CD_OK },
|
||||||
[WIN_PIDENTIFY] = { cmd_identify_packet, CD_OK },
|
[WIN_PIDENTIFY] = { cmd_identify_packet, CD_OK },
|
||||||
[WIN_SMART] = { cmd_smart, HD_CFA_OK | SET_DSC },
|
[WIN_SMART] = { cmd_smart, HD_CFA_OK | SET_DSC },
|
||||||
@@ -1789,19 +1788,19 @@ static const struct {
|
|||||||
[WIN_WRITEDMA] = { cmd_write_dma, HD_CFA_OK },
|
[WIN_WRITEDMA] = { cmd_write_dma, HD_CFA_OK },
|
||||||
[WIN_WRITEDMA_ONCE] = { cmd_write_dma, HD_CFA_OK },
|
[WIN_WRITEDMA_ONCE] = { cmd_write_dma, HD_CFA_OK },
|
||||||
[CFA_WRITE_MULTI_WO_ERASE] = { cmd_write_multiple, CFA_OK },
|
[CFA_WRITE_MULTI_WO_ERASE] = { cmd_write_multiple, CFA_OK },
|
||||||
[WIN_STANDBYNOW1] = { cmd_nop, ALL_OK },
|
[WIN_STANDBYNOW1] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_IDLEIMMEDIATE] = { cmd_nop, ALL_OK },
|
[WIN_IDLEIMMEDIATE] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_STANDBY] = { cmd_nop, ALL_OK },
|
[WIN_STANDBY] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_SETIDLE1] = { cmd_nop, ALL_OK },
|
[WIN_SETIDLE1] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_CHECKPOWERMODE1] = { cmd_check_power_mode, ALL_OK | SET_DSC },
|
[WIN_CHECKPOWERMODE1] = { cmd_check_power_mode, HD_CFA_OK | SET_DSC },
|
||||||
[WIN_SLEEPNOW1] = { cmd_nop, ALL_OK },
|
[WIN_SLEEPNOW1] = { cmd_nop, HD_CFA_OK },
|
||||||
[WIN_FLUSH_CACHE] = { cmd_flush_cache, ALL_OK },
|
[WIN_FLUSH_CACHE] = { cmd_flush_cache, ALL_OK },
|
||||||
[WIN_FLUSH_CACHE_EXT] = { cmd_flush_cache, HD_CFA_OK },
|
[WIN_FLUSH_CACHE_EXT] = { cmd_flush_cache, HD_CFA_OK },
|
||||||
[WIN_IDENTIFY] = { cmd_identify, ALL_OK },
|
[WIN_IDENTIFY] = { cmd_identify, ALL_OK },
|
||||||
[WIN_SETFEATURES] = { cmd_set_features, ALL_OK | SET_DSC },
|
[WIN_SETFEATURES] = { cmd_set_features, ALL_OK | SET_DSC },
|
||||||
[IBM_SENSE_CONDITION] = { cmd_ibm_sense_condition, CFA_OK | SET_DSC },
|
[IBM_SENSE_CONDITION] = { cmd_ibm_sense_condition, CFA_OK | SET_DSC },
|
||||||
[CFA_WEAR_LEVEL] = { cmd_cfa_erase_sectors, HD_CFA_OK | SET_DSC },
|
[CFA_WEAR_LEVEL] = { cmd_cfa_erase_sectors, HD_CFA_OK | SET_DSC },
|
||||||
[WIN_READ_NATIVE_MAX] = { cmd_read_native_max, ALL_OK | SET_DSC },
|
[WIN_READ_NATIVE_MAX] = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool ide_cmd_permitted(IDEState *s, uint32_t cmd)
|
static bool ide_cmd_permitted(IDEState *s, uint32_t cmd)
|
||||||
@@ -2021,12 +2020,18 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = s->data_ptr;
|
p = s->data_ptr;
|
||||||
|
if (p + 2 > s->data_end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
*(uint16_t *)p = le16_to_cpu(val);
|
*(uint16_t *)p = le16_to_cpu(val);
|
||||||
p += 2;
|
p += 2;
|
||||||
s->data_ptr = p;
|
s->data_ptr = p;
|
||||||
if (p >= s->data_end)
|
if (p >= s->data_end) {
|
||||||
|
s->status &= ~DRQ_STAT;
|
||||||
s->end_transfer_func(s);
|
s->end_transfer_func(s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
||||||
{
|
{
|
||||||
@@ -2042,11 +2047,17 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = s->data_ptr;
|
p = s->data_ptr;
|
||||||
|
if (p + 2 > s->data_end) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = cpu_to_le16(*(uint16_t *)p);
|
ret = cpu_to_le16(*(uint16_t *)p);
|
||||||
p += 2;
|
p += 2;
|
||||||
s->data_ptr = p;
|
s->data_ptr = p;
|
||||||
if (p >= s->data_end)
|
if (p >= s->data_end) {
|
||||||
|
s->status &= ~DRQ_STAT;
|
||||||
s->end_transfer_func(s);
|
s->end_transfer_func(s);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2063,12 +2074,18 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = s->data_ptr;
|
p = s->data_ptr;
|
||||||
|
if (p + 4 > s->data_end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
*(uint32_t *)p = le32_to_cpu(val);
|
*(uint32_t *)p = le32_to_cpu(val);
|
||||||
p += 4;
|
p += 4;
|
||||||
s->data_ptr = p;
|
s->data_ptr = p;
|
||||||
if (p >= s->data_end)
|
if (p >= s->data_end) {
|
||||||
|
s->status &= ~DRQ_STAT;
|
||||||
s->end_transfer_func(s);
|
s->end_transfer_func(s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
||||||
{
|
{
|
||||||
@@ -2084,11 +2101,17 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = s->data_ptr;
|
p = s->data_ptr;
|
||||||
|
if (p + 4 > s->data_end) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = cpu_to_le32(*(uint32_t *)p);
|
ret = cpu_to_le32(*(uint32_t *)p);
|
||||||
p += 4;
|
p += 4;
|
||||||
s->data_ptr = p;
|
s->data_ptr = p;
|
||||||
if (p >= s->data_end)
|
if (p >= s->data_end) {
|
||||||
|
s->status &= ~DRQ_STAT;
|
||||||
s->end_transfer_func(s);
|
s->end_transfer_func(s);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -536,6 +536,7 @@ int64_t ide_get_sector(IDEState *s);
|
|||||||
void ide_set_sector(IDEState *s, int64_t sector_num);
|
void ide_set_sector(IDEState *s, int64_t sector_num);
|
||||||
|
|
||||||
void ide_start_dma(IDEState *s, BlockCompletionFunc *cb);
|
void ide_start_dma(IDEState *s, BlockCompletionFunc *cb);
|
||||||
|
void dma_buf_commit(IDEState *s, uint32_t tx_bytes);
|
||||||
void ide_dma_error(IDEState *s);
|
void ide_dma_error(IDEState *s);
|
||||||
|
|
||||||
void ide_atapi_cmd_ok(IDEState *s);
|
void ide_atapi_cmd_ok(IDEState *s);
|
||||||
|
|||||||
@@ -208,6 +208,33 @@ static void pmac_dma_write(BlockBackend *blk,
|
|||||||
cb, io);
|
cb, io);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pmac_dma_trim(BlockBackend *blk,
|
||||||
|
int64_t offset, int bytes,
|
||||||
|
void (*cb)(void *opaque, int ret), void *opaque)
|
||||||
|
{
|
||||||
|
DBDMA_io *io = opaque;
|
||||||
|
MACIOIDEState *m = io->opaque;
|
||||||
|
IDEState *s = idebus_active_if(&m->bus);
|
||||||
|
dma_addr_t dma_addr, dma_len;
|
||||||
|
void *mem;
|
||||||
|
|
||||||
|
qemu_iovec_destroy(&io->iov);
|
||||||
|
qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1);
|
||||||
|
|
||||||
|
dma_addr = io->addr;
|
||||||
|
dma_len = io->len;
|
||||||
|
mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
|
||||||
|
DMA_DIRECTION_TO_DEVICE);
|
||||||
|
|
||||||
|
qemu_iovec_add(&io->iov, mem, io->len);
|
||||||
|
s->io_buffer_size -= io->len;
|
||||||
|
s->io_buffer_index += io->len;
|
||||||
|
io->len = 0;
|
||||||
|
|
||||||
|
m->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov, (bytes >> 9),
|
||||||
|
cb, io);
|
||||||
|
}
|
||||||
|
|
||||||
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
|
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
|
||||||
{
|
{
|
||||||
DBDMA_io *io = opaque;
|
DBDMA_io *io = opaque;
|
||||||
@@ -313,6 +340,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
|
|||||||
pmac_dma_write(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
|
pmac_dma_write(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
|
||||||
break;
|
break;
|
||||||
case IDE_DMA_TRIM:
|
case IDE_DMA_TRIM:
|
||||||
|
pmac_dma_trim(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
|
|||||||
PCIIDEState *pci_ide;
|
PCIIDEState *pci_ide;
|
||||||
DriveInfo *di;
|
DriveInfo *di;
|
||||||
int i;
|
int i;
|
||||||
|
IDEDevice *idedev;
|
||||||
|
|
||||||
pci_ide = PCI_IDE(dev);
|
pci_ide = PCI_IDE(dev);
|
||||||
|
|
||||||
@@ -181,6 +182,12 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
|
|||||||
blk_detach_dev(blk, ds);
|
blk_detach_dev(blk, ds);
|
||||||
}
|
}
|
||||||
pci_ide->bus[di->bus].ifs[di->unit].blk = NULL;
|
pci_ide->bus[di->bus].ifs[di->unit].blk = NULL;
|
||||||
|
if (!(i % 2)) {
|
||||||
|
idedev = pci_ide->bus[di->bus].master;
|
||||||
|
} else {
|
||||||
|
idedev = pci_ide->bus[di->bus].slave;
|
||||||
|
}
|
||||||
|
idedev->conf.blk = NULL;
|
||||||
blk_unref(blk);
|
blk_unref(blk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
|
|||||||
unsigned have, need;
|
unsigned have, need;
|
||||||
int i, len;
|
int i, len;
|
||||||
|
|
||||||
|
if (!vinput->active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* queue up events ... */
|
/* queue up events ... */
|
||||||
if (vinput->qindex == vinput->qsize) {
|
if (vinput->qindex == vinput->qsize) {
|
||||||
vinput->qsize++;
|
vinput->qsize++;
|
||||||
@@ -166,7 +170,8 @@ static void virtio_input_set_config(VirtIODevice *vdev,
|
|||||||
virtio_notify_config(vdev);
|
virtio_notify_config(vdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t virtio_input_get_features(VirtIODevice *vdev, uint64_t f)
|
static uint64_t virtio_input_get_features(VirtIODevice *vdev, uint64_t f,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ static void intdbg_control_init(Object *obj)
|
|||||||
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
|
||||||
IntegratorDebugState *s = INTEGRATOR_DEBUG(obj);
|
IntegratorDebugState *s = INTEGRATOR_DEBUG(obj);
|
||||||
|
|
||||||
memory_region_init_io(&s->iomem, NULL, &intdbg_control_ops,
|
memory_region_init_io(&s->iomem, obj, &intdbg_control_ops,
|
||||||
NULL, "dbg-leds", 0x1000000);
|
NULL, "dbg-leds", 0x1000000);
|
||||||
sysbus_init_mmio(sd, &s->iomem);
|
sysbus_init_mmio(sd, &s->iomem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -713,7 +713,7 @@ static void cuda_initfn(Object *obj)
|
|||||||
CUDAState *s = CUDA(obj);
|
CUDAState *s = CUDA(obj);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memory_region_init_io(&s->mem, NULL, &cuda_ops, s, "cuda", 0x2000);
|
memory_region_init_io(&s->mem, obj, &cuda_ops, s, "cuda", 0x2000);
|
||||||
sysbus_init_mmio(d, &s->mem);
|
sysbus_init_mmio(d, &s->mem);
|
||||||
sysbus_init_irq(d, &s->irq);
|
sysbus_init_irq(d, &s->irq);
|
||||||
|
|
||||||
|
|||||||
@@ -590,11 +590,12 @@ dbdma_control_write(DBDMA_channel *ch)
|
|||||||
if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
|
if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
|
||||||
/* RUN is cleared */
|
/* RUN is cleared */
|
||||||
status &= ~(ACTIVE|DEAD);
|
status &= ~(ACTIVE|DEAD);
|
||||||
|
}
|
||||||
|
|
||||||
if ((status & FLUSH) && ch->flush) {
|
if ((status & FLUSH) && ch->flush) {
|
||||||
ch->flush(&ch->io);
|
ch->flush(&ch->io);
|
||||||
status &= ~FLUSH;
|
status &= ~FLUSH;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DBDMA_DPRINTF(" status 0x%08x\n", status);
|
DBDMA_DPRINTF(" status 0x%08x\n", status);
|
||||||
|
|
||||||
@@ -603,9 +604,6 @@ dbdma_control_write(DBDMA_channel *ch)
|
|||||||
if (status & ACTIVE) {
|
if (status & ACTIVE) {
|
||||||
DBDMA_kick(dbdma_from_ch(ch));
|
DBDMA_kick(dbdma_from_ch(ch));
|
||||||
}
|
}
|
||||||
if ((status & FLUSH) && ch->flush) {
|
|
||||||
ch->flush(&ch->io);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dbdma_write(void *opaque, hwaddr addr,
|
static void dbdma_write(void *opaque, hwaddr addr,
|
||||||
|
|||||||
@@ -105,10 +105,10 @@ static void macio_escc_legacy_setup(MacIOState *macio_state)
|
|||||||
0xF0, 0xE0,
|
0xF0, 0xE0,
|
||||||
};
|
};
|
||||||
|
|
||||||
memory_region_init(escc_legacy, NULL, "escc-legacy", 256);
|
memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
|
||||||
for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
|
for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
|
||||||
MemoryRegion *port = g_new(MemoryRegion, 1);
|
MemoryRegion *port = g_new(MemoryRegion, 1);
|
||||||
memory_region_init_alias(port, NULL, "escc-legacy-port",
|
memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port",
|
||||||
macio_state->escc_mem, maps[i+1], 0x2);
|
macio_state->escc_mem, maps[i+1], 0x2);
|
||||||
memory_region_add_subregion(escc_legacy, maps[i], port);
|
memory_region_add_subregion(escc_legacy, maps[i], port);
|
||||||
}
|
}
|
||||||
@@ -131,6 +131,10 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
|
|||||||
MacIOState *s = MACIO(d);
|
MacIOState *s = MACIO(d);
|
||||||
SysBusDevice *sysbus_dev;
|
SysBusDevice *sysbus_dev;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
MemoryRegion *dbdma_mem;
|
||||||
|
|
||||||
|
s->dbdma = DBDMA_init(&dbdma_mem);
|
||||||
|
memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
|
||||||
|
|
||||||
object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
|
object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -328,16 +332,12 @@ static void macio_newworld_init(Object *obj)
|
|||||||
static void macio_instance_init(Object *obj)
|
static void macio_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
MacIOState *s = MACIO(obj);
|
MacIOState *s = MACIO(obj);
|
||||||
MemoryRegion *dbdma_mem;
|
|
||||||
|
|
||||||
memory_region_init(&s->bar, NULL, "macio", 0x80000);
|
memory_region_init(&s->bar, obj, "macio", 0x80000);
|
||||||
|
|
||||||
object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
|
object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
|
||||||
qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
|
qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
|
||||||
object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
|
object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
|
||||||
|
|
||||||
s->dbdma = DBDMA_init(&dbdma_mem);
|
|
||||||
memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_macio_oldworld = {
|
static const VMStateDescription vmstate_macio_oldworld = {
|
||||||
|
|||||||
+4
-4
@@ -393,12 +393,12 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->regs[LOCKSTA]) {
|
if (s->regs[LOCKSTA]) {
|
||||||
s->regs[offset / 4] = val;
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
} else {
|
"SCLR registers are locked. Unlock them first\n");
|
||||||
DB_PRINT("SCLR registers are locked. Unlock them first\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
s->regs[offset] = val;
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case PSS_RST_CTRL:
|
case PSS_RST_CTRL:
|
||||||
|
|||||||
+18
-7
@@ -327,9 +327,14 @@ static void dp8393x_do_stop_timer(dp8393xState *s)
|
|||||||
dp8393x_update_wt_regs(s);
|
dp8393x_update_wt_regs(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dp8393x_can_receive(NetClientState *nc);
|
||||||
|
|
||||||
static void dp8393x_do_receiver_enable(dp8393xState *s)
|
static void dp8393x_do_receiver_enable(dp8393xState *s)
|
||||||
{
|
{
|
||||||
s->regs[SONIC_CR] &= ~SONIC_CR_RXDIS;
|
s->regs[SONIC_CR] &= ~SONIC_CR_RXDIS;
|
||||||
|
if (dp8393x_can_receive(s->nic->ncs)) {
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(s->nic));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dp8393x_do_receiver_disable(dp8393xState *s)
|
static void dp8393x_do_receiver_disable(dp8393xState *s)
|
||||||
@@ -569,6 +574,9 @@ static void dp8393x_write(void *opaque, hwaddr addr, uint64_t data,
|
|||||||
dp8393x_do_read_rra(s);
|
dp8393x_do_read_rra(s);
|
||||||
}
|
}
|
||||||
dp8393x_update_irq(s);
|
dp8393x_update_irq(s);
|
||||||
|
if (dp8393x_can_receive(s->nic->ncs)) {
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(s->nic));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
/* Ignore least significant bit */
|
/* Ignore least significant bit */
|
||||||
case SONIC_RSA:
|
case SONIC_RSA:
|
||||||
@@ -635,11 +643,6 @@ static int dp8393x_receive_filter(dp8393xState *s, const uint8_t * buf,
|
|||||||
static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Check for runt packet (remember that checksum is not there) */
|
|
||||||
if (size < 64 - 4) {
|
|
||||||
return (s->regs[SONIC_RCR] & SONIC_RCR_RNT) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check promiscuous mode */
|
/* Check promiscuous mode */
|
||||||
if ((s->regs[SONIC_RCR] & SONIC_RCR_PRO) && (buf[0] & 1) == 0) {
|
if ((s->regs[SONIC_RCR] & SONIC_RCR_PRO) && (buf[0] & 1) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -828,6 +831,7 @@ static void dp8393x_realize(DeviceState *dev, Error **errp)
|
|||||||
dp8393xState *s = DP8393X(dev);
|
dp8393xState *s = DP8393X(dev);
|
||||||
int i, checksum;
|
int i, checksum;
|
||||||
uint8_t *prom;
|
uint8_t *prom;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
address_space_init(&s->as, s->dma_mr, "dp8393x");
|
address_space_init(&s->as, s->dma_mr, "dp8393x");
|
||||||
memory_region_init_io(&s->mmio, OBJECT(dev), &dp8393x_ops, s,
|
memory_region_init_io(&s->mmio, OBJECT(dev), &dp8393x_ops, s,
|
||||||
@@ -840,8 +844,13 @@ static void dp8393x_realize(DeviceState *dev, Error **errp)
|
|||||||
s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
|
s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
|
||||||
s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
|
s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
|
||||||
|
|
||||||
memory_region_init_rom_device(&s->prom, OBJECT(dev), NULL, NULL,
|
memory_region_init_ram(&s->prom, OBJECT(dev),
|
||||||
"dp8393x-prom", SONIC_PROM_SIZE, NULL);
|
"dp8393x-prom", SONIC_PROM_SIZE, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memory_region_set_readonly(&s->prom, true);
|
||||||
prom = memory_region_get_ram_ptr(&s->prom);
|
prom = memory_region_get_ram_ptr(&s->prom);
|
||||||
checksum = 0;
|
checksum = 0;
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
@@ -881,6 +890,8 @@ static void dp8393x_class_init(ObjectClass *klass, void *data)
|
|||||||
dc->reset = dp8393x_reset;
|
dc->reset = dp8393x_reset;
|
||||||
dc->vmsd = &vmstate_dp8393x;
|
dc->vmsd = &vmstate_dp8393x;
|
||||||
dc->props = dp8393x_properties;
|
dc->props = dp8393x_properties;
|
||||||
|
/* Reason: dma_mr property can't be set */
|
||||||
|
dc->cannot_instantiate_with_device_add_yet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo dp8393x_info = {
|
static const TypeInfo dp8393x_info = {
|
||||||
|
|||||||
+2
-1
@@ -740,7 +740,8 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
|
|||||||
memmove(tp->data, tp->header, tp->hdr_len);
|
memmove(tp->data, tp->header, tp->hdr_len);
|
||||||
tp->size = tp->hdr_len;
|
tp->size = tp->hdr_len;
|
||||||
}
|
}
|
||||||
} while (split_size -= bytes);
|
split_size -= bytes;
|
||||||
|
} while (bytes && split_size);
|
||||||
} else if (!tp->tse && tp->cptse) {
|
} else if (!tp->tse && tp->cptse) {
|
||||||
// context descriptor TSE is not set, while data descriptor TSE is set
|
// context descriptor TSE is not set, while data descriptor TSE is set
|
||||||
DBGOUT(TXERR, "TCP segmentation error\n");
|
DBGOUT(TXERR, "TCP segmentation error\n");
|
||||||
|
|||||||
@@ -1617,16 +1617,6 @@ static const MemoryRegionOps eepro100_ops = {
|
|||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int nic_can_receive(NetClientState *nc)
|
|
||||||
{
|
|
||||||
EEPRO100State *s = qemu_get_nic_opaque(nc);
|
|
||||||
TRACE(RXTX, logout("%p\n", s));
|
|
||||||
return get_ru_state(s) == ru_ready;
|
|
||||||
#if 0
|
|
||||||
return !eepro100_buffer_full(s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
|
static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
|
||||||
{
|
{
|
||||||
/* TODO:
|
/* TODO:
|
||||||
@@ -1844,7 +1834,6 @@ static void pci_nic_uninit(PCIDevice *pci_dev)
|
|||||||
static NetClientInfo net_eepro100_info = {
|
static NetClientInfo net_eepro100_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = nic_can_receive,
|
|
||||||
.receive = nic_receive,
|
.receive = nic_receive,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -338,25 +338,26 @@ static void etsec_reset(DeviceState *d)
|
|||||||
MII_SR_100X_FD_CAPS | MII_SR_100T4_CAPS;
|
MII_SR_100X_FD_CAPS | MII_SR_100T4_CAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int etsec_can_receive(NetClientState *nc)
|
|
||||||
{
|
|
||||||
eTSEC *etsec = qemu_get_nic_opaque(nc);
|
|
||||||
|
|
||||||
return etsec->rx_buffer_len == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t etsec_receive(NetClientState *nc,
|
static ssize_t etsec_receive(NetClientState *nc,
|
||||||
const uint8_t *buf,
|
const uint8_t *buf,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
|
ssize_t ret;
|
||||||
eTSEC *etsec = qemu_get_nic_opaque(nc);
|
eTSEC *etsec = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
#if defined(HEX_DUMP)
|
#if defined(HEX_DUMP)
|
||||||
fprintf(stderr, "%s receive size:%d\n", etsec->nic->nc.name, size);
|
fprintf(stderr, "%s receive size:%d\n", etsec->nic->nc.name, size);
|
||||||
qemu_hexdump(buf, stderr, "", size);
|
qemu_hexdump(buf, stderr, "", size);
|
||||||
#endif
|
#endif
|
||||||
etsec_rx_ring_write(etsec, buf, size);
|
/* Flush is unnecessary as are already in receiving path */
|
||||||
return size;
|
etsec->need_flush = false;
|
||||||
|
ret = etsec_rx_ring_write(etsec, buf, size);
|
||||||
|
if (ret == 0) {
|
||||||
|
/* The packet will be queued, let's flush it when buffer is avilable
|
||||||
|
* again. */
|
||||||
|
etsec->need_flush = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -370,7 +371,6 @@ static void etsec_set_link_status(NetClientState *nc)
|
|||||||
static NetClientInfo net_etsec_info = {
|
static NetClientInfo net_etsec_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = etsec_can_receive,
|
|
||||||
.receive = etsec_receive,
|
.receive = etsec_receive,
|
||||||
.link_status_changed = etsec_set_link_status,
|
.link_status_changed = etsec_set_link_status,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ typedef struct eTSEC {
|
|||||||
QEMUBH *bh;
|
QEMUBH *bh;
|
||||||
struct ptimer_state *ptimer;
|
struct ptimer_state *ptimer;
|
||||||
|
|
||||||
|
/* Whether we should flush the rx queue when buffer becomes available. */
|
||||||
|
bool need_flush;
|
||||||
} eTSEC;
|
} eTSEC;
|
||||||
|
|
||||||
#define TYPE_ETSEC_COMMON "eTSEC"
|
#define TYPE_ETSEC_COMMON "eTSEC"
|
||||||
@@ -162,7 +164,7 @@ DeviceState *etsec_create(hwaddr base,
|
|||||||
|
|
||||||
void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr);
|
void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr);
|
||||||
void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr);
|
void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr);
|
||||||
void etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size);
|
ssize_t etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size);
|
||||||
|
|
||||||
void etsec_write_miim(eTSEC *etsec,
|
void etsec_write_miim(eTSEC *etsec,
|
||||||
eTSEC_Register *reg,
|
eTSEC_Register *reg,
|
||||||
|
|||||||
@@ -481,40 +481,42 @@ static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size)
|
|||||||
etsec->rx_buffer_len, etsec->rx_padding);
|
etsec->rx_buffer_len, etsec->rx_padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
void etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size)
|
ssize_t etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size)
|
||||||
{
|
{
|
||||||
int ring_nbr = 0; /* Always use ring0 (no filer) */
|
int ring_nbr = 0; /* Always use ring0 (no filer) */
|
||||||
|
|
||||||
if (etsec->rx_buffer_len != 0) {
|
if (etsec->rx_buffer_len != 0) {
|
||||||
RING_DEBUG("%s: We can't receive now,"
|
RING_DEBUG("%s: We can't receive now,"
|
||||||
" a buffer is already in the pipe\n", __func__);
|
" a buffer is already in the pipe\n", __func__);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (etsec->regs[RSTAT].value & 1 << (23 - ring_nbr)) {
|
if (etsec->regs[RSTAT].value & 1 << (23 - ring_nbr)) {
|
||||||
RING_DEBUG("%s: The ring is halted\n", __func__);
|
RING_DEBUG("%s: The ring is halted\n", __func__);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (etsec->regs[DMACTRL].value & DMACTRL_GRS) {
|
if (etsec->regs[DMACTRL].value & DMACTRL_GRS) {
|
||||||
RING_DEBUG("%s: Graceful receive stop\n", __func__);
|
RING_DEBUG("%s: Graceful receive stop\n", __func__);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(etsec->regs[MACCFG1].value & MACCFG1_RX_EN)) {
|
if (!(etsec->regs[MACCFG1].value & MACCFG1_RX_EN)) {
|
||||||
RING_DEBUG("%s: MAC Receive not enabled\n", __func__);
|
RING_DEBUG("%s: MAC Receive not enabled\n", __func__);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((etsec->regs[RCTRL].value & RCTRL_RSF) && (size < 60)) {
|
if ((etsec->regs[RCTRL].value & RCTRL_RSF) && (size < 60)) {
|
||||||
/* CRC is not in the packet yet, so short frame is below 60 bytes */
|
/* CRC is not in the packet yet, so short frame is below 60 bytes */
|
||||||
RING_DEBUG("%s: Drop short frame\n", __func__);
|
RING_DEBUG("%s: Drop short frame\n", __func__);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rx_init_frame(etsec, buf, size);
|
rx_init_frame(etsec, buf, size);
|
||||||
|
|
||||||
etsec_walk_rx_ring(etsec, ring_nbr);
|
etsec_walk_rx_ring(etsec, ring_nbr);
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
||||||
@@ -644,6 +646,9 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
|||||||
} else {
|
} else {
|
||||||
etsec->rx_buffer_len = 0;
|
etsec->rx_buffer_len = 0;
|
||||||
etsec->rx_buffer = NULL;
|
etsec->rx_buffer = NULL;
|
||||||
|
if (etsec->need_flush) {
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(etsec->nic));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RING_DEBUG("eTSEC End of ring_write: remaining_data:%zu\n", remaining_data);
|
RING_DEBUG("eTSEC End of ring_write: remaining_data:%zu\n", remaining_data);
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ static const MemoryRegionOps lance_mem_ops = {
|
|||||||
static NetClientInfo net_lance_info = {
|
static NetClientInfo net_lance_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = pcnet_can_receive,
|
|
||||||
.receive = pcnet_receive,
|
.receive = pcnet_receive,
|
||||||
.link_status_changed = pcnet_set_link_status,
|
.link_status_changed = pcnet_set_link_status,
|
||||||
};
|
};
|
||||||
|
|||||||
+83
-18
@@ -8,6 +8,7 @@
|
|||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "net/net.h"
|
#include "net/net.h"
|
||||||
#include "hw/m68k/mcf.h"
|
#include "hw/m68k/mcf.h"
|
||||||
|
#include "hw/net/mii.h"
|
||||||
/* For crc32 */
|
/* For crc32 */
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
@@ -195,12 +196,14 @@ static void mcf_fec_do_tx(mcf_fec_state *s)
|
|||||||
|
|
||||||
static void mcf_fec_enable_rx(mcf_fec_state *s)
|
static void mcf_fec_enable_rx(mcf_fec_state *s)
|
||||||
{
|
{
|
||||||
|
NetClientState *nc = qemu_get_queue(s->nic);
|
||||||
mcf_fec_bd bd;
|
mcf_fec_bd bd;
|
||||||
|
|
||||||
mcf_fec_read_bd(&bd, s->rx_descriptor);
|
mcf_fec_read_bd(&bd, s->rx_descriptor);
|
||||||
s->rx_enabled = ((bd.flags & FEC_BD_E) != 0);
|
s->rx_enabled = ((bd.flags & FEC_BD_E) != 0);
|
||||||
if (!s->rx_enabled)
|
if (s->rx_enabled) {
|
||||||
DPRINTF("RX buffer full\n");
|
qemu_flush_queued_packets(nc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mcf_fec_reset(mcf_fec_state *s)
|
static void mcf_fec_reset(mcf_fec_state *s)
|
||||||
@@ -216,6 +219,51 @@ static void mcf_fec_reset(mcf_fec_state *s)
|
|||||||
s->rfsr = 0x500;
|
s->rfsr = 0x500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MMFR_WRITE_OP (1 << 28)
|
||||||
|
#define MMFR_READ_OP (2 << 28)
|
||||||
|
#define MMFR_PHYADDR(v) (((v) >> 23) & 0x1f)
|
||||||
|
#define MMFR_REGNUM(v) (((v) >> 18) & 0x1f)
|
||||||
|
|
||||||
|
static uint64_t mcf_fec_read_mdio(mcf_fec_state *s)
|
||||||
|
{
|
||||||
|
uint64_t v;
|
||||||
|
|
||||||
|
if (s->mmfr & MMFR_WRITE_OP)
|
||||||
|
return s->mmfr;
|
||||||
|
if (MMFR_PHYADDR(s->mmfr) != 1)
|
||||||
|
return s->mmfr |= 0xffff;
|
||||||
|
|
||||||
|
switch (MMFR_REGNUM(s->mmfr)) {
|
||||||
|
case MII_BMCR:
|
||||||
|
v = MII_BMCR_SPEED | MII_BMCR_AUTOEN | MII_BMCR_FD;
|
||||||
|
break;
|
||||||
|
case MII_BMSR:
|
||||||
|
v = MII_BMSR_100TX_FD | MII_BMSR_100TX_HD | MII_BMSR_10T_FD |
|
||||||
|
MII_BMSR_10T_HD | MII_BMSR_MFPS | MII_BMSR_AN_COMP |
|
||||||
|
MII_BMSR_AUTONEG | MII_BMSR_LINK_ST;
|
||||||
|
break;
|
||||||
|
case MII_PHYID1:
|
||||||
|
v = DP83848_PHYID1;
|
||||||
|
break;
|
||||||
|
case MII_PHYID2:
|
||||||
|
v = DP83848_PHYID2;
|
||||||
|
break;
|
||||||
|
case MII_ANAR:
|
||||||
|
v = MII_ANAR_TXFD | MII_ANAR_TX | MII_ANAR_10FD |
|
||||||
|
MII_ANAR_10 | MII_ANAR_CSMACD;
|
||||||
|
break;
|
||||||
|
case MII_ANLPAR:
|
||||||
|
v = MII_ANLPAR_ACK | MII_ANLPAR_TXFD | MII_ANLPAR_TX |
|
||||||
|
MII_ANLPAR_10FD | MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
v = 0xffff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s->mmfr = (s->mmfr & ~0xffff) | v;
|
||||||
|
return s->mmfr;
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t mcf_fec_read(void *opaque, hwaddr addr,
|
static uint64_t mcf_fec_read(void *opaque, hwaddr addr,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
@@ -226,7 +274,7 @@ static uint64_t mcf_fec_read(void *opaque, hwaddr addr,
|
|||||||
case 0x010: return s->rx_enabled ? (1 << 24) : 0; /* RDAR */
|
case 0x010: return s->rx_enabled ? (1 << 24) : 0; /* RDAR */
|
||||||
case 0x014: return 0; /* TDAR */
|
case 0x014: return 0; /* TDAR */
|
||||||
case 0x024: return s->ecr;
|
case 0x024: return s->ecr;
|
||||||
case 0x040: return s->mmfr;
|
case 0x040: return mcf_fec_read_mdio(s);
|
||||||
case 0x044: return s->mscr;
|
case 0x044: return s->mscr;
|
||||||
case 0x064: return 0; /* MIBC */
|
case 0x064: return 0; /* MIBC */
|
||||||
case 0x084: return s->rcr;
|
case 0x084: return s->rcr;
|
||||||
@@ -287,8 +335,8 @@ static void mcf_fec_write(void *opaque, hwaddr addr,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x040:
|
case 0x040:
|
||||||
/* TODO: Implement MII. */
|
|
||||||
s->mmfr = value;
|
s->mmfr = value;
|
||||||
|
s->eir |= FEC_INT_MII;
|
||||||
break;
|
break;
|
||||||
case 0x044:
|
case 0x044:
|
||||||
s->mscr = value & 0xfe;
|
s->mscr = value & 0xfe;
|
||||||
@@ -351,10 +399,30 @@ static void mcf_fec_write(void *opaque, hwaddr addr,
|
|||||||
mcf_fec_update(s);
|
mcf_fec_update(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mcf_fec_can_receive(NetClientState *nc)
|
static int mcf_fec_have_receive_space(mcf_fec_state *s, size_t want)
|
||||||
{
|
{
|
||||||
mcf_fec_state *s = qemu_get_nic_opaque(nc);
|
mcf_fec_bd bd;
|
||||||
return s->rx_enabled;
|
uint32_t addr;
|
||||||
|
|
||||||
|
/* Walk descriptor list to determine if we have enough buffer */
|
||||||
|
addr = s->rx_descriptor;
|
||||||
|
while (want > 0) {
|
||||||
|
mcf_fec_read_bd(&bd, addr);
|
||||||
|
if ((bd.flags & FEC_BD_E) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (want < s->emrbr) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
want -= s->emrbr;
|
||||||
|
/* Advance to the next descriptor. */
|
||||||
|
if ((bd.flags & FEC_BD_W) != 0) {
|
||||||
|
addr = s->erdsr;
|
||||||
|
} else {
|
||||||
|
addr += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t size)
|
static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t size)
|
||||||
@@ -367,10 +435,11 @@ static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t si
|
|||||||
uint32_t buf_addr;
|
uint32_t buf_addr;
|
||||||
uint8_t *crc_ptr;
|
uint8_t *crc_ptr;
|
||||||
unsigned int buf_len;
|
unsigned int buf_len;
|
||||||
|
size_t retsize;
|
||||||
|
|
||||||
DPRINTF("do_rx len %d\n", size);
|
DPRINTF("do_rx len %d\n", size);
|
||||||
if (!s->rx_enabled) {
|
if (!s->rx_enabled) {
|
||||||
fprintf(stderr, "mcf_fec_receive: Unexpected packet\n");
|
return -1;
|
||||||
}
|
}
|
||||||
/* 4 bytes for the CRC. */
|
/* 4 bytes for the CRC. */
|
||||||
size += 4;
|
size += 4;
|
||||||
@@ -385,17 +454,14 @@ static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t si
|
|||||||
if (size > (s->rcr >> 16)) {
|
if (size > (s->rcr >> 16)) {
|
||||||
flags |= FEC_BD_LG;
|
flags |= FEC_BD_LG;
|
||||||
}
|
}
|
||||||
|
/* Check if we have enough space in current descriptors */
|
||||||
|
if (!mcf_fec_have_receive_space(s, size)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
addr = s->rx_descriptor;
|
addr = s->rx_descriptor;
|
||||||
|
retsize = size;
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
mcf_fec_read_bd(&bd, addr);
|
mcf_fec_read_bd(&bd, addr);
|
||||||
if ((bd.flags & FEC_BD_E) == 0) {
|
|
||||||
/* No descriptors available. Bail out. */
|
|
||||||
/* FIXME: This is wrong. We should probably either save the
|
|
||||||
remainder for when more RX buffers are available, or
|
|
||||||
flag an error. */
|
|
||||||
fprintf(stderr, "mcf_fec: Lost end of frame\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf_len = (size <= s->emrbr) ? size: s->emrbr;
|
buf_len = (size <= s->emrbr) ? size: s->emrbr;
|
||||||
bd.length = buf_len;
|
bd.length = buf_len;
|
||||||
size -= buf_len;
|
size -= buf_len;
|
||||||
@@ -430,7 +496,7 @@ static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t si
|
|||||||
s->rx_descriptor = addr;
|
s->rx_descriptor = addr;
|
||||||
mcf_fec_enable_rx(s);
|
mcf_fec_enable_rx(s);
|
||||||
mcf_fec_update(s);
|
mcf_fec_update(s);
|
||||||
return size;
|
return retsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const MemoryRegionOps mcf_fec_ops = {
|
static const MemoryRegionOps mcf_fec_ops = {
|
||||||
@@ -442,7 +508,6 @@ static const MemoryRegionOps mcf_fec_ops = {
|
|||||||
static NetClientInfo net_mcf_fec_info = {
|
static NetClientInfo net_mcf_fec_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = mcf_fec_can_receive,
|
|
||||||
.receive = mcf_fec_receive,
|
.receive = mcf_fec_receive,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+16
-17
@@ -303,8 +303,7 @@ static ssize_t minimac2_rx(NetClientState *nc, const uint8_t *buf, size_t size)
|
|||||||
r_state = R_STATE1;
|
r_state = R_STATE1;
|
||||||
rx_buf = s->rx1_buf;
|
rx_buf = s->rx1_buf;
|
||||||
} else {
|
} else {
|
||||||
trace_milkymist_minimac2_drop_rx_frame(buf);
|
return 0;
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assemble frame */
|
/* assemble frame */
|
||||||
@@ -354,6 +353,18 @@ minimac2_read(void *opaque, hwaddr addr, unsigned size)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int minimac2_can_rx(MilkymistMinimac2State *s)
|
||||||
|
{
|
||||||
|
if (s->regs[R_STATE0] == STATE_LOADED) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (s->regs[R_STATE1] == STATE_LOADED) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
minimac2_write(void *opaque, hwaddr addr, uint64_t value,
|
minimac2_write(void *opaque, hwaddr addr, uint64_t value,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
@@ -387,6 +398,9 @@ minimac2_write(void *opaque, hwaddr addr, uint64_t value,
|
|||||||
case R_STATE1:
|
case R_STATE1:
|
||||||
s->regs[addr] = value;
|
s->regs[addr] = value;
|
||||||
update_rx_interrupt(s);
|
update_rx_interrupt(s);
|
||||||
|
if (minimac2_can_rx(s)) {
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(s->nic));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case R_SETUP:
|
case R_SETUP:
|
||||||
case R_COUNT0:
|
case R_COUNT0:
|
||||||
@@ -411,20 +425,6 @@ static const MemoryRegionOps minimac2_ops = {
|
|||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int minimac2_can_rx(NetClientState *nc)
|
|
||||||
{
|
|
||||||
MilkymistMinimac2State *s = qemu_get_nic_opaque(nc);
|
|
||||||
|
|
||||||
if (s->regs[R_STATE0] == STATE_LOADED) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (s->regs[R_STATE1] == STATE_LOADED) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void milkymist_minimac2_reset(DeviceState *d)
|
static void milkymist_minimac2_reset(DeviceState *d)
|
||||||
{
|
{
|
||||||
MilkymistMinimac2State *s = MILKYMIST_MINIMAC2(d);
|
MilkymistMinimac2State *s = MILKYMIST_MINIMAC2(d);
|
||||||
@@ -445,7 +445,6 @@ static void milkymist_minimac2_reset(DeviceState *d)
|
|||||||
static NetClientInfo net_milkymist_minimac2_info = {
|
static NetClientInfo net_milkymist_minimac2_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = minimac2_can_rx,
|
|
||||||
.receive = minimac2_rx,
|
.receive = minimac2_rx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -80,7 +80,7 @@ static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf, size_t si
|
|||||||
|
|
||||||
trace_mipsnet_receive(size);
|
trace_mipsnet_receive(size);
|
||||||
if (!mipsnet_can_receive(nc))
|
if (!mipsnet_can_receive(nc))
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
s->busy = 1;
|
s->busy = 1;
|
||||||
|
|
||||||
@@ -134,6 +134,9 @@ static uint64_t mipsnet_ioport_read(void *opaque, hwaddr addr,
|
|||||||
if (s->rx_count) {
|
if (s->rx_count) {
|
||||||
s->rx_count--;
|
s->rx_count--;
|
||||||
ret = s->rx_buffer[s->rx_read++];
|
ret = s->rx_buffer[s->rx_read++];
|
||||||
|
if (mipsnet_can_receive(s->nic->ncs)) {
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(s->nic));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* Reads as zero. */
|
/* Reads as zero. */
|
||||||
@@ -170,6 +173,9 @@ static void mipsnet_ioport_write(void *opaque, hwaddr addr,
|
|||||||
}
|
}
|
||||||
s->busy = !!s->intctl;
|
s->busy = !!s->intctl;
|
||||||
mipsnet_update_irq(s);
|
mipsnet_update_irq(s);
|
||||||
|
if (mipsnet_can_receive(s->nic->ncs)) {
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(s->nic));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MIPSNET_TX_DATA_BUFFER:
|
case MIPSNET_TX_DATA_BUFFER:
|
||||||
s->tx_buffer[s->tx_written++] = val;
|
s->tx_buffer[s->tx_written++] = val;
|
||||||
@@ -214,7 +220,6 @@ static const VMStateDescription vmstate_mipsnet = {
|
|||||||
static NetClientInfo net_mipsnet_info = {
|
static NetClientInfo net_mipsnet_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = mipsnet_can_receive,
|
|
||||||
.receive = mipsnet_receive,
|
.receive = mipsnet_receive,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+12
-1
@@ -230,6 +230,9 @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
index = s->curpag << 8;
|
index = s->curpag << 8;
|
||||||
|
if (index >= NE2000_PMEM_END) {
|
||||||
|
index = s->start;
|
||||||
|
}
|
||||||
/* 4 bytes for header */
|
/* 4 bytes for header */
|
||||||
total_len = size + 4;
|
total_len = size + 4;
|
||||||
/* address for next packet (4 bytes for CRC) */
|
/* address for next packet (4 bytes for CRC) */
|
||||||
@@ -253,7 +256,7 @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
|
|||||||
if (index <= s->stop)
|
if (index <= s->stop)
|
||||||
avail = s->stop - index;
|
avail = s->stop - index;
|
||||||
else
|
else
|
||||||
avail = 0;
|
break;
|
||||||
len = size;
|
len = size;
|
||||||
if (len > avail)
|
if (len > avail)
|
||||||
len = avail;
|
len = avail;
|
||||||
@@ -315,13 +318,19 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
offset = addr | (page << 4);
|
offset = addr | (page << 4);
|
||||||
switch(offset) {
|
switch(offset) {
|
||||||
case EN0_STARTPG:
|
case EN0_STARTPG:
|
||||||
|
if (val << 8 <= NE2000_PMEM_END) {
|
||||||
s->start = val << 8;
|
s->start = val << 8;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EN0_STOPPG:
|
case EN0_STOPPG:
|
||||||
|
if (val << 8 <= NE2000_PMEM_END) {
|
||||||
s->stop = val << 8;
|
s->stop = val << 8;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EN0_BOUNDARY:
|
case EN0_BOUNDARY:
|
||||||
|
if (val << 8 < NE2000_PMEM_END) {
|
||||||
s->boundary = val;
|
s->boundary = val;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EN0_IMR:
|
case EN0_IMR:
|
||||||
s->imr = val;
|
s->imr = val;
|
||||||
@@ -362,7 +371,9 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
s->phys[offset - EN1_PHYS] = val;
|
s->phys[offset - EN1_PHYS] = val;
|
||||||
break;
|
break;
|
||||||
case EN1_CURPAG:
|
case EN1_CURPAG:
|
||||||
|
if (val << 8 < NE2000_PMEM_END) {
|
||||||
s->curpag = val;
|
s->curpag = val;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EN1_MULT ... EN1_MULT + 7:
|
case EN1_MULT ... EN1_MULT + 7:
|
||||||
s->mult[offset - EN1_MULT] = val;
|
s->mult[offset - EN1_MULT] = val;
|
||||||
|
|||||||
@@ -273,7 +273,6 @@ static void pci_pcnet_uninit(PCIDevice *dev)
|
|||||||
static NetClientInfo net_pci_pcnet_info = {
|
static NetClientInfo net_pci_pcnet_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = pcnet_can_receive,
|
|
||||||
.receive = pcnet_receive,
|
.receive = pcnet_receive,
|
||||||
.link_status_changed = pcnet_set_link_status,
|
.link_status_changed = pcnet_set_link_status,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -995,15 +995,6 @@ static int pcnet_tdte_poll(PCNetState *s)
|
|||||||
return !!(CSR_CXST(s) & 0x8000);
|
return !!(CSR_CXST(s) & 0x8000);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pcnet_can_receive(NetClientState *nc)
|
|
||||||
{
|
|
||||||
PCNetState *s = qemu_get_nic_opaque(nc);
|
|
||||||
if (CSR_STOP(s) || CSR_SPND(s))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return sizeof(s->buffer)-16;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MIN_BUF_SIZE 60
|
#define MIN_BUF_SIZE 60
|
||||||
|
|
||||||
ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
|
ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr);
|
|||||||
void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val);
|
void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val);
|
||||||
uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr);
|
uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr);
|
||||||
uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
|
uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
|
||||||
int pcnet_can_receive(NetClientState *nc);
|
|
||||||
ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_);
|
ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_);
|
||||||
void pcnet_set_link_status(NetClientState *nc);
|
void pcnet_set_link_status(NetClientState *nc);
|
||||||
void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info);
|
void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info);
|
||||||
|
|||||||
+39
-20
@@ -1148,7 +1148,9 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||||||
|
|
||||||
/* if receiver buffer is empty then avail == 0 */
|
/* if receiver buffer is empty then avail == 0 */
|
||||||
|
|
||||||
if (avail != 0 && size + 8 >= avail)
|
#define RX_ALIGN(x) (((x) + 3) & ~0x3)
|
||||||
|
|
||||||
|
if (avail != 0 && RX_ALIGN(size + 8) >= avail)
|
||||||
{
|
{
|
||||||
DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
|
DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
|
||||||
"read 0x%04x === available 0x%04x need 0x%04x\n",
|
"read 0x%04x === available 0x%04x need 0x%04x\n",
|
||||||
@@ -1157,7 +1159,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||||||
s->IntrStatus |= RxOverflow;
|
s->IntrStatus |= RxOverflow;
|
||||||
++s->RxMissed;
|
++s->RxMissed;
|
||||||
rtl8139_update_irq(s);
|
rtl8139_update_irq(s);
|
||||||
return size_;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet_header |= RxStatusOK;
|
packet_header |= RxStatusOK;
|
||||||
@@ -1176,7 +1178,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||||||
rtl8139_write_buffer(s, (uint8_t *)&val, 4);
|
rtl8139_write_buffer(s, (uint8_t *)&val, 4);
|
||||||
|
|
||||||
/* correct buffer write pointer */
|
/* correct buffer write pointer */
|
||||||
s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize);
|
s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize);
|
||||||
|
|
||||||
/* now we can signal we have received something */
|
/* now we can signal we have received something */
|
||||||
|
|
||||||
@@ -2150,6 +2152,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||||||
{
|
{
|
||||||
DPRINTF("+++ C+ mode offloaded task checksum\n");
|
DPRINTF("+++ C+ mode offloaded task checksum\n");
|
||||||
|
|
||||||
|
/* Large enough for Ethernet and IP headers? */
|
||||||
|
if (saved_size < ETH_HLEN + sizeof(ip_header)) {
|
||||||
|
goto skip_offload;
|
||||||
|
}
|
||||||
|
|
||||||
/* ip packet header */
|
/* ip packet header */
|
||||||
ip_header *ip = NULL;
|
ip_header *ip = NULL;
|
||||||
int hlen = 0;
|
int hlen = 0;
|
||||||
@@ -2160,8 +2167,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||||||
size_t eth_payload_len = 0;
|
size_t eth_payload_len = 0;
|
||||||
|
|
||||||
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
||||||
if (proto == ETH_P_IP)
|
if (proto != ETH_P_IP)
|
||||||
{
|
{
|
||||||
|
goto skip_offload;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF("+++ C+ mode has IP packet\n");
|
DPRINTF("+++ C+ mode has IP packet\n");
|
||||||
|
|
||||||
/* not aligned */
|
/* not aligned */
|
||||||
@@ -2174,35 +2184,39 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||||||
DPRINTF("+++ C+ mode packet has bad IP version %d "
|
DPRINTF("+++ C+ mode packet has bad IP version %d "
|
||||||
"expected %d\n", IP_HEADER_VERSION(ip),
|
"expected %d\n", IP_HEADER_VERSION(ip),
|
||||||
IP_HEADER_VERSION_4);
|
IP_HEADER_VERSION_4);
|
||||||
ip = NULL;
|
goto skip_offload;
|
||||||
} else {
|
|
||||||
hlen = IP_HEADER_LENGTH(ip);
|
|
||||||
ip_protocol = ip->ip_p;
|
|
||||||
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip)
|
hlen = IP_HEADER_LENGTH(ip);
|
||||||
{
|
if (hlen < sizeof(ip_header) || hlen > eth_payload_len) {
|
||||||
|
goto skip_offload;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_protocol = ip->ip_p;
|
||||||
|
|
||||||
|
ip_data_len = be16_to_cpu(ip->ip_len);
|
||||||
|
if (ip_data_len < hlen || ip_data_len > eth_payload_len) {
|
||||||
|
goto skip_offload;
|
||||||
|
}
|
||||||
|
ip_data_len -= hlen;
|
||||||
|
|
||||||
if (txdw0 & CP_TX_IPCS)
|
if (txdw0 & CP_TX_IPCS)
|
||||||
{
|
{
|
||||||
DPRINTF("+++ C+ mode need IP checksum\n");
|
DPRINTF("+++ C+ mode need IP checksum\n");
|
||||||
|
|
||||||
if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
|
||||||
/* bad packet header len */
|
|
||||||
/* or packet too short */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ip->ip_sum = 0;
|
ip->ip_sum = 0;
|
||||||
ip->ip_sum = ip_checksum(ip, hlen);
|
ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
||||||
hlen, ip->ip_sum);
|
hlen, ip->ip_sum);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
||||||
{
|
{
|
||||||
|
/* Large enough for the TCP header? */
|
||||||
|
if (ip_data_len < sizeof(tcp_header)) {
|
||||||
|
goto skip_offload;
|
||||||
|
}
|
||||||
|
|
||||||
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
||||||
|
|
||||||
DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
||||||
@@ -2227,6 +2241,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||||||
|
|
||||||
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
|
||||||
|
/* Invalid TCP data offset? */
|
||||||
|
if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) {
|
||||||
|
goto skip_offload;
|
||||||
|
}
|
||||||
|
|
||||||
/* ETH_MTU = ip header len + tcp header len + payload */
|
/* ETH_MTU = ip header len + tcp header len + payload */
|
||||||
int tcp_data_len = ip_data_len - tcp_hlen;
|
int tcp_data_len = ip_data_len - tcp_hlen;
|
||||||
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
||||||
@@ -2375,8 +2394,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||||||
memcpy(eth_payload_data, saved_ip_header, hlen);
|
memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
skip_offload:
|
||||||
/* update tally counter */
|
/* update tally counter */
|
||||||
++s->tally_counters.TxOk;
|
++s->tally_counters.TxOk;
|
||||||
|
|
||||||
|
|||||||
@@ -228,8 +228,7 @@ static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, si
|
|||||||
if ((s->rctl & SE_RCTL_RXEN) == 0)
|
if ((s->rctl & SE_RCTL_RXEN) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (s->np >= 31) {
|
if (s->np >= 31) {
|
||||||
DPRINTF("Packet dropped\n");
|
return 0;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF("Received packet len=%zu\n", size);
|
DPRINTF("Received packet len=%zu\n", size);
|
||||||
@@ -260,13 +259,8 @@ static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, si
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stellaris_enet_can_receive(NetClientState *nc)
|
static int stellaris_enet_can_receive(stellaris_enet_state *s)
|
||||||
{
|
{
|
||||||
stellaris_enet_state *s = qemu_get_nic_opaque(nc);
|
|
||||||
|
|
||||||
if ((s->rctl & SE_RCTL_RXEN) == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return (s->np < 31);
|
return (s->np < 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,6 +301,9 @@ static uint64_t stellaris_enet_read(void *opaque, hwaddr offset,
|
|||||||
s->next_packet = 0;
|
s->next_packet = 0;
|
||||||
s->np--;
|
s->np--;
|
||||||
DPRINTF("RX done np=%d\n", s->np);
|
DPRINTF("RX done np=%d\n", s->np);
|
||||||
|
if (!s->np && stellaris_enet_can_receive(s)) {
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(s->nic));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@@ -454,7 +451,6 @@ static void stellaris_enet_reset(stellaris_enet_state *s)
|
|||||||
static NetClientInfo net_stellaris_enet_info = {
|
static NetClientInfo net_stellaris_enet_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = stellaris_enet_can_receive,
|
|
||||||
.receive = stellaris_enet_receive,
|
.receive = stellaris_enet_receive,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -197,7 +197,7 @@ static int vhost_net_set_vnet_endian(VirtIODevice *dev, NetClientState *peer,
|
|||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (virtio_has_feature(dev, VIRTIO_F_VERSION_1) ||
|
if (virtio_vdev_has_feature(dev, VIRTIO_F_VERSION_1) ||
|
||||||
(virtio_legacy_is_cross_endian(dev) && !virtio_is_big_endian(dev))) {
|
(virtio_legacy_is_cross_endian(dev) && !virtio_is_big_endian(dev))) {
|
||||||
r = qemu_set_vnet_le(peer, set);
|
r = qemu_set_vnet_le(peer, set);
|
||||||
if (r) {
|
if (r) {
|
||||||
|
|||||||
+37
-37
@@ -86,8 +86,8 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
|
|||||||
|
|
||||||
memcpy(&netcfg, config, n->config_size);
|
memcpy(&netcfg, config, n->config_size);
|
||||||
|
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) &&
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) &&
|
||||||
!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
||||||
memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
|
memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
|
||||||
memcpy(n->mac, netcfg.mac, ETH_ALEN);
|
memcpy(n->mac, netcfg.mac, ETH_ALEN);
|
||||||
qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
|
qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
|
||||||
@@ -304,7 +304,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
|
|||||||
info->multicast_table = str_list;
|
info->multicast_table = str_list;
|
||||||
info->vlan_table = get_vlan_table(n);
|
info->vlan_table = get_vlan_table(n);
|
||||||
|
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) {
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) {
|
||||||
info->vlan = RX_STATE_ALL;
|
info->vlan = RX_STATE_ALL;
|
||||||
} else if (!info->vlan_table) {
|
} else if (!info->vlan_table) {
|
||||||
info->vlan = RX_STATE_NONE;
|
info->vlan = RX_STATE_NONE;
|
||||||
@@ -446,7 +446,8 @@ static void virtio_net_set_queues(VirtIONet *n)
|
|||||||
|
|
||||||
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
|
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
|
||||||
|
|
||||||
static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
|
static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
VirtIONet *n = VIRTIO_NET(vdev);
|
VirtIONet *n = VIRTIO_NET(vdev);
|
||||||
NetClientState *nc = qemu_get_queue(n->nic);
|
NetClientState *nc = qemu_get_queue(n->nic);
|
||||||
@@ -528,12 +529,12 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
virtio_net_set_multiqueue(n,
|
virtio_net_set_multiqueue(n,
|
||||||
__virtio_has_feature(features, VIRTIO_NET_F_MQ));
|
virtio_has_feature(features, VIRTIO_NET_F_MQ));
|
||||||
|
|
||||||
virtio_net_set_mrg_rx_bufs(n,
|
virtio_net_set_mrg_rx_bufs(n,
|
||||||
__virtio_has_feature(features,
|
virtio_has_feature(features,
|
||||||
VIRTIO_NET_F_MRG_RXBUF),
|
VIRTIO_NET_F_MRG_RXBUF),
|
||||||
__virtio_has_feature(features,
|
virtio_has_feature(features,
|
||||||
VIRTIO_F_VERSION_1));
|
VIRTIO_F_VERSION_1));
|
||||||
|
|
||||||
if (n->has_vnet_hdr) {
|
if (n->has_vnet_hdr) {
|
||||||
@@ -551,7 +552,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
|
|||||||
vhost_net_ack_features(get_vhost_net(nc->peer), features);
|
vhost_net_ack_features(get_vhost_net(nc->peer), features);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) {
|
if (virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) {
|
||||||
memset(n->vlans, 0, MAX_VLAN >> 3);
|
memset(n->vlans, 0, MAX_VLAN >> 3);
|
||||||
} else {
|
} else {
|
||||||
memset(n->vlans, 0xff, MAX_VLAN >> 3);
|
memset(n->vlans, 0xff, MAX_VLAN >> 3);
|
||||||
@@ -598,7 +599,7 @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
|
|||||||
uint64_t offloads;
|
uint64_t offloads;
|
||||||
size_t s;
|
size_t s;
|
||||||
|
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
|
||||||
return VIRTIO_NET_ERR;
|
return VIRTIO_NET_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1085,13 +1086,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||||||
* must have consumed the complete packet.
|
* must have consumed the complete packet.
|
||||||
* Otherwise, drop it. */
|
* Otherwise, drop it. */
|
||||||
if (!n->mergeable_rx_bufs && offset < size) {
|
if (!n->mergeable_rx_bufs && offset < size) {
|
||||||
#if 0
|
virtqueue_discard(q->rx_vq, &elem, total);
|
||||||
error_report("virtio-net truncated non-mergeable packet: "
|
|
||||||
"i %zd mergeable %d offset %zd, size %zd, "
|
|
||||||
"guest hdr len %zd, host hdr len %zd",
|
|
||||||
i, n->mergeable_rx_bufs,
|
|
||||||
offset, size, n->guest_hdr_len, n->host_hdr_len);
|
|
||||||
#endif
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1452,7 +1447,7 @@ static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
|
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
|
||||||
qemu_put_be64(f, n->curr_guest_offloads);
|
qemu_put_be64(f, n->curr_guest_offloads);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1461,11 +1456,33 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
{
|
{
|
||||||
VirtIONet *n = opaque;
|
VirtIONet *n = opaque;
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
|
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return virtio_load(vdev, f, version_id);
|
ret = virtio_load(vdev, f, version_id);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
|
||||||
|
n->curr_guest_offloads = qemu_get_be64(f);
|
||||||
|
} else {
|
||||||
|
n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer_has_vnet_hdr(n)) {
|
||||||
|
virtio_net_apply_guest_offloads(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
|
||||||
|
virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
|
||||||
|
n->announce_counter = SELF_ANNOUNCE_ROUNDS;
|
||||||
|
timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
||||||
@@ -1478,7 +1495,8 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
|||||||
n->vqs[0].tx_waiting = qemu_get_be32(f);
|
n->vqs[0].tx_waiting = qemu_get_be32(f);
|
||||||
|
|
||||||
virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f),
|
virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f),
|
||||||
virtio_has_feature(vdev, VIRTIO_F_VERSION_1));
|
virtio_vdev_has_feature(vdev,
|
||||||
|
VIRTIO_F_VERSION_1));
|
||||||
|
|
||||||
if (version_id >= 3)
|
if (version_id >= 3)
|
||||||
n->status = qemu_get_be16(f);
|
n->status = qemu_get_be16(f);
|
||||||
@@ -1561,16 +1579,6 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
|
|
||||||
n->curr_guest_offloads = qemu_get_be64(f);
|
|
||||||
} else {
|
|
||||||
n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (peer_has_vnet_hdr(n)) {
|
|
||||||
virtio_net_apply_guest_offloads(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtio_net_set_queues(n);
|
virtio_net_set_queues(n);
|
||||||
|
|
||||||
/* Find the first multicast entry in the saved MAC filter */
|
/* Find the first multicast entry in the saved MAC filter */
|
||||||
@@ -1588,12 +1596,6 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
|||||||
qemu_get_subqueue(n->nic, i)->link_down = link_down;
|
qemu_get_subqueue(n->nic, i)->link_down = link_down;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
|
|
||||||
virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
|
|
||||||
n->announce_counter = SELF_ANNOUNCE_ROUNDS;
|
|
||||||
timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1777,8 +1779,6 @@ static void virtio_net_instance_init(Object *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Property virtio_net_properties[] = {
|
static Property virtio_net_properties[] = {
|
||||||
DEFINE_PROP_BIT("any_layout", VirtIONet, host_features,
|
|
||||||
VIRTIO_F_ANY_LAYOUT, true),
|
|
||||||
DEFINE_PROP_BIT("csum", VirtIONet, host_features, VIRTIO_NET_F_CSUM, true),
|
DEFINE_PROP_BIT("csum", VirtIONet, host_features, VIRTIO_NET_F_CSUM, true),
|
||||||
DEFINE_PROP_BIT("guest_csum", VirtIONet, host_features,
|
DEFINE_PROP_BIT("guest_csum", VirtIONet, host_features,
|
||||||
VIRTIO_NET_F_GUEST_CSUM, true),
|
VIRTIO_NET_F_GUEST_CSUM, true),
|
||||||
|
|||||||
@@ -1988,7 +1988,6 @@ static void vmxnet3_set_link_status(NetClientState *nc)
|
|||||||
static NetClientInfo net_vmxnet3_info = {
|
static NetClientInfo net_vmxnet3_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = vmxnet3_can_receive,
|
|
||||||
.receive = vmxnet3_receive,
|
.receive = vmxnet3_receive,
|
||||||
.link_status_changed = vmxnet3_set_link_status,
|
.link_status_changed = vmxnet3_set_link_status,
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-24
@@ -234,27 +234,6 @@ static void net_rx_response(struct XenNetDev *netdev,
|
|||||||
|
|
||||||
#define NET_IP_ALIGN 2
|
#define NET_IP_ALIGN 2
|
||||||
|
|
||||||
static int net_rx_ok(NetClientState *nc)
|
|
||||||
{
|
|
||||||
struct XenNetDev *netdev = qemu_get_nic_opaque(nc);
|
|
||||||
RING_IDX rc, rp;
|
|
||||||
|
|
||||||
if (netdev->xendev.be_state != XenbusStateConnected) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = netdev->rx_ring.req_cons;
|
|
||||||
rp = netdev->rx_ring.sring->req_prod;
|
|
||||||
xen_rmb();
|
|
||||||
|
|
||||||
if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
|
|
||||||
xen_be_printf(&netdev->xendev, 2, "%s: no rx buffers (%d/%d)\n",
|
|
||||||
__FUNCTION__, rc, rp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size)
|
static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct XenNetDev *netdev = qemu_get_nic_opaque(nc);
|
struct XenNetDev *netdev = qemu_get_nic_opaque(nc);
|
||||||
@@ -271,8 +250,7 @@ static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size
|
|||||||
xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
|
xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
|
||||||
|
|
||||||
if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
|
if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
|
||||||
xen_be_printf(&netdev->xendev, 2, "no buffer, drop packet\n");
|
return 0;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (size > XC_PAGE_SIZE - NET_IP_ALIGN) {
|
if (size > XC_PAGE_SIZE - NET_IP_ALIGN) {
|
||||||
xen_be_printf(&netdev->xendev, 0, "packet too big (%lu > %ld)",
|
xen_be_printf(&netdev->xendev, 0, "packet too big (%lu > %ld)",
|
||||||
@@ -304,7 +282,6 @@ static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size
|
|||||||
static NetClientInfo net_xen_info = {
|
static NetClientInfo net_xen_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = net_rx_ok,
|
|
||||||
.receive = net_rx_packet,
|
.receive = net_rx_packet,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -312,10 +312,8 @@ static const MemoryRegionOps enet_mem_ops = {
|
|||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int eth_can_rx(NetClientState *nc)
|
static int eth_can_rx(XgmacState *s)
|
||||||
{
|
{
|
||||||
XgmacState *s = qemu_get_nic_opaque(nc);
|
|
||||||
|
|
||||||
/* RX enabled? */
|
/* RX enabled? */
|
||||||
return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
|
return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
|
||||||
}
|
}
|
||||||
@@ -329,6 +327,9 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
|
|||||||
struct desc bd;
|
struct desc bd;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
|
if (!eth_can_rx(s)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
unicast = ~buf[0] & 0x1;
|
unicast = ~buf[0] & 0x1;
|
||||||
broadcast = memcmp(buf, sa_bcast, 6) == 0;
|
broadcast = memcmp(buf, sa_bcast, 6) == 0;
|
||||||
multicast = !unicast && !broadcast;
|
multicast = !unicast && !broadcast;
|
||||||
@@ -371,7 +372,6 @@ out:
|
|||||||
static NetClientInfo net_xgmac_enet_info = {
|
static NetClientInfo net_xgmac_enet_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = eth_can_rx,
|
|
||||||
.receive = eth_rx,
|
.receive = eth_rx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+13
-4
@@ -401,6 +401,9 @@ struct XilinxAXIEnet {
|
|||||||
|
|
||||||
uint8_t rxapp[CONTROL_PAYLOAD_SIZE];
|
uint8_t rxapp[CONTROL_PAYLOAD_SIZE];
|
||||||
uint32_t rxappsize;
|
uint32_t rxappsize;
|
||||||
|
|
||||||
|
/* Whether axienet_eth_rx_notify should flush incoming queue. */
|
||||||
|
bool need_flush;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void axienet_rx_reset(XilinxAXIEnet *s)
|
static void axienet_rx_reset(XilinxAXIEnet *s)
|
||||||
@@ -658,10 +661,8 @@ static const MemoryRegionOps enet_ops = {
|
|||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int eth_can_rx(NetClientState *nc)
|
static int eth_can_rx(XilinxAXIEnet *s)
|
||||||
{
|
{
|
||||||
XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
|
|
||||||
|
|
||||||
/* RX enabled? */
|
/* RX enabled? */
|
||||||
return !s->rxsize && !axienet_rx_resetting(s) && axienet_rx_enabled(s);
|
return !s->rxsize && !axienet_rx_resetting(s) && axienet_rx_enabled(s);
|
||||||
}
|
}
|
||||||
@@ -701,6 +702,10 @@ static void axienet_eth_rx_notify(void *opaque)
|
|||||||
s->rxpos += ret;
|
s->rxpos += ret;
|
||||||
if (!s->rxsize) {
|
if (!s->rxsize) {
|
||||||
s->regs[R_IS] |= IS_RX_COMPLETE;
|
s->regs[R_IS] |= IS_RX_COMPLETE;
|
||||||
|
if (s->need_flush) {
|
||||||
|
s->need_flush = false;
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(s->nic));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enet_update_irq(s);
|
enet_update_irq(s);
|
||||||
@@ -721,6 +726,11 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
|
|||||||
|
|
||||||
DENET(qemu_log("%s: %zd bytes\n", __func__, size));
|
DENET(qemu_log("%s: %zd bytes\n", __func__, size));
|
||||||
|
|
||||||
|
if (!eth_can_rx(s)) {
|
||||||
|
s->need_flush = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unicast = ~buf[0] & 0x1;
|
unicast = ~buf[0] & 0x1;
|
||||||
broadcast = memcmp(buf, sa_bcast, 6) == 0;
|
broadcast = memcmp(buf, sa_bcast, 6) == 0;
|
||||||
multicast = !unicast && !broadcast;
|
multicast = !unicast && !broadcast;
|
||||||
@@ -925,7 +935,6 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
|
|||||||
static NetClientInfo net_xilinx_enet_info = {
|
static NetClientInfo net_xilinx_enet_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = eth_can_rx,
|
|
||||||
.receive = eth_rx,
|
.receive = eth_rx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -500,6 +500,8 @@ static void pci_vpb_class_init(ObjectClass *klass, void *data)
|
|||||||
dc->reset = pci_vpb_reset;
|
dc->reset = pci_vpb_reset;
|
||||||
dc->vmsd = &pci_vpb_vmstate;
|
dc->vmsd = &pci_vpb_vmstate;
|
||||||
dc->props = pci_vpb_properties;
|
dc->props = pci_vpb_properties;
|
||||||
|
/* Reason: object_unref() hangs */
|
||||||
|
dc->cannot_destroy_with_object_finalize_yet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pci_vpb_info = {
|
static const TypeInfo pci_vpb_info = {
|
||||||
@@ -521,10 +523,19 @@ static void pci_realview_init(Object *obj)
|
|||||||
s->mem_win_size[2] = 0x08000000;
|
s->mem_win_size[2] = 0x08000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pci_realview_class_init(ObjectClass *class, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(class);
|
||||||
|
|
||||||
|
/* Reason: object_unref() hangs */
|
||||||
|
dc->cannot_destroy_with_object_finalize_yet = true;
|
||||||
|
}
|
||||||
|
|
||||||
static const TypeInfo pci_realview_info = {
|
static const TypeInfo pci_realview_info = {
|
||||||
.name = "realview_pci",
|
.name = "realview_pci",
|
||||||
.parent = TYPE_VERSATILE_PCI,
|
.parent = TYPE_VERSATILE_PCI,
|
||||||
.instance_init = pci_realview_init,
|
.instance_init = pci_realview_init,
|
||||||
|
.class_init = pci_realview_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void versatile_pci_register_types(void)
|
static void versatile_pci_register_types(void)
|
||||||
|
|||||||
+3
-3
@@ -163,7 +163,7 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
|
|||||||
sysbus_init_mmio(sbd, &s->container_mem);
|
sysbus_init_mmio(sbd, &s->container_mem);
|
||||||
|
|
||||||
/* Socket I/O Memory Space */
|
/* Socket I/O Memory Space */
|
||||||
memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
|
memory_region_init_io(&s->iomem, obj, &pxa2xx_pcmcia_io_ops, s,
|
||||||
"pxa2xx-pcmcia-io", 0x04000000);
|
"pxa2xx-pcmcia-io", 0x04000000);
|
||||||
memory_region_add_subregion(&s->container_mem, 0x00000000,
|
memory_region_add_subregion(&s->container_mem, 0x00000000,
|
||||||
&s->iomem);
|
&s->iomem);
|
||||||
@@ -171,13 +171,13 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
|
|||||||
/* Then next 64 MB is reserved */
|
/* Then next 64 MB is reserved */
|
||||||
|
|
||||||
/* Socket Attribute Memory Space */
|
/* Socket Attribute Memory Space */
|
||||||
memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
|
memory_region_init_io(&s->attr_iomem, obj, &pxa2xx_pcmcia_attr_ops, s,
|
||||||
"pxa2xx-pcmcia-attribute", 0x04000000);
|
"pxa2xx-pcmcia-attribute", 0x04000000);
|
||||||
memory_region_add_subregion(&s->container_mem, 0x08000000,
|
memory_region_add_subregion(&s->container_mem, 0x08000000,
|
||||||
&s->attr_iomem);
|
&s->attr_iomem);
|
||||||
|
|
||||||
/* Socket Common Memory Space */
|
/* Socket Common Memory Space */
|
||||||
memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
|
memory_region_init_io(&s->common_iomem, obj, &pxa2xx_pcmcia_common_ops, s,
|
||||||
"pxa2xx-pcmcia-common", 0x04000000);
|
"pxa2xx-pcmcia-common", 0x04000000);
|
||||||
memory_region_add_subregion(&s->container_mem, 0x0c000000,
|
memory_region_add_subregion(&s->container_mem, 0x0c000000,
|
||||||
&s->common_iomem);
|
&s->common_iomem);
|
||||||
|
|||||||
+10
-2
@@ -955,6 +955,7 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
|
|||||||
int pci_status, err;
|
int pci_status, err;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev);
|
uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev);
|
||||||
|
uint32_t max_msi, max_msix;
|
||||||
|
|
||||||
if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
|
if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
|
||||||
PCI_HEADER_TYPE_BRIDGE) {
|
PCI_HEADER_TYPE_BRIDGE) {
|
||||||
@@ -1035,8 +1036,15 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
|
|||||||
RESOURCE_CELLS_ADDRESS));
|
RESOURCE_CELLS_ADDRESS));
|
||||||
_FDT(fdt_setprop_cell(fdt, offset, "#size-cells",
|
_FDT(fdt_setprop_cell(fdt, offset, "#size-cells",
|
||||||
RESOURCE_CELLS_SIZE));
|
RESOURCE_CELLS_SIZE));
|
||||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x",
|
|
||||||
RESOURCE_CELLS_SIZE));
|
max_msi = msi_nr_vectors_allocated(dev);
|
||||||
|
if (max_msi) {
|
||||||
|
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi));
|
||||||
|
}
|
||||||
|
max_msix = dev->msix_entries_nr;
|
||||||
|
if (max_msix) {
|
||||||
|
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix));
|
||||||
|
}
|
||||||
|
|
||||||
populate_resource_props(dev, &rp);
|
populate_resource_props(dev, &rp);
|
||||||
_FDT(fdt_setprop(fdt, offset, "reg", (uint8_t *)rp.reg, rp.reg_len));
|
_FDT(fdt_setprop(fdt, offset, "reg", (uint8_t *)rp.reg, rp.reg_len));
|
||||||
|
|||||||
@@ -392,6 +392,8 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
|
|||||||
path = 0x80;
|
path = 0x80;
|
||||||
|
|
||||||
if (!(s->ctrl & SCSW_ACTL_SUSP)) {
|
if (!(s->ctrl & SCSW_ACTL_SUSP)) {
|
||||||
|
s->cstat = 0;
|
||||||
|
s->dstat = 0;
|
||||||
/* Look at the orb and try to execute the channel program. */
|
/* Look at the orb and try to execute the channel program. */
|
||||||
assert(orb != NULL); /* resume does not pass an orb */
|
assert(orb != NULL); /* resume does not pass an orb */
|
||||||
p->intparm = orb->intparm;
|
p->intparm = orb->intparm;
|
||||||
|
|||||||
@@ -2202,8 +2202,15 @@ static uint64_t megasas_queue_read(void *opaque, hwaddr addr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void megasas_queue_write(void *opaque, hwaddr addr,
|
||||||
|
uint64_t val, unsigned size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static const MemoryRegionOps megasas_queue_ops = {
|
static const MemoryRegionOps megasas_queue_ops = {
|
||||||
.read = megasas_queue_read,
|
.read = megasas_queue_read,
|
||||||
|
.write = megasas_queue_write,
|
||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
.impl = {
|
.impl = {
|
||||||
.min_access_size = 8,
|
.min_access_size = 8,
|
||||||
|
|||||||
+6
-1
@@ -1239,10 +1239,15 @@ int scsi_cdb_length(uint8_t *buf) {
|
|||||||
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
|
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
int len;
|
||||||
|
|
||||||
cmd->lba = -1;
|
cmd->lba = -1;
|
||||||
cmd->len = scsi_cdb_length(buf);
|
len = scsi_cdb_length(buf);
|
||||||
|
if (len < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->len = len;
|
||||||
switch (dev->type) {
|
switch (dev->type) {
|
||||||
case TYPE_TAPE:
|
case TYPE_TAPE:
|
||||||
rc = scsi_req_stream_xfer(cmd, dev, buf);
|
rc = scsi_req_stream_xfer(cmd, dev, buf);
|
||||||
|
|||||||
+19
-1
@@ -765,6 +765,9 @@ static inline bool media_is_dvd(SCSIDiskState *s)
|
|||||||
if (!blk_is_inserted(s->qdev.conf.blk)) {
|
if (!blk_is_inserted(s->qdev.conf.blk)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (s->tray_open) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
|
blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
|
||||||
return nb_sectors > CD_MAX_SECTORS;
|
return nb_sectors > CD_MAX_SECTORS;
|
||||||
}
|
}
|
||||||
@@ -778,6 +781,9 @@ static inline bool media_is_cd(SCSIDiskState *s)
|
|||||||
if (!blk_is_inserted(s->qdev.conf.blk)) {
|
if (!blk_is_inserted(s->qdev.conf.blk)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (s->tray_open) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
|
blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
|
||||||
return nb_sectors <= CD_MAX_SECTORS;
|
return nb_sectors <= CD_MAX_SECTORS;
|
||||||
}
|
}
|
||||||
@@ -975,7 +981,15 @@ static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
|
|||||||
if (s->qdev.type != TYPE_ROM) {
|
if (s->qdev.type != TYPE_ROM) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
|
|
||||||
|
if (media_is_dvd(s)) {
|
||||||
|
current = MMC_PROFILE_DVD_ROM;
|
||||||
|
} else if (media_is_cd(s)) {
|
||||||
|
current = MMC_PROFILE_CD_ROM;
|
||||||
|
} else {
|
||||||
|
current = MMC_PROFILE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
memset(outbuf, 0, 40);
|
memset(outbuf, 0, 40);
|
||||||
stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
|
stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
|
||||||
stw_be_p(&outbuf[6], current);
|
stw_be_p(&outbuf[6], current);
|
||||||
@@ -1669,6 +1683,10 @@ static void scsi_write_same_complete(void *opaque, int ret)
|
|||||||
if (data->iov.iov_len) {
|
if (data->iov.iov_len) {
|
||||||
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
|
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
|
||||||
data->iov.iov_len, BLOCK_ACCT_WRITE);
|
data->iov.iov_len, BLOCK_ACCT_WRITE);
|
||||||
|
/* blk_aio_write doesn't like the qiov size being different from
|
||||||
|
* nb_sectors, make sure they match.
|
||||||
|
*/
|
||||||
|
qemu_iovec_init_external(&data->qiov, &data->iov, 1);
|
||||||
r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector,
|
r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector,
|
||||||
&data->qiov, data->iov.iov_len / 512,
|
&data->qiov, data->iov.iov_len / 512,
|
||||||
scsi_write_same_complete, data);
|
scsi_write_same_complete, data);
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ static void vhost_scsi_stop(VHostSCSI *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t vhost_scsi_get_features(VirtIODevice *vdev,
|
static uint64_t vhost_scsi_get_features(VirtIODevice *vdev,
|
||||||
uint64_t features)
|
uint64_t features,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
VHostSCSI *s = VHOST_SCSI(vdev);
|
VHostSCSI *s = VHOST_SCSI(vdev);
|
||||||
|
|
||||||
@@ -290,7 +291,7 @@ static char *vhost_scsi_get_fw_dev_path(FWPathProvider *p, BusState *bus,
|
|||||||
{
|
{
|
||||||
VHostSCSI *s = VHOST_SCSI(dev);
|
VHostSCSI *s = VHOST_SCSI(dev);
|
||||||
/* format: channel@channel/vhost-scsi@target,lun */
|
/* format: channel@channel/vhost-scsi@target,lun */
|
||||||
return g_strdup_printf("channel@%x/%s@%x,%x", s->channel,
|
return g_strdup_printf("/channel@%x/%s@%x,%x", s->channel,
|
||||||
qdev_fw_name(dev), s->target, s->lun);
|
qdev_fw_name(dev), s->target, s->lun);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-7
@@ -145,7 +145,7 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
|
|||||||
*
|
*
|
||||||
* TODO: always disable this workaround for virtio 1.0 devices.
|
* TODO: always disable this workaround for virtio 1.0 devices.
|
||||||
*/
|
*/
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) {
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) {
|
||||||
if (req->elem.out_num) {
|
if (req->elem.out_num) {
|
||||||
req_size = req->elem.out_sg[0].iov_len;
|
req_size = req->elem.out_sg[0].iov_len;
|
||||||
}
|
}
|
||||||
@@ -629,7 +629,8 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t virtio_scsi_get_features(VirtIODevice *vdev,
|
static uint64_t virtio_scsi_get_features(VirtIODevice *vdev,
|
||||||
uint64_t requested_features)
|
uint64_t requested_features,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
||||||
|
|
||||||
@@ -661,6 +662,11 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
|
|||||||
static void virtio_scsi_save(QEMUFile *f, void *opaque)
|
static void virtio_scsi_save(QEMUFile *f, void *opaque)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
||||||
|
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
||||||
|
|
||||||
|
if (s->dataplane_started) {
|
||||||
|
virtio_scsi_dataplane_stop(s);
|
||||||
|
}
|
||||||
virtio_save(vdev, f);
|
virtio_save(vdev, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,7 +759,7 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
|
|||||||
VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
|
VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
||||||
|
|
||||||
if (virtio_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) &&
|
if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) &&
|
||||||
dev->type != TYPE_ROM) {
|
dev->type != TYPE_ROM) {
|
||||||
virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
|
virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
|
||||||
sense.asc | (sense.ascq << 8));
|
sense.asc | (sense.ascq << 8));
|
||||||
@@ -777,7 +783,7 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||||||
aio_context_release(s->ctx);
|
aio_context_release(s->ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
|
if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
|
||||||
virtio_scsi_push_event(s, sd,
|
virtio_scsi_push_event(s, sd,
|
||||||
VIRTIO_SCSI_T_TRANSPORT_RESET,
|
VIRTIO_SCSI_T_TRANSPORT_RESET,
|
||||||
VIRTIO_SCSI_EVT_RESET_RESCAN);
|
VIRTIO_SCSI_EVT_RESET_RESCAN);
|
||||||
@@ -791,7 +797,7 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||||||
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
||||||
SCSIDevice *sd = SCSI_DEVICE(dev);
|
SCSIDevice *sd = SCSI_DEVICE(dev);
|
||||||
|
|
||||||
if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
|
if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
|
||||||
virtio_scsi_push_event(s, sd,
|
virtio_scsi_push_event(s, sd,
|
||||||
VIRTIO_SCSI_T_TRANSPORT_RESET,
|
VIRTIO_SCSI_T_TRANSPORT_RESET,
|
||||||
VIRTIO_SCSI_EVT_RESET_REMOVED);
|
VIRTIO_SCSI_EVT_RESET_REMOVED);
|
||||||
@@ -953,8 +959,6 @@ static Property virtio_scsi_properties[] = {
|
|||||||
0xFFFF),
|
0xFFFF),
|
||||||
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun,
|
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun,
|
||||||
128),
|
128),
|
||||||
DEFINE_PROP_BIT("any_layout", VirtIOSCSI, host_features,
|
|
||||||
VIRTIO_F_ANY_LAYOUT, true),
|
|
||||||
DEFINE_PROP_BIT("hotplug", VirtIOSCSI, host_features,
|
DEFINE_PROP_BIT("hotplug", VirtIOSCSI, host_features,
|
||||||
VIRTIO_SCSI_F_HOTPLUG, true),
|
VIRTIO_SCSI_F_HOTPLUG, true),
|
||||||
DEFINE_PROP_BIT("param_change", VirtIOSCSI, host_features,
|
DEFINE_PROP_BIT("param_change", VirtIOSCSI, host_features,
|
||||||
|
|||||||
+4
-16
@@ -1268,6 +1268,10 @@ static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t siz
|
|||||||
uint8_t *in_buf = s->in_buf;
|
uint8_t *in_buf = s->in_buf;
|
||||||
size_t total_size = size;
|
size_t total_size = size;
|
||||||
|
|
||||||
|
if (!s->dev.config) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_rndis(s)) {
|
if (is_rndis(s)) {
|
||||||
if (s->rndis_state != RNDIS_DATA_INITIALIZED) {
|
if (s->rndis_state != RNDIS_DATA_INITIALIZED) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1309,21 +1313,6 @@ static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t siz
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbnet_can_receive(NetClientState *nc)
|
|
||||||
{
|
|
||||||
USBNetState *s = qemu_get_nic_opaque(nc);
|
|
||||||
|
|
||||||
if (!s->dev.config) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !s->in_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usbnet_cleanup(NetClientState *nc)
|
static void usbnet_cleanup(NetClientState *nc)
|
||||||
{
|
{
|
||||||
USBNetState *s = qemu_get_nic_opaque(nc);
|
USBNetState *s = qemu_get_nic_opaque(nc);
|
||||||
@@ -1343,7 +1332,6 @@ static void usb_net_handle_destroy(USBDevice *dev)
|
|||||||
static NetClientInfo net_usbnet_info = {
|
static NetClientInfo net_usbnet_info = {
|
||||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
.can_receive = usbnet_can_receive,
|
|
||||||
.receive = usbnet_receive,
|
.receive = usbnet_receive,
|
||||||
.cleanup = usbnet_cleanup,
|
.cleanup = usbnet_cleanup,
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-8
@@ -1517,7 +1517,7 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque,
|
|||||||
memory_region_name(&quirk->mem),
|
memory_region_name(&quirk->mem),
|
||||||
vdev->vbasedev.name);
|
vdev->vbasedev.name);
|
||||||
|
|
||||||
return quirk->data.address_match ^ 0x10000000U;
|
return quirk->data.address_match ^ 0x80000000U;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0: /* data */
|
case 0: /* data */
|
||||||
@@ -1558,7 +1558,7 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
|
|||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 4: /* address */
|
case 4: /* address */
|
||||||
if ((data & 0x7fff0000) == 0x10000) {
|
if ((data & 0x7fff0000) == 0x10000) {
|
||||||
if (data & 0x10000000U &&
|
if (data & 0x80000000U &&
|
||||||
vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) {
|
vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) {
|
||||||
|
|
||||||
trace_vfio_rtl8168_window_quirk_write_table(
|
trace_vfio_rtl8168_window_quirk_write_table(
|
||||||
@@ -1566,11 +1566,9 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
|
|||||||
vdev->vbasedev.name);
|
vdev->vbasedev.name);
|
||||||
|
|
||||||
memory_region_dispatch_write(&vdev->pdev.msix_table_mmio,
|
memory_region_dispatch_write(&vdev->pdev.msix_table_mmio,
|
||||||
(hwaddr)(quirk->data.address_match
|
(hwaddr)(data & 0xfff),
|
||||||
& 0xfff),
|
(uint64_t)quirk->data.address_mask,
|
||||||
data,
|
size, MEMTXATTRS_UNSPECIFIED);
|
||||||
size,
|
|
||||||
MEMTXATTRS_UNSPECIFIED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quirk->data.flags = 1;
|
quirk->data.flags = 1;
|
||||||
@@ -3751,7 +3749,6 @@ static Property vfio_pci_dev_properties[] = {
|
|||||||
VFIO_FEATURE_ENABLE_VGA_BIT, false),
|
VFIO_FEATURE_ENABLE_VGA_BIT, false),
|
||||||
DEFINE_PROP_BIT("x-req", VFIOPCIDevice, features,
|
DEFINE_PROP_BIT("x-req", VFIOPCIDevice, features,
|
||||||
VFIO_FEATURE_ENABLE_REQ_BIT, true),
|
VFIO_FEATURE_ENABLE_REQ_BIT, true),
|
||||||
DEFINE_PROP_INT32("bootindex", VFIOPCIDevice, bootindex, -1),
|
|
||||||
DEFINE_PROP_BOOL("x-mmap", VFIOPCIDevice, vbasedev.allow_mmap, true),
|
DEFINE_PROP_BOOL("x-mmap", VFIOPCIDevice, vbasedev.allow_mmap, true),
|
||||||
/*
|
/*
|
||||||
* TODO - support passed fds... is this necessary?
|
* TODO - support passed fds... is this necessary?
|
||||||
|
|||||||
+58
-17
@@ -67,22 +67,53 @@ static void vring_unmap(void *buffer, bool is_write)
|
|||||||
/* Map the guest's vring to host memory */
|
/* Map the guest's vring to host memory */
|
||||||
bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
|
bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
|
||||||
{
|
{
|
||||||
hwaddr vring_addr = virtio_queue_get_ring_addr(vdev, n);
|
struct vring *vr = &vring->vr;
|
||||||
hwaddr vring_size = virtio_queue_get_ring_size(vdev, n);
|
hwaddr addr;
|
||||||
void *vring_ptr;
|
hwaddr size;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
vring->broken = false;
|
vring->broken = false;
|
||||||
|
vr->num = virtio_queue_get_num(vdev, n);
|
||||||
|
|
||||||
vring_ptr = vring_map(&vring->mr, vring_addr, vring_size, true);
|
addr = virtio_queue_get_desc_addr(vdev, n);
|
||||||
if (!vring_ptr) {
|
size = virtio_queue_get_desc_size(vdev, n);
|
||||||
error_report("Failed to map vring "
|
/* Map the descriptor area as read only */
|
||||||
"addr %#" HWADDR_PRIx " size %" HWADDR_PRIu,
|
ptr = vring_map(&vring->mr_desc, addr, size, false);
|
||||||
vring_addr, vring_size);
|
if (!ptr) {
|
||||||
vring->broken = true;
|
error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring desc "
|
||||||
return false;
|
"at 0x%" HWADDR_PRIx,
|
||||||
|
size, addr);
|
||||||
|
goto out_err_desc;
|
||||||
}
|
}
|
||||||
|
vr->desc = ptr;
|
||||||
|
|
||||||
vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096);
|
addr = virtio_queue_get_avail_addr(vdev, n);
|
||||||
|
size = virtio_queue_get_avail_size(vdev, n);
|
||||||
|
/* Add the size of the used_event_idx */
|
||||||
|
size += sizeof(uint16_t);
|
||||||
|
/* Map the driver area as read only */
|
||||||
|
ptr = vring_map(&vring->mr_avail, addr, size, false);
|
||||||
|
if (!ptr) {
|
||||||
|
error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring avail "
|
||||||
|
"at 0x%" HWADDR_PRIx,
|
||||||
|
size, addr);
|
||||||
|
goto out_err_avail;
|
||||||
|
}
|
||||||
|
vr->avail = ptr;
|
||||||
|
|
||||||
|
addr = virtio_queue_get_used_addr(vdev, n);
|
||||||
|
size = virtio_queue_get_used_size(vdev, n);
|
||||||
|
/* Add the size of the avail_event_idx */
|
||||||
|
size += sizeof(uint16_t);
|
||||||
|
/* Map the device area as read-write */
|
||||||
|
ptr = vring_map(&vring->mr_used, addr, size, true);
|
||||||
|
if (!ptr) {
|
||||||
|
error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring used "
|
||||||
|
"at 0x%" HWADDR_PRIx,
|
||||||
|
size, addr);
|
||||||
|
goto out_err_used;
|
||||||
|
}
|
||||||
|
vr->used = ptr;
|
||||||
|
|
||||||
vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n);
|
vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n);
|
||||||
vring->last_used_idx = vring_get_used_idx(vdev, vring);
|
vring->last_used_idx = vring_get_used_idx(vdev, vring);
|
||||||
@@ -92,6 +123,14 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
|
|||||||
trace_vring_setup(virtio_queue_get_ring_addr(vdev, n),
|
trace_vring_setup(virtio_queue_get_ring_addr(vdev, n),
|
||||||
vring->vr.desc, vring->vr.avail, vring->vr.used);
|
vring->vr.desc, vring->vr.avail, vring->vr.used);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
out_err_used:
|
||||||
|
memory_region_unref(vring->mr_avail);
|
||||||
|
out_err_avail:
|
||||||
|
memory_region_unref(vring->mr_desc);
|
||||||
|
out_err_desc:
|
||||||
|
vring->broken = true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
|
void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
|
||||||
@@ -99,13 +138,15 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
|
|||||||
virtio_queue_set_last_avail_idx(vdev, n, vring->last_avail_idx);
|
virtio_queue_set_last_avail_idx(vdev, n, vring->last_avail_idx);
|
||||||
virtio_queue_invalidate_signalled_used(vdev, n);
|
virtio_queue_invalidate_signalled_used(vdev, n);
|
||||||
|
|
||||||
memory_region_unref(vring->mr);
|
memory_region_unref(vring->mr_desc);
|
||||||
|
memory_region_unref(vring->mr_avail);
|
||||||
|
memory_region_unref(vring->mr_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable guest->host notifies */
|
/* Disable guest->host notifies */
|
||||||
void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
|
void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
|
||||||
{
|
{
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||||
vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
|
vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +157,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
|
|||||||
*/
|
*/
|
||||||
bool vring_enable_notification(VirtIODevice *vdev, Vring *vring)
|
bool vring_enable_notification(VirtIODevice *vdev, Vring *vring)
|
||||||
{
|
{
|
||||||
if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||||
vring_avail_event(&vring->vr) = vring->vr.avail->idx;
|
vring_avail_event(&vring->vr) = vring->vr.avail->idx;
|
||||||
} else {
|
} else {
|
||||||
vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
|
vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
|
||||||
@@ -135,12 +176,12 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring)
|
|||||||
* interrupts. */
|
* interrupts. */
|
||||||
smp_mb();
|
smp_mb();
|
||||||
|
|
||||||
if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
|
if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
|
||||||
unlikely(!vring_more_avail(vdev, vring))) {
|
unlikely(!vring_more_avail(vdev, vring))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||||
return !(vring_get_avail_flags(vdev, vring) &
|
return !(vring_get_avail_flags(vdev, vring) &
|
||||||
VRING_AVAIL_F_NO_INTERRUPT);
|
VRING_AVAIL_F_NO_INTERRUPT);
|
||||||
}
|
}
|
||||||
@@ -402,7 +443,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
|
|||||||
|
|
||||||
/* On success, increment avail index. */
|
/* On success, increment avail index. */
|
||||||
vring->last_avail_idx++;
|
vring->last_avail_idx++;
|
||||||
if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||||
vring_avail_event(&vring->vr) =
|
vring_avail_event(&vring->vr) =
|
||||||
virtio_tswap16(vdev, vring->last_avail_idx);
|
virtio_tswap16(vdev, vring->last_avail_idx);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -742,7 +742,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
|
|||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
||||||
virtio_legacy_is_cross_endian(vdev)) {
|
virtio_legacy_is_cross_endian(vdev)) {
|
||||||
r = vhost_virtqueue_set_vring_endian_legacy(dev,
|
r = vhost_virtqueue_set_vring_endian_legacy(dev,
|
||||||
virtio_is_big_endian(vdev),
|
virtio_is_big_endian(vdev),
|
||||||
@@ -839,7 +839,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
|
|||||||
/* In the cross-endian case, we need to reset the vring endianness to
|
/* In the cross-endian case, we need to reset the vring endianness to
|
||||||
* native as legacy devices expect so by default.
|
* native as legacy devices expect so by default.
|
||||||
*/
|
*/
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
||||||
virtio_legacy_is_cross_endian(vdev)) {
|
virtio_legacy_is_cross_endian(vdev)) {
|
||||||
r = vhost_virtqueue_set_vring_endian_legacy(dev,
|
r = vhost_virtqueue_set_vring_endian_legacy(dev,
|
||||||
!virtio_is_big_endian(vdev),
|
!virtio_is_big_endian(vdev),
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ static inline void reset_stats(VirtIOBalloon *dev)
|
|||||||
static bool balloon_stats_supported(const VirtIOBalloon *s)
|
static bool balloon_stats_supported(const VirtIOBalloon *s)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
||||||
return virtio_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ);
|
return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool balloon_stats_enabled(const VirtIOBalloon *s)
|
static bool balloon_stats_enabled(const VirtIOBalloon *s)
|
||||||
@@ -310,7 +310,8 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
|
|||||||
trace_virtio_balloon_set_config(dev->actual, oldactual);
|
trace_virtio_balloon_set_config(dev->actual, oldactual);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f)
|
static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
||||||
f |= dev->host_features;
|
f |= dev->host_features;
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp)
|
|||||||
|
|
||||||
/* Get the features of the plugged device. */
|
/* Get the features of the plugged device. */
|
||||||
assert(vdc->get_features != NULL);
|
assert(vdc->get_features != NULL);
|
||||||
vdev->host_features = vdc->get_features(vdev, vdev->host_features);
|
vdev->host_features = vdc->get_features(vdev, vdev->host_features,
|
||||||
|
errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the virtio_bus */
|
/* Reset the virtio_bus */
|
||||||
|
|||||||
+17
-1
@@ -1095,7 +1095,8 @@ static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr,
|
|||||||
break;
|
break;
|
||||||
case VIRTIO_PCI_COMMON_DF:
|
case VIRTIO_PCI_COMMON_DF:
|
||||||
if (proxy->dfselect <= 1) {
|
if (proxy->dfselect <= 1) {
|
||||||
val = vdev->host_features >> (32 * proxy->dfselect);
|
val = (vdev->host_features & ~VIRTIO_LEGACY_FEATURES) >>
|
||||||
|
(32 * proxy->dfselect);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VIRTIO_PCI_COMMON_GFSELECT:
|
case VIRTIO_PCI_COMMON_GFSELECT:
|
||||||
@@ -1413,6 +1414,13 @@ static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy,
|
|||||||
virtio_pci_add_mem_cap(proxy, cap);
|
virtio_pci_add_mem_cap(proxy, cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virtio_pci_modern_region_unmap(VirtIOPCIProxy *proxy,
|
||||||
|
VirtIOPCIRegion *region)
|
||||||
|
{
|
||||||
|
memory_region_del_subregion(&proxy->modern_bar,
|
||||||
|
®ion->mr);
|
||||||
|
}
|
||||||
|
|
||||||
/* This is called by virtio-bus just after the device is plugged. */
|
/* This is called by virtio-bus just after the device is plugged. */
|
||||||
static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
|
static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
|
||||||
{
|
{
|
||||||
@@ -1519,8 +1527,16 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
|
|||||||
static void virtio_pci_device_unplugged(DeviceState *d)
|
static void virtio_pci_device_unplugged(DeviceState *d)
|
||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
|
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
|
||||||
|
bool modern = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN);
|
||||||
|
|
||||||
virtio_pci_stop_ioeventfd(proxy);
|
virtio_pci_stop_ioeventfd(proxy);
|
||||||
|
|
||||||
|
if (modern) {
|
||||||
|
virtio_pci_modern_region_unmap(proxy, &proxy->common);
|
||||||
|
virtio_pci_modern_region_unmap(proxy, &proxy->isr);
|
||||||
|
virtio_pci_modern_region_unmap(proxy, &proxy->device);
|
||||||
|
virtio_pci_modern_region_unmap(proxy, &proxy->notify);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
|
static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
virtio_rng_process(vrng);
|
virtio_rng_process(vrng);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t get_features(VirtIODevice *vdev, uint64_t f)
|
static uint64_t get_features(VirtIODevice *vdev, uint64_t f, Error **errp)
|
||||||
{
|
{
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|||||||
+80
-11
@@ -220,7 +220,7 @@ static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val)
|
|||||||
void virtio_queue_set_notification(VirtQueue *vq, int enable)
|
void virtio_queue_set_notification(VirtQueue *vq, int enable)
|
||||||
{
|
{
|
||||||
vq->notification = enable;
|
vq->notification = enable;
|
||||||
if (virtio_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
if (virtio_vdev_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||||
vring_set_avail_event(vq, vring_avail_idx(vq));
|
vring_set_avail_event(vq, vring_avail_idx(vq));
|
||||||
} else if (enable) {
|
} else if (enable) {
|
||||||
vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
|
vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
|
||||||
@@ -243,14 +243,12 @@ int virtio_queue_empty(VirtQueue *vq)
|
|||||||
return vring_avail_idx(vq) == vq->last_avail_idx;
|
return vring_avail_idx(vq) == vq->last_avail_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
unsigned int len, unsigned int idx)
|
unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
trace_virtqueue_fill(vq, elem, len, idx);
|
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
for (i = 0; i < elem->in_num; i++) {
|
for (i = 0; i < elem->in_num; i++) {
|
||||||
size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
|
size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
|
||||||
@@ -266,6 +264,21 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
|||||||
cpu_physical_memory_unmap(elem->out_sg[i].iov_base,
|
cpu_physical_memory_unmap(elem->out_sg[i].iov_base,
|
||||||
elem->out_sg[i].iov_len,
|
elem->out_sg[i].iov_len,
|
||||||
0, elem->out_sg[i].iov_len);
|
0, elem->out_sg[i].iov_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
|
unsigned int len)
|
||||||
|
{
|
||||||
|
vq->last_avail_idx--;
|
||||||
|
virtqueue_unmap_sg(vq, elem, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
|
unsigned int len, unsigned int idx)
|
||||||
|
{
|
||||||
|
trace_virtqueue_fill(vq, elem, len, idx);
|
||||||
|
|
||||||
|
virtqueue_unmap_sg(vq, elem, len);
|
||||||
|
|
||||||
idx = (idx + vring_used_idx(vq)) % vq->vring.num;
|
idx = (idx + vring_used_idx(vq)) % vq->vring.num;
|
||||||
|
|
||||||
@@ -471,7 +484,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
|
|||||||
max = vq->vring.num;
|
max = vq->vring.num;
|
||||||
|
|
||||||
i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
|
i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
|
||||||
if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||||
vring_set_avail_event(vq, vq->last_avail_idx);
|
vring_set_avail_event(vq, vq->last_avail_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,7 +573,7 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val)
|
|||||||
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
|
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
|
||||||
trace_virtio_set_status(vdev, val);
|
trace_virtio_set_status(vdev, val);
|
||||||
|
|
||||||
if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
|
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
|
||||||
if (!(vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) &&
|
if (!(vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) &&
|
||||||
val & VIRTIO_CONFIG_S_FEATURES_OK) {
|
val & VIRTIO_CONFIG_S_FEATURES_OK) {
|
||||||
int ret = virtio_validate_features(vdev);
|
int ret = virtio_validate_features(vdev);
|
||||||
@@ -898,7 +911,7 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
|
|||||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||||
|
|
||||||
/* virtio-1 compliant devices cannot change the alignment */
|
/* virtio-1 compliant devices cannot change the alignment */
|
||||||
if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
|
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
|
||||||
error_report("tried to modify queue alignment for virtio-1 device");
|
error_report("tried to modify queue alignment for virtio-1 device");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -993,12 +1006,12 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
/* We need to expose used array entries before checking used event. */
|
/* We need to expose used array entries before checking used event. */
|
||||||
smp_mb();
|
smp_mb();
|
||||||
/* Always notify when queue is empty (when feature acknowledge) */
|
/* Always notify when queue is empty (when feature acknowledge) */
|
||||||
if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
|
if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
|
||||||
!vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) {
|
!vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||||
return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT);
|
return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,7 +1048,7 @@ static bool virtio_device_endian_needed(void *opaque)
|
|||||||
VirtIODevice *vdev = opaque;
|
VirtIODevice *vdev = opaque;
|
||||||
|
|
||||||
assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
|
assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
|
||||||
if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
|
if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
|
||||||
return vdev->device_endian != virtio_default_endian();
|
return vdev->device_endian != virtio_default_endian();
|
||||||
}
|
}
|
||||||
/* Devices conforming to VIRTIO 1.0 or later are always LE. */
|
/* Devices conforming to VIRTIO 1.0 or later are always LE. */
|
||||||
@@ -1049,6 +1062,61 @@ static bool virtio_64bit_features_needed(void *opaque)
|
|||||||
return (vdev->host_features >> 32) != 0;
|
return (vdev->host_features >> 32) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool virtio_virtqueue_needed(void *opaque)
|
||||||
|
{
|
||||||
|
VirtIODevice *vdev = opaque;
|
||||||
|
|
||||||
|
return virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put_virtqueue_state(QEMUFile *f, void *pv, size_t size)
|
||||||
|
{
|
||||||
|
VirtIODevice *vdev = pv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
|
qemu_put_be64(f, vdev->vq[i].vring.avail);
|
||||||
|
qemu_put_be64(f, vdev->vq[i].vring.used);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_virtqueue_state(QEMUFile *f, void *pv, size_t size)
|
||||||
|
{
|
||||||
|
VirtIODevice *vdev = pv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
|
vdev->vq[i].vring.avail = qemu_get_be64(f);
|
||||||
|
vdev->vq[i].vring.used = qemu_get_be64(f);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VMStateInfo vmstate_info_virtqueue = {
|
||||||
|
.name = "virtqueue_state",
|
||||||
|
.get = get_virtqueue_state,
|
||||||
|
.put = put_virtqueue_state,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_virtio_virtqueues = {
|
||||||
|
.name = "virtio/virtqueues",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.needed = &virtio_virtqueue_needed,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
{
|
||||||
|
.name = "virtqueues",
|
||||||
|
.version_id = 0,
|
||||||
|
.field_exists = NULL,
|
||||||
|
.size = 0,
|
||||||
|
.info = &vmstate_info_virtqueue,
|
||||||
|
.flags = VMS_SINGLE,
|
||||||
|
.offset = 0,
|
||||||
|
},
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_virtio_device_endian = {
|
static const VMStateDescription vmstate_virtio_device_endian = {
|
||||||
.name = "virtio/device_endian",
|
.name = "virtio/device_endian",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
@@ -1082,6 +1150,7 @@ static const VMStateDescription vmstate_virtio = {
|
|||||||
.subsections = (const VMStateDescription*[]) {
|
.subsections = (const VMStateDescription*[]) {
|
||||||
&vmstate_virtio_device_endian,
|
&vmstate_virtio_device_endian,
|
||||||
&vmstate_virtio_64bit_features,
|
&vmstate_virtio_64bit_features,
|
||||||
|
&vmstate_virtio_virtqueues,
|
||||||
NULL
|
NULL
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -114,6 +114,9 @@ struct AioContext {
|
|||||||
bool notified;
|
bool notified;
|
||||||
EventNotifier notifier;
|
EventNotifier notifier;
|
||||||
|
|
||||||
|
/* Scheduling this BH forces the event loop it iterate */
|
||||||
|
QEMUBH *notify_dummy_bh;
|
||||||
|
|
||||||
/* Thread pool for performing work and receiving completion callbacks */
|
/* Thread pool for performing work and receiving completion callbacks */
|
||||||
struct ThreadPool *thread_pool;
|
struct ThreadPool *thread_pool;
|
||||||
|
|
||||||
|
|||||||
@@ -308,11 +308,7 @@ extern uintptr_t tci_tb_ptr;
|
|||||||
to indicate the compressed mode; subtracting two works around that. It
|
to indicate the compressed mode; subtracting two works around that. It
|
||||||
is also the case that there are no host isas that contain a call insn
|
is also the case that there are no host isas that contain a call insn
|
||||||
smaller than 4 bytes, so we don't worry about special-casing this. */
|
smaller than 4 bytes, so we don't worry about special-casing this. */
|
||||||
#if defined(CONFIG_TCG_INTERPRETER)
|
|
||||||
# define GETPC_ADJ 0
|
|
||||||
#else
|
|
||||||
#define GETPC_ADJ 2
|
#define GETPC_ADJ 2
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GETPC() (GETRA() - GETPC_ADJ)
|
#define GETPC() (GETRA() - GETPC_ADJ)
|
||||||
|
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ struct MemoryRegion {
|
|||||||
bool warning_printed; /* For reservations */
|
bool warning_printed; /* For reservations */
|
||||||
bool flush_coalesced_mmio;
|
bool flush_coalesced_mmio;
|
||||||
bool global_locking;
|
bool global_locking;
|
||||||
|
uint8_t vga_logging_count;
|
||||||
MemoryRegion *alias;
|
MemoryRegion *alias;
|
||||||
hwaddr alias_offset;
|
hwaddr alias_offset;
|
||||||
int32_t priority;
|
int32_t priority;
|
||||||
|
|||||||
+21
-1
@@ -2,7 +2,27 @@
|
|||||||
#define HW_COMPAT_H
|
#define HW_COMPAT_H
|
||||||
|
|
||||||
#define HW_COMPAT_2_3 \
|
#define HW_COMPAT_2_3 \
|
||||||
/* empty */
|
{\
|
||||||
|
.driver = "virtio-blk-pci",\
|
||||||
|
.property = "any_layout",\
|
||||||
|
.value = "off",\
|
||||||
|
},{\
|
||||||
|
.driver = "virtio-balloon-pci",\
|
||||||
|
.property = "any_layout",\
|
||||||
|
.value = "off",\
|
||||||
|
},{\
|
||||||
|
.driver = "virtio-serial-pci",\
|
||||||
|
.property = "any_layout",\
|
||||||
|
.value = "off",\
|
||||||
|
},{\
|
||||||
|
.driver = "virtio-9p-pci",\
|
||||||
|
.property = "any_layout",\
|
||||||
|
.value = "off",\
|
||||||
|
},{\
|
||||||
|
.driver = "virtio-rng-pci",\
|
||||||
|
.property = "any_layout",\
|
||||||
|
.value = "off",\
|
||||||
|
},
|
||||||
|
|
||||||
#define HW_COMPAT_2_2 \
|
#define HW_COMPAT_2_2 \
|
||||||
/* empty */
|
/* empty */
|
||||||
|
|||||||
@@ -350,6 +350,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
|||||||
.driver = "SandyBridge" "-" TYPE_X86_CPU,\
|
.driver = "SandyBridge" "-" TYPE_X86_CPU,\
|
||||||
.property = "xlevel",\
|
.property = "xlevel",\
|
||||||
.value = stringify(0x8000000a),\
|
.value = stringify(0x8000000a),\
|
||||||
|
},{\
|
||||||
|
.driver = "IvyBridge" "-" TYPE_X86_CPU,\
|
||||||
|
.property = "xlevel",\
|
||||||
|
.value = stringify(0x8000000a),\
|
||||||
},{\
|
},{\
|
||||||
.driver = "Haswell" "-" TYPE_X86_CPU,\
|
.driver = "Haswell" "-" TYPE_X86_CPU,\
|
||||||
.property = "xlevel",\
|
.property = "xlevel",\
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "net/net.h"
|
#include "net/net.h"
|
||||||
#include "qemu/fifo8.h"
|
#include "qemu/fifo8.h"
|
||||||
|
#include "hw/net/mii.h"
|
||||||
|
|
||||||
#define TYPE_AW_EMAC "allwinner-emac"
|
#define TYPE_AW_EMAC "allwinner-emac"
|
||||||
#define AW_EMAC(obj) OBJECT_CHECK(AwEmacState, (obj), TYPE_AW_EMAC)
|
#define AW_EMAC(obj) OBJECT_CHECK(AwEmacState, (obj), TYPE_AW_EMAC)
|
||||||
@@ -118,45 +119,6 @@
|
|||||||
#define EMAC_RX_IO_DATA_STATUS_OK (1 << 7)
|
#define EMAC_RX_IO_DATA_STATUS_OK (1 << 7)
|
||||||
#define EMAC_UNDOCUMENTED_MAGIC 0x0143414d /* header for RX frames */
|
#define EMAC_UNDOCUMENTED_MAGIC 0x0143414d /* header for RX frames */
|
||||||
|
|
||||||
/* PHY registers */
|
|
||||||
#define MII_BMCR 0
|
|
||||||
#define MII_BMSR 1
|
|
||||||
#define MII_PHYID1 2
|
|
||||||
#define MII_PHYID2 3
|
|
||||||
#define MII_ANAR 4
|
|
||||||
#define MII_ANLPAR 5
|
|
||||||
#define MII_ANER 6
|
|
||||||
#define MII_NSR 16
|
|
||||||
#define MII_LBREMR 17
|
|
||||||
#define MII_REC 18
|
|
||||||
#define MII_SNRDR 19
|
|
||||||
#define MII_TEST 25
|
|
||||||
|
|
||||||
/* PHY registers fields */
|
|
||||||
#define MII_BMCR_RESET (1 << 15)
|
|
||||||
#define MII_BMCR_LOOPBACK (1 << 14)
|
|
||||||
#define MII_BMCR_SPEED (1 << 13)
|
|
||||||
#define MII_BMCR_AUTOEN (1 << 12)
|
|
||||||
#define MII_BMCR_FD (1 << 8)
|
|
||||||
|
|
||||||
#define MII_BMSR_100TX_FD (1 << 14)
|
|
||||||
#define MII_BMSR_100TX_HD (1 << 13)
|
|
||||||
#define MII_BMSR_10T_FD (1 << 12)
|
|
||||||
#define MII_BMSR_10T_HD (1 << 11)
|
|
||||||
#define MII_BMSR_MFPS (1 << 6)
|
|
||||||
#define MII_BMSR_AN_COMP (1 << 5)
|
|
||||||
#define MII_BMSR_AUTONEG (1 << 3)
|
|
||||||
#define MII_BMSR_LINK_ST (1 << 2)
|
|
||||||
|
|
||||||
#define MII_ANAR_TXFD (1 << 8)
|
|
||||||
#define MII_ANAR_TX (1 << 7)
|
|
||||||
#define MII_ANAR_10FD (1 << 6)
|
|
||||||
#define MII_ANAR_10 (1 << 5)
|
|
||||||
#define MII_ANAR_CSMACD (1 << 0)
|
|
||||||
|
|
||||||
#define RTL8201CP_PHYID1 0x0000
|
|
||||||
#define RTL8201CP_PHYID2 0x8201
|
|
||||||
|
|
||||||
/* INT CTL and INT STA registers fields */
|
/* INT CTL and INT STA registers fields */
|
||||||
#define EMAC_INT_TX_CHAN(x) (1 << (x))
|
#define EMAC_INT_TX_CHAN(x) (1 << (x))
|
||||||
#define EMAC_INT_RX (1 << 8)
|
#define EMAC_INT_RX (1 << 8)
|
||||||
|
|||||||
Loaded 100 of 185 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user