mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
x86 and SCSI fixes. I left out the APIC device model
patches, pending confirmation from the submitter that they really fix QNX. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJUZMqiAAoJEL/70l94x66DQEEH/3kWZSwiC6yh5icRmLd1PX9Q P8a5qIGQUldN54orlr4bDs4Slb6w4CVwwupT6AIFvNbZDFQVlJTMd+3ssZ03H++D eJ9WvY3yVmrC1ofFk1WNIposk01gvM0U74Kns4ttEuJ7UyB75mhPEegQd3B8WbPa /eJILlXu9ayxj60yEqmoR8IfqrkuuTHx7P4QmpJigGeLkBhQOq0TXjb1xi+4JPnv BHjVjA6YNtzuMO2wP0y6KE/9HZpow0luAb+vB0NkY0NoEezVucoDWLMMUkpSiZI/ yYFEqp4lzRo2ygnJXlGvLFND6F2qacGIIU5lj5t8a2BmswqD83JEt/idQGYeIzM= =ExeA -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging x86 and SCSI fixes. I left out the APIC device model patches, pending confirmation from the submitter that they really fix QNX. # gpg: Signature made Thu 13 Nov 2014 15:13:38 GMT using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # 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 * remotes/bonzini/tags/for-upstream: acpi: accurate overflow check smbios: change 'ram_addr_t' variables to 'uint64_t' kvmclock: Add comment explaining why we need cpu_clean_all_dirty() target-i386: fix Coverity complaints about overflows apic_common: migrate missing fields target-i386: eliminate dead code and hoist common code out of "if" virtio-scsi: Fix comment for VirtIOSCSIReq virtio-scsi: dataplane: suppress guest notification esp: Do not overwrite ESP_TCHI after reset virtio-scsi: dataplane: fix allocation for 'cmd_vrings' esp: fix coding standards virtio-scsi: work around bug in old BIOSes esp-pci: fixup deadlock with linux Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c52e67924f
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -268,6 +268,9 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
|
||||
/* update status registers */
|
||||
pci->dma_regs[DMA_WBC] -= len;
|
||||
pci->dma_regs[DMA_WAC] += len;
|
||||
if (pci->dma_regs[DMA_WBC] == 0) {
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
|
||||
|
@ -364,7 +364,7 @@ void esp_hard_reset(ESPState *s)
|
||||
{
|
||||
memset(s->rregs, 0, ESP_REGS);
|
||||
memset(s->wregs, 0, ESP_REGS);
|
||||
s->rregs[ESP_TCHI] = s->chip_id;
|
||||
s->tchi_written = 0;
|
||||
s->ti_size = 0;
|
||||
s->ti_rptr = 0;
|
||||
s->ti_wptr = 0;
|
||||
@ -422,6 +422,11 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
|
||||
esp_lower_irq(s);
|
||||
|
||||
return old_val;
|
||||
case ESP_TCHI:
|
||||
/* Return the unique id if the value has never been written */
|
||||
if (!s->tchi_written) {
|
||||
return s->chip_id;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -432,9 +437,11 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
|
||||
{
|
||||
trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
|
||||
switch (saddr) {
|
||||
case ESP_TCHI:
|
||||
s->tchi_written = true;
|
||||
/* fall through */
|
||||
case ESP_TCLO:
|
||||
case ESP_TCMID:
|
||||
case ESP_TCHI:
|
||||
s->rregs[ESP_RSTAT] &= ~STAT_TC;
|
||||
break;
|
||||
case ESP_FIFO:
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1104,7 +1104,7 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env,
|
||||
}
|
||||
|
||||
static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu,
|
||||
int sipi_vector)
|
||||
uint8_t sipi_vector)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
@ -883,32 +883,23 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
|
||||
}
|
||||
if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
|
||||
/* to inner privilege */
|
||||
if (ist != 0) {
|
||||
esp = get_rsp_from_tss(env, ist + 3);
|
||||
} else {
|
||||
esp = get_rsp_from_tss(env, dpl);
|
||||
}
|
||||
esp &= ~0xfLL; /* align stack */
|
||||
ss = 0;
|
||||
new_stack = 1;
|
||||
esp = get_rsp_from_tss(env, ist != 0 ? ist + 3 : dpl);
|
||||
ss = 0;
|
||||
} else if ((e2 & DESC_C_MASK) || dpl == cpl) {
|
||||
/* to same privilege */
|
||||
if (env->eflags & VM_MASK) {
|
||||
raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
|
||||
}
|
||||
new_stack = 0;
|
||||
if (ist != 0) {
|
||||
esp = get_rsp_from_tss(env, ist + 3);
|
||||
} else {
|
||||
esp = env->regs[R_ESP];
|
||||
}
|
||||
esp &= ~0xfLL; /* align stack */
|
||||
esp = env->regs[R_ESP];
|
||||
dpl = cpl;
|
||||
} else {
|
||||
raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
|
||||
new_stack = 0; /* avoid warning */
|
||||
esp = 0; /* avoid warning */
|
||||
}
|
||||
esp &= ~0xfLL; /* align stack */
|
||||
|
||||
PUSHQ(esp, env->segs[R_SS].selector);
|
||||
PUSHQ(esp, env->regs[R_ESP]);
|
||||
|
Loading…
Reference in New Issue
Block a user