Compare commits
19 Commits
44b7329de4
...
59084feb25
Author | SHA1 | Date | |
---|---|---|---|
|
59084feb25 | ||
|
4a3eceb403 | ||
|
83d9019202 | ||
|
f15da599a1 | ||
|
956b30b9cf | ||
|
2457343d05 | ||
|
d7c8c95fbc | ||
|
8fe0ebe15d | ||
|
d59ca1ca17 | ||
|
3966bca539 | ||
|
37baedf8e8 | ||
|
d847ea7cfc | ||
|
d8b76d9ab1 | ||
|
61f9376775 | ||
|
f2146bc6cb | ||
|
2095468d2c | ||
|
578c6e9ed5 | ||
|
0b51fd0f99 | ||
|
eec2f9cc69 |
@ -552,9 +552,12 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Net */
|
||||
for (i = 0; i < sc->macs_num; i++) {
|
||||
object_property_set_bool(OBJECT(&s->ftgmac100[i]), "aspeed", true,
|
||||
&error_abort);
|
||||
object_property_set_bool(OBJECT(&s->ftgmac100[i]), "dma64", true,
|
||||
&error_abort);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->ftgmac100[i]), errp)) {
|
||||
return;
|
||||
}
|
||||
|
@ -416,6 +416,7 @@ typedef enum {
|
||||
/*
|
||||
* Micron: 0x35 - enable QPI
|
||||
* Spansion: 0x35 - read control register
|
||||
* Winbond: 0x35 - quad enable
|
||||
*/
|
||||
RDCR_EQIO = 0x35,
|
||||
RSTQIO = 0xf5,
|
||||
@ -798,6 +799,11 @@ static void complete_collecting_data(Flash *s)
|
||||
s->four_bytes_address_mode = extract32(s->data[1], 5, 1);
|
||||
}
|
||||
break;
|
||||
case MAN_WINBOND:
|
||||
if (s->len > 1) {
|
||||
s->quad_enable = !!(s->data[1] & 0x02);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1254,6 +1260,10 @@ static void decode_new_cmd(Flash *s, uint32_t value)
|
||||
s->needed_bytes = 2;
|
||||
s->state = STATE_COLLECTING_VAR_LEN_DATA;
|
||||
break;
|
||||
case MAN_WINBOND:
|
||||
s->needed_bytes = 2;
|
||||
s->state = STATE_COLLECTING_VAR_LEN_DATA;
|
||||
break;
|
||||
default:
|
||||
s->needed_bytes = 1;
|
||||
s->state = STATE_COLLECTING_DATA;
|
||||
@ -1431,6 +1441,12 @@ static void decode_new_cmd(Flash *s, uint32_t value)
|
||||
case MAN_MACRONIX:
|
||||
s->quad_enable = true;
|
||||
break;
|
||||
case MAN_WINBOND:
|
||||
s->data[0] = (!!s->quad_enable) << 1;
|
||||
s->pos = 0;
|
||||
s->len = 1;
|
||||
s->state = STATE_READING_DATA;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -56,6 +56,16 @@
|
||||
#define FTGMAC100_PHYDATA 0x64
|
||||
#define FTGMAC100_FCR 0x68
|
||||
|
||||
/*
|
||||
* FTGMAC100 registers high
|
||||
*
|
||||
* values below are offset by - FTGMAC100_REG_HIGH_OFFSET from datasheet
|
||||
* because its memory region is start at FTGMAC100_REG_HIGH_OFFSET
|
||||
*/
|
||||
#define FTGMAC100_NPTXR_BADR_HIGH (0x17C - FTGMAC100_REG_HIGH_OFFSET)
|
||||
#define FTGMAC100_HPTXR_BADR_HIGH (0x184 - FTGMAC100_REG_HIGH_OFFSET)
|
||||
#define FTGMAC100_RXR_BADR_HIGH (0x18C - FTGMAC100_REG_HIGH_OFFSET)
|
||||
|
||||
/*
|
||||
* Interrupt status register & interrupt enable register
|
||||
*/
|
||||
@ -165,6 +175,8 @@
|
||||
#define FTGMAC100_TXDES1_TX2FIC (1 << 30)
|
||||
#define FTGMAC100_TXDES1_TXIC (1 << 31)
|
||||
|
||||
#define FTGMAC100_TXDES2_TXBUF_BADR_HI(x) (((x) >> 16) & 0x7)
|
||||
|
||||
/*
|
||||
* Receive descriptor
|
||||
*/
|
||||
@ -198,13 +210,15 @@
|
||||
#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR (1 << 26)
|
||||
#define FTGMAC100_RXDES1_IP_CHKSUM_ERR (1 << 27)
|
||||
|
||||
#define FTGMAC100_RXDES2_RXBUF_BADR_HI(x) (((x) >> 16) & 0x7)
|
||||
|
||||
/*
|
||||
* Receive and transmit Buffer Descriptor
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t des0;
|
||||
uint32_t des1;
|
||||
uint32_t des2; /* not used by HW */
|
||||
uint32_t des2; /* used by HW 64 bits DMA */
|
||||
uint32_t des3;
|
||||
} FTGMAC100Desc;
|
||||
|
||||
@ -515,12 +529,13 @@ out:
|
||||
return frame_size;
|
||||
}
|
||||
|
||||
static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
|
||||
uint32_t tx_descriptor)
|
||||
static void ftgmac100_do_tx(FTGMAC100State *s, uint64_t tx_ring,
|
||||
uint64_t tx_descriptor)
|
||||
{
|
||||
int frame_size = 0;
|
||||
uint8_t *ptr = s->frame;
|
||||
uint32_t addr = tx_descriptor;
|
||||
uint64_t addr = tx_descriptor;
|
||||
uint64_t buf_addr = 0;
|
||||
uint32_t flags = 0;
|
||||
|
||||
while (1) {
|
||||
@ -559,7 +574,12 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
|
||||
len = sizeof(s->frame) - frame_size;
|
||||
}
|
||||
|
||||
if (dma_memory_read(&address_space_memory, bd.des3,
|
||||
buf_addr = bd.des3;
|
||||
if (s->dma64) {
|
||||
buf_addr = deposit64(buf_addr, 32, 32,
|
||||
FTGMAC100_TXDES2_TXBUF_BADR_HI(bd.des2));
|
||||
}
|
||||
if (dma_memory_read(&address_space_memory, buf_addr,
|
||||
ptr, len, MEMTXATTRS_UNSPECIFIED)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to read packet @ 0x%x\n",
|
||||
__func__, bd.des3);
|
||||
@ -726,9 +746,9 @@ static uint64_t ftgmac100_read(void *opaque, hwaddr addr, unsigned size)
|
||||
case FTGMAC100_MATH1:
|
||||
return s->math[1];
|
||||
case FTGMAC100_RXR_BADR:
|
||||
return s->rx_ring;
|
||||
return extract64(s->rx_ring, 0, 32);
|
||||
case FTGMAC100_NPTXR_BADR:
|
||||
return s->tx_ring;
|
||||
return extract64(s->tx_ring, 0, 32);
|
||||
case FTGMAC100_ITC:
|
||||
return s->itc;
|
||||
case FTGMAC100_DBLAC:
|
||||
@ -799,9 +819,8 @@ static void ftgmac100_write(void *opaque, hwaddr addr,
|
||||
HWADDR_PRIx "\n", __func__, value);
|
||||
return;
|
||||
}
|
||||
|
||||
s->rx_ring = value;
|
||||
s->rx_descriptor = s->rx_ring;
|
||||
s->rx_ring = deposit64(s->rx_ring, 0, 32, value);
|
||||
s->rx_descriptor = deposit64(s->rx_descriptor, 0, 32, value);
|
||||
break;
|
||||
|
||||
case FTGMAC100_RBSR: /* DMA buffer size */
|
||||
@ -814,8 +833,8 @@ static void ftgmac100_write(void *opaque, hwaddr addr,
|
||||
HWADDR_PRIx "\n", __func__, value);
|
||||
return;
|
||||
}
|
||||
s->tx_ring = value;
|
||||
s->tx_descriptor = s->tx_ring;
|
||||
s->tx_ring = deposit64(s->tx_ring, 0, 32, value);
|
||||
s->tx_descriptor = deposit64(s->tx_descriptor, 0, 32, value);
|
||||
break;
|
||||
|
||||
case FTGMAC100_NPTXPD: /* Trigger transmit */
|
||||
@ -914,6 +933,60 @@ static void ftgmac100_write(void *opaque, hwaddr addr,
|
||||
ftgmac100_update_irq(s);
|
||||
}
|
||||
|
||||
static uint64_t ftgmac100_high_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
FTGMAC100State *s = FTGMAC100(opaque);
|
||||
uint64_t val = 0;
|
||||
|
||||
switch (addr) {
|
||||
case FTGMAC100_NPTXR_BADR_HIGH:
|
||||
val = extract64(s->tx_ring, 32, 32);
|
||||
break;
|
||||
case FTGMAC100_HPTXR_BADR_HIGH:
|
||||
/* High Priority Transmit Ring Base High Address */
|
||||
qemu_log_mask(LOG_UNIMP, "%s: read to unimplemented register 0x%"
|
||||
HWADDR_PRIx "\n", __func__, addr);
|
||||
break;
|
||||
case FTGMAC100_RXR_BADR_HIGH:
|
||||
val = extract64(s->rx_ring, 32, 32);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset 0x%"
|
||||
HWADDR_PRIx "\n", __func__, addr);
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void ftgmac100_high_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
FTGMAC100State *s = FTGMAC100(opaque);
|
||||
|
||||
switch (addr) {
|
||||
case FTGMAC100_NPTXR_BADR_HIGH:
|
||||
s->tx_ring = deposit64(s->tx_ring, 32, 32, value);
|
||||
s->tx_descriptor = deposit64(s->tx_descriptor, 32, 32, value);
|
||||
break;
|
||||
case FTGMAC100_HPTXR_BADR_HIGH:
|
||||
/* High Priority Transmit Ring Base High Address */
|
||||
qemu_log_mask(LOG_UNIMP, "%s: write to unimplemented register 0x%"
|
||||
HWADDR_PRIx "\n", __func__, addr);
|
||||
break;
|
||||
case FTGMAC100_RXR_BADR_HIGH:
|
||||
s->rx_ring = deposit64(s->rx_ring, 32, 32, value);
|
||||
s->rx_descriptor = deposit64(s->rx_descriptor, 32, 32, value);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset 0x%"
|
||||
HWADDR_PRIx "\n", __func__, addr);
|
||||
break;
|
||||
}
|
||||
|
||||
ftgmac100_update_irq(s);
|
||||
}
|
||||
|
||||
static int ftgmac100_filter(FTGMAC100State *s, const uint8_t *buf, size_t len)
|
||||
{
|
||||
unsigned mcast_idx;
|
||||
@ -957,9 +1030,9 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
|
||||
FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
|
||||
FTGMAC100Desc bd;
|
||||
uint32_t flags = 0;
|
||||
uint32_t addr;
|
||||
uint64_t addr;
|
||||
uint32_t crc;
|
||||
uint32_t buf_addr;
|
||||
uint64_t buf_addr = 0;
|
||||
uint8_t *crc_ptr;
|
||||
uint32_t buf_len;
|
||||
size_t size = len;
|
||||
@ -1024,7 +1097,12 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
|
||||
if (size < 4) {
|
||||
buf_len += size - 4;
|
||||
}
|
||||
|
||||
buf_addr = bd.des3;
|
||||
if (s->dma64) {
|
||||
buf_addr = deposit64(buf_addr, 32, 32,
|
||||
FTGMAC100_RXDES2_RXBUF_BADR_HI(bd.des2));
|
||||
}
|
||||
if (first && proto == ETH_P_VLAN && buf_len >= 18) {
|
||||
bd.des1 = lduw_be_p(buf + 14) | FTGMAC100_RXDES1_VLANTAG_AVAIL;
|
||||
|
||||
@ -1078,6 +1156,14 @@ static const MemoryRegionOps ftgmac100_ops = {
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps ftgmac100_high_ops = {
|
||||
.read = ftgmac100_high_read,
|
||||
.write = ftgmac100_high_write,
|
||||
.valid.min_access_size = 4,
|
||||
.valid.max_access_size = 4,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void ftgmac100_cleanup(NetClientState *nc)
|
||||
{
|
||||
FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
|
||||
@ -1107,9 +1193,23 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp)
|
||||
s->rxdes0_edorr = FTGMAC100_RXDES0_EDORR;
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(dev), &ftgmac100_ops, s,
|
||||
TYPE_FTGMAC100, 0x2000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
memory_region_init(&s->iomem_container, OBJECT(s),
|
||||
TYPE_FTGMAC100 ".container", FTGMAC100_MEM_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->iomem_container);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &ftgmac100_ops, s,
|
||||
TYPE_FTGMAC100 ".regs", FTGMAC100_REG_MEM_SIZE);
|
||||
memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
|
||||
|
||||
if (s->dma64) {
|
||||
memory_region_init_io(&s->iomem_high, OBJECT(s), &ftgmac100_high_ops,
|
||||
s, TYPE_FTGMAC100 ".regs.high",
|
||||
FTGMAC100_REG_HIGH_MEM_SIZE);
|
||||
memory_region_add_subregion(&s->iomem_container,
|
||||
FTGMAC100_REG_HIGH_OFFSET,
|
||||
&s->iomem_high);
|
||||
}
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
||||
|
||||
@ -1121,18 +1221,14 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
static const VMStateDescription vmstate_ftgmac100 = {
|
||||
.name = TYPE_FTGMAC100,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_UINT32(irq_state, FTGMAC100State),
|
||||
VMSTATE_UINT32(isr, FTGMAC100State),
|
||||
VMSTATE_UINT32(ier, FTGMAC100State),
|
||||
VMSTATE_UINT32(rx_enabled, FTGMAC100State),
|
||||
VMSTATE_UINT32(rx_ring, FTGMAC100State),
|
||||
VMSTATE_UINT32(rbsr, FTGMAC100State),
|
||||
VMSTATE_UINT32(tx_ring, FTGMAC100State),
|
||||
VMSTATE_UINT32(rx_descriptor, FTGMAC100State),
|
||||
VMSTATE_UINT32(tx_descriptor, FTGMAC100State),
|
||||
VMSTATE_UINT32_ARRAY(math, FTGMAC100State, 2),
|
||||
VMSTATE_UINT32(itc, FTGMAC100State),
|
||||
VMSTATE_UINT32(aptcr, FTGMAC100State),
|
||||
@ -1151,6 +1247,10 @@ static const VMStateDescription vmstate_ftgmac100 = {
|
||||
VMSTATE_UINT32(phy_int_mask, FTGMAC100State),
|
||||
VMSTATE_UINT32(txdes0_edotr, FTGMAC100State),
|
||||
VMSTATE_UINT32(rxdes0_edorr, FTGMAC100State),
|
||||
VMSTATE_UINT64(rx_ring, FTGMAC100State),
|
||||
VMSTATE_UINT64(tx_ring, FTGMAC100State),
|
||||
VMSTATE_UINT64(rx_descriptor, FTGMAC100State),
|
||||
VMSTATE_UINT64(tx_descriptor, FTGMAC100State),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
@ -1158,6 +1258,7 @@ static const VMStateDescription vmstate_ftgmac100 = {
|
||||
static Property ftgmac100_properties[] = {
|
||||
DEFINE_PROP_BOOL("aspeed", FTGMAC100State, aspeed, false),
|
||||
DEFINE_NIC_PROPERTIES(FTGMAC100State, conf),
|
||||
DEFINE_PROP_BOOL("dma64", FTGMAC100State, dma64, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -622,14 +622,6 @@ static void vfio_listener_region_add(MemoryListener *listener,
|
||||
int128_get64(llend),
|
||||
iommu_idx);
|
||||
|
||||
ret = memory_region_iommu_set_page_size_mask(giommu->iommu_mr,
|
||||
bcontainer->pgsizes,
|
||||
&err);
|
||||
if (ret) {
|
||||
g_free(giommu);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = memory_region_register_iommu_notifier(section->mr, &giommu->n,
|
||||
&err);
|
||||
if (ret) {
|
||||
|
@ -83,6 +83,21 @@ int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
|
||||
errp);
|
||||
}
|
||||
|
||||
static gpointer copy_iova_range(gconstpointer src, gpointer data)
|
||||
{
|
||||
Range *source = (Range *)src;
|
||||
Range *dest = g_new(Range, 1);
|
||||
|
||||
range_set_bounds(dest, range_lob(source), range_upb(source));
|
||||
return dest;
|
||||
}
|
||||
|
||||
GList *vfio_container_get_iova_ranges(const VFIOContainerBase *bcontainer)
|
||||
{
|
||||
assert(bcontainer);
|
||||
return g_list_copy_deep(bcontainer->iova_ranges, copy_iova_range, NULL);
|
||||
}
|
||||
|
||||
static void vfio_container_instance_finalize(Object *obj)
|
||||
{
|
||||
VFIOContainerBase *bcontainer = VFIO_IOMMU(obj);
|
||||
|
@ -1165,18 +1165,21 @@ static int hiod_legacy_vfio_get_cap(HostIOMMUDevice *hiod, int cap,
|
||||
}
|
||||
|
||||
static GList *
|
||||
hiod_legacy_vfio_get_iova_ranges(HostIOMMUDevice *hiod, Error **errp)
|
||||
hiod_legacy_vfio_get_iova_ranges(HostIOMMUDevice *hiod)
|
||||
{
|
||||
VFIODevice *vdev = hiod->agent;
|
||||
GList *l = NULL;
|
||||
|
||||
g_assert(vdev);
|
||||
return vfio_container_get_iova_ranges(vdev->bcontainer);
|
||||
}
|
||||
|
||||
if (vdev->bcontainer) {
|
||||
l = g_list_copy(vdev->bcontainer->iova_ranges);
|
||||
}
|
||||
static uint64_t
|
||||
hiod_legacy_vfio_get_page_size_mask(HostIOMMUDevice *hiod)
|
||||
{
|
||||
VFIODevice *vdev = hiod->agent;
|
||||
|
||||
return l;
|
||||
g_assert(vdev);
|
||||
return vfio_container_get_page_size_mask(vdev->bcontainer);
|
||||
}
|
||||
|
||||
static void vfio_iommu_legacy_instance_init(Object *obj)
|
||||
@ -1193,6 +1196,7 @@ static void hiod_legacy_vfio_class_init(ObjectClass *oc, void *data)
|
||||
hioc->realize = hiod_legacy_vfio_realize;
|
||||
hioc->get_cap = hiod_legacy_vfio_get_cap;
|
||||
hioc->get_iova_ranges = hiod_legacy_vfio_get_iova_ranges;
|
||||
hioc->get_page_size_mask = hiod_legacy_vfio_get_page_size_mask;
|
||||
};
|
||||
|
||||
static const TypeInfo types[] = {
|
||||
|
@ -124,7 +124,7 @@ static void vfio_display_edid_ui_info(void *opaque, uint32_t idx,
|
||||
}
|
||||
}
|
||||
|
||||
static void vfio_display_edid_init(VFIOPCIDevice *vdev)
|
||||
static bool vfio_display_edid_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
{
|
||||
VFIODisplay *dpy = vdev->dpy;
|
||||
int fd = vdev->vbasedev.fd;
|
||||
@ -135,7 +135,8 @@ static void vfio_display_edid_init(VFIOPCIDevice *vdev)
|
||||
VFIO_REGION_SUBTYPE_GFX_EDID,
|
||||
&dpy->edid_info);
|
||||
if (ret) {
|
||||
return;
|
||||
/* Failed to get GFX edid info, allow to go through without edid. */
|
||||
return true;
|
||||
}
|
||||
|
||||
trace_vfio_display_edid_available();
|
||||
@ -167,13 +168,16 @@ static void vfio_display_edid_init(VFIOPCIDevice *vdev)
|
||||
vfio_display_edid_link_up, vdev);
|
||||
|
||||
vfio_display_edid_update(vdev, true, 0, 0);
|
||||
return;
|
||||
return true;
|
||||
|
||||
err:
|
||||
error_setg(errp, "vfio: failed to read GFX edid field");
|
||||
trace_vfio_display_edid_write_error();
|
||||
g_free(dpy->edid_info);
|
||||
g_free(dpy->edid_regs);
|
||||
dpy->edid_info = NULL;
|
||||
dpy->edid_regs = NULL;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void vfio_display_edid_exit(VFIODisplay *dpy)
|
||||
@ -182,6 +186,7 @@ static void vfio_display_edid_exit(VFIODisplay *dpy)
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(dpy->edid_info);
|
||||
g_free(dpy->edid_regs);
|
||||
g_free(dpy->edid_blob);
|
||||
timer_free(dpy->edid_link_timer);
|
||||
@ -365,8 +370,7 @@ static bool vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
vfio_display_edid_init(vdev);
|
||||
return true;
|
||||
return vfio_display_edid_init(vdev, errp);
|
||||
}
|
||||
|
||||
static void vfio_display_dmabuf_exit(VFIODisplay *dpy)
|
||||
|
@ -644,26 +644,31 @@ static bool hiod_iommufd_vfio_realize(HostIOMMUDevice *hiod, void *opaque,
|
||||
}
|
||||
|
||||
static GList *
|
||||
hiod_iommufd_vfio_get_iova_ranges(HostIOMMUDevice *hiod, Error **errp)
|
||||
hiod_iommufd_vfio_get_iova_ranges(HostIOMMUDevice *hiod)
|
||||
{
|
||||
VFIODevice *vdev = hiod->agent;
|
||||
GList *l = NULL;
|
||||
|
||||
g_assert(vdev);
|
||||
|
||||
if (vdev->bcontainer) {
|
||||
l = g_list_copy(vdev->bcontainer->iova_ranges);
|
||||
}
|
||||
|
||||
return l;
|
||||
return vfio_container_get_iova_ranges(vdev->bcontainer);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
hiod_iommufd_vfio_get_page_size_mask(HostIOMMUDevice *hiod)
|
||||
{
|
||||
VFIODevice *vdev = hiod->agent;
|
||||
|
||||
g_assert(vdev);
|
||||
return vfio_container_get_page_size_mask(vdev->bcontainer);
|
||||
}
|
||||
|
||||
|
||||
static void hiod_iommufd_vfio_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
HostIOMMUDeviceClass *hiodc = HOST_IOMMU_DEVICE_CLASS(oc);
|
||||
|
||||
hiodc->realize = hiod_iommufd_vfio_realize;
|
||||
hiodc->get_iova_ranges = hiod_iommufd_vfio_get_iova_ranges;
|
||||
hiodc->get_page_size_mask = hiod_iommufd_vfio_get_page_size_mask;
|
||||
};
|
||||
|
||||
static const TypeInfo types[] = {
|
||||
|
@ -131,7 +131,7 @@ virtio_iommu_fill_resv_property(uint32_t devid, uint8_t subtype, uint64_t start,
|
||||
virtio_iommu_notify_map(const char *name, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start, uint32_t flags) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64" phys_start=0x%"PRIx64" flags=%d"
|
||||
virtio_iommu_notify_unmap(const char *name, uint64_t virt_start, uint64_t virt_end) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64
|
||||
virtio_iommu_remap(const char *name, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64" phys_start=0x%"PRIx64
|
||||
virtio_iommu_set_page_size_mask(const char *name, uint64_t old, uint64_t new) "mr=%s old_mask=0x%"PRIx64" new_mask=0x%"PRIx64
|
||||
virtio_iommu_update_page_size_mask(const char *name, uint64_t old, uint64_t new) "host iommu device=%s old_mask=0x%"PRIx64" new_mask=0x%"PRIx64
|
||||
virtio_iommu_notify_flag_add(const char *name) "add notifier to mr %s"
|
||||
virtio_iommu_notify_flag_del(const char *name) "del notifier from mr %s"
|
||||
virtio_iommu_switch_address_space(uint8_t bus, uint8_t slot, uint8_t fn, bool on) "Device %02x:%02x.%x switching address space (iommu enabled=%d)"
|
||||
|
@ -563,10 +563,15 @@ static int virtio_iommu_set_host_iova_ranges(VirtIOIOMMU *s, PCIBus *bus,
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!sbus) {
|
||||
error_report("%s no sbus", __func__);
|
||||
error_setg(errp, "%s: no IOMMUPciBus found!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sdev = sbus->pbdev[devfn];
|
||||
if (!sdev) {
|
||||
error_setg(errp, "%s: no IOMMUDevice found!", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
current_ranges = sdev->host_resv_ranges;
|
||||
|
||||
@ -613,9 +618,39 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool check_page_size_mask(VirtIOIOMMU *viommu, uint64_t new_mask,
|
||||
Error **errp)
|
||||
{
|
||||
uint64_t cur_mask = viommu->config.page_size_mask;
|
||||
|
||||
if ((cur_mask & new_mask) == 0) {
|
||||
error_setg(errp, "virtio-iommu reports a page size mask 0x%"PRIx64
|
||||
" incompatible with currently supported mask 0x%"PRIx64,
|
||||
new_mask, cur_mask);
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Once the granule is frozen we can't change the mask anymore. If by
|
||||
* chance the hotplugged device supports the same granule, we can still
|
||||
* accept it.
|
||||
*/
|
||||
if (viommu->granule_frozen) {
|
||||
int cur_granule = ctz64(cur_mask);
|
||||
|
||||
if (!(BIT_ULL(cur_granule) & new_mask)) {
|
||||
error_setg(errp,
|
||||
"virtio-iommu does not support frozen granule 0x%llx",
|
||||
BIT_ULL(cur_granule));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool virtio_iommu_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
|
||||
HostIOMMUDevice *hiod, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
VirtIOIOMMU *viommu = opaque;
|
||||
HostIOMMUDeviceClass *hiodc = HOST_IOMMU_DEVICE_GET_CLASS(hiod);
|
||||
struct hiod_key *new_key;
|
||||
@ -630,7 +665,7 @@ static bool virtio_iommu_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
|
||||
|
||||
if (hiodc->get_iova_ranges) {
|
||||
int ret;
|
||||
host_iova_ranges = hiodc->get_iova_ranges(hiod, errp);
|
||||
host_iova_ranges = hiodc->get_iova_ranges(hiod);
|
||||
if (!host_iova_ranges) {
|
||||
return true; /* some old kernels may not support that capability */
|
||||
}
|
||||
@ -638,8 +673,28 @@ static bool virtio_iommu_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
|
||||
hiod->aliased_devfn,
|
||||
host_iova_ranges, errp);
|
||||
if (ret) {
|
||||
g_list_free_full(host_iova_ranges, g_free);
|
||||
return false;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (hiodc->get_page_size_mask) {
|
||||
uint64_t new_mask = hiodc->get_page_size_mask(hiod);
|
||||
|
||||
if (check_page_size_mask(viommu, new_mask, errp)) {
|
||||
/*
|
||||
* The default mask depends on the "granule" property. For example,
|
||||
* with 4k granule, it is -(4 * KiB). When an assigned device has
|
||||
* page size restrictions due to the hardware IOMMU configuration,
|
||||
* apply this restriction to the mask.
|
||||
*/
|
||||
trace_virtio_iommu_update_page_size_mask(hiod->name,
|
||||
viommu->config.page_size_mask,
|
||||
new_mask);
|
||||
if (!viommu->granule_frozen) {
|
||||
viommu->config.page_size_mask &= new_mask;
|
||||
}
|
||||
} else {
|
||||
error_prepend(errp, "%s: ", hiod->name);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -652,6 +707,9 @@ static bool virtio_iommu_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
|
||||
g_list_free_full(host_iova_ranges, g_free);
|
||||
|
||||
return true;
|
||||
error:
|
||||
g_list_free_full(host_iova_ranges, g_free);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1350,50 +1408,6 @@ static int virtio_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu_mr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The default mask depends on the "granule" property. For example, with
|
||||
* 4k granule, it is -(4 * KiB). When an assigned device has page size
|
||||
* restrictions due to the hardware IOMMU configuration, apply this restriction
|
||||
* to the mask.
|
||||
*/
|
||||
static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr,
|
||||
uint64_t new_mask,
|
||||
Error **errp)
|
||||
{
|
||||
IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr);
|
||||
VirtIOIOMMU *s = sdev->viommu;
|
||||
uint64_t cur_mask = s->config.page_size_mask;
|
||||
|
||||
trace_virtio_iommu_set_page_size_mask(mr->parent_obj.name, cur_mask,
|
||||
new_mask);
|
||||
|
||||
if ((cur_mask & new_mask) == 0) {
|
||||
error_setg(errp, "virtio-iommu %s reports a page size mask 0x%"PRIx64
|
||||
" incompatible with currently supported mask 0x%"PRIx64,
|
||||
mr->parent_obj.name, new_mask, cur_mask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Once the granule is frozen we can't change the mask anymore. If by
|
||||
* chance the hotplugged device supports the same granule, we can still
|
||||
* accept it.
|
||||
*/
|
||||
if (s->granule_frozen) {
|
||||
int cur_granule = ctz64(cur_mask);
|
||||
|
||||
if (!(BIT_ULL(cur_granule) & new_mask)) {
|
||||
error_setg(errp, "virtio-iommu %s does not support frozen granule 0x%llx",
|
||||
mr->parent_obj.name, BIT_ULL(cur_granule));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->config.page_size_mask &= new_mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtio_iommu_system_reset(void *opaque)
|
||||
{
|
||||
VirtIOIOMMU *s = opaque;
|
||||
@ -1416,18 +1430,6 @@ static void virtio_iommu_freeze_granule(Notifier *notifier, void *data)
|
||||
VirtIOIOMMU *s = container_of(notifier, VirtIOIOMMU, machine_done);
|
||||
int granule;
|
||||
|
||||
if (likely(s->config.bypass)) {
|
||||
/*
|
||||
* Transient IOMMU MR enable to collect page_size_mask requirements
|
||||
* through memory_region_iommu_set_page_size_mask() called by
|
||||
* VFIO region_add() callback
|
||||
*/
|
||||
s->config.bypass = false;
|
||||
virtio_iommu_switch_address_space_all(s);
|
||||
/* restore default */
|
||||
s->config.bypass = true;
|
||||
virtio_iommu_switch_address_space_all(s);
|
||||
}
|
||||
s->granule_frozen = true;
|
||||
granule = ctz64(s->config.page_size_mask);
|
||||
trace_virtio_iommu_freeze_granule(BIT_ULL(granule));
|
||||
@ -1718,7 +1720,6 @@ static void virtio_iommu_memory_region_class_init(ObjectClass *klass,
|
||||
imrc->translate = virtio_iommu_translate;
|
||||
imrc->replay = virtio_iommu_replay;
|
||||
imrc->notify_flag_changed = virtio_iommu_notify_flag_changed;
|
||||
imrc->iommu_set_page_size_mask = virtio_iommu_set_page_size_mask;
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_iommu_info = {
|
||||
|
@ -504,32 +504,6 @@ struct IOMMUMemoryRegionClass {
|
||||
* @iommu: the IOMMUMemoryRegion
|
||||
*/
|
||||
int (*num_indexes)(IOMMUMemoryRegion *iommu);
|
||||
|
||||
/**
|
||||
* @iommu_set_page_size_mask:
|
||||
*
|
||||
* Restrict the page size mask that can be supported with a given IOMMU
|
||||
* memory region. Used for example to propagate host physical IOMMU page
|
||||
* size mask limitations to the virtual IOMMU.
|
||||
*
|
||||
* Optional method: if this method is not provided, then the default global
|
||||
* page mask is used.
|
||||
*
|
||||
* @iommu: the IOMMUMemoryRegion
|
||||
*
|
||||
* @page_size_mask: a bitmask of supported page sizes. At least one bit,
|
||||
* representing the smallest page size, must be set. Additional set bits
|
||||
* represent supported block sizes. For example a host physical IOMMU that
|
||||
* uses page tables with a page size of 4kB, and supports 2MB and 4GB
|
||||
* blocks, will set mask 0x40201000. A granule of 4kB with indiscriminate
|
||||
* block sizes is specified with mask 0xfffffffffffff000.
|
||||
*
|
||||
* Returns 0 on success, or a negative error. In case of failure, the error
|
||||
* object must be created.
|
||||
*/
|
||||
int (*iommu_set_page_size_mask)(IOMMUMemoryRegion *iommu,
|
||||
uint64_t page_size_mask,
|
||||
Error **errp);
|
||||
};
|
||||
|
||||
typedef struct RamDiscardListener RamDiscardListener;
|
||||
@ -1919,18 +1893,6 @@ int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr,
|
||||
*/
|
||||
int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr);
|
||||
|
||||
/**
|
||||
* memory_region_iommu_set_page_size_mask: set the supported page
|
||||
* sizes for a given IOMMU memory region
|
||||
*
|
||||
* @iommu_mr: IOMMU memory region
|
||||
* @page_size_mask: supported page size mask
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
*/
|
||||
int memory_region_iommu_set_page_size_mask(IOMMUMemoryRegion *iommu_mr,
|
||||
uint64_t page_size_mask,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* memory_region_name: get a memory region's name
|
||||
*
|
||||
|
@ -14,6 +14,11 @@
|
||||
#define TYPE_FTGMAC100 "ftgmac100"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(FTGMAC100State, FTGMAC100)
|
||||
|
||||
#define FTGMAC100_MEM_SIZE 0x1000
|
||||
#define FTGMAC100_REG_MEM_SIZE 0x100
|
||||
#define FTGMAC100_REG_HIGH_MEM_SIZE 0x100
|
||||
#define FTGMAC100_REG_HIGH_OFFSET 0x100
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "net/net.h"
|
||||
|
||||
@ -30,7 +35,9 @@ struct FTGMAC100State {
|
||||
NICState *nic;
|
||||
NICConf conf;
|
||||
qemu_irq irq;
|
||||
MemoryRegion iomem_container;
|
||||
MemoryRegion iomem;
|
||||
MemoryRegion iomem_high;
|
||||
|
||||
uint8_t frame[FTGMAC100_MAX_FRAME_SIZE];
|
||||
|
||||
@ -38,10 +45,6 @@ struct FTGMAC100State {
|
||||
uint32_t isr;
|
||||
uint32_t ier;
|
||||
uint32_t rx_enabled;
|
||||
uint32_t rx_ring;
|
||||
uint32_t rx_descriptor;
|
||||
uint32_t tx_ring;
|
||||
uint32_t tx_descriptor;
|
||||
uint32_t math[2];
|
||||
uint32_t rbsr;
|
||||
uint32_t itc;
|
||||
@ -54,7 +57,10 @@ struct FTGMAC100State {
|
||||
uint32_t phycr;
|
||||
uint32_t phydata;
|
||||
uint32_t fcr;
|
||||
|
||||
uint64_t rx_ring;
|
||||
uint64_t rx_descriptor;
|
||||
uint64_t tx_ring;
|
||||
uint64_t tx_descriptor;
|
||||
|
||||
uint32_t phy_status;
|
||||
uint32_t phy_control;
|
||||
@ -65,6 +71,7 @@ struct FTGMAC100State {
|
||||
bool aspeed;
|
||||
uint32_t txdes0_edotr;
|
||||
uint32_t rxdes0_edorr;
|
||||
bool dma64;
|
||||
};
|
||||
|
||||
#define TYPE_ASPEED_MII "aspeed-mmi"
|
||||
|
@ -86,6 +86,15 @@ int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer,
|
||||
int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
|
||||
VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp);
|
||||
|
||||
GList *vfio_container_get_iova_ranges(const VFIOContainerBase *bcontainer);
|
||||
|
||||
static inline uint64_t
|
||||
vfio_container_get_page_size_mask(const VFIOContainerBase *bcontainer)
|
||||
{
|
||||
assert(bcontainer);
|
||||
return bcontainer->pgsizes;
|
||||
}
|
||||
|
||||
#define TYPE_VFIO_IOMMU "vfio-iommu"
|
||||
#define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy"
|
||||
#define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr"
|
||||
|
@ -87,9 +87,16 @@ struct HostIOMMUDeviceClass {
|
||||
* @hiod Host IOMMU device
|
||||
*
|
||||
* @hiod: handle to the host IOMMU device
|
||||
* @errp: error handle
|
||||
*/
|
||||
GList* (*get_iova_ranges)(HostIOMMUDevice *hiod, Error **errp);
|
||||
GList* (*get_iova_ranges)(HostIOMMUDevice *hiod);
|
||||
/**
|
||||
*
|
||||
* @get_page_size_mask: Return the page size mask supported along this
|
||||
* @hiod Host IOMMU device
|
||||
*
|
||||
* @hiod: handle to the host IOMMU device
|
||||
*/
|
||||
uint64_t (*get_page_size_mask)(HostIOMMUDevice *hiod);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1901,19 +1901,6 @@ static int memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int memory_region_iommu_set_page_size_mask(IOMMUMemoryRegion *iommu_mr,
|
||||
uint64_t page_size_mask,
|
||||
Error **errp)
|
||||
{
|
||||
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
|
||||
int ret = 0;
|
||||
|
||||
if (imrc->iommu_set_page_size_mask) {
|
||||
ret = imrc->iommu_set_page_size_mask(iommu_mr, page_size_mask, errp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int memory_region_register_iommu_notifier(MemoryRegion *mr,
|
||||
IOMMUNotifier *n, Error **errp)
|
||||
{
|
||||
|
@ -313,14 +313,14 @@ class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn):
|
||||
|
||||
def do_test_aarch64_aspeed_sdk_start(self, image):
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw')
|
||||
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
|
||||
'-net', 'nic', '-net', 'user,hostfwd=:127.0.0.1:0-:22')
|
||||
|
||||
self.vm.launch()
|
||||
|
||||
self.wait_for_console_pattern('U-Boot 2023.10')
|
||||
self.wait_for_console_pattern('## Loading kernel from FIT Image')
|
||||
self.wait_for_console_pattern('Starting kernel ...')
|
||||
self.wait_for_console_pattern("systemd[1]: Hostname set to")
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
||||
|
||||
@ -387,15 +387,15 @@ class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn):
|
||||
year = time.strftime("%Y")
|
||||
self.ssh_command_output_contains('/sbin/hwclock -f /dev/rtc1', year);
|
||||
|
||||
def test_aarch64_ast2700_evb_sdk_v09_01(self):
|
||||
def test_aarch64_ast2700_evb_sdk_v09_02(self):
|
||||
"""
|
||||
:avocado: tags=arch:aarch64
|
||||
:avocado: tags=machine:ast2700-evb
|
||||
"""
|
||||
|
||||
image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
|
||||
'download/v09.01/ast2700-default-obmc.tar.gz')
|
||||
image_hash = 'b1cc0fd73c7650d34c9c8459a243f52a91e9e27144b8608b2645ab19461d1e07'
|
||||
'download/v09.02/ast2700-default-obmc.tar.gz')
|
||||
image_hash = 'ac969c2602f4e6bdb69562ff466b89ae3fe1d86e1f6797bb7969d787f82116a7'
|
||||
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
|
||||
algorithm='sha256')
|
||||
archive.extract(image_path, self.workdir)
|
||||
@ -436,4 +436,6 @@ class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn):
|
||||
|
||||
self.vm.add_args('-smp', str(num_cpu))
|
||||
self.do_test_aarch64_aspeed_sdk_start(image_dir + 'image-bmc')
|
||||
self.wait_for_console_pattern('nodistro.0 ast2700-default ttyS12')
|
||||
self.ssh_connect('root', '0penBmc', False)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user