From c63c453889d0bfbd183da686bc076590220fd44a Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 24 May 2012 13:22:55 +0200 Subject: virtio-blk: Fix geometry sector calculation Currently the sector value for the geometry is masked, even if the user usesa command line parameter that explicitely gives a number. This breaks dasd devices on s390. A dasd device can have a physical block size of 4096 (== same for logical block size) and a typcial geometry of 15 heads and 12 sectors per cyl. The ibm partition detection relies on a correct geometry reported by the device. Unfortunately the current code changes 12 to 8. This would be necessary if the total size is not a multiple of logical sector size, but for dasd this is not the case. This patch checks the device size and only applies sector mask if necessary. Signed-off-by: Christian Borntraeger CC: Christoph Hellwig Reviewed-by: Paolo Bonzini Signed-off-by: Kevin Wolf (cherry picked from commit 136be99e6e2130d3cd960b6b7d0ca86b6f011e5f) Signed-off-by: Michael Roth --- hw/virtio-blk.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index f9e1896ea..4f5745033 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -489,7 +489,22 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size); stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size); blkcfg.heads = heads; - blkcfg.sectors = secs & ~s->sector_mask; + /* + * We must ensure that the block device capacity is a multiple of + * the logical block size. If that is not the case, lets use + * sector_mask to adopt the geometry to have a correct picture. + * For those devices where the capacity is ok for the given geometry + * we dont touch the sector value of the geometry, since some devices + * (like s390 dasd) need a specific value. Here the capacity is already + * cyls*heads*secs*blk_size and the sector value is not block size + * divided by 512 - instead it is the amount of blk_size blocks + * per track (cylinder). + */ + if (bdrv_getlength(s->bs) / heads / secs % blk_size) { + blkcfg.sectors = secs & ~s->sector_mask; + } else { + blkcfg.sectors = secs; + } blkcfg.size_max = 0; blkcfg.physical_block_exp = get_physical_block_exp(s->conf); blkcfg.alignment_offset = 0; -- cgit v1.2.3 From 6514fe50471ca277c461435b17771e91c115b010 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 27 May 2012 18:34:49 +0400 Subject: target-xtensa: flush TLB page for new MMU mapping Both old and new mappings need flushing because their VPN may be different in MMU case. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl (cherry picked from commit e323bdeff28f3bd647bf02cc9df57971eff3e258) Signed-off-by: Michael Roth --- target-xtensa/op_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 364dc19bc..ce61157c9 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -669,6 +669,7 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb, entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi); entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff; entry->attr = pte & 0xf; + tlb_flush_page(env, entry->vaddr); } else { qemu_log("%s %d, %d, %d trying to set immutable entry\n", __func__, dtlb, wi, ei); -- cgit v1.2.3 From b696aeab6ad6abe3b45fac96264a40a555ff64ce Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 27 May 2012 18:34:50 +0400 Subject: target-xtensa: update EXCVADDR in case of page table lookup According to ISA, 4.4.2.6, EXCVADDR may be changed by any TLB miss, even if the miss is handled entirely by processor hardware. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl (cherry picked from commit 39e7d37f0f25823c00d1105e8eb9b61182fd349c) Signed-off-by: Michael Roth --- target-xtensa/helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 209422784..43a6611e6 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -516,6 +516,7 @@ static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb, *wi = (++env->autorefill_idx) & 0x3; split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, *wi, ei); xtensa_tlb_set_entry(env, dtlb, *wi, *ei, vpn, pte); + env->sregs[EXCVADDR] = vaddr; qemu_log("%s: autorefill(%08x): %08x -> %08x\n", __func__, vaddr, vpn, pte); } -- cgit v1.2.3 From adda59173c976b8863d74b612fafa9212b9182f2 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 27 May 2012 18:34:51 +0400 Subject: target-xtensa: extract TLB entry setting method Signed-off-by: Max Filippov Signed-off-by: Blue Swirl (cherry picked from commit 16bde77a298acfe15f5e948aceff550d0cb173e8) Signed-off-by: Michael Roth --- target-xtensa/cpu.h | 3 +++ target-xtensa/op_helper.c | 15 +++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 6d0ea7c03..6c590fe80 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -370,6 +370,9 @@ void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb, uint32_t *vpn, uint32_t wi, uint32_t *ei); int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb, uint32_t *pwi, uint32_t *pei, uint8_t *pring); +void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env, + xtensa_tlb_entry *entry, bool dtlb, + unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb, unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); int xtensa_get_physical_addr(CPUXtensaState *env, diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index ce61157c9..663bb6dc6 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -655,6 +655,16 @@ uint32_t HELPER(ptlb)(uint32_t v, uint32_t dtlb) } } +void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env, + xtensa_tlb_entry *entry, bool dtlb, + unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte) +{ + entry->vaddr = vpn; + entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi); + entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff; + entry->attr = pte & 0xf; +} + void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb, unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte) { @@ -665,10 +675,7 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb, if (entry->asid) { tlb_flush_page(env, entry->vaddr); } - entry->vaddr = vpn; - entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi); - entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff; - entry->attr = pte & 0xf; + xtensa_tlb_set_entry_mmu(env, entry, dtlb, wi, ei, vpn, pte); tlb_flush_page(env, entry->vaddr); } else { qemu_log("%s %d, %d, %d trying to set immutable entry\n", -- cgit v1.2.3 From 2eb4d314cef55749f7835f6338080895daed277e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 27 May 2012 18:34:52 +0400 Subject: target-xtensa: update autorefill TLB entries conditionally This is to avoid interference of internal QEMU helpers (cpu_get_phys_page_debug, tb_invalidate_virtual_addr) with guest-visible TLB state. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl (cherry picked from commit ae4e7982e6db8b88e90db74779f4693bc2c636a8) Signed-off-by: Michael Roth --- target-xtensa/cpu.h | 2 +- target-xtensa/helper.c | 56 +++++++++++++++++++++++++++-------------------- target-xtensa/op_helper.c | 4 ++-- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 6c590fe80..d5b50d111 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -375,7 +375,7 @@ void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env, unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb, unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); -int xtensa_get_physical_addr(CPUXtensaState *env, +int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb, uint32_t vaddr, int is_write, int mmu_idx, uint32_t *paddr, uint32_t *page_size, unsigned *access); void reset_mmu(CPUXtensaState *env); diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 43a6611e6..86c33d2e6 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -135,11 +135,11 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUXtensaState *env, target_ulong add uint32_t page_size; unsigned access; - if (xtensa_get_physical_addr(env, addr, 0, 0, + if (xtensa_get_physical_addr(env, false, addr, 0, 0, &paddr, &page_size, &access) == 0) { return paddr; } - if (xtensa_get_physical_addr(env, addr, 2, 0, + if (xtensa_get_physical_addr(env, false, addr, 2, 0, &paddr, &page_size, &access) == 0) { return paddr; } @@ -448,10 +448,9 @@ static bool is_access_granted(unsigned access, int is_write) } } -static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb, - uint32_t *wi, uint32_t *ei, uint8_t *ring); +static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte); -static int get_physical_addr_mmu(CPUXtensaState *env, +static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb, uint32_t vaddr, int is_write, int mmu_idx, uint32_t *paddr, uint32_t *page_size, unsigned *access) { @@ -459,19 +458,38 @@ static int get_physical_addr_mmu(CPUXtensaState *env, uint32_t wi; uint32_t ei; uint8_t ring; + uint32_t vpn; + uint32_t pte; + const xtensa_tlb_entry *entry = NULL; + xtensa_tlb_entry tmp_entry; int ret = xtensa_tlb_lookup(env, vaddr, dtlb, &wi, &ei, &ring); if ((ret == INST_TLB_MISS_CAUSE || ret == LOAD_STORE_TLB_MISS_CAUSE) && (mmu_idx != 0 || ((vaddr ^ env->sregs[PTEVADDR]) & 0xffc00000)) && - autorefill_mmu(env, vaddr, dtlb, &wi, &ei, &ring) == 0) { + get_pte(env, vaddr, &pte) == 0) { + ring = (pte >> 4) & 0x3; + wi = 0; + split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, wi, &ei); + + if (update_tlb) { + wi = ++env->autorefill_idx & 0x3; + xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, pte); + env->sregs[EXCVADDR] = vaddr; + qemu_log("%s: autorefill(%08x): %08x -> %08x\n", + __func__, vaddr, vpn, pte); + } else { + xtensa_tlb_set_entry_mmu(env, &tmp_entry, dtlb, wi, ei, vpn, pte); + entry = &tmp_entry; + } ret = 0; } if (ret != 0) { return ret; } - const xtensa_tlb_entry *entry = - xtensa_tlb_get_entry(env, dtlb, wi, ei); + if (entry == NULL) { + entry = xtensa_tlb_get_entry(env, dtlb, wi, ei); + } if (ring < mmu_idx) { return dtlb ? @@ -494,31 +512,21 @@ static int get_physical_addr_mmu(CPUXtensaState *env, return 0; } -static int autorefill_mmu(CPUXtensaState *env, uint32_t vaddr, bool dtlb, - uint32_t *wi, uint32_t *ei, uint8_t *ring) +static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte) { uint32_t paddr; uint32_t page_size; unsigned access; uint32_t pt_vaddr = (env->sregs[PTEVADDR] | (vaddr >> 10)) & 0xfffffffc; - int ret = get_physical_addr_mmu(env, pt_vaddr, 0, 0, + int ret = get_physical_addr_mmu(env, false, pt_vaddr, 0, 0, &paddr, &page_size, &access); qemu_log("%s: trying autorefill(%08x) -> %08x\n", __func__, vaddr, ret ? ~0 : paddr); if (ret == 0) { - uint32_t vpn; - uint32_t pte = ldl_phys(paddr); - - *ring = (pte >> 4) & 0x3; - *wi = (++env->autorefill_idx) & 0x3; - split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, *wi, ei); - xtensa_tlb_set_entry(env, dtlb, *wi, *ei, vpn, pte); - env->sregs[EXCVADDR] = vaddr; - qemu_log("%s: autorefill(%08x): %08x -> %08x\n", - __func__, vaddr, vpn, pte); + *pte = ldl_phys(paddr); } return ret; } @@ -554,13 +562,13 @@ static int get_physical_addr_region(CPUXtensaState *env, * * \return 0 if ok, exception cause code otherwise */ -int xtensa_get_physical_addr(CPUXtensaState *env, +int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb, uint32_t vaddr, int is_write, int mmu_idx, uint32_t *paddr, uint32_t *page_size, unsigned *access) { if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { - return get_physical_addr_mmu(env, vaddr, is_write, mmu_idx, - paddr, page_size, access); + return get_physical_addr_mmu(env, update_tlb, + vaddr, is_write, mmu_idx, paddr, page_size, access); } else if (xtensa_option_bits_enabled(env->config, XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) | XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) { diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 663bb6dc6..41107ff64 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -79,7 +79,7 @@ void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_id uint32_t paddr; uint32_t page_size; unsigned access; - int ret = xtensa_get_physical_addr(env, vaddr, is_write, mmu_idx, + int ret = xtensa_get_physical_addr(env, true, vaddr, is_write, mmu_idx, &paddr, &page_size, &access); qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__, @@ -103,7 +103,7 @@ static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr) uint32_t paddr; uint32_t page_size; unsigned access; - int ret = xtensa_get_physical_addr(env, vaddr, 2, 0, + int ret = xtensa_get_physical_addr(env, false, vaddr, 2, 0, &paddr, &page_size, &access); if (ret == 0) { tb_invalidate_phys_addr(paddr); -- cgit v1.2.3 From 8b3ac661208c88b9d424ede176b99be6fff1283e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 27 May 2012 18:34:53 +0400 Subject: target-xtensa: control page table lookup explicitly Hardware pagetable walking may not be nested. Stop guessing and pass explicit flag to the get_physical_addr_mmu function that controls page table lookup. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl (cherry picked from commit 57705a676c65e6ecacc44c23b192f3d7ed2cdedd) Signed-off-by: Michael Roth --- target-xtensa/helper.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 86c33d2e6..8ebef729b 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -452,7 +452,8 @@ static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte); static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb, uint32_t vaddr, int is_write, int mmu_idx, - uint32_t *paddr, uint32_t *page_size, unsigned *access) + uint32_t *paddr, uint32_t *page_size, unsigned *access, + bool may_lookup_pt) { bool dtlb = is_write != 2; uint32_t wi; @@ -465,8 +466,7 @@ static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb, int ret = xtensa_tlb_lookup(env, vaddr, dtlb, &wi, &ei, &ring); if ((ret == INST_TLB_MISS_CAUSE || ret == LOAD_STORE_TLB_MISS_CAUSE) && - (mmu_idx != 0 || ((vaddr ^ env->sregs[PTEVADDR]) & 0xffc00000)) && - get_pte(env, vaddr, &pte) == 0) { + may_lookup_pt && get_pte(env, vaddr, &pte) == 0) { ring = (pte >> 4) & 0x3; wi = 0; split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, wi, &ei); @@ -520,7 +520,7 @@ static int get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte) uint32_t pt_vaddr = (env->sregs[PTEVADDR] | (vaddr >> 10)) & 0xfffffffc; int ret = get_physical_addr_mmu(env, false, pt_vaddr, 0, 0, - &paddr, &page_size, &access); + &paddr, &page_size, &access, false); qemu_log("%s: trying autorefill(%08x) -> %08x\n", __func__, vaddr, ret ? ~0 : paddr); @@ -568,7 +568,7 @@ int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb, { if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { return get_physical_addr_mmu(env, update_tlb, - vaddr, is_write, mmu_idx, paddr, page_size, access); + vaddr, is_write, mmu_idx, paddr, page_size, access, true); } else if (xtensa_option_bits_enabled(env->config, XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) | XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) { -- cgit v1.2.3 From e77326d99c938d78a06036b8529b669253baec59 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 27 May 2012 18:34:54 +0400 Subject: target-xtensa: add MMU pagewalking tests Signed-off-by: Max Filippov Signed-off-by: Blue Swirl (cherry picked from commit c305e32f4336e29fd3f86fc32ffce7b00e5bd9e1) Signed-off-by: Michael Roth --- tests/tcg/xtensa/test_mmu.S | 221 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 207 insertions(+), 14 deletions(-) diff --git a/tests/tcg/xtensa/test_mmu.S b/tests/tcg/xtensa/test_mmu.S index 52d577421..5d87fbb70 100644 --- a/tests/tcg/xtensa/test_mmu.S +++ b/tests/tcg/xtensa/test_mmu.S @@ -293,26 +293,219 @@ test store_prohibited assert eq, a2, a3 test_end -test dtlb_autoload - set_vector kernel, 0 - - movi a2, 0xd4000000 +/* Set up page table entry vaddr->paddr, ring=pte_ring, attr=pte_attr + * and DTLB way 7 to cover this PTE, ring=pt_ring, attr=pt_attr + */ +.macro pt_setup pt_ring, pt_attr, pte_ring, vaddr, paddr, pte_attr + movi a2, 0x80000000 wsr a2, ptevaddr - movi a3, 0x00001013 - s32i a3, a2, 4 + + movi a3, 0x80000007 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */ + movi a4, 0x04000003 | ((\pt_ring) << 4) /* PADDR 64M */ + wdtlb a4, a3 + isync + + movi a3, ((\paddr) & 0xfffff000) | ((\pte_ring) << 4) | (\pte_attr) + movi a1, ((\vaddr) >> 12) << 2 + add a2, a1, a2 + s32i a3, a2, 0 + + movi a3, 0x80000007 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */ + movi a4, 0x04000000 | ((\pt_ring) << 4) | (\pt_attr) /* PADDR 64M */ + wdtlb a4, a3 + isync + + movi a3, (\vaddr) +.endm + +/* out: PS.RING=ring, PS.EXCM=excm, a3=vaddr */ +.macro go_ring ring, excm, vaddr + movi a3, 10f + pitlb a3, a3 + ritlb1 a2, a3 + movi a1, 0x10 + or a2, a2, a1 + movi a1, 0x000ff000 + and a3, a3, a1 + movi a1, 4 + or a3, a3, a1 + witlb a2, a3 + movi a3, 10f + movi a1, 0x000fffff + and a1, a3, a1 + + movi a2, 0 + wsr a2, excvaddr + + movi a3, \vaddr + movi a2, 0x4000f | ((\ring) << 6) | ((\excm) << 4) + jx a1 +10: + wsr a2, ps + isync +.endm + +/* in: a3 -- virtual address to test */ +.macro assert_auto_tlb + movi a2, 0x4000f + wsr a2, ps + isync + pdtlb a2, a3 + movi a1, 0xfffff01f + and a2, a2, a1 + movi a1, 0xfffff000 + and a1, a1, a3 + xor a1, a1, a2 + assert gei, a1, 0x10 + movi a2, 0x14 + assert lt, a1, a2 +.endm + +/* in: a3 -- virtual address to test */ +.macro assert_no_auto_tlb + movi a2, 0x4000f + wsr a2, ps + isync pdtlb a2, a3 movi a1, 0x10 and a1, a1, a2 assert eqi, a1, 0 - l8ui a1, a3, 0 - pdtlb a2, a3 - movi a1, 0xfffff010 - and a1, a1, a2 - movi a3, 0x00001010 - assert eq, a1, a3 - movi a1, 0xf +.endm + +.macro assert_sr sr, v + rsr a2, \sr + movi a1, (\v) + assert eq, a1, a2 +.endm + +.macro assert_epc1_1m vaddr + movi a2, (\vaddr) + movi a1, 0xfffff and a1, a1, a2 - assert lti, a1, 4 + rsr a2, epc1 + assert eq, a1, a2 +.endm + +test dtlb_autoload + set_vector kernel, 0 + + pt_setup 0, 3, 1, 0x1000, 0x1000, 3 + assert_no_auto_tlb + + l8ui a1, a3, 0 + + rsr a2, excvaddr + assert eq, a2, a3 + + assert_auto_tlb +test_end + +test autoload_load_store_privilege + set_vector kernel, 0 + set_vector double, 2f + + pt_setup 0, 3, 0, 0x2000, 0x2000, 3 + movi a3, 0x2004 + assert_no_auto_tlb + + movi a2, 0x4005f /* ring 1 + excm => cring == 0 */ + wsr a2, ps + isync +1: + l32e a2, a3, -4 /* ring used */ + test_fail +2: + rsr a2, excvaddr + addi a1, a3, -4 + assert eq, a1, a2 + + assert_auto_tlb + assert_sr depc, 1b + assert_sr exccause, 26 +test_end + +test autoload_pte_load_prohibited + set_vector kernel, 2f + + pt_setup 0, 3, 0, 0x3000, 0, 0xc + assert_no_auto_tlb +1: + l32i a2, a3, 0 + test_fail +2: + rsr a2, excvaddr + assert eq, a2, a3 + + assert_auto_tlb + assert_sr epc1, 1b + assert_sr exccause, 28 +test_end + +test autoload_pt_load_prohibited + set_vector kernel, 2f + + pt_setup 0, 0xc, 0, 0x4000, 0x4000, 3 + assert_no_auto_tlb +1: + l32i a2, a3, 0 + test_fail +2: + rsr a2, excvaddr + assert eq, a2, a3 + + assert_no_auto_tlb + assert_sr epc1, 1b + assert_sr exccause, 24 +test_end + +test autoload_pt_privilege + set_vector kernel, 2f + pt_setup 0, 3, 1, 0x5000, 0, 3 + go_ring 1, 0, 0x5001 + + l8ui a2, a3, 0 +1: + syscall +2: + rsr a2, excvaddr + assert eq, a2, a3 + + assert_auto_tlb + assert_epc1_1m 1b + assert_sr exccause, 1 +test_end + +test autoload_pte_privilege + set_vector kernel, 2f + pt_setup 0, 3, 0, 0x6000, 0, 3 + go_ring 1, 0, 0x6001 +1: + l8ui a2, a3, 0 + syscall +2: + rsr a2, excvaddr + assert eq, a2, a3 + + assert_auto_tlb + assert_epc1_1m 1b + assert_sr exccause, 26 +test_end + +test autoload_3_level_pt + set_vector kernel, 2f + pt_setup 1, 3, 1, 0x00400000, 0, 3 + pt_setup 1, 3, 1, 0x80001000, 0x2000000, 3 + go_ring 1, 0, 0x00400001 +1: + l8ui a2, a3, 0 + syscall +2: + rsr a2, excvaddr + assert eq, a2, a3 + + assert_no_auto_tlb + assert_epc1_1m 1b + assert_sr exccause, 24 test_end test_suite_end -- cgit v1.2.3 From 07ff37597bee726681c94c650568870bd4ff94d1 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 27 May 2012 20:21:08 +0400 Subject: exec: fix TB invalidation after breakpoint insertion/deletion tb_invalidate_phys_addr has to be called with the exact physical address of the breakpoint we add/remove, not just the page's base address. Otherwise we easily fail to flush the right TB. This breakage was introduced by the commit f3705d5329 "memory: make phys_page_find() return an unadjusted". This appeared to work for some guest architectures because their cpu_get_phys_page_debug implementation returns full translated physical address, not just the base of the TARGET_PAGE_SIZE-sized page. Reported-by: TeLeMan Signed-off-by: Jan Kiszka Signed-off-by: Max Filippov Signed-off-by: Blue Swirl (cherry picked from commit 9d70c4b7b8a580959cc4f739e7c9a04964d00d46) Signed-off-by: Michael Roth --- exec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index a0494c72b..0a67f078c 100644 --- a/exec.c +++ b/exec.c @@ -1492,7 +1492,8 @@ void tb_invalidate_phys_addr(target_phys_addr_t addr) static void breakpoint_invalidate(CPUArchState *env, target_ulong pc) { - tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc)); + tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) | + (pc & ~TARGET_PAGE_MASK)); } #endif #endif /* TARGET_HAS_ICE */ -- cgit v1.2.3 From b993b863e78ae54c5e966f4e1626bc37c560e6aa Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 28 May 2012 03:18:33 +0400 Subject: target-xtensa: fix CCOUNT for conditional branches Taken conditional branches fail to update CCOUNT register because accumulated ccount_delta is reset during translation of non-taken branch. To fix it only update CCOUNT once per conditional branch instruction translation. This fixes guest linux freeze on LTP waitpid06 test. Signed-off-by: Max Filippov Signed-off-by: Blue Swirl (cherry picked from commit d865f307399441919d6646545b7735e57920da04) Signed-off-by: Michael Roth --- target-xtensa/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 521c0e622..a542a319d 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -388,6 +388,7 @@ static bool gen_check_loop_end(DisasContext *dc, int slot) dc->next_pc == dc->lend) { int label = gen_new_label(); + gen_advance_ccount(dc); tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_SR[LCOUNT], 0, label); tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_SR[LCOUNT], 1); gen_jumpi(dc, dc->lbeg, slot); @@ -410,6 +411,7 @@ static void gen_brcond(DisasContext *dc, TCGCond cond, { int label = gen_new_label(); + gen_advance_ccount(dc); tcg_gen_brcond_i32(cond, t0, t1, label); gen_jumpi_check_loop_end(dc, 0); gen_set_label(label); -- cgit v1.2.3 From 08375616a0e24484f313900311e1748a2fe12f87 Mon Sep 17 00:00:00 2001 From: Harsh Prateek Bora Date: Fri, 8 Jun 2012 03:20:42 +0530 Subject: trace/simple.c: fix deprecated glib2 interface Signed-off-by: Harsh Prateek Bora Signed-off-by: Stefan Hajnoczi (cherry picked from commit 0d665005c7fd3800f1ae590701f60fe7e4c9a57a) Signed-off-by: Michael Roth --- trace/simple.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/trace/simple.c b/trace/simple.c index 33ae48696..b4a3c6e95 100644 --- a/trace/simple.c +++ b/trace/simple.c @@ -161,8 +161,11 @@ static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, } timestamp = get_clock(); - +#if GLIB_CHECK_VERSION(2, 30, 0) + idx = g_atomic_int_add((gint *)&trace_idx, 1) % TRACE_BUF_LEN; +#else idx = g_atomic_int_exchange_and_add((gint *)&trace_idx, 1) % TRACE_BUF_LEN; +#endif trace_buf[idx] = (TraceRecord){ .event = event, .timestamp_ns = timestamp, -- cgit v1.2.3 From 0cc21de484d4f00c7b7cacb487bd343cc55effa5 Mon Sep 17 00:00:00 2001 From: Harsh Prateek Bora Date: Fri, 8 Jun 2012 03:20:43 +0530 Subject: configure: report missing libraries for virtfs Signed-off-by: Harsh Prateek Bora Signed-off-by: Stefan Hajnoczi (cherry picked from commit 263ddcc81bf45d475ef86100a8567b3fb2129b8d) Signed-off-by: Michael Roth --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 1f338f8dc..268ed21b6 100755 --- a/configure +++ b/configure @@ -2915,7 +2915,8 @@ if test "$softmmu" = yes ; then tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" else if test "$virtfs" = yes; then - feature_not_found "virtfs" + echo "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel" + exit 1 fi virtfs=no fi -- cgit v1.2.3 From ca09717e8e0664801522781962a3c727d04eef33 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 10 May 2012 18:19:47 +0200 Subject: kvm/apic: correct short memset kvm_put_apic_state's attempt to clear *kapic before setting its bits cleared sizeof(void*) bytes (no more than 8) rather than the intended 1024 (KVM_APIC_REG_SIZE) bytes. Spotted by coverity. Signed-off-by: Jim Meyering Signed-off-by: Avi Kivity (cherry picked from commit 0614cb82ca27bdffb83864e693fc29e29182667b) Signed-off-by: Michael Roth --- hw/kvm/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index ffe7a521b..a0ab50316 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -29,7 +29,7 @@ void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic) APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); int i; - memset(kapic, 0, sizeof(kapic)); + memset(kapic, 0, sizeof(*kapic)); kvm_apic_set_reg(kapic, 0x2, s->id << 24); kvm_apic_set_reg(kapic, 0x8, s->tpr); kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24); -- cgit v1.2.3 From 7672b714b28e3d49f73c605873404bf6f644c2b2 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 6 Jun 2012 16:28:42 +0200 Subject: kvm: i8254: Fix conversion of in-kernel to userspace state Due to a offset between the clock used to generate the in-kernel count_load_time (CLOCK_MONOTONIC) and the clock used for processing this in userspace (vm_clock), reading back the output of PIT channel 2 via port 0x61 was broken. One use cases that suffered from it was the CPU frequency calibration of SeaBIOS, which also affected IDE/AHCI timeouts. This fixes it by calibrating the offset between both clocks on kvm_pit_get and adjusting the kernel value before saving it in the userspace state. As the calibration only works while the vm_clock is running, we cache the in-kernel state across stopped phases. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity (cherry picked from commit 0cdd3d14447da1a04e778c219c77db8b96f9cf33) Signed-off-by: Michael Roth --- hw/kvm/i8254.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c index bb5fe07d1..c5d3711a0 100644 --- a/hw/kvm/i8254.c +++ b/hw/kvm/i8254.c @@ -23,31 +23,63 @@ * THE SOFTWARE. */ #include "qemu-timer.h" +#include "sysemu.h" #include "hw/i8254.h" #include "hw/i8254_internal.h" #include "kvm.h" #define KVM_PIT_REINJECT_BIT 0 +#define CALIBRATION_ROUNDS 3 + typedef struct KVMPITState { PITCommonState pit; LostTickPolicy lost_tick_policy; + bool state_valid; } KVMPITState; -static void kvm_pit_get(PITCommonState *s) +static int64_t abs64(int64_t v) { + return v < 0 ? -v : v; +} + +static void kvm_pit_get(PITCommonState *pit) +{ + KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit); struct kvm_pit_state2 kpit; struct kvm_pit_channel_state *kchan; struct PITChannelState *sc; + int64_t offset, clock_offset; + struct timespec ts; int i, ret; + if (s->state_valid) { + return; + } + + /* + * Measure the delta between CLOCK_MONOTONIC, the base used for + * kvm_pit_channel_state::count_load_time, and vm_clock. Take the + * minimum of several samples to filter out scheduling noise. + */ + clock_offset = INT64_MAX; + for (i = 0; i < CALIBRATION_ROUNDS; i++) { + offset = qemu_get_clock_ns(vm_clock); + clock_gettime(CLOCK_MONOTONIC, &ts); + offset -= ts.tv_nsec; + offset -= (int64_t)ts.tv_sec * 1000000000; + if (abs64(offset) < abs64(clock_offset)) { + clock_offset = offset; + } + } + if (kvm_has_pit_state2()) { ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT2, &kpit); if (ret < 0) { fprintf(stderr, "KVM_GET_PIT2 failed: %s\n", strerror(ret)); abort(); } - s->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY; + pit->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY; } else { /* * kvm_pit_state2 is superset of kvm_pit_state struct, @@ -61,7 +93,7 @@ static void kvm_pit_get(PITCommonState *s) } for (i = 0; i < 3; i++) { kchan = &kpit.channels[i]; - sc = &s->channels[i]; + sc = &pit->channels[i]; sc->count = kchan->count; sc->latched_count = kchan->latched_count; sc->count_latched = kchan->count_latched; @@ -74,10 +106,10 @@ static void kvm_pit_get(PITCommonState *s) sc->mode = kchan->mode; sc->bcd = kchan->bcd; sc->gate = kchan->gate; - sc->count_load_time = kchan->count_load_time; + sc->count_load_time = kchan->count_load_time + clock_offset; } - sc = &s->channels[0]; + sc = &pit->channels[0]; sc->next_transition_time = pit_get_next_transition_time(sc, sc->count_load_time); } @@ -173,6 +205,19 @@ static void kvm_pit_irq_control(void *opaque, int n, int enable) kvm_pit_put(pit); } +static void kvm_pit_vm_state_change(void *opaque, int running, + RunState state) +{ + KVMPITState *s = opaque; + + if (running) { + s->state_valid = false; + } else { + kvm_pit_get(&s->pit); + s->state_valid = true; + } +} + static int kvm_pit_initfn(PITCommonState *pit) { KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit); @@ -215,6 +260,8 @@ static int kvm_pit_initfn(PITCommonState *pit) qdev_init_gpio_in(&pit->dev.qdev, kvm_pit_irq_control, 1); + qemu_add_vm_change_state_handler(kvm_pit_vm_state_change, s); + return 0; } -- cgit v1.2.3 From b4fcb4b4995b292b6013600af78d37416c6ebb34 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 15 Jun 2012 13:43:18 +0200 Subject: qcow2: Silence false warning Some gcc versions seem not to be able to figure out that the switch statement covers all possible values and that c is therefore always initialised. Add a default branch for them. Reported-by: malc Signed-off-by: Kevin Wolf Signed-off-by: malc (cherry picked from commit 1417d7e40eaf1418333fb2ec43d0c7f4245b10e7) Signed-off-by: Michael Roth --- block/qcow2-cluster.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 4b3345b11..c173fcd48 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -471,6 +471,8 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO); *cluster_offset &= L2E_OFFSET_MASK; break; + default: + abort(); } qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); -- cgit v1.2.3 From c49dd1bf6450b7880972b2f176ec10e8a496073c Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 14 May 2012 09:47:20 +0000 Subject: monitor: Fix memory leak with readline completion Each string which is shown during readline completion in the QEMU monitor is allocated dynamically but currently never deallocated. Add the missing loop which calls g_free for the allocated strings. Signed-off-by: Stefan Weil Reviewed-by: Stefan Hajnoczi (cherry picked from commit fc9fa4bd0a295ac18808c4cd2cfac484bc4649d3) Signed-off-by: Michael Roth --- readline.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readline.c b/readline.c index a6c0039ad..540cd8a02 100644 --- a/readline.c +++ b/readline.c @@ -337,6 +337,9 @@ static void readline_completion(ReadLineState *rs) } readline_show_prompt(rs); } + for (i = 0; i < rs->nb_completions; i++) { + g_free(rs->completions[i]); + } } /* return true if command handled */ -- cgit v1.2.3 From f6db26e4f8fe6d80e17aa62e6bcc465e323a7fee Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 6 Jun 2012 19:35:57 +0000 Subject: configure: Fix build for some versions of glibc (9pfs) Some versions declare open_by_handle_at, but don't define AT_EMPTY_PATH. Extend the check in configure to test both preconditions. Signed-off-by: Stefan Weil Acked-by: Stefano Stabellini Acked-by: Serge Hallyn (cherry picked from commit acc55ba8b1519bda27be19fad50b65d2b0c7d26d) Signed-off-by: Michael Roth --- configure | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure b/configure index 268ed21b6..72d16a495 100755 --- a/configure +++ b/configure @@ -2811,7 +2811,11 @@ fi open_by_hande_at=no cat > $TMPC << EOF #include +#if !defined(AT_EMPTY_PATH) +# error missing definition +#else int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); } +#endif EOF if compile_prog "" "" ; then open_by_handle_at=yes -- cgit v1.2.3 From 065436479b9164b51892dbd7a7e35a3f9f496894 Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Mon, 4 Jun 2012 17:35:11 +0300 Subject: rtl8139: honor RxOverflow flag in can_receive method Some drivers (Linux' 8139too among them) rely on the NIC injecting an interrupt in the event of a receive buffer overflow and, accordingly, set the RxOverflow bit in the interrupt mask. Unfortunately rtl8139's can_receive method ignores the RxOverflow flag, which may lead to a situation where rtl8139 stops receiving packets (can_receive returns 0) when the receive buffer becomes full. If the driver eventually read from the receive buffer or reset the card the emulator could recover from this situation. However some implementations only do this upon receiving an interrupt with either RxOK or RxOverflow set in the ISR; interrupt that will never come because QEMU's flow control mechanisms would prevent rtl8139 from receiving any packet. Letting packets go through when the overflow interrupt is enabled makes the QEMU emulator compliant to the spec and solves the problem. This patch should fix a relatively common (in our experience) network stall observed when running enterprise distros with rtl8139 as the NIC; in some cases the 8139too device driver gets loaded and when under heavy load the network eventually stops working. Reported-by: Hayato Kakuta Tested-by: Hayato Kakuta Acked-by: Igor Kovalenko Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: Michael S. Tsirkin (cherry picked from commit fee9d348ffc5c9f80068086799a948996f633f7e) Signed-off-by: Michael Roth --- hw/rtl8139.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index eb22d04fa..f6f144b52 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -802,7 +802,7 @@ static int rtl8139_can_receive(VLANClientState *nc) } else { avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); - return (avail == 0 || avail >= 1514); + return (avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow)); } } -- cgit v1.2.3 From 1658e3cd893e3a35d89388fdd736a6d81cb405e8 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 11 May 2012 11:42:34 -0300 Subject: ahci: Fix reset of MSI function Call msi_reset on device reset as still required by the core. CC: Alexander Graf CC: qemu-stable@nongnu.org Signed-off-by: Jan Kiszka Signed-off-by: Michael S. Tsirkin (cherry picked from commit 868a1a52267daddf933ee18480ae036da029b561) Signed-off-by: Michael Roth --- hw/ide/ich.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 560ae3761..242254e8d 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -84,6 +84,14 @@ static const VMStateDescription vmstate_ahci = { .unmigratable = 1, }; +static void pci_ich9_reset(void *opaque) +{ + struct AHCIPCIState *d = opaque; + + msi_reset(&d->card); + ahci_reset(opaque); +} + static int pci_ich9_ahci_init(PCIDevice *dev) { struct AHCIPCIState *d; @@ -102,7 +110,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev) /* XXX Software should program this register */ d->card.config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */ - qemu_register_reset(ahci_reset, d); + qemu_register_reset(pci_ich9_reset, d); msi_init(dev, 0x50, 1, true, false); d->ahci.irq = d->card.irq[0]; @@ -133,7 +141,7 @@ static int pci_ich9_uninit(PCIDevice *dev) d = DO_UPCAST(struct AHCIPCIState, card, dev); msi_uninit(dev); - qemu_unregister_reset(ahci_reset, d); + qemu_unregister_reset(pci_ich9_reset, d); ahci_uninit(&d->ahci); return 0; -- cgit v1.2.3 From 0ec39075710ae15acc2a5825cd21e0c229fa04af Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 11 May 2012 11:42:35 -0300 Subject: intel-hda: Fix reset of MSI function Call msi_reset on device reset as still required by the core. CC: Gerd Hoffmann CC: qemu-stable@nongnu.org Signed-off-by: Jan Kiszka Signed-off-by: Michael S. Tsirkin (cherry picked from commit 8e729e3b521d9fcd87fc2e40b6322e684f58bb2e) Signed-off-by: Michael Roth --- hw/intel-hda.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index bb11af286..e38861e5d 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -1107,6 +1107,9 @@ static void intel_hda_reset(DeviceState *dev) DeviceState *qdev; HDACodecDevice *cdev; + if (d->msi) { + msi_reset(&d->pci); + } intel_hda_regs_reset(d); d->wall_base_ns = qemu_get_clock_ns(vm_clock); -- cgit v1.2.3 From f63e60327b8e239ae97fa71060940ca20a8bf38e Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Wed, 2 May 2012 22:42:10 -0400 Subject: qdev: release parent properties on dc->init failure While looking into hot-plugging bridges, I can create a qemu segfault via: $ device_add pci-bridge Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0. ** ERROR:qom/object.c:389:object_delete: assertion failed: (obj->ref == 0) I'm proposing to fix this by adding a call to 'object_unparent()', before the call to qdev_free(). I see there is already a precedent for this usage pattern as seen in qdev_simple_unplug_cb(): /* can be used as ->unplug() callback for the simple cases */ int qdev_simple_unplug_cb(DeviceState *dev) { /* just zap it */ object_unparent(OBJECT(dev)); qdev_free(dev); return 0; } Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin (cherry picked from commit 266ca11a0433643a3cc3146a9837d9f2b0bfbe3b) Signed-off-by: Michael Roth --- hw/qdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/qdev.c b/hw/qdev.c index 6a8f6bda2..af419b9c1 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -150,6 +150,7 @@ int qdev_init(DeviceState *dev) rc = dc->init(dev); if (rc < 0) { + object_unparent(OBJECT(dev)); qdev_free(dev); return rc; } -- cgit v1.2.3 From dbe4ac16bbab4c237ff54132968accad4f5a4757 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Wed, 2 May 2012 22:42:15 -0400 Subject: pci_bridge_dev: fix error path in pci_bridge_dev_initfn() Currently, we do not properly cleanup, if pci_bridge_dev_initfn fails to initialize properly. Make sure to call pci_bridge_exitfn() in the error path. Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin (cherry picked from commit 80aa796bf38b7ef21daa42673b4711510c450d8a) Signed-off-by: Michael Roth --- hw/pci_bridge_dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c index eccaa5831..ad63703c0 100644 --- a/hw/pci_bridge_dev.c +++ b/hw/pci_bridge_dev.c @@ -52,7 +52,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev) { PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev); PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br); - int err; + int err, ret; pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn); err = pci_bridge_initfn(dev); if (err) { @@ -86,6 +86,8 @@ slotid_error: shpc_cleanup(dev, &bridge_dev->bar); shpc_error: memory_region_destroy(&bridge_dev->bar); + ret = pci_bridge_exitfn(dev); + assert(!ret); bridge_error: return err; } -- cgit v1.2.3 From 02fe741375d4993b3d6870ff6466cc775b409ba1 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Sat, 28 Apr 2012 15:38:08 +0800 Subject: qcow2: fix endianness conversion Signed-off-by: Zhi Yong Wu Reviewed-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf (cherry picked from commit 87267753a36798e25262ee48264bea2ab70921aa) Signed-off-by: Michael Roth --- block/qcow2-refcount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 812c93c5c..443c02145 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -367,7 +367,7 @@ static int alloc_refcount_block(BlockDriverState *bs, } for(i = 0; i < table_size; i++) { - cpu_to_be64s(&new_table[i]); + be64_to_cpus(&new_table[i]); } /* Hook up the new refcount table in the qcow2 header */ -- cgit v1.2.3 From ee7735fa639c43ccb3746d84609332e48e22479f Mon Sep 17 00:00:00 2001 From: Pavel Dovgaluk Date: Wed, 30 May 2012 10:08:04 +0400 Subject: Prevent disk data loss when closing qemu Prevent disk data loss when closing qemu console window under Windows 7. v3. Comment for Sleep() parameter was updated. Signed-off-by: Pavel Dovgalyuk Signed-off-by: Kevin Wolf (cherry picked from commit b75a02829dde98723dfe16fa098338cb267b28b9) Signed-off-by: Michael Roth --- os-win32.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/os-win32.c b/os-win32.c index ad76370c7..13892ba32 100644 --- a/os-win32.c +++ b/os-win32.c @@ -57,7 +57,13 @@ int setenv(const char *name, const char *value, int overwrite) static BOOL WINAPI qemu_ctrl_handler(DWORD type) { - exit(STATUS_CONTROL_C_EXIT); + qemu_system_shutdown_request(); + /* Windows 7 kills application when the function returns. + Sleep here to give QEMU a try for closing. + Sleep period is 10000ms because Windows kills the program + after 10 seconds anyway. */ + Sleep(10000); + return TRUE; } -- cgit v1.2.3 From 0da4c073228c645a0366f3fe801df072cf268482 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 14 Jun 2012 11:42:23 +0100 Subject: qcow2: fix autoclear image header update The autoclear feature bits can be used for qcow2 file format features that are safe to "drop" by old programs that do not understand the feature. Upon opening the image file unknown autoclear feature bits are cleared and the image file header is rewritten, but this was happening too early in the code when critical header fields were not yet loaded. Process autoclear feature bits after all necessary header information has been loaded. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf (cherry picked from commit af7b708db2d03eb47f7ba44a050439ad9ee65e7a) Signed-off-by: Michael Roth --- block/qcow2.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index c2e49cded..79201fce2 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -298,14 +298,6 @@ static int qcow2_open(BlockDriverState *bs, int flags) goto fail; } - if (!bs->read_only && s->autoclear_features != 0) { - s->autoclear_features = 0; - ret = qcow2_update_header(bs); - if (ret < 0) { - goto fail; - } - } - /* Check support for various header values */ if (header.refcount_order != 4) { report_unsupported(bs, "%d bit reference counts", @@ -411,6 +403,15 @@ static int qcow2_open(BlockDriverState *bs, int flags) goto fail; } + /* Clear unknown autoclear feature bits */ + if (!bs->read_only && s->autoclear_features != 0) { + s->autoclear_features = 0; + ret = qcow2_update_header(bs); + if (ret < 0) { + goto fail; + } + } + /* Initialise locks */ qemu_co_mutex_init(&s->lock); -- cgit v1.2.3 From 70d582074f0b9485ad9800f8e0126ef68608ba85 Mon Sep 17 00:00:00 2001 From: Pavel Hrdina Date: Wed, 13 Jun 2012 15:43:11 +0200 Subject: fdc: fix implied seek while there is no media in drive The Windows uses 'READ' command at the start of an instalation without checking the 'dir' register. We have to abort the transfer with an abnormal termination if there is no media in the drive. Signed-off-by: Pavel Hrdina Signed-off-by: Kevin Wolf (cherry picked from commit c52acf60b6c12ff5eb58eb6ac568c159ae0c8737) Signed-off-by: Michael Roth --- hw/fdc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/fdc.c b/hw/fdc.c index 30d34e3f1..be3520112 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -159,6 +159,10 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect, drv->sect = sect; } + if (drv->bs == NULL || !bdrv_is_inserted(drv->bs)) { + ret = 2; + } + return ret; } -- cgit v1.2.3 From 4c45bf61d315316b5932051551c16b17cf9b3d85 Mon Sep 17 00:00:00 2001 From: Bruce Rogers Date: Wed, 13 Jun 2012 16:29:17 -0600 Subject: build: install qmp-commands.txt File is targeted for install, but is never installed. Signed-off-by: Bruce Rogers Signed-off-by: Luiz Capitulino (cherry picked from commit 0cd23fcc0afe0a847e2e68797b64b297b20121f9) Signed-off-by: Michael Roth --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 9b7a85e4d..9707fa0ef 100644 --- a/Makefile +++ b/Makefile @@ -271,6 +271,7 @@ endif install-doc: $(DOCS) $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)" $(INSTALL_DATA) qemu-doc.html qemu-tech.html "$(DESTDIR)$(qemu_docdir)" + $(INSTALL_DATA) QMP/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)" ifdef CONFIG_POSIX $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" $(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1" -- cgit v1.2.3 From c9c2479289fd1faf4a1a40db54cc255fbf03af21 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 11 Jun 2012 09:52:27 +0000 Subject: qemu/xendisk: set maximum number of grants to be used Legacy (non-pvops) gntdev drivers may require this to be done when the number of grants intended to be used simultaneously exceeds a certain driver specific default limit. Signed-off-by: Jan Beulich Signed-off-by: Stefano Stabellini (cherry picked from commit 64c27e5b1fdb6d94bdc0bda3b1869d7383a35c65) Signed-off-by: Michael Roth --- hw/xen_disk.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 07594bc0c..de7e8a4a5 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -537,6 +537,15 @@ static void blk_bh(void *opaque) blk_handle_requests(blkdev); } +/* + * We need to account for the grant allocations requiring contiguous + * chunks; the worst case number would be + * max_req * max_seg + (max_req - 1) * (max_seg - 1) + 1, + * but in order to keep things simple just use + * 2 * max_req * max_seg. + */ +#define MAX_GRANTS(max_req, max_seg) (2 * (max_req) * (max_seg)) + static void blk_alloc(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); @@ -548,6 +557,11 @@ static void blk_alloc(struct XenDevice *xendev) if (xen_mode != XEN_EMULATE) { batch_maps = 1; } + if (xc_gnttab_set_max_grants(xendev->gnttabdev, + MAX_GRANTS(max_requests, BLKIF_MAX_SEGMENTS_PER_REQUEST)) < 0) { + xen_be_printf(xendev, 0, "xc_gnttab_set_max_grants failed: %s\n", + strerror(errno)); + } } static int blk_init(struct XenDevice *xendev) -- cgit v1.2.3 From feba8ae20b372115bc15432d7c484171c25bee62 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Wed, 30 May 2012 01:05:15 +0900 Subject: sheepdog: fix return value of do_load_save_vm_state bdrv_save_vmstate and bdrv_load_vmstate should return the vmstate size on success, and -errno on error. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf (cherry picked from commit 6f3c714eb7730630241fd0b33b799352d7feb876) Signed-off-by: Michael Roth --- block/sheepdog.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index 6d52277a8..f46ca8fb6 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1957,7 +1957,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, int64_t pos, int size, int load) { int fd, create; - int ret = 0; + int ret = 0, remaining = size; unsigned int data_len; uint64_t vmstate_oid; uint32_t vdi_index; @@ -1968,11 +1968,11 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, return fd; } - while (size) { + while (remaining) { vdi_index = pos / SD_DATA_OBJ_SIZE; offset = pos % SD_DATA_OBJ_SIZE; - data_len = MIN(size, SD_DATA_OBJ_SIZE); + data_len = MIN(remaining, SD_DATA_OBJ_SIZE); vmstate_oid = vid_to_vmstate_oid(s->inode.vdi_id, vdi_index); @@ -1993,9 +1993,9 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, } pos += data_len; - size -= data_len; - ret += data_len; + remaining -= data_len; } + ret = size; cleanup: closesocket(fd); return ret; -- cgit v1.2.3 From 7d440f20bda8658fe16bdfe9c41c689764c50248 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 22 May 2012 23:23:32 +0200 Subject: virtio: Fix compiler warning for non Linux hosts The local variables ret, i are only used if __linux__ is defined. Signed-off-by: Stefan Weil Signed-off-by: Kevin Wolf (cherry picked from commit 47ce9ef7f89032c4079bf5132a12d1bfd4d5bca5) Signed-off-by: Michael Roth --- hw/virtio-blk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 4f5745033..fe0774617 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -147,9 +147,11 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) static void virtio_blk_handle_scsi(VirtIOBlockReq *req) { +#ifdef __linux__ int ret; - int status = VIRTIO_BLK_S_OK; int i; +#endif + int status = VIRTIO_BLK_S_OK; /* * We require at least one output segment each for the virtio_blk_outhdr -- cgit v1.2.3 From 845685265756467050859e2359acf16321111352 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 13 Jun 2012 14:29:15 +0100 Subject: qemu-img: document qed format on qemu-img man page The qemu-img.1 man page is missing the qed format from its list of supported formats. Document the image creation options for qed. Suggested-by: Michael Tokarev Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf (cherry picked from commit f085800e245836fed27fddb3b624a29326637657) Signed-off-by: Michael Roth --- qemu-img.texi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/qemu-img.texi b/qemu-img.texi index 6fc3c28e0..9cee2eaa6 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -232,6 +232,29 @@ to grow. @end table +@item qed +Image format with support for backing files and compact image files (when your +filesystem or transport medium does not support holes). Good performance due +to less metadata than the more featureful qcow2 format, especially with +cache=writethrough or cache=directsync. Consider using qcow2 which will soon +have a similar optimization and is most actively developed. + +Supported options: +@table @code +@item backing_file +File name of a base image (see @option{create} subcommand). +@item backing_fmt +Image file format of backing file (optional). Useful if the format cannot be +autodetected because it has no header, like some vhd/vpc files. +@item cluster_size +Changes the cluster size (must be power-of-2 between 4K and 64K). Smaller +cluster sizes can improve the image file size whereas larger cluster sizes +generally provide better performance. +@item table_size +Changes the number of clusters per L1/L2 table (must be power-of-2 between 1 +and 16). There is normally no need to change this value but this option can be +used for performance benchmarking. +@end table @item qcow Old QEMU image format. Left for compatibility. -- cgit v1.2.3 From cd63a77e990f68a699ba220c8006386bd4379f81 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Tue, 22 May 2012 16:26:42 -0700 Subject: ahci: SATA FIS is 20 bytes, not 0x20 As in the SATA and AHCI specifications, a FIS is 5 Dwords of 4 bytes each, which comes to 20 bytes (decimal), not 0x20. Signed-off-by: Daniel Verkamp Signed-off-by: Kevin Wolf (cherry picked from commit 4bb9c939a57103898f5a51aa6a7336eb3320d923) Signed-off-by: Michael Roth --- hw/ide/ahci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index a883a920b..2d7d03d77 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -462,7 +462,7 @@ static void ahci_check_cmd_bh(void *opaque) static void ahci_init_d2h(AHCIDevice *ad) { - uint8_t init_fis[0x20]; + uint8_t init_fis[20]; IDEState *ide_state = &ad->port.ifs[0]; memset(init_fis, 0, sizeof(init_fis)); @@ -619,7 +619,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) d2h_fis[11] = cmd_fis[11]; d2h_fis[12] = cmd_fis[12]; d2h_fis[13] = cmd_fis[13]; - for (i = 14; i < 0x20; i++) { + for (i = 14; i < 20; i++) { d2h_fis[i] = 0; } -- cgit v1.2.3 From b7093f294c330c4db789c077dac9d8611e4f8ee0 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 17 May 2012 13:25:43 +0800 Subject: rtl8139: validate rx ring before receiving packets Commit ff71f2e8cacefae99179993204172bc65e4303df prevent the possible crash during initialization of linux driver by checking the operating mode.This seems too strict as: - the real card could still work in mode other than normal - some buggy driver who does not set correct opmode after eeprom access So, considering rx ring address were reset to zero (which could be safely trated as an address not intened to DMA to), in order to both letting old guest work and preventing the unexpected DMA to guest, we can forbid packet receiving when rx ring address is zero. Tested-by: Avi Kivity Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori (cherry picked from commit fcce6fd25f3e233f9da9ef01230a668ab35bd343) Signed-off-by: Michael Roth --- hw/rtl8139.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index f6f144b52..7b150475f 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -781,6 +781,13 @@ static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high) #endif } +/* Workaround for buggy guest driver such as linux who allocates rx + * rings after the receiver were enabled. */ +static bool rtl8139_cp_rx_valid(RTL8139State *s) +{ + return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0); +} + static int rtl8139_can_receive(VLANClientState *nc) { RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -791,11 +798,8 @@ static int rtl8139_can_receive(VLANClientState *nc) return 1; if (!rtl8139_receiver_enabled(s)) return 1; - /* network/host communication happens only in normal mode */ - if ((s->Cfg9346 & Chip9346_op_mask) != Cfg9346_Normal) - return 0; - if (rtl8139_cp_receiver_enabled(s)) { + if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) { /* ??? Flow control not implemented in c+ mode. This is a hack to work around slirp deficiencies anyway. */ return 1; @@ -836,12 +840,6 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ return -1; } - /* check whether we are in normal mode */ - if ((s->Cfg9346 & Chip9346_op_mask) != Cfg9346_Normal) { - DPRINTF("not in normal op mode\n"); - return -1; - } - /* XXX: check this */ if (s->RxConfig & AcceptAllPhys) { /* promiscuous: receive all */ @@ -946,6 +944,10 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ if (rtl8139_cp_receiver_enabled(s)) { + if (!rtl8139_cp_rx_valid(s)) { + return size; + } + DPRINTF("in C+ Rx mode ================\n"); /* begin C+ receiver mode */ -- cgit v1.2.3 From 4082e889ee8aa43b303105180399bab14312231e Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 18 May 2012 02:36:26 +0200 Subject: s390x: fix s390 virtio aliases Some of the virtio devices have the same frontend name, but actually implement different devices behind the scenes through aliases. The indicator which device type to use is the architecture. On s390, we want s390 virtio devices. On everything else, we want PCI devices. Reflect this in the alias selection code. This way we fix commands like -device virtio-blk on s390x which with this patch applied select the correct virtio-blk-s390 device rather than virtio-blk-pci. Reported-by: Christian Borntraeger Signed-off-by: Anthony Liguori Signed-off-by: Alexander Graf --- hw/qdev-monitor.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index eed781d2f..405697e76 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -20,6 +20,7 @@ #include "qdev.h" #include "monitor.h" #include "qmp-commands.h" +#include "arch_init.h" /* * Aliases were a bad idea from the start. Let's keep them @@ -29,16 +30,18 @@ typedef struct QDevAlias { const char *typename; const char *alias; + uint32_t arch_mask; } QDevAlias; static const QDevAlias qdev_alias_table[] = { - { "virtio-blk-pci", "virtio-blk" }, - { "virtio-net-pci", "virtio-net" }, - { "virtio-serial-pci", "virtio-serial" }, - { "virtio-balloon-pci", "virtio-balloon" }, - { "virtio-blk-s390", "virtio-blk" }, - { "virtio-net-s390", "virtio-net" }, - { "virtio-serial-s390", "virtio-serial" }, + { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-balloon-pci", "virtio-balloon", + QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X }, + { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X }, + { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X }, { "lsi53c895a", "lsi" }, { "ich9-ahci", "ahci" }, { } @@ -50,6 +53,11 @@ static const char *qdev_class_get_alias(DeviceClass *dc) int i; for (i = 0; qdev_alias_table[i].typename; i++) { + if (qdev_alias_table[i].arch_mask && + !(qdev_alias_table[i].arch_mask & arch_type)) { + continue; + } + if (strcmp(qdev_alias_table[i].typename, typename) == 0) { return qdev_alias_table[i].alias; } @@ -110,6 +118,11 @@ static const char *find_typename_by_alias(const char *alias) int i; for (i = 0; qdev_alias_table[i].alias; i++) { + if (qdev_alias_table[i].arch_mask && + !(qdev_alias_table[i].arch_mask & arch_type)) { + continue; + } + if (strcmp(qdev_alias_table[i].alias, alias) == 0) { return qdev_alias_table[i].typename; } -- cgit v1.2.3 From 785adb09b9fd0d4df6707f00247ec519c42fcfc6 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Thu, 12 Jul 2012 13:36:14 -0500 Subject: update VERSION for v1.1.1 Signed-off-by: Michael Roth --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9084fa2f7..524cb5524 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.0 +1.1.1 -- cgit v1.2.3