* target/i386: Fix physical address truncation on 32-bit PAE
* Remove globals for options -no-fd-bootchk and -win2k-hack -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmXebwQUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroPozAf/Vgc9u6C+8PcPDrol6qxjI+EOHLNy 7M3/OFpUkwLXuOSawb6syYxHpLS38fKRcsb2ninngUmbRWA6p+KNUizlAFMj7op5 wJmtdamCwCwXXaw20SfWxx2Ih0JS7FQsRsU94HTOdaDB17C9+hBcYwcggsOAXCmq gyVenEF1mov2A4jLMhdVIRX784AAoEP+QAuhBKQBrQwRLCTTyNdHl7jXdB9w+2sh KafokoFLcozJHz/tN3AhRKy6zjPugJyQmJwBRuj9tstCILtXpvf/ZE/3pUq5l3ZY A6dCI0zWAlGNTkpKRXsMFozNIVP2htnyidy29XHptlY5acfjtQ++rMu3BQ== =WY4H -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging * target/i386: Fix physical address truncation on 32-bit PAE * Remove globals for options -no-fd-bootchk and -win2k-hack # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmXebwQUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroPozAf/Vgc9u6C+8PcPDrol6qxjI+EOHLNy # 7M3/OFpUkwLXuOSawb6syYxHpLS38fKRcsb2ninngUmbRWA6p+KNUizlAFMj7op5 # wJmtdamCwCwXXaw20SfWxx2Ih0JS7FQsRsU94HTOdaDB17C9+hBcYwcggsOAXCmq # gyVenEF1mov2A4jLMhdVIRX784AAoEP+QAuhBKQBrQwRLCTTyNdHl7jXdB9w+2sh # KafokoFLcozJHz/tN3AhRKy6zjPugJyQmJwBRuj9tstCILtXpvf/ZE/3pUq5l3ZY # A6dCI0zWAlGNTkpKRXsMFozNIVP2htnyidy29XHptlY5acfjtQ++rMu3BQ== # =WY4H # -----END PGP SIGNATURE----- # gpg: Signature made Tue 27 Feb 2024 23:23:48 GMT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: ide, vl: turn -win2k-hack into a property on IDE devices ide: collapse parameters to ide_init_drive target/i386: leave the A20 bit set in the final NPT walk target/i386: remove unnecessary/wrong application of the A20 mask target/i386: Fix physical address truncation target/i386: use separate MMU indexes for 32-bit accesses target/i386: introduce function to query MMU indices target/i386: check validity of VMCB addresses target/i386: mask high bits of CR3 in 32-bit mode vl, pc: turn -no-fd-bootchk into a machine property Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
bfe8020c81
39
hw/i386/pc.c
39
hw/i386/pc.c
@ -399,8 +399,8 @@ static int boot_device2nibble(char boot_device)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_boot_dev(MC146818RtcState *s, const char *boot_device,
|
static void set_boot_dev(PCMachineState *pcms, MC146818RtcState *s,
|
||||||
Error **errp)
|
const char *boot_device, Error **errp)
|
||||||
{
|
{
|
||||||
#define PC_MAX_BOOT_DEVICES 3
|
#define PC_MAX_BOOT_DEVICES 3
|
||||||
int nbds, bds[3] = { 0, };
|
int nbds, bds[3] = { 0, };
|
||||||
@ -420,12 +420,14 @@ static void set_boot_dev(MC146818RtcState *s, const char *boot_device,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mc146818rtc_set_cmos_data(s, 0x3d, (bds[1] << 4) | bds[0]);
|
mc146818rtc_set_cmos_data(s, 0x3d, (bds[1] << 4) | bds[0]);
|
||||||
mc146818rtc_set_cmos_data(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
|
mc146818rtc_set_cmos_data(s, 0x38, (bds[2] << 4) | !pcms->fd_bootchk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_boot_set(void *opaque, const char *boot_device, Error **errp)
|
static void pc_boot_set(void *opaque, const char *boot_device, Error **errp)
|
||||||
{
|
{
|
||||||
set_boot_dev(opaque, boot_device, errp);
|
PCMachineState *pcms = PC_MACHINE(current_machine);
|
||||||
|
|
||||||
|
set_boot_dev(pcms, opaque, boot_device, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_cmos_init_floppy(MC146818RtcState *rtc_state, ISADevice *floppy)
|
static void pc_cmos_init_floppy(MC146818RtcState *rtc_state, ISADevice *floppy)
|
||||||
@ -611,7 +613,15 @@ void pc_cmos_init(PCMachineState *pcms,
|
|||||||
mc146818rtc_set_cmos_data(s, 0x5c, val >> 8);
|
mc146818rtc_set_cmos_data(s, 0x5c, val >> 8);
|
||||||
mc146818rtc_set_cmos_data(s, 0x5d, val >> 16);
|
mc146818rtc_set_cmos_data(s, 0x5d, val >> 16);
|
||||||
|
|
||||||
set_boot_dev(s, MACHINE(pcms)->boot_config.order, &error_fatal);
|
object_property_add_link(OBJECT(pcms), "rtc_state",
|
||||||
|
TYPE_ISA_DEVICE,
|
||||||
|
(Object **)&x86ms->rtc,
|
||||||
|
object_property_allow_set_link,
|
||||||
|
OBJ_PROP_LINK_STRONG);
|
||||||
|
object_property_set_link(OBJECT(pcms), "rtc_state", OBJECT(s),
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
|
set_boot_dev(pcms, s, MACHINE(pcms)->boot_config.order, &error_fatal);
|
||||||
|
|
||||||
val = 0;
|
val = 0;
|
||||||
val |= 0x02; /* FPU is there */
|
val |= 0x02; /* FPU is there */
|
||||||
@ -1535,6 +1545,20 @@ static void pc_machine_set_vmport(Object *obj, Visitor *v, const char *name,
|
|||||||
visit_type_OnOffAuto(v, name, &pcms->vmport, errp);
|
visit_type_OnOffAuto(v, name, &pcms->vmport, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pc_machine_get_fd_bootchk(Object *obj, Error **errp)
|
||||||
|
{
|
||||||
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
|
|
||||||
|
return pcms->fd_bootchk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pc_machine_set_fd_bootchk(Object *obj, bool value, Error **errp)
|
||||||
|
{
|
||||||
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
|
|
||||||
|
pcms->fd_bootchk = value;
|
||||||
|
}
|
||||||
|
|
||||||
static bool pc_machine_get_smbus(Object *obj, Error **errp)
|
static bool pc_machine_get_smbus(Object *obj, Error **errp)
|
||||||
{
|
{
|
||||||
PCMachineState *pcms = PC_MACHINE(obj);
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
@ -1723,6 +1747,7 @@ static void pc_machine_initfn(Object *obj)
|
|||||||
#ifdef CONFIG_HPET
|
#ifdef CONFIG_HPET
|
||||||
pcms->hpet_enabled = true;
|
pcms->hpet_enabled = true;
|
||||||
#endif
|
#endif
|
||||||
|
pcms->fd_bootchk = true;
|
||||||
pcms->default_bus_bypass_iommu = false;
|
pcms->default_bus_bypass_iommu = false;
|
||||||
|
|
||||||
pcms->pcspk = isa_new(TYPE_PC_SPEAKER);
|
pcms->pcspk = isa_new(TYPE_PC_SPEAKER);
|
||||||
@ -1869,6 +1894,10 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
|||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
object_class_property_set_description(oc, PC_MACHINE_SMBIOS_EP,
|
object_class_property_set_description(oc, PC_MACHINE_SMBIOS_EP,
|
||||||
"SMBIOS Entry Point type [32, 64]");
|
"SMBIOS Entry Point type [32, 64]");
|
||||||
|
|
||||||
|
object_class_property_add_bool(oc, "fd-bootchk",
|
||||||
|
pc_machine_get_fd_bootchk,
|
||||||
|
pc_machine_set_fd_bootchk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pc_machine_info = {
|
static const TypeInfo pc_machine_info = {
|
||||||
|
@ -1059,7 +1059,7 @@ static void ide_sector_write_cb(void *opaque, int ret)
|
|||||||
ide_sector_write);
|
ide_sector_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
|
if (s->win2k_install_hack && ((++s->irq_count % 16) == 0)) {
|
||||||
/* It seems there is a bug in the Windows 2000 installer HDD
|
/* It seems there is a bug in the Windows 2000 installer HDD
|
||||||
IDE driver which fills the disk with empty logs when the
|
IDE driver which fills the disk with empty logs when the
|
||||||
IDE write IRQ comes too early. This hack tries to correct
|
IDE write IRQ comes too early. This hack tries to correct
|
||||||
@ -2589,24 +2589,21 @@ static const BlockDevOps ide_hd_block_ops = {
|
|||||||
.resize_cb = ide_resize_cb,
|
.resize_cb = ide_resize_cb,
|
||||||
};
|
};
|
||||||
|
|
||||||
int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
|
int ide_init_drive(IDEState *s, IDEDevice *dev, IDEDriveKind kind, Error **errp)
|
||||||
const char *version, const char *serial, const char *model,
|
|
||||||
uint64_t wwn,
|
|
||||||
uint32_t cylinders, uint32_t heads, uint32_t secs,
|
|
||||||
int chs_trans, Error **errp)
|
|
||||||
{
|
{
|
||||||
uint64_t nb_sectors;
|
uint64_t nb_sectors;
|
||||||
|
|
||||||
s->blk = blk;
|
s->blk = dev->conf.blk;
|
||||||
s->drive_kind = kind;
|
s->drive_kind = kind;
|
||||||
|
|
||||||
blk_get_geometry(blk, &nb_sectors);
|
blk_get_geometry(s->blk, &nb_sectors);
|
||||||
s->cylinders = cylinders;
|
s->win2k_install_hack = dev->win2k_install_hack;
|
||||||
s->heads = s->drive_heads = heads;
|
s->cylinders = dev->conf.cyls;
|
||||||
s->sectors = s->drive_sectors = secs;
|
s->heads = s->drive_heads = dev->conf.heads;
|
||||||
s->chs_trans = chs_trans;
|
s->sectors = s->drive_sectors = dev->conf.secs;
|
||||||
|
s->chs_trans = dev->chs_trans;
|
||||||
s->nb_sectors = nb_sectors;
|
s->nb_sectors = nb_sectors;
|
||||||
s->wwn = wwn;
|
s->wwn = dev->wwn;
|
||||||
/* The SMART values should be preserved across power cycles
|
/* The SMART values should be preserved across power cycles
|
||||||
but they aren't. */
|
but they aren't. */
|
||||||
s->smart_enabled = 1;
|
s->smart_enabled = 1;
|
||||||
@ -2614,26 +2611,26 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
|
|||||||
s->smart_errors = 0;
|
s->smart_errors = 0;
|
||||||
s->smart_selftest_count = 0;
|
s->smart_selftest_count = 0;
|
||||||
if (kind == IDE_CD) {
|
if (kind == IDE_CD) {
|
||||||
blk_set_dev_ops(blk, &ide_cd_block_ops, s);
|
blk_set_dev_ops(s->blk, &ide_cd_block_ops, s);
|
||||||
} else {
|
} else {
|
||||||
if (!blk_is_inserted(s->blk)) {
|
if (!blk_is_inserted(s->blk)) {
|
||||||
error_setg(errp, "Device needs media, but drive is empty");
|
error_setg(errp, "Device needs media, but drive is empty");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!blk_is_writable(blk)) {
|
if (!blk_is_writable(s->blk)) {
|
||||||
error_setg(errp, "Can't use a read-only drive");
|
error_setg(errp, "Can't use a read-only drive");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
blk_set_dev_ops(blk, &ide_hd_block_ops, s);
|
blk_set_dev_ops(s->blk, &ide_hd_block_ops, s);
|
||||||
}
|
}
|
||||||
if (serial) {
|
if (dev->serial) {
|
||||||
pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), serial);
|
pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), dev->serial);
|
||||||
} else {
|
} else {
|
||||||
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
|
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
|
||||||
"QM%05d", s->drive_serial);
|
"QM%05d", s->drive_serial);
|
||||||
}
|
}
|
||||||
if (model) {
|
if (dev->model) {
|
||||||
pstrcpy(s->drive_model_str, sizeof(s->drive_model_str), model);
|
pstrcpy(s->drive_model_str, sizeof(s->drive_model_str), dev->model);
|
||||||
} else {
|
} else {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case IDE_CD:
|
case IDE_CD:
|
||||||
@ -2648,14 +2645,14 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version) {
|
if (dev->version) {
|
||||||
pstrcpy(s->version, sizeof(s->version), version);
|
pstrcpy(s->version, sizeof(s->version), dev->version);
|
||||||
} else {
|
} else {
|
||||||
pstrcpy(s->version, sizeof(s->version), qemu_hw_version());
|
pstrcpy(s->version, sizeof(s->version), qemu_hw_version());
|
||||||
}
|
}
|
||||||
|
|
||||||
ide_reset(s);
|
ide_reset(s);
|
||||||
blk_iostatus_enable(blk);
|
blk_iostatus_enable(s->blk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
static Property ide_props[] = {
|
static Property ide_props[] = {
|
||||||
DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
|
DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
|
||||||
|
DEFINE_PROP_BOOL("win2k-install-hack", IDEDevice, win2k_install_hack, false),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -118,10 +119,7 @@ void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ide_init_drive(s, dev->conf.blk, kind,
|
if (ide_init_drive(s, dev, kind, errp) < 0) {
|
||||||
dev->version, dev->serial, dev->model, dev->wwn,
|
|
||||||
dev->conf.cyls, dev->conf.heads, dev->conf.secs,
|
|
||||||
dev->chs_trans, errp) < 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,11 +416,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
|
|||||||
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
|
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
|
||||||
uint32_t ide_data_readl(void *opaque, uint32_t addr);
|
uint32_t ide_data_readl(void *opaque, uint32_t addr);
|
||||||
|
|
||||||
int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
|
int ide_init_drive(IDEState *s, IDEDevice *dev, IDEDriveKind kind, Error **errp);
|
||||||
const char *version, const char *serial, const char *model,
|
|
||||||
uint64_t wwn,
|
|
||||||
uint32_t cylinders, uint32_t heads, uint32_t secs,
|
|
||||||
int chs_trans, Error **errp);
|
|
||||||
void ide_exit(IDEState *s);
|
void ide_exit(IDEState *s);
|
||||||
void ide_bus_init_output_irq(IDEBus *bus, qemu_irq irq_out);
|
void ide_bus_init_output_irq(IDEBus *bus, qemu_irq irq_out);
|
||||||
int ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
|
int ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
|
||||||
|
@ -50,6 +50,7 @@ typedef struct PCMachineState {
|
|||||||
bool hpet_enabled;
|
bool hpet_enabled;
|
||||||
bool i8042_enabled;
|
bool i8042_enabled;
|
||||||
bool default_bus_bypass_iommu;
|
bool default_bus_bypass_iommu;
|
||||||
|
bool fd_bootchk;
|
||||||
uint64_t max_fw_size;
|
uint64_t max_fw_size;
|
||||||
|
|
||||||
/* ACPI Memory hotplug IO base address */
|
/* ACPI Memory hotplug IO base address */
|
||||||
@ -146,7 +147,6 @@ OBJECT_DECLARE_TYPE(PCMachineState, PCMachineClass, PC_MACHINE)
|
|||||||
GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled);
|
GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled);
|
||||||
|
|
||||||
/* pc.c */
|
/* pc.c */
|
||||||
extern int fd_bootchk;
|
|
||||||
|
|
||||||
void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
|
void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ struct IDEState {
|
|||||||
int drive_serial;
|
int drive_serial;
|
||||||
char drive_serial_str[21];
|
char drive_serial_str[21];
|
||||||
char drive_model_str[41];
|
char drive_model_str[41];
|
||||||
|
bool win2k_install_hack;
|
||||||
uint64_t wwn;
|
uint64_t wwn;
|
||||||
/* ide regs */
|
/* ide regs */
|
||||||
uint8_t feature;
|
uint8_t feature;
|
||||||
@ -163,6 +164,7 @@ struct IDEDevice {
|
|||||||
* 0xffff - reserved
|
* 0xffff - reserved
|
||||||
*/
|
*/
|
||||||
uint16_t rotation_rate;
|
uint16_t rotation_rate;
|
||||||
|
bool win2k_install_hack;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct IDEDrive {
|
typedef struct IDEDrive {
|
||||||
|
@ -41,7 +41,6 @@ extern int graphic_height;
|
|||||||
extern int graphic_depth;
|
extern int graphic_depth;
|
||||||
extern int display_opengl;
|
extern int display_opengl;
|
||||||
extern const char *keyboard_layout;
|
extern const char *keyboard_layout;
|
||||||
extern int win2k_install_hack;
|
|
||||||
extern int graphic_rotate;
|
extern int graphic_rotate;
|
||||||
extern int old_param;
|
extern int old_param;
|
||||||
extern uint8_t *boot_splash_filedata;
|
extern uint8_t *boot_splash_filedata;
|
||||||
|
@ -2641,7 +2641,8 @@ SRST
|
|||||||
``-win2k-hack``
|
``-win2k-hack``
|
||||||
Use it when installing Windows 2000 to avoid a disk full bug. After
|
Use it when installing Windows 2000 to avoid a disk full bug. After
|
||||||
Windows 2000 is installed, you no longer need this option (this
|
Windows 2000 is installed, you no longer need this option (this
|
||||||
option slows down the IDE transfers).
|
option slows down the IDE transfers). Synonym of ``-global
|
||||||
|
ide-device.win2k-install-hack=on``.
|
||||||
ERST
|
ERST
|
||||||
|
|
||||||
DEF("no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk,
|
DEF("no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk,
|
||||||
@ -2650,7 +2651,7 @@ DEF("no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk,
|
|||||||
SRST
|
SRST
|
||||||
``-no-fd-bootchk``
|
``-no-fd-bootchk``
|
||||||
Disable boot signature checking for floppy disks in BIOS. May be
|
Disable boot signature checking for floppy disks in BIOS. May be
|
||||||
needed to boot from old floppy disks.
|
needed to boot from old floppy disks. Synonym of ``-m fd-bootchk=off``.
|
||||||
ERST
|
ERST
|
||||||
|
|
||||||
DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable,
|
DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable,
|
||||||
|
@ -40,8 +40,6 @@ int autostart = 1;
|
|||||||
int vga_interface_type = VGA_NONE;
|
int vga_interface_type = VGA_NONE;
|
||||||
bool vga_interface_created;
|
bool vga_interface_created;
|
||||||
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
|
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
|
||||||
int win2k_install_hack;
|
|
||||||
int fd_bootchk = 1;
|
|
||||||
int graphic_rotate;
|
int graphic_rotate;
|
||||||
QEMUOptionRom option_rom[MAX_OPTION_ROMS];
|
QEMUOptionRom option_rom[MAX_OPTION_ROMS];
|
||||||
int nb_option_roms;
|
int nb_option_roms;
|
||||||
|
@ -2927,7 +2927,7 @@ void qemu_init(int argc, char **argv)
|
|||||||
optarg, FD_OPTS);
|
optarg, FD_OPTS);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_no_fd_bootchk:
|
case QEMU_OPTION_no_fd_bootchk:
|
||||||
fd_bootchk = 0;
|
qdict_put_str(machine_opts_dict, "fd-bootchk", "off");
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_netdev:
|
case QEMU_OPTION_netdev:
|
||||||
default_net = 0;
|
default_net = 0;
|
||||||
@ -3265,7 +3265,7 @@ void qemu_init(int argc, char **argv)
|
|||||||
pid_file = optarg;
|
pid_file = optarg;
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_win2k_hack:
|
case QEMU_OPTION_win2k_hack:
|
||||||
win2k_install_hack = 1;
|
object_register_sugar_prop("ide-device", "win2k-install-hack", "true", true);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_acpitable:
|
case QEMU_OPTION_acpitable:
|
||||||
opts = qemu_opts_parse_noisily(qemu_find_opts("acpi"),
|
opts = qemu_opts_parse_noisily(qemu_find_opts("acpi"),
|
||||||
|
@ -7735,10 +7735,13 @@ static bool x86_cpu_has_work(CPUState *cs)
|
|||||||
static int x86_cpu_mmu_index(CPUState *cs, bool ifetch)
|
static int x86_cpu_mmu_index(CPUState *cs, bool ifetch)
|
||||||
{
|
{
|
||||||
CPUX86State *env = cpu_env(cs);
|
CPUX86State *env = cpu_env(cs);
|
||||||
|
int mmu_index_32 = (env->hflags & HF_CS64_MASK) ? 1 : 0;
|
||||||
|
int mmu_index_base =
|
||||||
|
(env->hflags & HF_CPL_MASK) == 3 ? MMU_USER64_IDX :
|
||||||
|
!(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX :
|
||||||
|
(env->eflags & AC_MASK) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX;
|
||||||
|
|
||||||
return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX :
|
return mmu_index_base + mmu_index_32;
|
||||||
(!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK))
|
|
||||||
? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x86_disas_set_info(CPUState *cs, disassemble_info *info)
|
static void x86_disas_set_info(CPUState *cs, disassemble_info *info)
|
||||||
|
@ -2299,17 +2299,47 @@ uint64_t cpu_get_tsc(CPUX86State *env);
|
|||||||
#define cpu_list x86_cpu_list
|
#define cpu_list x86_cpu_list
|
||||||
|
|
||||||
/* MMU modes definitions */
|
/* MMU modes definitions */
|
||||||
#define MMU_KSMAP_IDX 0
|
#define MMU_KSMAP64_IDX 0
|
||||||
#define MMU_USER_IDX 1
|
#define MMU_KSMAP32_IDX 1
|
||||||
#define MMU_KNOSMAP_IDX 2
|
#define MMU_USER64_IDX 2
|
||||||
#define MMU_NESTED_IDX 3
|
#define MMU_USER32_IDX 3
|
||||||
#define MMU_PHYS_IDX 4
|
#define MMU_KNOSMAP64_IDX 4
|
||||||
|
#define MMU_KNOSMAP32_IDX 5
|
||||||
|
#define MMU_PHYS_IDX 6
|
||||||
|
#define MMU_NESTED_IDX 7
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
#ifdef TARGET_X86_64
|
||||||
|
#define MMU_USER_IDX MMU_USER64_IDX
|
||||||
|
#else
|
||||||
|
#define MMU_USER_IDX MMU_USER32_IDX
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline bool is_mmu_index_smap(int mmu_index)
|
||||||
|
{
|
||||||
|
return (mmu_index & ~1) == MMU_KSMAP64_IDX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_mmu_index_user(int mmu_index)
|
||||||
|
{
|
||||||
|
return (mmu_index & ~1) == MMU_USER64_IDX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_mmu_index_32(int mmu_index)
|
||||||
|
{
|
||||||
|
assert(mmu_index < MMU_PHYS_IDX);
|
||||||
|
return mmu_index & 1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int cpu_mmu_index_kernel(CPUX86State *env)
|
static inline int cpu_mmu_index_kernel(CPUX86State *env)
|
||||||
{
|
{
|
||||||
return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX :
|
int mmu_index_32 = (env->hflags & HF_LMA_MASK) ? 1 : 0;
|
||||||
((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK))
|
int mmu_index_base =
|
||||||
? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
|
!(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX :
|
||||||
|
((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK)) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX;
|
||||||
|
|
||||||
|
return mmu_index_base + mmu_index_32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CC_DST (env->cc_dst)
|
#define CC_DST (env->cc_dst)
|
||||||
|
@ -134,10 +134,9 @@ static inline bool ptw_setl(const PTETranslate *in, uint32_t old, uint32_t set)
|
|||||||
static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
||||||
TranslateResult *out, TranslateFault *err)
|
TranslateResult *out, TranslateFault *err)
|
||||||
{
|
{
|
||||||
const int32_t a20_mask = x86_get_a20_mask(env);
|
|
||||||
const target_ulong addr = in->addr;
|
const target_ulong addr = in->addr;
|
||||||
const int pg_mode = in->pg_mode;
|
const int pg_mode = in->pg_mode;
|
||||||
const bool is_user = (in->mmu_idx == MMU_USER_IDX);
|
const bool is_user = is_mmu_index_user(in->mmu_idx);
|
||||||
const MMUAccessType access_type = in->access_type;
|
const MMUAccessType access_type = in->access_type;
|
||||||
uint64_t ptep, pte, rsvd_mask;
|
uint64_t ptep, pte, rsvd_mask;
|
||||||
PTETranslate pte_trans = {
|
PTETranslate pte_trans = {
|
||||||
@ -164,8 +163,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||||||
/*
|
/*
|
||||||
* Page table level 5
|
* Page table level 5
|
||||||
*/
|
*/
|
||||||
pte_addr = ((in->cr3 & ~0xfff) +
|
pte_addr = (in->cr3 & ~0xfff) + (((addr >> 48) & 0x1ff) << 3);
|
||||||
(((addr >> 48) & 0x1ff) << 3)) & a20_mask;
|
|
||||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -189,8 +187,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||||||
/*
|
/*
|
||||||
* Page table level 4
|
* Page table level 4
|
||||||
*/
|
*/
|
||||||
pte_addr = ((pte & PG_ADDRESS_MASK) +
|
pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 39) & 0x1ff) << 3);
|
||||||
(((addr >> 39) & 0x1ff) << 3)) & a20_mask;
|
|
||||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -210,8 +207,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||||||
/*
|
/*
|
||||||
* Page table level 3
|
* Page table level 3
|
||||||
*/
|
*/
|
||||||
pte_addr = ((pte & PG_ADDRESS_MASK) +
|
pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3);
|
||||||
(((addr >> 30) & 0x1ff) << 3)) & a20_mask;
|
|
||||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -238,7 +234,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||||||
/*
|
/*
|
||||||
* Page table level 3
|
* Page table level 3
|
||||||
*/
|
*/
|
||||||
pte_addr = ((in->cr3 & ~0x1f) + ((addr >> 27) & 0x18)) & a20_mask;
|
pte_addr = (in->cr3 & 0xffffffe0ULL) + ((addr >> 27) & 0x18);
|
||||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -260,8 +256,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||||||
/*
|
/*
|
||||||
* Page table level 2
|
* Page table level 2
|
||||||
*/
|
*/
|
||||||
pte_addr = ((pte & PG_ADDRESS_MASK) +
|
pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3);
|
||||||
(((addr >> 21) & 0x1ff) << 3)) & a20_mask;
|
|
||||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -287,8 +282,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||||||
/*
|
/*
|
||||||
* Page table level 1
|
* Page table level 1
|
||||||
*/
|
*/
|
||||||
pte_addr = ((pte & PG_ADDRESS_MASK) +
|
pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3);
|
||||||
(((addr >> 12) & 0x1ff) << 3)) & a20_mask;
|
|
||||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -306,7 +300,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||||||
/*
|
/*
|
||||||
* Page table level 2
|
* Page table level 2
|
||||||
*/
|
*/
|
||||||
pte_addr = ((in->cr3 & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
|
pte_addr = (in->cr3 & 0xfffff000ULL) + ((addr >> 20) & 0xffc);
|
||||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -335,7 +329,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
|||||||
/*
|
/*
|
||||||
* Page table level 1
|
* Page table level 1
|
||||||
*/
|
*/
|
||||||
pte_addr = ((pte & ~0xfffu) + ((addr >> 10) & 0xffc)) & a20_mask;
|
pte_addr = (pte & ~0xfffu) + ((addr >> 10) & 0xffc);
|
||||||
if (!ptw_translate(&pte_trans, pte_addr)) {
|
if (!ptw_translate(&pte_trans, pte_addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -363,7 +357,7 @@ do_check_protect_pse36:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int prot = 0;
|
int prot = 0;
|
||||||
if (in->mmu_idx != MMU_KSMAP_IDX || !(ptep & PG_USER_MASK)) {
|
if (!is_mmu_index_smap(in->mmu_idx) || !(ptep & PG_USER_MASK)) {
|
||||||
prot |= PAGE_READ;
|
prot |= PAGE_READ;
|
||||||
if ((ptep & PG_RW_MASK) || !(is_user || (pg_mode & PG_MODE_WP))) {
|
if ((ptep & PG_RW_MASK) || !(is_user || (pg_mode & PG_MODE_WP))) {
|
||||||
prot |= PAGE_WRITE;
|
prot |= PAGE_WRITE;
|
||||||
@ -422,10 +416,13 @@ do_check_protect_pse36:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* align to page_size */
|
/* merge offset within page */
|
||||||
paddr = (pte & a20_mask & PG_ADDRESS_MASK & ~(page_size - 1))
|
paddr = (pte & PG_ADDRESS_MASK & ~(page_size - 1)) | (addr & (page_size - 1));
|
||||||
| (addr & (page_size - 1));
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that NPT is walked (for both paging structures and final guest
|
||||||
|
* addresses) using the address with the A20 bit set.
|
||||||
|
*/
|
||||||
if (in->ptw_idx == MMU_NESTED_IDX) {
|
if (in->ptw_idx == MMU_NESTED_IDX) {
|
||||||
CPUTLBEntryFull *full;
|
CPUTLBEntryFull *full;
|
||||||
int flags, nested_page_size;
|
int flags, nested_page_size;
|
||||||
@ -464,7 +461,7 @@ do_check_protect_pse36:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out->paddr = paddr;
|
out->paddr = paddr & x86_get_a20_mask(env);
|
||||||
out->prot = prot;
|
out->prot = prot;
|
||||||
out->page_size = page_size;
|
out->page_size = page_size;
|
||||||
return true;
|
return true;
|
||||||
@ -545,7 +542,8 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
|
|||||||
if (likely(use_stage2)) {
|
if (likely(use_stage2)) {
|
||||||
in.cr3 = env->nested_cr3;
|
in.cr3 = env->nested_cr3;
|
||||||
in.pg_mode = env->nested_pg_mode;
|
in.pg_mode = env->nested_pg_mode;
|
||||||
in.mmu_idx = MMU_USER_IDX;
|
in.mmu_idx =
|
||||||
|
env->nested_pg_mode & PG_MODE_LMA ? MMU_USER64_IDX : MMU_USER32_IDX;
|
||||||
in.ptw_idx = MMU_PHYS_IDX;
|
in.ptw_idx = MMU_PHYS_IDX;
|
||||||
|
|
||||||
if (!mmu_translate(env, &in, out, err)) {
|
if (!mmu_translate(env, &in, out, err)) {
|
||||||
@ -557,6 +555,10 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (is_mmu_index_32(mmu_idx)) {
|
||||||
|
addr = (uint32_t)addr;
|
||||||
|
}
|
||||||
|
|
||||||
if (likely(env->cr[0] & CR0_PG_MASK)) {
|
if (likely(env->cr[0] & CR0_PG_MASK)) {
|
||||||
in.cr3 = env->cr[3];
|
in.cr3 = env->cr[3];
|
||||||
in.mmu_idx = mmu_idx;
|
in.mmu_idx = mmu_idx;
|
||||||
@ -580,14 +582,8 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translation disabled. */
|
/* No translation needed. */
|
||||||
out->paddr = addr & x86_get_a20_mask(env);
|
out->paddr = addr & x86_get_a20_mask(env);
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
if (!(env->hflags & HF_LMA_MASK)) {
|
|
||||||
/* Without long mode we can only address 32bits in real mode */
|
|
||||||
out->paddr = (uint32_t)out->paddr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
out->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
out->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
out->page_size = TARGET_PAGE_SIZE;
|
out->page_size = TARGET_PAGE_SIZE;
|
||||||
return true;
|
return true;
|
||||||
|
@ -212,6 +212,9 @@ void helper_wrmsr(CPUX86State *env)
|
|||||||
tlb_flush(cs);
|
tlb_flush(cs);
|
||||||
break;
|
break;
|
||||||
case MSR_VM_HSAVE_PA:
|
case MSR_VM_HSAVE_PA:
|
||||||
|
if (val & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
env->vm_hsave = val;
|
env->vm_hsave = val;
|
||||||
break;
|
break;
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
|
@ -164,14 +164,19 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
|||||||
uint64_t new_cr3;
|
uint64_t new_cr3;
|
||||||
uint64_t new_cr4;
|
uint64_t new_cr4;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
|
|
||||||
|
|
||||||
if (aflag == 2) {
|
if (aflag == 2) {
|
||||||
addr = env->regs[R_EAX];
|
addr = env->regs[R_EAX];
|
||||||
} else {
|
} else {
|
||||||
addr = (uint32_t)env->regs[R_EAX];
|
addr = (uint32_t)env->regs[R_EAX];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Exceptions are checked before the intercept. */
|
||||||
|
if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
|
||||||
|
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
|
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
|
||||||
|
|
||||||
env->vm_vmcb = addr;
|
env->vm_vmcb = addr;
|
||||||
@ -463,14 +468,19 @@ void helper_vmload(CPUX86State *env, int aflag)
|
|||||||
int mmu_idx = MMU_PHYS_IDX;
|
int mmu_idx = MMU_PHYS_IDX;
|
||||||
target_ulong addr;
|
target_ulong addr;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
|
|
||||||
|
|
||||||
if (aflag == 2) {
|
if (aflag == 2) {
|
||||||
addr = env->regs[R_EAX];
|
addr = env->regs[R_EAX];
|
||||||
} else {
|
} else {
|
||||||
addr = (uint32_t)env->regs[R_EAX];
|
addr = (uint32_t)env->regs[R_EAX];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Exceptions are checked before the intercept. */
|
||||||
|
if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
|
||||||
|
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
|
||||||
|
|
||||||
if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMLOAD, GETPC())) {
|
if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMLOAD, GETPC())) {
|
||||||
mmu_idx = MMU_NESTED_IDX;
|
mmu_idx = MMU_NESTED_IDX;
|
||||||
}
|
}
|
||||||
@ -519,14 +529,19 @@ void helper_vmsave(CPUX86State *env, int aflag)
|
|||||||
int mmu_idx = MMU_PHYS_IDX;
|
int mmu_idx = MMU_PHYS_IDX;
|
||||||
target_ulong addr;
|
target_ulong addr;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
|
|
||||||
|
|
||||||
if (aflag == 2) {
|
if (aflag == 2) {
|
||||||
addr = env->regs[R_EAX];
|
addr = env->regs[R_EAX];
|
||||||
} else {
|
} else {
|
||||||
addr = (uint32_t)env->regs[R_EAX];
|
addr = (uint32_t)env->regs[R_EAX];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Exceptions are checked before the intercept. */
|
||||||
|
if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
|
||||||
|
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
|
||||||
|
|
||||||
if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMSAVE, GETPC())) {
|
if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMSAVE, GETPC())) {
|
||||||
mmu_idx = MMU_NESTED_IDX;
|
mmu_idx = MMU_NESTED_IDX;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user