aboutsummaryrefslogtreecommitdiff
path: root/libbacktrace
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-05-12 09:23:56 -0700
committerH.J. Lu <hjl.tools@gmail.com>2020-05-12 09:24:09 -0700
commitd21486483579c2205fcabf1308b155000af86fe1 (patch)
treea5b4e18599210993422ffb62f003b72f98f97554 /libbacktrace
parentb3d16040feb2df017eb5a18ca641b06cc1ff6947 (diff)
downloadgcc-d21486483579c2205fcabf1308b155000af86fe1.zip
gcc-d21486483579c2205fcabf1308b155000af86fe1.tar.gz
gcc-d21486483579c2205fcabf1308b155000af86fe1.tar.bz2
libbacktrace: Enable Intel CET on Intel CET enabled host for jit
Since on Intel CET enabled host, dlopen in Intel CET enabled applications fails on shared libraries which aren't Intel CET enabled, compile with -fcf-protection on Intel CET enabled host when jit is enabled to enable Intel CET on libgccjit. * Makefile.am (AM_CFLAGS): Add $(CET_HOST_FLAGS). * configure.ac: Add GCC_CET_HOST_FLAGS(CET_HOST_FLAGS) and AC_SUBST(CET_HOST_FLAGS). Clear CET_HOST_FLAGS if jit isn't enabled. * Makefile.in: Regenerated. * configure: Likewise.
Diffstat (limited to 'libbacktrace')
-rw-r--r--libbacktrace/ChangeLog8
-rw-r--r--libbacktrace/Makefile.am2
-rw-r--r--libbacktrace/Makefile.in3
-rwxr-xr-xlibbacktrace/configure181
-rw-r--r--libbacktrace/configure.ac11
5 files changed, 201 insertions, 4 deletions
diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 3767852..9668906 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,11 @@
+
+ * Makefile.am (AM_CFLAGS): Add $(CET_HOST_FLAGS).
+ * configure.ac: Add GCC_CET_HOST_FLAGS(CET_HOST_FLAGS) and
+ AC_SUBST(CET_HOST_FLAGS). Clear CET_HOST_FLAGS if jit isn't
+ enabled.
+ * Makefile.in: Regenerated.
+ * configure: Likewise.
+
2020-05-11 Ian Lance Taylor <iant@golang.org>
PR libbacktrace/95012
diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index d3a9ba8..6fc0749 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -34,7 +34,7 @@ ACLOCAL_AMFLAGS = -I .. -I ../config
AM_CPPFLAGS = -I $(top_srcdir)/../include -I $(top_srcdir)/../libgcc \
-I ../libgcc
-AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
+AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG) $(CET_HOST_FLAGS)
noinst_LTLIBRARIES = libbacktrace.la
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index 3fbbb05..b244ca1 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -783,6 +783,7 @@ BACKTRACE_SUPPORTS_DATA = @BACKTRACE_SUPPORTS_DATA@
BACKTRACE_SUPPORTS_THREADS = @BACKTRACE_SUPPORTS_THREADS@
BACKTRACE_USES_MALLOC = @BACKTRACE_USES_MALLOC@
CC = @CC@
+CET_HOST_FLAGS = @CET_HOST_FLAGS@
CFLAGS = @CFLAGS@
CLOCK_GETTIME_LINK = @CLOCK_GETTIME_LINK@
CPP = @CPP@
@@ -902,7 +903,7 @@ ACLOCAL_AMFLAGS = -I .. -I ../config
AM_CPPFLAGS = -I $(top_srcdir)/../include -I $(top_srcdir)/../libgcc \
-I ../libgcc
-AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
+AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG) $(CET_HOST_FLAGS)
noinst_LTLIBRARIES = libbacktrace.la
libbacktrace_la_SOURCES = \
backtrace.h \
diff --git a/libbacktrace/configure b/libbacktrace/configure
index f6e35c2..b72380e 100755
--- a/libbacktrace/configure
+++ b/libbacktrace/configure
@@ -660,6 +660,7 @@ HAVE_ELF_FALSE
HAVE_ELF_TRUE
FORMAT_FILE
BACKTRACE_SUPPORTS_THREADS
+CET_HOST_FLAGS
PIC_FLAG
WARN_FLAGS
EXTRA_FLAGS
@@ -1437,6 +1438,7 @@ Optional Features:
--disable-largefile omit support for large files
--enable-cet enable Intel CET in target libraries [default=no]
--enable-host-shared build host code as shared libraries
+ --enable-cet enable Intel CET in host libraries [default=auto]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -11503,7 +11505,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11506 "configure"
+#line 11508 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11609,7 +11611,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11612 "configure"
+#line 11614 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12378,6 +12380,181 @@ fi
+# Enable Intel CET on Intel CET enabled host if jit is enabled.
+ # Check whether --enable-cet was given.
+if test "${enable_cet+set}" = set; then :
+ enableval=$enable_cet;
+ case "$enableval" in
+ yes|no|auto) ;;
+ *) as_fn_error $? "Unknown argument to enable/disable cet" "$LINENO" 5 ;;
+ esac
+
+else
+ enable_cet=auto
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CET support" >&5
+$as_echo_n "checking for CET support... " >&6; }
+
+case "$host" in
+ i[34567]86-*-linux* | x86_64-*-linux*)
+ may_have_cet=yes
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fcf-protection"
+ case "$enable_cet" in
+ auto)
+ # Check if target supports multi-byte NOPs
+ # and if assembler supports CET insn.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+#if !defined(__SSE2__)
+#error target does not support multi-byte NOPs
+#else
+asm ("setssbsy");
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ enable_cet=yes
+else
+ enable_cet=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+ yes)
+ # Check if assembler supports CET.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+asm ("setssbsy");
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ as_fn_error $? "assembler with CET support is required for --enable-cet" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+ esac
+ CFLAGS="$save_CFLAGS"
+ ;;
+ *)
+ may_have_cet=no
+ enable_cet=no
+ ;;
+esac
+
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fcf-protection=none"
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS -Wl,-z,ibt,-z,shstk"
+if test x$may_have_cet = xyes; then
+ # Check whether -fcf-protection=none -Wl,-z,ibt,-z,shstk work.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ may_have_cet=yes
+else
+ may_have_cet=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test x$may_have_cet = xyes; then
+ if test "$cross_compiling" = yes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+static void
+foo (void)
+{
+}
+
+static void
+__attribute__ ((noinline, noclone))
+xxx (void (*f) (void))
+{
+ f ();
+}
+
+static void
+__attribute__ ((noinline, noclone))
+bar (void)
+{
+ xxx (foo);
+}
+
+int
+main ()
+{
+ bar ();
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ have_cet=no
+else
+ have_cet=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ if test x$enable_cet = xno -a x$have_cet = xyes; then
+ as_fn_error $? "Intel CET must be enabled on Intel CET enabled host" "$LINENO" 5
+ fi
+fi
+if test x$enable_cet = xyes; then
+ CET_HOST_FLAGS="-fcf-protection"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+CFLAGS="$save_CFLAGS"
+LDFLAGS="$save_LDFLAGS"
+
+case x$enable_languages in
+*jit*)
+ ;;
+*)
+ CET_HOST_FLAGS=
+ ;;
+esac
+
+
# Test for __sync support.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __sync extensions" >&5
$as_echo_n "checking __sync extensions... " >&6; }
diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac
index 7c073fa..bd16f20 100644
--- a/libbacktrace/configure.ac
+++ b/libbacktrace/configure.ac
@@ -178,6 +178,17 @@ AC_ARG_ENABLE(host-shared,
[PIC_FLAG=-fPIC], [PIC_FLAG=])
AC_SUBST(PIC_FLAG)
+# Enable Intel CET on Intel CET enabled host if jit is enabled.
+GCC_CET_HOST_FLAGS(CET_HOST_FLAGS)
+case x$enable_languages in
+*jit*)
+ ;;
+*)
+ CET_HOST_FLAGS=
+ ;;
+esac
+AC_SUBST(CET_HOST_FLAGS)
+
# Test for __sync support.
AC_CACHE_CHECK([__sync extensions],
[libbacktrace_cv_sys_sync],
/span> *opaque, int irq_num, int level); static void apb_config_writel (void *opaque, hwaddr addr, uint64_t val, unsigned size) { APBState *s = opaque; APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val); switch (addr & 0xffff) { case 0x30 ... 0x4f: /* DMA error registers */ /* XXX: not implemented yet */ break; case 0x200 ... 0x20b: /* IOMMU */ s->iommu[(addr & 0xf) >> 2] = val; break; case 0x20c ... 0x3ff: /* IOMMU flush */ break; case 0xc00 ... 0xc3f: /* PCI interrupt control */ if (addr & 4) { s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK; s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK; } break; case 0x1000 ... 0x1080: /* OBIO interrupt control */ if (addr & 4) { s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK; s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK; } break; case 0x1400 ... 0x143f: /* PCI interrupt clear */ if (addr & 4) { pci_apb_set_irq(s, (addr & 0x3f) >> 3, 0); } break; case 0x1800 ... 0x1860: /* OBIO interrupt clear */ if (addr & 4) { pci_apb_set_irq(s, 0x20 | ((addr & 0xff) >> 3), 0); } break; case 0x2000 ... 0x202f: /* PCI control */ s->pci_control[(addr & 0x3f) >> 2] = val; break; case 0xf020 ... 0xf027: /* Reset control */ if (addr & 4) { val &= RESET_MASK; s->reset_control &= ~(val & RESET_WCMASK); s->reset_control |= val & RESET_WMASK; if (val & SOFT_POR) { s->nr_resets = 0; qemu_system_reset_request(); } else if (val & SOFT_XIR) { qemu_system_reset_request(); } } break; case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */ case 0xa400 ... 0xa67f: /* IOMMU diagnostics */ case 0xa800 ... 0xa80f: /* Interrupt diagnostics */ case 0xf000 ... 0xf01f: /* FFB config, memory control */ /* we don't care */ default: break; } } static uint64_t apb_config_readl (void *opaque, hwaddr addr, unsigned size) { APBState *s = opaque; uint32_t val; switch (addr & 0xffff) { case 0x30 ... 0x4f: /* DMA error registers */ val = 0; /* XXX: not implemented yet */ break; case 0x200 ... 0x20b: /* IOMMU */ val = s->iommu[(addr & 0xf) >> 2]; break; case 0x20c ... 0x3ff: /* IOMMU flush */ val = 0; break; case 0xc00 ... 0xc3f: /* PCI interrupt control */ if (addr & 4) { val = s->pci_irq_map[(addr & 0x3f) >> 3]; } else { val = 0; } break; case 0x1000 ... 0x1080: /* OBIO interrupt control */ if (addr & 4) { val = s->obio_irq_map[(addr & 0xff) >> 3]; } else { val = 0; } break; case 0x2000 ... 0x202f: /* PCI control */ val = s->pci_control[(addr & 0x3f) >> 2]; break; case 0xf020 ... 0xf027: /* Reset control */ if (addr & 4) { val = s->reset_control; } else { val = 0; } break; case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */ case 0xa400 ... 0xa67f: /* IOMMU diagnostics */ case 0xa800 ... 0xa80f: /* Interrupt diagnostics */ case 0xf000 ... 0xf01f: /* FFB config, memory control */ /* we don't care */ default: val = 0; break; } APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val); return val; } static const MemoryRegionOps apb_config_ops = { .read = apb_config_readl, .write = apb_config_writel, .endianness = DEVICE_NATIVE_ENDIAN, }; static void apb_pci_config_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { APBState *s = opaque; val = qemu_bswap_len(val, size); APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val); pci_data_write(s->bus, addr, val, size); } static uint64_t apb_pci_config_read(void *opaque, hwaddr addr, unsigned size) { uint32_t ret; APBState *s = opaque; ret = pci_data_read(s->bus, addr, size); ret = qemu_bswap_len(ret, size); APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret); return ret; } static void pci_apb_iowriteb (void *opaque, hwaddr addr, uint32_t val) { cpu_outb(addr & IOPORTS_MASK, val); } static void pci_apb_iowritew (void *opaque, hwaddr addr, uint32_t val) { cpu_outw(addr & IOPORTS_MASK, bswap16(val)); } static void pci_apb_iowritel (void *opaque, hwaddr addr, uint32_t val) { cpu_outl(addr & IOPORTS_MASK, bswap32(val)); } static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr) { uint32_t val; val = cpu_inb(addr & IOPORTS_MASK); return val; } static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr) { uint32_t val; val = bswap16(cpu_inw(addr & IOPORTS_MASK)); return val; } static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr) { uint32_t val; val = bswap32(cpu_inl(addr & IOPORTS_MASK)); return val; } static const MemoryRegionOps pci_ioport_ops = { .old_mmio = { .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl }, .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, }, }, .endianness = DEVICE_NATIVE_ENDIAN, }; /* The APB host has an IRQ line for each IRQ line of each slot. */ static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num) { return ((pci_dev->devfn & 0x18) >> 1) + irq_num; } static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num) { int bus_offset; if (pci_dev->devfn & 1) bus_offset = 16; else bus_offset = 0; return bus_offset + irq_num; } static void pci_apb_set_irq(void *opaque, int irq_num, int level) { APBState *s = opaque; /* PCI IRQ map onto the first 32 INO. */ if (irq_num < 32) { if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) { APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level); qemu_set_irq(s->ivec_irqs[irq_num], level); } else { APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num); qemu_irq_lower(s->ivec_irqs[irq_num]); } } else { /* OBIO IRQ map onto the next 16 INO. */ if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) { APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level); qemu_set_irq(s->ivec_irqs[irq_num], level); } else { APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num); qemu_irq_lower(s->ivec_irqs[irq_num]); } } } static int apb_pci_bridge_initfn(PCIDevice *dev) { int rc; rc = pci_bridge_initfn(dev); if (rc < 0) { return rc; } /* * command register: * According to PCI bridge spec, after reset * bus master bit is off * memory space enable bit is off * According to manual (805-1251.pdf). * the reset value should be zero unless the boot pin is tied high * (which is true) and thus it should be PCI_COMMAND_MEMORY. */ pci_set_word(dev->config + PCI_COMMAND, PCI_COMMAND_MEMORY); pci_set_word(dev->config + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); return 0; } PCIBus *pci_apb_init(hwaddr special_base, hwaddr mem_base, qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3, qemu_irq **pbm_irqs) { DeviceState *dev; SysBusDevice *s; APBState *d; PCIDevice *pci_dev; PCIBridge *br; /* Ultrasparc PBM main bus */ dev = qdev_create(NULL, "pbm"); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); /* apb_config */ sysbus_mmio_map(s, 0, special_base); /* PCI configuration space */ sysbus_mmio_map(s, 1, special_base + 0x1000000ULL); /* pci_ioport */ sysbus_mmio_map(s, 2, special_base + 0x2000000ULL); d = FROM_SYSBUS(APBState, s); memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); d->bus = pci_register_bus(&d->busdev.qdev, "pci", pci_apb_set_irq, pci_pbm_map_irq, d, &d->pci_mmio, get_system_io(), 0, 32); *pbm_irqs = d->pbm_irqs; d->ivec_irqs = ivec_irqs; pci_create_simple(d->bus, 0, "pbm-pci"); /* APB secondary busses */ pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true, "pbm-bridge"); br = DO_UPCAST(PCIBridge, dev, pci_dev); pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1", pci_apb_map_irq); qdev_init_nofail(&pci_dev->qdev); *bus2 = pci_bridge_get_sec_bus(br); pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true, "pbm-bridge"); br = DO_UPCAST(PCIBridge, dev, pci_dev); pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2", pci_apb_map_irq); qdev_init_nofail(&pci_dev->qdev); *bus3 = pci_bridge_get_sec_bus(br); return d->bus; } static void pci_pbm_reset(DeviceState *d) { unsigned int i; APBState *s = container_of(d, APBState, busdev.qdev); for (i = 0; i < 8; i++) { s->pci_irq_map[i] &= PBM_PCI_IMR_MASK; } for (i = 0; i < 32; i++) { s->obio_irq_map[i] &= PBM_PCI_IMR_MASK; } if (s->nr_resets++ == 0) { /* Power on reset */ s->reset_control = POR; } } static const MemoryRegionOps pci_config_ops = { .read = apb_pci_config_read, .write = apb_pci_config_write, .endianness = DEVICE_NATIVE_ENDIAN, }; static int pci_pbm_init_device(SysBusDevice *dev) { APBState *s; unsigned int i; s = FROM_SYSBUS(APBState, dev); for (i = 0; i < 8; i++) { s->pci_irq_map[i] = (0x1f << 6) | (i << 2); } for (i = 0; i < 32; i++) { s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i; } s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC); /* apb_config */ memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config", 0x10000); /* at region 0 */ sysbus_init_mmio(dev, &s->apb_config); memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config", 0x1000000); /* at region 1 */ sysbus_init_mmio(dev, &s->pci_config); /* pci_ioport */ memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s, "apb-pci-ioport", 0x10000); /* at region 2 */ sysbus_init_mmio(dev, &s->pci_ioport); return 0; } static int pbm_pci_host_init(PCIDevice *d) { pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); pci_set_word(d->config + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); return 0; } static void pbm_pci_host_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); k->init = pbm_pci_host_init; k->vendor_id = PCI_VENDOR_ID_SUN; k->device_id = PCI_DEVICE_ID_SUN_SABRE; k->class_id = PCI_CLASS_BRIDGE_HOST; } static const TypeInfo pbm_pci_host_info = { .name = "pbm-pci", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), .class_init = pbm_pci_host_class_init, }; static void pbm_host_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); k->init = pci_pbm_init_device; dc->reset = pci_pbm_reset; } static const TypeInfo pbm_host_info = { .name = "pbm", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(APBState), .class_init = pbm_host_class_init, }; static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); k->init = apb_pci_bridge_initfn; k->exit = pci_bridge_exitfn; k->vendor_id = PCI_VENDOR_ID_SUN; k->device_id = PCI_DEVICE_ID_SUN_SIMBA; k->revision = 0x11; k->config_write = pci_bridge_write_config; k->is_bridge = 1; dc->reset = pci_bridge_reset; dc->vmsd = &vmstate_pci_device; } static const TypeInfo pbm_pci_bridge_info = { .name = "pbm-bridge", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIBridge), .class_init = pbm_pci_bridge_class_init, }; static void pbm_register_types(void) { type_register_static(&pbm_host_info); type_register_static(&pbm_pci_host_info); type_register_static(&pbm_pci_bridge_info); } type_init(pbm_register_types)