Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F173940069
D60118.id187982.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D60118.id187982.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D60118: bhyve: Add Arm GICv5 support
Attached
Detach File
Event Timeline
Log In to Comment