Page MenuHomeFreeBSD

D60118.id187982.diff
No OneTemporary

D60118.id187982.diff

diff --git a/usr.sbin/bhyve/aarch64/bhyve_machdep.h b/usr.sbin/bhyve/aarch64/bhyve_machdep.h
--- a/usr.sbin/bhyve/aarch64/bhyve_machdep.h
+++ b/usr.sbin/bhyve/aarch64/bhyve_machdep.h
@@ -10,4 +10,6 @@
extern uint64_t *cpu_to_mpidr;
extern cpuset_t running_cpumask;
+extern int vgic_version;
+
#endif /* _BHYVE_MACHDEP_H_ */
diff --git a/usr.sbin/bhyve/aarch64/bhyverun_machdep.c b/usr.sbin/bhyve/aarch64/bhyverun_machdep.c
--- a/usr.sbin/bhyve/aarch64/bhyverun_machdep.c
+++ b/usr.sbin/bhyve/aarch64/bhyverun_machdep.c
@@ -56,7 +56,7 @@
#include "uart_emul.h"
/* Start of mem + 1M */
-#define FDT_BASE 0x100000
+#define FDT_BASE 0x8000000
#define FDT_SIZE (64 * 1024)
/* Start of lowmem + 64K */
@@ -79,6 +79,8 @@
uint64_t *cpu_to_mpidr;
+int vgic_version = -1;
+
void
bhyve_init_config(void)
{
@@ -99,11 +101,13 @@
progname = getprogname();
fprintf(stderr,
- "Usage: %s [-CDHhSW]\n"
+ "Usage: %s [-35CDHhSW]\n"
" %*s [-c [[cpus=]numcpus][,sockets=n][,cores=n][,threads=n]]\n"
" %*s [-k config_file] [-m mem] [-o var=value]\n"
" %*s [-p vcpuN[-vcpuM]]:hostcpuX[-hostcpuY]\n"
" %*s [-r file] [-s pci] [-U uuid] vmname\n"
+ " -3: force GIC v3\n"
+ " -5: force GIC v5\n"
" -C: include guest memory in core file\n"
" -c: number of CPUs and/or topology specification\n"
" -D: destroy on power-off\n"
@@ -130,7 +134,7 @@
const char *optstr;
int c;
- optstr = "hCDMNSWk:f:o:p:G:c:s:m:U:";
+ optstr = "hCDMNSWk35:f:o:p:G:c:s:m:U:";
while ((c = getopt(argc, argv, optstr)) != -1) {
switch (c) {
case 'c':
@@ -191,6 +195,12 @@
case 'W':
set_config_bool("virtio.msix", false);
break;
+ case '3':
+ vgic_version = 3;
+ break;
+ case '5':
+ vgic_version = 5;
+ break;
case 'h':
bhyve_usage(0);
default:
@@ -254,7 +264,10 @@
{
struct vmctx *ctx = arg;
- vm_assert_irq(ctx, UART_INTR);
+ if (vgic_version == 5)
+ vm_assert_irq(ctx, (3u << 29) | UART_INTR);
+ else
+ vm_assert_irq(ctx, UART_INTR);
}
static void
@@ -262,7 +275,10 @@
{
struct vmctx *ctx = arg;
- vm_deassert_irq(ctx, UART_INTR);
+ if (vgic_version == 5)
+ vm_deassert_irq(ctx, (3u << 29) | UART_INTR);
+ else
+ vm_deassert_irq(ctx, UART_INTR);
}
static int
@@ -320,7 +336,10 @@
{
struct vmctx *ctx = arg;
- vm_assert_irq(ctx, RTC_INTR);
+ if (vgic_version == 5)
+ vm_assert_irq(ctx, (3u << 29) | RTC_INTR);
+ else
+ vm_assert_irq(ctx, RTC_INTR);
}
static void
@@ -328,7 +347,10 @@
{
struct vmctx *ctx = arg;
- vm_deassert_irq(ctx, RTC_INTR);
+ if (vgic_version == 5)
+ vm_deassert_irq(ctx, (3u << 29) | RTC_INTR);
+ else
+ vm_deassert_irq(ctx, RTC_INTR);
}
static int
@@ -383,6 +405,14 @@
int error;
int pcie_intrs[4] = {PCIE_INTA, PCIE_INTB, PCIE_INTC, PCIE_INTD};
+ if (vgic_version == -1) {
+ vgic_version = vm_get_vgic_version(ctx);
+ if (vgic_version < 0) {
+ warnx("unable to detect vgic version");
+ return (-vgic_version);
+ }
+ }
+
cpu_to_mpidr = calloc(guest_ncpus, sizeof(*cpu_to_mpidr));
if (cpu_to_mpidr == NULL) {
warnx("unable to allocate space for mpidr list");
@@ -416,10 +446,14 @@
if (error != 0)
return (error);
- fdt_add_gic(GIC_DIST_BASE, GIC_DIST_SIZE, GIC_REDIST_BASE,
- GIC_REDIST_SIZE(guest_ncpus));
- error = vm_attach_vgic(ctx, GIC_DIST_BASE, GIC_DIST_SIZE,
- GIC_REDIST_BASE, GIC_REDIST_SIZE(guest_ncpus));
+ if (vgic_version == 5)
+ fdt_add_gicv5(GIC_DIST_BASE, GIC_DIST_SIZE);
+ else
+ fdt_add_gicv3(GIC_DIST_BASE, GIC_DIST_SIZE, GIC_REDIST_BASE,
+ GIC_REDIST_SIZE(guest_ncpus));
+
+ error = vm_attach_vgic_ex(ctx, GIC_DIST_BASE, GIC_DIST_SIZE,
+ GIC_REDIST_BASE, GIC_REDIST_SIZE(guest_ncpus), vgic_version);
if (error != 0) {
warn("vm_attach_vgic()");
return (error);
diff --git a/usr.sbin/bhyve/aarch64/fdt.h b/usr.sbin/bhyve/aarch64/fdt.h
--- a/usr.sbin/bhyve/aarch64/fdt.h
+++ b/usr.sbin/bhyve/aarch64/fdt.h
@@ -37,8 +37,9 @@
int fdt_init(struct vmctx *ctx, int ncpu, vm_paddr_t addrp,
vm_size_t size);
-void fdt_add_gic(uint64_t dist_base, uint64_t dist_size,
+void fdt_add_gicv3(uint64_t dist_base, uint64_t dist_size,
uint64_t redist_base, uint64_t redist_size);
+void fdt_add_gicv5(uint64_t config_base, uint64_t config_size);
void fdt_add_timer(void);
void fdt_add_pcie(int intrs[static 4]);
void fdt_add_uart(uint64_t uart_base, uint64_t uart_size, int intr);
diff --git a/usr.sbin/bhyve/aarch64/fdt.c b/usr.sbin/bhyve/aarch64/fdt.c
--- a/usr.sbin/bhyve/aarch64/fdt.c
+++ b/usr.sbin/bhyve/aarch64/fdt.c
@@ -48,18 +48,55 @@
#define SET_PROP_U64(prop, idx, val) \
((uint64_t *)(prop))[(idx)] = cpu_to_fdt64(val)
-#define GIC_SPI 0
#define GIC_PPI 1
+#define GIC_LPI 2
+#define GIC_V5_SPI 3
+#define GIC_V3_SPI 0
#define IRQ_TYPE_LEVEL_HIGH 4
#define IRQ_TYPE_LEVEL_LOW 8
-#define GIC_FIRST_PPI 16
-#define GIC_FIRST_SPI 32
+#define GIC_V3_FIRST_PPI 16
+#define GIC_V3_FIRST_SPI 32
+#define GIC_V5_FIRST_PPI 0
+#define GIC_V5_FIRST_SPI 0
static void *fdtroot;
static uint32_t gic_phandle = 0;
static uint32_t apb_pclk_phandle;
+static int fdt_ncpu;
+static uint32_t *cpu_phandles;
+
+static int
+translate_ppi(int ppi)
+{
+ if (vgic_version == 3)
+ return (ppi - GIC_V3_FIRST_PPI);
+ else
+ return (ppi - GIC_V5_FIRST_PPI);
+}
+
+static uint32_t
+spi_type(void)
+{
+ if (vgic_version == 3)
+ return (GIC_V3_SPI);
+ else
+ return (GIC_V5_SPI);
+}
+
+static int
+translate_spi(int spi)
+{
+ if (vgic_version == 3) {
+ assert(spi >= GIC_V3_FIRST_SPI);
+ return (spi - GIC_V3_FIRST_SPI);
+ } else {
+ assert(spi >= GIC_V5_FIRST_SPI);
+ return (spi - GIC_V5_FIRST_SPI);
+ }
+}
+
static uint32_t
assign_phandle(void *fdt)
{
@@ -91,6 +128,7 @@
snprintf(node_name, sizeof(node_name), "cpu@%d", cpuid);
fdt_begin_node(fdt, node_name);
+ cpu_phandles[cpuid] = cpu_to_fdt32(assign_phandle(fdt));
fdt_property_string(fdt, "device_type", "cpu");
fdt_property_string(fdt, "compatible", "arm,armv8");
fdt_property_u64(fdt, "reg", cpu_to_mpidr[cpuid]);
@@ -108,6 +146,10 @@
fdt_property_u32(fdt, "#address-cells", 2);
fdt_property_u32(fdt, "#size-cells", 0);
+ fdt_ncpu = ncpu;
+ cpu_phandles = calloc(ncpu, sizeof(*cpu_phandles));
+ assert(cpu_phandles != NULL);
+
for (cpuid = 0; cpuid < ncpu; cpuid++) {
add_cpu(fdt, cpuid);
}
@@ -172,7 +214,7 @@
}
void
-fdt_add_gic(uint64_t dist_base, uint64_t dist_size,
+fdt_add_gicv3(uint64_t dist_base, uint64_t dist_size,
uint64_t redist_base, uint64_t redist_size)
{
char node_name[32];
@@ -209,6 +251,48 @@
fdt_property_u32(fdt, "interrupt-parent", gic_phandle);
}
+void
+fdt_add_gicv5(uint64_t irs_base, uint64_t irs_size)
+{
+ //char node_name[32];
+ void *fdt, *prop;
+
+ fdt = fdtroot;
+
+ fdt_begin_node(fdt, "interrupt-controller");
+
+ gic_phandle = assign_phandle(fdt);
+ fdt_property_string(fdt, "compatible", "arm,gic-v5");
+ fdt_property(fdt, "interrupt-controller", NULL, 0);
+ //fdt_property(fdt, "msi-controller", NULL, 0);
+ /* XXX: Needed given the root #address-cells? */
+ fdt_property_u32(fdt, "#address-cells", 2);
+ fdt_property_u32(fdt, "#size-cells", 2);
+ fdt_property_u32(fdt, "#interrupt-cells", 3);
+ fdt_property(fdt, "ranges", NULL, 0);
+
+ fdt_begin_node(fdt, "irs@0");
+
+ fdt_property_string(fdt, "compatible", "arm,gic-v5-irs");
+ fdt_property_placeholder(fdt, "reg", 2 * sizeof(uint64_t), &prop);
+ SET_PROP_U64(prop, 0, irs_base);
+ SET_PROP_U64(prop, 1, irs_size);
+ fdt_property_string(fdt, "reg-names", "ns-config");
+ fdt_property(fdt, "cpus", cpu_phandles,
+ fdt_ncpu * sizeof(*cpu_phandles));
+ fdt_property_placeholder(fdt, "arm,iaffids",
+ fdt_ncpu * sizeof(uint64_t), &prop);
+ for (int cpu = 0; cpu < fdt_ncpu; cpu++) {
+ SET_PROP_U32(prop, cpu, cpu);
+ }
+
+ fdt_end_node(fdt);
+
+ fdt_end_node(fdt);
+
+ fdt_property_u32(fdt, "interrupt-parent", gic_phandle);
+}
+
void
fdt_add_uart(uint64_t uart_base, uint64_t uart_size, int intr)
{
@@ -217,7 +301,6 @@
assert(gic_phandle != 0);
assert(apb_pclk_phandle != 0);
- assert(intr >= GIC_FIRST_SPI);
fdt = fdtroot;
@@ -230,8 +313,8 @@
fdt_property_u32(fdt, "interrupt-parent", gic_phandle);
fdt_property_placeholder(fdt, "interrupts", 3 * sizeof(uint32_t),
&interrupts);
- SET_PROP_U32(interrupts, 0, GIC_SPI);
- SET_PROP_U32(interrupts, 1, intr - GIC_FIRST_SPI);
+ SET_PROP_U32(interrupts, 0, spi_type());
+ SET_PROP_U32(interrupts, 1, translate_spi(intr));
SET_PROP_U32(interrupts, 2, IRQ_TYPE_LEVEL_HIGH);
fdt_property_placeholder(fdt, "clocks", 2 * sizeof(uint32_t), &prop);
SET_PROP_U32(prop, 0, apb_pclk_phandle);
@@ -257,7 +340,6 @@
assert(gic_phandle != 0);
assert(apb_pclk_phandle != 0);
- assert(intr >= GIC_FIRST_SPI);
fdt = fdtroot;
@@ -270,8 +352,8 @@
fdt_property_u32(fdt, "interrupt-parent", gic_phandle);
fdt_property_placeholder(fdt, "interrupts", 3 * sizeof(uint32_t),
&interrupts);
- SET_PROP_U32(interrupts, 0, GIC_SPI);
- SET_PROP_U32(interrupts, 1, intr - GIC_FIRST_SPI);
+ SET_PROP_U32(interrupts, 0, spi_type());
+ SET_PROP_U32(interrupts, 1, translate_spi(intr));
SET_PROP_U32(interrupts, 2, IRQ_TYPE_LEVEL_HIGH);
fdt_property_placeholder(fdt, "clocks", sizeof(uint32_t), &prop);
SET_PROP_U32(prop, 0, apb_pclk_phandle);
@@ -284,7 +366,11 @@
fdt_add_timer(void)
{
void *fdt, *interrupts;
- uint32_t irqs[] = { 13, 14, 11 };
+ uint32_t irqs[] = {
+ 29, /* Secure */
+ 30, /* Physical */
+ 27 /* Virtual */
+ };
assert(gic_phandle != 0);
@@ -293,18 +379,18 @@
fdt_begin_node(fdt, "timer");
fdt_property_string(fdt, "compatible", "arm,armv8-timer");
fdt_property_u32(fdt, "interrupt-parent", gic_phandle);
- fdt_property_placeholder(fdt, "interrupts", 9 * sizeof(uint32_t),
- &interrupts);
+ fdt_property_placeholder(fdt, "interrupts",
+ nitems(irqs) * 3 * sizeof(uint32_t), &interrupts);
for (u_int i = 0; i < nitems(irqs); i++) {
SET_PROP_U32(interrupts, i * 3 + 0, GIC_PPI);
- SET_PROP_U32(interrupts, i * 3 + 1, irqs[i]);
+ SET_PROP_U32(interrupts, i * 3 + 1, translate_ppi(irqs[i]));
SET_PROP_U32(interrupts, i * 3 + 2, IRQ_TYPE_LEVEL_LOW);
}
fdt_end_node(fdt);
}
void
-fdt_add_pcie(int intrs[static 4])
+fdt_add_pcie(int intrs[static 4] __unused)
{
void *fdt, *prop;
int slot, pin, intr, i;
@@ -370,7 +456,8 @@
pin = i % 4;
slot = i / 4;
intr = intrs[(pin + slot) % 4];
- assert(intr >= GIC_FIRST_SPI);
+ assert(intr >= ((vgic_version == 3) ? GIC_V3_FIRST_SPI :
+ GIC_V5_FIRST_SPI));
SET_PROP_U32(prop, 10 * i + 0, slot << 11);
SET_PROP_U32(prop, 10 * i + 1, 0);
SET_PROP_U32(prop, 10 * i + 2, 0);
@@ -378,8 +465,8 @@
SET_PROP_U32(prop, 10 * i + 4, gic_phandle);
SET_PROP_U32(prop, 10 * i + 5, 0);
SET_PROP_U32(prop, 10 * i + 6, 0);
- SET_PROP_U32(prop, 10 * i + 7, GIC_SPI);
- SET_PROP_U32(prop, 10 * i + 8, intr - GIC_FIRST_SPI);
+ SET_PROP_U32(prop, 10 * i + 7, spi_type());
+ SET_PROP_U32(prop, 10 * i + 8, translate_spi(intr));
SET_PROP_U32(prop, 10 * i + 9, IRQ_TYPE_LEVEL_HIGH);
}
diff --git a/usr.sbin/bhyve/aarch64/pci_irq.c b/usr.sbin/bhyve/aarch64/pci_irq.c
--- a/usr.sbin/bhyve/aarch64/pci_irq.c
+++ b/usr.sbin/bhyve/aarch64/pci_irq.c
@@ -27,6 +27,7 @@
#include <vmmapi.h>
+#include "bhyve_machdep.h"
#include "pci_emul.h"
#include "pci_irq.h"
@@ -44,13 +45,21 @@
void
pci_irq_assert(struct pci_devinst *pi)
{
- vm_assert_irq(pi->pi_vmctx, pi->pi_lintr.irq.gic_irq);
+ if (vgic_version == 5)
+ vm_assert_irq(pi->pi_vmctx, (3u << 29) |
+ pi->pi_lintr.irq.gic_irq);
+ else
+ vm_assert_irq(pi->pi_vmctx, pi->pi_lintr.irq.gic_irq);
}
void
pci_irq_deassert(struct pci_devinst *pi)
{
- vm_deassert_irq(pi->pi_vmctx, pi->pi_lintr.irq.gic_irq);
+ if (vgic_version == 5)
+ vm_deassert_irq(pi->pi_vmctx, (3u << 29) |
+ pi->pi_lintr.irq.gic_irq);
+ else
+ vm_deassert_irq(pi->pi_vmctx, pi->pi_lintr.irq.gic_irq);
}
void

File Metadata

Mime Type
text/plain
Expires
Wed, Sep 30, 12:45 PM (11 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39945343
Default Alt Text
D60118.id187982.diff (11 KB)

Event Timeline