Compare commits
176
Commits
v2.2.0-rc0
...
v2.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
51fc44768a | ||
|
|
935fb91522 | ||
|
|
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 | ||
|
|
558c2c8ddf | ||
|
|
09c7fbef76 | ||
|
|
1b3e71f8ee | ||
|
|
7a8dda7e5d | ||
|
|
2d9177588b | ||
|
|
25aaa2c568 | ||
|
|
7b4b7c5fc7 | ||
|
|
ea3beed41d | ||
|
|
d20418ee51 | ||
|
|
d21de4d97f | ||
|
|
55783a5521 | ||
|
|
cb269f273f | ||
|
|
342368aff7 | ||
|
|
854795753c | ||
|
|
e30614d517 | ||
|
|
70409e6726 | ||
|
|
c3543fb5fe | ||
|
|
272f458dc8 | ||
|
|
dff4021730 | ||
|
|
7eb7311427 | ||
|
|
c4d01535dc | ||
|
|
e56934bece | ||
|
|
cc4d3ee435 | ||
|
|
bb3e9e1fd7 | ||
|
|
87f2eff016 | ||
|
|
b3191432cf | ||
|
|
f0d4dc18ce | ||
|
|
80765f0734 | ||
|
|
63c693f8d0 | ||
|
|
3a0614c6c7 |
No files matched your search
+20
@@ -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
|
||||
+15
-5
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
@@ -5608,11 +5608,6 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
ret = bdrv_open(&bs, backing_file, NULL, NULL, back_flags,
|
||||
backing_drv, &local_err);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not open '%s': %s",
|
||||
backing_file,
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
local_err = NULL;
|
||||
goto out;
|
||||
}
|
||||
size = bdrv_getlength(bs);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
+95
-86
@@ -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,
|
||||
|
||||
+12
-2
@@ -120,8 +120,18 @@ typedef unsigned char uuid_t[16];
|
||||
|
||||
#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
|
||||
|
||||
/* max blocks in image is (0xffffffff / 4) */
|
||||
#define VDI_BLOCKS_IN_IMAGE_MAX 0x3fffffff
|
||||
/* The bmap will take up VDI_BLOCKS_IN_IMAGE_MAX * sizeof(uint32_t) bytes; since
|
||||
* the bmap is read and written in a single operation, its size needs to be
|
||||
* limited to INT_MAX; furthermore, when opening an image, the bmap size is
|
||||
* rounded up to be aligned on BDRV_SECTOR_SIZE.
|
||||
* Therefore this should satisfy the following:
|
||||
* VDI_BLOCKS_IN_IMAGE_MAX * sizeof(uint32_t) + BDRV_SECTOR_SIZE == INT_MAX + 1
|
||||
* (INT_MAX + 1 is the first value not representable as an int)
|
||||
* This guarantees that any value below or equal to the constant will, when
|
||||
* multiplied by sizeof(uint32_t) and rounded up to a BDRV_SECTOR_SIZE boundary,
|
||||
* still be below or equal to INT_MAX. */
|
||||
#define VDI_BLOCKS_IN_IMAGE_MAX \
|
||||
((unsigned)((INT_MAX + 1u - BDRV_SECTOR_SIZE) / sizeof(uint32_t)))
|
||||
#define VDI_DISK_SIZE_MAX ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
|
||||
(uint64_t)DEFAULT_CLUSTER_SIZE)
|
||||
|
||||
|
||||
+14
-8
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -32,6 +32,5 @@ CONFIG_G364FB=y
|
||||
CONFIG_I8259=y
|
||||
CONFIG_JAZZ_LED=y
|
||||
CONFIG_MC146818RTC=y
|
||||
CONFIG_VT82C686=y
|
||||
CONFIG_ISA_TESTDEV=y
|
||||
CONFIG_EMPTY_SLOT=y
|
||||
@@ -32,6 +32,5 @@ CONFIG_G364FB=y
|
||||
CONFIG_I8259=y
|
||||
CONFIG_JAZZ_LED=y
|
||||
CONFIG_MC146818RTC=y
|
||||
CONFIG_VT82C686=y
|
||||
CONFIG_ISA_TESTDEV=y
|
||||
CONFIG_EMPTY_SLOT=y
|
||||
@@ -32,6 +32,5 @@ CONFIG_G364FB=y
|
||||
CONFIG_I8259=y
|
||||
CONFIG_JAZZ_LED=y
|
||||
CONFIG_MC146818RTC=y
|
||||
CONFIG_VT82C686=y
|
||||
CONFIG_ISA_TESTDEV=y
|
||||
CONFIG_EMPTY_SLOT=y
|
||||
+3
-3
@@ -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.
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+5
-2
@@ -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);
|
||||
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+66
-6
@@ -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);
|
||||
|
||||
@@ -52,7 +52,8 @@ typedef struct SCLPConsoleLM {
|
||||
* event_pending is set when a newline character is encountered
|
||||
*
|
||||
* The maximum command line length is limited by the maximum
|
||||
* space available in an SCCB
|
||||
* space available in an SCCB. Line mode console input is sent
|
||||
* truncated to the guest in case it doesn't fit into the SCCB.
|
||||
*/
|
||||
|
||||
static int chr_can_read(void *opaque)
|
||||
@@ -61,10 +62,8 @@ static int chr_can_read(void *opaque)
|
||||
|
||||
if (scon->event.event_pending) {
|
||||
return 0;
|
||||
} else if (SIZE_CONSOLE_BUFFER - scon->length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||
@@ -78,6 +77,10 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||
sclp_service_interrupt(0);
|
||||
return;
|
||||
}
|
||||
if (scon->length == SIZE_CONSOLE_BUFFER) {
|
||||
/* Eat the character, but still process CR and LF. */
|
||||
return;
|
||||
}
|
||||
scon->buf[scon->length] = *buf;
|
||||
scon->length += 1;
|
||||
if (scon->echo) {
|
||||
@@ -125,6 +128,7 @@ static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
|
||||
cons->length = 0;
|
||||
/* data provided and no more data pending */
|
||||
event->event_pending = false;
|
||||
qemu_notify_event();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -36,6 +36,7 @@ typedef struct SCLPConsole {
|
||||
uint32_t iov_bs; /* offset in buf for char layer read operation */
|
||||
uint32_t iov_data_len; /* length of byte stream in buffer */
|
||||
uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
|
||||
bool notify; /* qemu_notify_event() req'd if true */
|
||||
} SCLPConsole;
|
||||
|
||||
/* character layer call-back functions */
|
||||
@@ -44,8 +45,12 @@ typedef struct SCLPConsole {
|
||||
static int chr_can_read(void *opaque)
|
||||
{
|
||||
SCLPConsole *scon = opaque;
|
||||
int avail = SIZE_BUFFER_VT220 - scon->iov_data_len;
|
||||
|
||||
return SIZE_BUFFER_VT220 - scon->iov_data_len;
|
||||
if (avail == 0) {
|
||||
scon->notify = true;
|
||||
}
|
||||
return avail;
|
||||
}
|
||||
|
||||
/* Send data from a char device over to the guest */
|
||||
@@ -113,6 +118,10 @@ static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
|
||||
cons->iov_sclp += avail;
|
||||
/* more data pending */
|
||||
}
|
||||
if (cons->notify) {
|
||||
cons->notify = false;
|
||||
qemu_notify_event();
|
||||
}
|
||||
}
|
||||
|
||||
static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
|
||||
@@ -229,6 +238,7 @@ static void console_reset(DeviceState *dev)
|
||||
scon->iov_bs = 0;
|
||||
scon->iov_data_len = 0;
|
||||
scon->iov_sclp_rest = 0;
|
||||
scon->notify = false;
|
||||
}
|
||||
|
||||
static int console_exit(SCLPEvent *event)
|
||||
|
||||
@@ -871,7 +871,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (find_port_by_name(port->name)) {
|
||||
if (port->name != NULL && find_port_by_name(port->name)) {
|
||||
error_setg(errp, "virtio-serial-bus: A port already exists by name %s",
|
||||
port->name);
|
||||
return;
|
||||
|
||||
+18
-3
@@ -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
|
||||
|
||||
+10
-2
@@ -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);
|
||||
|
||||
+2
-2
@@ -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,
|
||||
|
||||
+48
-17
@@ -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,
|
||||
|
||||
+11
-11
@@ -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");
|
||||
|
||||
@@ -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));
|
||||
|
||||
+90
-12
@@ -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)
|
||||
|
||||
+8
-12
@@ -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
|
||||
|
||||
|
||||
+9
-1
@@ -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,
|
||||
|
||||
+5
-5
@@ -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,
|
||||
|
||||
+2
-163
@@ -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()
|
||||
}
|
||||
+24
-810
@@ -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
|
||||
|
||||
+155
-124
@@ -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
|
||||
|
||||
+13
-3
@@ -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;
|
||||
|
||||
+7
-6
@@ -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;
|
||||
|
||||
+6
-1
@@ -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,
|
||||
|
||||
+21
-6
@@ -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 */
|
||||
|
||||
+12
-8
@@ -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()
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+17
-2
@@ -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. */
|
||||
|
||||
+32
-27
@@ -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))
|
||||
|
||||
+3
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -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 */
|
||||
|
||||
+2
-2
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -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)
|
||||
|
||||
+9
-2
@@ -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);
|
||||
|
||||
+6
-2
@@ -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:
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
+17
-11
@@ -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;
|
||||
}
|
||||
|
||||
+37
-17
@@ -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
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+2
-3
@@ -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) {
|
||||
|
||||
+9
-3
@@ -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);
|
||||
|
||||
+7
-6
@@ -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;
|
||||
|
||||
Loaded 100 of 156 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user