diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/audio/es1370.c | 9 | ||||
| -rw-r--r-- | hw/hppa/machine.c | 5 | ||||
| -rw-r--r-- | hw/pci-host/astro.c | 73 | ||||
| -rw-r--r-- | hw/pci-host/meson.build | 2 | ||||
| -rw-r--r-- | hw/s390x/s390-pci-vfio.c | 6 | ||||
| -rw-r--r-- | hw/virtio/virtio-mem.c | 22 |
6 files changed, 60 insertions, 57 deletions
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 91c47330ad..fad5541211 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -670,8 +670,13 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, cnt += (transferred + d->leftover) >> 2; if (s->sctl & loop_sel) { - /* Bah, how stupid is that having a 0 represent true value? - i just spent few hours on this shit */ + /* + * loop_sel tells us which bit in the SCTL register to look at + * (either P1_LOOP_SEL, P2_LOOP_SEL or R1_LOOP_SEL). The sense + * of these bits is 0 for loop mode (set interrupt and keep recording + * when the sample count reaches zero) or 1 for stop mode (set + * interrupt and stop recording). + */ AUD_log ("es1370: warning", "non looping mode\n"); } else { d->frame_cnt = size; diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index a3222d3a96..9d08f39490 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -34,9 +34,10 @@ #include "net/net.h" #include "qemu/log.h" -#define MIN_SEABIOS_HPPA_VERSION 10 /* require at least this fw version */ +#define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */ -#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10) +/* Power button address at &PAGE0->pad[4] */ +#define HPA_POWER_BUTTON (0x40 + 4 * sizeof(uint32_t)) #define enable_lasi_lan() 0 diff --git a/hw/pci-host/astro.c b/hw/pci-host/astro.c index bd226581af..7d68ccee7e 100644 --- a/hw/pci-host/astro.c +++ b/hw/pci-host/astro.c @@ -32,6 +32,7 @@ #include "hw/pci-host/astro.h" #include "hw/hppa/hppa_hardware.h" #include "migration/vmstate.h" +#include "target/hppa/cpu.h" #include "trace.h" #include "qom/object.h" @@ -268,22 +269,6 @@ static const MemoryRegionOps elroy_config_addr_ops = { }; -/* - * A subroutine of astro_translate_iommu that builds an IOMMUTLBEntry using the - * given translated address and mask. - */ -static bool make_iommu_tlbe(hwaddr addr, hwaddr taddr, hwaddr mask, - IOMMUTLBEntry *ret) -{ - hwaddr tce_mask = ~((1ull << 12) - 1); - ret->target_as = &address_space_memory; - ret->iova = addr & tce_mask; - ret->translated_addr = taddr & tce_mask; - ret->addr_mask = ~tce_mask; - ret->perm = IOMMU_RW; - return true; -} - /* Handle PCI-to-system address translation. */ static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, @@ -291,53 +276,59 @@ static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu, int iommu_idx) { AstroState *s = container_of(iommu, AstroState, iommu); - IOMMUTLBEntry ret = { - .target_as = &address_space_memory, - .iova = addr, - .translated_addr = 0, - .addr_mask = ~(hwaddr)0, - .perm = IOMMU_NONE, - }; - hwaddr pdir_ptr, index, a, ibase; + hwaddr pdir_ptr, index, ibase; hwaddr addr_mask = 0xfff; /* 4k translation */ uint64_t entry; #define IOVP_SHIFT 12 /* equals PAGE_SHIFT */ #define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT) -#define IOVP_MASK PAGE_MASK #define SBA_PDIR_VALID_BIT 0x8000000000000000ULL + addr &= ~addr_mask; + + /* + * Default translation: "32-bit PCI Addressing on 40-bit Runway". + * For addresses in the 32-bit memory address range ... and then + * language which not-coincidentally matches the PSW.W=0 mapping. + */ + if (addr <= UINT32_MAX) { + entry = hppa_abs_to_phys_pa2_w0(addr); + } else { + entry = addr; + } + /* "range enable" flag cleared? */ if ((s->tlb_ibase & 1) == 0) { - make_iommu_tlbe(addr, addr, addr_mask, &ret); - return ret; + goto skip; } - a = addr; ibase = s->tlb_ibase & ~1ULL; - if ((a & s->tlb_imask) != ibase) { + if ((addr & s->tlb_imask) != ibase) { /* do not translate this one! */ - make_iommu_tlbe(addr, addr, addr_mask, &ret); - return ret; + goto skip; } - index = PDIR_INDEX(a); + + index = PDIR_INDEX(addr); pdir_ptr = s->tlb_pdir_base + index * sizeof(entry); entry = ldq_le_phys(&address_space_memory, pdir_ptr); + if (!(entry & SBA_PDIR_VALID_BIT)) { /* I/O PDIR entry valid ? */ - g_assert_not_reached(); - goto failure; + /* failure */ + return (IOMMUTLBEntry) { .perm = IOMMU_NONE }; } + entry &= ~SBA_PDIR_VALID_BIT; entry >>= IOVP_SHIFT; entry <<= 12; - entry |= addr & 0xfff; - make_iommu_tlbe(addr, entry, addr_mask, &ret); - goto success; - failure: - ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE }; - success: - return ret; + skip: + return (IOMMUTLBEntry) { + .target_as = &address_space_memory, + .iova = addr, + .translated_addr = entry, + .addr_mask = addr_mask, + .perm = IOMMU_RW, + }; } static AddressSpace *elroy_pcihost_set_iommu(PCIBus *bus, void *opaque, diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index de7bfb5a62..36d5ab756f 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -29,7 +29,7 @@ pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c')) pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c')) # HPPA devices -pci_ss.add(when: 'CONFIG_ASTRO', if_true: files('astro.c')) +specific_ss.add(when: 'CONFIG_ASTRO', if_true: files('astro.c')) pci_ss.add(when: 'CONFIG_DINO', if_true: files('dino.c')) system_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss) diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index 59a2e03873..7dbbc76823 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -66,6 +66,10 @@ S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, assert(vpdev); + if (!vpdev->vbasedev.group) { + return NULL; + } + id = vpdev->vbasedev.group->container->fd; if (!s390_pci_update_dma_avail(id, &avail)) { @@ -132,7 +136,7 @@ static void s390_pci_read_base(S390PCIBusDevice *pbdev, * to the guest based upon the vfio DMA limit. */ vfio_size = pbdev->iommu->max_dma_limit << TARGET_PAGE_BITS; - if (vfio_size < (cap->end_dma - cap->start_dma + 1)) { + if (vfio_size > 0 && vfio_size < cap->end_dma - cap->start_dma + 1) { pbdev->zpci_fn.edma = cap->start_dma + vfio_size - 1; } } diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index a5ea3be414..75ee38aa46 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -525,9 +525,7 @@ static void virtio_mem_activate_memslots_to_plug(VirtIOMEM *vmem, vmem->memslot_size; unsigned int idx; - if (!vmem->dynamic_memslots) { - return; - } + assert(vmem->dynamic_memslots); /* Activate all involved memslots in a single transaction. */ memory_region_transaction_begin(); @@ -547,9 +545,7 @@ static void virtio_mem_deactivate_unplugged_memslots(VirtIOMEM *vmem, vmem->memslot_size; unsigned int idx; - if (!vmem->dynamic_memslots) { - return; - } + assert(vmem->dynamic_memslots); /* Deactivate all memslots with unplugged blocks in a single transaction. */ memory_region_transaction_begin(); @@ -598,7 +594,9 @@ static int virtio_mem_set_block_state(VirtIOMEM *vmem, uint64_t start_gpa, virtio_mem_notify_unplug(vmem, offset, size); virtio_mem_set_range_unplugged(vmem, start_gpa, size); /* Deactivate completely unplugged memslots after updating the state. */ - virtio_mem_deactivate_unplugged_memslots(vmem, offset, size); + if (vmem->dynamic_memslots) { + virtio_mem_deactivate_unplugged_memslots(vmem, offset, size); + } return 0; } @@ -635,9 +633,11 @@ static int virtio_mem_set_block_state(VirtIOMEM *vmem, uint64_t start_gpa, * blocks we are plugging here. The following notification will inform * registered listeners about the blocks we're plugging. */ - virtio_mem_activate_memslots_to_plug(vmem, offset, size); + if (vmem->dynamic_memslots) { + virtio_mem_activate_memslots_to_plug(vmem, offset, size); + } ret = virtio_mem_notify_plug(vmem, offset, size); - if (ret) { + if (ret && vmem->dynamic_memslots) { virtio_mem_deactivate_unplugged_memslots(vmem, offset, size); } } @@ -749,7 +749,9 @@ static int virtio_mem_unplug_all(VirtIOMEM *vmem) notifier_list_notify(&vmem->size_change_notifiers, &vmem->size); /* Deactivate all memslots after updating the state. */ - virtio_mem_deactivate_unplugged_memslots(vmem, 0, region_size); + if (vmem->dynamic_memslots) { + virtio_mem_deactivate_unplugged_memslots(vmem, 0, region_size); + } } trace_virtio_mem_unplugged_all(); |