ppc patch queue 2018-01-29
Here's another batch of patches for ppc, spapr and related things. Higlights: * Implement (with a bunch of necessary infrastructure) a hypercall to let guests properly apply Spectre and Meltdown workarounds. * Convert a number of old devices to trace events * Fix some bugs -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAlpulKIACgkQbDjKyiDZ s5JvIw/+OYY+Wj4vqpUO5jxvawC5GmENJEr0Ff03iVaSqw2Xt7J+yYs2tCeaWp5Y 3OmqKPqdE1Mo+YPAFSemYr1FV6ZybBBiNPcl99XU8OTQtsPvY4QLQjHzmAuFLp0z fAxzAOn7aprXuTo0zlhvTZdPS6yZ4i7+6x3M2HWJ6isuHHrR4tEXsE68xoSrsM2k vJ9Ix0sjPFyhzn1FHjwRPKCCH9NhmWwxfyp6qRWz/v02hqCH/uW/Rcbr2xQiHsws dUS6egrmKvR4tyjm82e28BfPvCfwY3ZuJ4nK07urvKUAbbMq2ydLYgkZxs2QLV+m QAGy/kagdKJDel29ZNIQyRTi1MoFnN+FgV28uew+IqroVSR9q46/gLl8tmaCb0+E bVUi5Wy2hQbyQhh/TMAs43+7NALd4cttaHabgwtVup3/DplHVvghR8gLSR9pJJpi XLi3D1Q5flPrzb0nMv8BWP3jwIKkiNVmqT5WSXY9Sd7bivFB2y6FVJuq1ejBoHrv n3718ANKeTSWWKs37VLndBmYy7AGGkKKNokBNoUB9kqkDK8NfmQ5mkY5qsbaIGB4 vKlA1b5obzxLF+cNVnMgdbXhneiYyYX0Q5zwXk7gDCmIKEZ0cysujzOyF6SvfIRL HBJ2Tmkd0+hYHppw38wUUAMq9CZftTFQkOl+Atm3u45xlwVm5Ao= =N96F -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.12-20180129' into staging ppc patch queue 2018-01-29 Here's another batch of patches for ppc, spapr and related things. Higlights: * Implement (with a bunch of necessary infrastructure) a hypercall to let guests properly apply Spectre and Meltdown workarounds. * Convert a number of old devices to trace events * Fix some bugs # gpg: Signature made Mon 29 Jan 2018 03:27:30 GMT # gpg: using RSA key 0x6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-2.12-20180129: target/ppc/spapr: Add H-Call H_GET_CPU_CHARACTERISTICS target/ppc/spapr_caps: Add new tristate cap safe_indirect_branch target/ppc/spapr_caps: Add new tristate cap safe_bounds_check target/ppc/spapr_caps: Add new tristate cap safe_cache target/ppc/spapr_caps: Add support for tristate spapr_capabilities target/ppc/kvm: Add cap_ppc_safe_[cache/bounds_check/indirect_branch] spapr_pci: fix MSI/MSIX selection input: add missing newline from trace-events uninorth: convert to trace-events grackle: convert to trace-events ppc: Deprecate qemu-system-ppcemb ppc/pnv: fix PnvChip redefinition in <hw/ppc/pnv_xscom.h> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
fccfcc6328
@ -4,6 +4,7 @@
|
||||
adb_kbd_no_key(void) "Ignoring NO_KEY"
|
||||
adb_kbd_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x"
|
||||
adb_kbd_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x"
|
||||
|
||||
# hw/input/adb-mouse.c
|
||||
adb_mouse_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x"
|
||||
adb_mouse_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x"
|
||||
|
@ -27,16 +27,7 @@
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "hw/ppc/mac.h"
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
/* debug Grackle */
|
||||
//#define DEBUG_GRACKLE
|
||||
|
||||
#ifdef DEBUG_GRACKLE
|
||||
#define GRACKLE_DPRINTF(fmt, ...) \
|
||||
do { printf("GRACKLE: " fmt , ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define GRACKLE_DPRINTF(fmt, ...)
|
||||
#endif
|
||||
#include "trace.h"
|
||||
|
||||
#define GRACKLE_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE)
|
||||
@ -58,7 +49,7 @@ static void pci_grackle_set_irq(void *opaque, int irq_num, int level)
|
||||
{
|
||||
qemu_irq *pic = opaque;
|
||||
|
||||
GRACKLE_DPRINTF("set_irq num %d level %d\n", irq_num, level);
|
||||
trace_grackle_set_irq(irq_num, level);
|
||||
qemu_set_irq(pic[irq_num + 0x15], level);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# hw/pci-host/grackle.c
|
||||
grackle_set_irq(int irq_num, int level) "set_irq num %d level %d"
|
||||
|
||||
# hw/pci-host/sabre.c
|
||||
sabre_set_request(int irq_num) "request irq %d"
|
||||
sabre_clear_request(int irq_num) "clear request irq %d"
|
||||
@ -9,3 +12,9 @@ sabre_pci_config_write(uint64_t addr, uint64_t val) "addr 0x%"PRIx64" val 0x%"PR
|
||||
sabre_pci_config_read(uint64_t addr, uint64_t val) "addr 0x%"PRIx64" val 0x%"PRIx64
|
||||
sabre_pci_set_irq(int irq_num, int level) "set irq_in %d level %d"
|
||||
sabre_pci_set_obio_irq(int irq_num, int level) "set irq %d level %d"
|
||||
|
||||
# hw/pci-host/uninorth.c
|
||||
unin_set_irq(int irq_num, int level) "setting INT %d = %d"
|
||||
unin_get_config_reg(uint32_t reg, uint32_t addr, uint32_t retval) "converted config space accessor 0x%"PRIx32 "/0x%"PRIx32 " -> 0x%"PRIx32
|
||||
unin_data_write(uint64_t addr, unsigned len, uint64_t val) "write addr 0x%"PRIx64 " len %d val 0x%"PRIx64
|
||||
unin_data_read(uint64_t addr, unsigned len, uint64_t val) "read addr 0x%"PRIx64 " len %d val 0x%"PRIx64
|
||||
|
@ -26,16 +26,7 @@
|
||||
#include "hw/ppc/mac.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
|
||||
/* debug UniNorth */
|
||||
//#define DEBUG_UNIN
|
||||
|
||||
#ifdef DEBUG_UNIN
|
||||
#define UNIN_DPRINTF(fmt, ...) \
|
||||
do { printf("UNIN: " fmt , ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define UNIN_DPRINTF(fmt, ...)
|
||||
#endif
|
||||
#include "trace.h"
|
||||
|
||||
static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
|
||||
|
||||
@ -69,8 +60,7 @@ static void pci_unin_set_irq(void *opaque, int irq_num, int level)
|
||||
{
|
||||
qemu_irq *pic = opaque;
|
||||
|
||||
UNIN_DPRINTF("%s: setting INT %d = %d\n", __func__,
|
||||
unin_irq_line[irq_num], level);
|
||||
trace_unin_set_irq(unin_irq_line[irq_num], level);
|
||||
qemu_set_irq(pic[unin_irq_line[irq_num]], level);
|
||||
}
|
||||
|
||||
@ -103,9 +93,7 @@ static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
|
||||
retval |= func << 8;
|
||||
}
|
||||
|
||||
|
||||
UNIN_DPRINTF("Converted config space accessor %08x/%08x -> %08x\n",
|
||||
reg, addr, retval);
|
||||
trace_unin_get_config_reg(reg, addr, retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -115,8 +103,7 @@ static void unin_data_write(void *opaque, hwaddr addr,
|
||||
{
|
||||
UNINState *s = opaque;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
UNIN_DPRINTF("write addr " TARGET_FMT_plx " len %d val %"PRIx64"\n",
|
||||
addr, len, val);
|
||||
trace_unin_data_write(addr, len, val);
|
||||
pci_data_write(phb->bus,
|
||||
unin_get_config_reg(phb->config_reg, addr),
|
||||
val, len);
|
||||
@ -132,8 +119,7 @@ static uint64_t unin_data_read(void *opaque, hwaddr addr,
|
||||
val = pci_data_read(phb->bus,
|
||||
unin_get_config_reg(phb->config_reg, addr),
|
||||
len);
|
||||
UNIN_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n",
|
||||
addr, len, val);
|
||||
trace_unin_data_read(addr, len, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -202,6 +202,13 @@ static void ref405ep_init(MachineState *machine)
|
||||
DriveInfo *dinfo;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
|
||||
#ifdef TARGET_PPCEMB
|
||||
if (!qtest_enabled()) {
|
||||
warn_report("qemu-system-ppcemb is deprecated, "
|
||||
"please use qemu-system-ppc instead.");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX: fix this */
|
||||
memory_region_allocate_system_memory(&ram_memories[0], NULL, "ef405ep.ram",
|
||||
0x08000000);
|
||||
@ -497,6 +504,13 @@ static void taihu_405ep_init(MachineState *machine)
|
||||
int fl_idx, fl_sectors;
|
||||
DriveInfo *dinfo;
|
||||
|
||||
#ifdef TARGET_PPCEMB
|
||||
if (!qtest_enabled()) {
|
||||
warn_report("qemu-system-ppcemb is deprecated, "
|
||||
"please use qemu-system-ppc instead.");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* RAM is soldered to the board so the size cannot be changed */
|
||||
ram_size = 0x08000000;
|
||||
memory_region_allocate_system_memory(ram, NULL, "taihu_405ep.ram",
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/pci/pci.h"
|
||||
@ -27,6 +28,7 @@
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "ppc405.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
|
||||
@ -191,6 +193,13 @@ static void bamboo_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef TARGET_PPCEMB
|
||||
if (!qtest_enabled()) {
|
||||
warn_report("qemu-system-ppcemb is deprecated, "
|
||||
"please use qemu-system-ppc instead.");
|
||||
}
|
||||
#endif
|
||||
|
||||
qemu_register_reset(main_cpu_reset, cpu);
|
||||
ppc_booke_timers_init(cpu, 400000000, 0);
|
||||
ppc_dcr_init(env, NULL, NULL);
|
||||
|
@ -1791,6 +1791,9 @@ static const VMStateDescription vmstate_spapr = {
|
||||
&vmstate_spapr_cap_htm,
|
||||
&vmstate_spapr_cap_vsx,
|
||||
&vmstate_spapr_cap_dfp,
|
||||
&vmstate_spapr_cap_cfpc,
|
||||
&vmstate_spapr_cap_sbbc,
|
||||
&vmstate_spapr_cap_ibs,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
@ -3881,6 +3884,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
|
||||
smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
|
||||
smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
|
||||
smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
|
||||
smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
|
||||
smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
|
||||
spapr_caps_add_properties(smc, &error_abort);
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,66 @@ static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name,
|
||||
spapr->eff.caps[cap->index] = value ? SPAPR_CAP_ON : SPAPR_CAP_OFF;
|
||||
}
|
||||
|
||||
static void spapr_cap_get_tristate(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
sPAPRCapabilityInfo *cap = opaque;
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
char *val = NULL;
|
||||
uint8_t value = spapr_get_cap(spapr, cap->index);
|
||||
|
||||
switch (value) {
|
||||
case SPAPR_CAP_BROKEN:
|
||||
val = g_strdup("broken");
|
||||
break;
|
||||
case SPAPR_CAP_WORKAROUND:
|
||||
val = g_strdup("workaround");
|
||||
break;
|
||||
case SPAPR_CAP_FIXED:
|
||||
val = g_strdup("fixed");
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Invalid value (%d) for cap-%s", value, cap->name);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_str(v, name, &val, errp);
|
||||
g_free(val);
|
||||
}
|
||||
|
||||
static void spapr_cap_set_tristate(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
sPAPRCapabilityInfo *cap = opaque;
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
char *val;
|
||||
Error *local_err = NULL;
|
||||
uint8_t value;
|
||||
|
||||
visit_type_str(v, name, &val, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcasecmp(val, "broken")) {
|
||||
value = SPAPR_CAP_BROKEN;
|
||||
} else if (!strcasecmp(val, "workaround")) {
|
||||
value = SPAPR_CAP_WORKAROUND;
|
||||
} else if (!strcasecmp(val, "fixed")) {
|
||||
value = SPAPR_CAP_FIXED;
|
||||
} else {
|
||||
error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val,
|
||||
cap->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spapr->cmd_line_caps[cap->index] = true;
|
||||
spapr->eff.caps[cap->index] = value;
|
||||
out:
|
||||
g_free(val);
|
||||
}
|
||||
|
||||
static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
|
||||
{
|
||||
if (!val) {
|
||||
@ -120,6 +180,40 @@ static void cap_dfp_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_safe_cache_apply(sPAPRMachineState *spapr, uint8_t val,
|
||||
Error **errp)
|
||||
{
|
||||
if (tcg_enabled() && val) {
|
||||
/* TODO - for now only allow broken for TCG */
|
||||
error_setg(errp, "Requested safe cache capability level not supported by tcg, try a different value for cap-cfpc");
|
||||
} else if (kvm_enabled() && (val > kvmppc_get_cap_safe_cache())) {
|
||||
error_setg(errp, "Requested safe cache capability level not supported by kvm, try a different value for cap-cfpc");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val,
|
||||
Error **errp)
|
||||
{
|
||||
if (tcg_enabled() && val) {
|
||||
/* TODO - for now only allow broken for TCG */
|
||||
error_setg(errp, "Requested safe bounds check capability level not supported by tcg, try a different value for cap-sbbc");
|
||||
} else if (kvm_enabled() && (val > kvmppc_get_cap_safe_bounds_check())) {
|
||||
error_setg(errp, "Requested safe bounds check capability level not supported by kvm, try a different value for cap-sbbc");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
|
||||
uint8_t val, Error **errp)
|
||||
{
|
||||
if (tcg_enabled() && val) {
|
||||
/* TODO - for now only allow broken for TCG */
|
||||
error_setg(errp, "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs");
|
||||
} else if (kvm_enabled() && (val > kvmppc_get_cap_safe_indirect_branch())) {
|
||||
error_setg(errp, "Requested safe indirect branch capability level not supported by kvm, try a different value for cap-ibs");
|
||||
}
|
||||
}
|
||||
|
||||
#define VALUE_DESC_TRISTATE " (broken, workaround, fixed)"
|
||||
|
||||
sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
|
||||
[SPAPR_CAP_HTM] = {
|
||||
@ -149,6 +243,33 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
|
||||
.type = "bool",
|
||||
.apply = cap_dfp_apply,
|
||||
},
|
||||
[SPAPR_CAP_CFPC] = {
|
||||
.name = "cfpc",
|
||||
.description = "Cache Flush on Privilege Change" VALUE_DESC_TRISTATE,
|
||||
.index = SPAPR_CAP_CFPC,
|
||||
.get = spapr_cap_get_tristate,
|
||||
.set = spapr_cap_set_tristate,
|
||||
.type = "string",
|
||||
.apply = cap_safe_cache_apply,
|
||||
},
|
||||
[SPAPR_CAP_SBBC] = {
|
||||
.name = "sbbc",
|
||||
.description = "Speculation Barrier Bounds Checking" VALUE_DESC_TRISTATE,
|
||||
.index = SPAPR_CAP_SBBC,
|
||||
.get = spapr_cap_get_tristate,
|
||||
.set = spapr_cap_set_tristate,
|
||||
.type = "string",
|
||||
.apply = cap_safe_bounds_check_apply,
|
||||
},
|
||||
[SPAPR_CAP_IBS] = {
|
||||
.name = "ibs",
|
||||
.description = "Indirect Branch Serialisation" VALUE_DESC_TRISTATE,
|
||||
.index = SPAPR_CAP_IBS,
|
||||
.get = spapr_cap_get_tristate,
|
||||
.set = spapr_cap_set_tristate,
|
||||
.type = "string",
|
||||
.apply = cap_safe_indirect_branch_apply,
|
||||
},
|
||||
};
|
||||
|
||||
static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
|
||||
@ -254,6 +375,9 @@ const VMStateDescription vmstate_spapr_cap_##cap = { \
|
||||
SPAPR_CAP_MIG_STATE(htm, HTM);
|
||||
SPAPR_CAP_MIG_STATE(vsx, VSX);
|
||||
SPAPR_CAP_MIG_STATE(dfp, DFP);
|
||||
SPAPR_CAP_MIG_STATE(cfpc, CFPC);
|
||||
SPAPR_CAP_MIG_STATE(sbbc, SBBC);
|
||||
SPAPR_CAP_MIG_STATE(ibs, IBS);
|
||||
|
||||
void spapr_caps_reset(sPAPRMachineState *spapr)
|
||||
{
|
||||
|
@ -1654,6 +1654,60 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
|
||||
sPAPRMachineState *spapr,
|
||||
target_ulong opcode,
|
||||
target_ulong *args)
|
||||
{
|
||||
uint64_t characteristics = H_CPU_CHAR_HON_BRANCH_HINTS &
|
||||
~H_CPU_CHAR_THR_RECONF_TRIG;
|
||||
uint64_t behaviour = H_CPU_BEHAV_FAVOUR_SECURITY;
|
||||
uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC);
|
||||
uint8_t safe_bounds_check = spapr_get_cap(spapr, SPAPR_CAP_SBBC);
|
||||
uint8_t safe_indirect_branch = spapr_get_cap(spapr, SPAPR_CAP_IBS);
|
||||
|
||||
switch (safe_cache) {
|
||||
case SPAPR_CAP_WORKAROUND:
|
||||
characteristics |= H_CPU_CHAR_L1D_FLUSH_ORI30;
|
||||
characteristics |= H_CPU_CHAR_L1D_FLUSH_TRIG2;
|
||||
characteristics |= H_CPU_CHAR_L1D_THREAD_PRIV;
|
||||
behaviour |= H_CPU_BEHAV_L1D_FLUSH_PR;
|
||||
break;
|
||||
case SPAPR_CAP_FIXED:
|
||||
break;
|
||||
default: /* broken */
|
||||
assert(safe_cache == SPAPR_CAP_BROKEN);
|
||||
behaviour |= H_CPU_BEHAV_L1D_FLUSH_PR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (safe_bounds_check) {
|
||||
case SPAPR_CAP_WORKAROUND:
|
||||
characteristics |= H_CPU_CHAR_SPEC_BAR_ORI31;
|
||||
behaviour |= H_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
|
||||
break;
|
||||
case SPAPR_CAP_FIXED:
|
||||
break;
|
||||
default: /* broken */
|
||||
assert(safe_bounds_check == SPAPR_CAP_BROKEN);
|
||||
behaviour |= H_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (safe_indirect_branch) {
|
||||
case SPAPR_CAP_FIXED:
|
||||
characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
|
||||
default: /* broken */
|
||||
assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
|
||||
break;
|
||||
}
|
||||
|
||||
args[0] = characteristics;
|
||||
args[1] = behaviour;
|
||||
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
|
||||
static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
|
||||
|
||||
@ -1733,6 +1787,10 @@ static void hypercall_register_types(void)
|
||||
spapr_register_hypercall(H_INVALIDATE_PID, h_invalidate_pid);
|
||||
spapr_register_hypercall(H_REGISTER_PROC_TBL, h_register_process_table);
|
||||
|
||||
/* hcall-get-cpu-characteristics */
|
||||
spapr_register_hypercall(H_GET_CPU_CHARACTERISTICS,
|
||||
h_get_cpu_characteristics);
|
||||
|
||||
/* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
|
||||
* here between the "CI" and the "CACHE" variants, they will use whatever
|
||||
* mapping attributes qemu is using. When using KVM, the kernel will
|
||||
|
@ -280,20 +280,6 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
int *config_addr_key;
|
||||
Error *err = NULL;
|
||||
|
||||
switch (func) {
|
||||
case RTAS_CHANGE_MSI_FN:
|
||||
case RTAS_CHANGE_FN:
|
||||
ret_intr_type = RTAS_TYPE_MSI;
|
||||
break;
|
||||
case RTAS_CHANGE_MSIX_FN:
|
||||
ret_intr_type = RTAS_TYPE_MSIX;
|
||||
break;
|
||||
default:
|
||||
error_report("rtas_ibm_change_msi(%u) is not implemented", func);
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fins sPAPRPHBState */
|
||||
phb = spapr_pci_find_phb(spapr, buid);
|
||||
if (phb) {
|
||||
@ -304,6 +290,39 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return;
|
||||
}
|
||||
|
||||
switch (func) {
|
||||
case RTAS_CHANGE_FN:
|
||||
if (msi_present(pdev)) {
|
||||
ret_intr_type = RTAS_TYPE_MSI;
|
||||
} else if (msix_present(pdev)) {
|
||||
ret_intr_type = RTAS_TYPE_MSIX;
|
||||
} else {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case RTAS_CHANGE_MSI_FN:
|
||||
if (msi_present(pdev)) {
|
||||
ret_intr_type = RTAS_TYPE_MSI;
|
||||
} else {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case RTAS_CHANGE_MSIX_FN:
|
||||
if (msix_present(pdev)) {
|
||||
ret_intr_type = RTAS_TYPE_MSIX;
|
||||
} else {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_report("rtas_ibm_change_msi(%u) is not implemented", func);
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
msi = (spapr_pci_msi *) g_hash_table_lookup(phb->msi, &config_addr);
|
||||
|
||||
/* Releasing MSIs */
|
||||
@ -1286,13 +1305,17 @@ static void spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "#size-cells",
|
||||
RESOURCE_CELLS_SIZE));
|
||||
|
||||
max_msi = msi_nr_vectors_allocated(dev);
|
||||
if (max_msi) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi));
|
||||
if (msi_present(dev)) {
|
||||
max_msi = msi_nr_vectors_allocated(dev);
|
||||
if (max_msi) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi));
|
||||
}
|
||||
}
|
||||
max_msix = dev->msix_entries_nr;
|
||||
if (max_msix) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix));
|
||||
if (msix_present(dev)) {
|
||||
max_msix = dev->msix_entries_nr;
|
||||
if (max_msix) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix));
|
||||
}
|
||||
}
|
||||
|
||||
populate_resource_props(dev, &rp);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "hw/char/serial.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/devices.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
@ -210,6 +211,13 @@ static void virtex_init(MachineState *machine)
|
||||
int kernel_size;
|
||||
int i;
|
||||
|
||||
#ifdef TARGET_PPCEMB
|
||||
if (!qtest_enabled()) {
|
||||
warn_report("qemu-system-ppcemb is deprecated, "
|
||||
"please use qemu-system-ppc instead.");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* init CPUs */
|
||||
cpu = ppc440_init_xilinx(&ram_size, 1, machine->cpu_type, 400000000);
|
||||
env = &cpu->env;
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
#include "qom/object.h"
|
||||
|
||||
typedef struct PnvChip PnvChip;
|
||||
|
||||
typedef struct PnvXScomInterface {
|
||||
Object parent;
|
||||
} PnvXScomInterface;
|
||||
|
@ -60,8 +60,14 @@ typedef enum {
|
||||
#define SPAPR_CAP_VSX 0x01
|
||||
/* Decimal Floating Point */
|
||||
#define SPAPR_CAP_DFP 0x02
|
||||
/* Cache Flush on Privilege Change */
|
||||
#define SPAPR_CAP_CFPC 0x03
|
||||
/* Speculation Barrier Bounds Checking */
|
||||
#define SPAPR_CAP_SBBC 0x04
|
||||
/* Indirect Branch Serialisation */
|
||||
#define SPAPR_CAP_IBS 0x05
|
||||
/* Num Caps */
|
||||
#define SPAPR_CAP_NUM (SPAPR_CAP_DFP + 1)
|
||||
#define SPAPR_CAP_NUM (SPAPR_CAP_IBS + 1)
|
||||
|
||||
/*
|
||||
* Capability Values
|
||||
@ -69,6 +75,10 @@ typedef enum {
|
||||
/* Bool Caps */
|
||||
#define SPAPR_CAP_OFF 0x00
|
||||
#define SPAPR_CAP_ON 0x01
|
||||
/* Broken | Workaround | Fixed Caps */
|
||||
#define SPAPR_CAP_BROKEN 0x00
|
||||
#define SPAPR_CAP_WORKAROUND 0x01
|
||||
#define SPAPR_CAP_FIXED 0x02
|
||||
|
||||
typedef struct sPAPRCapabilities sPAPRCapabilities;
|
||||
struct sPAPRCapabilities {
|
||||
@ -295,6 +305,18 @@ struct sPAPRMachineState {
|
||||
#define H_DABRX_KERNEL (1ULL<<(63-62))
|
||||
#define H_DABRX_USER (1ULL<<(63-63))
|
||||
|
||||
/* Values for KVM_PPC_GET_CPU_CHAR & H_GET_CPU_CHARACTERISTICS */
|
||||
#define H_CPU_CHAR_SPEC_BAR_ORI31 PPC_BIT(0)
|
||||
#define H_CPU_CHAR_BCCTRL_SERIALISED PPC_BIT(1)
|
||||
#define H_CPU_CHAR_L1D_FLUSH_ORI30 PPC_BIT(2)
|
||||
#define H_CPU_CHAR_L1D_FLUSH_TRIG2 PPC_BIT(3)
|
||||
#define H_CPU_CHAR_L1D_THREAD_PRIV PPC_BIT(4)
|
||||
#define H_CPU_CHAR_HON_BRANCH_HINTS PPC_BIT(5)
|
||||
#define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6)
|
||||
#define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0)
|
||||
#define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1)
|
||||
#define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2)
|
||||
|
||||
/* Each control block has to be on a 4K boundary */
|
||||
#define H_CB_ALIGNMENT 4096
|
||||
|
||||
@ -382,6 +404,7 @@ struct sPAPRMachineState {
|
||||
#define H_GET_HCA_INFO 0x1B8
|
||||
#define H_GET_PERF_COUNT 0x1BC
|
||||
#define H_MANAGE_TRACE 0x1C0
|
||||
#define H_GET_CPU_CHARACTERISTICS 0x1C8
|
||||
#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
|
||||
#define H_QUERY_INT_STATE 0x1E4
|
||||
#define H_POLL_PENDING 0x1D8
|
||||
@ -763,6 +786,9 @@ int spapr_caps_pre_save(void *opaque);
|
||||
extern const VMStateDescription vmstate_spapr_cap_htm;
|
||||
extern const VMStateDescription vmstate_spapr_cap_vsx;
|
||||
extern const VMStateDescription vmstate_spapr_cap_dfp;
|
||||
extern const VMStateDescription vmstate_spapr_cap_cfpc;
|
||||
extern const VMStateDescription vmstate_spapr_cap_sbbc;
|
||||
extern const VMStateDescription vmstate_spapr_cap_ibs;
|
||||
|
||||
static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
|
||||
{
|
||||
|
@ -2773,6 +2773,12 @@ The ``host_net_remove'' command is replaced by the ``netdev_del'' command.
|
||||
The ``ivshmem'' device type is replaced by either the ``ivshmem-plain''
|
||||
or ``ivshmem-doorbell`` device types.
|
||||
|
||||
@subsection Page size support < 4k for embedded PowerPC CPUs (since 2.12.0)
|
||||
|
||||
qemu-system-ppcemb will be removed. qemu-system-ppc (or qemu-system-ppc64)
|
||||
should be used instead. That means that embedded 4xx PowerPC CPUs will not
|
||||
support page sizes < 4096 any longer.
|
||||
|
||||
@section System emulator machines
|
||||
|
||||
@subsection Xilinx EP108 (since 2.11.0)
|
||||
|
@ -89,6 +89,9 @@ static int cap_mmu_radix;
|
||||
static int cap_mmu_hash_v3;
|
||||
static int cap_resize_hpt;
|
||||
static int cap_ppc_pvr_compat;
|
||||
static int cap_ppc_safe_cache;
|
||||
static int cap_ppc_safe_bounds_check;
|
||||
static int cap_ppc_safe_indirect_branch;
|
||||
|
||||
static uint32_t debug_inst_opcode;
|
||||
|
||||
@ -121,6 +124,7 @@ static bool kvmppc_is_pr(KVMState *ks)
|
||||
}
|
||||
|
||||
static int kvm_ppc_register_host_cpu_type(MachineState *ms);
|
||||
static void kvmppc_get_cpu_characteristics(KVMState *s);
|
||||
|
||||
int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
{
|
||||
@ -147,6 +151,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX);
|
||||
cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3);
|
||||
cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
|
||||
kvmppc_get_cpu_characteristics(s);
|
||||
/*
|
||||
* Note: setting it to false because there is not such capability
|
||||
* in KVM at this moment.
|
||||
@ -2456,6 +2461,59 @@ bool kvmppc_has_cap_mmu_hash_v3(void)
|
||||
return cap_mmu_hash_v3;
|
||||
}
|
||||
|
||||
static void kvmppc_get_cpu_characteristics(KVMState *s)
|
||||
{
|
||||
struct kvm_ppc_cpu_char c;
|
||||
int ret;
|
||||
|
||||
/* Assume broken */
|
||||
cap_ppc_safe_cache = 0;
|
||||
cap_ppc_safe_bounds_check = 0;
|
||||
cap_ppc_safe_indirect_branch = 0;
|
||||
|
||||
ret = kvm_vm_check_extension(s, KVM_CAP_PPC_GET_CPU_CHAR);
|
||||
if (!ret) {
|
||||
return;
|
||||
}
|
||||
ret = kvm_vm_ioctl(s, KVM_PPC_GET_CPU_CHAR, &c);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
/* Parse and set cap_ppc_safe_cache */
|
||||
if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) {
|
||||
cap_ppc_safe_cache = 2;
|
||||
} else if ((c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) &&
|
||||
(c.character & c.character_mask
|
||||
& (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) {
|
||||
cap_ppc_safe_cache = 1;
|
||||
}
|
||||
/* Parse and set cap_ppc_safe_bounds_check */
|
||||
if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) {
|
||||
cap_ppc_safe_bounds_check = 2;
|
||||
} else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) {
|
||||
cap_ppc_safe_bounds_check = 1;
|
||||
}
|
||||
/* Parse and set cap_ppc_safe_indirect_branch */
|
||||
if (c.character & H_CPU_CHAR_BCCTRL_SERIALISED) {
|
||||
cap_ppc_safe_indirect_branch = 2;
|
||||
}
|
||||
}
|
||||
|
||||
int kvmppc_get_cap_safe_cache(void)
|
||||
{
|
||||
return cap_ppc_safe_cache;
|
||||
}
|
||||
|
||||
int kvmppc_get_cap_safe_bounds_check(void)
|
||||
{
|
||||
return cap_ppc_safe_bounds_check;
|
||||
}
|
||||
|
||||
int kvmppc_get_cap_safe_indirect_branch(void)
|
||||
{
|
||||
return cap_ppc_safe_indirect_branch;
|
||||
}
|
||||
|
||||
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
|
||||
{
|
||||
uint32_t host_pvr = mfpvr();
|
||||
|
@ -59,6 +59,9 @@ bool kvmppc_has_cap_fixup_hcalls(void);
|
||||
bool kvmppc_has_cap_htm(void);
|
||||
bool kvmppc_has_cap_mmu_radix(void);
|
||||
bool kvmppc_has_cap_mmu_hash_v3(void);
|
||||
int kvmppc_get_cap_safe_cache(void);
|
||||
int kvmppc_get_cap_safe_bounds_check(void);
|
||||
int kvmppc_get_cap_safe_indirect_branch(void);
|
||||
int kvmppc_enable_hwrng(void);
|
||||
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
|
||||
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
|
||||
@ -290,6 +293,21 @@ static inline bool kvmppc_has_cap_mmu_hash_v3(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_cap_safe_cache(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_cap_safe_bounds_check(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_cap_safe_indirect_branch(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kvmppc_enable_hwrng(void)
|
||||
{
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user