Compare commits
153 Commits
pull-input
...
pull-vnc-2
Author | SHA1 | Date | |
---|---|---|---|
|
43948386bb | ||
|
525965b85d | ||
|
45e1611de8 | ||
|
d00e6cddc2 | ||
|
54f3a180a3 | ||
|
0d7954c288 | ||
|
b19ca18802 | ||
|
bf25983345 | ||
|
d3532a0db0 | ||
|
db12451dec | ||
|
771b6ed37e | ||
|
4cae4d5aca | ||
|
490309fcfb | ||
|
3ef4ebcc5c | ||
|
dc622deb2d | ||
|
f3b3766899 | ||
|
d1048bef9d | ||
|
2528043f1f | ||
|
df5b2adb73 | ||
|
ca6028185d | ||
|
dd0247e09a | ||
|
6c150fbd34 | ||
|
8e815eeefe | ||
|
4f99ab7a78 | ||
|
ad5b88b1f1 | ||
|
109e90e470 | ||
|
085f8e88ba | ||
|
b03541fa77 | ||
|
3d4a70f80f | ||
|
a31a7475e9 | ||
|
5224c88dd3 | ||
|
8092cb7132 | ||
|
60e68042cf | ||
|
24bf10dac3 | ||
|
0c0de1b681 | ||
|
91aa70ab2a | ||
|
a2b257d621 | ||
|
92a37a04d6 | ||
|
34dde13685 | ||
|
b8865591d4 | ||
|
c409572678 | ||
|
0e88f47850 | ||
|
a00c117338 | ||
|
b0af844007 | ||
|
7b50d00911 | ||
|
8db804ac41 | ||
|
7a8919dc29 | ||
|
b310a2a609 | ||
|
8a0f9b5263 | ||
|
9c7074da5e | ||
|
ff323a6b54 | ||
|
76cb658419 | ||
|
f2a64032a1 | ||
|
3ade1a055c | ||
|
f75ad80f6c | ||
|
6c1b663c4c | ||
|
af3ff19b48 | ||
|
6b896ab261 | ||
|
8336e465ac | ||
|
b1b1e81fb5 | ||
|
ed6273e26f | ||
|
776ec96f79 | ||
|
b73e8bd414 | ||
|
1ab8f867ef | ||
|
ea5b201a0a | ||
|
444b1996cb | ||
|
0be839a270 | ||
|
098ffa6674 | ||
|
731de38052 | ||
|
39411cf3c3 | ||
|
f874bf905f | ||
|
8676785302 | ||
|
d1f06fe665 | ||
|
c4875e5b22 | ||
|
be2ebc6dad | ||
|
d6be29e3fb | ||
|
1aba4be97e | ||
|
a9be76576e | ||
|
d8edf52a51 | ||
|
fae38221e7 | ||
|
0e8b439ae5 | ||
|
86d10328a0 | ||
|
6cfcd864a4 | ||
|
720fdd6fa9 | ||
|
ddd2eab72f | ||
|
1def74548d | ||
|
77e205a528 | ||
|
d4754a9531 | ||
|
35fb5b73a2 | ||
|
4e70f9271d | ||
|
77374582ab | ||
|
5bbebf6228 | ||
|
b87dcdd074 | ||
|
2f01dfacb5 | ||
|
91ab2ed722 | ||
|
5f58330790 | ||
|
f3a9cfddae | ||
|
107f0d4677 | ||
|
102e56254d | ||
|
36ab3c3400 | ||
|
1cbdd96813 | ||
|
72a065dbb1 | ||
|
3251bdcf1c | ||
|
bef1301acb | ||
|
36334faf35 | ||
|
a395f3fa2f | ||
|
c52e67924f | ||
|
3ef0eab178 | ||
|
f4ec5cd29d | ||
|
1154d84dcc | ||
|
e6a33e45c2 | ||
|
c2c00148ec | ||
|
b56cb28895 | ||
|
e08d300450 | ||
|
953ea14d66 | ||
|
410bd787bf | ||
|
79ae25af15 | ||
|
ae67dc72e4 | ||
|
f69c111585 | ||
|
6012ca8159 | ||
|
c9cf45c1a4 | ||
|
e0d0041ec6 | ||
|
7f06a3b14d | ||
|
4cc47f8b3c | ||
|
f73adec709 | ||
|
776346cd63 | ||
|
705be728c0 | ||
|
00c2275c95 | ||
|
8f9d989cac | ||
|
d208a85f15 | ||
|
8447414510 | ||
|
ed4b43265d | ||
|
59c4f2ecef | ||
|
c0787c8dd1 | ||
|
f05d9999f4 | ||
|
b5e9476c0f | ||
|
7f151e6f71 | ||
|
f2ad97ff81 | ||
|
1e03e40784 | ||
|
aecc88616a | ||
|
ccf661f827 | ||
|
c21fd2c79e | ||
|
f17b069010 | ||
|
5b009e4008 | ||
|
7912d04be6 | ||
|
9df98352b7 | ||
|
09c7fbef76 | ||
|
1b3e71f8ee | ||
|
25aaa2c568 | ||
|
55783a5521 | ||
|
c3543fb5fe | ||
|
63c693f8d0 | ||
|
3a0614c6c7 |
20
MAINTAINERS
20
MAINTAINERS
@@ -880,6 +880,12 @@ S: Maintained
|
||||
F: qobject/
|
||||
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
|
||||
|
||||
QEMU Guest Agent
|
||||
M: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
S: Maintained
|
||||
F: qga/
|
||||
T: git git://github.com/mdroth/qemu.git qga
|
||||
|
||||
QOM
|
||||
M: Anthony Liguori <aliguori@amazon.com>
|
||||
M: Andreas Färber <afaerber@suse.de>
|
||||
@@ -920,6 +926,15 @@ M: Blue Swirl <blauwirbel@gmail.com>
|
||||
S: Odd Fixes
|
||||
F: scripts/checkpatch.pl
|
||||
|
||||
Migration
|
||||
M: Juan Quintela <quintela@redhat.com>
|
||||
S: Maintained
|
||||
F: include/migration/
|
||||
F: migration*
|
||||
F: savevm.c
|
||||
F: arch_init.c
|
||||
F: vmstate.c
|
||||
|
||||
Seccomp
|
||||
M: Eduardo Otubo <eduardo.otubo@profitbricks.com>
|
||||
S: Supported
|
||||
@@ -1078,3 +1093,8 @@ M: Chrysostomos Nanakos <cnanakos@grnet.gr>
|
||||
M: Chrysostomos Nanakos <chris@include.gr>
|
||||
S: Maintained
|
||||
F: block/archipelago.c
|
||||
|
||||
Bootdevice
|
||||
M: Gonglei <arei.gonglei@huawei.com>
|
||||
S: Maintained
|
||||
F: bootdevice.c
|
||||
|
20
arch_init.c
20
arch_init.c
@@ -486,15 +486,23 @@ static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
|
||||
|
||||
|
||||
/* Needs iothread lock! */
|
||||
/* Fix me: there are too many global variables used in migration process. */
|
||||
static int64_t start_time;
|
||||
static int64_t bytes_xfer_prev;
|
||||
static int64_t num_dirty_pages_period;
|
||||
|
||||
static void migration_bitmap_sync_init(void)
|
||||
{
|
||||
start_time = 0;
|
||||
bytes_xfer_prev = 0;
|
||||
num_dirty_pages_period = 0;
|
||||
}
|
||||
|
||||
static void migration_bitmap_sync(void)
|
||||
{
|
||||
RAMBlock *block;
|
||||
uint64_t num_dirty_pages_init = migration_dirty_pages;
|
||||
MigrationState *s = migrate_get_current();
|
||||
static int64_t start_time;
|
||||
static int64_t bytes_xfer_prev;
|
||||
static int64_t num_dirty_pages_period;
|
||||
int64_t end_time;
|
||||
int64_t bytes_xfer_now;
|
||||
static uint64_t xbzrle_cache_miss_prev;
|
||||
@@ -774,6 +782,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
|
||||
mig_throttle_on = false;
|
||||
dirty_rate_high_cnt = 0;
|
||||
bitmap_sync_count = 0;
|
||||
migration_bitmap_sync_init();
|
||||
|
||||
if (migrate_use_xbzrle()) {
|
||||
XBZRLE_cache_lock();
|
||||
@@ -1006,7 +1015,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
|
||||
uint8_t len;
|
||||
|
||||
if (flags & RAM_SAVE_FLAG_CONTINUE) {
|
||||
if (!block) {
|
||||
if (!block || block->length <= offset) {
|
||||
error_report("Ack, bad migration stream!");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1019,8 +1028,9 @@ static inline void *host_from_stream_offset(QEMUFile *f,
|
||||
id[len] = 0;
|
||||
|
||||
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
|
||||
if (!strncmp(id, block->idstr, sizeof(id)))
|
||||
if (!strncmp(id, block->idstr, sizeof(id)) && block->length > offset) {
|
||||
return memory_region_get_ram_ptr(block->mr) + offset;
|
||||
}
|
||||
}
|
||||
|
||||
error_report("Can't find block %s!", id);
|
||||
|
10
block.c
10
block.c
@@ -2790,8 +2790,8 @@ int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
||||
if (nb_sectors <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (nb_sectors > INT_MAX) {
|
||||
nb_sectors = INT_MAX;
|
||||
if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
||||
nb_sectors = INT_MAX / BDRV_SECTOR_SIZE;
|
||||
}
|
||||
ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n);
|
||||
if (ret < 0) {
|
||||
@@ -3903,9 +3903,9 @@ typedef struct BdrvCoGetBlockStatusData {
|
||||
} BdrvCoGetBlockStatusData;
|
||||
|
||||
/*
|
||||
* Returns true iff the specified sector is present in the disk image. Drivers
|
||||
* not implementing the functionality are assumed to not support backing files,
|
||||
* hence all their sectors are reported as allocated.
|
||||
* Returns the allocation status of the specified sectors.
|
||||
* Drivers not implementing the functionality are assumed to not support
|
||||
* backing files, hence all their sectors are reported as allocated.
|
||||
*
|
||||
* If 'sector_num' is beyond the end of the disk image the return value is 0
|
||||
* and 'pnum' is set to 0.
|
||||
|
26
block/qapi.c
26
block/qapi.c
@@ -29,13 +29,6 @@
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#ifdef __linux__
|
||||
#include <linux/fs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifndef FS_NOCOW_FL
|
||||
#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs)
|
||||
{
|
||||
@@ -180,9 +173,6 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
||||
int ret;
|
||||
Error *err = NULL;
|
||||
ImageInfo *info;
|
||||
#ifdef __linux__
|
||||
int fd, attr;
|
||||
#endif
|
||||
|
||||
size = bdrv_getlength(bs);
|
||||
if (size < 0) {
|
||||
@@ -212,18 +202,6 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
||||
info->format_specific = bdrv_get_specific_info(bs);
|
||||
info->has_format_specific = info->format_specific != NULL;
|
||||
|
||||
#ifdef __linux__
|
||||
/* get NOCOW info */
|
||||
fd = qemu_open(bs->filename, O_RDONLY | O_NONBLOCK);
|
||||
if (fd >= 0) {
|
||||
if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0 && (attr & FS_NOCOW_FL)) {
|
||||
info->has_nocow = true;
|
||||
info->nocow = true;
|
||||
}
|
||||
qemu_close(fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
backing_filename = bs->backing_file;
|
||||
if (backing_filename[0] != '\0') {
|
||||
info->backing_filename = g_strdup(backing_filename);
|
||||
@@ -655,8 +633,4 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
|
||||
func_fprintf(f, "Format specific information:\n");
|
||||
bdrv_image_info_specific_dump(func_fprintf, f, info->format_specific);
|
||||
}
|
||||
|
||||
if (info->has_nocow && info->nocow) {
|
||||
func_fprintf(f, "NOCOW flag: set\n");
|
||||
}
|
||||
}
|
||||
|
@@ -60,9 +60,6 @@
|
||||
#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_FIEMAP
|
||||
#include <linux/fiemap.h>
|
||||
#endif
|
||||
#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
|
||||
#include <linux/falloc.h>
|
||||
#endif
|
||||
@@ -151,9 +148,6 @@ typedef struct BDRVRawState {
|
||||
bool has_write_zeroes:1;
|
||||
bool discard_zeroes:1;
|
||||
bool needs_alignment;
|
||||
#ifdef CONFIG_FIEMAP
|
||||
bool skip_fiemap;
|
||||
#endif
|
||||
} BDRVRawState;
|
||||
|
||||
typedef struct BDRVRawReopenState {
|
||||
@@ -1457,9 +1451,16 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
"Could not write to the new file");
|
||||
break;
|
||||
}
|
||||
left -= num;
|
||||
left -= result;
|
||||
}
|
||||
if (result >= 0) {
|
||||
result = fsync(fd);
|
||||
if (result < 0) {
|
||||
result = -errno;
|
||||
error_setg_errno(errp, -result,
|
||||
"Could not flush new file to disk");
|
||||
}
|
||||
}
|
||||
fsync(fd);
|
||||
g_free(buf);
|
||||
break;
|
||||
}
|
||||
@@ -1481,83 +1482,93 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int try_fiemap(BlockDriverState *bs, off_t start, off_t *data,
|
||||
off_t *hole, int nb_sectors)
|
||||
{
|
||||
#ifdef CONFIG_FIEMAP
|
||||
BDRVRawState *s = bs->opaque;
|
||||
int ret = 0;
|
||||
struct {
|
||||
struct fiemap fm;
|
||||
struct fiemap_extent fe;
|
||||
} f;
|
||||
|
||||
if (s->skip_fiemap) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
f.fm.fm_start = start;
|
||||
f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE;
|
||||
f.fm.fm_flags = FIEMAP_FLAG_SYNC;
|
||||
f.fm.fm_extent_count = 1;
|
||||
f.fm.fm_reserved = 0;
|
||||
if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) {
|
||||
s->skip_fiemap = true;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (f.fm.fm_mapped_extents == 0) {
|
||||
/* No extents found, data is beyond f.fm.fm_start + f.fm.fm_length.
|
||||
* f.fm.fm_start + f.fm.fm_length must be clamped to the file size!
|
||||
*/
|
||||
off_t length = lseek(s->fd, 0, SEEK_END);
|
||||
*hole = f.fm.fm_start;
|
||||
*data = MIN(f.fm.fm_start + f.fm.fm_length, length);
|
||||
} else {
|
||||
*data = f.fe.fe_logical;
|
||||
*hole = f.fe.fe_logical + f.fe.fe_length;
|
||||
if (f.fe.fe_flags & FIEMAP_EXTENT_UNWRITTEN) {
|
||||
ret |= BDRV_BLOCK_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int try_seek_hole(BlockDriverState *bs, off_t start, off_t *data,
|
||||
off_t *hole)
|
||||
/*
|
||||
* Find allocation range in @bs around offset @start.
|
||||
* May change underlying file descriptor's file offset.
|
||||
* If @start is not in a hole, store @start in @data, and the
|
||||
* beginning of the next hole in @hole, and return 0.
|
||||
* If @start is in a non-trailing hole, store @start in @hole and the
|
||||
* beginning of the next non-hole in @data, and return 0.
|
||||
* If @start is in a trailing hole or beyond EOF, return -ENXIO.
|
||||
* If we can't find out, return a negative errno other than -ENXIO.
|
||||
*/
|
||||
static int find_allocation(BlockDriverState *bs, off_t start,
|
||||
off_t *data, off_t *hole)
|
||||
{
|
||||
#if defined SEEK_HOLE && defined SEEK_DATA
|
||||
BDRVRawState *s = bs->opaque;
|
||||
off_t offs;
|
||||
|
||||
*hole = lseek(s->fd, start, SEEK_HOLE);
|
||||
if (*hole == -1) {
|
||||
return -errno;
|
||||
/*
|
||||
* SEEK_DATA cases:
|
||||
* D1. offs == start: start is in data
|
||||
* D2. offs > start: start is in a hole, next data at offs
|
||||
* D3. offs < 0, errno = ENXIO: either start is in a trailing hole
|
||||
* or start is beyond EOF
|
||||
* If the latter happens, the file has been truncated behind
|
||||
* our back since we opened it. All bets are off then.
|
||||
* Treating like a trailing hole is simplest.
|
||||
* D4. offs < 0, errno != ENXIO: we learned nothing
|
||||
*/
|
||||
offs = lseek(s->fd, start, SEEK_DATA);
|
||||
if (offs < 0) {
|
||||
return -errno; /* D3 or D4 */
|
||||
}
|
||||
assert(offs >= start);
|
||||
|
||||
if (offs > start) {
|
||||
/* D2: in hole, next data at offs */
|
||||
*hole = start;
|
||||
*data = offs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*hole > start) {
|
||||
/* D1: in data, end not yet known */
|
||||
|
||||
/*
|
||||
* SEEK_HOLE cases:
|
||||
* H1. offs == start: start is in a hole
|
||||
* If this happens here, a hole has been dug behind our back
|
||||
* since the previous lseek().
|
||||
* H2. offs > start: either start is in data, next hole at offs,
|
||||
* or start is in trailing hole, EOF at offs
|
||||
* Linux treats trailing holes like any other hole: offs ==
|
||||
* start. Solaris seeks to EOF instead: offs > start (blech).
|
||||
* If that happens here, a hole has been dug behind our back
|
||||
* since the previous lseek().
|
||||
* H3. offs < 0, errno = ENXIO: start is beyond EOF
|
||||
* If this happens, the file has been truncated behind our
|
||||
* back since we opened it. Treat it like a trailing hole.
|
||||
* H4. offs < 0, errno != ENXIO: we learned nothing
|
||||
* Pretend we know nothing at all, i.e. "forget" about D1.
|
||||
*/
|
||||
offs = lseek(s->fd, start, SEEK_HOLE);
|
||||
if (offs < 0) {
|
||||
return -errno; /* D1 and (H3 or H4) */
|
||||
}
|
||||
assert(offs >= start);
|
||||
|
||||
if (offs > start) {
|
||||
/*
|
||||
* D1 and H2: either in data, next hole at offs, or it was in
|
||||
* data but is now in a trailing hole. In the latter case,
|
||||
* all bets are off. Treating it as if it there was data all
|
||||
* the way to EOF is safe, so simply do that.
|
||||
*/
|
||||
*data = start;
|
||||
} else {
|
||||
/* On a hole. We need another syscall to find its end. */
|
||||
*data = lseek(s->fd, start, SEEK_DATA);
|
||||
if (*data == -1) {
|
||||
*data = lseek(s->fd, 0, SEEK_END);
|
||||
}
|
||||
*hole = offs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* D1 and H1 */
|
||||
return -EBUSY;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true iff the specified sector is present in the disk image. Drivers
|
||||
* not implementing the functionality are assumed to not support backing files,
|
||||
* hence all their sectors are reported as allocated.
|
||||
* Returns the allocation status of the specified sectors.
|
||||
*
|
||||
* If 'sector_num' is beyond the end of the disk image the return value is 0
|
||||
* and 'pnum' is set to 0.
|
||||
@@ -1593,28 +1604,26 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
|
||||
nb_sectors = DIV_ROUND_UP(total_size - start, BDRV_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
ret = try_seek_hole(bs, start, &data, &hole);
|
||||
if (ret < 0) {
|
||||
ret = try_fiemap(bs, start, &data, &hole, nb_sectors);
|
||||
if (ret < 0) {
|
||||
/* Assume everything is allocated. */
|
||||
data = 0;
|
||||
hole = start + nb_sectors * BDRV_SECTOR_SIZE;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
assert(ret >= 0);
|
||||
|
||||
if (data <= start) {
|
||||
ret = find_allocation(bs, start, &data, &hole);
|
||||
if (ret == -ENXIO) {
|
||||
/* Trailing hole */
|
||||
*pnum = nb_sectors;
|
||||
ret = BDRV_BLOCK_ZERO;
|
||||
} else if (ret < 0) {
|
||||
/* No info available, so pretend there are no holes */
|
||||
*pnum = nb_sectors;
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
} else if (data == start) {
|
||||
/* On a data extent, compute sectors to the end of the extent. */
|
||||
*pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE);
|
||||
return ret | BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
} else {
|
||||
/* On a hole, compute sectors to the beginning of the next extent. */
|
||||
assert(hole == start);
|
||||
*pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
|
||||
return ret | BDRV_BLOCK_ZERO | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
ret = BDRV_BLOCK_ZERO;
|
||||
}
|
||||
return ret | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
}
|
||||
|
||||
static coroutine_fn BlockAIOCB *raw_aio_discard(BlockDriverState *bs,
|
||||
|
22
block/vmdk.c
22
block/vmdk.c
@@ -2137,23 +2137,29 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
|
||||
return spec_info;
|
||||
}
|
||||
|
||||
static bool vmdk_extents_type_eq(const VmdkExtent *a, const VmdkExtent *b)
|
||||
{
|
||||
return a->flat == b->flat &&
|
||||
a->compressed == b->compressed &&
|
||||
(a->flat || a->cluster_sectors == b->cluster_sectors);
|
||||
}
|
||||
|
||||
static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
{
|
||||
int i;
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
assert(s->num_extents);
|
||||
|
||||
/* See if we have multiple extents but they have different cases */
|
||||
for (i = 1; i < s->num_extents; i++) {
|
||||
if (!vmdk_extents_type_eq(&s->extents[0], &s->extents[i])) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
bdi->needs_compressed_writes = s->extents[0].compressed;
|
||||
if (!s->extents[0].flat) {
|
||||
bdi->cluster_size = s->extents[0].cluster_sectors << BDRV_SECTOR_BITS;
|
||||
}
|
||||
/* See if we have multiple extents but they have different cases */
|
||||
for (i = 1; i < s->num_extents; i++) {
|
||||
if (bdi->needs_compressed_writes != s->extents[i].compressed ||
|
||||
(bdi->cluster_size && bdi->cluster_size !=
|
||||
s->extents[i].cluster_sectors << BDRV_SECTOR_BITS)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
3
configure
vendored
3
configure
vendored
@@ -1823,7 +1823,8 @@ fi
|
||||
# libseccomp check
|
||||
|
||||
if test "$seccomp" != "no" ; then
|
||||
if $pkg_config --atleast-version=2.1.0 libseccomp; then
|
||||
if test "$cpu" = "i386" || test "$cpu" = "x86_64" &&
|
||||
$pkg_config --atleast-version=2.1.1 libseccomp; then
|
||||
libs_softmmu="$libs_softmmu `$pkg_config --libs libseccomp`"
|
||||
QEMU_CFLAGS="$QEMU_CFLAGS `$pkg_config --cflags libseccomp`"
|
||||
seccomp="yes"
|
||||
|
@@ -155,7 +155,7 @@ Coroutine *qemu_coroutine_new(void)
|
||||
stack_t oss;
|
||||
sigset_t sigs;
|
||||
sigset_t osigs;
|
||||
jmp_buf old_env;
|
||||
sigjmp_buf old_env;
|
||||
|
||||
/* The way to manipulate stack is with the sigaltstack function. We
|
||||
* prepare a stack, with it delivering a signal to ourselves and then
|
||||
|
@@ -139,12 +139,12 @@ events are not tightly coupled to a specific trace backend, such as LTTng or
|
||||
SystemTap. Support for trace backends can be added by extending the "tracetool"
|
||||
script.
|
||||
|
||||
The trace backend is chosen at configure time and only one trace backend can
|
||||
be built into the binary:
|
||||
The trace backends are chosen at configure time:
|
||||
|
||||
./configure --trace-backends=simple
|
||||
./configure --enable-trace-backends=simple
|
||||
|
||||
For a list of supported trace backends, try ./configure --help or see below.
|
||||
If multiple backends are enabled, the trace is sent to them all.
|
||||
|
||||
The following subsections describe the supported trace backends.
|
||||
|
||||
|
15
exec.c
15
exec.c
@@ -909,14 +909,15 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
|
||||
uint16_t section);
|
||||
static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
|
||||
|
||||
static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
|
||||
static void *(*phys_mem_alloc)(size_t size, uint64_t *align) =
|
||||
qemu_anon_ram_alloc;
|
||||
|
||||
/*
|
||||
* Set a custom physical guest memory alloator.
|
||||
* Accelerators with unusual needs may need this. Hopefully, we can
|
||||
* get rid of it eventually.
|
||||
*/
|
||||
void phys_mem_set_alloc(void *(*alloc)(size_t))
|
||||
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align))
|
||||
{
|
||||
phys_mem_alloc = alloc;
|
||||
}
|
||||
@@ -1098,6 +1099,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||
error_propagate(errp, local_err);
|
||||
goto error;
|
||||
}
|
||||
block->mr->align = hpagesize;
|
||||
|
||||
if (memory < hpagesize) {
|
||||
error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
|
||||
@@ -1309,7 +1311,8 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
|
||||
if (xen_enabled()) {
|
||||
xen_ram_alloc(new_block->offset, new_block->length, new_block->mr);
|
||||
} else {
|
||||
new_block->host = phys_mem_alloc(new_block->length);
|
||||
new_block->host = phys_mem_alloc(new_block->length,
|
||||
&new_block->mr->align);
|
||||
if (!new_block->host) {
|
||||
error_setg_errno(errp, errno,
|
||||
"cannot set up guest memory '%s'",
|
||||
@@ -2066,10 +2069,8 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
||||
static void invalidate_and_set_dirty(hwaddr addr,
|
||||
hwaddr length)
|
||||
{
|
||||
if (cpu_physical_memory_is_clean(addr)) {
|
||||
/* invalidate code */
|
||||
tb_invalidate_phys_page_range(addr, addr + length, 0);
|
||||
/* set dirty bit */
|
||||
if (cpu_physical_memory_range_includes_clean(addr, length)) {
|
||||
tb_invalidate_phys_range(addr, addr + length, 0);
|
||||
cpu_physical_memory_set_dirty_range_nocode(addr, length);
|
||||
}
|
||||
xen_modified_memory(addr, length);
|
||||
|
@@ -823,7 +823,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
||||
action = *p++;
|
||||
signal = 0;
|
||||
if (action == 'C' || action == 'S') {
|
||||
signal = strtoul(p, (char **)&p, 16);
|
||||
signal = gdb_signal_to_target(strtoul(p, (char **)&p, 16));
|
||||
if (signal == -1) {
|
||||
signal = 0;
|
||||
}
|
||||
} else if (action != 'c' && action != 's') {
|
||||
res = 0;
|
||||
break;
|
||||
|
@@ -376,8 +376,11 @@ static void acpi_notify_wakeup(Notifier *notifier, void *data)
|
||||
/* ACPI PM1a EVT */
|
||||
uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar)
|
||||
{
|
||||
int64_t d = acpi_pm_tmr_get_clock();
|
||||
if (d >= ar->tmr.overflow_time) {
|
||||
/* Compare ns-clock, not PM timer ticks, because
|
||||
acpi_pm_tmr_update function uses ns for setting the timer. */
|
||||
int64_t d = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
if (d >= muldiv64(ar->tmr.overflow_time,
|
||||
get_ticks_per_sec(), PM_TIMER_FREQUENCY)) {
|
||||
ar->pm1.evt.sts |= ACPI_BITMASK_TIMER_STATUS;
|
||||
}
|
||||
return ar->pm1.evt.sts;
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
#include "hw/acpi/memory_hotplug.h"
|
||||
#include "hw/acpi/acpi_dev_interface.h"
|
||||
#include "hw/xen/xen.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
@@ -501,6 +502,9 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
|
||||
s->irq = sci_irq;
|
||||
s->smi_irq = smi_irq;
|
||||
s->kvm_enabled = kvm_enabled;
|
||||
if (xen_enabled()) {
|
||||
s->use_acpi_pci_hotplug = false;
|
||||
}
|
||||
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
|
@@ -389,7 +389,7 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
qemu_fdt_setprop(vbi->fdt, nodename, "clock-names",
|
||||
clocknames, sizeof(clocknames));
|
||||
|
||||
qemu_fdt_setprop_string(vbi->fdt, "/chosen", "linux,stdout-path", nodename);
|
||||
qemu_fdt_setprop_string(vbi->fdt, "/chosen", "stdout-path", nodename);
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
|
@@ -583,8 +583,7 @@ static int nvme_start_ctrl(NvmeCtrl *n)
|
||||
NVME_CC_IOCQES(n->bar.cc) > NVME_CTRL_CQES_MAX(n->id_ctrl.cqes) ||
|
||||
NVME_CC_IOSQES(n->bar.cc) < NVME_CTRL_SQES_MIN(n->id_ctrl.sqes) ||
|
||||
NVME_CC_IOSQES(n->bar.cc) > NVME_CTRL_SQES_MAX(n->id_ctrl.sqes) ||
|
||||
!NVME_AQA_ASQS(n->bar.aqa) || NVME_AQA_ASQS(n->bar.aqa) > 4095 ||
|
||||
!NVME_AQA_ACQS(n->bar.aqa) || NVME_AQA_ACQS(n->bar.aqa) > 4095) {
|
||||
!NVME_AQA_ASQS(n->bar.aqa) || !NVME_AQA_ACQS(n->bar.aqa)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@@ -59,6 +59,13 @@ struct PersistentGrant {
|
||||
|
||||
typedef struct PersistentGrant PersistentGrant;
|
||||
|
||||
struct PersistentRegion {
|
||||
void *addr;
|
||||
int num;
|
||||
};
|
||||
|
||||
typedef struct PersistentRegion PersistentRegion;
|
||||
|
||||
struct ioreq {
|
||||
blkif_request_t req;
|
||||
int16_t status;
|
||||
@@ -118,6 +125,7 @@ struct XenBlkDev {
|
||||
gboolean feature_discard;
|
||||
gboolean feature_persistent;
|
||||
GTree *persistent_gnts;
|
||||
GSList *persistent_regions;
|
||||
unsigned int persistent_gnt_count;
|
||||
unsigned int max_grants;
|
||||
|
||||
@@ -177,6 +185,23 @@ static void destroy_grant(gpointer pgnt)
|
||||
g_free(grant);
|
||||
}
|
||||
|
||||
static void remove_persistent_region(gpointer data, gpointer dev)
|
||||
{
|
||||
PersistentRegion *region = data;
|
||||
struct XenBlkDev *blkdev = dev;
|
||||
XenGnttab gnt = blkdev->xendev.gnttabdev;
|
||||
|
||||
if (xc_gnttab_munmap(gnt, region->addr, region->num) != 0) {
|
||||
xen_be_printf(&blkdev->xendev, 0,
|
||||
"xc_gnttab_munmap region %p failed: %s\n",
|
||||
region->addr, strerror(errno));
|
||||
}
|
||||
xen_be_printf(&blkdev->xendev, 3,
|
||||
"unmapped grant region %p with %d pages\n",
|
||||
region->addr, region->num);
|
||||
g_free(region);
|
||||
}
|
||||
|
||||
static struct ioreq *ioreq_start(struct XenBlkDev *blkdev)
|
||||
{
|
||||
struct ioreq *ioreq = NULL;
|
||||
@@ -343,6 +368,7 @@ static int ioreq_map(struct ioreq *ioreq)
|
||||
void *page[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
int i, j, new_maps = 0;
|
||||
PersistentGrant *grant;
|
||||
PersistentRegion *region;
|
||||
/* domids and refs variables will contain the information necessary
|
||||
* to map the grants that are needed to fulfill this request.
|
||||
*
|
||||
@@ -421,7 +447,22 @@ static int ioreq_map(struct ioreq *ioreq)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ioreq->blkdev->feature_persistent) {
|
||||
if (ioreq->blkdev->feature_persistent && new_maps != 0 &&
|
||||
(!batch_maps || (ioreq->blkdev->persistent_gnt_count + new_maps <=
|
||||
ioreq->blkdev->max_grants))) {
|
||||
/*
|
||||
* If we are using persistent grants and batch mappings only
|
||||
* add the new maps to the list of persistent grants if the whole
|
||||
* area can be persistently mapped.
|
||||
*/
|
||||
if (batch_maps) {
|
||||
region = g_malloc0(sizeof(*region));
|
||||
region->addr = ioreq->pages;
|
||||
region->num = new_maps;
|
||||
ioreq->blkdev->persistent_regions = g_slist_append(
|
||||
ioreq->blkdev->persistent_regions,
|
||||
region);
|
||||
}
|
||||
while ((ioreq->blkdev->persistent_gnt_count < ioreq->blkdev->max_grants)
|
||||
&& new_maps) {
|
||||
/* Go through the list of newly mapped grants and add as many
|
||||
@@ -447,6 +488,7 @@ static int ioreq_map(struct ioreq *ioreq)
|
||||
grant);
|
||||
ioreq->blkdev->persistent_gnt_count++;
|
||||
}
|
||||
assert(!batch_maps || new_maps == 0);
|
||||
}
|
||||
for (i = 0; i < ioreq->v.niov; i++) {
|
||||
ioreq->v.iov[i].iov_base += (uintptr_t)page[i];
|
||||
@@ -971,7 +1013,10 @@ static int blk_connect(struct XenDevice *xendev)
|
||||
blkdev->max_grants = max_requests * BLKIF_MAX_SEGMENTS_PER_REQUEST;
|
||||
blkdev->persistent_gnts = g_tree_new_full((GCompareDataFunc)int_cmp,
|
||||
NULL, NULL,
|
||||
batch_maps ?
|
||||
(GDestroyNotify)g_free :
|
||||
(GDestroyNotify)destroy_grant);
|
||||
blkdev->persistent_regions = NULL;
|
||||
blkdev->persistent_gnt_count = 0;
|
||||
}
|
||||
|
||||
@@ -1000,6 +1045,26 @@ static void blk_disconnect(struct XenDevice *xendev)
|
||||
blkdev->cnt_map--;
|
||||
blkdev->sring = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmap persistent grants before switching to the closed state
|
||||
* so the frontend can free them.
|
||||
*
|
||||
* In the !batch_maps case g_tree_destroy will take care of unmapping
|
||||
* the grant, but in the batch_maps case we need to iterate over every
|
||||
* region in persistent_regions and unmap it.
|
||||
*/
|
||||
if (blkdev->feature_persistent) {
|
||||
g_tree_destroy(blkdev->persistent_gnts);
|
||||
assert(batch_maps || blkdev->persistent_gnt_count == 0);
|
||||
if (batch_maps) {
|
||||
blkdev->persistent_gnt_count = 0;
|
||||
g_slist_foreach(blkdev->persistent_regions,
|
||||
(GFunc)remove_persistent_region, blkdev);
|
||||
g_slist_free(blkdev->persistent_regions);
|
||||
}
|
||||
blkdev->feature_persistent = false;
|
||||
}
|
||||
}
|
||||
|
||||
static int blk_free(struct XenDevice *xendev)
|
||||
@@ -1011,11 +1076,6 @@ static int blk_free(struct XenDevice *xendev)
|
||||
blk_disconnect(xendev);
|
||||
}
|
||||
|
||||
/* Free persistent grants */
|
||||
if (blkdev->feature_persistent) {
|
||||
g_tree_destroy(blkdev->persistent_gnts);
|
||||
}
|
||||
|
||||
while (!QLIST_EMPTY(&blkdev->freelist)) {
|
||||
ioreq = QLIST_FIRST(&blkdev->freelist);
|
||||
QLIST_REMOVE(ioreq, list);
|
||||
|
@@ -80,6 +80,13 @@ int load_image(const char *filename, uint8_t *addr)
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
size = lseek(fd, 0, SEEK_END);
|
||||
if (size == -1) {
|
||||
fprintf(stderr, "file %-20s: get size error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
if (read(fd, addr, size) != size) {
|
||||
close(fd);
|
||||
@@ -748,6 +755,12 @@ int rom_add_file(const char *file, const char *fw_dir,
|
||||
}
|
||||
rom->addr = addr;
|
||||
rom->romsize = lseek(fd, 0, SEEK_END);
|
||||
if (rom->romsize == -1) {
|
||||
fprintf(stderr, "rom: file %-20s: get size error: %s\n",
|
||||
rom->name, strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
rom->datasize = rom->romsize;
|
||||
rom->data = g_malloc0(rom->datasize);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
@@ -798,12 +811,12 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
hwaddr addr, const char *fw_file_name,
|
||||
FWCfgReadCallback fw_callback, void *callback_opaque)
|
||||
{
|
||||
Rom *rom;
|
||||
void *data = NULL;
|
||||
ram_addr_t ret = RAM_ADDR_MAX;
|
||||
|
||||
rom = g_malloc0(sizeof(*rom));
|
||||
rom->name = g_strdup(name);
|
||||
@@ -815,11 +828,13 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
rom_insert(rom);
|
||||
if (fw_file_name && fw_cfg) {
|
||||
char devpath[100];
|
||||
void *data;
|
||||
|
||||
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
|
||||
|
||||
if (rom_file_has_mr) {
|
||||
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
|
||||
ret = memory_region_get_ram_addr(rom->mr);
|
||||
} else {
|
||||
data = rom->data;
|
||||
}
|
||||
@@ -828,7 +843,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
fw_callback, callback_opaque,
|
||||
data, rom->romsize);
|
||||
}
|
||||
return data;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function is specific for elf program because we don't need to allocate
|
||||
|
@@ -935,7 +935,7 @@ void qdev_alias_all_properties(DeviceState *target, Object *source)
|
||||
} while (class != object_class_by_name(TYPE_DEVICE));
|
||||
}
|
||||
|
||||
int qdev_build_hotpluggable_device_list(Object *obj, void *opaque)
|
||||
static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
|
||||
{
|
||||
GSList **list = opaque;
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
@@ -944,10 +944,18 @@ int qdev_build_hotpluggable_device_list(Object *obj, void *opaque)
|
||||
*list = g_slist_append(*list, dev);
|
||||
}
|
||||
|
||||
object_child_foreach(obj, qdev_build_hotpluggable_device_list, opaque);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GSList *qdev_build_hotpluggable_device_list(Object *peripheral)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
|
||||
object_child_foreach(peripheral, qdev_add_hotpluggable_device, &list);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static bool device_get_realized(Object *obj, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
|
@@ -73,11 +73,11 @@ typedef struct ICCBridgeState {
|
||||
MemoryRegion apic_container;
|
||||
} ICCBridgeState;
|
||||
|
||||
#define ICC_BRIGDE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE)
|
||||
#define ICC_BRIDGE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE)
|
||||
|
||||
static void icc_bridge_init(Object *obj)
|
||||
{
|
||||
ICCBridgeState *s = ICC_BRIGDE(obj);
|
||||
ICCBridgeState *s = ICC_BRIDGE(obj);
|
||||
SysBusDevice *sb = SYS_BUS_DEVICE(obj);
|
||||
|
||||
qbus_create_inplace(&s->icc_bus, sizeof(s->icc_bus), TYPE_ICC_BUS,
|
||||
|
@@ -173,20 +173,6 @@
|
||||
|
||||
#define CIRRUS_PNPMMIO_SIZE 0x1000
|
||||
|
||||
#define BLTUNSAFE(s) \
|
||||
( \
|
||||
( /* check dst is within bounds */ \
|
||||
(s)->cirrus_blt_height * ABS((s)->cirrus_blt_dstpitch) \
|
||||
+ ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
|
||||
(s)->vga.vram_size \
|
||||
) || \
|
||||
( /* check src is within bounds */ \
|
||||
(s)->cirrus_blt_height * ABS((s)->cirrus_blt_srcpitch) \
|
||||
+ ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
|
||||
(s)->vga.vram_size \
|
||||
) \
|
||||
)
|
||||
|
||||
struct CirrusVGAState;
|
||||
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
|
||||
uint8_t * dst, const uint8_t * src,
|
||||
@@ -279,6 +265,50 @@ static void cirrus_update_memory_access(CirrusVGAState *s);
|
||||
*
|
||||
***************************************/
|
||||
|
||||
static bool blit_region_is_unsafe(struct CirrusVGAState *s,
|
||||
int32_t pitch, int32_t addr)
|
||||
{
|
||||
if (pitch < 0) {
|
||||
int64_t min = addr
|
||||
+ ((int64_t)s->cirrus_blt_height-1) * pitch;
|
||||
int32_t max = addr
|
||||
+ s->cirrus_blt_width;
|
||||
if (min < 0 || max >= s->vga.vram_size) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
int64_t max = addr
|
||||
+ ((int64_t)s->cirrus_blt_height-1) * pitch
|
||||
+ s->cirrus_blt_width;
|
||||
if (max >= s->vga.vram_size) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool blit_is_unsafe(struct CirrusVGAState *s)
|
||||
{
|
||||
/* should be the case, see cirrus_bitblt_start */
|
||||
assert(s->cirrus_blt_width > 0);
|
||||
assert(s->cirrus_blt_height > 0);
|
||||
|
||||
if (s->cirrus_blt_width > CIRRUS_BLTBUFSIZE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
|
||||
s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {
|
||||
return true;
|
||||
}
|
||||
if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
|
||||
s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
|
||||
uint8_t *dst,const uint8_t *src,
|
||||
int dstpitch,int srcpitch,
|
||||
@@ -636,7 +666,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
|
||||
|
||||
dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
|
||||
|
||||
if (BLTUNSAFE(s))
|
||||
if (blit_is_unsafe(s))
|
||||
return 0;
|
||||
|
||||
(*s->cirrus_rop) (s, dst, src,
|
||||
@@ -654,8 +684,9 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
|
||||
{
|
||||
cirrus_fill_t rop_func;
|
||||
|
||||
if (BLTUNSAFE(s))
|
||||
if (blit_is_unsafe(s)) {
|
||||
return 0;
|
||||
}
|
||||
rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
|
||||
rop_func(s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||
s->cirrus_blt_dstpitch,
|
||||
@@ -752,7 +783,7 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
||||
|
||||
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
|
||||
{
|
||||
if (BLTUNSAFE(s))
|
||||
if (blit_is_unsafe(s))
|
||||
return 0;
|
||||
|
||||
cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
|
||||
|
@@ -56,6 +56,7 @@
|
||||
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qom/qom-qobject.h"
|
||||
#include "exec/ram_addr.h"
|
||||
|
||||
/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
|
||||
* -M pc-i440fx-2.0. Even if the actual amount of AML generated grows
|
||||
@@ -1269,8 +1270,7 @@ acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
|
||||
}
|
||||
|
||||
static void
|
||||
build_srat(GArray *table_data, GArray *linker,
|
||||
AcpiCpuInfo *cpu, PcGuestInfo *guest_info)
|
||||
build_srat(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
|
||||
{
|
||||
AcpiSystemResourceAffinityTable *srat;
|
||||
AcpiSratProcessorAffinity *core;
|
||||
@@ -1300,11 +1300,7 @@ build_srat(GArray *table_data, GArray *linker,
|
||||
core->proximity_lo = curnode;
|
||||
memset(core->proximity_hi, 0, 3);
|
||||
core->local_sapic_eid = 0;
|
||||
if (test_bit(i, cpu->found_cpus)) {
|
||||
core->flags = cpu_to_le32(1);
|
||||
} else {
|
||||
core->flags = cpu_to_le32(0);
|
||||
}
|
||||
core->flags = cpu_to_le32(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1511,7 +1507,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
|
||||
typedef
|
||||
struct AcpiBuildState {
|
||||
/* Copy of table in RAM (for patching). */
|
||||
uint8_t *table_ram;
|
||||
ram_addr_t table_ram;
|
||||
uint32_t table_size;
|
||||
/* Is table patched? */
|
||||
uint8_t patched;
|
||||
@@ -1622,7 +1618,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
|
||||
}
|
||||
if (guest_info->numa_nodes) {
|
||||
acpi_add_table(table_offsets, tables->table_data);
|
||||
build_srat(tables->table_data, tables->linker, &cpu, guest_info);
|
||||
build_srat(tables->table_data, tables->linker, guest_info);
|
||||
}
|
||||
if (acpi_get_mcfg(&mcfg)) {
|
||||
acpi_add_table(table_offsets, tables->table_data);
|
||||
@@ -1716,9 +1712,12 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
|
||||
acpi_build(build_state->guest_info, &tables);
|
||||
|
||||
assert(acpi_data_len(tables.table_data) == build_state->table_size);
|
||||
memcpy(build_state->table_ram, tables.table_data->data,
|
||||
memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
|
||||
build_state->table_size);
|
||||
|
||||
cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
|
||||
build_state->table_size);
|
||||
|
||||
acpi_build_tables_cleanup(&tables, true);
|
||||
}
|
||||
|
||||
@@ -1728,7 +1727,7 @@ static void acpi_build_reset(void *build_opaque)
|
||||
build_state->patched = 0;
|
||||
}
|
||||
|
||||
static void *acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
|
||||
static ram_addr_t acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
|
||||
const char *name)
|
||||
{
|
||||
return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, name,
|
||||
@@ -1777,6 +1776,7 @@ void acpi_setup(PcGuestInfo *guest_info)
|
||||
/* Now expose it all to Guest */
|
||||
build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data,
|
||||
ACPI_BUILD_TABLE_FILE);
|
||||
assert(build_state->table_ram != RAM_ADDR_MAX);
|
||||
build_state->table_size = acpi_data_len(tables.table_data);
|
||||
|
||||
acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader");
|
||||
|
176
hw/i386/acpi-dsdt-mem-hotplug.dsl
Normal file
176
hw/i386/acpi-dsdt-mem-hotplug.dsl
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
External(MEMORY_SLOT_NOTIFY_METHOD, MethodObj)
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
Device(MEMORY_HOTPLUG_DEVICE) {
|
||||
Name(_HID, "PNP0A06")
|
||||
Name(_UID, "Memory hotplug resources")
|
||||
External(MEMORY_SLOTS_NUMBER, IntObj)
|
||||
|
||||
/* Memory hotplug IO registers */
|
||||
OperationRegion(MEMORY_HOTPLUG_IO_REGION, SystemIO,
|
||||
ACPI_MEMORY_HOTPLUG_BASE,
|
||||
ACPI_MEMORY_HOTPLUG_IO_LEN)
|
||||
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, ACPI_MEMORY_HOTPLUG_BASE, ACPI_MEMORY_HOTPLUG_BASE,
|
||||
0, ACPI_MEMORY_HOTPLUG_IO_LEN, IO)
|
||||
})
|
||||
|
||||
Method(_STA, 0) {
|
||||
If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
|
||||
Return(0x0)
|
||||
}
|
||||
/* present, functioning, decoding, not shown in UI */
|
||||
Return(0xB)
|
||||
}
|
||||
|
||||
Field(MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
|
||||
MEMORY_SLOT_ADDR_LOW, 32, // read only
|
||||
MEMORY_SLOT_ADDR_HIGH, 32, // read only
|
||||
MEMORY_SLOT_SIZE_LOW, 32, // read only
|
||||
MEMORY_SLOT_SIZE_HIGH, 32, // read only
|
||||
MEMORY_SLOT_PROXIMITY, 32, // read only
|
||||
}
|
||||
Field(MEMORY_HOTPLUG_IO_REGION, ByteAcc, NoLock, Preserve) {
|
||||
Offset(20),
|
||||
MEMORY_SLOT_ENABLED, 1, // 1 if enabled, read only
|
||||
MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event
|
||||
}
|
||||
|
||||
Mutex (MEMORY_SLOT_LOCK, 0)
|
||||
Field (MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
|
||||
MEMORY_SLOT_SLECTOR, 32, // DIMM selector, write only
|
||||
MEMORY_SLOT_OST_EVENT, 32, // _OST event code, write only
|
||||
MEMORY_SLOT_OST_STATUS, 32, // _OST status code, write only
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_SCAN_METHOD, 0) {
|
||||
If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
|
||||
Return(Zero)
|
||||
}
|
||||
|
||||
Store(Zero, Local0) // Mem devs iterrator
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
while (LLess(Local0, MEMORY_SLOTS_NUMBER)) {
|
||||
Store(Local0, MEMORY_SLOT_SLECTOR) // select Local0 DIMM
|
||||
If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
|
||||
MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
|
||||
Store(1, MEMORY_SLOT_INSERT_EVENT)
|
||||
}
|
||||
// TODO: handle memory eject request
|
||||
Add(Local0, One, Local0) // goto next DIMM
|
||||
}
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(One)
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_STATUS_METHOD, 1) {
|
||||
Store(Zero, Local0)
|
||||
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
|
||||
|
||||
If (LEqual(MEMORY_SLOT_ENABLED, One)) {
|
||||
Store(0xF, Local0)
|
||||
}
|
||||
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(Local0)
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_CRS_METHOD, 1, Serialized) {
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
|
||||
|
||||
Name(MR64, ResourceTemplate() {
|
||||
QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
|
||||
Cacheable, ReadWrite,
|
||||
0x0000000000000000, // Address Space Granularity
|
||||
0x0000000000000000, // Address Range Minimum
|
||||
0xFFFFFFFFFFFFFFFE, // Address Range Maximum
|
||||
0x0000000000000000, // Address Translation Offset
|
||||
0xFFFFFFFFFFFFFFFF, // Address Length
|
||||
,, MW64, AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
|
||||
CreateDWordField(MR64, 14, MINL)
|
||||
CreateDWordField(MR64, 18, MINH)
|
||||
CreateDWordField(MR64, 38, LENL)
|
||||
CreateDWordField(MR64, 42, LENH)
|
||||
CreateDWordField(MR64, 22, MAXL)
|
||||
CreateDWordField(MR64, 26, MAXH)
|
||||
|
||||
Store(MEMORY_SLOT_ADDR_HIGH, MINH)
|
||||
Store(MEMORY_SLOT_ADDR_LOW, MINL)
|
||||
Store(MEMORY_SLOT_SIZE_HIGH, LENH)
|
||||
Store(MEMORY_SLOT_SIZE_LOW, LENL)
|
||||
|
||||
// 64-bit math: MAX = MIN + LEN - 1
|
||||
Add(MINL, LENL, MAXL)
|
||||
Add(MINH, LENH, MAXH)
|
||||
If (LLess(MAXL, MINL)) {
|
||||
Add(MAXH, One, MAXH)
|
||||
}
|
||||
If (LLess(MAXL, One)) {
|
||||
Subtract(MAXH, One, MAXH)
|
||||
}
|
||||
Subtract(MAXL, One, MAXL)
|
||||
|
||||
If (LEqual(MAXH, Zero)){
|
||||
Name(MR32, ResourceTemplate() {
|
||||
DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
|
||||
Cacheable, ReadWrite,
|
||||
0x00000000, // Address Space Granularity
|
||||
0x00000000, // Address Range Minimum
|
||||
0xFFFFFFFE, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0xFFFFFFFF, // Address Length
|
||||
,, MW32, AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
CreateDWordField(MR32, MW32._MIN, MIN)
|
||||
CreateDWordField(MR32, MW32._MAX, MAX)
|
||||
CreateDWordField(MR32, MW32._LEN, LEN)
|
||||
Store(MINL, MIN)
|
||||
Store(MAXL, MAX)
|
||||
Store(LENL, LEN)
|
||||
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(MR32)
|
||||
}
|
||||
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(MR64)
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_PROXIMITY_METHOD, 1) {
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
|
||||
Store(MEMORY_SLOT_PROXIMITY, Local0)
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(Local0)
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_OST_METHOD, 4) {
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
|
||||
Store(Arg1, MEMORY_SLOT_OST_EVENT)
|
||||
Store(Arg2, MEMORY_SLOT_OST_STATUS)
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
}
|
||||
} // Device()
|
||||
} // Scope()
|
@@ -297,13 +297,12 @@ DefinitionBlock (
|
||||
#include "hw/acpi/pc-hotplug.h"
|
||||
#define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE
|
||||
#include "acpi-dsdt-cpu-hotplug.dsl"
|
||||
#include "acpi-dsdt-mem-hotplug.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* General purpose events
|
||||
****************************************************************/
|
||||
External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_SCAN_METHOD, MethodObj)
|
||||
|
||||
Scope(\_GPE) {
|
||||
Name(_HID, "ACPI0006")
|
||||
|
||||
|
@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0xf7,
|
||||
0xa,
|
||||
0x8,
|
||||
0xe,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x1f,
|
||||
0xfc,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
@@ -32,8 +32,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
||||
0x54,
|
||||
0x4c,
|
||||
0x28,
|
||||
0x5,
|
||||
0x10,
|
||||
0x8,
|
||||
0x14,
|
||||
0x20,
|
||||
0x10,
|
||||
0x49,
|
||||
@@ -2593,6 +2593,791 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
||||
0xa,
|
||||
0xb,
|
||||
0x10,
|
||||
0x40,
|
||||
0x31,
|
||||
0x2e,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x42,
|
||||
0x5f,
|
||||
0x50,
|
||||
0x43,
|
||||
0x49,
|
||||
0x30,
|
||||
0x5b,
|
||||
0x82,
|
||||
0x43,
|
||||
0x30,
|
||||
0x4d,
|
||||
0x48,
|
||||
0x50,
|
||||
0x44,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x48,
|
||||
0x49,
|
||||
0x44,
|
||||
0xd,
|
||||
0x50,
|
||||
0x4e,
|
||||
0x50,
|
||||
0x30,
|
||||
0x41,
|
||||
0x30,
|
||||
0x36,
|
||||
0x0,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x55,
|
||||
0x49,
|
||||
0x44,
|
||||
0xd,
|
||||
0x4d,
|
||||
0x65,
|
||||
0x6d,
|
||||
0x6f,
|
||||
0x72,
|
||||
0x79,
|
||||
0x20,
|
||||
0x68,
|
||||
0x6f,
|
||||
0x74,
|
||||
0x70,
|
||||
0x6c,
|
||||
0x75,
|
||||
0x67,
|
||||
0x20,
|
||||
0x72,
|
||||
0x65,
|
||||
0x73,
|
||||
0x6f,
|
||||
0x75,
|
||||
0x72,
|
||||
0x63,
|
||||
0x65,
|
||||
0x73,
|
||||
0x0,
|
||||
0x5b,
|
||||
0x80,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x1,
|
||||
0xb,
|
||||
0x0,
|
||||
0xa,
|
||||
0xa,
|
||||
0x18,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x11,
|
||||
0xd,
|
||||
0xa,
|
||||
0xa,
|
||||
0x47,
|
||||
0x1,
|
||||
0x0,
|
||||
0xa,
|
||||
0x0,
|
||||
0xa,
|
||||
0x0,
|
||||
0x18,
|
||||
0x79,
|
||||
0x0,
|
||||
0x14,
|
||||
0x13,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x41,
|
||||
0x0,
|
||||
0xa0,
|
||||
0x9,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x0,
|
||||
0xa4,
|
||||
0xa,
|
||||
0xb,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x1f,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x3,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x48,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x48,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x20,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x13,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x1,
|
||||
0x0,
|
||||
0x40,
|
||||
0xa,
|
||||
0x4d,
|
||||
0x45,
|
||||
0x53,
|
||||
0x5f,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x1,
|
||||
0x5b,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0x0,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x15,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x3,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x45,
|
||||
0x56,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x43,
|
||||
0x20,
|
||||
0x14,
|
||||
0x4a,
|
||||
0x4,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x43,
|
||||
0x4e,
|
||||
0x0,
|
||||
0xa0,
|
||||
0x9,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x0,
|
||||
0x70,
|
||||
0x0,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0xa2,
|
||||
0x25,
|
||||
0x95,
|
||||
0x60,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x70,
|
||||
0x60,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0x13,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x54,
|
||||
0x46,
|
||||
0x59,
|
||||
0x60,
|
||||
0x1,
|
||||
0x70,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x72,
|
||||
0x60,
|
||||
0x1,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x1,
|
||||
0x14,
|
||||
0x2d,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x53,
|
||||
0x54,
|
||||
0x1,
|
||||
0x70,
|
||||
0x0,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0xb,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x45,
|
||||
0x53,
|
||||
0x5f,
|
||||
0x1,
|
||||
0x70,
|
||||
0xa,
|
||||
0xf,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x60,
|
||||
0x14,
|
||||
0x41,
|
||||
0x18,
|
||||
0x4d,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x9,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x8,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0x11,
|
||||
0x33,
|
||||
0xa,
|
||||
0x30,
|
||||
0x8a,
|
||||
0x2b,
|
||||
0x0,
|
||||
0x0,
|
||||
0xc,
|
||||
0x3,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xfe,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x79,
|
||||
0x0,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0xe,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x12,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x26,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x2a,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x16,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x1a,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x48,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x48,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0xa0,
|
||||
0x14,
|
||||
0x95,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0xa0,
|
||||
0x11,
|
||||
0x95,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x1,
|
||||
0x74,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x74,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0x44,
|
||||
0x7,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x0,
|
||||
0x8,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0x11,
|
||||
0x1f,
|
||||
0xa,
|
||||
0x1c,
|
||||
0x87,
|
||||
0x17,
|
||||
0x0,
|
||||
0x0,
|
||||
0xc,
|
||||
0x3,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xfe,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x79,
|
||||
0x0,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0xa,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0xe,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0x16,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0x14,
|
||||
0x24,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x4d,
|
||||
0x1,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x60,
|
||||
0x14,
|
||||
0x28,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x4,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x69,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x45,
|
||||
0x56,
|
||||
0x70,
|
||||
0x6a,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x43,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0x10,
|
||||
0x45,
|
||||
0xd,
|
||||
0x5f,
|
||||
|
@@ -175,6 +175,9 @@ static void kvm_apic_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(dev);
|
||||
|
||||
/* Not used by KVM, which uses the CPU mp_state instead. */
|
||||
s->wait_for_sipi = 0;
|
||||
|
||||
memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi",
|
||||
APIC_SPACE_SIZE);
|
||||
|
||||
|
@@ -127,7 +127,21 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
||||
}
|
||||
|
||||
cpu_synchronize_all_states();
|
||||
/* In theory, the cpu_synchronize_all_states() call above wouldn't
|
||||
* affect the rest of the code, as the VCPU state inside CPUState
|
||||
* is supposed to always match the VCPU state on the kernel side.
|
||||
*
|
||||
* In practice, calling cpu_synchronize_state() too soon will load the
|
||||
* kernel-side APIC state into X86CPU.apic_state too early, APIC state
|
||||
* won't be reloaded later because CPUState.vcpu_dirty==true, and
|
||||
* outdated APIC state may be migrated to another host.
|
||||
*
|
||||
* The real fix would be to make sure outdated APIC state is read
|
||||
* from the kernel again when necessary. While this is not fixed, we
|
||||
* need the cpu_clean_all_dirty() call below.
|
||||
*/
|
||||
cpu_clean_all_dirty();
|
||||
|
||||
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
|
||||
|
102
hw/i386/pc.c
102
hw/i386/pc.c
@@ -61,6 +61,7 @@
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
#include "trace.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi-visit.h"
|
||||
|
||||
/* debug PC/ISA interrupts */
|
||||
//#define DEBUG_IRQ
|
||||
@@ -1247,6 +1248,11 @@ FWCfgState *pc_memory_init(MachineState *machine,
|
||||
pcms->hotplug_memory_base =
|
||||
ROUND_UP(0x100000000ULL + above_4g_mem_size, 1ULL << 30);
|
||||
|
||||
if (pcms->enforce_aligned_dimm) {
|
||||
/* size hotplug region assuming 1G page max alignment per slot */
|
||||
hotplug_mem_size += (1ULL << 30) * machine->ram_slots;
|
||||
}
|
||||
|
||||
if ((pcms->hotplug_memory_base + hotplug_mem_size) <
|
||||
hotplug_mem_size) {
|
||||
error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT,
|
||||
@@ -1545,6 +1551,37 @@ void qemu_register_pc_machine(QEMUMachine *m)
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
static int pc_dimm_count(Object *obj, void *opaque)
|
||||
{
|
||||
int *count = opaque;
|
||||
|
||||
if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
object_child_foreach(obj, pc_dimm_count, opaque);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pc_existing_dimms_capacity(Object *obj, void *opaque)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
uint64_t *size = opaque;
|
||||
|
||||
if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
|
||||
(*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, &local_err);
|
||||
|
||||
if (local_err) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
object_child_foreach(obj, pc_dimm_count, opaque);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pc_dimm_plug(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
@@ -1556,20 +1593,40 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
|
||||
PCDIMMDevice *dimm = PC_DIMM(dev);
|
||||
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
|
||||
MemoryRegion *mr = ddc->get_memory_region(dimm);
|
||||
uint64_t addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP,
|
||||
&local_err);
|
||||
uint64_t existing_dimms_capacity = 0;
|
||||
uint64_t align = TARGET_PAGE_SIZE;
|
||||
uint64_t addr;
|
||||
|
||||
addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memory_region_get_alignment(mr) && pcms->enforce_aligned_dimm) {
|
||||
align = memory_region_get_alignment(mr);
|
||||
}
|
||||
|
||||
addr = pc_dimm_get_free_addr(pcms->hotplug_memory_base,
|
||||
memory_region_size(&pcms->hotplug_memory),
|
||||
!addr ? NULL : &addr,
|
||||
!addr ? NULL : &addr, align,
|
||||
memory_region_size(mr), &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pc_existing_dimms_capacity(OBJECT(machine), &existing_dimms_capacity)) {
|
||||
error_setg(&local_err, "failed to get total size of existing DIMMs");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (existing_dimms_capacity + memory_region_size(mr) >
|
||||
machine->maxram_size - machine->ram_size) {
|
||||
error_setg(&local_err, "not enough space, currently 0x%" PRIx64
|
||||
" in use of total 0x" RAM_ADDR_FMT,
|
||||
existing_dimms_capacity, machine->maxram_size);
|
||||
goto out;
|
||||
}
|
||||
|
||||
object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
@@ -1598,6 +1655,11 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (kvm_enabled() && !kvm_has_free_slot(machine)) {
|
||||
error_setg(&local_err, "hypervisor has no free memory slots left");
|
||||
goto out;
|
||||
}
|
||||
|
||||
memory_region_add_subregion(&pcms->hotplug_memory,
|
||||
addr - pcms->hotplug_memory_base, mr);
|
||||
vmstate_register_ram(mr, dev);
|
||||
@@ -1711,18 +1773,28 @@ static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
|
||||
pcms->max_ram_below_4g = value;
|
||||
}
|
||||
|
||||
static bool pc_machine_get_vmport(Object *obj, Error **errp)
|
||||
static void pc_machine_get_vmport(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
OnOffAuto vmport = pcms->vmport;
|
||||
|
||||
return pcms->vmport;
|
||||
visit_type_OnOffAuto(v, &vmport, name, errp);
|
||||
}
|
||||
|
||||
static void pc_machine_set_vmport(Object *obj, bool value, Error **errp)
|
||||
static void pc_machine_set_vmport(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
|
||||
pcms->vmport = value;
|
||||
visit_type_OnOffAuto(v, &pcms->vmport, name, errp);
|
||||
}
|
||||
|
||||
static bool pc_machine_get_aligned_dimm(Object *obj, Error **errp)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
|
||||
return pcms->enforce_aligned_dimm;
|
||||
}
|
||||
|
||||
static void pc_machine_initfn(Object *obj)
|
||||
@@ -1737,11 +1809,17 @@ static void pc_machine_initfn(Object *obj)
|
||||
pc_machine_get_max_ram_below_4g,
|
||||
pc_machine_set_max_ram_below_4g,
|
||||
NULL, NULL, NULL);
|
||||
pcms->vmport = !xen_enabled();
|
||||
object_property_add_bool(obj, PC_MACHINE_VMPORT,
|
||||
pc_machine_get_vmport,
|
||||
pc_machine_set_vmport,
|
||||
NULL);
|
||||
|
||||
pcms->vmport = ON_OFF_AUTO_AUTO;
|
||||
object_property_add(obj, PC_MACHINE_VMPORT, "OnOffAuto",
|
||||
pc_machine_get_vmport,
|
||||
pc_machine_set_vmport,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
pcms->enforce_aligned_dimm = true;
|
||||
object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
|
||||
pc_machine_get_aligned_dimm,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
|
@@ -234,9 +234,14 @@ static void pc_init1(MachineState *machine,
|
||||
|
||||
pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
|
||||
|
||||
assert(pc_machine->vmport != ON_OFF_AUTO_MAX);
|
||||
if (pc_machine->vmport == ON_OFF_AUTO_AUTO) {
|
||||
pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
|
||||
}
|
||||
|
||||
/* init basic PC hardware */
|
||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy,
|
||||
!pc_machine->vmport, 0x4);
|
||||
(pc_machine->vmport != ON_OFF_AUTO_ON), 0x4);
|
||||
|
||||
pc_nic_init(isa_bus, pci_bus);
|
||||
|
||||
@@ -305,10 +310,12 @@ static void pc_init_pci(MachineState *machine)
|
||||
|
||||
static void pc_compat_2_1(MachineState *machine)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(machine);
|
||||
smbios_uuid_encoded = false;
|
||||
x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
|
||||
x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
|
||||
x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM);
|
||||
pcms->enforce_aligned_dimm = false;
|
||||
}
|
||||
|
||||
static void pc_compat_2_0(MachineState *machine)
|
||||
@@ -916,17 +923,6 @@ static QEMUMachine xenfv_machine = {
|
||||
.max_cpus = HVM_MAX_VCPUS,
|
||||
.default_machine_opts = "accel=xen",
|
||||
.hot_add_cpu = pc_hot_add_cpu,
|
||||
.compat_props = (GlobalProperty[]) {
|
||||
/* xenfv has no fwcfg and so does not load acpi from QEMU.
|
||||
* as such new acpi features don't work.
|
||||
*/
|
||||
{
|
||||
.driver = "PIIX4_PM",
|
||||
.property = "acpi-pci-hotplug-with-bridge-support",
|
||||
.value = "off",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@@ -242,9 +242,14 @@ static void pc_q35_init(MachineState *machine)
|
||||
|
||||
pc_register_ferr_irq(gsi[13]);
|
||||
|
||||
assert(pc_machine->vmport != ON_OFF_AUTO_MAX);
|
||||
if (pc_machine->vmport == ON_OFF_AUTO_AUTO) {
|
||||
pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
|
||||
}
|
||||
|
||||
/* init basic PC hardware */
|
||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy,
|
||||
!pc_machine->vmport, 0xff0104);
|
||||
(pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104);
|
||||
|
||||
/* connect pm stuff to lpc */
|
||||
ich9_lpc_pm_init(lpc);
|
||||
@@ -284,6 +289,9 @@ static void pc_q35_init(MachineState *machine)
|
||||
|
||||
static void pc_compat_2_1(MachineState *machine)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(machine);
|
||||
|
||||
pcms->enforce_aligned_dimm = false;
|
||||
smbios_uuid_encoded = false;
|
||||
x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
|
||||
x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
|
||||
|
@@ -405,13 +405,12 @@ DefinitionBlock (
|
||||
#include "hw/acpi/pc-hotplug.h"
|
||||
#define CPU_STATUS_BASE ICH9_CPU_HOTPLUG_IO_BASE
|
||||
#include "acpi-dsdt-cpu-hotplug.dsl"
|
||||
#include "acpi-dsdt-mem-hotplug.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* General purpose events
|
||||
****************************************************************/
|
||||
External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_SCAN_METHOD, MethodObj)
|
||||
|
||||
Scope(\_GPE) {
|
||||
Name(_HID, "ACPI0006")
|
||||
|
||||
|
@@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0xe5,
|
||||
0x1c,
|
||||
0xf6,
|
||||
0x1f,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0xb7,
|
||||
0x91,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
@@ -31,9 +31,9 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
||||
0x4e,
|
||||
0x54,
|
||||
0x4c,
|
||||
0x15,
|
||||
0x11,
|
||||
0x13,
|
||||
0x28,
|
||||
0x8,
|
||||
0x14,
|
||||
0x20,
|
||||
0x10,
|
||||
0x49,
|
||||
@@ -7234,6 +7234,791 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
||||
0xa,
|
||||
0xb,
|
||||
0x10,
|
||||
0x40,
|
||||
0x31,
|
||||
0x2e,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x42,
|
||||
0x5f,
|
||||
0x50,
|
||||
0x43,
|
||||
0x49,
|
||||
0x30,
|
||||
0x5b,
|
||||
0x82,
|
||||
0x43,
|
||||
0x30,
|
||||
0x4d,
|
||||
0x48,
|
||||
0x50,
|
||||
0x44,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x48,
|
||||
0x49,
|
||||
0x44,
|
||||
0xd,
|
||||
0x50,
|
||||
0x4e,
|
||||
0x50,
|
||||
0x30,
|
||||
0x41,
|
||||
0x30,
|
||||
0x36,
|
||||
0x0,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x55,
|
||||
0x49,
|
||||
0x44,
|
||||
0xd,
|
||||
0x4d,
|
||||
0x65,
|
||||
0x6d,
|
||||
0x6f,
|
||||
0x72,
|
||||
0x79,
|
||||
0x20,
|
||||
0x68,
|
||||
0x6f,
|
||||
0x74,
|
||||
0x70,
|
||||
0x6c,
|
||||
0x75,
|
||||
0x67,
|
||||
0x20,
|
||||
0x72,
|
||||
0x65,
|
||||
0x73,
|
||||
0x6f,
|
||||
0x75,
|
||||
0x72,
|
||||
0x63,
|
||||
0x65,
|
||||
0x73,
|
||||
0x0,
|
||||
0x5b,
|
||||
0x80,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x1,
|
||||
0xb,
|
||||
0x0,
|
||||
0xa,
|
||||
0xa,
|
||||
0x18,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x11,
|
||||
0xd,
|
||||
0xa,
|
||||
0xa,
|
||||
0x47,
|
||||
0x1,
|
||||
0x0,
|
||||
0xa,
|
||||
0x0,
|
||||
0xa,
|
||||
0x0,
|
||||
0x18,
|
||||
0x79,
|
||||
0x0,
|
||||
0x14,
|
||||
0x13,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x41,
|
||||
0x0,
|
||||
0xa0,
|
||||
0x9,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x0,
|
||||
0xa4,
|
||||
0xa,
|
||||
0xb,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x1f,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x3,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x48,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x48,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x20,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x13,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x1,
|
||||
0x0,
|
||||
0x40,
|
||||
0xa,
|
||||
0x4d,
|
||||
0x45,
|
||||
0x53,
|
||||
0x5f,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x1,
|
||||
0x5b,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0x0,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x15,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x3,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x45,
|
||||
0x56,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x43,
|
||||
0x20,
|
||||
0x14,
|
||||
0x4a,
|
||||
0x4,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x43,
|
||||
0x4e,
|
||||
0x0,
|
||||
0xa0,
|
||||
0x9,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x0,
|
||||
0x70,
|
||||
0x0,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0xa2,
|
||||
0x25,
|
||||
0x95,
|
||||
0x60,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x70,
|
||||
0x60,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0x13,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x54,
|
||||
0x46,
|
||||
0x59,
|
||||
0x60,
|
||||
0x1,
|
||||
0x70,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x72,
|
||||
0x60,
|
||||
0x1,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x1,
|
||||
0x14,
|
||||
0x2d,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x53,
|
||||
0x54,
|
||||
0x1,
|
||||
0x70,
|
||||
0x0,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0xb,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x45,
|
||||
0x53,
|
||||
0x5f,
|
||||
0x1,
|
||||
0x70,
|
||||
0xa,
|
||||
0xf,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x60,
|
||||
0x14,
|
||||
0x41,
|
||||
0x18,
|
||||
0x4d,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x9,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x8,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0x11,
|
||||
0x33,
|
||||
0xa,
|
||||
0x30,
|
||||
0x8a,
|
||||
0x2b,
|
||||
0x0,
|
||||
0x0,
|
||||
0xc,
|
||||
0x3,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xfe,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x79,
|
||||
0x0,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0xe,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x12,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x26,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x2a,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x16,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x1a,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x48,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x48,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0xa0,
|
||||
0x14,
|
||||
0x95,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0xa0,
|
||||
0x11,
|
||||
0x95,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x1,
|
||||
0x74,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x74,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0x44,
|
||||
0x7,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x0,
|
||||
0x8,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0x11,
|
||||
0x1f,
|
||||
0xa,
|
||||
0x1c,
|
||||
0x87,
|
||||
0x17,
|
||||
0x0,
|
||||
0x0,
|
||||
0xc,
|
||||
0x3,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xfe,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x79,
|
||||
0x0,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0xa,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0xe,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0x16,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0x14,
|
||||
0x24,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x4d,
|
||||
0x1,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x60,
|
||||
0x14,
|
||||
0x28,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x4,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x69,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x45,
|
||||
0x56,
|
||||
0x70,
|
||||
0x6a,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x43,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0x10,
|
||||
0x42,
|
||||
0xa,
|
||||
0x5f,
|
||||
|
@@ -645,7 +645,7 @@ static void smbios_build_type_4_table(unsigned instance)
|
||||
|
||||
static void smbios_build_type_16_table(unsigned dimm_cnt)
|
||||
{
|
||||
ram_addr_t size_kb;
|
||||
uint64_t size_kb;
|
||||
|
||||
SMBIOS_BUILD_TABLE_PRE(16, 0x1000, true); /* required */
|
||||
|
||||
@@ -669,10 +669,10 @@ static void smbios_build_type_16_table(unsigned dimm_cnt)
|
||||
#define MAX_T17_STD_SZ 0x7FFF /* (32G - 1M), in Megabytes */
|
||||
#define MAX_T17_EXT_SZ 0x80000000 /* 2P, in Megabytes */
|
||||
|
||||
static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
|
||||
static void smbios_build_type_17_table(unsigned instance, uint64_t size)
|
||||
{
|
||||
char loc_str[128];
|
||||
ram_addr_t size_mb;
|
||||
uint64_t size_mb;
|
||||
|
||||
SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
|
||||
|
||||
@@ -711,9 +711,9 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
|
||||
}
|
||||
|
||||
static void smbios_build_type_19_table(unsigned instance,
|
||||
ram_addr_t start, ram_addr_t size)
|
||||
uint64_t start, uint64_t size)
|
||||
{
|
||||
ram_addr_t end, start_kb, end_kb;
|
||||
uint64_t end, start_kb, end_kb;
|
||||
|
||||
SMBIOS_BUILD_TABLE_PRE(19, 0x1300 + instance, true); /* required */
|
||||
|
||||
|
@@ -11,7 +11,7 @@ static unsigned char ssdm_mem_aml[] = {
|
||||
0x0,
|
||||
0x0,
|
||||
0x2,
|
||||
0x71,
|
||||
0x66,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
@@ -34,9 +34,9 @@ static unsigned char ssdm_mem_aml[] = {
|
||||
0x4e,
|
||||
0x54,
|
||||
0x4c,
|
||||
0x15,
|
||||
0x11,
|
||||
0x13,
|
||||
0x28,
|
||||
0x8,
|
||||
0x14,
|
||||
0x20,
|
||||
0x10,
|
||||
0x42,
|
||||
|
@@ -36,6 +36,8 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
|
||||
Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
|
||||
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
|
||||
Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
|
||||
ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots
|
||||
Name(MEMORY_SLOTS_NUMBER, 0x12345678)
|
||||
}
|
||||
|
||||
|
||||
@@ -117,167 +119,4 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
External(MEMORY_SLOT_NOTIFY_METHOD, MethodObj)
|
||||
Scope(\_SB.PCI0) {
|
||||
Device(MEMORY_HOTPLUG_DEVICE) {
|
||||
Name(_HID, "PNP0A06")
|
||||
Name(_UID, "Memory hotplug resources")
|
||||
|
||||
ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots
|
||||
Name(MEMORY_SLOTS_NUMBER, 0x12345678)
|
||||
|
||||
/* Memory hotplug IO registers */
|
||||
OperationRegion(MEMORY_HOTPLUG_IO_REGION, SystemIO,
|
||||
ACPI_MEMORY_HOTPLUG_BASE,
|
||||
ACPI_MEMORY_HOTPLUG_IO_LEN)
|
||||
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, ACPI_MEMORY_HOTPLUG_BASE, ACPI_MEMORY_HOTPLUG_BASE,
|
||||
0, ACPI_MEMORY_HOTPLUG_IO_LEN, IO)
|
||||
})
|
||||
|
||||
Method(_STA, 0) {
|
||||
If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
|
||||
Return(0x0)
|
||||
}
|
||||
/* present, functioning, decoding, not shown in UI */
|
||||
Return(0xB)
|
||||
}
|
||||
|
||||
Field(MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
|
||||
MEMORY_SLOT_ADDR_LOW, 32, // read only
|
||||
MEMORY_SLOT_ADDR_HIGH, 32, // read only
|
||||
MEMORY_SLOT_SIZE_LOW, 32, // read only
|
||||
MEMORY_SLOT_SIZE_HIGH, 32, // read only
|
||||
MEMORY_SLOT_PROXIMITY, 32, // read only
|
||||
}
|
||||
Field(MEMORY_HOTPLUG_IO_REGION, ByteAcc, NoLock, Preserve) {
|
||||
Offset(20),
|
||||
MEMORY_SLOT_ENABLED, 1, // 1 if enabled, read only
|
||||
MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event
|
||||
}
|
||||
|
||||
Mutex (MEMORY_SLOT_LOCK, 0)
|
||||
Field (MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
|
||||
MEMORY_SLOT_SLECTOR, 32, // DIMM selector, write only
|
||||
MEMORY_SLOT_OST_EVENT, 32, // _OST event code, write only
|
||||
MEMORY_SLOT_OST_STATUS, 32, // _OST status code, write only
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_SCAN_METHOD, 0) {
|
||||
If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
|
||||
Return(Zero)
|
||||
}
|
||||
|
||||
Store(Zero, Local0) // Mem devs iterrator
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
while (LLess(Local0, MEMORY_SLOTS_NUMBER)) {
|
||||
Store(Local0, MEMORY_SLOT_SLECTOR) // select Local0 DIMM
|
||||
If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
|
||||
MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
|
||||
Store(1, MEMORY_SLOT_INSERT_EVENT)
|
||||
}
|
||||
// TODO: handle memory eject request
|
||||
Add(Local0, One, Local0) // goto next DIMM
|
||||
}
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(One)
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_STATUS_METHOD, 1) {
|
||||
Store(Zero, Local0)
|
||||
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
|
||||
|
||||
If (LEqual(MEMORY_SLOT_ENABLED, One)) {
|
||||
Store(0xF, Local0)
|
||||
}
|
||||
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(Local0)
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_CRS_METHOD, 1, Serialized) {
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
|
||||
|
||||
Name(MR64, ResourceTemplate() {
|
||||
QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
|
||||
Cacheable, ReadWrite,
|
||||
0x0000000000000000, // Address Space Granularity
|
||||
0x0000000000000000, // Address Range Minimum
|
||||
0xFFFFFFFFFFFFFFFE, // Address Range Maximum
|
||||
0x0000000000000000, // Address Translation Offset
|
||||
0xFFFFFFFFFFFFFFFF, // Address Length
|
||||
,, MW64, AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
|
||||
CreateDWordField(MR64, 14, MINL)
|
||||
CreateDWordField(MR64, 18, MINH)
|
||||
CreateDWordField(MR64, 38, LENL)
|
||||
CreateDWordField(MR64, 42, LENH)
|
||||
CreateDWordField(MR64, 22, MAXL)
|
||||
CreateDWordField(MR64, 26, MAXH)
|
||||
|
||||
Store(MEMORY_SLOT_ADDR_HIGH, MINH)
|
||||
Store(MEMORY_SLOT_ADDR_LOW, MINL)
|
||||
Store(MEMORY_SLOT_SIZE_HIGH, LENH)
|
||||
Store(MEMORY_SLOT_SIZE_LOW, LENL)
|
||||
|
||||
// 64-bit math: MAX = MIN + LEN - 1
|
||||
Add(MINL, LENL, MAXL)
|
||||
Add(MINH, LENH, MAXH)
|
||||
If (LLess(MAXL, MINL)) {
|
||||
Add(MAXH, One, MAXH)
|
||||
}
|
||||
If (LLess(MAXL, One)) {
|
||||
Subtract(MAXH, One, MAXH)
|
||||
}
|
||||
Subtract(MAXL, One, MAXL)
|
||||
|
||||
If (LEqual(MAXH, Zero)){
|
||||
Name(MR32, ResourceTemplate() {
|
||||
DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
|
||||
Cacheable, ReadWrite,
|
||||
0x00000000, // Address Space Granularity
|
||||
0x00000000, // Address Range Minimum
|
||||
0xFFFFFFFE, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0xFFFFFFFF, // Address Length
|
||||
,, MW32, AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
CreateDWordField(MR32, MW32._MIN, MIN)
|
||||
CreateDWordField(MR32, MW32._MAX, MAX)
|
||||
CreateDWordField(MR32, MW32._LEN, LEN)
|
||||
Store(MINL, MIN)
|
||||
Store(MAXL, MAX)
|
||||
Store(LENL, LEN)
|
||||
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(MR32)
|
||||
}
|
||||
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(MR64)
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_PROXIMITY_METHOD, 1) {
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
|
||||
Store(MEMORY_SLOT_PROXIMITY, Local0)
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
Return(Local0)
|
||||
}
|
||||
|
||||
Method(MEMORY_SLOT_OST_METHOD, 4) {
|
||||
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
|
||||
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
|
||||
Store(Arg1, MEMORY_SLOT_OST_EVENT)
|
||||
Store(Arg2, MEMORY_SLOT_OST_STATUS)
|
||||
Release(MEMORY_SLOT_LOCK)
|
||||
}
|
||||
} // Device()
|
||||
} // Scope()
|
||||
}
|
||||
|
@@ -2,13 +2,13 @@ static unsigned char acpi_pci64_length[] = {
|
||||
0x6f
|
||||
};
|
||||
static unsigned char acpi_s4_pkg[] = {
|
||||
0x8f
|
||||
0x99
|
||||
};
|
||||
static unsigned short ssdt_mctrl_nr_slots[] = {
|
||||
0x1aa
|
||||
static unsigned char ssdt_mctrl_nr_slots[] = {
|
||||
0x7d
|
||||
};
|
||||
static unsigned char acpi_s3_name[] = {
|
||||
0x7c
|
||||
0x86
|
||||
};
|
||||
static unsigned char acpi_pci32_start[] = {
|
||||
0x2f
|
||||
@@ -21,12 +21,12 @@ static unsigned char ssdp_misc_aml[] = {
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x7e,
|
||||
0x4,
|
||||
0x6c,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x8b,
|
||||
0x3,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
@@ -49,12 +49,12 @@ static unsigned char ssdp_misc_aml[] = {
|
||||
0x4e,
|
||||
0x54,
|
||||
0x4c,
|
||||
0x15,
|
||||
0x11,
|
||||
0x13,
|
||||
0x28,
|
||||
0x8,
|
||||
0x14,
|
||||
0x20,
|
||||
0x10,
|
||||
0x42,
|
||||
0x4c,
|
||||
0x5,
|
||||
0x5c,
|
||||
0x0,
|
||||
@@ -136,6 +136,16 @@ static unsigned char ssdp_misc_aml[] = {
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x8,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0xc,
|
||||
0x78,
|
||||
0x56,
|
||||
0x34,
|
||||
0x12,
|
||||
0x10,
|
||||
0x29,
|
||||
0x5c,
|
||||
@@ -370,809 +380,13 @@ static unsigned char ssdp_misc_aml[] = {
|
||||
0x49,
|
||||
0x4f,
|
||||
0x4d,
|
||||
0x58,
|
||||
0x10,
|
||||
0x4b,
|
||||
0x31,
|
||||
0x5c,
|
||||
0x2e,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x42,
|
||||
0x5f,
|
||||
0x50,
|
||||
0x43,
|
||||
0x49,
|
||||
0x30,
|
||||
0x5b,
|
||||
0x82,
|
||||
0x4d,
|
||||
0x30,
|
||||
0x4d,
|
||||
0x48,
|
||||
0x50,
|
||||
0x44,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x48,
|
||||
0x49,
|
||||
0x44,
|
||||
0xd,
|
||||
0x50,
|
||||
0x4e,
|
||||
0x50,
|
||||
0x30,
|
||||
0x41,
|
||||
0x30,
|
||||
0x36,
|
||||
0x0,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x55,
|
||||
0x49,
|
||||
0x44,
|
||||
0xd,
|
||||
0x4d,
|
||||
0x65,
|
||||
0x6d,
|
||||
0x6f,
|
||||
0x72,
|
||||
0x79,
|
||||
0x20,
|
||||
0x68,
|
||||
0x6f,
|
||||
0x74,
|
||||
0x70,
|
||||
0x6c,
|
||||
0x75,
|
||||
0x67,
|
||||
0x20,
|
||||
0x72,
|
||||
0x65,
|
||||
0x73,
|
||||
0x6f,
|
||||
0x75,
|
||||
0x72,
|
||||
0x63,
|
||||
0x65,
|
||||
0x73,
|
||||
0x0,
|
||||
0x8,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0xc,
|
||||
0x78,
|
||||
0x56,
|
||||
0x34,
|
||||
0x12,
|
||||
0x5b,
|
||||
0x80,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x1,
|
||||
0xb,
|
||||
0x0,
|
||||
0xa,
|
||||
0xa,
|
||||
0x18,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x11,
|
||||
0xd,
|
||||
0xa,
|
||||
0xa,
|
||||
0x47,
|
||||
0x1,
|
||||
0x0,
|
||||
0xa,
|
||||
0x0,
|
||||
0xa,
|
||||
0x0,
|
||||
0x18,
|
||||
0x79,
|
||||
0x0,
|
||||
0x14,
|
||||
0x13,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x41,
|
||||
0x0,
|
||||
0xa0,
|
||||
0x9,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x0,
|
||||
0xa4,
|
||||
0xa,
|
||||
0xb,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x1f,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x3,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x48,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x48,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x20,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x13,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x1,
|
||||
0x0,
|
||||
0x40,
|
||||
0xa,
|
||||
0x4d,
|
||||
0x45,
|
||||
0x53,
|
||||
0x5f,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x1,
|
||||
0x5b,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0x0,
|
||||
0x5b,
|
||||
0x81,
|
||||
0x15,
|
||||
0x48,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x3,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x45,
|
||||
0x56,
|
||||
0x20,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x43,
|
||||
0x20,
|
||||
0x14,
|
||||
0x4a,
|
||||
0x4,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x43,
|
||||
0x4e,
|
||||
0x0,
|
||||
0xa0,
|
||||
0x9,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x0,
|
||||
0x70,
|
||||
0x0,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0xa2,
|
||||
0x25,
|
||||
0x95,
|
||||
0x60,
|
||||
0x4d,
|
||||
0x44,
|
||||
0x4e,
|
||||
0x52,
|
||||
0x70,
|
||||
0x60,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0x13,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x54,
|
||||
0x46,
|
||||
0x59,
|
||||
0x60,
|
||||
0x1,
|
||||
0x70,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x53,
|
||||
0x72,
|
||||
0x60,
|
||||
0x1,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x1,
|
||||
0x14,
|
||||
0x2d,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x53,
|
||||
0x54,
|
||||
0x1,
|
||||
0x70,
|
||||
0x0,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0xb,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x45,
|
||||
0x53,
|
||||
0x5f,
|
||||
0x1,
|
||||
0x70,
|
||||
0xa,
|
||||
0xf,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x60,
|
||||
0x14,
|
||||
0x41,
|
||||
0x18,
|
||||
0x4d,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x9,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x8,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0x11,
|
||||
0x33,
|
||||
0xa,
|
||||
0x30,
|
||||
0x8a,
|
||||
0x2b,
|
||||
0x0,
|
||||
0x0,
|
||||
0xc,
|
||||
0x3,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xfe,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x79,
|
||||
0x0,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0xe,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x12,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x26,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x2a,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x16,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0xa,
|
||||
0x1a,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x48,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x42,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x48,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x48,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0xa0,
|
||||
0x14,
|
||||
0x95,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x72,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0xa0,
|
||||
0x11,
|
||||
0x95,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x1,
|
||||
0x74,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x74,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x1,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0xa0,
|
||||
0x44,
|
||||
0x7,
|
||||
0x93,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x48,
|
||||
0x0,
|
||||
0x8,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0x11,
|
||||
0x1f,
|
||||
0xa,
|
||||
0x1c,
|
||||
0x87,
|
||||
0x17,
|
||||
0x0,
|
||||
0x0,
|
||||
0xc,
|
||||
0x3,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xfe,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x79,
|
||||
0x0,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0xa,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0xe,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x8a,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0xa,
|
||||
0x16,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x4c,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x70,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x4c,
|
||||
0x4c,
|
||||
0x45,
|
||||
0x4e,
|
||||
0x5f,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x33,
|
||||
0x32,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x4d,
|
||||
0x52,
|
||||
0x36,
|
||||
0x34,
|
||||
0x14,
|
||||
0x24,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x4d,
|
||||
0x1,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x4d,
|
||||
0x50,
|
||||
0x58,
|
||||
0x5f,
|
||||
0x60,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xa4,
|
||||
0x60,
|
||||
0x14,
|
||||
0x28,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x4,
|
||||
0x5b,
|
||||
0x23,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b,
|
||||
0xff,
|
||||
0xff,
|
||||
0x70,
|
||||
0x99,
|
||||
0x68,
|
||||
0x0,
|
||||
0x4d,
|
||||
0x53,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x70,
|
||||
0x69,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x45,
|
||||
0x56,
|
||||
0x70,
|
||||
0x6a,
|
||||
0x4d,
|
||||
0x4f,
|
||||
0x53,
|
||||
0x43,
|
||||
0x5b,
|
||||
0x27,
|
||||
0x4d,
|
||||
0x4c,
|
||||
0x43,
|
||||
0x4b
|
||||
0x58
|
||||
};
|
||||
static unsigned char ssdt_isa_pest[] = {
|
||||
0xd0
|
||||
0xda
|
||||
};
|
||||
static unsigned char acpi_s4_name[] = {
|
||||
0x88
|
||||
0x92
|
||||
};
|
||||
static unsigned char acpi_pci64_start[] = {
|
||||
0x4d
|
||||
|
279
hw/ide/ahci.c
279
hw/ide/ahci.c
@@ -730,7 +730,8 @@ static int prdt_tbl_entry_size(const AHCI_SG *tbl)
|
||||
return (le32_to_cpu(tbl->flags_size) & AHCI_PRDT_SIZE_MASK) + 1;
|
||||
}
|
||||
|
||||
static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
|
||||
static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist,
|
||||
int32_t offset)
|
||||
{
|
||||
AHCICmdHdr *cmd = ad->cur_cmd;
|
||||
uint32_t opts = le32_to_cpu(cmd->opts);
|
||||
@@ -741,13 +742,21 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
|
||||
uint8_t *prdt;
|
||||
int i;
|
||||
int r = 0;
|
||||
int sum = 0;
|
||||
uint64_t sum = 0;
|
||||
int off_idx = -1;
|
||||
int off_pos = -1;
|
||||
int64_t off_pos = -1;
|
||||
int tbl_entry_size;
|
||||
IDEBus *bus = &ad->port;
|
||||
BusState *qbus = BUS(bus);
|
||||
|
||||
/*
|
||||
* Note: AHCI PRDT can describe up to 256GiB. SATA/ATA only support
|
||||
* transactions of up to 32MiB as of ATA8-ACS3 rev 1b, assuming a
|
||||
* 512 byte sector size. We limit the PRDT in this implementation to
|
||||
* a reasonably large 2GiB, which can accommodate the maximum transfer
|
||||
* request for sector sizes up to 32K.
|
||||
*/
|
||||
|
||||
if (!sglist_alloc_hint) {
|
||||
DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
|
||||
return -1;
|
||||
@@ -782,7 +791,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
|
||||
}
|
||||
if ((off_idx == -1) || (off_pos < 0) || (off_pos > tbl_entry_size)) {
|
||||
DPRINTF(ad->port_no, "%s: Incorrect offset! "
|
||||
"off_idx: %d, off_pos: %d\n",
|
||||
"off_idx: %d, off_pos: %"PRId64"\n",
|
||||
__func__, off_idx, off_pos);
|
||||
r = -1;
|
||||
goto out;
|
||||
@@ -797,6 +806,13 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
|
||||
/* flags_size is zero-based */
|
||||
qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr),
|
||||
prdt_tbl_entry_size(&tbl[i]));
|
||||
if (sglist->size > INT32_MAX) {
|
||||
error_report("AHCI Physical Region Descriptor Table describes "
|
||||
"more than 2 GiB.\n");
|
||||
qemu_sglist_destroy(sglist);
|
||||
r = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,6 +854,21 @@ static void ncq_cb(void *opaque, int ret)
|
||||
ncq_tfs->used = 0;
|
||||
}
|
||||
|
||||
static int is_ncq(uint8_t ata_cmd)
|
||||
{
|
||||
/* Based on SATA 3.2 section 13.6.3.2 */
|
||||
switch (ata_cmd) {
|
||||
case READ_FPDMA_QUEUED:
|
||||
case WRITE_FPDMA_QUEUED:
|
||||
case NCQ_NON_DATA:
|
||||
case RECEIVE_FPDMA_QUEUED:
|
||||
case SEND_FPDMA_QUEUED:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
|
||||
int slot)
|
||||
{
|
||||
@@ -903,16 +934,106 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
|
||||
ncq_cb, ncq_tfs);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(port, "error: tried to process non-NCQ command as NCQ\n");
|
||||
if (is_ncq(cmd_fis[2])) {
|
||||
DPRINTF(port,
|
||||
"error: unsupported NCQ command (0x%02x) received\n",
|
||||
cmd_fis[2]);
|
||||
} else {
|
||||
DPRINTF(port,
|
||||
"error: tried to process non-NCQ command as NCQ\n");
|
||||
}
|
||||
qemu_sglist_destroy(&ncq_tfs->sglist);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_reg_h2d_fis(AHCIState *s, int port,
|
||||
int slot, uint8_t *cmd_fis)
|
||||
{
|
||||
IDEState *ide_state = &s->dev[port].port.ifs[0];
|
||||
AHCICmdHdr *cmd = s->dev[port].cur_cmd;
|
||||
uint32_t opts = le32_to_cpu(cmd->opts);
|
||||
|
||||
if (cmd_fis[1] & 0x0F) {
|
||||
DPRINTF(port, "Port Multiplier not supported."
|
||||
" cmd_fis[0]=%02x cmd_fis[1]=%02x cmd_fis[2]=%02x\n",
|
||||
cmd_fis[0], cmd_fis[1], cmd_fis[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_fis[1] & 0x70) {
|
||||
DPRINTF(port, "Reserved flags set in H2D Register FIS."
|
||||
" cmd_fis[0]=%02x cmd_fis[1]=%02x cmd_fis[2]=%02x\n",
|
||||
cmd_fis[0], cmd_fis[1], cmd_fis[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(cmd_fis[1] & SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER)) {
|
||||
switch (s->dev[port].port_state) {
|
||||
case STATE_RUN:
|
||||
if (cmd_fis[15] & ATA_SRST) {
|
||||
s->dev[port].port_state = STATE_RESET;
|
||||
}
|
||||
break;
|
||||
case STATE_RESET:
|
||||
if (!(cmd_fis[15] & ATA_SRST)) {
|
||||
ahci_reset_port(s, port);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for NCQ command */
|
||||
if (is_ncq(cmd_fis[2])) {
|
||||
process_ncq_command(s, port, cmd_fis, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Decompose the FIS:
|
||||
* AHCI does not interpret FIS packets, it only forwards them.
|
||||
* SATA 1.0 describes how to decode LBA28 and CHS FIS packets.
|
||||
* Later specifications, e.g, SATA 3.2, describe LBA48 FIS packets.
|
||||
*
|
||||
* ATA4 describes sector number for LBA28/CHS commands.
|
||||
* ATA6 describes sector number for LBA48 commands.
|
||||
* ATA8 deprecates CHS fully, describing only LBA28/48.
|
||||
*
|
||||
* We dutifully convert the FIS into IDE registers, and allow the
|
||||
* core layer to interpret them as needed. */
|
||||
ide_state->feature = cmd_fis[3];
|
||||
ide_state->sector = cmd_fis[4]; /* LBA 7:0 */
|
||||
ide_state->lcyl = cmd_fis[5]; /* LBA 15:8 */
|
||||
ide_state->hcyl = cmd_fis[6]; /* LBA 23:16 */
|
||||
ide_state->select = cmd_fis[7]; /* LBA 27:24 (LBA28) */
|
||||
ide_state->hob_sector = cmd_fis[8]; /* LBA 31:24 */
|
||||
ide_state->hob_lcyl = cmd_fis[9]; /* LBA 39:32 */
|
||||
ide_state->hob_hcyl = cmd_fis[10]; /* LBA 47:40 */
|
||||
ide_state->hob_feature = cmd_fis[11];
|
||||
ide_state->nsector = (int64_t)((cmd_fis[13] << 8) | cmd_fis[12]);
|
||||
/* 14, 16, 17, 18, 19: Reserved (SATA 1.0) */
|
||||
/* 15: Only valid when UPDATE_COMMAND not set. */
|
||||
|
||||
/* Copy the ACMD field (ATAPI packet, if any) from the AHCI command
|
||||
* table to ide_state->io_buffer */
|
||||
if (opts & AHCI_CMD_ATAPI) {
|
||||
memcpy(ide_state->io_buffer, &cmd_fis[AHCI_COMMAND_TABLE_ACMD], 0x10);
|
||||
debug_print_fis(ide_state->io_buffer, 0x10);
|
||||
s->dev[port].done_atapi_packet = false;
|
||||
/* XXX send PIO setup FIS */
|
||||
}
|
||||
|
||||
ide_state->error = 0;
|
||||
|
||||
/* Reset transferred byte counter */
|
||||
cmd->status = 0;
|
||||
|
||||
/* We're ready to process the command in FIS byte 2. */
|
||||
ide_exec_cmd(&s->dev[port].port, cmd_fis[2]);
|
||||
}
|
||||
|
||||
static int handle_cmd(AHCIState *s, int port, int slot)
|
||||
{
|
||||
IDEState *ide_state;
|
||||
uint32_t opts;
|
||||
uint64_t tbl_addr;
|
||||
AHCICmdHdr *cmd;
|
||||
uint8_t *cmd_fis;
|
||||
@@ -924,142 +1045,48 @@ static int handle_cmd(AHCIState *s, int port, int slot)
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd = &((AHCICmdHdr *)s->dev[port].lst)[slot];
|
||||
|
||||
if (!s->dev[port].lst) {
|
||||
DPRINTF(port, "error: lst not given but cmd handled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd = &((AHCICmdHdr *)s->dev[port].lst)[slot];
|
||||
/* remember current slot handle for later */
|
||||
s->dev[port].cur_cmd = cmd;
|
||||
|
||||
opts = le32_to_cpu(cmd->opts);
|
||||
tbl_addr = le64_to_cpu(cmd->tbl_addr);
|
||||
|
||||
cmd_len = 0x80;
|
||||
cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len,
|
||||
DMA_DIRECTION_FROM_DEVICE);
|
||||
|
||||
if (!cmd_fis) {
|
||||
DPRINTF(port, "error: guest passed us an invalid cmd fis\n");
|
||||
/* The device we are working for */
|
||||
ide_state = &s->dev[port].port.ifs[0];
|
||||
if (!ide_state->blk) {
|
||||
DPRINTF(port, "error: guest accessed unused port");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The device we are working for */
|
||||
ide_state = &s->dev[port].port.ifs[0];
|
||||
|
||||
if (!ide_state->blk) {
|
||||
DPRINTF(port, "error: guest accessed unused port");
|
||||
tbl_addr = le64_to_cpu(cmd->tbl_addr);
|
||||
cmd_len = 0x80;
|
||||
cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len,
|
||||
DMA_DIRECTION_FROM_DEVICE);
|
||||
if (!cmd_fis) {
|
||||
DPRINTF(port, "error: guest passed us an invalid cmd fis\n");
|
||||
return -1;
|
||||
} else if (cmd_len != 0x80) {
|
||||
ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_HBUS_ERR);
|
||||
DPRINTF(port, "error: dma_memory_map failed: "
|
||||
"(len(%02"PRIx64") != 0x80)\n",
|
||||
cmd_len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
debug_print_fis(cmd_fis, 0x90);
|
||||
//debug_print_fis(cmd_fis, (opts & AHCI_CMD_HDR_CMD_FIS_LEN) * 4);
|
||||
debug_print_fis(cmd_fis, 0x80);
|
||||
|
||||
switch (cmd_fis[0]) {
|
||||
case SATA_FIS_TYPE_REGISTER_H2D:
|
||||
handle_reg_h2d_fis(s, port, slot, cmd_fis);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(port, "unknown command cmd_fis[0]=%02x cmd_fis[1]=%02x "
|
||||
"cmd_fis[2]=%02x\n", cmd_fis[0], cmd_fis[1],
|
||||
cmd_fis[2]);
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmd_fis[1]) {
|
||||
case SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER:
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
DPRINTF(port, "unknown command cmd_fis[0]=%02x cmd_fis[1]=%02x "
|
||||
"cmd_fis[2]=%02x\n", cmd_fis[0], cmd_fis[1],
|
||||
cmd_fis[2]);
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (s->dev[port].port_state) {
|
||||
case STATE_RUN:
|
||||
if (cmd_fis[15] & ATA_SRST) {
|
||||
s->dev[port].port_state = STATE_RESET;
|
||||
}
|
||||
break;
|
||||
case STATE_RESET:
|
||||
if (!(cmd_fis[15] & ATA_SRST)) {
|
||||
ahci_reset_port(s, port);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd_fis[1] == SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER) {
|
||||
|
||||
/* Check for NCQ command */
|
||||
if ((cmd_fis[2] == READ_FPDMA_QUEUED) ||
|
||||
(cmd_fis[2] == WRITE_FPDMA_QUEUED)) {
|
||||
process_ncq_command(s, port, cmd_fis, slot);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Decompose the FIS */
|
||||
ide_state->nsector = (int64_t)((cmd_fis[13] << 8) | cmd_fis[12]);
|
||||
ide_state->feature = cmd_fis[3];
|
||||
if (!ide_state->nsector) {
|
||||
ide_state->nsector = 256;
|
||||
}
|
||||
|
||||
if (ide_state->drive_kind != IDE_CD) {
|
||||
/*
|
||||
* We set the sector depending on the sector defined in the FIS.
|
||||
* Unfortunately, the spec isn't exactly obvious on this one.
|
||||
*
|
||||
* Apparently LBA48 commands set fis bytes 10,9,8,6,5,4 to the
|
||||
* 48 bit sector number. ATA_CMD_READ_DMA_EXT is an example for
|
||||
* such a command.
|
||||
*
|
||||
* Non-LBA48 commands however use 7[lower 4 bits],6,5,4 to define a
|
||||
* 28-bit sector number. ATA_CMD_READ_DMA is an example for such
|
||||
* a command.
|
||||
*
|
||||
* Since the spec doesn't explicitly state what each field should
|
||||
* do, I simply assume non-used fields as reserved and OR everything
|
||||
* together, independent of the command.
|
||||
*/
|
||||
ide_set_sector(ide_state, ((uint64_t)cmd_fis[10] << 40)
|
||||
| ((uint64_t)cmd_fis[9] << 32)
|
||||
/* This is used for LBA48 commands */
|
||||
| ((uint64_t)cmd_fis[8] << 24)
|
||||
/* This is used for non-LBA48 commands */
|
||||
| ((uint64_t)(cmd_fis[7] & 0xf) << 24)
|
||||
| ((uint64_t)cmd_fis[6] << 16)
|
||||
| ((uint64_t)cmd_fis[5] << 8)
|
||||
| cmd_fis[4]);
|
||||
}
|
||||
|
||||
/* Copy the ACMD field (ATAPI packet, if any) from the AHCI command
|
||||
* table to ide_state->io_buffer
|
||||
*/
|
||||
if (opts & AHCI_CMD_ATAPI) {
|
||||
memcpy(ide_state->io_buffer, &cmd_fis[AHCI_COMMAND_TABLE_ACMD], 0x10);
|
||||
ide_state->lcyl = 0x14;
|
||||
ide_state->hcyl = 0xeb;
|
||||
debug_print_fis(ide_state->io_buffer, 0x10);
|
||||
ide_state->feature = IDE_FEATURE_DMA;
|
||||
s->dev[port].done_atapi_packet = false;
|
||||
/* XXX send PIO setup FIS */
|
||||
}
|
||||
|
||||
ide_state->error = 0;
|
||||
|
||||
/* Reset transferred byte counter */
|
||||
cmd->status = 0;
|
||||
|
||||
/* We're ready to process the command in FIS byte 2. */
|
||||
ide_exec_cmd(&s->dev[port].port, cmd_fis[2]);
|
||||
}
|
||||
|
||||
out:
|
||||
dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE,
|
||||
cmd_len);
|
||||
@@ -1089,10 +1116,11 @@ static void ahci_start_transfer(IDEDMA *dma)
|
||||
if (is_atapi && !ad->done_atapi_packet) {
|
||||
/* already prepopulated iobuffer */
|
||||
ad->done_atapi_packet = true;
|
||||
size = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ahci_populate_sglist(ad, &s->sg, 0)) {
|
||||
if (ahci_dma_prepare_buf(dma, is_write)) {
|
||||
has_sglist = 1;
|
||||
}
|
||||
|
||||
@@ -1139,16 +1167,19 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s,
|
||||
* Not currently invoked by PIO R/W chains,
|
||||
* which invoke ahci_populate_sglist via ahci_start_transfer.
|
||||
*/
|
||||
static int ahci_dma_prepare_buf(IDEDMA *dma, int is_write)
|
||||
static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int is_write)
|
||||
{
|
||||
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
||||
IDEState *s = &ad->port.ifs[0];
|
||||
|
||||
ahci_populate_sglist(ad, &s->sg, 0);
|
||||
if (ahci_populate_sglist(ad, &s->sg, s->io_buffer_offset) == -1) {
|
||||
DPRINTF(ad->port_no, "ahci_dma_prepare_buf failed.\n");
|
||||
return -1;
|
||||
}
|
||||
s->io_buffer_size = s->sg.size;
|
||||
|
||||
DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size);
|
||||
return s->io_buffer_size != 0;
|
||||
return s->io_buffer_size;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -186,6 +186,9 @@
|
||||
|
||||
#define READ_FPDMA_QUEUED 0x60
|
||||
#define WRITE_FPDMA_QUEUED 0x61
|
||||
#define NCQ_NON_DATA 0x63
|
||||
#define RECEIVE_FPDMA_QUEUED 0x65
|
||||
#define SEND_FPDMA_QUEUED 0x64
|
||||
|
||||
#define RES_FIS_DSFIS 0x00
|
||||
#define RES_FIS_PSFIS 0x20
|
||||
|
@@ -592,6 +592,7 @@ static void ide_sector_read_cb(void *opaque, int ret)
|
||||
|
||||
ide_set_sector(s, ide_get_sector(s) + n);
|
||||
s->nsector -= n;
|
||||
s->io_buffer_offset += 512 * n;
|
||||
}
|
||||
|
||||
void ide_sector_read(IDEState *s)
|
||||
@@ -730,10 +731,11 @@ void ide_dma_cb(void *opaque, int ret)
|
||||
n = s->nsector;
|
||||
s->io_buffer_index = 0;
|
||||
s->io_buffer_size = n * 512;
|
||||
if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) == 0) {
|
||||
if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) < 512) {
|
||||
/* The PRDs were too short. Reset the Active bit, but don't raise an
|
||||
* interrupt. */
|
||||
s->status = READY_STAT | SEEK_STAT;
|
||||
dma_buf_commit(s, 0);
|
||||
goto eot;
|
||||
}
|
||||
|
||||
@@ -832,6 +834,8 @@ static void ide_sector_write_cb(void *opaque, int ret)
|
||||
n = s->req_nb_sectors;
|
||||
}
|
||||
s->nsector -= n;
|
||||
s->io_buffer_offset += 512 * n;
|
||||
|
||||
if (s->nsector == 0) {
|
||||
/* no more sectors to write */
|
||||
ide_transfer_stop(s);
|
||||
@@ -1824,6 +1828,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
||||
|
||||
s->status = READY_STAT | BUSY_STAT;
|
||||
s->error = 0;
|
||||
s->io_buffer_offset = 0;
|
||||
|
||||
complete = ide_cmd_table[val].handler(s, val);
|
||||
if (complete) {
|
||||
@@ -2309,12 +2314,17 @@ static int ide_nop_int(IDEDMA *dma, int x)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t ide_nop_int32(IDEDMA *dma, int x)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ide_nop_restart(void *opaque, int x, RunState y)
|
||||
{
|
||||
}
|
||||
|
||||
static const IDEDMAOps ide_dma_nop_ops = {
|
||||
.prepare_buf = ide_nop_int,
|
||||
.prepare_buf = ide_nop_int32,
|
||||
.rw_buf = ide_nop_int,
|
||||
.set_unit = ide_nop_int,
|
||||
.restart_cb = ide_nop_restart,
|
||||
@@ -2391,7 +2401,7 @@ static int ide_drive_post_load(void *opaque, int version_id)
|
||||
{
|
||||
IDEState *s = opaque;
|
||||
|
||||
if (s->identify_set) {
|
||||
if (s->blk && s->identify_set) {
|
||||
blk_set_enable_write_cache(s->blk, !!(s->identify_data[85] & (1 << 5)));
|
||||
}
|
||||
return 0;
|
||||
|
@@ -322,6 +322,7 @@ typedef void EndTransferFunc(IDEState *);
|
||||
typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *);
|
||||
typedef void DMAVoidFunc(IDEDMA *);
|
||||
typedef int DMAIntFunc(IDEDMA *, int);
|
||||
typedef int32_t DMAInt32Func(IDEDMA *, int);
|
||||
typedef void DMAu32Func(IDEDMA *, uint32_t);
|
||||
typedef void DMAStopFunc(IDEDMA *, bool);
|
||||
typedef void DMARestartFunc(void *, int, RunState);
|
||||
@@ -385,7 +386,7 @@ struct IDEState {
|
||||
uint8_t cdrom_changed;
|
||||
int packet_transfer_size;
|
||||
int elementary_transfer_size;
|
||||
int io_buffer_index;
|
||||
int32_t io_buffer_index;
|
||||
int lba;
|
||||
int cd_sector_size;
|
||||
int atapi_dma; /* true if dma is requested for the packet cmd */
|
||||
@@ -394,8 +395,8 @@ struct IDEState {
|
||||
struct iovec iov;
|
||||
QEMUIOVector qiov;
|
||||
/* ATA DMA state */
|
||||
int io_buffer_offset;
|
||||
int io_buffer_size;
|
||||
int32_t io_buffer_offset;
|
||||
int32_t io_buffer_size;
|
||||
QEMUSGList sg;
|
||||
/* PIO transfer handling */
|
||||
int req_nb_sectors; /* number of sectors per interrupt */
|
||||
@@ -405,8 +406,8 @@ struct IDEState {
|
||||
uint8_t *io_buffer;
|
||||
/* PIO save/restore */
|
||||
int32_t io_buffer_total_len;
|
||||
int cur_io_buffer_offset;
|
||||
int cur_io_buffer_len;
|
||||
int32_t cur_io_buffer_offset;
|
||||
int32_t cur_io_buffer_len;
|
||||
uint8_t end_transfer_fn_idx;
|
||||
QEMUTimer *sector_write_timer; /* only used for win2k install hack */
|
||||
uint32_t irq_count; /* counts IRQs when using win2k install hack */
|
||||
@@ -430,7 +431,7 @@ struct IDEState {
|
||||
struct IDEDMAOps {
|
||||
DMAStartFunc *start_dma;
|
||||
DMAVoidFunc *start_transfer;
|
||||
DMAIntFunc *prepare_buf;
|
||||
DMAInt32Func *prepare_buf;
|
||||
DMAu32Func *commit_buf;
|
||||
DMAIntFunc *rw_buf;
|
||||
DMAIntFunc *set_unit;
|
||||
|
@@ -553,6 +553,11 @@ static int ide_nop_int(IDEDMA *dma, int x)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t ide_nop_int32(IDEDMA *dma, int x)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ide_nop_restart(void *opaque, int x, RunState y)
|
||||
{
|
||||
}
|
||||
@@ -569,7 +574,7 @@ static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
|
||||
|
||||
static const IDEDMAOps dbdma_ops = {
|
||||
.start_dma = ide_dbdma_start,
|
||||
.prepare_buf = ide_nop_int,
|
||||
.prepare_buf = ide_nop_int32,
|
||||
.rw_buf = ide_nop_int,
|
||||
.set_unit = ide_nop_int,
|
||||
.restart_cb = ide_nop_restart,
|
||||
|
27
hw/ide/pci.c
27
hw/ide/pci.c
@@ -28,7 +28,7 @@
|
||||
#include <hw/isa/isa.h>
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/dma.h"
|
||||
|
||||
#include "qemu/error-report.h"
|
||||
#include <hw/ide/pci.h>
|
||||
|
||||
#define BMDMA_PAGE_SIZE 4096
|
||||
@@ -55,8 +55,11 @@ static void bmdma_start_dma(IDEDMA *dma, IDEState *s,
|
||||
}
|
||||
}
|
||||
|
||||
/* return 0 if buffer completed */
|
||||
static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
|
||||
/**
|
||||
* Return the number of bytes successfully prepared.
|
||||
* -1 on error.
|
||||
*/
|
||||
static int32_t bmdma_prepare_buf(IDEDMA *dma, int is_write)
|
||||
{
|
||||
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
|
||||
IDEState *s = bmdma_active_if(bm);
|
||||
@@ -74,8 +77,9 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
|
||||
if (bm->cur_prd_len == 0) {
|
||||
/* end of table (with a fail safe of one page) */
|
||||
if (bm->cur_prd_last ||
|
||||
(bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
|
||||
return s->io_buffer_size != 0;
|
||||
(bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) {
|
||||
return s->io_buffer_size;
|
||||
}
|
||||
pci_dma_read(pci_dev, bm->cur_addr, &prd, 8);
|
||||
bm->cur_addr += 8;
|
||||
prd.addr = le32_to_cpu(prd.addr);
|
||||
@@ -90,12 +94,23 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
|
||||
l = bm->cur_prd_len;
|
||||
if (l > 0) {
|
||||
qemu_sglist_add(&s->sg, bm->cur_prd_addr, l);
|
||||
|
||||
/* Note: We limit the max transfer to be 2GiB.
|
||||
* This should accommodate the largest ATA transaction
|
||||
* for LBA48 (65,536 sectors) and 32K sector sizes. */
|
||||
if (s->sg.size > INT32_MAX) {
|
||||
error_report("IDE: sglist describes more than 2GiB.\n");
|
||||
break;
|
||||
}
|
||||
bm->cur_prd_addr += l;
|
||||
bm->cur_prd_len -= l;
|
||||
s->io_buffer_size += l;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
qemu_sglist_destroy(&s->sg);
|
||||
s->io_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* return 0 if buffer completed */
|
||||
|
@@ -188,7 +188,7 @@ void apic_deliver_pic_intr(DeviceState *dev, int level)
|
||||
apic_reset_bit(s->irr, lvt & 0xff);
|
||||
/* fall through */
|
||||
case APIC_DM_EXTINT:
|
||||
cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
|
||||
apic_update_irq(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -349,6 +349,11 @@ static int apic_get_arb_pri(APICCommonState *s)
|
||||
static int apic_irq_pending(APICCommonState *s)
|
||||
{
|
||||
int irrv, ppr;
|
||||
|
||||
if (!(s->spurious_vec & APIC_SV_ENABLE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
irrv = get_highest_priority_int(s->irr);
|
||||
if (irrv < 0) {
|
||||
return 0;
|
||||
@@ -366,14 +371,13 @@ static void apic_update_irq(APICCommonState *s)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
if (!(s->spurious_vec & APIC_SV_ENABLE)) {
|
||||
return;
|
||||
}
|
||||
cpu = CPU(s->cpu);
|
||||
if (!qemu_cpu_is_self(cpu)) {
|
||||
cpu_interrupt(cpu, CPU_INTERRUPT_POLL);
|
||||
} else if (apic_irq_pending(s) > 0) {
|
||||
cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
|
||||
} else if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) {
|
||||
cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,7 +571,10 @@ int apic_get_interrupt(DeviceState *dev)
|
||||
apic_sync_vapic(s, SYNC_FROM_VAPIC);
|
||||
intno = apic_irq_pending(s);
|
||||
|
||||
if (intno == 0) {
|
||||
/* if there is an interrupt from the 8259, let the caller handle
|
||||
* that first since ExtINT interrupts ignore the priority.
|
||||
*/
|
||||
if (intno == 0 || apic_check_pic(s)) {
|
||||
apic_sync_vapic(s, SYNC_TO_VAPIC);
|
||||
return -1;
|
||||
} else if (intno < 0) {
|
||||
@@ -578,9 +585,6 @@ int apic_get_interrupt(DeviceState *dev)
|
||||
apic_set_bit(s->isr, intno);
|
||||
apic_sync_vapic(s, SYNC_TO_VAPIC);
|
||||
|
||||
/* re-inject if there is still a pending PIC interrupt */
|
||||
apic_check_pic(s);
|
||||
|
||||
apic_update_irq(s);
|
||||
|
||||
return intno;
|
||||
|
@@ -324,6 +324,19 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
}
|
||||
|
||||
static int apic_pre_load(void *opaque)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(opaque);
|
||||
|
||||
/* The default is !cpu_is_bsp(s->cpu), but the common value is 0
|
||||
* so that's what apic_common_sipi_needed checks for. Reset to
|
||||
* the value that is assumed when the apic_sipi subsection is
|
||||
* absent.
|
||||
*/
|
||||
s->wait_for_sipi = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void apic_dispatch_pre_save(void *opaque)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(opaque);
|
||||
@@ -345,12 +358,30 @@ static int apic_dispatch_post_load(void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool apic_common_sipi_needed(void *opaque)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(opaque);
|
||||
return s->wait_for_sipi != 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_apic_common_sipi = {
|
||||
.name = "apic_sipi",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT32(sipi_vector, APICCommonState),
|
||||
VMSTATE_INT32(wait_for_sipi, APICCommonState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_apic_common = {
|
||||
.name = "apic",
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 3,
|
||||
.minimum_version_id_old = 1,
|
||||
.load_state_old = apic_load_old,
|
||||
.pre_load = apic_pre_load,
|
||||
.pre_save = apic_dispatch_pre_save,
|
||||
.post_load = apic_dispatch_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
@@ -375,6 +406,13 @@ static const VMStateDescription vmstate_apic_common = {
|
||||
VMSTATE_INT64(timer_expiry,
|
||||
APICCommonState), /* open-coded timer state */
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (VMStateSubsection[]) {
|
||||
{
|
||||
.vmsd = &vmstate_apic_common_sipi,
|
||||
.needed = apic_common_sipi_needed,
|
||||
},
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -139,19 +139,34 @@ static int pc_dimm_built_list(Object *obj, void *opaque)
|
||||
|
||||
uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
|
||||
uint64_t address_space_size,
|
||||
uint64_t *hint, uint64_t size,
|
||||
uint64_t *hint, uint64_t align, uint64_t size,
|
||||
Error **errp)
|
||||
{
|
||||
GSList *list = NULL, *item;
|
||||
uint64_t new_addr, ret = 0;
|
||||
uint64_t address_space_end = address_space_start + address_space_size;
|
||||
|
||||
g_assert(QEMU_ALIGN_UP(address_space_start, align) == address_space_start);
|
||||
g_assert(QEMU_ALIGN_UP(address_space_size, align) == address_space_size);
|
||||
|
||||
if (!address_space_size) {
|
||||
error_setg(errp, "memory hotplug is not enabled, "
|
||||
"please add maxmem option");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hint && QEMU_ALIGN_UP(*hint, align) != *hint) {
|
||||
error_setg(errp, "address must be aligned to 0x%" PRIx64 " bytes",
|
||||
align);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (QEMU_ALIGN_UP(size, align) != size) {
|
||||
error_setg(errp, "backend memory size must be multiple of 0x%"
|
||||
PRIx64, align);
|
||||
goto out;
|
||||
}
|
||||
|
||||
assert(address_space_end > address_space_start);
|
||||
object_child_foreach(qdev_get_machine(), pc_dimm_built_list, &list);
|
||||
|
||||
@@ -177,7 +192,7 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
|
||||
error_setg(errp, "address range conflicts with '%s'", d->id);
|
||||
goto out;
|
||||
}
|
||||
new_addr = dimm->addr + dimm_size;
|
||||
new_addr = QEMU_ALIGN_UP(dimm->addr + dimm_size, align);
|
||||
}
|
||||
}
|
||||
ret = new_addr;
|
||||
|
@@ -197,7 +197,7 @@ mips_mipssim_init(MachineState *machine)
|
||||
!kernel_filename && !qtest_enabled()) {
|
||||
/* Bail out if we have neither a kernel image nor boot vector code. */
|
||||
error_report("Could not load MIPS bios '%s', and no "
|
||||
"-kernel argument was specified", filename);
|
||||
"-kernel argument was specified", bios_name);
|
||||
exit(1);
|
||||
} else {
|
||||
/* We have a boot vector start address. */
|
||||
|
@@ -1212,7 +1212,7 @@ static void pcnet_transmit(PCNetState *s)
|
||||
hwaddr xmit_cxda = 0;
|
||||
int count = CSR_XMTRL(s)-1;
|
||||
int add_crc = 0;
|
||||
|
||||
int bcnt;
|
||||
s->xmit_pos = -1;
|
||||
|
||||
if (!CSR_TXON(s)) {
|
||||
@@ -1247,35 +1247,40 @@ static void pcnet_transmit(PCNetState *s)
|
||||
s->xmit_pos = -1;
|
||||
goto txdone;
|
||||
}
|
||||
if (!GET_FIELD(tmd.status, TMDS, ENP)) {
|
||||
int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
|
||||
s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
|
||||
s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
|
||||
s->xmit_pos += bcnt;
|
||||
} else if (s->xmit_pos >= 0) {
|
||||
int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
|
||||
s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
|
||||
s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
|
||||
s->xmit_pos += bcnt;
|
||||
#ifdef PCNET_DEBUG
|
||||
printf("pcnet_transmit size=%d\n", s->xmit_pos);
|
||||
#endif
|
||||
if (CSR_LOOP(s)) {
|
||||
if (BCR_SWSTYLE(s) == 1)
|
||||
add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
|
||||
s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
|
||||
pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
|
||||
s->looptest = 0;
|
||||
} else
|
||||
if (s->nic)
|
||||
qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
|
||||
s->xmit_pos);
|
||||
|
||||
s->csr[0] &= ~0x0008; /* clear TDMD */
|
||||
s->csr[4] |= 0x0004; /* set TXSTRT */
|
||||
s->xmit_pos = -1;
|
||||
if (s->xmit_pos < 0) {
|
||||
goto txdone;
|
||||
}
|
||||
|
||||
bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
|
||||
s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
|
||||
s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
|
||||
s->xmit_pos += bcnt;
|
||||
|
||||
if (!GET_FIELD(tmd.status, TMDS, ENP)) {
|
||||
goto txdone;
|
||||
}
|
||||
|
||||
#ifdef PCNET_DEBUG
|
||||
printf("pcnet_transmit size=%d\n", s->xmit_pos);
|
||||
#endif
|
||||
if (CSR_LOOP(s)) {
|
||||
if (BCR_SWSTYLE(s) == 1)
|
||||
add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
|
||||
s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
|
||||
pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
|
||||
s->looptest = 0;
|
||||
} else {
|
||||
if (s->nic) {
|
||||
qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
|
||||
s->xmit_pos);
|
||||
}
|
||||
}
|
||||
|
||||
s->csr[0] &= ~0x0008; /* clear TDMD */
|
||||
s->csr[4] |= 0x0004; /* set TXSTRT */
|
||||
s->xmit_pos = -1;
|
||||
|
||||
txdone:
|
||||
SET_FIELD(&tmd.status, TMDS, OWN, 0);
|
||||
TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
|
||||
|
@@ -1775,6 +1775,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
|
||||
int do_interrupt, const uint8_t *dot1q_buf)
|
||||
{
|
||||
struct iovec *iov = NULL;
|
||||
struct iovec vlan_iov[3];
|
||||
|
||||
if (!size)
|
||||
{
|
||||
@@ -1789,6 +1790,9 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
|
||||
{ .iov_base = buf + ETHER_ADDR_LEN * 2,
|
||||
.iov_len = size - ETHER_ADDR_LEN * 2 },
|
||||
};
|
||||
|
||||
memcpy(vlan_iov, iov, sizeof(vlan_iov));
|
||||
iov = vlan_iov;
|
||||
}
|
||||
|
||||
if (TxLoopBack == (s->TxConfig & TxLoopBack))
|
||||
|
@@ -798,7 +798,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
|
||||
virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
|
||||
VirtQueueElement elem;
|
||||
size_t s;
|
||||
struct iovec *iov;
|
||||
struct iovec *iov, *iov2;
|
||||
unsigned int iov_cnt;
|
||||
|
||||
while (virtqueue_pop(vq, &elem)) {
|
||||
@@ -808,8 +808,8 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
iov = elem.out_sg;
|
||||
iov_cnt = elem.out_num;
|
||||
iov2 = iov = g_memdup(elem.out_sg, sizeof(struct iovec) * elem.out_num);
|
||||
s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
|
||||
iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
|
||||
if (s != sizeof(ctrl)) {
|
||||
@@ -833,6 +833,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
|
||||
|
||||
virtqueue_push(vq, &elem, sizeof(status));
|
||||
virtio_notify(vdev, vq);
|
||||
g_free(iov2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -523,6 +523,7 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename,
|
||||
void *data, size_t len)
|
||||
{
|
||||
int i, index;
|
||||
void *ptr = NULL;
|
||||
|
||||
assert(s->files);
|
||||
|
||||
@@ -531,8 +532,10 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename,
|
||||
|
||||
for (i = 0; i < index; i++) {
|
||||
if (strcmp(filename, s->files->f[i].name) == 0) {
|
||||
return fw_cfg_modify_bytes_read(s, FW_CFG_FILE_FIRST + i,
|
||||
data, len);
|
||||
ptr = fw_cfg_modify_bytes_read(s, FW_CFG_FILE_FIRST + i,
|
||||
data, len);
|
||||
s->files->f[i].size = cpu_to_be32(len);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
/* add new one */
|
||||
|
@@ -145,7 +145,7 @@ void pcie_cap_deverr_init(PCIDevice *dev)
|
||||
PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
|
||||
pci_long_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_DEVSTA,
|
||||
PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED |
|
||||
PCI_EXP_DEVSTA_URD | PCI_EXP_DEVSTA_URD);
|
||||
PCI_EXP_DEVSTA_FED | PCI_EXP_DEVSTA_URD);
|
||||
}
|
||||
|
||||
void pcie_cap_deverr_reset(PCIDevice *dev)
|
||||
@@ -229,7 +229,7 @@ static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev,
|
||||
/* the slot is electromechanically locked.
|
||||
* This error is propagated up to qdev and then to HMP/QMP.
|
||||
*/
|
||||
error_setg_errno(errp, -EBUSY, "slot is electromechanically locked");
|
||||
error_setg_errno(errp, EBUSY, "slot is electromechanically locked");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -559,8 +559,9 @@ void shpc_device_hot_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
uint8_t led;
|
||||
int slot;
|
||||
|
||||
shpc_device_hotplug_common(PCI_DEVICE(dev), &slot, shpc, errp);
|
||||
shpc_device_hotplug_common(PCI_DEVICE(dev), &slot, shpc, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -662,6 +663,7 @@ void shpc_cleanup(PCIDevice *d, MemoryRegion *bar)
|
||||
SHPCDevice *shpc = d->shpc;
|
||||
d->cap_present &= ~QEMU_PCI_CAP_SHPC;
|
||||
memory_region_del_subregion(bar, &shpc->mmio);
|
||||
object_unparent(OBJECT(&shpc->mmio));
|
||||
/* TODO: cleanup config space changes? */
|
||||
g_free(shpc->config);
|
||||
g_free(shpc->cmask);
|
||||
|
@@ -268,6 +268,9 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
|
||||
/* update status registers */
|
||||
pci->dma_regs[DMA_WBC] -= len;
|
||||
pci->dma_regs[DMA_WAC] += len;
|
||||
if (pci->dma_regs[DMA_WBC] == 0) {
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
|
||||
|
@@ -364,7 +364,7 @@ void esp_hard_reset(ESPState *s)
|
||||
{
|
||||
memset(s->rregs, 0, ESP_REGS);
|
||||
memset(s->wregs, 0, ESP_REGS);
|
||||
s->rregs[ESP_TCHI] = s->chip_id;
|
||||
s->tchi_written = 0;
|
||||
s->ti_size = 0;
|
||||
s->ti_rptr = 0;
|
||||
s->ti_wptr = 0;
|
||||
@@ -422,6 +422,11 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
|
||||
esp_lower_irq(s);
|
||||
|
||||
return old_val;
|
||||
case ESP_TCHI:
|
||||
/* Return the unique id if the value has never been written */
|
||||
if (!s->tchi_written) {
|
||||
return s->chip_id;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -432,9 +437,11 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
|
||||
{
|
||||
trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
|
||||
switch (saddr) {
|
||||
case ESP_TCHI:
|
||||
s->tchi_written = true;
|
||||
/* fall through */
|
||||
case ESP_TCLO:
|
||||
case ESP_TCMID:
|
||||
case ESP_TCHI:
|
||||
s->rregs[ESP_RSTAT] &= ~STAT_TC;
|
||||
break;
|
||||
case ESP_FIFO:
|
||||
|
@@ -233,6 +233,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
|
||||
vhost_dummy_handle_output);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
close(vhostfd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -92,9 +92,14 @@ VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s,
|
||||
|
||||
void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
|
||||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(req->vring->parent);
|
||||
|
||||
vring_push(&req->vring->vring, &req->elem,
|
||||
req->qsgl.size + req->resp_iov.size);
|
||||
event_notifier_set(&req->vring->guest_notifier);
|
||||
|
||||
if (vring_should_notify(vdev, &req->vring->vring)) {
|
||||
event_notifier_set(&req->vring->guest_notifier);
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
|
||||
@@ -230,7 +235,7 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s)
|
||||
if (!s->event_vring) {
|
||||
goto fail_vrings;
|
||||
}
|
||||
s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues);
|
||||
s->cmd_vrings = g_new(VirtIOSCSIVring *, vs->conf.num_queues);
|
||||
for (i = 0; i < vs->conf.num_queues; i++) {
|
||||
s->cmd_vrings[i] =
|
||||
virtio_scsi_vring_init(s, vs->cmd_vqs[i],
|
||||
|
@@ -118,6 +118,7 @@ static size_t qemu_sgl_concat(VirtIOSCSIReq *req, struct iovec *iov,
|
||||
static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
|
||||
unsigned req_size, unsigned resp_size)
|
||||
{
|
||||
VirtIODevice *vdev = (VirtIODevice *) req->dev;
|
||||
size_t in_size, out_size;
|
||||
|
||||
if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
|
||||
@@ -130,8 +131,24 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
|
||||
resp_size) < resp_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req->resp_size = resp_size;
|
||||
|
||||
/* Old BIOSes left some padding by mistake after the req_size/resp_size.
|
||||
* As a workaround, always consider the first buffer as the virtio-scsi
|
||||
* request/response, making the payload start at the second element
|
||||
* of the iovec.
|
||||
*
|
||||
* The actual length of the response header, stored in req->resp_size,
|
||||
* does not change.
|
||||
*
|
||||
* TODO: always disable this workaround for virtio 1.0 devices.
|
||||
*/
|
||||
if ((vdev->guest_features & VIRTIO_F_ANY_LAYOUT) == 0) {
|
||||
req_size = req->elem.out_sg[0].iov_len;
|
||||
resp_size = req->elem.in_sg[0].iov_len;
|
||||
}
|
||||
|
||||
out_size = qemu_sgl_concat(req, req->elem.out_sg,
|
||||
&req->elem.out_addr[0], req->elem.out_num,
|
||||
req_size);
|
||||
|
@@ -608,6 +608,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
|
||||
USBDevice *dev;
|
||||
USBEndpoint *uep;
|
||||
int idx = epnum && dir;
|
||||
int id;
|
||||
int ttype;
|
||||
|
||||
/* ep->type[0,1] contains:
|
||||
@@ -625,8 +626,11 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
|
||||
/* A wild guess on the FADDR semantics... */
|
||||
dev = usb_find_device(&s->port, ep->faddr[idx]);
|
||||
uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
|
||||
usb_packet_setup(&ep->packey[dir].p, pid, uep, 0,
|
||||
(dev->addr << 16) | (uep->nr << 8) | pid, false, true);
|
||||
id = pid;
|
||||
if (uep) {
|
||||
id |= (dev->addr << 16) | (uep->nr << 8);
|
||||
}
|
||||
usb_packet_setup(&ep->packey[dir].p, pid, uep, 0, id, false, true);
|
||||
usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
|
||||
ep->packey[dir].ep = ep;
|
||||
ep->packey[dir].dir = dir;
|
||||
|
@@ -2262,6 +2262,9 @@ static USBPort *xhci_lookup_uport(XHCIState *xhci, uint32_t *slot_ctx)
|
||||
int i, pos, port;
|
||||
|
||||
port = (slot_ctx[1]>>16) & 0xFF;
|
||||
if (port < 1 || port > xhci->numports) {
|
||||
return NULL;
|
||||
}
|
||||
port = xhci->ports[port-1].uport->index+1;
|
||||
pos = snprintf(path, sizeof(path), "%d", port);
|
||||
for (i = 0; i < 5; i++) {
|
||||
@@ -3706,6 +3709,12 @@ static int usb_xhci_post_load(void *opaque, int version_id)
|
||||
xhci_mask64(ldq_le_pci_dma(pci_dev, dcbaap + 8 * slotid));
|
||||
xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx));
|
||||
slot->uport = xhci_lookup_uport(xhci, slot_ctx);
|
||||
if (!slot->uport) {
|
||||
/* should not happen, but may trigger on guest bugs */
|
||||
slot->enabled = 0;
|
||||
slot->addressed = 0;
|
||||
continue;
|
||||
}
|
||||
assert(slot->uport && slot->uport->dev);
|
||||
|
||||
for (epid = 1; epid <= 31; epid++) {
|
||||
|
@@ -143,6 +143,12 @@ static void usb_host_attach_kernel(USBHostDevice *s);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#ifndef LIBUSB_LOG_LEVEL_WARNING /* older libusb didn't define these */
|
||||
#define LIBUSB_LOG_LEVEL_WARNING 2
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#define CONTROL_TIMEOUT 10000 /* 10 sec */
|
||||
#define BULK_TIMEOUT 0 /* unlimited */
|
||||
#define INTR_TIMEOUT 0 /* unlimited */
|
||||
@@ -743,13 +749,13 @@ static void usb_host_speed_compat(USBHostDevice *s)
|
||||
|
||||
udev->speedmask = (1 << udev->speed);
|
||||
if (udev->speed == USB_SPEED_SUPER && compat_high) {
|
||||
udev->speedmask |= USB_SPEED_HIGH;
|
||||
udev->speedmask |= USB_SPEED_MASK_HIGH;
|
||||
}
|
||||
if (udev->speed == USB_SPEED_SUPER && compat_full) {
|
||||
udev->speedmask |= USB_SPEED_FULL;
|
||||
udev->speedmask |= USB_SPEED_MASK_FULL;
|
||||
}
|
||||
if (udev->speed == USB_SPEED_HIGH && compat_full) {
|
||||
udev->speedmask |= USB_SPEED_FULL;
|
||||
udev->speedmask |= USB_SPEED_MASK_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -817,10 +817,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
||||
int i, r;
|
||||
|
||||
if (vhost_set_backend_type(hdev, backend_type) < 0) {
|
||||
close((uintptr_t)opaque);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdev->vhost_ops->vhost_backend_init(hdev, opaque) < 0) {
|
||||
close((uintptr_t)opaque);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
@@ -113,20 +113,22 @@ static void virtio_rng_save(QEMUFile *f, void *opaque)
|
||||
|
||||
static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
VirtIORNG *vrng = opaque;
|
||||
int ret;
|
||||
|
||||
if (version_id != 1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return virtio_load(VIRTIO_DEVICE(opaque), f, version_id);
|
||||
}
|
||||
ret = virtio_load(VIRTIO_DEVICE(vrng), f, version_id);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int virtio_rng_load_device(VirtIODevice *vdev, QEMUFile *f,
|
||||
int version_id)
|
||||
{
|
||||
/* We may have an element ready but couldn't process it due to a quota
|
||||
* limit. Make sure to try again after live migration when the quota may
|
||||
* have been reset.
|
||||
*/
|
||||
virtio_rng_process(VIRTIO_RNG(vdev));
|
||||
virtio_rng_process(vrng);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -231,7 +233,6 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
|
||||
vdc->realize = virtio_rng_device_realize;
|
||||
vdc->unrealize = virtio_rng_device_unrealize;
|
||||
vdc->get_features = get_features;
|
||||
vdc->load = virtio_rng_load_device;
|
||||
}
|
||||
|
||||
static void virtio_rng_initfn(Object *obj)
|
||||
|
@@ -83,7 +83,9 @@ typedef enum {
|
||||
#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS)
|
||||
#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1)
|
||||
|
||||
/* BDRV_BLOCK_DATA: data is read from bs->file or another file
|
||||
/*
|
||||
* Allocation status flags
|
||||
* BDRV_BLOCK_DATA: data is read from bs->file or another file
|
||||
* BDRV_BLOCK_ZERO: sectors read as zero
|
||||
* BDRV_BLOCK_OFFSET_VALID: sector stored in bs->file as raw data
|
||||
* BDRV_BLOCK_ALLOCATED: the content of the block is determined by this
|
||||
|
@@ -333,7 +333,7 @@ extern uintptr_t tci_tb_ptr;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
void phys_mem_set_alloc(void *(*alloc)(size_t));
|
||||
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
|
||||
|
||||
struct MemoryRegion *iotlb_to_region(AddressSpace *as, hwaddr index);
|
||||
bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
|
||||
|
@@ -146,6 +146,7 @@ struct MemoryRegion {
|
||||
hwaddr addr;
|
||||
void (*destructor)(MemoryRegion *mr);
|
||||
ram_addr_t ram_addr;
|
||||
uint64_t align;
|
||||
bool subpage;
|
||||
bool terminates;
|
||||
bool romd_mode;
|
||||
@@ -838,6 +839,7 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
|
||||
*/
|
||||
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
|
||||
|
||||
uint64_t memory_region_get_alignment(const MemoryRegion *mr);
|
||||
/**
|
||||
* memory_region_del_subregion: Remove a subregion.
|
||||
*
|
||||
|
@@ -49,6 +49,21 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
|
||||
return next < end;
|
||||
}
|
||||
|
||||
static inline bool cpu_physical_memory_get_clean(ram_addr_t start,
|
||||
ram_addr_t length,
|
||||
unsigned client)
|
||||
{
|
||||
unsigned long end, page, next;
|
||||
|
||||
assert(client < DIRTY_MEMORY_NUM);
|
||||
|
||||
end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
|
||||
page = start >> TARGET_PAGE_BITS;
|
||||
next = find_next_zero_bit(ram_list.dirty_memory[client], end, page);
|
||||
|
||||
return next < end;
|
||||
}
|
||||
|
||||
static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
|
||||
unsigned client)
|
||||
{
|
||||
@@ -64,6 +79,16 @@ static inline bool cpu_physical_memory_is_clean(ram_addr_t addr)
|
||||
return !(vga && code && migration);
|
||||
}
|
||||
|
||||
static inline bool cpu_physical_memory_range_includes_clean(ram_addr_t start,
|
||||
ram_addr_t length)
|
||||
{
|
||||
bool vga = cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_VGA);
|
||||
bool code = cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_CODE);
|
||||
bool migration =
|
||||
cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_MIGRATION);
|
||||
return vga || code || migration;
|
||||
}
|
||||
|
||||
static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
|
||||
unsigned client)
|
||||
{
|
||||
|
@@ -24,6 +24,8 @@
|
||||
* address space begins.
|
||||
* @hotplug_memory: hotplug memory addess space container
|
||||
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
|
||||
* @enforce_aligned_dimm: check that DIMM's address/size is aligned by
|
||||
* backend's alignment value if provided
|
||||
*/
|
||||
struct PCMachineState {
|
||||
/*< private >*/
|
||||
@@ -37,13 +39,15 @@ struct PCMachineState {
|
||||
ISADevice *rtc;
|
||||
|
||||
uint64_t max_ram_below_4g;
|
||||
bool vmport;
|
||||
OnOffAuto vmport;
|
||||
bool enforce_aligned_dimm;
|
||||
};
|
||||
|
||||
#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
|
||||
#define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size"
|
||||
#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
|
||||
#define PC_MACHINE_VMPORT "vmport"
|
||||
#define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm"
|
||||
|
||||
/**
|
||||
* PCMachineClass:
|
||||
|
@@ -59,7 +59,7 @@ extern bool rom_file_has_mr;
|
||||
int rom_add_file(const char *file, const char *fw_dir,
|
||||
hwaddr addr, int32_t bootindex,
|
||||
bool option_rom);
|
||||
void *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
hwaddr addr, const char *fw_file_name,
|
||||
FWCfgReadCallback fw_callback, void *callback_opaque);
|
||||
int rom_add_elf_program(const char *name, void *data, size_t datasize,
|
||||
|
@@ -72,7 +72,7 @@ typedef struct PCDIMMDeviceClass {
|
||||
|
||||
uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
|
||||
uint64_t address_space_size,
|
||||
uint64_t *hint, uint64_t size,
|
||||
uint64_t *hint, uint64_t align, uint64_t size,
|
||||
Error **errp);
|
||||
|
||||
int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
|
||||
|
@@ -365,7 +365,7 @@ extern int qdev_hotplug;
|
||||
|
||||
char *qdev_get_dev_path(DeviceState *dev);
|
||||
|
||||
int qdev_build_hotpluggable_device_list(Object *obj, void *opaque);
|
||||
GSList *qdev_build_hotpluggable_device_list(Object *peripheral);
|
||||
|
||||
void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler,
|
||||
Error **errp);
|
||||
|
@@ -22,6 +22,7 @@ struct ESPState {
|
||||
uint8_t wregs[ESP_REGS];
|
||||
qemu_irq irq;
|
||||
uint8_t chip_id;
|
||||
bool tchi_written;
|
||||
int32_t ti_size;
|
||||
uint32_t ti_rptr, ti_wptr;
|
||||
uint32_t status;
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#define QDEV_MAX_PIO 32
|
||||
|
||||
#define TYPE_SYSTEM_BUS "System"
|
||||
#define SYSTEM_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
|
||||
#define SYSTEM_BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_SYSTEM_BUS)
|
||||
|
||||
typedef struct SysBusDevice SysBusDevice;
|
||||
|
||||
|
@@ -209,7 +209,8 @@ typedef struct VirtIOSCSIReq {
|
||||
/* Note:
|
||||
* - fields before elem are initialized by virtio_scsi_init_req;
|
||||
* - elem is uninitialized at the time of allocation.
|
||||
* - fields after elem are zeroed by virtio_scsi_init_req.
|
||||
* - fields after elem (except the ending cdb[]) are zeroed by
|
||||
* virtio_scsi_init_req.
|
||||
* */
|
||||
|
||||
VirtQueueElement elem;
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef __OpenBSD__
|
||||
#include <sys/signal.h>
|
||||
@@ -103,7 +104,7 @@ typedef signed int int_fast16_t;
|
||||
int qemu_daemon(int nochdir, int noclose);
|
||||
void *qemu_try_memalign(size_t alignment, size_t size);
|
||||
void *qemu_memalign(size_t alignment, size_t size);
|
||||
void *qemu_anon_ram_alloc(size_t size);
|
||||
void *qemu_anon_ram_alloc(size_t size, uint64_t *align);
|
||||
void qemu_vfree(void *ptr);
|
||||
void qemu_anon_ram_free(void *ptr, size_t size);
|
||||
|
||||
|
@@ -163,6 +163,7 @@ extern KVMState *kvm_state;
|
||||
|
||||
/* external API */
|
||||
|
||||
bool kvm_has_free_slot(MachineState *ms);
|
||||
int kvm_has_sync_mmu(void);
|
||||
int kvm_has_vcpu_events(void);
|
||||
int kvm_has_robust_singlestep(void);
|
||||
|
@@ -161,6 +161,7 @@ typedef struct node_info {
|
||||
extern NodeInfo numa_info[MAX_NODES];
|
||||
void set_numa_nodes(void);
|
||||
void set_numa_modes(void);
|
||||
void query_numa_node_mem(uint64_t node_mem[]);
|
||||
extern QemuOptsList qemu_numa_opts;
|
||||
int numa_init_func(QemuOpts *opts, void *opaque);
|
||||
|
||||
|
24
kvm-all.c
24
kvm-all.c
@@ -132,7 +132,7 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||
KVM_CAP_LAST_INFO
|
||||
};
|
||||
|
||||
static KVMSlot *kvm_alloc_slot(KVMState *s)
|
||||
static KVMSlot *kvm_get_free_slot(KVMState *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -142,6 +142,22 @@ static KVMSlot *kvm_alloc_slot(KVMState *s)
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool kvm_has_free_slot(MachineState *ms)
|
||||
{
|
||||
return kvm_get_free_slot(KVM_STATE(ms->accelerator));
|
||||
}
|
||||
|
||||
static KVMSlot *kvm_alloc_slot(KVMState *s)
|
||||
{
|
||||
KVMSlot *slot = kvm_get_free_slot(s);
|
||||
|
||||
if (slot) {
|
||||
return slot;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: no free slot available\n", __func__);
|
||||
abort();
|
||||
}
|
||||
@@ -634,8 +650,10 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||
unsigned delta;
|
||||
|
||||
/* kvm works in page size chunks, but the function may be called
|
||||
with sub-page size and unaligned start address. */
|
||||
delta = TARGET_PAGE_ALIGN(size) - size;
|
||||
with sub-page size and unaligned start address. Pad the start
|
||||
address to next and truncate size to previous page boundary. */
|
||||
delta = (TARGET_PAGE_SIZE - (start_addr & ~TARGET_PAGE_MASK));
|
||||
delta &= ~TARGET_PAGE_MASK;
|
||||
if (delta > size) {
|
||||
return;
|
||||
}
|
||||
|
@@ -147,4 +147,9 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
bool kvm_has_free_slot(MachineState *ms)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@@ -597,7 +597,7 @@ connect_to_qemu(
|
||||
const char *port
|
||||
) {
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *server;
|
||||
struct addrinfo *server = NULL;
|
||||
int ret, sock;
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
@@ -629,9 +629,14 @@ connect_to_qemu(
|
||||
if (verbose) {
|
||||
printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
|
||||
}
|
||||
|
||||
freeaddrinfo(server);
|
||||
return sock;
|
||||
|
||||
cleanup_socket:
|
||||
if (server) {
|
||||
freeaddrinfo(server);
|
||||
}
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#define __KVM_HAVE_GUEST_DEBUG
|
||||
#define __KVM_HAVE_IRQ_LINE
|
||||
#define __KVM_HAVE_READONLY_MEM
|
||||
|
||||
#define KVM_REG_SIZE(id) \
|
||||
(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
|
||||
@@ -173,6 +174,7 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
|
@@ -37,6 +37,7 @@
|
||||
|
||||
#define __KVM_HAVE_GUEST_DEBUG
|
||||
#define __KVM_HAVE_IRQ_LINE
|
||||
#define __KVM_HAVE_READONLY_MEM
|
||||
|
||||
#define KVM_REG_SIZE(id) \
|
||||
(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
|
||||
@@ -159,6 +160,7 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
|
@@ -476,6 +476,11 @@ struct kvm_get_htab_header {
|
||||
|
||||
/* FP and vector status/control registers */
|
||||
#define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
|
||||
/*
|
||||
* VSCR register is documented as a 32-bit register in the ISA, but it can
|
||||
* only be accesses via a vector register. Expose VSCR as a 32-bit register
|
||||
* even though the kernel represents it as a 128-bit vector.
|
||||
*/
|
||||
#define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
|
||||
|
||||
/* Virtual processor areas */
|
||||
@@ -557,6 +562,7 @@ struct kvm_get_htab_header {
|
||||
#define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8)
|
||||
#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9)
|
||||
#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
|
||||
#define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
|
||||
|
||||
/* Transactional Memory checkpointed state:
|
||||
* This is all GPRs, all VSX regs and a subset of SPRs
|
||||
|
@@ -111,12 +111,22 @@ struct kvm_guest_debug_arch {
|
||||
#define KVM_SYNC_GPRS (1UL << 1)
|
||||
#define KVM_SYNC_ACRS (1UL << 2)
|
||||
#define KVM_SYNC_CRS (1UL << 3)
|
||||
#define KVM_SYNC_ARCH0 (1UL << 4)
|
||||
#define KVM_SYNC_PFAULT (1UL << 5)
|
||||
/* definition of registers in kvm_run */
|
||||
struct kvm_sync_regs {
|
||||
__u64 prefix; /* prefix register */
|
||||
__u64 gprs[16]; /* general purpose registers */
|
||||
__u32 acrs[16]; /* access registers */
|
||||
__u64 crs[16]; /* control registers */
|
||||
__u64 todpr; /* tod programmable register [ARCH0] */
|
||||
__u64 cputm; /* cpu timer [ARCH0] */
|
||||
__u64 ckc; /* clock comparator [ARCH0] */
|
||||
__u64 pp; /* program parameter [ARCH0] */
|
||||
__u64 gbea; /* guest breaking-event address [ARCH0] */
|
||||
__u64 pft; /* pfault token [PFAULT] */
|
||||
__u64 pfs; /* pfault select [PFAULT] */
|
||||
__u64 pfc; /* pfault compare [PFAULT] */
|
||||
};
|
||||
|
||||
#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
|
||||
|
@@ -654,9 +654,7 @@ struct kvm_ppc_smmu_info {
|
||||
#endif
|
||||
/* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
|
||||
#define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
|
||||
#ifdef __KVM_HAVE_USER_NMI
|
||||
#define KVM_CAP_USER_NMI 22
|
||||
#endif
|
||||
#ifdef __KVM_HAVE_GUEST_DEBUG
|
||||
#define KVM_CAP_SET_GUEST_DEBUG 23
|
||||
#endif
|
||||
@@ -738,9 +736,7 @@ struct kvm_ppc_smmu_info {
|
||||
#define KVM_CAP_PPC_GET_SMMU_INFO 78
|
||||
#define KVM_CAP_S390_COW 79
|
||||
#define KVM_CAP_PPC_ALLOC_HTAB 80
|
||||
#ifdef __KVM_HAVE_READONLY_MEM
|
||||
#define KVM_CAP_READONLY_MEM 81
|
||||
#endif
|
||||
#define KVM_CAP_IRQFD_RESAMPLE 82
|
||||
#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
|
||||
#define KVM_CAP_PPC_HTAB_FD 84
|
||||
@@ -947,15 +943,25 @@ struct kvm_device_attr {
|
||||
__u64 addr; /* userspace address of attr data */
|
||||
};
|
||||
|
||||
#define KVM_DEV_TYPE_FSL_MPIC_20 1
|
||||
#define KVM_DEV_TYPE_FSL_MPIC_42 2
|
||||
#define KVM_DEV_TYPE_XICS 3
|
||||
#define KVM_DEV_TYPE_VFIO 4
|
||||
#define KVM_DEV_VFIO_GROUP 1
|
||||
#define KVM_DEV_VFIO_GROUP_ADD 1
|
||||
#define KVM_DEV_VFIO_GROUP_DEL 2
|
||||
#define KVM_DEV_TYPE_ARM_VGIC_V2 5
|
||||
#define KVM_DEV_TYPE_FLIC 6
|
||||
|
||||
enum kvm_device_type {
|
||||
KVM_DEV_TYPE_FSL_MPIC_20 = 1,
|
||||
#define KVM_DEV_TYPE_FSL_MPIC_20 KVM_DEV_TYPE_FSL_MPIC_20
|
||||
KVM_DEV_TYPE_FSL_MPIC_42,
|
||||
#define KVM_DEV_TYPE_FSL_MPIC_42 KVM_DEV_TYPE_FSL_MPIC_42
|
||||
KVM_DEV_TYPE_XICS,
|
||||
#define KVM_DEV_TYPE_XICS KVM_DEV_TYPE_XICS
|
||||
KVM_DEV_TYPE_VFIO,
|
||||
#define KVM_DEV_TYPE_VFIO KVM_DEV_TYPE_VFIO
|
||||
KVM_DEV_TYPE_ARM_VGIC_V2,
|
||||
#define KVM_DEV_TYPE_ARM_VGIC_V2 KVM_DEV_TYPE_ARM_VGIC_V2
|
||||
KVM_DEV_TYPE_FLIC,
|
||||
#define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC
|
||||
KVM_DEV_TYPE_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* ioctls for VM fds
|
||||
@@ -1093,7 +1099,7 @@ struct kvm_s390_ucas_mapping {
|
||||
#define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97)
|
||||
#define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state)
|
||||
#define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state)
|
||||
/* Available with KVM_CAP_NMI */
|
||||
/* Available with KVM_CAP_USER_NMI */
|
||||
#define KVM_NMI _IO(KVMIO, 0x9a)
|
||||
/* Available with KVM_CAP_SET_GUEST_DEBUG */
|
||||
#define KVM_SET_GUEST_DEBUG _IOW(KVMIO, 0x9b, struct kvm_guest_debug)
|
||||
|
@@ -33,6 +33,9 @@
|
||||
/* Check if EEH is supported */
|
||||
#define VFIO_EEH 5
|
||||
|
||||
/* Two-stage IOMMU */
|
||||
#define VFIO_TYPE1_NESTING_IOMMU 6 /* Implies v2 */
|
||||
|
||||
/*
|
||||
* The IOCTL interface is designed for extensibility by embedding the
|
||||
* structure length (argsz) and flags into structures passed between
|
||||
|
@@ -1824,7 +1824,7 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
if (a < loaddr) {
|
||||
loaddr = a;
|
||||
}
|
||||
a += phdr[i].p_memsz;
|
||||
a = phdr[i].p_vaddr + phdr[i].p_memsz;
|
||||
if (a > hiaddr) {
|
||||
hiaddr = a;
|
||||
}
|
||||
|
@@ -5473,6 +5473,27 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags,
|
||||
return get_errno(sys_openat(dirfd, path(pathname), flags, mode));
|
||||
}
|
||||
|
||||
#define TIMER_MAGIC 0x0caf0000
|
||||
#define TIMER_MAGIC_MASK 0xffff0000
|
||||
|
||||
/* Convert QEMU provided timer ID back to internal 16bit index format */
|
||||
static target_timer_t get_timer_id(abi_long arg)
|
||||
{
|
||||
target_timer_t timerid = arg;
|
||||
|
||||
if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
timerid &= 0xffff;
|
||||
|
||||
if (timerid >= ARRAY_SIZE(g_posix_timers)) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
return timerid;
|
||||
}
|
||||
|
||||
/* do_syscall() should always have a single exit point at the end so
|
||||
that actions, such as logging of syscall results, can be performed.
|
||||
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
|
||||
@@ -9579,7 +9600,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
/* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
|
||||
|
||||
struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
|
||||
struct target_timer_t *ptarget_timer;
|
||||
|
||||
int clkid = arg1;
|
||||
int timer_index = next_free_host_timer();
|
||||
@@ -9601,11 +9621,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
if (ret) {
|
||||
phtimer = NULL;
|
||||
} else {
|
||||
if (!lock_user_struct(VERIFY_WRITE, ptarget_timer, arg3, 1)) {
|
||||
if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
|
||||
goto efault;
|
||||
}
|
||||
ptarget_timer->ptr = tswap32(0xcafe0000 | timer_index);
|
||||
unlock_user_struct(ptarget_timer, arg3, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -9617,9 +9635,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
{
|
||||
/* args: timer_t timerid, int flags, const struct itimerspec *new_value,
|
||||
* struct itimerspec * old_value */
|
||||
target_ulong timerid = arg1;
|
||||
target_timer_t timerid = get_timer_id(arg1);
|
||||
|
||||
if (arg3 == 0 || timerid >= ARRAY_SIZE(g_posix_timers)) {
|
||||
if (timerid < 0) {
|
||||
ret = timerid;
|
||||
} else if (arg3 == 0) {
|
||||
ret = -TARGET_EINVAL;
|
||||
} else {
|
||||
timer_t htimer = g_posix_timers[timerid];
|
||||
@@ -9638,12 +9658,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
case TARGET_NR_timer_gettime:
|
||||
{
|
||||
/* args: timer_t timerid, struct itimerspec *curr_value */
|
||||
target_ulong timerid = arg1;
|
||||
target_timer_t timerid = get_timer_id(arg1);
|
||||
|
||||
if (!arg2) {
|
||||
return -TARGET_EFAULT;
|
||||
} else if (timerid >= ARRAY_SIZE(g_posix_timers)) {
|
||||
ret = -TARGET_EINVAL;
|
||||
if (timerid < 0) {
|
||||
ret = timerid;
|
||||
} else if (!arg2) {
|
||||
ret = -TARGET_EFAULT;
|
||||
} else {
|
||||
timer_t htimer = g_posix_timers[timerid];
|
||||
struct itimerspec hspec;
|
||||
@@ -9661,10 +9681,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
case TARGET_NR_timer_getoverrun:
|
||||
{
|
||||
/* args: timer_t timerid */
|
||||
target_ulong timerid = arg1;
|
||||
target_timer_t timerid = get_timer_id(arg1);
|
||||
|
||||
if (timerid >= ARRAY_SIZE(g_posix_timers)) {
|
||||
ret = -TARGET_EINVAL;
|
||||
if (timerid < 0) {
|
||||
ret = timerid;
|
||||
} else {
|
||||
timer_t htimer = g_posix_timers[timerid];
|
||||
ret = get_errno(timer_getoverrun(htimer));
|
||||
@@ -9677,10 +9697,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
case TARGET_NR_timer_delete:
|
||||
{
|
||||
/* args: timer_t timerid */
|
||||
target_ulong timerid = arg1;
|
||||
target_timer_t timerid = get_timer_id(arg1);
|
||||
|
||||
if (timerid >= ARRAY_SIZE(g_posix_timers)) {
|
||||
ret = -TARGET_EINVAL;
|
||||
if (timerid < 0) {
|
||||
ret = timerid;
|
||||
} else {
|
||||
timer_t htimer = g_posix_timers[timerid];
|
||||
ret = get_errno(timer_delete(htimer));
|
||||
|
@@ -2564,10 +2564,7 @@ struct target_ucred {
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct target_timer_t {
|
||||
abi_ulong ptr;
|
||||
};
|
||||
typedef int32_t target_timer_t;
|
||||
|
||||
#define TARGET_SIGEV_MAX_SIZE 64
|
||||
|
||||
|
5
memory.c
5
memory.c
@@ -1749,6 +1749,11 @@ ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
|
||||
return mr->ram_addr;
|
||||
}
|
||||
|
||||
uint64_t memory_region_get_alignment(const MemoryRegion *mr)
|
||||
{
|
||||
return mr->align;
|
||||
}
|
||||
|
||||
static int cmp_flatrange_addr(const void *addr_, const void *fr_)
|
||||
{
|
||||
const AddrRange *addr = addr_;
|
||||
|
17
monitor.c
17
monitor.c
@@ -1948,7 +1948,10 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int i;
|
||||
CPUState *cpu;
|
||||
uint64_t *node_mem;
|
||||
|
||||
node_mem = g_new0(uint64_t, nb_numa_nodes);
|
||||
query_numa_node_mem(node_mem);
|
||||
monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
|
||||
for (i = 0; i < nb_numa_nodes; i++) {
|
||||
monitor_printf(mon, "node %d cpus:", i);
|
||||
@@ -1959,8 +1962,9 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
monitor_printf(mon, "\n");
|
||||
monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
|
||||
numa_info[i].node_mem >> 20);
|
||||
node_mem[i] >> 20);
|
||||
}
|
||||
g_free(node_mem);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
@@ -4317,17 +4321,14 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
static void peripheral_device_del_completion(ReadLineState *rs,
|
||||
const char *str, size_t len)
|
||||
{
|
||||
Object *peripheral;
|
||||
GSList *list = NULL, *item;
|
||||
Object *peripheral = container_get(qdev_get_machine(), "/peripheral");
|
||||
GSList *list, *item;
|
||||
|
||||
peripheral = object_resolve_path("/machine/peripheral/", NULL);
|
||||
if (peripheral == NULL) {
|
||||
list = qdev_build_hotpluggable_device_list(peripheral);
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
|
||||
object_child_foreach(peripheral, qdev_build_hotpluggable_device_list,
|
||||
&list);
|
||||
|
||||
for (item = list; item; item = g_slist_next(item)) {
|
||||
DeviceState *dev = item->data;
|
||||
|
||||
|
@@ -516,7 +516,7 @@ static void net_l2tpv3_cleanup(NetClientState *nc)
|
||||
qemu_purge_queued_packets(nc);
|
||||
l2tpv3_read_poll(s, false);
|
||||
l2tpv3_write_poll(s, false);
|
||||
if (s->fd > 0) {
|
||||
if (s->fd >= 0) {
|
||||
close(s->fd);
|
||||
}
|
||||
destroy_vector(s->msgvec, MAX_L2TPV3_MSGCNT, IOVSIZE);
|
||||
@@ -660,7 +660,6 @@ int net_init_l2tpv3(const NetClientOptions *opts,
|
||||
if (fd == -1) {
|
||||
fd = -errno;
|
||||
error_report("l2tpv3_open : socket creation failed, errno = %d", -fd);
|
||||
freeaddrinfo(result);
|
||||
goto outerr;
|
||||
}
|
||||
if (bind(fd, (struct sockaddr *) result->ai_addr, result->ai_addrlen)) {
|
||||
@@ -746,7 +745,7 @@ int net_init_l2tpv3(const NetClientOptions *opts,
|
||||
return 0;
|
||||
outerr:
|
||||
qemu_del_net_client(nc);
|
||||
if (fd > 0) {
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
if (result) {
|
||||
|
12
net/slirp.c
12
net/slirp.c
@@ -523,15 +523,21 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
|
||||
fprintf(f,
|
||||
"[global]\n"
|
||||
"private dir=%s\n"
|
||||
"socket address=127.0.0.1\n"
|
||||
"interfaces=127.0.0.1\n"
|
||||
"bind interfaces only=yes\n"
|
||||
"pid directory=%s\n"
|
||||
"lock directory=%s\n"
|
||||
"state directory=%s\n"
|
||||
"cache directory=%s\n"
|
||||
"ncalrpc dir=%s/ncalrpc\n"
|
||||
"log file=%s/log.smbd\n"
|
||||
"smb passwd file=%s/smbpasswd\n"
|
||||
"security = user\n"
|
||||
"map to guest = Bad User\n"
|
||||
"load printers = no\n"
|
||||
"printing = bsd\n"
|
||||
"disable spoolss = yes\n"
|
||||
"usershare max shares = 0\n"
|
||||
"[qemu]\n"
|
||||
"path=%s\n"
|
||||
"read only=no\n"
|
||||
@@ -544,6 +550,7 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
|
||||
s->smb_dir,
|
||||
s->smb_dir,
|
||||
s->smb_dir,
|
||||
s->smb_dir,
|
||||
exported_dir,
|
||||
passwd->pw_name
|
||||
);
|
||||
@@ -636,17 +643,16 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
fwd = g_malloc(sizeof(struct GuestFwd));
|
||||
snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
|
||||
|
||||
if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) {
|
||||
if (slirp_add_exec(s->slirp, 0, &p[4], &server, port) < 0) {
|
||||
error_report("conflicting/invalid host:port in guest forwarding "
|
||||
"rule '%s'", config_str);
|
||||
g_free(fwd);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fwd = g_malloc(sizeof(struct GuestFwd));
|
||||
fwd->hd = qemu_chr_new(buf, p, NULL);
|
||||
if (!fwd->hd) {
|
||||
error_report("could not open guest forwarding device '%s'", buf);
|
||||
|
13
net/socket.c
13
net/socket.c
@@ -352,7 +352,7 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
int newfd;
|
||||
socklen_t saddr_len;
|
||||
socklen_t saddr_len = sizeof(saddr);
|
||||
NetClientState *nc;
|
||||
NetSocketState *s;
|
||||
|
||||
@@ -389,11 +389,6 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
|
||||
|
||||
nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name);
|
||||
|
||||
snprintf(nc->info_str, sizeof(nc->info_str),
|
||||
"socket: fd=%d (%s mcast=%s:%d)",
|
||||
fd, is_connected ? "cloned" : "",
|
||||
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
|
||||
|
||||
s = DO_UPCAST(NetSocketState, nc, nc);
|
||||
|
||||
s->fd = fd;
|
||||
@@ -404,6 +399,12 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
|
||||
/* mcast: save bound address as dst */
|
||||
if (is_connected) {
|
||||
s->dgram_dst = saddr;
|
||||
snprintf(nc->info_str, sizeof(nc->info_str),
|
||||
"socket: fd=%d (cloned mcast=%s:%d)",
|
||||
fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
|
||||
} else {
|
||||
snprintf(nc->info_str, sizeof(nc->info_str),
|
||||
"socket: fd=%d", fd);
|
||||
}
|
||||
|
||||
return s;
|
||||
|
38
numa.c
38
numa.c
@@ -35,6 +35,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/hostmem.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
|
||||
QemuOptsList qemu_numa_opts = {
|
||||
.name = "numa",
|
||||
@@ -315,6 +316,43 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
|
||||
}
|
||||
}
|
||||
|
||||
static void numa_stat_memory_devices(uint64_t node_mem[])
|
||||
{
|
||||
MemoryDeviceInfoList *info_list = NULL;
|
||||
MemoryDeviceInfoList **prev = &info_list;
|
||||
MemoryDeviceInfoList *info;
|
||||
|
||||
qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
|
||||
for (info = info_list; info; info = info->next) {
|
||||
MemoryDeviceInfo *value = info->value;
|
||||
|
||||
if (value) {
|
||||
switch (value->kind) {
|
||||
case MEMORY_DEVICE_INFO_KIND_DIMM:
|
||||
node_mem[value->dimm->node] += value->dimm->size;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
qapi_free_MemoryDeviceInfoList(info_list);
|
||||
}
|
||||
|
||||
void query_numa_node_mem(uint64_t node_mem[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (nb_numa_nodes <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
numa_stat_memory_devices(node_mem);
|
||||
for (i = 0; i < nb_numa_nodes; i++) {
|
||||
node_mem[i] += numa_info[i].node_mem;
|
||||
}
|
||||
}
|
||||
|
||||
static int query_memdev(Object *obj, void *opaque)
|
||||
{
|
||||
MemdevList **list = opaque;
|
||||
|
Binary file not shown.
BIN
pc-bios/bios.bin
BIN
pc-bios/bios.bin
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user