[Qemu-devel] [Bug 1649040] [NEW] Ubuntu 16.04.1 Grub Splash Doesn't Appear
Public bug reported: My Specs: Slackware 14.2 x86_64 > Host QEMU 2.7.0 Ubuntu 16.04.1 x86_64 > Guest Start options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 I've started Ubuntu around 6-8 times, and I have only see the Grub Boot Splash appear twice, so pretty much without fail it typically boots past the grub splash and automatically boots... These are the /etc/default/grub settings; (I only changed these options GRUB_TIMEOUT=15 and GRUB_GFXMODE=1440x900) # If you change this file, run 'update-grub' afterwards to update # /boot/grub/grub.cfg. # For full documentation of the options in this file, see: # info -f grub -n 'Simple configuration' GRUB_DEFAULT=0 GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT_QUIET=true GRUB_TIMEOUT=15 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDLINE_LINUX="" # Uncomment to enable BadRAM filtering, modify to suit your needs # This works with Linux (no patch required) and with any kernel that obtains # the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...) #GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef" # Uncomment to disable graphical terminal (grub-pc only) #GRUB_TERMINAL=console # The resolution used on graphical terminal # note that you can use only modes which your graphic card supports via VBE # you can see them in real GRUB with the command `vbeinfo' GRUB_GFXMODE=1440x900 # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux #GRUB_DISABLE_LINUX_UUID=true # Uncomment to disable generation of recovery mode menu entries #GRUB_DISABLE_RECOVERY="true" # Uncomment to get a beep at grub start #GRUB_INIT_TUNE="480 440 1" ** Affects: qemu Importance: Undecided Status: New ** Description changed: My Specs: Slackware 14.2 x86_64 > Host - QEMU 2.7.0 + QEMU 2.7.0 - Ubuntu 16.04.1 > Guest + Ubuntu 16.04.1 x86_64 > Guest Start options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 - I've started Ubuntu around 6-8 times, and I have only see the Grub Boot Splash appear twice, so pretty much without fail it typically boots past the grub splash and automatically boots... - - These are the /etc/default/grub settings; (I only changed these options GRUB_TIMEOUT=15 and GRUB_GFXMODE=1440x900) - + These are the /etc/default/grub settings; (I only changed these options + GRUB_TIMEOUT=15 and GRUB_GFXMODE=1440x900) # If you change this file, run 'update-grub' afterwards to update # /boot/grub/grub.cfg. # For full documentation of the options in this file, see: # info -f grub -n 'Simple configuration' GRUB_DEFAULT=0 GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT_QUIET=true GRUB_TIMEOUT=15 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDLINE_LINUX="" # Uncomment to enable BadRAM filtering, modify to suit your needs # This works with Linux (no patch required) and with any kernel that obtains # the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...) #GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef" # Uncomment to disable graphical terminal (grub-pc only) #GRUB_TERMINAL=console # The resolution used on graphical terminal # note that you can use only modes which your graphic card supports via VBE # you can see them in real GRUB with the command `vbeinfo' GRUB_GFXMODE=1440x900 # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux #GRUB_DISABLE_LINUX_UUID=true # Uncomment to disable generation of recovery mode menu entries #GRUB_DISABLE_RECOVERY="true" # Uncomment to get a beep at grub start #GRUB_INIT_TUNE="480 440 1" -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1649040 Title: Ubuntu 16.04.1 Grub Splash Doesn't Appear Status in QEMU: New Bug description: My Specs: Slackware 14.2 x86_64 > Host QEMU 2.7.0 Ubuntu 16.04.1 x86_64 > Guest Start options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 I've started Ubuntu around 6-8 times, and I have only see the Grub Boot Splash appear twice, so pretty much without fail it typically boots past the grub splash and automatically boots... These are the /etc/default/grub settings; (I only changed these options GRUB_TIMEOUT=15 and GRUB_GFXMODE=144
[Qemu-devel] [Bug 1649042] [NEW] Ubuntu 16.04.1 LightDM Resolution Not Correct
Public bug reported: My Specs: Slackware 14.2 x86_64 > Host Nvidia GPU GTX660M nvidia-driver-352.63 QEMU 2.7.0 Ubuntu 16.04.1 x86_64 > Guest Unity Xorg nouveau - 1:1.0.12-1build2 These are the startup options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 Unity desktop resolution set for 1440x900. I noticed when I come to the login screen to enter my password the LightDM resolution fills my entire desktop. I searched online and found this solution; cp ~/.config/monitor.xml /var/lib/lightdm/.config For now I'm assuming this step should not be needed and the resolution should be correctly detected and set? ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1649042 Title: Ubuntu 16.04.1 LightDM Resolution Not Correct Status in QEMU: New Bug description: My Specs: Slackware 14.2 x86_64 > Host Nvidia GPU GTX660M nvidia-driver-352.63 QEMU 2.7.0 Ubuntu 16.04.1 x86_64 > Guest Unity Xorg nouveau - 1:1.0.12-1build2 These are the startup options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 Unity desktop resolution set for 1440x900. I noticed when I come to the login screen to enter my password the LightDM resolution fills my entire desktop. I searched online and found this solution; cp ~/.config/monitor.xml /var/lib/lightdm/.config For now I'm assuming this step should not be needed and the resolution should be correctly detected and set? To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1649042/+subscriptions
Re: [Qemu-devel] [for-2.9 2/5] pseries: Stubs for HPT resizing
On Fri, Dec 09, 2016 at 11:08:02AM -0600, Michael Roth wrote: > Quoting David Gibson (2016-12-08 20:23:11) > > This introduces stub implementations of the H_RESIZE_HPT_PREPARE and > > H_RESIZE_HPT_COMMIT hypercalls which we hope to add in a PAPR > > extension to allow run time resizing of a guest's hash page table. It > > also adds a new machine property for controlling whether this new > > facility is available, and logic to check that against availability > > with KVM (only supported with KVM PR for now). > > > > Finally, it adds a new string to the hypertas property in the device > > tree, advertising to the guest the availability of the HPT resizing > > hypercalls. This is a tentative suggested value, and would need to be > > standardized by PAPR before being merged. > > > > Signed-off-by: David Gibson > > --- > > hw/ppc/spapr.c | 66 > > ++ > > hw/ppc/spapr_hcall.c | 36 +++ > > hw/ppc/trace-events| 2 ++ > > include/hw/ppc/spapr.h | 11 + > > target-ppc/kvm.c | 26 > > target-ppc/kvm_ppc.h | 5 > > 6 files changed, 146 insertions(+) > > > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > > index 0f25e83..ecb0822 100644 > > --- a/hw/ppc/spapr.c > > +++ b/hw/ppc/spapr.c > > @@ -760,6 +760,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, > > void *fdt) > > if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { > > add_str(hypertas, "hcall-multi-tce"); > > } > > + > > +if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { > > +add_str(hypertas, "hcall-hpt-resize"); > > +} > > + > > _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", > > hypertas->str, hypertas->len)); > > g_string_free(hypertas, TRUE); > > @@ -1839,11 +1844,31 @@ static void ppc_spapr_init(MachineState *machine) > > long load_limit, fw_size; > > char *filename; > > int smt = kvmppc_smt_threads(); > > +Error *resize_hpt_err = NULL; > > > > msi_nonbroken = true; > > > > QLIST_INIT(&spapr->phbs); > > > > +/* Check HPT resizing availability */ > > +kvmppc_check_papr_resize_hpt(&resize_hpt_err); > > +if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { > > +if (resize_hpt_err) { > > +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; > > +error_free(resize_hpt_err); > > +resize_hpt_err = NULL; > > +} else { > > +spapr->resize_hpt = smc->resize_hpt_default; > > +} > > +} > > + > > +assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); > > + > > +if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && > > resize_hpt_err) { > > +error_report_err(resize_hpt_err); > > +exit(1); > > +} > > I'm also a bit confused by this. Aren't semantics that HPT_ENABLED will allow > a fallback to non-resizable HPTs if the feature isn't available (whereas > HPT_REQUIRED won't)? I don't understand how such a fallback can ever be > reached > with this check in place. resize-hpt=enabled means we'll fall back if the guest doesn't support it. An error here means the _host_ can't support it. I think not falling back is the better option in this case - if you've explicitly tried to enable it from it should be available or fail. In particular this will make it safer for migrations where the source is already using hpt resizing. > > + > > /* Allocate RMA if necessary */ > > rma_alloc_size = kvmppc_alloc_rma(&rma); > > > > @@ -2236,6 +2261,40 @@ static void spapr_set_modern_hotplug_events(Object > > *obj, bool value, > > spapr->use_hotplug_event_source = value; > > } > > > > +static char *spapr_get_resize_hpt(Object *obj, Error **errp) > > +{ > > +sPAPRMachineState *spapr = SPAPR_MACHINE(obj); > > + > > +switch (spapr->resize_hpt) { > > +case SPAPR_RESIZE_HPT_DEFAULT: > > +return g_strdup("default"); > > +case SPAPR_RESIZE_HPT_DISABLED: > > +return g_strdup("disabled"); > > +case SPAPR_RESIZE_HPT_ENABLED: > > +return g_strdup("enabled"); > > +case SPAPR_RESIZE_HPT_REQUIRED: > > +return g_strdup("required"); > > +} > > +assert(0); > > +} > > + > > +static void spapr_set_resize_hpt(Object *obj, const char *value, Error > > **errp) > > +{ > > +sPAPRMachineState *spapr = SPAPR_MACHINE(obj); > > + > > +if (strcmp(value, "default") == 0) { > > +spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; > > +} else if (strcmp(value, "disabled") == 0) { > > +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; > > +} else if (strcmp(value, "enabled") == 0) { > > +spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; > > +} else if (strcmp(value, "required") == 0) { > > +spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; > > +} else { > > +error_setg(errp, "Bad value for \"resize-hpt\" property"); > > +}
[Qemu-devel] [PATCH v6 04/10] tcg-mips: Add bswap32u and bswap64
Without the mips32r2 instructions to perform swapping, bswap is quite large, dominating the size of each reverse-endian qemu_ld/qemu_st operation. Create two subroutines in the prologue block. The subroutines require extra reserved registers (TCG_TMP[2, 3]). Using these within qemu_ld means that we need not place additional restrictions on the qemu_ld outputs. Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.inc.c | 102 -- 1 file changed, 99 insertions(+), 3 deletions(-) diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index 2d91d0c..ec139cd 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -125,6 +125,8 @@ static const TCGReg tcg_target_call_oarg_regs[2] = { static tcg_insn_unit *tb_ret_addr; static tcg_insn_unit *bswap32_addr; +static tcg_insn_unit *bswap32u_addr; +static tcg_insn_unit *bswap64_addr; static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target) { @@ -622,7 +624,10 @@ static void tcg_out_bswap32u(TCGContext *s, TCGReg ret, TCGReg arg) tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret); tcg_out_dsrl(s, ret, ret, 32); } else { -abort(); +tcg_out_bswap_subr(s, bswap32u_addr); +/* delay slot -- never omit the insn, like tcg_out_mov might. */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO); +tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3); } } @@ -632,7 +637,10 @@ static void tcg_out_bswap64(TCGContext *s, TCGReg ret, TCGReg arg) tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg); tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret); } else { -abort(); +tcg_out_bswap_subr(s, bswap64_addr); +/* delay slot -- never omit the insn, like tcg_out_mov might. */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO); +tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3); } } @@ -2279,7 +2287,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) return; } -/* Bswap subroutine: Input in TCG_TMP0, output in TCG_TMP3; +/* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3; clobbers TCG_TMP1, TCG_TMP2. */ /* @@ -2305,6 +2313,94 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0); /* t3 = dcba -- delay slot */ tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1); + +if (TCG_TARGET_REG_BITS == 32) { +return; +} + +/* + * bswap32u -- unsigned 32-bit swap. a0 = abcd. + */ +bswap32u_addr = align_code_ptr(s); +/* t1 = ()000d */ +tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff); +/* t3 = 000a */ +tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24); +/* t1 = ()d000 */ +tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24); +/* t2 = 00c0 */ +tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00); +/* t3 = d00a */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1); +/* t1 = 0abc */ +tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8); +/* t2 = 0c00 */ +tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8); +/* t1 = 00b0 */ +tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00); +/* t3 = dc0a */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2); +tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0); +/* t3 = dcba -- delay slot */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1); + +/* + * bswap64 -- 64-bit swap. a0 = abcdefgh + */ +bswap64_addr = align_code_ptr(s); +/* t3 = h000 */ +tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56); +/* t1 = 000a */ +tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56); + +/* t2 = 00g0 */ +tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00); +/* t3 = h00a */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1); +/* t1 = 0abc */ +tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40); +/* t2 = 0g00 */ +tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40); +/* t1 = 00b0 */ +tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00); + +/* t3 = hg0a */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2); +/* t2 = abcd */ +tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32); +/* t3 = hgba */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1); + +/* t1 = 00c0 */ +tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00); +/* t2 = 000d */ +tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff); +/* t1 = 0c00 */ +tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8); +/* t2 = d000 */ +tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24); + +/* t3 = hg000cba */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1); +/* t1 = 00abcdef */ +tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 1
[Qemu-devel] [PATCH v6 05/10] tcg-mips: Adjust move functions for mips64
tcg_out_mov: using OPC_OR as most mips assemblers do; tcg_out_movi: extended to 64-bit immediate. Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.inc.c | 34 +- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index ec139cd..18368f0 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -544,23 +544,39 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type, { /* Simple reg-reg move, optimising out the 'do nothing' case */ if (ret != arg) { -tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO); +tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO); } } -static inline void tcg_out_movi(TCGContext *s, TCGType type, -TCGReg reg, tcg_target_long arg) +static void tcg_out_movi(TCGContext *s, TCGType type, + TCGReg ret, tcg_target_long arg) { +if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { +arg = (int32_t)arg; +} if (arg == (int16_t)arg) { -tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg); -} else if (arg == (uint16_t)arg) { -tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg); +tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg); +return; +} +if (arg == (uint16_t)arg) { +tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg); +return; +} +if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) { +tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16); } else { -tcg_out_opc_imm(s, OPC_LUI, reg, TCG_REG_ZERO, arg >> 16); -if (arg & 0x) { -tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0x); +tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1); +if (arg & 0xull) { +tcg_out_dsll(s, ret, ret, 16); +tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16); +tcg_out_dsll(s, ret, ret, 16); +} else { +tcg_out_dsll(s, ret, ret, 32); } } +if (arg & 0x) { +tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0x); +} } static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg) -- 2.1.0
[Qemu-devel] [PATCH v6 01/10] tcg-mips: Move bswap code to a subroutine
Without the mips32r2 instructions to perform swapping, bswap is quite large, dominating the size of each reverse-endian qemu_ld/qemu_st operation. Create a subroutine in the prologue block. The subroutine requires extra reserved registers (TCG_TMP[2, 3]). Using these within qemu_ld means that we need not place additional restrictions on the qemu_ld outputs. Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.h | 2 +- tcg/mips/tcg-target.inc.c | 207 ++ 2 files changed, 139 insertions(+), 70 deletions(-) diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 3aeac87..a6871fb 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -117,11 +117,11 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_muls2_i32(!use_mips32r6_instructions) #define TCG_TARGET_HAS_muluh_i321 #define TCG_TARGET_HAS_mulsh_i321 +#define TCG_TARGET_HAS_bswap32_i32 1 /* optional instructions detected at runtime */ #define TCG_TARGET_HAS_movcond_i32 use_movnz_instructions #define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_bswap32_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_deposit_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_ext8s_i32use_mips32r2_instructions #define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index abce602..2b116ea 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -74,6 +74,8 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { #define TCG_TMP0 TCG_REG_AT #define TCG_TMP1 TCG_REG_T9 +#define TCG_TMP2 TCG_REG_T8 +#define TCG_TMP3 TCG_REG_T7 /* check if we really need so many registers :P */ static const int tcg_target_reg_alloc_order[] = { @@ -122,6 +124,7 @@ static const TCGReg tcg_target_call_oarg_regs[2] = { }; static tcg_insn_unit *tb_ret_addr; +static tcg_insn_unit *bswap32_addr; static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target) { @@ -177,12 +180,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ct->ct |= TCG_CT_REG; tcg_regset_set(ct->u.regs, 0x); break; -case 'L': /* qemu_ld output arg constraint */ -ct->ct |= TCG_CT_REG; -tcg_regset_set(ct->u.regs, 0x); -tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0); -break; -case 'l': /* qemu_ld input arg constraint */ +case 'L': /* qemu_ld input arg constraint */ ct->ct |= TCG_CT_REG; tcg_regset_set(ct->u.regs, 0x); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); @@ -513,29 +511,22 @@ static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg) } } -static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) +static void tcg_out_bswap_subr(TCGContext *s, tcg_insn_unit *sub) +{ +bool ok = tcg_out_opc_jmp(s, OPC_JAL, sub); +tcg_debug_assert(ok); +} + +static void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) { if (use_mips32r2_instructions) { tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16); } else { -/* ret and arg must be different and can't be register at */ -if (ret == arg || ret == TCG_TMP0 || arg == TCG_TMP0) { -tcg_abort(); -} - -tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); - -tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 24); -tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); - -tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, arg, 0xff00); -tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8); -tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); - -tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8); -tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0xff00); -tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); +tcg_out_bswap_subr(s, bswap32_addr); +/* delay slot -- never omit the insn, like tcg_out_mov might. */ +tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO); +tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3); } } @@ -1044,7 +1035,7 @@ static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah) } /* Perform the tlb comparison operation. The complete host address is - placed in BASE. Clobbers AT, T0, A0. */ + placed in BASE. Clobbers TMP0, TMP1, A0. */ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl, TCGReg addrh, TCGMemOpIdx oi, tcg_insn_unit *label_ptr[2], bool is_load) @@ -1227,46 +1218,72 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) } #endif -static voi
[Qemu-devel] [PATCH v6 02/10] tcg-mips: Add mips64 opcodes
Since the mips manual tables are in octal, reorg all of the opcodes into that format for clarity. Note that the 64-bit opcodes are as yet unused. Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.inc.c | 193 -- 1 file changed, 118 insertions(+), 75 deletions(-) diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index 2b116ea..fb84ea5 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -254,81 +254,118 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type, /* instruction opcodes */ typedef enum { -OPC_J= 0x02 << 26, -OPC_JAL = 0x03 << 26, -OPC_BEQ = 0x04 << 26, -OPC_BNE = 0x05 << 26, -OPC_BLEZ = 0x06 << 26, -OPC_BGTZ = 0x07 << 26, -OPC_ADDIU= 0x09 << 26, -OPC_SLTI = 0x0A << 26, -OPC_SLTIU= 0x0B << 26, -OPC_ANDI = 0x0C << 26, -OPC_ORI = 0x0D << 26, -OPC_XORI = 0x0E << 26, -OPC_LUI = 0x0F << 26, -OPC_LB = 0x20 << 26, -OPC_LH = 0x21 << 26, -OPC_LW = 0x23 << 26, -OPC_LBU = 0x24 << 26, -OPC_LHU = 0x25 << 26, -OPC_LWU = 0x27 << 26, -OPC_SB = 0x28 << 26, -OPC_SH = 0x29 << 26, -OPC_SW = 0x2B << 26, - -OPC_SPECIAL = 0x00 << 26, -OPC_SLL = OPC_SPECIAL | 0x00, -OPC_SRL = OPC_SPECIAL | 0x02, -OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02, -OPC_SRA = OPC_SPECIAL | 0x03, -OPC_SLLV = OPC_SPECIAL | 0x04, -OPC_SRLV = OPC_SPECIAL | 0x06, -OPC_ROTRV= OPC_SPECIAL | (0x01 << 6) | 0x06, -OPC_SRAV = OPC_SPECIAL | 0x07, -OPC_JR_R5= OPC_SPECIAL | 0x08, -OPC_JALR = OPC_SPECIAL | 0x09, -OPC_MOVZ = OPC_SPECIAL | 0x0A, -OPC_MOVN = OPC_SPECIAL | 0x0B, -OPC_SYNC = OPC_SPECIAL | 0x0F, -OPC_MFHI = OPC_SPECIAL | 0x10, -OPC_MFLO = OPC_SPECIAL | 0x12, -OPC_MULT = OPC_SPECIAL | 0x18, -OPC_MUL_R6 = OPC_SPECIAL | (0x02 << 6) | 0x18, -OPC_MUH = OPC_SPECIAL | (0x03 << 6) | 0x18, -OPC_MULTU= OPC_SPECIAL | 0x19, -OPC_MULU = OPC_SPECIAL | (0x02 << 6) | 0x19, -OPC_MUHU = OPC_SPECIAL | (0x03 << 6) | 0x19, -OPC_DIV = OPC_SPECIAL | 0x1A, -OPC_DIV_R6 = OPC_SPECIAL | (0x02 << 6) | 0x1A, -OPC_MOD = OPC_SPECIAL | (0x03 << 6) | 0x1A, -OPC_DIVU = OPC_SPECIAL | 0x1B, -OPC_DIVU_R6 = OPC_SPECIAL | (0x02 << 6) | 0x1B, -OPC_MODU = OPC_SPECIAL | (0x03 << 6) | 0x1B, -OPC_ADDU = OPC_SPECIAL | 0x21, -OPC_SUBU = OPC_SPECIAL | 0x23, -OPC_AND = OPC_SPECIAL | 0x24, -OPC_OR = OPC_SPECIAL | 0x25, -OPC_XOR = OPC_SPECIAL | 0x26, -OPC_NOR = OPC_SPECIAL | 0x27, -OPC_SLT = OPC_SPECIAL | 0x2A, -OPC_SLTU = OPC_SPECIAL | 0x2B, -OPC_SELEQZ = OPC_SPECIAL | 0x35, -OPC_SELNEZ = OPC_SPECIAL | 0x37, - -OPC_REGIMM = 0x01 << 26, -OPC_BLTZ = OPC_REGIMM | (0x00 << 16), -OPC_BGEZ = OPC_REGIMM | (0x01 << 16), - -OPC_SPECIAL2 = 0x1c << 26, -OPC_MUL_R5 = OPC_SPECIAL2 | 0x002, - -OPC_SPECIAL3 = 0x1f << 26, -OPC_EXT = OPC_SPECIAL3 | 0x000, -OPC_INS = OPC_SPECIAL3 | 0x004, -OPC_WSBH = OPC_SPECIAL3 | 0x0a0, -OPC_SEB = OPC_SPECIAL3 | 0x420, -OPC_SEH = OPC_SPECIAL3 | 0x620, +OPC_J= 002 << 26, +OPC_JAL = 003 << 26, +OPC_BEQ = 004 << 26, +OPC_BNE = 005 << 26, +OPC_BLEZ = 006 << 26, +OPC_BGTZ = 007 << 26, +OPC_ADDIU= 011 << 26, +OPC_SLTI = 012 << 26, +OPC_SLTIU= 013 << 26, +OPC_ANDI = 014 << 26, +OPC_ORI = 015 << 26, +OPC_XORI = 016 << 26, +OPC_LUI = 017 << 26, +OPC_DADDIU = 031 << 26, +OPC_LB = 040 << 26, +OPC_LH = 041 << 26, +OPC_LW = 043 << 26, +OPC_LBU = 044 << 26, +OPC_LHU = 045 << 26, +OPC_LWU = 047 << 26, +OPC_SB = 050 << 26, +OPC_SH = 051 << 26, +OPC_SW = 053 << 26, +OPC_LD = 067 << 26, +OPC_SD = 077 << 26, + +OPC_SPECIAL = 000 << 26, +OPC_SLL = OPC_SPECIAL | 000, +OPC_SRL = OPC_SPECIAL | 002, +OPC_ROTR = OPC_SPECIAL | 002 | (1 << 21), +OPC_SRA = OPC_SPECIAL | 003, +OPC_SLLV = OPC_SPECIAL | 004, +OPC_SRLV = OPC_SPECIAL | 006, +OPC_ROTRV= OPC_SPECIAL | 006 | 0100, +OPC_SRAV = OPC_SPECIAL | 007, +OPC_JR_R5= OPC_SPECIAL | 010, +OPC_JALR = OPC_SPECIAL | 011, +OPC_MOVZ = OPC_SPECIAL | 012, +OPC_MOVN = OPC_SPECIAL | 013, +OPC_SYNC = OPC_SPECIAL | 017, +OPC_MFHI = OPC_SPECIAL | 020, +OPC_MFLO = OPC_SPECIAL | 022, +OPC_DSLLV= OPC_SPECIAL | 024, +
[Qemu-devel] [PATCH v6 03/10] tcg-mips: Support 64-bit opcodes
Bulk patch adding 64-bit opcodes into tcg_out_op. Note that mips64 is as yet neither complete nor enabled. Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.h | 41 ++ tcg/mips/tcg-target.inc.c | 322 -- 2 files changed, 353 insertions(+), 10 deletions(-) diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index a6871fb..4b7d3ae 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -27,6 +27,7 @@ #ifndef MIPS_TCG_TARGET_H #define MIPS_TCG_TARGET_H +#define TCG_TARGET_REG_BITS 32 #define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 16 #define TCG_TARGET_NB_REGS 32 @@ -119,6 +120,29 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_mulsh_i321 #define TCG_TARGET_HAS_bswap32_i32 1 +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_extrl_i64_i321 +#define TCG_TARGET_HAS_extrh_i64_i321 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_nor_i64 1 +#define TCG_TARGET_HAS_andc_i64 0 +#define TCG_TARGET_HAS_orc_i64 0 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64(!use_mips32r6_instructions) +#define TCG_TARGET_HAS_muls2_i64(!use_mips32r6_instructions) +#define TCG_TARGET_HAS_muluh_i641 +#define TCG_TARGET_HAS_mulsh_i641 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#endif + /* optional instructions detected at runtime */ #define TCG_TARGET_HAS_movcond_i32 use_movnz_instructions #define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions @@ -127,11 +151,28 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_movcond_i64 use_movnz_instructions +#define TCG_TARGET_HAS_bswap16_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_bswap32_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_bswap64_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_deposit_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_ext8s_i64use_mips32r2_instructions +#define TCG_TARGET_HAS_ext16s_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_rot_i64 use_mips32r2_instructions +#endif + /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */ #define TCG_TARGET_HAS_ext8u_i320 /* andi rt, rs, 0xff */ #define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0x */ +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_neg_i64 0 /* sub rd, zero, rt */ +#define TCG_TARGET_HAS_ext8u_i640 /* andi rt, rs, 0xff */ +#define TCG_TARGET_HAS_ext16u_i64 0 /* andi rt, rs, 0x */ +#endif + #ifdef __OpenBSD__ #include #else diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index fb84ea5..2d91d0c 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -437,6 +437,21 @@ static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt, tcg_out32(s, inst); } +static inline void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm, +MIPSInsn oph, TCGReg rt, TCGReg rs, +int msb, int lsb) +{ +if (lsb >= 32) { +opc = oph; +msb -= 32; +lsb -= 32; +} else if (msb >= 32) { +opc = opm; +msb -= 32; +} +tcg_out_opc_bf(s, opc, rt, rs, msb, lsb); +} + /* * Type branch */ @@ -467,6 +482,18 @@ static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc, } +static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2, + TCGReg rd, TCGReg rt, TCGArg sa) +{ +int32_t inst; + +inst = (sa & 32 ? opc2 : opc1); +inst |= (rt & 0x1F) << 16; +inst |= (rd & 0x1F) << 11; +inst |= (sa & 0x1F) << 6; +tcg_out32(s, inst); +} + /* * Type jump. * Returns true if the branch was in range and the insn was emitted. @@ -495,6 +522,21 @@ static inline void tcg_out_nop(TCGContext *s) tcg_out32(s, 0); } +static inline void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa) +{ +tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa); +} + +static inline void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa) +{ +tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSR
[Qemu-devel] [PATCH v6 08/10] tcg-mips: Add tcg unwind info
Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.inc.c | 44 1 file changed, 44 insertions(+) diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index 9e24662..b7e2586 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -2465,3 +2465,47 @@ void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) atomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2)); flush_icache_range(jmp_addr, jmp_addr + 4); } + +typedef struct { +DebugFrameHeader h; +uint8_t fde_def_cfa[4]; +uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; +} DebugFrame; + +#define ELF_HOST_MACHINE EM_MIPS +/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS, + which is good because they're really quite complicated for MIPS. */ + +static const DebugFrame debug_frame = { +.h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ +.h.cie.id = -1, +.h.cie.version = 1, +.h.cie.code_align = 1, +.h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ +.h.cie.return_column = TCG_REG_RA, + +/* Total FDE size does not include the "len" member. */ +.h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), + +.fde_def_cfa = { +12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ +(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ +(FRAME_SIZE >> 7) +}, +.fde_reg_ofs = { +0x80 + 16, 9, /* DW_CFA_offset, s0, -72 */ +0x80 + 17, 8, /* DW_CFA_offset, s2, -64 */ +0x80 + 18, 7, /* DW_CFA_offset, s3, -56 */ +0x80 + 19, 6, /* DW_CFA_offset, s4, -48 */ +0x80 + 20, 5, /* DW_CFA_offset, s5, -40 */ +0x80 + 21, 4, /* DW_CFA_offset, s6, -32 */ +0x80 + 22, 3, /* DW_CFA_offset, s7, -24 */ +0x80 + 30, 2, /* DW_CFA_offset, s8, -16 */ +0x80 + 31, 1, /* DW_CFA_offset, ra, -8 */ +} +}; + +void tcg_register_jit(void *buf, size_t buf_size) +{ +tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); +} -- 2.1.0
[Qemu-devel] [PATCH v6 00/10] tcg mips64 and mips r6 improvements
Changes in v6: * Update against master(v2.8.0-rc3) * Fix two bugs according to Richard Henderson's review comments (1) mask: extend TARGET_PAGE_MASK to the proper type (2) zero-extend the guest address, not the address loaded from CMP_OFF * MIPS R6: tested successfully on a qemu mipsel64r6 host (emulating I6400) - Debian amd64 with qemu-system-x86_64 Changes in v5: * Update against master(v2.8.0-rc2) * Fix a bug: 64-bit big-endian guests hang on mips64 little-endian hosts, and vice versa. This bug was first introduced in v2 patch, due to obvious misuse of ret/arg registers in tcg_out_bswap64(). tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg); - tcg_out_opc_reg(s, OPC_DSHD, ret, 0, arg); + tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret); * Fix a style problem: checkpatch.pl forbids 'extern' to be used in .c. ERROR: externs should be avoided in .c files #28: FILE: tcg/mips/tcg-target.inc.c:39: +extern int link_error(void); Simply comment the type identifier to pass the check. * Tested successfully on following machines: | HOST| qemu-system | Debian ISO | |-| | mips 32 le |i386 |i386 | | mips 32 le |x86_64 |i386 | | mips 32 le |x86_64 |amd64| | mips 64 le |i386 |i386 | | mips 64 le |x86_64 |i386 | | mips 64 le |x86_64 |amd64| | mips 64 le | mips 64 be | mips 64 be | |-| | mips 32 be |i386 | i386| | mips 32 be |x86_64 | i386| | mips 32 be |x86_64 | amd64 | | mips 64 be |i386 | i386| | mips 64 be |x86_64 | i386| | mips 64 be |x86_64 | amd64 | | mips n32 be |386 | i386| | mips n32 be |x86_64 | i386| | mips n32 be |x86_64 | amd64 | (No plan to test MIPS R6 in this patch.) Summary of changes from v4: | tcg-mips: Support 64-bit opcodes | Fix tcg_out_bswap64() | | tcg-mips: Adjust qemu_ld/st for mips64 | Fix a style problem | Changes in v4: * tcg_out_qemu_ld_slow_path: always sign-extend 32-bit loads. Provide a better solution than patch11 in v3. Fix the blocking bug when emulating i386 kernel on mips64el. * Redefine LO_OFF/HI_OFF as v2. On mips64 host, they are defined as link_error, to ensure that all paths that lead to the use of the symbol are eliminated by the compiler. Changes in v3: * Update against master(v2.8.0-rc1) * Tested on Loongson as mips32r2(el) and mips64r2(el) hosts. Loongson only implements little-endian mips32/mips64 ISA. * Fully work for 32-bit and 64-bit guests. Fix two bugs:segmentation fault on mips64el with 32-bit guests, blocking when emulating i386 kernel on mips64el. * Fix some minor style problems. * PATCH v2 12~16 are not examined due to the lack of R6 machine. Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie Jin Guojie (10): tcg-mips: Move bswap code to a subroutine tcg-mips: Add mips64 opcodes tcg-mips: Support 64-bit opcodes tcg-mips: Add bswap32u and bswap64 tcg-mips: Adjust move functions for mips64 tcg-mips: Adjust load/store functions for mips64 tcg-mips: Adjust prologue for mips64 tcg-mips: Add tcg unwind info tcg-mips: Adjust calling conventions for mips64 tcg-mips: Adjust qemu_ld/st for mips64 tcg/mips/tcg-target.h | 60 ++- tcg/mips/tcg-target.inc.c | 1170 +++-- 2 files changed, 977 insertions(+), 253 deletions(-) -- 2.1.0
[Qemu-devel] [PATCH v6 10/10] tcg-mips: Adjust qemu_ld/st for mips64
Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.inc.c | 203 +- 1 file changed, 146 insertions(+), 57 deletions(-) diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index 7282a4a..b992852 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -32,8 +32,16 @@ # define MIPS_BE 0 #endif -#define LO_OFF(MIPS_BE * 4) -#define HI_OFF(4 - LO_OFF) +#if TCG_TARGET_REG_BITS == 32 +# define LO_OFF (MIPS_BE * 4) +# define HI_OFF (4 - LO_OFF) +#else +/* To assert at compile-time that these values were never used + for TCG_TARGET_REGS == 64 */ +/* extern */ int link_error(void); +# define LO_OFF link_error() +# define HI_OFF link_error() +#endif #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -193,7 +201,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set(ct->u.regs, 0x); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); #if defined(CONFIG_SOFTMMU) -if (TARGET_LONG_BITS == 64) { +if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); } #endif @@ -203,11 +211,11 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set(ct->u.regs, 0x); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); #if defined(CONFIG_SOFTMMU) -if (TARGET_LONG_BITS == 32) { -tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1); -} else { +if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3); +} else { +tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1); } #endif break; @@ -1104,6 +1112,10 @@ static void * const qemu_ld_helpers[16] = { [MO_BESW] = helper_be_ldsw_mmu, [MO_BEUL] = helper_be_ldul_mmu, [MO_BEQ] = helper_be_ldq_mmu, +#if TCG_TARGET_REG_BITS == 64 +[MO_LESL] = helper_le_ldsl_mmu, +[MO_BESL] = helper_be_ldsl_mmu, +#endif }; static void * const qemu_st_helpers[16] = { @@ -1131,6 +1143,9 @@ static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg) if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) { tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg); } else { +/* For N32 and N64, the initial offset is different. But there + we also have 8 argument register so we don't run out here. */ +tcg_debug_assert(TCG_TARGET_REG_BITS == 32); tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i); } return i + 1; @@ -1172,6 +1187,7 @@ static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg) static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah) { +tcg_debug_assert(TCG_TARGET_REG_BITS == 32); i = (i + 1) & ~1; i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al)); i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah)); @@ -1179,7 +1195,7 @@ static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah) } /* Perform the tlb comparison operation. The complete host address is - placed in BASE. Clobbers TMP0, TMP1, A0. */ + placed in BASE. Clobbers TMP0, TMP1, TMP2, A0. */ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl, TCGReg addrh, TCGMemOpIdx oi, tcg_insn_unit *label_ptr[2], bool is_load) @@ -1187,6 +1203,7 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl, TCGMemOp opc = get_memop(oi); unsigned s_bits = opc & MO_SIZE; unsigned a_bits = get_alignment_bits(opc); +target_ulong mask; int mem_index = get_mmuidx(oi); int cmp_off = (is_load @@ -1194,11 +1211,11 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl, : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write)); int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend); -tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addrl, +tcg_out_opc_sa(s, ALIAS_TSRL, TCG_REG_A0, addrl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); -tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0); +tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, TCG_REG_A0, TCG_AREG0); /* Compensate for very large offsets. */ if (add_off >= 0x8000) { @@ -1208,51 +1225,63 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl, QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
[Qemu-devel] [PATCH v6 06/10] tcg-mips: Adjust load/store functions for mips64
tcg_out_ldst: using a generic ALIAS_PADD to avoid ifdefs tcg_out_ld: generates LD or LW tcg_out_st: generates SD or SW Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.inc.c | 14 +++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index 18368f0..5cc8df3 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -697,7 +697,7 @@ static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data, if (ofs != lo) { tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo); if (addr != TCG_REG_ZERO) { -tcg_out_opc_reg(s, OPC_ADDU, TCG_TMP0, TCG_TMP0, addr); +tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP0, TCG_TMP0, addr); } addr = TCG_TMP0; } @@ -707,13 +707,21 @@ static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data, static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, intptr_t arg2) { -tcg_out_ldst(s, OPC_LW, arg, arg1, arg2); +MIPSInsn opc = OPC_LD; +if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) { +opc = OPC_LW; +} +tcg_out_ldst(s, opc, arg, arg1, arg2); } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, intptr_t arg2) { -tcg_out_ldst(s, OPC_SW, arg, arg1, arg2); +MIPSInsn opc = OPC_SD; +if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) { +opc = OPC_SW; +} +tcg_out_ldst(s, opc, arg, arg1, arg2); } static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, -- 2.1.0
[Qemu-devel] [PATCH v6 07/10] tcg-mips: Adjust prologue for mips64
Take stack frame parameters out from the function body. Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.inc.c | 54 ++- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index 5cc8df3..9e24662 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -734,16 +734,6 @@ static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, return false; } -static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val) -{ -if (val == (int16_t)val) { -tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val); -} else { -tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, val); -tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_TMP0); -} -} - static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al, TCGReg ah, TCGArg bl, TCGArg bh, bool cbl, bool cbh, bool is_sub) @@ -2270,42 +2260,48 @@ static tcg_insn_unit *align_code_ptr(TCGContext *s) return s->code_ptr; } +/* Stack frame parameters. */ +#define REG_SIZE (TCG_TARGET_REG_BITS / 8) +#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) +#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) + +#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ + + TCG_TARGET_STACK_ALIGN - 1) \ +& -TCG_TARGET_STACK_ALIGN) +#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) + +/* We're expecting to be able to use an immediate for frame allocation. */ +QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff); + /* Generate global QEMU prologue and epilogue code */ static void tcg_target_qemu_prologue(TCGContext *s) { -int i, frame_size; +int i; -/* reserve some stack space, also for TCG temps. */ -frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4 - + TCG_STATIC_CALL_ARGS_SIZE - + CPU_TEMP_BUF_NLONGS * sizeof(long); -frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & - ~(TCG_TARGET_STACK_ALIGN - 1); -tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4 - + TCG_STATIC_CALL_ARGS_SIZE, - CPU_TEMP_BUF_NLONGS * sizeof(long)); +tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); /* TB prologue */ -tcg_out_addi(s, TCG_REG_SP, -frame_size); -for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) { -tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i], - TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4); +tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); +for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { +tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], + TCG_REG_SP, SAVE_OFS + i * REG_SIZE); } /* Call generated code */ tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0); +/* delay slot */ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); -tb_ret_addr = s->code_ptr; /* TB epilogue */ -for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) { -tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i], - TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4); +tb_ret_addr = s->code_ptr; +for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { +tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], + TCG_REG_SP, SAVE_OFS + i * REG_SIZE); } tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0); /* delay slot */ -tcg_out_addi(s, TCG_REG_SP, frame_size); +tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); if (use_mips32r2_instructions) { return; -- 2.1.0
[Qemu-devel] [PATCH v6 09/10] tcg-mips: Adjust calling conventions for mips64
Tested-by: Aurelien Jarno Tested-by: James Hogan Tested-by: YunQiang Su Signed-off-by: Richard Henderson Signed-off-by: Jin Guojie --- tcg/mips/tcg-target.h | 19 +++ tcg/mips/tcg-target.inc.c | 21 +++-- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 4b7d3ae..d352c97 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -27,7 +27,14 @@ #ifndef MIPS_TCG_TARGET_H #define MIPS_TCG_TARGET_H -#define TCG_TARGET_REG_BITS 32 +#if _MIPS_SIM == _ABIO32 +# define TCG_TARGET_REG_BITS 32 +#elif _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 +# define TCG_TARGET_REG_BITS 64 +#else +# error "Unknown ABI" +#endif + #define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 16 #define TCG_TARGET_NB_REGS 32 @@ -71,9 +78,13 @@ typedef enum { } TCGReg; /* used for function call generation */ -#define TCG_TARGET_STACK_ALIGN 8 -#define TCG_TARGET_CALL_STACK_OFFSET 16 -#define TCG_TARGET_CALL_ALIGN_ARGS 1 +#define TCG_TARGET_STACK_ALIGN16 +#if _MIPS_SIM == _ABIO32 +# define TCG_TARGET_CALL_STACK_OFFSET 16 +#else +# define TCG_TARGET_CALL_STACK_OFFSET 0 +#endif +#define TCG_TARGET_CALL_ALIGN_ARGS1 /* MOVN/MOVZ instructions detection */ #if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \ diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index b7e2586..7282a4a 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -91,10 +91,6 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_S8, /* Call clobbered registers. */ -TCG_REG_T0, -TCG_REG_T1, -TCG_REG_T2, -TCG_REG_T3, TCG_REG_T4, TCG_REG_T5, TCG_REG_T6, @@ -105,17 +101,27 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_V0, /* Argument registers, opposite order of allocation. */ +TCG_REG_T3, +TCG_REG_T2, +TCG_REG_T1, +TCG_REG_T0, TCG_REG_A3, TCG_REG_A2, TCG_REG_A1, TCG_REG_A0, }; -static const TCGReg tcg_target_call_iarg_regs[4] = { +static const TCGReg tcg_target_call_iarg_regs[] = { TCG_REG_A0, TCG_REG_A1, TCG_REG_A2, -TCG_REG_A3 +TCG_REG_A3, +#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 +TCG_REG_T0, +TCG_REG_T1, +TCG_REG_T2, +TCG_REG_T3, +#endif }; static const TCGReg tcg_target_call_oarg_regs[2] = { @@ -2427,6 +2433,9 @@ static void tcg_target_init(TCGContext *s) { tcg_target_detect_isa(); tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0x); +if (TCG_TARGET_REG_BITS == 64) { +tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I64], 0x); +} tcg_regset_set(tcg_target_call_clobber_regs, (1 << TCG_REG_V0) | (1 << TCG_REG_V1) | -- 2.1.0
Re: [Qemu-devel] [PATCH 4/4] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered
On Fri, Dec 09, 2016 at 04:30:20PM +, Peter Maydell wrote: > The architectural timers in ARM CPUs all have level triggered interrupts > (unless you're using KVM on a host kernel before 4.4, which misimplemented > them as edge-triggered). > > We were incorrectly describing them in the device tree as edge triggered. > This can cause problems for guest kernels in 4.8 before rc6: > * pre-4.8 kernels ignore the values in the DT > * 4.8 before rc6 write the DT values to the GIC config registers > * newer than rc6 ignore the DT and insist that the timer interrupts >are level triggered regardless > > Fix the DT so we're describing reality. For backwards-compatibility > purposes, only do this for the virt-2.9 machine onward. > > Signed-off-by: Peter Maydell > --- > hw/arm/virt.c | 34 ++ > 1 file changed, 30 insertions(+), 4 deletions(-) > > diff --git a/hw/arm/virt.c b/hw/arm/virt.c > index 54498ea..2ca9527 100644 > --- a/hw/arm/virt.c > +++ b/hw/arm/virt.c > @@ -71,6 +71,7 @@ typedef struct { > bool disallow_affinity_adjustment; > bool no_its; > bool no_pmu; > +bool claim_edge_triggered_timers; > } VirtMachineClass; > > typedef struct { > @@ -309,12 +310,31 @@ static void fdt_add_psci_node(const VirtMachineState > *vms) > > static void fdt_add_timer_nodes(const VirtMachineState *vms, int gictype) > { > -/* Note that on A15 h/w these interrupts are level-triggered, > - * but for the GIC implementation provided by both QEMU and KVM > - * they are edge-triggered. > +/* On real hardware these interrupts are level-triggered. > + * On KVM they were edge-triggered before host kernel version 4.4, > + * and level-triggered afterwards. > + * On emulated QEMU they are level-triggered. > + * > + * Getting the DTB info about them wrong is awkward for some > + * guest kernels: > + * pre-4.8 ignore the DT and leave the interrupt configured > + * with whatever the GIC reset value (or the bootloader) left it at > + * 4.8 before rc6 honour the incorrect data by programming it back > + * into the GIC, causing problems > + * 4.8rc6 and later ignore the DT and always write "level triggered" > + * into the GIC > + * > + * For backwards-compatibility, virt-2.8 and earlier will continue > + * to say these are edge-triggered, but later machines will report > + * the correct information. > */ Is this really necessary? I don't think the KVM GIC implementation ever listened to the guest in terms of how to configure PPIs, but instead ignores writes to the config registers for these interrupts (which I think the GIC architecture allows). So this would only be a matter of how the guest kernel between v4.8-rc1 and v4.8-rc6 expects the behavior to be. Does the arch timer driver really do something different in how it deals with interrupts based on this DT value? Of course, I suppose we could also be running other guests (UEFI?) but again, if the KVM GIC doesn't care about how the guest tries to program it, can it make a difference? > ARMCPU *armcpu; > -uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI; > +VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); > +uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; > + > +if (vmc->claim_edge_triggered_timers) { > +irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI; > +} > > if (gictype == 2) { > irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, > @@ -1556,8 +1576,14 @@ static void virt_2_8_instance_init(Object *obj) > > static void virt_machine_2_8_options(MachineClass *mc) > { > +VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); > + > virt_machine_2_9_options(mc); > SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_8); > +/* For 2.8 and earlier we falsely claimed in the DT that > + * our timers were edge-triggered, not level-triggered. > + */ > +vmc->claim_edge_triggered_timers = true; > } > DEFINE_VIRT_MACHINE(2, 8) > I don't understand this virt machine class version stuff. In which case is the claim_edge_triggered_timers set to true? (ok, appears to be when a 2.8 machine is created, but does that happen automatically or does the user specifically have to ask for it?) Thanks, -Christoffer
[Qemu-devel] aarch64-linux-user compilation error
Hi, I am getting a strange compilation error lately for aarch64-linux-user. I think it is somehow related to TYPE_PTRVOID handling but my investigation has not led to anything concrete. I think this is a compiler error since the build passes on an other system with gcc-6. Info: ubuntu 16.04 x86_64 system $ gcc --version gcc (Ubuntu 5.4.1-2ubuntu1~16.04) 5.4.1 20160904 Error: /home/pranith/devops/code/qemu/linux-user/ioctls.h:224:9: error: ‘SNDCTL_DSP_MAPINBUF’ undeclared here (not in a function) IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc))) ^ /home/pranith/devops/code/qemu/linux-user/syscall.c:5453:23: note: in definition of macro ‘IOCTL’ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, ^ /home/pranith/devops/code/qemu/linux-user/ioctls.h:225:9: error: ‘SNDCTL_DSP_MAPOUTBUF’ undeclared here (not in a function) IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc))) ^ /home/pranith/devops/code/qemu/linux-user/syscall.c:5453:23: note: in definition of macro ‘IOCTL’ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, ^ /home/pranith/devops/code/qemu/linux-user/ioctls.h:280:9: error: ‘SOUND_MIXER_ACCESS’ undeclared here (not in a function) IOCTL(SOUND_MIXER_ACCESS, 0, TYPE_PTRVOID) ^ /home/pranith/devops/code/qemu/linux-user/syscall.c:5453:23: note: in definition of macro ‘IOCTL’ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, ^ /home/pranith/devops/code/qemu/rules.mak:60: recipe for target 'linux-user/syscall.o' failed -- Pranith
Re: [Qemu-devel] aarch64-linux-user compilation error
On Sun, Dec 11, 2016 at 2:09 PM, Pranith Kumar wrote: > Hi, > > I am getting a strange compilation error lately for aarch64-linux-user. I > think it is somehow related to TYPE_PTRVOID handling but my investigation has > not led to anything concrete. I think this is a compiler error since the build > passes on an other system with gcc-6. > > Info: ubuntu 16.04 x86_64 system > > $ gcc --version > gcc (Ubuntu 5.4.1-2ubuntu1~16.04) 5.4.1 20160904 > The issue occurs even with a newer gcc. $ gcc --version gcc (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901 -- Pranith
Re: [Qemu-devel] [PATCH 4/4] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered
On 11 December 2016 at 16:35, Christoffer Dall wrote: > On Fri, Dec 09, 2016 at 04:30:20PM +, Peter Maydell wrote: >> + * For backwards-compatibility, virt-2.8 and earlier will continue >> + * to say these are edge-triggered, but later machines will report >> + * the correct information. >> */ > > Is this really necessary? It's being conservative -- from the guest's point of view (any guest, not necessarily just Linux) "virt-2.8" should behave like the "virt" machine in the 2.8 QEMU release, including bugs, not providing newer devices, and so on. Andrew would be the expert on whether this is being unnecessarily conservative in this specific case. >> static void virt_machine_2_8_options(MachineClass *mc) >> { >> +VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); >> + >> virt_machine_2_9_options(mc); >> SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_8); >> +/* For 2.8 and earlier we falsely claimed in the DT that >> + * our timers were edge-triggered, not level-triggered. >> + */ >> +vmc->claim_edge_triggered_timers = true; >> } >> DEFINE_VIRT_MACHINE(2, 8) >> > I don't understand this virt machine class version stuff. In which case > is the claim_edge_triggered_timers set to true? (ok, appears to be when > a 2.8 machine is created, but does that happen automatically or does the > user specifically have to ask for it?) If you say "-M virt-2.8" (or -2.7 or earlier, etc), it's set to true. If you say "-M virt" or "-M virt-2.9" (or "-M virt-2.10" or whatever we call the next release) it stays at the default false. thanks -- PMM
Re: [Qemu-devel] aarch64-linux-user compilation error
On 11 December 2016 at 19:09, Pranith Kumar wrote: > I am getting a strange compilation error lately for aarch64-linux-user. I > think it is somehow related to TYPE_PTRVOID handling but my investigation has > not led to anything concrete. I think this is a compiler error since the build > passes on an other system with gcc-6. > Error: > /home/pranith/devops/code/qemu/linux-user/ioctls.h:224:9: error: > ‘SNDCTL_DSP_MAPINBUF’ undeclared here (not in a function) >IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc))) > ^ SNDCTL_DSP_MAPINBUF is supposed to be defined by your system headers (/usr/include/linux/soundcard.h or equivalent). Similarly for SNDCTL_DSP_MAPOUTBUF and SOUND_MIXER_ACCESS. Looking at QEMU's git history we've used these symbols for years. I would check whether your system headers are actually providing these symbols (and that the compiler is really putting the right headers on the include path). thanks -- PMM
[Qemu-devel] [Bug 1648726] Re: [usb-host] Passthrough of UAS devices fails with Windows (10) guests
** Summary changed: - Passthrough of UAS devices fails with Windows (10) guests + [usb-host] Passthrough of UAS devices fails with Windows (10) guests -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1648726 Title: [usb-host] Passthrough of UAS devices fails with Windows (10) guests Status in QEMU: New Bug description: Split off from https://bugs.launchpad.net/qemu/+bug/1579306 as this is a distinct issue. Physical USB storage devices that support the UAS protocol do not work correctly when passed through to Windows guests (I've only tested this with Windows 10 x64, build 1607). Passing through such a device results in the older BOT/MSC protocol being used: Using the same domain configuration with a Linux guest (tested with SystemRescueCD 4.8.0) works correctly: /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M In both cases, the VM was launched via libvirt, which generated the following command line: /usr/bin/qemu-system-x86_64 -name guest=Win10-Edge-IE11,debug- threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-13-Win10 -Edge-IE11/master-key.aes -machine pc-q35-2.7,accel=kvm,usb=off,vmport=off,dump-guest-core=off -cpu host,hv_time,hv_relaxed,hv_vapic,hv_spinlocks=0x1fff -m 4096 -realtime mlock=off -smp 8,sockets=1,cores=4,threads=2 -uuid 47c39707-088c-4edc- 8b6a-a7856e09f43d -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-13-Win10-Edge- IE11/monitor.sock,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=localtime,driftfix=slew -global kvm-pit.lost_tick_policy=discard -no-hpet -no-shutdown -global ICH9-LPC.disable_s3=1 -global ICH9-LPC.disable_s4=1 -boot strict=on -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e -device pci- bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 -device nec-usb- xhci,id=usb,bus=pci.2,addr=0x6 -device virtio-scsi- pci,id=scsi0,bus=pci.2,addr=0x3 -device virtio-serial-pci,id=virtio- serial0,bus=pci.2,addr=0x4 -drive file=/home/jack/IMG/Win10-Edge- IE11.qcow2,format=qcow2,if=none,id=drive-scsi0-0-0-0,discard=unmap -device scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive- scsi0-0-0-0,id=scsi0-0-0-0,bootindex=1 -drive if=none,id=drive- scsi0-0-0-1,readonly=on -device scsi-cd,bus=scsi0.0,channel=0,scsi- id=0,lun=1,drive=drive-scsi0-0-0-1,id=scsi0-0-0-1 -netdev tap,fd=22,id=hostnet0,vhost=on,vhostfd=24 -device virtio-net- pci,netdev=hostnet0,id=net0,mac=52:54:00:27:94:5d,bus=pci.2,addr=0x1 -chardev pty,id=charserial0 -device isa- serial,chardev=charserial0,id=serial0 -chardev spicevmc,id=charchannel0,name=vdagent -device virtserialport,bus =virtio- serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0 -device usb-tablet,id=input0,bus=usb.0,port=2 -spice port=5900,addr=127.0.0.1,disable-ticketing,image-compression=off ,seamless-migration=on -device qxl- vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=16,max_outputs=1,bus=pcie.0,addr=0x1 -device intel-hda,id=sound0,bus=pci.2,addr=0x2 -device hda- duplex,id=sound0-codec0,bus=sound0.0,cad=0 -chardev spicevmc,id=charredir0,name=usbredir -device usb- redir,chardev=charredir0,id=redir0,bus=usb.0,port=3 -chardev spicevmc,id=charredir1,name=usbredir -device usb- redir,chardev=charredir1,id=redir1,bus=usb.0,port=4 -device usb- host,hostbus=4,hostaddr=4,id=hostdev0,bus=usb.0,port=1 -device virtio- balloon-pci,id=balloon0,bus=pci.2,addr=0x5 -msg timestamp=on To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1648726/+subscriptions
Re: [Qemu-devel] [PATCH 01/20] Makefile: Allow CPU targets to reside in target/ folder, too
On Sat, Dec 10, 2016 at 11:59:09AM +0100, Laurent Vivier wrote: > Le 09/12/2016 à 17:51, Thomas Huth a écrit : > > On 09.12.2016 13:24, Laurent Vivier wrote: > >> Le 09/12/2016 à 13:17, Thomas Huth a écrit : > >>> To be able to compile the CPU targets from within a subfolder > >>> of the target/ folder, we've got to adapt the Makefile.target > >>> a little bit first. After this change, target CPUs can either > >>> reside in a target/xxx folder or continue to use the target-xxx > >>> scheme. The latter will be disabled once all targets have been > >>> moved. > >>> > >>> Signed-off-by: Thomas Huth > >>> --- > >>> Makefile.target | 10 -- > >>> 1 file changed, 8 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/Makefile.target b/Makefile.target > >>> index 7a5080e..90b25ae 100644 > >>> --- a/Makefile.target > >>> +++ b/Makefile.target > >>> @@ -7,11 +7,17 @@ include config-target.mak > >>> include config-devices.mak > >>> include $(SRC_PATH)/rules.mak > >>> > >>> +ifneq ($(wildcard $(SRC_PATH)/target/$(TARGET_BASE_ARCH)),) > >>> +TARGET_FOLDER=target/$(TARGET_BASE_ARCH) > >>> +else > >>> +TARGET_FOLDER=target-$(TARGET_BASE_ARCH) > >>> +endif > >> > >> Perhaps you should consider to use ':=' instead of '='. > > > > Most of the other variables in that file seem to be set with '=' instead > > of ':=', so using '=' sounds more consistent to me ... is there a real > > benefit of using ':=' here? > > With ':=' your variable is expanded once, with '=' it is expanded > whenever it is used. I think this is not needed in your case. > > https://www.gnu.org/software/make/manual/html_node/Flavors.html#Flavors I tend to thing '=' is the safer default option unless you're really hitting performance problems that ':=' can alleviate. Not re-expanding can lead to confusing bugs later if the definition is changed so that re-expansion matters in future. -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
Re: [Qemu-devel] [PATCH v2 5/6] target-ppc: implement xxextractuw instruction
On Fri, Dec 09, 2016 at 05:47:24PM +0530, Nikunj A Dadhania wrote: > xxextractuw: VSX Vector Extract Unsigned Word > > Signed-off-by: Nikunj A Dadhania > --- > target-ppc/helper.h | 1 + > target-ppc/int_helper.c | 21 + > target-ppc/translate/vsx-impl.inc.c | 27 +++ > target-ppc/translate/vsx-ops.inc.c | 5 + > 4 files changed, 54 insertions(+) > > diff --git a/target-ppc/helper.h b/target-ppc/helper.h > index 4707db4..8b30420 100644 > --- a/target-ppc/helper.h > +++ b/target-ppc/helper.h > @@ -540,6 +540,7 @@ DEF_HELPER_2(xvrspip, void, env, i32) > DEF_HELPER_2(xvrspiz, void, env, i32) > DEF_HELPER_2(xxperm, void, env, i32) > DEF_HELPER_2(xxpermr, void, env, i32) > +DEF_HELPER_4(xxextractuw, void, env, tl, tl, i32) > > DEF_HELPER_2(efscfsi, i32, env, i32) > DEF_HELPER_2(efscfui, i32, env, i32) > diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c > index 7989b1f..e3f66ac 100644 > --- a/target-ppc/int_helper.c > +++ b/target-ppc/int_helper.c > @@ -2033,6 +2033,27 @@ VEXTRACT(uw, u32) > VEXTRACT(d, u64) > #undef VEXTRACT > > +void helper_xxextractuw(CPUPPCState *env, target_ulong xtn, > +target_ulong xbn, uint32_t index) > +{ > +ppc_vsr_t xt, xb; > +size_t es = sizeof(uint32_t); > +uint32_t ext_index; > + > +getVSR(xbn, &xb, env); > +memset(&xt, 0, sizeof(xt)); > + > +#if defined(HOST_WORDS_BIGENDIAN) > +ext_index = index; > +memcpy(&xt.u8[8 - es], &xb.u8[ext_index], es); > +#else > +ext_index = (16 - index) - es; > +memcpy(&xt.u8[8], &xb.u8[ext_index], es); Hm. So, IIUC, ext_index is the byte element - in IBM numbering - to start copying from. But I thought that when we have an LE host, the IBM byte element ordering is reversed from the actual order in host memory, so we'd need &xb.u8[16 - ext_index - es] > +#endif > + > +putVSR(xtn, &xt, env); > +} > + > #define VEXT_SIGNED(name, element, mask, cast, recast) \ > void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ > { \ > diff --git a/target-ppc/translate/vsx-impl.inc.c > b/target-ppc/translate/vsx-impl.inc.c > index 2a17c35..1c40a35 100644 > --- a/target-ppc/translate/vsx-impl.inc.c > +++ b/target-ppc/translate/vsx-impl.inc.c > @@ -1180,6 +1180,33 @@ static void gen_xxsldwi(DisasContext *ctx) > tcg_temp_free_i64(xtl); > } > > +#define VSX_EXTRACT(name) \ > +static void gen_##name(DisasContext *ctx) \ > +{ \ > +TCGv xt, xb;\ > +TCGv_i32 t0 = tcg_temp_new_i32(); \ > +uint8_t uimm = UIMM4(ctx->opcode); \ > +\ > +if (unlikely(!ctx->vsx_enabled)) { \ > +gen_exception(ctx, POWERPC_EXCP_VSXU); \ > +return; \ > +} \ > +if (uimm > 12) {\ Throughout the helper you use es == sizeof(uint32_t), but here you hardcode the assumption of 4 bytes, seems a bit inconsistent. > +tcg_gen_movi_i64(cpu_vsrh(xT(ctx->opcode)), 0); \ > +tcg_gen_movi_i64(cpu_vsrl(xT(ctx->opcode)), 0); \ > +return; \ So, I know the architecture says it is undefined. But since you're testing for the bogus case anyway, why not turn this into an exception. That seems like it would be more helpful for debugging the guest than just setting the result to zero. Or is this done to match actual hardware behaviour? > +} \ > +xt = tcg_const_tl(xT(ctx->opcode)); \ > +xb = tcg_const_tl(xB(ctx->opcode)); \ > +tcg_gen_movi_i32(t0, uimm); \ > +gen_helper_##name(cpu_env, xt, xb, t0); \ > +tcg_temp_free(xb); \ > +tcg_temp_free(xt); \ > +tcg_temp_free_i32(t0); \ > +} > + > +VSX_EXTRACT(xxextractuw) > + > #undef GEN_XX2FORM > #undef GEN_XX3FORM > #undef GEN_XX2IFORM > diff --git a/target-ppc/translate/vsx-ops.inc.c > b/target-ppc/translate/vsx-ops.inc.c > index 46b95e3..473d925 100644 > --- a/target-ppc/translate/vsx-ops.inc.c > +++ b/target-ppc/translate/vsx-ops.inc.c > @@ -49,6 +49,10 @@ GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, > PPC_NONE, fl2) > GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \ >
Re: [Qemu-devel] [PATCH v2 ppc-for-2.9 0/6] POWER9 TCG enablements - part9
On Fri, Dec 09, 2016 at 05:47:19PM +0530, Nikunj A Dadhania wrote: > This series contains 6 new instructions for POWER9 ISA3.0 > VSX Vector Insert/Extract Word > VSX Load/Store with length > > Although, lxvl/lxvll and stxvl/stxvll can be combined as single patch, > have left it for detailed commit log for instruction explanation. I've applied patches 1-4 to ppc-for-2.9. 5 & 6 I still have some questions about. > > Changelog: > v1: > * Combine helpers of lxvl and lxvll > * Combine helpers of stxvl and stxvll > * Rework xxextractuw and xxinsertw to simplify helper > > v0: > * Fixed lxvl/lxvll and stxvl/stxvll as suggested by Richard > * Dropped mask_u128, which is not needed anymore > * Prevent UIMM > 12 in xxextractuw > * Drop xori from xsnegqp > * Rewrite xxperm/xxpermr without double copy > > Nikunj A Dadhania (6): > target-ppc: implement lxvl instruction > target-ppc: implement lxvll instruction > target-ppc: implement stxvl instruction > target-ppc: implement stxvll instructions > target-ppc: implement xxextractuw instruction > target-ppc: implement xxinsertw instruction > > target-ppc/helper.h | 8 + > target-ppc/int_helper.c | 42 +++ > target-ppc/mem_helper.c | 66 > + > target-ppc/translate/vsx-impl.inc.c | 60 + > target-ppc/translate/vsx-ops.inc.c | 14 > 5 files changed, 190 insertions(+) > -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
Re: [Qemu-devel] [for-2.9 2/5] pseries: Stubs for HPT resizing
On Fri, Dec 09, 2016 at 11:08:02AM -0600, Michael Roth wrote: > Quoting David Gibson (2016-12-08 20:23:11) > > This introduces stub implementations of the H_RESIZE_HPT_PREPARE and > > H_RESIZE_HPT_COMMIT hypercalls which we hope to add in a PAPR > > extension to allow run time resizing of a guest's hash page table. It > > also adds a new machine property for controlling whether this new > > facility is available, and logic to check that against availability > > with KVM (only supported with KVM PR for now). > > > > Finally, it adds a new string to the hypertas property in the device > > tree, advertising to the guest the availability of the HPT resizing > > hypercalls. This is a tentative suggested value, and would need to be > > standardized by PAPR before being merged. > > > > Signed-off-by: David Gibson > > --- > > hw/ppc/spapr.c | 66 > > ++ > > hw/ppc/spapr_hcall.c | 36 +++ > > hw/ppc/trace-events| 2 ++ > > include/hw/ppc/spapr.h | 11 + > > target-ppc/kvm.c | 26 > > target-ppc/kvm_ppc.h | 5 > > 6 files changed, 146 insertions(+) > > > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > > index 0f25e83..ecb0822 100644 > > --- a/hw/ppc/spapr.c > > +++ b/hw/ppc/spapr.c > > @@ -760,6 +760,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, > > void *fdt) > > if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { > > add_str(hypertas, "hcall-multi-tce"); > > } > > + > > +if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { > > +add_str(hypertas, "hcall-hpt-resize"); > > +} > > + > > _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", > > hypertas->str, hypertas->len)); > > g_string_free(hypertas, TRUE); > > @@ -1839,11 +1844,31 @@ static void ppc_spapr_init(MachineState *machine) > > long load_limit, fw_size; > > char *filename; > > int smt = kvmppc_smt_threads(); > > +Error *resize_hpt_err = NULL; > > > > msi_nonbroken = true; > > > > QLIST_INIT(&spapr->phbs); > > > > +/* Check HPT resizing availability */ > > +kvmppc_check_papr_resize_hpt(&resize_hpt_err); > > +if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { > > +if (resize_hpt_err) { > > +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; > > +error_free(resize_hpt_err); > > +resize_hpt_err = NULL; > > +} else { > > +spapr->resize_hpt = smc->resize_hpt_default; > > +} > > +} > > + > > +assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); > > + > > +if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && > > resize_hpt_err) { > > +error_report_err(resize_hpt_err); > > +exit(1); > > +} > > I'm also a bit confused by this. Aren't semantics that HPT_ENABLED will allow > a fallback to non-resizable HPTs if the feature isn't available (whereas > HPT_REQUIRED won't)? I don't understand how such a fallback can ever be > reached > with this check in place. We fall back if the _guest_ doesn't support HPT resizing. This error path is if the _host_ can't support HPT resizing. Some extra information about this in the reply I'll shortly send to Thomas. -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
Re: [Qemu-devel] aarch64-linux-user compilation error
On Sun, Dec 11, 2016 at 5:59 PM, Peter Maydell wrote: > >> Error: >> /home/pranith/devops/code/qemu/linux-user/ioctls.h:224:9: error: >> ‘SNDCTL_DSP_MAPINBUF’ undeclared here (not in a function) >>IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc))) >> ^ > > SNDCTL_DSP_MAPINBUF is supposed to be defined by your system > headers (/usr/include/linux/soundcard.h or equivalent). > Similarly for SNDCTL_DSP_MAPOUTBUF and SOUND_MIXER_ACCESS. > > Looking at QEMU's git history we've used these symbols > for years. I would check whether your system headers > are actually providing these symbols (and that the > compiler is really putting the right headers on the > include path). So soundcard.h header is provided by two packages: $ apt-file search /usr/include/linux/soundcard.h linux-libc-dev: /usr/include/linux/soundcard.h oss4-dev: /usr/include/linux/soundcard.h I had oss4-dev installed. After removing that and reinstalling linux-libc-dev, it compiles fine. Not sure why this file differs. May be a packaging issue. Thanks for the help! -- Pranith
Re: [Qemu-devel] [PATCH for-2.9 1/2] intel_iommu: check validity for GAW bits in CE
On Thu, Dec 08, 2016 at 10:21:35AM +0800, Jason Wang wrote: > > > On 2016年12月08日 10:16, Peter Xu wrote: > >On Thu, Dec 08, 2016 at 10:02:15AM +0800, Jason Wang wrote: > >> > >>On 2016年12月07日 13:52, Peter Xu wrote: > >>>Currently vt-d Context Entry (CE) only allows 39/48 bits address width. > >>>If guest software configured more than that, we complain and force > >>>shrink to the maximum supported, which is 48bits. > >>> > >>>Signed-off-by: Peter Xu > >>>--- > >>> hw/i386/intel_iommu.c | 12 +++- > >>> hw/i386/intel_iommu_internal.h | 2 ++ > >>> 2 files changed, 13 insertions(+), 1 deletion(-) > >>> > >>>diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c > >>>index 5f3e351..98d45ef 100644 > >>>--- a/hw/i386/intel_iommu.c > >>>+++ b/hw/i386/intel_iommu.c > >>>@@ -601,7 +601,17 @@ static inline uint32_t > >>>vtd_get_level_from_context_entry(VTDContextEntry *ce) > >>> static inline uint32_t vtd_get_agaw_from_context_entry(VTDContextEntry > >>> *ce) > >>> { > >>>-return 30 + (ce->hi & VTD_CONTEXT_ENTRY_AW) * 9; > >>>+uint8_t aw = (ce->hi & VTD_CONTEXT_ENTRY_AW); > >>>+/* > >>>+ * According to vt-d spec 10.4.2 bits 12:8, SAGAW only allows > >>>+ * 39/48 bits. > >>>+ */ > >>>+if (aw > VTD_CE_AW_48BIT) { > >>>+error_report("Context entry address width not supported (aw=%d), " > >>>+ "Shrinking to maximum.", aw); > >>>+aw = VTD_CE_AW_48BIT; > >>>+} > >>Is this behavior specified by spec? > >That's how I understand spec 10.4.2 bits 12:8 (as mentioned in above > >comment). Only 39/48 bits AGAW are allowed, and others are reserved. > > > >When writting up this patch, I thought illegal value for this aw bits > >(from guest software) might cause trouble, but I was wrong, since we > >have a "MIN(ce_agaw, VTD_MGAW)" check later on. So that won't be a > >problem, and this patch is not that necessary now. > > > >Thanks, > > > >-- peterx > > Yes, and it can even report DMAR fault to guest which is better. Yes. Will respin, thanks. :-) -- peterx
Re: [Qemu-devel] [PATCH for-2.9 2/2] intel_iommu: extend supported guest aw to 48 bits
On Sun, Dec 11, 2016 at 05:13:45AM +0200, Michael S. Tsirkin wrote: > On Wed, Dec 07, 2016 at 01:52:45PM +0800, Peter Xu wrote: > > Previously vt-d codes only supports 39 bits iova address width. It won't > > be hard to extend it to 48 bits. > > > > After enabling this, we should be able to map larger iova addresses. > > > > To check whether 48 bits aw is enabled, we can grep in the guest dmesg > > with line: "dmar: Host address width 48" (previously it was 39). > > > > Signed-off-by: Peter Xu > > I suspect we can't do this for old machine types. > Need to behave in compatible ways. Sure. I can do that. Btw, is vt-d iommu still in experimental stage? I am just thinking whether it'll be overkill we add lots of tunables before we have one stable and mature vt-d emulation. > Also, is 48 always enough? 5 level with 57 bits > is just around the corner. Please refer to the discussion with Jason - looks like vt-d spec currently supports only 39/48 bits address width? Please correct if I made a mistake. > And is it always supported? for things like vfio > to work, don't we need to check what does host support? Hmm, yes, we should do that. But until now, we still don't have a complete vfio support. IMHO we can postpone this issue until vfio is fully supported. Thanks, -- peterx
Re: [Qemu-devel] An issue for migration determining the cpu throttle value according to workload
ping... Thanks, Chao Fan On Tue, Dec 06, 2016 at 04:52:11PM +0800, Chao Fan wrote: >Hi all, > >Here is an issue in auto-converge feature of migration. > >When migrating a guest which consumes too much CPU & memory, dirty >pages amount will increase significantly, so does the migration >time, migration can not even complete, at worst. > >I did some simple tests on this feature. Set the two parameters >the same as 10,20,30,40,50,60,70,80,99 and run the same task in the >same guest. The result roughly is, with the increment of the >two parameters, the total_time and the dirty_sync_count will decrease. >Result shows larger the value of the two parameters is, faster the >migration is, but much more slowly the guest runs. > >So I think there should be a appropriate throttle value according to >the workload of guest. But users do not know how to determine the >appropriate value. > >So I want to do a job that qemu can set the throttle value according >to the workload of guest. I think qemu could calculate the instant >dirty pages rate, and then determine a appropriate throttle value. >The instant dirty pages rate means in a short fixed time, how >many dirty pages born. But I have two questions: >1. Where to add this feature. I have two options: > a. Now qemu detects the rest migration time and decides whether > to execute the CPU throttle. It can be changed to that qemu > executes the CPU throttle when instant dirty pages rate increases > to a certain threshold and sets the throttle value according to > the instant dirty pages rate. > b. Using the current way as it is, when the rest migration time > is too long and begin to execute the CPU throttle, assign > appropriate throttle value according to the workload. Codes > will be changed fewer in this method. >2. How to determine the CPU throttle value according to the dirty pages. > My preliminary idea is, the CPU throttle should be related to > the instant dirty pages rate and the total memory. > But I am not sure how to do the map from instant dirty pages rate > and total memory to CPU throttle value is best. > >Any comments will be welcome, and I want to know whether more people >think this feature is needed. >If anyone has good ideas, please tell me. > >Thanks, >Chao Fan
Re: [Qemu-devel] [for-2.9 2/5] pseries: Stubs for HPT resizing
On Fri, Dec 09, 2016 at 10:18:59AM +0100, Thomas Huth wrote: > On 09.12.2016 10:09, David Gibson wrote: > > On Fri, Dec 09, 2016 at 09:18:51AM +0100, Thomas Huth wrote: > >> On 09.12.2016 03:23, David Gibson wrote: > >>> This introduces stub implementations of the H_RESIZE_HPT_PREPARE and > >>> H_RESIZE_HPT_COMMIT hypercalls which we hope to add in a PAPR > >>> extension to allow run time resizing of a guest's hash page table. It > >>> also adds a new machine property for controlling whether this new > >>> facility is available, and logic to check that against availability > >>> with KVM (only supported with KVM PR for now). > >>> > >>> Finally, it adds a new string to the hypertas property in the device > >>> tree, advertising to the guest the availability of the HPT resizing > >>> hypercalls. This is a tentative suggested value, and would need to be > >>> standardized by PAPR before being merged. > >>> > >>> Signed-off-by: David Gibson > >>> --- > >>> hw/ppc/spapr.c | 66 > >>> ++ > >>> hw/ppc/spapr_hcall.c | 36 +++ > >>> hw/ppc/trace-events| 2 ++ > >>> include/hw/ppc/spapr.h | 11 + > >>> target-ppc/kvm.c | 26 > >>> target-ppc/kvm_ppc.h | 5 > >>> 6 files changed, 146 insertions(+) > >>> > >>> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > >>> index 0f25e83..ecb0822 100644 > >>> --- a/hw/ppc/spapr.c > >>> +++ b/hw/ppc/spapr.c > >>> @@ -760,6 +760,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, > >>> void *fdt) > >>> if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { > >>> add_str(hypertas, "hcall-multi-tce"); > >>> } > >>> + > >>> +if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { > >>> +add_str(hypertas, "hcall-hpt-resize"); > >>> +} > >>> + > >>> _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", > >>> hypertas->str, hypertas->len)); > >>> g_string_free(hypertas, TRUE); > >>> @@ -1839,11 +1844,31 @@ static void ppc_spapr_init(MachineState *machine) > >>> long load_limit, fw_size; > >>> char *filename; > >>> int smt = kvmppc_smt_threads(); > >>> +Error *resize_hpt_err = NULL; > >>> > >>> msi_nonbroken = true; > >>> > >>> QLIST_INIT(&spapr->phbs); > >>> > >>> +/* Check HPT resizing availability */ > >>> +kvmppc_check_papr_resize_hpt(&resize_hpt_err); > >>> +if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { > >>> +if (resize_hpt_err) { > >>> +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; > >>> +error_free(resize_hpt_err); > >>> +resize_hpt_err = NULL; > >>> +} else { > >>> +spapr->resize_hpt = smc->resize_hpt_default; > >>> +} > >>> +} > >>> + > >>> +assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); > >>> + > >>> +if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && > >>> resize_hpt_err) { > >>> +error_report_err(resize_hpt_err); > >>> +exit(1); > >>> +} > >> > >> The logic here is IMHO a little bit hard to understand. Why do you need > >> the SPAPR_RESIZE_HPT_DEFAULT state here at all? Wouldn't it be > >> sufficient to start with SPAPR_RESIZE_HPT_DISABLED by default and to > >> only enable it when the extension is available? > > > > Because if the user explicitly sets something, we should never > > override itin the logic here. In order to determine whether the user > > has set something explicitly, we need another value that means "not > > set explicitly". > > Hmm, ok, I think I slowly get it. Another question: Does this also take > care of the handling if the user migrates from a machine that supports > HPT resizing to a machine that does not support this feature? Ok, so there are a fair few cases here. The key point, though is that even before now, we helpefully transferred the size of the HPT in the migration stream before sending its contents (that was done so we could update the sizing heuristics without breaking migration). For TCG and KVM PR: Here the ability to HPT resize depends purely on the qemu version. Assuming this gets merged for qemu-2.9, pseries-2.9 TCG or PR guests should always support resizing so that should be fine. If you explicitly enabled HPT resizing for a pseries-2.8 guest running under qemu-2.9 to an older qemu, then things could get odd. The destination guest would get an HPT of the size it had at the source at the point of migration. Any further attempts to resize would fail. Given you have to explicitly set up this poor situation and the failure mode isn't _that_ bad, I think that's ok. For KVM HV: Assuming we're migrating from a host kernel which can support resize to one which can't: If the resize-hpt is (explicitly) set differently on the the two ends then, well, don't do that. So assume it's the same on each end: If resize-hpt=disabled, things are fine, obviously. If resi
[Qemu-devel] [kvm-unit-tests PATCH v8 03/14] libcflat: introduce is_power_of_2()
Suggested-by: Andrew Jones Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/libcflat.h | 5 + 1 file changed, 5 insertions(+) diff --git a/lib/libcflat.h b/lib/libcflat.h index c622198..8455c3d 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -104,4 +104,9 @@ do { \ } \ } while (0) +static inline bool is_power_of_2(unsigned long n) +{ + return n && !(n & (n - 1)); +} + #endif -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 02/14] x86/asm: add cpu_relax()
This will be useful to be put inside loops. Suggested-by: Andrew Jones Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/x86/asm/barrier.h | 11 +++ 1 file changed, 11 insertions(+) diff --git a/lib/x86/asm/barrier.h b/lib/x86/asm/barrier.h index 7c108bd..193fb4c 100644 --- a/lib/x86/asm/barrier.h +++ b/lib/x86/asm/barrier.h @@ -13,4 +13,15 @@ #define smp_rmb() barrier() #define smp_wmb() barrier() +/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ +static inline void rep_nop(void) +{ + asm volatile("rep; nop" ::: "memory"); +} + +static inline void cpu_relax(void) +{ + rep_nop(); +} + #endif -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 01/14] pci: fix missing extern for pci_testdev()
Suggested-by: Andrew Jones Signed-off-by: Peter Xu --- lib/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pci.h b/lib/pci.h index 30f5381..86d6b42 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -43,7 +43,7 @@ extern bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num); extern void pci_bar_print(pcidevaddr_t dev, int bar_num); extern void pci_dev_print_id(pcidevaddr_t dev); -int pci_testdev(void); +extern int pci_testdev(void); /* * pci-testdev is a driver for the pci-testdev qemu pci device. The -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 05/14] libcflat: add IS_ALIGNED() macro, and page sizes
These macros will be useful to do page alignment checks. Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/libcflat.h | 6 ++ 1 file changed, 6 insertions(+) diff --git a/lib/libcflat.h b/lib/libcflat.h index 8455c3d..88b10e2 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -33,6 +33,12 @@ #define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) #define ALIGN(x, a)__ALIGN((x), (a)) +#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) + +#define SZ_4K (1 << 12) +#define SZ_64K (1 << 16) +#define SZ_2M (1 << 21) +#define SZ_1G (1 << 30) typedef uint8_tu8; typedef int8_t s8; -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 04/14] x86: intel-iommu: add vt-d init test
Adding fundamental init test for Intel IOMMU. This includes basic initialization of Intel IOMMU device, like DMAR (DMA Remapping), IR (Interrupt Remapping), QI (Queue Invalidation), etc. Further tests can use vtd_init() to initialize Intel IOMMU environment. x86/unittests is updated to add this test. Signed-off-by: Peter Xu --- lib/x86/intel-iommu.c | 99 +++ lib/x86/intel-iommu.h | 141 ++ x86/Makefile.x86_64 | 2 + x86/intel-iommu.c | 27 ++ x86/unittests.cfg | 7 +++ 5 files changed, 276 insertions(+) create mode 100644 lib/x86/intel-iommu.c create mode 100644 lib/x86/intel-iommu.h create mode 100644 x86/intel-iommu.c diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c new file mode 100644 index 000..1887998 --- /dev/null +++ b/lib/x86/intel-iommu.c @@ -0,0 +1,99 @@ +/* + * Intel IOMMU APIs + * + * Copyright (C) 2016 Red Hat, Inc. + * + * Authors: + * Peter Xu , + * + * This work is licensed under the terms of the GNU LGPL, version 2 or + * later. + */ + +#include "intel-iommu.h" + +#define VTD_RTA_MASK (PAGE_MASK) +#define VTD_IRTA_MASK (PAGE_MASK) + +void *vtd_reg_base; + +static uint64_t vtd_root_table(void) +{ + /* No extend root table support yet */ + return vtd_readq(DMAR_RTADDR_REG) & VTD_RTA_MASK; +} + +static uint64_t vtd_ir_table(void) +{ + return vtd_readq(DMAR_IRTA_REG) & VTD_IRTA_MASK; +} + +static void vtd_gcmd_or(uint32_t cmd) +{ + uint32_t status; + + /* We only allow set one bit for each time */ + assert(is_power_of_2(cmd)); + + status = vtd_readl(DMAR_GSTS_REG); + vtd_writel(DMAR_GCMD_REG, status | cmd); + + if (cmd & VTD_GCMD_ONE_SHOT_BITS) { + /* One-shot bits are taking effect immediately */ + return; + } + + /* Make sure IOMMU handled our command request */ + while (!(vtd_readl(DMAR_GSTS_REG) & cmd)) + cpu_relax(); +} + +static void vtd_dump_init_info(void) +{ + uint32_t version; + + version = vtd_readl(DMAR_VER_REG); + + /* Major version >= 1 */ + assert(((version >> 3) & 0xf) >= 1); + + printf("VT-d version: 0x%x\n", version); + printf(" cap: 0x%016lx\n", vtd_readq(DMAR_CAP_REG)); + printf(" ecap: 0x%016lx\n", vtd_readq(DMAR_ECAP_REG)); +} + +static void vtd_setup_root_table(void) +{ + void *root = alloc_page(); + + memset(root, 0, PAGE_SIZE); + vtd_writeq(DMAR_RTADDR_REG, virt_to_phys(root)); + vtd_gcmd_or(VTD_GCMD_ROOT); + printf("DMAR table address: 0x%016lx\n", vtd_root_table()); +} + +static void vtd_setup_ir_table(void) +{ + void *root = alloc_page(); + + memset(root, 0, PAGE_SIZE); + /* 0xf stands for table size (2^(0xf+1) == 65536) */ + vtd_writeq(DMAR_IRTA_REG, virt_to_phys(root) | 0xf); + vtd_gcmd_or(VTD_GCMD_IR_TABLE); + printf("IR table address: 0x%016lx\n", vtd_ir_table()); +} + +void vtd_init(void) +{ + setup_vm(); + smp_init(); + + vtd_reg_base = ioremap(Q35_HOST_BRIDGE_IOMMU_ADDR, PAGE_SIZE); + + vtd_dump_init_info(); + vtd_gcmd_or(VTD_GCMD_QI); /* Enable QI */ + vtd_setup_root_table(); + vtd_setup_ir_table(); + vtd_gcmd_or(VTD_GCMD_DMAR); /* Enable DMAR */ + vtd_gcmd_or(VTD_GCMD_IR); /* Enable IR */ +} diff --git a/lib/x86/intel-iommu.h b/lib/x86/intel-iommu.h new file mode 100644 index 000..92cc85f --- /dev/null +++ b/lib/x86/intel-iommu.h @@ -0,0 +1,141 @@ +/* + * Intel IOMMU header + * + * Copyright (C) 2016 Red Hat, Inc. + * + * Authors: + * Peter Xu , + * + * This work is licensed under the terms of the GNU LGPL, version 2 or + * later. + * + * (From include/linux/intel-iommu.h) + */ + +#ifndef __INTEL_IOMMU_H__ +#define __INTEL_IOMMU_H__ + +#include "libcflat.h" +#include "vm.h" +#include "isr.h" +#include "smp.h" +#include "desc.h" +#include "asm/io.h" + +#define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed9ULL + +/* + * Intel IOMMU register specification + */ +#define DMAR_VER_REG0x0 /* Arch version supported by this IOMMU */ +#define DMAR_CAP_REG0x8 /* Hardware supported capabilities */ +#define DMAR_CAP_REG_HI 0xc /* High 32-bit of DMAR_CAP_REG */ +#define DMAR_ECAP_REG 0x10 /* Extended capabilities supported */ +#define DMAR_ECAP_REG_HI0X14 +#define DMAR_GCMD_REG 0x18 /* Global command */ +#define DMAR_GSTS_REG 0x1c /* Global status */ +#define DMAR_RTADDR_REG 0x20 /* Root entry table */ +#define DMAR_RTADDR_REG_HI 0X24 +#define DMAR_CCMD_REG 0x28 /* Context command */ +#define DMAR_CCMD_REG_HI0x2c +#define DMAR_FSTS_REG 0x34 /* Fault status */ +#define DMAR_FECTL_REG 0x38 /* Fault control */ +#define DMAR_FEDATA_REG 0x3c /* Fault event interrupt data */ +#define DMAR_FEADDR_REG 0x40 /* Fault event
[Qemu-devel] [kvm-unit-tests PATCH v8 00/14] VT-d unit test
This is v8 of vt-d unit test series. (CC qemu-devel list this time.) Patch "libcflat: add IS_ALIGNED() macro, and page sizes" is picked up by Drew in the ARM GIC framework series, so please feel free to drop it when needed. Online repo: https://github.com/xzpeter/kvm-unit-tests.git iommu-ut-v8 Please review. Thanks, v8: - use ioremap() to access vt-d/edu registers (adding vtd_reg_base to store vt-d mmio base register vaddr, and pci_edu_dev.reg_base to store edu device base register vaddr) [Alex] - check vt-d version [Alex] - vtd_install_pte: do phys_to_virt() for root pointer [Alex] - renaming VTD_FETCH_VIRT_ADDR to VTD_PHYS_TO_VIRT [Alex] - define VTD_PAGE_SHIFT and VTD_PAGE_SIZE, use them when necessary [Alex] - change define of VTD_PTE_ADDR to cover bits 63:12 v7: - patch 13: add r-b for Drew - change type of dev_offset in edu_dma() into unsigned [Alex] - squash Alex's fix (thanks) for ARM build into patch 08/14 [Alex] v6: - pci: rename pci_dev.bar to pcidev.resource (to Drew: I didn't remove your r-b in several patches due to this change, assuming the change is trivial) [Alex] - pci_cap_walk(): add an assert to avoid dead loop [Alex] - pci_cap_walk(): another assertion to make sure cap_id is valid [Drew] v5: - add one more patch at the beginning of series to add "extern" to pci_testdev() header definition [Drew] - add "extern" to all pci.h functions [Drew] - update IS_ALIGNED patch to be aligned with Drew's gic series [Drew] - replace one more PCI_DEVFN_MAX/PCI_BAR_NUM in lib/pci-host-generic.c [Drew] - add {} in vtd_install_pte() when there are one line code and one line comment [Drew] - drop Drew's suggested-by in patch "x86: intel-iommu: add IR MSI test" (I forgot why I added it, but anyway let me drop it here...) [Drew] v4: (same as v3, but with correct patches sent out) v3: - is_power_of_2(): remove outer "()" [Drew] - fix indent for vtd_root_table() [Drew] - pci_find_dev(): keep {} to avoid touching more codes [Drew] - pci_scan_bars(): check whether bar is 64bits [Drew] - pci_enable_defaults(): make it return nothing [Drew] - fix strnang blanks in lib/x86/intel-iommu.h [Drew] - pci_setup_msi(): fix correct assert() inside [Drew] - squash patches: 03+17 08+09 10+11 12+14 [Drew] - remove all "()" for raw defines (numbers) in macros [Drew] v2: - move cpu_relax patch to the beginning, and use them in all places [Drew] - replace all corresponding 256 into PCI_DEVFN_MAX, as well for PCI_BAR_NUM [Drew] - adding is_power_of_2() to replace ONE_BIT_ONLY() [Drew] - add SZ_64K macro [Drew] - declare pci_config_write[wb] in lib/asm-generic/pci-host-bridge.h [Alex] - edu_reg_read/write() add "l" in func name [Drew] - drop pci_set_master(), instead, provide pci_cmd_set_clr() [Drew] - change return code into bool (always) for functions that apply [Drew] - keep old pci_find_dev() interface [Drew/Alex] - use __raw_{read|write}*() for both vt-d and edu register read/writes [Alex] - remove pci_ prefix for all pci_dev fields [Drew] - replace 0xff in cap_handlers[0xff] into (PCI_CAP_ID_MAX + 1) [Drew] - make x86/unittest.cfg simpler by using q35 directly with eim=off [Drew] RFC -> v1: - when init edu device fail, report_skip() rather than return error [Radim] - use asserts rather than "static bool inited" to avoid multiple init of components (affects patch 1/2) [Drew] - moving the first two patches out of the series [Drew] - int vtd_init(), do not setup_idt() since smp_init() did it [Drew] - when edu do not have MSI enabled, skip interrupt test [Radim] - rename vtd_reg_*() into vtd_{read|write}[lq](), and move them to header file [Drew] - use PAGE_MASK when able [Drew] - use "&" instead of "|" in intel-iommu init test (three places) [Drew] - use "vtd_init()" in unit test [Drew] - mention that where intel-iommu.h comes from [Drew] - re-written vtd_gcmd_or(), make it also work on even hardware [Drew] - remove most of the oneline wrapper for VT-d registers, instead, use vtd_{read|write}* with register names [Drew] - remove useless BDF helpers [Drew] - move edu device macros into header file [Drew] - make edu_check_alive static inline [Drew] - remove all useless wrappers in pci-edu.c [Drew] - remove pci_dma_dir_t and all its users, instead, use "bool from_device" [Drew] - not use typedef for structs, to follow Linux/kvm-unit-tests coding style [Drew] - let pci_dev_init() clean and simple, then provide pci_enable_defaults() for more complicated things [Drew] - add one more patch to add intel-iommu test into x86/unittest [Radim] - use 0x60 intr request instead of factorial to trigger edu device interrupt [Drew] - ...and some other changes I just forgot to note down... Currently only a very small test scope is covered: * VT-d init * DMAR: 4 bytes copy * IR: MSI However this series could be a base point to add more test cases for VT-d. The problem is, there are many IOMMU error conditions which are very hard to be triggered in a real guest (IOMMU has merely no interface for guest user,
[Qemu-devel] [kvm-unit-tests PATCH v8 08/14] pci: introduce struct pci_dev
To extend current PCI framework, we need a per-device struct to store device specific information. Time to have a pci_dev struct. Most of the current PCI APIs are converted to use this pci_dev object as the first argument. Currently it only contains one field "bdf", which is the bdf of current device. For a few APIs like pci_config_*() ops or pci_find_dev(), I kept the old interface (use PCI BDF value rather than "struct pci_dev") since they can be used in a open context that without any specific PCI device. Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/pci-host-generic.c | 17 --- lib/pci-testdev.c | 10 + lib/pci.c | 56 ++ lib/pci.h | 24 ++ x86/vmexit.c | 18 5 files changed, 76 insertions(+), 49 deletions(-) diff --git a/lib/pci-host-generic.c b/lib/pci-host-generic.c index 6ac0f15..958ef70 100644 --- a/lib/pci-host-generic.c +++ b/lib/pci-host-generic.c @@ -165,7 +165,7 @@ static struct pci_host_bridge *pci_dt_probe(void) return host; } -static bool pci_alloc_resource(pcidevaddr_t dev, int bar_num, u64 *addr) +static bool pci_alloc_resource(struct pci_dev *dev, int bar_num, u64 *addr) { struct pci_host_bridge *host = pci_host_bridge; struct pci_addr_space *as = &host->addr_space[0]; @@ -192,7 +192,7 @@ static bool pci_alloc_resource(pcidevaddr_t dev, int bar_num, u64 *addr) if (i >= host->nr_addr_spaces) { printf("%s: warning: can't satisfy request for ", __func__); - pci_dev_print_id(dev); + pci_dev_print_id(dev->bdf); printf(" "); pci_bar_print(dev, bar_num); printf("\n"); @@ -211,6 +211,7 @@ static bool pci_alloc_resource(pcidevaddr_t dev, int bar_num, u64 *addr) bool pci_probe(void) { + struct pci_dev pci_dev; pcidevaddr_t dev; u8 header; u32 cmd; @@ -221,10 +222,12 @@ bool pci_probe(void) if (!pci_host_bridge) return false; - for (dev = 0; dev < 256; dev++) { + for (dev = 0; dev < PCI_DEVFN_MAX; dev++) { if (!pci_dev_exists(dev)) continue; + pci_dev_init(&pci_dev, dev); + /* We are only interested in normal PCI devices */ header = pci_config_readb(dev, PCI_HEADER_TYPE); if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL) @@ -235,16 +238,16 @@ bool pci_probe(void) for (i = 0; i < 6; i++) { u64 addr; - if (pci_alloc_resource(dev, i, &addr)) { - pci_bar_set_addr(dev, i, addr); + if (pci_alloc_resource(&pci_dev, i, &addr)) { + pci_bar_set_addr(&pci_dev, i, addr); - if (pci_bar_is_memory(dev, i)) + if (pci_bar_is_memory(&pci_dev, i)) cmd |= PCI_COMMAND_MEMORY; else cmd |= PCI_COMMAND_IO; } - if (pci_bar_is64(dev, i)) + if (pci_bar_is64(&pci_dev, i)) i++; } diff --git a/lib/pci-testdev.c b/lib/pci-testdev.c index ad482d3..7d298e6 100644 --- a/lib/pci-testdev.c +++ b/lib/pci-testdev.c @@ -163,9 +163,10 @@ static int pci_testdev_all(struct pci_test_dev_hdr *test, int pci_testdev(void) { + struct pci_dev pci_dev; + pcidevaddr_t dev; phys_addr_t addr; void __iomem *mem, *io; - pcidevaddr_t dev; int nr_tests = 0; bool ret; @@ -175,14 +176,15 @@ int pci_testdev(void) "check QEMU '-device pci-testdev' parameter\n"); return -1; } + pci_dev_init(&pci_dev, dev); - ret = pci_bar_is_valid(dev, 0) && pci_bar_is_valid(dev, 1); + ret = pci_bar_is_valid(&pci_dev, 0) && pci_bar_is_valid(&pci_dev, 1); assert(ret); - addr = pci_bar_get_addr(dev, 0); + addr = pci_bar_get_addr(&pci_dev, 0); mem = ioremap(addr, PAGE_SIZE); - addr = pci_bar_get_addr(dev, 1); + addr = pci_bar_get_addr(&pci_dev, 1); io = (void *)(unsigned long)addr; nr_tests += pci_testdev_all(mem, &pci_testdev_mem_ops); diff --git a/lib/pci.c b/lib/pci.c index 6bd54cb..8f2356d 100644 --- a/lib/pci.c +++ b/lib/pci.c @@ -13,12 +13,18 @@ bool pci_dev_exists(pcidevaddr_t dev) pci_config_readw(dev, PCI_DEVICE_ID) != 0x); } +void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf) +{ + memset(dev, 0, sizeof(*dev)); + dev->bdf = bdf; +} + /* Scan bus look for a specific device. Only bus 0 scanned for now. */ pcidevaddr_t pci_find_dev(uint16_t
[Qemu-devel] [kvm-unit-tests PATCH v8 10/14] pci: provide pci_enable_defaults()
One helper function to set/clear specific bit in PCI_COMMAND register is introduced. Then, provide a function to do most of the common PCI init work. Suggested-by: Andrew Jones Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/pci.c | 19 +++ lib/pci.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/lib/pci.c b/lib/pci.c index d4521be..bf2a3df 100644 --- a/lib/pci.c +++ b/lib/pci.c @@ -7,6 +7,18 @@ #include "pci.h" #include "asm/pci.h" +void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr) +{ + uint16_t val = pci_config_readw(dev->bdf, PCI_COMMAND); + + /* No overlap is allowed */ + assert((set & clr) == 0); + val |= set; + val &= ~clr; + + pci_config_writew(dev->bdf, PCI_COMMAND, val); +} + bool pci_dev_exists(pcidevaddr_t dev) { return (pci_config_readw(dev, PCI_VENDOR_ID) != 0x && @@ -242,3 +254,10 @@ void pci_scan_bars(struct pci_dev *dev) } } } + +void pci_enable_defaults(struct pci_dev *dev) +{ + pci_scan_bars(dev); + /* Enable device DMA operations */ + pci_cmd_set_clr(dev, PCI_COMMAND_MASTER, 0); +} diff --git a/lib/pci.h b/lib/pci.h index 8215c9d..d3052ef 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -25,6 +25,8 @@ struct pci_dev { extern void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf); extern void pci_scan_bars(struct pci_dev *dev); +extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr); +extern void pci_enable_defaults(struct pci_dev *dev); extern bool pci_probe(void); extern void pci_print(void); -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 06/14] libcflat: moving MIN/MAX here
That's something can be used outside alloc.c. Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/alloc.c| 3 --- lib/libcflat.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/alloc.c b/lib/alloc.c index e1d7b8a..58af52b 100644 --- a/lib/alloc.c +++ b/lib/alloc.c @@ -7,9 +7,6 @@ #include "asm/spinlock.h" #include "asm/io.h" -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - #define PHYS_ALLOC_NR_REGIONS 256 struct phys_alloc_region { diff --git a/lib/libcflat.h b/lib/libcflat.h index 88b10e2..94d2a53 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -40,6 +40,9 @@ #define SZ_2M (1 << 21) #define SZ_1G (1 << 30) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + typedef uint8_tu8; typedef int8_t s8; typedef uint16_t u16; -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 09/14] pci: provide pci_scan_bars()
Let's provide a more general way to scan PCI bars, rather than read the config registers every time. Then let x86/vmexit.c leverage pci_scan_bars() Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/pci-host-generic.c | 2 +- lib/pci.c | 17 - lib/pci.h | 5 + x86/vmexit.c | 17 ++--- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/pci-host-generic.c b/lib/pci-host-generic.c index 958ef70..b1d2fc5 100644 --- a/lib/pci-host-generic.c +++ b/lib/pci-host-generic.c @@ -235,7 +235,7 @@ bool pci_probe(void) cmd = PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - for (i = 0; i < 6; i++) { + for (i = 0; i < PCI_BAR_NUM; i++) { u64 addr; if (pci_alloc_resource(&pci_dev, i, &addr)) { diff --git a/lib/pci.c b/lib/pci.c index 8f2356d..d4521be 100644 --- a/lib/pci.c +++ b/lib/pci.c @@ -207,7 +207,7 @@ static void pci_dev_print(pcidevaddr_t dev) if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL) return; - for (i = 0; i < 6; i++) { + for (i = 0; i < PCI_BAR_NUM; i++) { if (pci_bar_size(&pci_dev, i)) { printf("\t"); pci_bar_print(&pci_dev, i); @@ -227,3 +227,18 @@ void pci_print(void) pci_dev_print(dev); } } + +void pci_scan_bars(struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_BAR_NUM; i++) { + if (!pci_bar_is_valid(dev, i)) + continue; + dev->resource[i] = pci_bar_get_addr(dev, i); + if (pci_bar_is64(dev, i)) { + i++; + dev->resource[i] = (phys_addr_t)0; + } + } +} diff --git a/lib/pci.h b/lib/pci.h index 355acd0..8215c9d 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -15,13 +15,16 @@ enum { PCIDEVADDR_INVALID = 0x, }; +#define PCI_BAR_NUM 6 #define PCI_DEVFN_MAX 256 struct pci_dev { uint16_t bdf; + phys_addr_t resource[PCI_BAR_NUM]; }; extern void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf); +extern void pci_scan_bars(struct pci_dev *dev); extern bool pci_probe(void); extern void pci_print(void); @@ -65,6 +68,8 @@ extern int pci_testdev(void); * pci-testdev supports at least three types of tests (via mmio and * portio BARs): no-eventfd, wildcard-eventfd and datamatch-eventfd */ +#define PCI_TESTDEV_BAR_MEM0 +#define PCI_TESTDEV_BAR_IO 1 #define PCI_TESTDEV_NUM_BARS 2 #define PCI_TESTDEV_NUM_TESTS 3 diff --git a/x86/vmexit.c b/x86/vmexit.c index 63fa070..f9a22de 100644 --- a/x86/vmexit.c +++ b/x86/vmexit.c @@ -389,17 +389,12 @@ int main(int ac, char **av) ret = pci_find_dev(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_TEST); if (ret != PCIDEVADDR_INVALID) { pci_dev_init(&pcidev, ret); - for (i = 0; i < PCI_TESTDEV_NUM_BARS; i++) { - if (!pci_bar_is_valid(&pcidev, i)) { - continue; - } - if (pci_bar_is_memory(&pcidev, i)) { - membar = pci_bar_get_addr(&pcidev, i); - pci_test.memaddr = ioremap(membar, PAGE_SIZE); - } else { - pci_test.iobar = pci_bar_get_addr(&pcidev, i); - } - } + pci_scan_bars(&pcidev); + assert(pci_bar_is_memory(&pcidev, PCI_TESTDEV_BAR_MEM)); + assert(!pci_bar_is_memory(&pcidev, PCI_TESTDEV_BAR_IO)); + membar = pcidev.resource[PCI_TESTDEV_BAR_MEM]; + pci_test.memaddr = ioremap(membar, PAGE_SIZE); + pci_test.iobar = pcidev.resource[PCI_TESTDEV_BAR_IO]; printf("pci-testdev at 0x%x membar %lx iobar %x\n", pcidev.bdf, membar, pci_test.iobar); } -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 07/14] vm/page: provide PGDIR_OFFSET() macro
This can be used in further patches. Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/x86/asm/page.h | 3 +++ lib/x86/vm.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/x86/asm/page.h b/lib/x86/asm/page.h index 5044a49..c43bab2 100644 --- a/lib/x86/asm/page.h +++ b/lib/x86/asm/page.h @@ -41,5 +41,8 @@ #definePGDIR_MASK 1023 #endif +#define PGDIR_BITS(lvl)(((lvl) - 1) * PGDIR_WIDTH + PAGE_SHIFT) +#define PGDIR_OFFSET(va, lvl) (((va) >> PGDIR_BITS(lvl)) & PGDIR_MASK) + #endif /* !__ASSEMBLY__ */ #endif diff --git a/lib/x86/vm.c b/lib/x86/vm.c index f7e778b..cda4c5f 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -48,7 +48,7 @@ unsigned long *install_pte(unsigned long *cr3, unsigned offset; for (level = PAGE_LEVEL; level > pte_level; --level) { - offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK; + offset = PGDIR_OFFSET((unsigned long)virt, level); if (!(pt[offset] & PT_PRESENT_MASK)) { unsigned long *new_pt = pt_page; if (!new_pt) @@ -60,7 +60,7 @@ unsigned long *install_pte(unsigned long *cr3, } pt = phys_to_virt(pt[offset] & PT_ADDR_MASK); } -offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK; +offset = PGDIR_OFFSET((unsigned long)virt, level); pt[offset] = pte; return &pt[offset]; } -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 11/14] pci: edu: introduce pci-edu helpers
QEMU edu device is a pci device that is originally written for educational purpose, however it also suits for IOMMU unit test. Adding helpers for this specific device to implement the device logic. The device supports lots of functions, here only DMA operation is supported. The spec of the device can be found at: https://github.com/qemu/qemu/blob/master/docs/specs/edu.txt Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/pci-edu.c | 73 lib/pci-edu.h | 83 +++ 2 files changed, 156 insertions(+) create mode 100644 lib/pci-edu.c create mode 100644 lib/pci-edu.h diff --git a/lib/pci-edu.c b/lib/pci-edu.c new file mode 100644 index 000..8096470 --- /dev/null +++ b/lib/pci-edu.c @@ -0,0 +1,73 @@ +/* + * Edu PCI device. + * + * Copyright (C) 2016 Red Hat, Inc. + * + * Authors: + * Peter Xu , + * + * This work is licensed under the terms of the GNU LGPL, version 2 or + * later. + */ + +#include "pci-edu.h" +#include "asm/barrier.h" + +/* Return true if alive */ +static inline bool edu_check_alive(struct pci_edu_dev *dev) +{ + static uint32_t live_count = 1; + uint32_t value; + + edu_reg_writel(dev, EDU_REG_ALIVE, live_count++); + value = edu_reg_readl(dev, EDU_REG_ALIVE); + return (live_count - 1 == ~value); +} + +bool edu_init(struct pci_edu_dev *dev) +{ + pcidevaddr_t dev_addr; + + dev_addr = pci_find_dev(PCI_VENDOR_ID_QEMU, PCI_DEVICE_ID_EDU); + if (dev_addr == PCIDEVADDR_INVALID) + return false; + + pci_dev_init(&dev->pci_dev, dev_addr); + pci_enable_defaults(&dev->pci_dev); + dev->reg_base = ioremap(dev->pci_dev.resource[EDU_BAR], PAGE_SIZE); + assert(edu_check_alive(dev)); + return true; +} + +void edu_dma(struct pci_edu_dev *dev, iova_t iova, +size_t size, unsigned int dev_offset, bool from_device) +{ + uint64_t from, to; + uint32_t cmd = EDU_CMD_DMA_START; + + assert(size <= EDU_DMA_SIZE_MAX); + assert(dev_offset < EDU_DMA_SIZE_MAX); + + printf("edu device DMA start %s addr %p size 0x%lu off 0x%x\n", + from_device ? "FROM" : "TO", + (void *)iova, size, dev_offset); + + if (from_device) { + from = dev_offset + EDU_DMA_START; + to = iova; + cmd |= EDU_CMD_DMA_FROM; + } else { + from = iova; + to = EDU_DMA_START + dev_offset; + cmd |= EDU_CMD_DMA_TO; + } + + edu_reg_writeq(dev, EDU_REG_DMA_SRC, from); + edu_reg_writeq(dev, EDU_REG_DMA_DST, to); + edu_reg_writeq(dev, EDU_REG_DMA_COUNT, size); + edu_reg_writel(dev, EDU_REG_DMA_CMD, cmd); + + /* Wait until DMA finished */ + while (edu_reg_readl(dev, EDU_REG_DMA_CMD) & EDU_CMD_DMA_START) + cpu_relax(); +} diff --git a/lib/pci-edu.h b/lib/pci-edu.h new file mode 100644 index 000..8395ebe --- /dev/null +++ b/lib/pci-edu.h @@ -0,0 +1,83 @@ +/* + * Edu PCI device header. + * + * Copyright (C) 2016 Red Hat, Inc. + * + * Authors: + * Peter Xu , + * + * This work is licensed under the terms of the GNU LGPL, version 2 or + * later. + * + * Edu device is a virtualized device in QEMU. Please refer to + * docs/specs/edu.txt in QEMU repository for EDU device manual. + */ +#ifndef __PCI_EDU_H__ +#define __PCI_EDU_H__ + +#include "pci.h" +#include "asm/io.h" + +#define PCI_VENDOR_ID_QEMU 0x1234 +#define PCI_DEVICE_ID_EDU 0x11e8 + +/* The only bar used by EDU device */ +#define EDU_BAR 0 +#define EDU_MAGIC 0xed +#define EDU_VERSION 0x100 +#define EDU_DMA_BUF_SIZE(1 << 20) +#define EDU_INPUT_BUF_SIZE 256 + +#define EDU_REG_ID 0x0 +#define EDU_REG_ALIVE 0x4 +#define EDU_REG_FACTORIAL 0x8 +#define EDU_REG_STATUS 0x20 +#define EDU_REG_DMA_SRC 0x80 +#define EDU_REG_DMA_DST 0x88 +#define EDU_REG_DMA_COUNT 0x90 +#define EDU_REG_DMA_CMD 0x98 + +#define EDU_CMD_DMA_START 0x01 +#define EDU_CMD_DMA_FROM0x02 +#define EDU_CMD_DMA_TO 0x00 + +#define EDU_STATUS_FACTORIAL0x1 +#define EDU_STATUS_INT_ENABLE 0x80 + +#define EDU_DMA_START 0x4 +#define EDU_DMA_SIZE_MAX4096 + +struct pci_edu_dev { + struct pci_dev pci_dev; + volatile void *reg_base; +}; + +#define edu_reg(d, r) (volatile void *)((d)->reg_base + (r)) + +static inline uint64_t edu_reg_readq(struct pci_edu_dev *dev, int reg) +{ + return __raw_readq(edu_reg(dev, reg)); +} + +static inline uint32_t edu_reg_readl(struct pci_edu_dev *dev, int reg) +{ + return __raw_readl(edu_reg(dev, reg)); +} + +static inline void edu_reg_writeq(struct pci_edu_dev *dev, int reg, +
[Qemu-devel] [kvm-unit-tests PATCH v8 12/14] x86: intel-iommu: add dmar test
DMAR test is based on QEMU edu device. A 4B DMA memory copy is carried out as the simplest DMAR test. Signed-off-by: Peter Xu --- lib/pci.h | 5 ++ lib/x86/intel-iommu.c | 133 ++ lib/x86/intel-iommu.h | 4 ++ x86/Makefile.common | 1 + x86/intel-iommu.c | 51 +++ 5 files changed, 194 insertions(+) diff --git a/lib/pci.h b/lib/pci.h index d3052ef..26968b1 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -18,6 +18,9 @@ enum { #define PCI_BAR_NUM 6 #define PCI_DEVFN_MAX 256 +#define PCI_BDF_GET_DEVFN(x)((x) & 0xff) +#define PCI_BDF_GET_BUS(x) (((x) >> 8) & 0xff) + struct pci_dev { uint16_t bdf; phys_addr_t resource[PCI_BAR_NUM]; @@ -28,6 +31,8 @@ extern void pci_scan_bars(struct pci_dev *dev); extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr); extern void pci_enable_defaults(struct pci_dev *dev); +typedef phys_addr_t iova_t; + extern bool pci_probe(void); extern void pci_print(void); extern bool pci_dev_exists(pcidevaddr_t dev); diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c index 1887998..86b1805 100644 --- a/lib/x86/intel-iommu.c +++ b/lib/x86/intel-iommu.c @@ -11,6 +11,42 @@ */ #include "intel-iommu.h" +#include "libcflat.h" + +/* + * VT-d in QEMU currently only support 39 bits address width, which is + * 3-level translation. + */ +#define VTD_PAGE_LEVEL 3 +#define VTD_CE_AW_39BIT 0x1 + +typedef uint64_t vtd_pte_t; + +struct vtd_root_entry { + /* Quad 1 */ + uint64_t present:1; + uint64_t __reserved:11; + uint64_t context_table_p:52; + /* Quad 2 */ + uint64_t __reserved_2; +} __attribute__ ((packed)); +typedef struct vtd_root_entry vtd_re_t; + +struct vtd_context_entry { + /* Quad 1 */ + uint64_t present:1; + uint64_t disable_fault_report:1; + uint64_t trans_type:2; + uint64_t __reserved:8; + uint64_t slptptr:52; + /* Quad 2 */ + uint64_t addr_width:3; + uint64_t __ignore:4; + uint64_t __reserved_2:1; + uint64_t domain_id:16; + uint64_t __reserved_3:40; +} __attribute__ ((packed)); +typedef struct vtd_context_entry vtd_ce_t; #define VTD_RTA_MASK (PAGE_MASK) #define VTD_IRTA_MASK (PAGE_MASK) @@ -83,6 +119,103 @@ static void vtd_setup_ir_table(void) printf("IR table address: 0x%016lx\n", vtd_ir_table()); } +static void vtd_install_pte(vtd_pte_t *root, iova_t iova, + phys_addr_t pa, int level_target) +{ + int level; + unsigned int offset; + void *page; + + for (level = VTD_PAGE_LEVEL; level > level_target; level--) { + offset = PGDIR_OFFSET(iova, level); + if (!(root[offset] & VTD_PTE_RW)) { + page = alloc_page(); + memset(page, 0, PAGE_SIZE); + root[offset] = virt_to_phys(page) | VTD_PTE_RW; + } + root = (uint64_t *)(phys_to_virt(root[offset] & +VTD_PTE_ADDR)); + } + + offset = PGDIR_OFFSET(iova, level); + root[offset] = pa | VTD_PTE_RW; + if (level != 1) { + /* This is huge page */ + root[offset] |= VTD_PTE_HUGE; + } +} + +#define VTD_PHYS_TO_VIRT(x) \ + ((void *)(((uint64_t)phys_to_virt(x)) >> VTD_PAGE_SHIFT)) + +/** + * vtd_map_range: setup IO address mapping for specific memory range + * + * @sid: source ID of the device to setup + * @iova: start IO virtual address + * @pa: start physical address + * @size: size of the mapping area + */ +void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t pa, size_t size) +{ + uint8_t bus_n, devfn; + void *slptptr; + vtd_ce_t *ce; + vtd_re_t *re = phys_to_virt(vtd_root_table()); + + assert(IS_ALIGNED(iova, SZ_4K)); + assert(IS_ALIGNED(pa, SZ_4K)); + assert(IS_ALIGNED(size, SZ_4K)); + + bus_n = PCI_BDF_GET_BUS(sid); + devfn = PCI_BDF_GET_DEVFN(sid); + + /* Point to the correct root entry */ + re += bus_n; + + if (!re->present) { + ce = alloc_page(); + memset(ce, 0, PAGE_SIZE); + memset(re, 0, sizeof(*re)); + re->context_table_p = virt_to_phys(ce) >> VTD_PAGE_SHIFT; + re->present = 1; + printf("allocated vt-d root entry for PCI bus %d\n", + bus_n); + } else + ce = VTD_PHYS_TO_VIRT(re->context_table_p); + + /* Point to the correct context entry */ + ce += devfn; + + if (!ce->present) { + slptptr = alloc_page(); + memset(slptptr, 0, PAGE_SIZE); + memset(ce, 0, sizeof(*ce)); + /* To make it simple, domain ID is the same as SID */ + ce->domain_id = sid; +
Re: [Qemu-devel] [PATCH for-2.9 v2] virtio-crypto: zeroize the key material before free
> -Original Message- > From: Michael S. Tsirkin [mailto:m...@redhat.com] > Sent: Sunday, December 11, 2016 10:51 AM > To: Eric Blake > Cc: Gonglei (Arei); qemu-devel@nongnu.org; stefa...@redhat.com > Subject: Re: [PATCH for-2.9 v2] virtio-crypto: zeroize the key material before > free > > On Thu, Dec 08, 2016 at 09:20:07AM -0600, Eric Blake wrote: > > On 12/07/2016 08:33 PM, Gonglei (Arei) wrote: > > > > >> Sensitive information is sometimes also held in mlocked pages to prevent > > >> it being swapped to disk, but qemu in general is not currently taking > > >> that level of precaution (see also commit 8813800b). > > >> > > >>> > > >>> Let's zeroize the memory of CryptoDevBackendSymOpInfo structure > pointed > > >>> for key material security. > > >>> > > >>> [v2: Stefan perfects the commit message, thanks] > > >> > > >> The v2 blurb should appear after the --- line, as it is nice for > > >> reviewers but a year from now when reading 'git log' we won't care how > > >> many versions were on the list, only about the one version in git. > > >> > > > Yes, you are right. I just wanted to keep the Stefan's work because > > > the most of commit message comes from him. :) > > > > Then I might have written: > > > > [Thanks to Stefan for help with crafting the commit message] > > > > > > > >>> Signed-off-by: Gonglei > > >>> Reviewed-by: Stefan Hajnoczi > > >>> --- > > >>> hw/virtio/virtio-crypto.c | 13 - > > >>> 1 file changed, 12 insertions(+), 1 deletion(-) > > >>> > > >> > > >> The commit message may still need improvement, but the maintainer > might > > >> be willing to do that without needing a v3. At any rate, > > >> Reviewed-by: Eric Blake > > >> > > > Thanks. > > > > We'll see what the maintainer thinks :) > > > > -- > > Eric Blake eblake redhat com+1-919-301-3266 > > Libvirt virtualization library http://libvirt.org > > > > I'd suggest post v3 after 2.8 is out. > OK, will do. Regards, -Gonglei
[Qemu-devel] [kvm-unit-tests PATCH v8 13/14] pci: add msi support for 32/64bit address
pci_cap_walk() is provided to allow walk through all the capability bits for a specific PCI device. If a cap handler is provided, it'll be triggered if the cap is detected along the cap walk. MSI cap handler is the first one supported. We can add more cap handler in the future. Meanwhile, pci_setup_msi() API is provided to support basic 32/64 bit address MSI setup. Reviewed-by: Andrew Jones Signed-off-by: Peter Xu --- lib/pci.c | 69 +++ lib/pci.h | 4 2 files changed, 73 insertions(+) diff --git a/lib/pci.c b/lib/pci.c index bf2a3df..a51eb8e 100644 --- a/lib/pci.c +++ b/lib/pci.c @@ -7,6 +7,74 @@ #include "pci.h" #include "asm/pci.h" +typedef void (*pci_cap_handler)(struct pci_dev *dev, int cap_offset); + +static void pci_cap_msi_handler(struct pci_dev *dev, int cap_offset) +{ + printf("Detected MSI for device 0x%x offset 0x%x\n", + dev->bdf, cap_offset); + dev->msi_offset = cap_offset; +} + +static pci_cap_handler cap_handlers[PCI_CAP_ID_MAX + 1] = { + [PCI_CAP_ID_MSI] = pci_cap_msi_handler, +}; + +void pci_cap_walk(struct pci_dev *dev) +{ + uint8_t cap_offset; + uint8_t cap_id; + int count = 0; + + cap_offset = pci_config_readb(dev->bdf, PCI_CAPABILITY_LIST); + while (cap_offset) { + cap_id = pci_config_readb(dev->bdf, cap_offset); + printf("PCI detected cap 0x%x\n", cap_id); + assert(cap_id < PCI_CAP_ID_MAX + 1); + if (cap_handlers[cap_id]) + cap_handlers[cap_id](dev, cap_offset); + cap_offset = pci_config_readb(dev->bdf, cap_offset + 1); + /* Avoid dead loop during cap walk */ + assert(++count <= 255); + } +} + +bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr, uint32_t msi_data) +{ + uint16_t msi_control; + uint16_t offset; + pcidevaddr_t addr; + + assert(dev); + + if (!dev->msi_offset) { + printf("MSI: dev 0x%x does not support MSI.\n", dev->bdf); + return false; + } + + addr = dev->bdf; + offset = dev->msi_offset; + msi_control = pci_config_readw(addr, offset + PCI_MSI_FLAGS); + pci_config_writel(addr, offset + PCI_MSI_ADDRESS_LO, + msi_addr & 0x); + + if (msi_control & PCI_MSI_FLAGS_64BIT) { + pci_config_writel(addr, offset + PCI_MSI_ADDRESS_HI, + (uint32_t)(msi_addr >> 32)); + pci_config_writel(addr, offset + PCI_MSI_DATA_64, msi_data); + printf("MSI: dev 0x%x init 64bit address: ", addr); + } else { + pci_config_writel(addr, offset + PCI_MSI_DATA_32, msi_data); + printf("MSI: dev 0x%x init 32bit address: ", addr); + } + printf("addr=0x%lx, data=0x%x\n", msi_addr, msi_data); + + msi_control |= PCI_MSI_FLAGS_ENABLE; + pci_config_writew(addr, offset + PCI_MSI_FLAGS, msi_control); + + return true; +} + void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr) { uint16_t val = pci_config_readw(dev->bdf, PCI_COMMAND); @@ -260,4 +328,5 @@ void pci_enable_defaults(struct pci_dev *dev) pci_scan_bars(dev); /* Enable device DMA operations */ pci_cmd_set_clr(dev, PCI_COMMAND_MASTER, 0); + pci_cap_walk(dev); } diff --git a/lib/pci.h b/lib/pci.h index 26968b1..e71a05d 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -23,13 +23,17 @@ enum { struct pci_dev { uint16_t bdf; + uint16_t msi_offset; phys_addr_t resource[PCI_BAR_NUM]; }; extern void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf); extern void pci_scan_bars(struct pci_dev *dev); extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr); +extern void pci_cap_walk(struct pci_dev *dev); extern void pci_enable_defaults(struct pci_dev *dev); +extern bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr, + uint32_t msi_data); typedef phys_addr_t iova_t; -- 2.7.4
[Qemu-devel] [kvm-unit-tests PATCH v8 14/14] x86: intel-iommu: add IR MSI test
First of all, vtd_setup_msi() is provided. It setup IRTE entries, meanwhile, setup PCI device MSI vectors corresponding to VT-d spec. Meanwhile, IR MSI test is added to intel IOMMU unit test. The basic IR test is carried out by a edu INTR raise request. When write to the intr raise register, interrupt will be generated. Type of interrupt will depend on the setup (either INTx or MSI). Signed-off-by: Peter Xu --- lib/pci-edu.h | 1 + lib/x86/intel-iommu.c | 94 +++ lib/x86/intel-iommu.h | 1 + x86/intel-iommu.c | 44 +++- 4 files changed, 139 insertions(+), 1 deletion(-) diff --git a/lib/pci-edu.h b/lib/pci-edu.h index 8395ebe..9fe32c6 100644 --- a/lib/pci-edu.h +++ b/lib/pci-edu.h @@ -32,6 +32,7 @@ #define EDU_REG_ALIVE 0x4 #define EDU_REG_FACTORIAL 0x8 #define EDU_REG_STATUS 0x20 +#define EDU_REG_INTR_RAISE 0x60 #define EDU_REG_DMA_SRC 0x80 #define EDU_REG_DMA_DST 0x88 #define EDU_REG_DMA_COUNT 0x90 diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c index 86b1805..20b9240 100644 --- a/lib/x86/intel-iommu.c +++ b/lib/x86/intel-iommu.c @@ -12,6 +12,7 @@ #include "intel-iommu.h" #include "libcflat.h" +#include "pci.h" /* * VT-d in QEMU currently only support 39 bits address width, which is @@ -48,6 +49,26 @@ struct vtd_context_entry { } __attribute__ ((packed)); typedef struct vtd_context_entry vtd_ce_t; +struct vtd_irte { + uint32_t present:1; + uint32_t fault_disable:1;/* Fault Processing Disable */ + uint32_t dest_mode:1;/* Destination Mode */ + uint32_t redir_hint:1; /* Redirection Hint */ + uint32_t trigger_mode:1; /* Trigger Mode */ + uint32_t delivery_mode:3;/* Delivery Mode */ + uint32_t __avail:4; /* Available spaces for software */ + uint32_t __reserved_0:3; /* Reserved 0 */ + uint32_t irte_mode:1;/* IRTE Mode */ + uint32_t vector:8; /* Interrupt Vector */ + uint32_t __reserved_1:8; /* Reserved 1 */ + uint32_t dest_id;/* Destination ID */ + uint16_t source_id:16; /* Source-ID */ + uint64_t sid_q:2;/* Source-ID Qualifier */ + uint64_t sid_vtype:2;/* Source-ID Validation Type */ + uint64_t __reserved_2:44;/* Reserved 2 */ +} __attribute__ ((packed)); +typedef struct vtd_irte vtd_irte_t; + #define VTD_RTA_MASK (PAGE_MASK) #define VTD_IRTA_MASK (PAGE_MASK) @@ -216,6 +237,79 @@ void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t pa, size_t size) } } +static uint16_t vtd_intr_index_alloc(void) +{ + static int index_ctr = 0; + assert(index_ctr < 65535); + return index_ctr++; +} + +static void vtd_setup_irte(struct pci_dev *dev, vtd_irte_t *irte, + int vector, int dest_id) +{ + assert(sizeof(vtd_irte_t) == 16); + memset(irte, 0, sizeof(*irte)); + irte->fault_disable = 1; + irte->dest_mode = 0; /* physical */ + irte->trigger_mode = 0; /* edge */ + irte->delivery_mode = 0; /* fixed */ + irte->irte_mode = 0; /* remapped */ + irte->vector = vector; + irte->dest_id = dest_id; + irte->source_id = dev->bdf; + irte->sid_q = 0; + irte->sid_vtype = 1; /* full-sid verify */ + irte->present = 1; +} + +struct vtd_msi_addr { + uint32_t __dont_care:2; + uint32_t handle_15:1;/* handle[15] */ + uint32_t shv:1; + uint32_t interrupt_format:1; + uint32_t handle_0_14:15; /* handle[0:14] */ + uint32_t head:12;/* 0xfee */ + uint32_t addr_hi;/* not used except with x2apic */ +} __attribute__ ((packed)); +typedef struct vtd_msi_addr vtd_msi_addr_t; + +struct vtd_msi_data { + uint16_t __reserved; + uint16_t subhandle; +} __attribute__ ((packed)); +typedef struct vtd_msi_data vtd_msi_data_t; + +/** + * vtd_setup_msi - setup MSI message for a device + * + * @dev: PCI device to setup MSI + * @vector: interrupt vector + * @dest_id: destination processor + */ +bool vtd_setup_msi(struct pci_dev *dev, int vector, int dest_id) +{ + vtd_msi_data_t msi_data = {}; + vtd_msi_addr_t msi_addr = {}; + vtd_irte_t *irte = phys_to_virt(vtd_ir_table()); + uint16_t index = vtd_intr_index_alloc(); + + assert(sizeof(vtd_msi_addr_t) == 8); + assert(sizeof(vtd_msi_data_t) == 4); + + printf("INTR: setup IRTE index %d\n", index); + vtd_setup_irte(dev, irte + index, vector, dest_id); + + msi_addr.handle_15 = index >> 15 & 1; + msi_addr.shv = 0; + msi_addr.interrupt_format = 1; + msi_addr.handle_0_14 = index & 0x7fff; + msi_addr.head = 0xfee; + msi_data.subhandle = 0; + + return pci_setup_msi(dev, *(uint64_t *)&msi_addr, +*(uint32_t
Re: [Qemu-devel] [PATCH for-2.9 0/3] cryptodev: prepare works for hotplug
> > From: Michael S. Tsirkin [mailto:m...@redhat.com] > Sent: Sunday, December 11, 2016 11:38 AM > To: Gonglei (Arei) > Cc: qemu-devel@nongnu.org; Wubin (H); longpeng > Subject: Re: [PATCH for-2.9 0/3] cryptodev: prepare works for hotplug > > On Mon, Dec 05, 2016 at 11:27:09AM +0800, Gonglei wrote: > > The patch set make the cryptodev object can be hot plugging > > in safety, and which are preparing works for virtio-crypto > > device hotpulgging. > > > Thanks, pls remember to ping after 2.8 is out. > OK, the v2 will be posted with virtio-crypto device hotplugging function. Regards, -Gonglei > > Gonglei (3): > > cryptodev: introduce a new is_used property > > cryptodev: wrap the ready flag > > virtio-crypto: avoid one cryptodev device is used by multiple virtio > > crypto devices > > > > backends/cryptodev-builtin.c | 4 > > backends/cryptodev.c | 34 > ++ > > hw/virtio/virtio-crypto.c| 22 +++--- > > include/sysemu/cryptodev.h | 42 > ++ > > 4 files changed, 95 insertions(+), 7 deletions(-) > > > > -- > > 1.8.3.1 > >
Re: [Qemu-devel] experience with SDL2, event loop & main thread
On Sat, 12/10 18:16, Liviu Ionescu wrote: > conclusions: > > - the graphical event loop and all graphical primitives must be called from > the main thread context > - in qemu this is not possible directly; an inefficient but functional > solution uses a timer programmed to call a function every few milliseconds, to > poll the event loop. (if the qemu I/O event loop is executed on the main > thread, the timer function will be called from the main thread context) Isn't it possible to notify the main thread with an EventNotifier and process the deferred events in its handler? Fam > - all graphical operations initiated by the all other thread (like the > emulator thread), must be deferred (in SDL using user events) to the > graphical event loop > - a function to run graphical destruction must be registered with atexit() > - only the main thread can call exit(), to ensure the destruction functions > are not called from other threads > - exiting from other threads must be also deferred to the main thread, > possibly with unlocking a mutex. > > > I hope that helps, > > Liviu > > > > > > >
[Qemu-devel] [PATCHv3 3/5] pseries: Implement HPT resizing
This patch implements hypercalls allowing a PAPR guest to resize its own hash page table. This will eventually allow for more flexible memory hotplug. The implementation is partially asynchronous, handled in a special thread running the hpt_prepare_thread() function. The state of a pending resize is stored in SPAPR_MACHINE->pending_hpt. The H_RESIZE_HPT_PREPARE hypercall will kick off creation of a new HPT, or, if one is already in progress, monitor it for completion. If there is an existing HPT resize in progress that doesn't match the size specified in the call, it will cancel it, replacing it with a new one matching the given size. The H_RESIZE_HPT_COMMIT completes transition to a resized HPT, and can only be called successfully once H_RESIZE_HPT_PREPARE has successfully completed initialization of a new HPT. The guest must ensure that there are no concurrent accesses to the existing HPT while this is called (this effectively means stop_machine() for Linux guests). For now H_RESIZE_HPT_COMMIT goes through the whole old HPT, rehashing each HPTE into the new HPT. This can have quite high latency, but it seems to be of the order of typical migration downtime latencies for HPTs of size up to ~2GiB (which would be used in a 256GiB guest). In future we probably want to move more of the rehashing to the "prepare" phase, by having H_ENTER and other hcalls update both current and pending HPTs. That's a project for another day, but should be possible without any changes to the guest interface. Signed-off-by: David Gibson --- hw/ppc/spapr.c | 4 +- hw/ppc/spapr_hcall.c| 345 +++- include/hw/ppc/spapr.h | 6 + target-ppc/mmu-hash64.h | 4 + 4 files changed, 353 insertions(+), 6 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 846ce51..d057031 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -93,8 +93,6 @@ #define PHANDLE_XICP0x -#define HTAB_SIZE(spapr)(1ULL << ((spapr)->htab_shift)) - static XICSState *try_create_xics(const char *type, int nr_servers, int nr_irqs, Error **errp) { @@ -1055,7 +1053,7 @@ static void close_htab_fd(sPAPRMachineState *spapr) spapr->htab_fd = -1; } -static int spapr_hpt_shift_for_ramsize(uint64_t ramsize) +int spapr_hpt_shift_for_ramsize(uint64_t ramsize) { int shift; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 72a9c4d..1e89061 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -2,6 +2,7 @@ #include "qapi/error.h" #include "sysemu/sysemu.h" #include "qemu/log.h" +#include "qemu/error-report.h" #include "cpu.h" #include "exec/exec-all.h" #include "helper_regs.h" @@ -355,20 +356,319 @@ static target_ulong h_read(PowerPCCPU *cpu, sPAPRMachineState *spapr, return H_SUCCESS; } +struct sPAPRPendingHPT { +/* These fields are read-only after initialization */ +int shift; +QemuThread thread; + +/* These fields are protected by the BQL */ +bool complete; + +/* These fields are private to the preparation thread if + * !complete, otherwise protected by the BQL */ +int ret; +void *hpt; +}; + +static void free_pending_hpt(sPAPRPendingHPT *pending) +{ +if (pending->hpt) { +qemu_vfree(pending->hpt); +} + +g_free(pending); +} + +static void *hpt_prepare_thread(void *opaque) +{ +sPAPRPendingHPT *pending = opaque; +size_t size = 1ULL << pending->shift; + +pending->hpt = qemu_memalign(size, size); +if (pending->hpt) { +memset(pending->hpt, 0, size); +pending->ret = H_SUCCESS; +} else { +pending->ret = H_NO_MEM; +} + +qemu_mutex_lock_iothread(); + +if (SPAPR_MACHINE(qdev_get_machine())->pending_hpt == pending) { +/* Ready to go */ +pending->complete = true; +} else { +/* We've been cancelled, clean ourselves up */ +free_pending_hpt(pending); +} + +qemu_mutex_unlock_iothread(); +return NULL; +} + +/* Must be called with BQL held */ +static void cancel_hpt_prepare(sPAPRMachineState *spapr) +{ +sPAPRPendingHPT *pending = spapr->pending_hpt; + +/* Let the thread know it's cancelled */ +spapr->pending_hpt = NULL; + +if (!pending) { +/* Nothing to do */ +return; +} + +if (!pending->complete) { +/* thread will clean itself up */ +return; +} + +free_pending_hpt(pending); +} + +static int build_dimm_list(Object *obj, void *opaque) +{ +GSList **list = opaque; + +if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { +DeviceState *dev = DEVICE(obj); +if (dev->realized) { /* only realized DIMMs matter */ +*list = g_slist_prepend(*list, dev); +} +} + +object_child_foreach(obj, build_dimm_list, opaque); +return 0; +} + +static ram_addr_t get_current_ram_size(void) +{ +GSList *list = NULL, *item; +ram_addr_t size = ram_size
[Qemu-devel] [PATCHv3 1/5] pseries: Add pseries-2.9 machine type
Signed-off-by: David Gibson Reviewed-by: Thomas Huth Reviewed-by: Laurent Vivier --- hw/ppc/spapr.c | 23 +-- include/hw/compat.h | 3 +++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index cfadc46..0f25e83 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2761,18 +2761,37 @@ static const TypeInfo spapr_machine_info = { type_init(spapr_machine_register_##suffix) /* + * pseries-2.9 + */ +static void spapr_machine_2_9_instance_options(MachineState *machine) +{ +} + +static void spapr_machine_2_9_class_options(MachineClass *mc) +{ +/* Defaults for the latest behaviour inherited from the base class */ +} + +DEFINE_SPAPR_MACHINE(2_9, "2.9", true); + +/* * pseries-2.8 */ +#define SPAPR_COMPAT_2_8\ +HW_COMPAT_2_8 + static void spapr_machine_2_8_instance_options(MachineState *machine) { +spapr_machine_2_9_instance_options(machine); } static void spapr_machine_2_8_class_options(MachineClass *mc) { -/* Defaults for the latest behaviour inherited from the base class */ +spapr_machine_2_9_class_options(mc); +SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_8); } -DEFINE_SPAPR_MACHINE(2_8, "2.8", true); +DEFINE_SPAPR_MACHINE(2_8, "2.8", false); /* * pseries-2.7 diff --git a/include/hw/compat.h b/include/hw/compat.h index 0f06e11..f8b8354 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -1,6 +1,9 @@ #ifndef HW_COMPAT_H #define HW_COMPAT_H +#define HW_COMPAT_2_8 \ +/* empty */ + #define HW_COMPAT_2_7 \ {\ .driver = "virtio-pci",\ -- 2.9.3
[Qemu-devel] [PATCHv3 2/5] pseries: Stubs for HPT resizing
This introduces stub implementations of the H_RESIZE_HPT_PREPARE and H_RESIZE_HPT_COMMIT hypercalls which we hope to add in a PAPR extension to allow run time resizing of a guest's hash page table. It also adds a new machine property for controlling whether this new facility is available, and logic to check that against availability with KVM (only supported with KVM PR for now). Finally, it adds a new string to the hypertas property in the device tree, advertising to the guest the availability of the HPT resizing hypercalls. This is a tentative suggested value, and would need to be standardized by PAPR before being merged. Signed-off-by: David Gibson --- hw/ppc/spapr.c | 75 ++ hw/ppc/spapr_hcall.c | 36 hw/ppc/trace-events| 2 ++ include/hw/ppc/spapr.h | 11 target-ppc/kvm.c | 25 + target-ppc/kvm_ppc.h | 5 6 files changed, 154 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 0f25e83..846ce51 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -760,6 +760,11 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt) if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { add_str(hypertas, "hcall-multi-tce"); } + +if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { +add_str(hypertas, "hcall-hpt-resize"); +} + _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", hypertas->str, hypertas->len)); g_string_free(hypertas, TRUE); @@ -1839,11 +1844,40 @@ static void ppc_spapr_init(MachineState *machine) long load_limit, fw_size; char *filename; int smt = kvmppc_smt_threads(); +Error *resize_hpt_err = NULL; msi_nonbroken = true; QLIST_INIT(&spapr->phbs); +/* Check HPT resizing availability */ +kvmppc_check_papr_resize_hpt(&resize_hpt_err); +if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) { +/* + * If the user explicitly requested a mode we should either + * supply it, or fail completely (which we do below). But if + * it's not set explicitly, we reset our mode to something + * that works + */ +if (resize_hpt_err) { +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; +error_free(resize_hpt_err); +resize_hpt_err = NULL; +} else { +spapr->resize_hpt = smc->resize_hpt_default; +} +} + +assert(spapr->resize_hpt != SPAPR_RESIZE_HPT_DEFAULT); + +if ((spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) && resize_hpt_err) { +/* + * User requested HPT resize, but this host can't supply it. Bail out + */ +error_report_err(resize_hpt_err); +exit(1); +} + /* Allocate RMA if necessary */ rma_alloc_size = kvmppc_alloc_rma(&rma); @@ -2236,6 +2270,40 @@ static void spapr_set_modern_hotplug_events(Object *obj, bool value, spapr->use_hotplug_event_source = value; } +static char *spapr_get_resize_hpt(Object *obj, Error **errp) +{ +sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + +switch (spapr->resize_hpt) { +case SPAPR_RESIZE_HPT_DEFAULT: +return g_strdup("default"); +case SPAPR_RESIZE_HPT_DISABLED: +return g_strdup("disabled"); +case SPAPR_RESIZE_HPT_ENABLED: +return g_strdup("enabled"); +case SPAPR_RESIZE_HPT_REQUIRED: +return g_strdup("required"); +} +assert(0); +} + +static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) +{ +sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + +if (strcmp(value, "default") == 0) { +spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT; +} else if (strcmp(value, "disabled") == 0) { +spapr->resize_hpt = SPAPR_RESIZE_HPT_DISABLED; +} else if (strcmp(value, "enabled") == 0) { +spapr->resize_hpt = SPAPR_RESIZE_HPT_ENABLED; +} else if (strcmp(value, "required") == 0) { +spapr->resize_hpt = SPAPR_RESIZE_HPT_REQUIRED; +} else { +error_setg(errp, "Bad value for \"resize-hpt\" property"); +} +} + static void spapr_machine_initfn(Object *obj) { sPAPRMachineState *spapr = SPAPR_MACHINE(obj); @@ -2256,6 +2324,12 @@ static void spapr_machine_initfn(Object *obj) " place of standard EPOW events when possible" " (required for memory hot-unplug support)", NULL); + +object_property_add_str(obj, "resize-hpt", +spapr_get_resize_hpt, spapr_set_resize_hpt, NULL); +object_property_set_description(obj, "resize-hpt", +"Resizing of the Hash Page Table (enabled, disabled, required)", +NULL); } static void spapr_machine_finalizefn(Object *obj) @@ -2707,6 +2781,7 @@ static void spapr_machine_class_i
[Qemu-devel] [PATCHv3 5/5] pseries: Use smaller default hash page tables when guest can resize
We've now implemented a PAPR extension allowing PAPR guest to resize their hash page table (HPT) during runtime. This patch makes use of that facility to allocate smaller HPTs by default. Specifically when a guest is aware of the HPT resize facility, qemu sizes the HPT to the initial memory size, rather than the maximum memory size on the assumption that the guest will resize its HPT if necessary for hot plugged memory. When the initial memory size is much smaller than the maximum memory size (a common configuration with e.g. oVirt / RHEV) then this can save significant memory on the HPT. If the guest does *not* advertise HPT resize awareness when it makes the ibm,client-architecture-support call, qemu resizes the HPT for maxmimum memory size (unless it's been configured not to allow such guests at all). For now we make that reallocation assuming the guest has not yet used the HPT at all. That's true in practice, but not, strictly, an architectural or PAPR requirement. If we need to in future we can fix this by having the client-architecture-support call reboot the guest with the revised HPT size (the client-architecture-support call is explicitly permitted to trigger a reboot in this way). Signed-off-by: David Gibson --- hw/ppc/spapr.c | 21 - hw/ppc/spapr_hcall.c| 32 include/hw/ppc/spapr.h | 2 ++ include/hw/ppc/spapr_ovec.h | 1 + 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index f05d0e5..51b189d 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1066,8 +1066,8 @@ int spapr_hpt_shift_for_ramsize(uint64_t ramsize) return shift; } -static void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, - Error **errp) +void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, + Error **errp) { long rc; @@ -1140,14 +1140,20 @@ static void ppc_spapr_reset(void) hwaddr rtas_addr, fdt_addr; void *fdt; int rc; +int hpt_shift; /* Check for unknown sysbus devices */ foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); /* Allocate and/or reset the hash page table */ -spapr_reallocate_hpt(spapr, - spapr_hpt_shift_for_ramsize(machine->maxram_size), - &error_fatal); +if ((spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) +|| (spapr->cas_reboot +&& !spapr_ovec_test(spapr->ov5_cas, OV5_HPT_RESIZE))) { +hpt_shift = spapr_hpt_shift_for_ramsize(machine->maxram_size); +} else { +hpt_shift = spapr_hpt_shift_for_ramsize(machine->ram_size); +} +spapr_reallocate_hpt(spapr, hpt_shift, &error_fatal); /* Update the RMA size if necessary */ if (spapr->vrma_adjust) { @@ -1941,6 +1947,11 @@ static void ppc_spapr_init(MachineState *machine) spapr_ovec_set(spapr->ov5, OV5_HP_EVT); } +/* advertise support for HPT resizing */ +if (spapr->resize_hpt != SPAPR_RESIZE_HPT_DISABLED) { +spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); +} + /* init CPUs */ if (machine->cpu_model == NULL) { machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 1e89061..5bebfc3 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1415,6 +1415,38 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, ov5_guest = spapr_ovec_parse_vector(ov_table, 5); +/* + * HPT resizing is a bit of a special case, because when enabled + * we assume the guest will support it until it says it doesn't, + * instead of assuming it won't support it until it says it does. + * Strictly speaking that approach could break for guests which + * don't make a CAS call, but those are so old we don't care about + * them. Without that assumption we'd have to make at least a + * temporary allocation of an HPT sized for max memory, which + * could be impossibly difficult under KVM HV if maxram is large. + */ +if (!spapr_ovec_test(ov5_guest, OV5_HPT_RESIZE)) { +int maxshift = spapr_hpt_shift_for_ramsize(MACHINE(spapr)->maxram_size); + +if (spapr->resize_hpt == SPAPR_RESIZE_HPT_REQUIRED) { +error_report( +"h_client_architecture_support: Guest doesn't support HPT resizing, but resize-hpt=required"); +exit(1); +} + +if (spapr->htab_shift < maxshift) { +CPUState *cs; +/* Guest doesn't know about HPT resizing, so we + * pre-emptively resize for the maximum permitted RAM. At + * the point this is called, nothing should have been + * entered into the existing HPT */ +spapr_reallocate_hpt(spapr, maxshift, &error_fatal); +CPU_FOREACH(cs) { +run_on_cpu(
[Qemu-devel] [PATCHv3 0/5] Hash Page Table resizing for TCG pseries guests
This series implements the host side of the PAPR ACR to allow runtime resizing of the Hashed Page Table (HPT) for pseries guests. Exercising this feature requires a guest OS which is also aware of it. Patches to implement the guest side in Linux have just been submitted upstream: https://lists.ozlabs.org/pipermail/linuxppc-dev/2016-December/152164.html Availability of the feature is controlled by a new 'resize-hpt' machine option: it can be set to "disabled", "enabled" or "required". The last means that qemu will refuse to boot a guest which is not aware of the HPT resizing feature (it will instead quit during feature negotiation). This is potentially useful because guests which don't support resizing will need an HPT sized for their maximum possible RAM, which can be very wasteful of host resources. So far this is only tested for TCG guests. PR KVM guests should work in theory, but I haven't been able to test yet due to (probably unrelated) problems booting a suitable guest kernel. HV KVM guests will require substantial extra work in the host kernel; development is in progress. Changes since v2: * Some clearer comments based on review * Some minor cleanups based on review David Gibson (5): pseries: Add pseries-2.9 machine type pseries: Stubs for HPT resizing pseries: Implement HPT resizing pseries: Enable HPT resizing for 2.9 pseries: Use smaller default hash page tables when guest can resize hw/ppc/spapr.c | 126 -- hw/ppc/spapr_hcall.c| 407 hw/ppc/trace-events | 2 + include/hw/compat.h | 3 + include/hw/ppc/spapr.h | 19 +++ include/hw/ppc/spapr_ovec.h | 1 + target-ppc/kvm.c| 25 +++ target-ppc/kvm_ppc.h| 5 + target-ppc/mmu-hash64.h | 4 + 9 files changed, 582 insertions(+), 10 deletions(-) -- 2.9.3
Re: [Qemu-devel] [Qemu-ppc] [PATCH v2 5/6] target-ppc: implement xxextractuw instruction
On Mon, Dec 12, 2016 at 09:31:11AM +0530, Nikunj Dadhania wrote: > On 12 December 2016 at 06:00, David Gibson > wrote: > > On Fri, Dec 09, 2016 at 05:47:24PM +0530, Nikunj A Dadhania wrote: > >> xxextractuw: VSX Vector Extract Unsigned Word > >> > >> Signed-off-by: Nikunj A Dadhania > >> --- > >> target-ppc/helper.h | 1 + > >> target-ppc/int_helper.c | 21 + > >> target-ppc/translate/vsx-impl.inc.c | 27 +++ > >> target-ppc/translate/vsx-ops.inc.c | 5 + > >> 4 files changed, 54 insertions(+) > >> > >> diff --git a/target-ppc/helper.h b/target-ppc/helper.h > >> index 4707db4..8b30420 100644 > >> --- a/target-ppc/helper.h > >> +++ b/target-ppc/helper.h > >> @@ -540,6 +540,7 @@ DEF_HELPER_2(xvrspip, void, env, i32) > >> DEF_HELPER_2(xvrspiz, void, env, i32) > >> DEF_HELPER_2(xxperm, void, env, i32) > >> DEF_HELPER_2(xxpermr, void, env, i32) > >> +DEF_HELPER_4(xxextractuw, void, env, tl, tl, i32) > >> > >> DEF_HELPER_2(efscfsi, i32, env, i32) > >> DEF_HELPER_2(efscfui, i32, env, i32) > >> diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c > >> index 7989b1f..e3f66ac 100644 > >> --- a/target-ppc/int_helper.c > >> +++ b/target-ppc/int_helper.c > >> @@ -2033,6 +2033,27 @@ VEXTRACT(uw, u32) > >> VEXTRACT(d, u64) > >> #undef VEXTRACT > >> > >> +void helper_xxextractuw(CPUPPCState *env, target_ulong xtn, > >> +target_ulong xbn, uint32_t index) > >> +{ > >> +ppc_vsr_t xt, xb; > >> +size_t es = sizeof(uint32_t); > >> +uint32_t ext_index; > >> + > >> +getVSR(xbn, &xb, env); > >> +memset(&xt, 0, sizeof(xt)); > >> + > >> +#if defined(HOST_WORDS_BIGENDIAN) > >> +ext_index = index; > >> +memcpy(&xt.u8[8 - es], &xb.u8[ext_index], es); > >> +#else > >> +ext_index = (16 - index) - es; > >> +memcpy(&xt.u8[8], &xb.u8[ext_index], es); > > > > Hm. So, IIUC, ext_index is the byte element - in IBM numbering - to > > start copying from. But I thought that when we have an LE host, the > > IBM byte element ordering is reversed from the actual order in host > > memory, so we'd need &xb.u8[16 - ext_index - es] > > I am not getting you, I am getting index from user. So in case of BE host: > > ext_index = index; > > LE Host: > > ext_index = (16 - index) - es; > > I am already doing that. Am I missing something. Duh, sorry, apparently I'm blind and missed that logic. > >> +#endif > >> + > >> +putVSR(xtn, &xt, env); > >> +} > >> + > >> #define VEXT_SIGNED(name, element, mask, cast, recast) \ > >> void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ > >> { \ > >> diff --git a/target-ppc/translate/vsx-impl.inc.c > >> b/target-ppc/translate/vsx-impl.inc.c > >> index 2a17c35..1c40a35 100644 > >> --- a/target-ppc/translate/vsx-impl.inc.c > >> +++ b/target-ppc/translate/vsx-impl.inc.c > >> @@ -1180,6 +1180,33 @@ static void gen_xxsldwi(DisasContext *ctx) > >> tcg_temp_free_i64(xtl); > >> } > >> > >> +#define VSX_EXTRACT(name) \ > >> +static void gen_##name(DisasContext *ctx) \ > >> +{ \ > >> +TCGv xt, xb;\ > >> +TCGv_i32 t0 = tcg_temp_new_i32(); \ > >> +uint8_t uimm = UIMM4(ctx->opcode); \ > >> +\ > >> +if (unlikely(!ctx->vsx_enabled)) { \ > >> +gen_exception(ctx, POWERPC_EXCP_VSXU); \ > >> +return; \ > >> +} \ > >> +if (uimm > 12) {\ > > > > Throughout the helper you use es == sizeof(uint32_t), but here you > > hardcode the assumption of 4 bytes, seems a bit inconsistent. > > > >> +tcg_gen_movi_i64(cpu_vsrh(xT(ctx->opcode)), 0); \ > >> +tcg_gen_movi_i64(cpu_vsrl(xT(ctx->opcode)), 0); \ > >> +return; \ > > > > So, I know the architecture says it is undefined. But since you're > > testing for the bogus case anyway, why not turn this into an > > exception. That seems like it would be more helpful for debugging the > > guest than just setting the result to zero. Or is this done to match > > actual hardware behaviour? > > I havent had a change to run on the real hardware, but on the system > simulator, it happily > returns extracted content even if UIMM > 12. Hm. Returns what exactly? -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way
[Qemu-devel] [PATCHv3 4/5] pseries: Enable HPT resizing for 2.9
We've now implemented a PAPR extensions which allows PAPR guests (i.e. "pseries" machine type) to resize their hash page table during runtime. However, that extension is only enabled if explicitly chosen on the command line. This patch enables it by default for spapr-2.9, but leaves it disabled (by default) for older machine types. Signed-off-by: David Gibson Reviewed-by: Laurent Vivier --- hw/ppc/spapr.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d057031..f05d0e5 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2779,7 +2779,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) smc->dr_lmb_enabled = true; smc->tcg_default_cpu = "POWER8"; -smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; +smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus; fwc->get_dev_path = spapr_get_fw_dev_path; nc->nmi_monitor_handler = spapr_nmi; @@ -2860,8 +2860,11 @@ static void spapr_machine_2_8_instance_options(MachineState *machine) static void spapr_machine_2_8_class_options(MachineClass *mc) { +sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); + spapr_machine_2_9_class_options(mc); SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_8); +smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; } DEFINE_SPAPR_MACHINE(2_8, "2.8", false); -- 2.9.3
Re: [Qemu-devel] Reproducible crash on PCIe hotplug
On 12/10/2016 04:39 AM, Eduardo Habkost wrote: > Using latest qemu.git master: > > $ qemu-system-x86_64 -machine q35 -readconfig docs/q35-chipset.cfg -monitor > stdio > QEMU 2.7.93 monitor - type 'help' for more information > (qemu) device_add e1000e,bus=ich9-pcie-port-4,addr=00 > (qemu) device_add e1000e,bus=ich9-pcie-port-4,addr=08 > Segmentation fault (core dumped) > > It crashes at: > > #7 0x5598d7dc in do_pci_register_device (errp=0x7fffbfd0, > devfn=64, name=0x565df340 "e1000e", bus=0x58487380, > pci_dev=0x589cd000) > at /home/ehabkost/rh/proj/virt/qemu/hw/pci/pci.c:983 > 983 error_setg(errp, "PCI: slot %d function 0 already ocuppied > by %s," > (gdb) l > 978PCI_SLOT(devfn), PCI_FUNC(devfn), name, > 979bus->devices[devfn]->name); > 980 return NULL; > 981 } else if (dev->hotplugged && > 982pci_get_function_0(pci_dev)) { > 983 error_setg(errp, "PCI: slot %d function 0 already ocuppied > by %s," > 984" new func %s cannot be exposed to guest.", > 985PCI_SLOT(devfn), > 986bus->devices[PCI_DEVFN(PCI_SLOT(devfn), > 0)]->name, > 987name); > Thanks for informing me. I am kind of busy for now, so I suppose I will investigate it after 2.8 release. -- Sincerely, Cao jin
Re: [Qemu-devel] [PATCH v6 2/2] crypto: add virtio-crypto driver
Hi, Michael & Herbert Because the virtio-crypto device emulation had been in QEMU 2.8, would you please merge the virtio-crypto driver for 4.10 if no other comments? If so, Miachel pls ack and/or review the patch, then Herbert will take it (I asked him last week). Thank you! Ps: Note on 4.10 merge window timing from Linus https://lkml.org/lkml/2016/12/7/506 Dec 23rd is the deadline for 4.10 merge window. Regards, -Gonglei > -Original Message- > From: Gonglei (Arei) > Sent: Thursday, December 08, 2016 12:37 PM > Subject: [PATCH v6 2/2] crypto: add virtio-crypto driver > > This patch introduces virtio-crypto driver for Linux Kernel. > > The virtio crypto device is a virtual cryptography device > as well as a kind of virtual hardware accelerator for > virtual machines. The encryption anddecryption requests > are placed in the data queue and are ultimately handled by > thebackend crypto accelerators. The second queue is the > control queue used to create or destroy sessions for > symmetric algorithms and will control some advanced features > in the future. The virtio crypto device provides the following > cryptoservices: CIPHER, MAC, HASH, and AEAD. > > For more information about virtio-crypto device, please see: > http://qemu-project.org/Features/VirtioCrypto > > CC: Michael S. Tsirkin > CC: Cornelia Huck > CC: Stefan Hajnoczi > CC: Herbert Xu > CC: Halil Pasic > CC: David S. Miller > CC: Zeng Xin > Signed-off-by: Gonglei > --- > MAINTAINERS | 9 + > drivers/crypto/Kconfig | 2 + > drivers/crypto/Makefile | 1 + > drivers/crypto/virtio/Kconfig| 10 + > drivers/crypto/virtio/Makefile | 5 + > drivers/crypto/virtio/virtio_crypto_algs.c | 541 > +++ > drivers/crypto/virtio/virtio_crypto_common.h | 122 ++ > drivers/crypto/virtio/virtio_crypto_core.c | 464 > +++ > drivers/crypto/virtio/virtio_crypto_mgr.c| 264 + > include/uapi/linux/Kbuild| 1 + > include/uapi/linux/virtio_crypto.h | 450 > ++ > include/uapi/linux/virtio_ids.h | 1 + > 12 files changed, 1870 insertions(+) > create mode 100644 drivers/crypto/virtio/Kconfig > create mode 100644 drivers/crypto/virtio/Makefile > create mode 100644 drivers/crypto/virtio/virtio_crypto_algs.c > create mode 100644 drivers/crypto/virtio/virtio_crypto_common.h > create mode 100644 drivers/crypto/virtio/virtio_crypto_core.c > create mode 100644 drivers/crypto/virtio/virtio_crypto_mgr.c > create mode 100644 include/uapi/linux/virtio_crypto.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index ad9b965..cccaaf0 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -12810,6 +12810,7 @@ F:drivers/net/virtio_net.c > F: drivers/block/virtio_blk.c > F: include/linux/virtio_*.h > F: include/uapi/linux/virtio_*.h > +F: drivers/crypto/virtio/ > > VIRTIO DRIVERS FOR S390 > M: Christian Borntraeger > @@ -12846,6 +12847,14 @@ S: Maintained > F: drivers/virtio/virtio_input.c > F: include/uapi/linux/virtio_input.h > > +VIRTIO CRYPTO DRIVER > +M: Gonglei > +L: virtualizat...@lists.linux-foundation.org > +L: linux-cry...@vger.kernel.org > +S: Maintained > +F: drivers/crypto/virtio/ > +F: include/uapi/linux/virtio_crypto.h > + > VIA RHINE NETWORK DRIVER > S: Orphan > F: drivers/net/ethernet/via/via-rhine.c > diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig > index 4d2b81f..7956478 100644 > --- a/drivers/crypto/Kconfig > +++ b/drivers/crypto/Kconfig > @@ -555,4 +555,6 @@ config CRYPTO_DEV_ROCKCHIP > > source "drivers/crypto/chelsio/Kconfig" > > +source "drivers/crypto/virtio/Kconfig" > + > endif # CRYPTO_HW > diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile > index ad7250f..bc53cb8 100644 > --- a/drivers/crypto/Makefile > +++ b/drivers/crypto/Makefile > @@ -32,3 +32,4 @@ obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/ > obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/ > obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/ > obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/ > +obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio/ > diff --git a/drivers/crypto/virtio/Kconfig b/drivers/crypto/virtio/Kconfig > new file mode 100644 > index 000..d80f733 > --- /dev/null > +++ b/drivers/crypto/virtio/Kconfig > @@ -0,0 +1,10 @@ > +config CRYPTO_DEV_VIRTIO > + tristate "VirtIO crypto driver" > + depends on VIRTIO > + select CRYPTO_AEAD > + select CRYPTO_AUTHENC > + select CRYPTO_BLKCIPHER > + default m > + help > + This driver provides support for virtio crypto device. If you > + choose 'M' here, this module will be called virtio_crypto. > diff --git a/drivers/crypto/virtio/Makefile b/drivers/crypto/virtio/Makefile > new file mode 100644 > index 000..dd342c9 > --- /dev/null > +++ b/drivers/crypto/virtio/Makefile > @@ -0,0 +1,5 @@ > +
Re: [Qemu-devel] experience with SDL2, event loop & main thread
> On 12 Dec 2016, at 05:35, Fam Zheng wrote: > > Isn't it possible to notify the main thread with an EventNotifier and process > the deferred events in its handler? ideally, the SDL main loop might be re-implemented asynchronously, for example using a pipe to pass the events, and in this case the SDL would be just a regular client of the main I/O loop. any idea how difficult would be to push any changes to SDL? regards, Liviu
[Qemu-devel] [PATCH for-2.9 v1 1/7] qapi: crypto: add defination about HMAC algorithms
This patch introduce HMAC algorithms relevant defination, they will be used by the following patch. Signed-off-by: Longpeng(Mike) --- qapi/crypto.json | 17 + 1 file changed, 17 insertions(+) diff --git a/qapi/crypto.json b/qapi/crypto.json index f4fd93b..e63862a 100644 --- a/qapi/crypto.json +++ b/qapi/crypto.json @@ -55,6 +55,23 @@ ## +# @QCryptoHmacAlgorithm: +# +# The supported algorithms for hash-based message authentication code +# +# @md5: HMAC-MD5 +# @sha1: HMAC-SHA1 +# @sha256: HMAC-SHA256 +# @sha512: HMAC-SHA512 +# +# Since 2.9 +## +{ 'enum': 'QCryptoHmacAlgorithm', + 'prefix': 'QCRYPTO_HMAC_ALG', + 'data': ['md5', 'sha1', 'sha256', 'sha512']} + + +## # @QCryptoCipherAlgorithm: # # The supported algorithms for content encryption ciphers -- 1.8.3.1
[Qemu-devel] [PATCH for-2.9 v1 2/7] crypto: add HMAC algorithms framework
This patch introduce HMAC algorithms framework. Signed-off-by: Longpeng(Mike) --- crypto/Makefile.objs | 4 ++ crypto/hmac-gcrypt.c | 44 ++ crypto/hmac-glib.c | 44 ++ crypto/hmac-nettle.c | 44 ++ crypto/hmac.c| 72 ++ crypto/hmac.h| 166 +++ 6 files changed, 374 insertions(+) create mode 100644 crypto/hmac-gcrypt.c create mode 100644 crypto/hmac-glib.c create mode 100644 crypto/hmac-nettle.c create mode 100644 crypto/hmac.c create mode 100644 crypto/hmac.h diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs index a36d2d9..7978a46 100644 --- a/crypto/Makefile.objs +++ b/crypto/Makefile.objs @@ -3,6 +3,10 @@ crypto-obj-y += hash.o crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hash-glib.o +crypto-obj-y += hmac.o +crypto-obj-$(CONFIG_NETTLE) += hmac-nettle.o +crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hmac-gcrypt.o +crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hmac-glib.o crypto-obj-y += aes.o crypto-obj-y += desrfb.o crypto-obj-y += cipher.o diff --git a/crypto/hmac-gcrypt.c b/crypto/hmac-gcrypt.c new file mode 100644 index 000..26f42bc --- /dev/null +++ b/crypto/hmac-gcrypt.c @@ -0,0 +1,44 @@ +/* + * QEMU Crypto hmac algorithms (based on libgcrypt) + * + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. + * + * Authors: + *Longpeng(Mike) + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "crypto/hmac.h" + +bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg) +{ +return false; +} + +QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg, + const uint8_t *key, size_t nkey, + Error **errp) +{ +return NULL; +} + +void qcrypto_hmac_free(QCryptoHmac *hmac) +{ +return; +} + +int qcrypto_hmac_bytesv(QCryptoHmac *hmac, +const struct iovec *iov, +size_t niov, +uint8_t **result, +size_t *resultlen, +Error **errp) +{ +return -1; +} diff --git a/crypto/hmac-glib.c b/crypto/hmac-glib.c new file mode 100644 index 000..42f63c6 --- /dev/null +++ b/crypto/hmac-glib.c @@ -0,0 +1,44 @@ +/* + * QEMU Crypto hmac algorithms (based on glib) + * + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. + * + * Authors: + *Longpeng(Mike) + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "crypto/hmac.h" + +bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg) +{ +return false; +} + +QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg, + const uint8_t *key, size_t nkey, + Error **errp) +{ +return NULL; +} + +void qcrypto_hmac_free(QCryptoHmac *hmac) +{ +return; +} + +int qcrypto_hmac_bytesv(QCryptoHmac *hmac, +const struct iovec *iov, +size_t niov, +uint8_t **result, +size_t *resultlen, +Error **errp) +{ +return -1; +} diff --git a/crypto/hmac-nettle.c b/crypto/hmac-nettle.c new file mode 100644 index 000..7a9cd2e --- /dev/null +++ b/crypto/hmac-nettle.c @@ -0,0 +1,44 @@ +/* + * QEMU Crypto hmac algorithms (based on nettle) + * + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. + * + * Authors: + *Longpeng(Mike) + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "crypto/hmac.h" + +bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg) +{ +return false; +} + +QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg, + const uint8_t *key, size_t nkey, + Error **errp) +{ +return NULL; +} + +void qcrypto_hmac_free(QCryptoHmac *hmac) +{ +return; +} + +int qcrypto_hmac_bytesv(QCryptoHmac *hmac, +const struct iovec *iov, +size_t niov, +uint8_t **result, +size_t *resultlen, +Error **errp) +{ +return -1; +} diff --git a/crypto/hmac.c b/crypto/hmac.c new file mode 100644 index 000..5750405 --- /dev/null +++ b/crypto/hmac.c @@ -0,0 +1,72 @@ +/* + * QEMU C
[Qemu-devel] [PATCH for-2.9 v1 4/7] crypto: support HMAC algorithms based on libgcrypt
This patch add HMAC algorithms based on libgcrypt support Signed-off-by: Longpeng(Mike) --- crypto/hmac-gcrypt.c | 138 +++ 1 file changed, 138 insertions(+) diff --git a/crypto/hmac-gcrypt.c b/crypto/hmac-gcrypt.c index 26f42bc..6cf3046 100644 --- a/crypto/hmac-gcrypt.c +++ b/crypto/hmac-gcrypt.c @@ -15,6 +15,142 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "crypto/hmac.h" +#include + +#ifdef CONFIG_GCRYPT_SUPPORT_HMAC + +static int qcrypto_hmac_alg_map[QCRYPTO_HMAC_ALG__MAX] = { +[QCRYPTO_HMAC_ALG_MD5] = GCRY_MAC_HMAC_MD5, +[QCRYPTO_HMAC_ALG_SHA1] = GCRY_MAC_HMAC_SHA1, +[QCRYPTO_HMAC_ALG_SHA256] = GCRY_MAC_HMAC_SHA256, +[QCRYPTO_HMAC_ALG_SHA512] = GCRY_MAC_HMAC_SHA512, +}; + +typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt; +struct QCryptoHmacGcrypt { +gcry_mac_hd_t handle; +}; + +bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg) +{ +if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) && +qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) { +return true; +} + +return false; +} + +QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg, + const uint8_t *key, size_t nkey, + Error **errp) +{ +QCryptoHmac *hmac; +QCryptoHmacGcrypt *ctx; +gcry_error_t err; + +if (!qcrypto_hmac_supports(alg)) { +error_setg(errp, "Unsupported hmac algorithm %s", +QCryptoHmacAlgorithm_lookup[alg]); +return NULL; +} + +hmac = g_new0(QCryptoHmac, 1); +hmac->alg = alg; + +ctx = g_new0(QCryptoHmacGcrypt, 1); + +err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg], +GCRY_MAC_FLAG_SECURE, NULL); +if (err != 0) { +error_setg(errp, "Cannot initialize hmac: %s", +gcry_strerror(err)); +goto error; +} + +err = gcry_mac_setkey(ctx->handle, (const void *)key, nkey); +if (err != 0) { +error_setg(errp, "Cannot set key: %s", +gcry_strerror(err)); +goto error; +} + +hmac->opaque = ctx; +return hmac; + +error: +g_free(ctx); +g_free(hmac); +return NULL; +} + +void qcrypto_hmac_free(QCryptoHmac *hmac) +{ +QCryptoHmacGcrypt *ctx; + +if (!hmac) { +return; +} + +ctx = hmac->opaque; +gcry_mac_close(ctx->handle); + +g_free(ctx); +g_free(hmac); +} + +int qcrypto_hmac_bytesv(QCryptoHmac *hmac, +const struct iovec *iov, +size_t niov, +uint8_t **result, +size_t *resultlen, +Error **errp) +{ +QCryptoHmacGcrypt *ctx; +gcry_error_t err; +uint32_t ret; +int i; + +ctx = hmac->opaque; + +for (i = 0; i < niov; i++) { +gcry_mac_write(ctx->handle, iov[i].iov_base, iov[i].iov_len); +} + +ret = gcry_mac_get_algo_maclen(qcrypto_hmac_alg_map[hmac->alg]); +if (ret <= 0) { +error_setg(errp, "Unable to get hmac length: %s", +gcry_strerror(ret)); +return -1; +} + +if (*resultlen == 0) { +*resultlen = ret; +*result = g_new0(uint8_t, *resultlen); +} else if (*resultlen != ret) { +error_setg(errp, "Result buffer size %zu is smaller than hmac %d", +*resultlen, ret); +return -1; +} + +err = gcry_mac_read(ctx->handle, *result, resultlen); +if (err != 0) { +error_setg(errp, "Cannot get result: %s", +gcry_strerror(err)); +return -1; +} + +err = gcry_mac_reset(ctx->handle); +if (err != 0) { +error_setg(errp, "Cannot reset hmac context: %s", +gcry_strerror(err)); +return -1; +} + +return 0; +} + +#else bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg) { @@ -42,3 +178,5 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac, { return -1; } + +#endif -- 1.8.3.1
[Qemu-devel] [PATCH for-2.9 v1 6/7] crypto: support HMAC algorithms based on nettle
This patch add nettle-backed HMAC algorithms support Signed-off-by: Longpeng(Mike) --- crypto/hmac-nettle.c | 118 +-- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/crypto/hmac-nettle.c b/crypto/hmac-nettle.c index 7a9cd2e..a082bc0 100644 --- a/crypto/hmac-nettle.c +++ b/crypto/hmac-nettle.c @@ -15,9 +15,66 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "crypto/hmac.h" +#include + +typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx, +size_t key_length, const uint8_t *key); + +typedef void (*qcrypto_nettle_hmac_update)(void *ctx, +size_t length, const uint8_t *data); + +typedef void (*qcrypto_nettle_hmac_digest)(void *ctx, +size_t length, uint8_t *digest); + +typedef struct QCryptoHmacNettle QCryptoHmacNettle; +struct QCryptoHmacNettle { +union qcrypto_nettle_hmac_ctx { +struct hmac_md5_ctx md5_ctx; +struct hmac_sha1_ctx sha1_ctx; +struct hmac_sha256_ctx sha256_ctx; +struct hmac_sha512_ctx sha512_ctx; +} u; +}; + +struct qcrypto_nettle_hmac_alg { +qcrypto_nettle_hmac_setkey setkey; +qcrypto_nettle_hmac_update update; +qcrypto_nettle_hmac_digest digest; +size_t len; +} qcrypto_hmac_alg_map[QCRYPTO_HMAC_ALG__MAX] = { +[QCRYPTO_HMAC_ALG_MD5] = { +.setkey = (qcrypto_nettle_hmac_setkey)hmac_md5_set_key, +.update = (qcrypto_nettle_hmac_update)hmac_md5_update, +.digest = (qcrypto_nettle_hmac_digest)hmac_md5_digest, +.len = MD5_DIGEST_SIZE, +}, +[QCRYPTO_HMAC_ALG_SHA1] = { +.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha1_set_key, +.update = (qcrypto_nettle_hmac_update)hmac_sha1_update, +.digest = (qcrypto_nettle_hmac_digest)hmac_sha1_digest, +.len = SHA1_DIGEST_SIZE, +}, +[QCRYPTO_HMAC_ALG_SHA256] = { +.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha256_set_key, +.update = (qcrypto_nettle_hmac_update)hmac_sha256_update, +.digest = (qcrypto_nettle_hmac_digest)hmac_sha256_digest, +.len = SHA256_DIGEST_SIZE, +}, +[QCRYPTO_HMAC_ALG_SHA512] = { +.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha512_set_key, +.update = (qcrypto_nettle_hmac_update)hmac_sha512_update, +.digest = (qcrypto_nettle_hmac_digest)hmac_sha512_digest, +.len = SHA512_DIGEST_SIZE, +}, +}; bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg) { +if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) && +qcrypto_hmac_alg_map[alg].setkey != NULL) { +return true; +} + return false; } @@ -25,12 +82,39 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg, const uint8_t *key, size_t nkey, Error **errp) { -return NULL; +QCryptoHmac *hmac; +QCryptoHmacNettle *ctx; + +if (!qcrypto_hmac_supports(alg)) { +error_setg(errp, "Unsupported hmac algorithm %s", +QCryptoHmacAlgorithm_lookup[alg]); +return NULL; +} + +hmac = g_new0(QCryptoHmac, 1); +hmac->alg = alg; + +ctx = g_new0(QCryptoHmacNettle, 1); + +qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key); + +hmac->opaque = ctx; + +return hmac; } void qcrypto_hmac_free(QCryptoHmac *hmac) { -return; +QCryptoHmacNettle *ctx; + +if (!hmac) { +return; +} + +ctx = hmac->opaque; + +g_free(ctx); +g_free(hmac); } int qcrypto_hmac_bytesv(QCryptoHmac *hmac, @@ -40,5 +124,33 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac, size_t *resultlen, Error **errp) { -return -1; +QCryptoHmacNettle *ctx; +int i; + +ctx = (QCryptoHmacNettle *)hmac->opaque; + +for (i = 0; i < niov; ++i) { +size_t len = iov[i].iov_len; +uint8_t *base = iov[i].iov_base; +while (len) { +size_t shortlen = MIN(len, UINT_MAX); +qcrypto_hmac_alg_map[hmac->alg].update(&ctx->u, len, base); +len -= shortlen; +base += len; +} +} + +if (*resultlen == 0) { +*resultlen = qcrypto_hmac_alg_map[hmac->alg].len; +*result = g_new0(uint8_t, *resultlen); +} else if (*resultlen != qcrypto_hmac_alg_map[hmac->alg].len) { +error_setg(errp, + "Result buffer size %zu is smaller than hash %zu", + *resultlen, qcrypto_hmac_alg_map[hmac->alg].len); +return -1; +} + +qcrypto_hmac_alg_map[hmac->alg].digest(&ctx->u, *resultlen, *result); + +return 0; } -- 1.8.3.1
[Qemu-devel] [PATCH for-2.9 v1 0/7] crypto: add HMAC algorithms support
Since QEMU has been supported cryptodev, so it is necessary to support more crypto algorithms(i.e. hmac,aead) in QEMU backend. This patchset add HMAC algorithms support. Longpeng(Mike) (7): qapi: crypto: add defination about HMAC algorithms crypto: add HMAC algorithms framework configure: add CONFIG_GCRYPT_SUPPORT_HMAC item crypto: support HMAC algorithms based on libgcrypt crypto: support HMAC algorithms based on glibc crypto: support HMAC algorithms based on nettle crypto: add HMAC algorithms testcases configure| 18 + crypto/Makefile.objs | 4 ++ crypto/hmac-gcrypt.c | 182 +++ crypto/hmac-glib.c | 163 ++ crypto/hmac-nettle.c | 156 crypto/hmac.c| 72 +++ crypto/hmac.h| 166 ++ qapi/crypto.json | 17 + tests/Makefile.include | 2 + tests/test-crypto-hmac.c | 162 + 10 files changed, 942 insertions(+) create mode 100644 crypto/hmac-gcrypt.c create mode 100644 crypto/hmac-glib.c create mode 100644 crypto/hmac-nettle.c create mode 100644 crypto/hmac.c create mode 100644 crypto/hmac.h create mode 100644 tests/test-crypto-hmac.c -- 1.8.3.1
[Qemu-devel] [PATCH for-2.9 v1 7/7] crypto: add HMAC algorithms testcases
This patch add HMAC algorithms testcases Signed-off-by: Longpeng(Mike) --- tests/Makefile.include | 2 + tests/test-crypto-hmac.c | 162 +++ 2 files changed, 164 insertions(+) create mode 100644 tests/test-crypto-hmac.c diff --git a/tests/Makefile.include b/tests/Makefile.include index e98d3b6..4841d58 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -91,6 +91,7 @@ gcov-files-test-qemu-opts-y = qom/test-qemu-opts.c check-unit-y += tests/test-write-threshold$(EXESUF) gcov-files-test-write-threshold-y = block/write-threshold.c check-unit-y += tests/test-crypto-hash$(EXESUF) +check-unit-y += tests/test-crypto-hmac$(EXESUF) check-unit-y += tests/test-crypto-cipher$(EXESUF) check-unit-y += tests/test-crypto-secret$(EXESUF) check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF) @@ -571,6 +572,7 @@ tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y) tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y) tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y) +tests/test-crypto-hmac$(EXESUF): tests/test-crypto-hmac.o $(test-crypto-obj-y) tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y) tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o $(test-crypto-obj-y) tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y) diff --git a/tests/test-crypto-hmac.c b/tests/test-crypto-hmac.c new file mode 100644 index 000..08e1887 --- /dev/null +++ b/tests/test-crypto-hmac.c @@ -0,0 +1,162 @@ +/* + * QEMU Crypto hmac algorithms tests + * + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. + * + * Authors: + *Longpeng(Mike) + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "crypto/init.h" +#include "crypto/hmac.h" + +typedef struct QCryptoHmacTestData QCryptoHmacTestData; +struct QCryptoHmacTestData { +const char *path; +QCryptoHmacAlgorithm alg; +const char *key; +const char *message; +const char *digest; +}; + +static QCryptoHmacTestData test_data[] = { +{ +.path = "/crypto/hmac/hmac-md5", +.alg = QCRYPTO_HMAC_ALG_MD5, +.key = +"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", +.message = +"4869205468657265", +.digest = +"9294727a3638bb1c13f48ef8158bfc9d", +}, +{ +.path = "/crypto/hmac/hmac-sha1", +.alg = QCRYPTO_HMAC_ALG_SHA1, +.key = +"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" +"0b0b0b0b", +.message = +"4869205468657265", +.digest = +"b617318655057264e28bc0b6fb378c8e" +"f146be00", +}, +}; + +static inline int unhex(char c) +{ +if (c >= 'a' && c <= 'f') { +return 10 + (c - 'a'); +} +if (c >= 'A' && c <= 'F') { +return 10 + (c - 'A'); +} +return c - '0'; +} + +static inline char hex(int i) +{ +if (i < 10) { +return '0' + i; +} +return 'a' + (i - 10); +} + +static size_t unhex_string(const char *hexstr, + uint8_t **data) +{ +size_t len; +size_t i; + +if (!hexstr) { +*data = NULL; +return 0; +} + +len = strlen(hexstr); +*data = g_new0(uint8_t, len / 2); + +for (i = 0; i < len; i += 2) { +(*data)[i / 2] = (unhex(hexstr[i]) << 4) | unhex(hexstr[i + 1]); +} +return len / 2; +} + +static char *hex_string(const uint8_t *bytes, +size_t len) +{ +char *hexstr = g_new0(char, len * 2 + 1); +size_t i; + +for (i = 0; i < len; i++) { +hexstr[i * 2] = hex((bytes[i] >> 4) & 0xf); +hexstr[i * 2 + 1] = hex(bytes[i] & 0xf); +} +hexstr[len * 2] = '\0'; + +return hexstr; +} + +static void test_hmac(const void *opaque) +{ +const QCryptoHmacTestData *data = opaque; +size_t nkey, digest_len, msg_len; +uint8_t *key = NULL; +uint8_t *message = NULL; +uint8_t *digest = NULL; +uint8_t *output = NULL; +char *outputhex = NULL; +QCryptoHmac *hmac = NULL; +Error *err = NULL; +int ret; + +nkey = unhex_string(data->key, &key); +digest_len = unhex_string(data->digest, &digest); +msg_len = unhex_string(data->message, &message); + +output = g_new0(uint8_t, digest_len); + +hmac = qcrypto_hmac_new(data->alg, key, nkey, &err); +g_assert(err == NULL); +g_assert(hmac != NULL); + +ret = qcrypto_hmac_bytes(hmac, (const char *)message, +msg_len, &output, &digest_len, &err); + +g_assert(ret == 0); + +outputhex = hex_string(output, digest_len); + +g_assert_cmpstr(outputhex, ==, data->digest); + +qcrypto_hmac_free(hma
[Qemu-devel] [PATCH for-2.9 v1 3/7] configure: add CONFIG_GCRYPT_SUPPORT_HMAC item
This item will be used for support libcrypt-backed HMAC algorithms. Support for hmac has been added in Libgcrypt 1.6.0, but we cannot use pkg-config to get libcrypt's version. However we can make a in configure to know whether current libcrypt support hmac. Signed-off-by: Longpeng(Mike) --- configure | 18 ++ 1 file changed, 18 insertions(+) diff --git a/configure b/configure index 3770d7c..6eb5f5c 100755 --- a/configure +++ b/configure @@ -2417,6 +2417,21 @@ EOF if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then gcrypt_kdf=yes fi + +cat > $TMPC << EOF +#include +int main(void) { + gcry_mac_hd_t handle; + gcry_mac_open(&handle, GCRY_MAC_HMAC_MD5, +GCRY_MAC_FLAG_SECURE, NULL); + return 0; +} +EOF +if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then +gcrypy_support_hmac="yes" +else +gcrypy_support_hmac="no" +fi else if test "$gcrypt" = "yes"; then feature_not_found "gcrypt" "Install gcrypt devel" @@ -5387,6 +5402,9 @@ if test "$gnutls_rnd" = "yes" ; then fi if test "$gcrypt" = "yes" ; then echo "CONFIG_GCRYPT=y" >> $config_host_mak + if test "gcrypy_support_hmac" = "yes" ; then +echo "CONFIG_GCRYPT_SUPPORT_HMAC=y" >> $config_host_mak + fi if test "$gcrypt_kdf" = "yes" ; then echo "CONFIG_GCRYPT_KDF=y" >> $config_host_mak fi -- 1.8.3.1
[Qemu-devel] [PATCH for-2.9 v1 5/7] crypto: support HMAC algorithms based on glibc
This patch add glibc-backed HMAC algorithms support Signed-off-by: Longpeng(Mike) --- crypto/hmac-glib.c | 119 + 1 file changed, 119 insertions(+) diff --git a/crypto/hmac-glib.c b/crypto/hmac-glib.c index 42f63c6..6a5f722 100644 --- a/crypto/hmac-glib.c +++ b/crypto/hmac-glib.c @@ -16,6 +16,123 @@ #include "qapi/error.h" #include "crypto/hmac.h" +/* Support for HMAC Algos has been added in GLib 2.30 */ +#if GLIB_CHECK_VERSION(2, 30, 0) + +static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = { +[QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5, +[QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1, +[QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256, +/* Support for HMAC SHA-512 in GLib 2.42 */ +#if GLIB_CHECK_VERSION(2, 42, 0) +[QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512, +#else +[QCRYPTO_HASH_ALG_SHA512] = -1, +#endif +}; + +typedef struct QCryptoHmacGlib QCryptoHmacGlib; +struct QCryptoHmacGlib { +GHmac *ghmac; +}; + +bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg) +{ +if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) && +qcrypto_hmac_alg_map[alg] != -1) { +return true; +} + +return false; +} + +QCryptoHmac *qcrypto_hmac_new(QCryptoHmacAlgorithm alg, + const uint8_t *key, size_t nkey, + Error **errp) +{ +QCryptoHmac *hmac; +QCryptoHmacGlib *ctx; + +if (!qcrypto_hmac_supports(alg)) { +error_setg(errp, "Unsupported hmac algorithm %s", +QCryptoHmacAlgorithm_lookup[alg]); +return NULL; +} + +hmac = g_new0(QCryptoHmac, 1); +hmac->alg = alg; + +ctx = g_new0(QCryptoHmacGlib, 1); + +ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg], +(const uint8_t *)key, nkey); +if (!ctx->ghmac) { +error_setg(errp, "Cannot initialize hmac and set key"); +goto error; +} + +hmac->opaque = ctx; +return hmac; + +error: +g_free(ctx); +g_free(hmac); +return NULL; +} + +void qcrypto_hmac_free(QCryptoHmac *hmac) +{ +QCryptoHmacGlib *ctx; + +if (!hmac) { +return; +} + +ctx = hmac->opaque; +g_hmac_unref(ctx->ghmac); + +g_free(ctx); +g_free(hmac); +} + +int qcrypto_hmac_bytesv(QCryptoHmac *hmac, +const struct iovec *iov, +size_t niov, +uint8_t **result, +size_t *resultlen, +Error **errp) +{ +QCryptoHmacGlib *ctx; +int i, ret; + +ctx = hmac->opaque; + +for (i = 0; i < niov; i++) { +g_hmac_update(ctx->ghmac, iov[i].iov_base, iov[i].iov_len); +} + +ret = g_checksum_type_get_length(qcrypto_hmac_alg_map[hmac->alg]); +if (ret < 0) { +error_setg(errp, "Unable to get hmac length"); +return -1; +} + +if (*resultlen == 0) { +*resultlen = ret; +*result = g_new0(uint8_t, *resultlen); +} else if (*resultlen != ret) { +error_setg(errp, "Result buffer size %zu is smaller than hmac %d", +*resultlen, ret); +return -1; +} + +g_hmac_get_digest(ctx->ghmac, *result, resultlen); + +return 0; +} + +#else + bool qcrypto_hmac_supports(QCryptoHmacAlgorithm alg) { return false; @@ -42,3 +159,5 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac, { return -1; } + +#endif -- 1.8.3.1
Re: [Qemu-devel] [qemu patch V4 2/2] kvmclock: reduce kvmclock difference on migration
Hello Marcelo, > > Check for KVM_CAP_ADJUST_CLOCK capability KVM_CLOCK_TSC_STABLE, which > indicates that KVM_GET_CLOCK returns a value as seen by the guest at > that moment. > > For new machine types, use this value rather than reading > from guest memory. > > This reduces kvmclock difference on migration from 5s to 0.1s > (when max_downtime == 5s). > > Note: pre_save contradicts the following comment > /* > * If the VM is stopped, declare the clock state valid to > * avoid re-reading it on next vmsave (which would return > * a different value). Will be reset when the VM is continued. > */ > But the comment is bogus: vm_state_change is never called twice in a row > with running=0 or running=1. > > Signed-off-by: Marcelo Tosatti > > --- > hw/i386/kvm/clock.c| 107 > ++--- > include/hw/i386/pc.h |5 ++ > target-i386/kvm.c |7 +++ > target-i386/kvm_i386.h |1 > 4 files changed, 106 insertions(+), 14 deletions(-) > > v2: > - improve variable names (Juan) > - consolidate code on kvm_get_clock function (Paolo) > - return mach_use_reliable_get_clock from needed function (Paolo) > v3: > - simplify check for src_use_reliable_get_clock (Eduardo) > - move src_use_reliable_get_clock initialization to realize (Eduardo) > > v4: > - have kvm_get_clock and clock_is_reliable assignments synchronized (Eduardo) > - add comment to the reasoning of kvmclock_pre_save (Eduardo) > > > Index: qemu-mig-advance-clock/hw/i386/kvm/clock.c > === > --- qemu-mig-advance-clock.orig/hw/i386/kvm/clock.c 2016-11-17 > 15:07:11.220632761 -0200 > +++ qemu-mig-advance-clock/hw/i386/kvm/clock.c2016-12-10 > 13:57:58.115983966 > -0200 > @@ -36,6 +36,13 @@ > > uint64_t clock; > bool clock_valid; > + > +/* whether machine type supports reliable get clock */ > +bool mach_use_reliable_get_clock; > + > +/* whether the 'clock' value was obtained in a host with > + * reliable KVM_GET_CLOCK */ > +bool clock_is_reliable; > } KVMClockState; > > struct pvclock_vcpu_time_info { > @@ -81,6 +88,19 @@ > return nsec + time.system_time; > } > > +static uint64_t kvm_get_clock(void) > +{ > +struct kvm_clock_data data; > +int ret; > + > +ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data); > +if (ret < 0) { > +fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret)); > +abort(); > +} > +return data.clock; > +} > + > static void kvmclock_vm_state_change(void *opaque, int running, > RunState state) > { > @@ -91,15 +111,23 @@ > > if (running) { > struct kvm_clock_data data = {}; > -uint64_t time_at_migration = kvmclock_current_nsec(s); > +uint64_t pvclock_via_mem = 0; > > -s->clock_valid = false; > +/* > + * If the host where s->clock was read did not support reliable > + * KVM_GET_CLOCK, read kvmclock value from memory. > + */ > +if (!s->clock_is_reliable) { > +pvclock_via_mem = kvmclock_current_nsec(s); > +} > > -/* We can't rely on the migrated clock value, just discard it */ > -if (time_at_migration) { > -s->clock = time_at_migration; > +/* We can't rely on the saved clock value, just discard it */ > +if (pvclock_via_mem) { > +s->clock = pvclock_via_mem; > } > > +s->clock_valid = false; > + > data.clock = s->clock; > ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data); > if (ret < 0) { > @@ -120,8 +148,6 @@ > } > } > } else { > -struct kvm_clock_data data; > -int ret; > > if (s->clock_valid) { > return; > @@ -129,13 +155,11 @@ > > kvm_synchronize_all_tsc(); > > -ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data); > -if (ret < 0) { > -fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret)); > -abort(); > -} > -s->clock = data.clock; > - > +s->clock = kvm_get_clock(); > +/* any code that sets s->clock needs to ensure clock_is_reliable > + * is correctly set. > + */ > +s->clock_is_reliable = kvm_has_adjust_clock_stable(); Is it required to call 'kvm_has_adjust_clock_stable' here. Is there any chance of getting different value then in 'realize'? > /* > * If the VM is stopped, declare the clock state valid to > * avoid re-reading it on next vmsave (which would return > @@ -149,25 +173,80 @@ > { > KVMClockState *s = KVM_CLOCK(dev); > > +if (kvm_has_adjust_clock_stable()) { > +s->clock_is_reliable = true; > +} > + > qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s); > } > > +
Re: [Qemu-devel] [PATCH 13/21] qcow2: add .bdrv_store_persistent_dirty_bitmaps()
10.12.2016 17:53, Max Reitz wrote: On 09.12.2016 18:55, Vladimir Sementsov-Ogievskiy wrote: 09.12.2016 20:05, Max Reitz wrote: On 22.11.2016 18:26, Vladimir Sementsov-Ogievskiy wrote: Realize block bitmap storing interface, to allow qcow2 images store persistent bitmaps. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-bitmap.c | 451 +++ block/qcow2.c| 1 + block/qcow2.h| 1 + 3 files changed, 453 insertions(+) diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 81be1ca..a975388 100644 --- a/block/qcow2-bitmap.c [...] +return; +} +} + +/* check constraints and names */ +for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap != NULL; +bitmap = bdrv_dirty_bitmap_next(bs, bitmap)) { Alignment to the opening parenthesis, please. Hmm.. without an alignment it is not so simple to distinguish for-loop header from its body. I know, and it's even worse for "if". That is why I usually put the opening { on a new line if I have to spread an if/while/for header over multiple lines. The usual convention for qemu code is to align at an opening parenthesis if there is one. Admittedly, the reasoning I gave for changing checkpatch.pl to accept opening { on a new line in certain cases was that: Good news, didn't know) (1) We never codified exactly what to allow for multi-line if/while/for conditions. (2) It was existing practice. (1) applies in your case also; we don't have any explicitly written-out convention for alignment of wrapped lines. (2) is more difficult, but there are indeed a handful of cases where lines are wrapped and not aligned to the opening parenthesis but just indented by an additional four spaces... So I guess since I'm insisting on putting the opening { on a new line for multi-line conditions, you are allowed to indent the consecutive lines by an additional level. ;-) (It *is* against existing convention, but I'm not in a position to argue.) [...] [1] What about bitmaps that have BME_FLAG_IN_USE set but do not have a corresponding BDS bitmap? If such a bitmap does not have BME_FLAG_AUTO set, we didn't set the flag, so we should keep it unchanged. That's what this function is currently doing. However, if such a bitmap does have BME_FLAG_AUTO set, it was definitely us who set the IN_USE flag (because otherwise we would have aborted loading the bitmaps, and thus also aborted bdrv_open_common()). Therefore, the only explanation is that the bitmap was deleted in the meantime, and that means we should also delete it in the qcow2 file. Right. Or, alternatively, these bitmaps may be deleted on corresponding BdrvDirtyBitmap deletion. Right, that would work, too. Max -- Best regards, Vladimir
Re: [Qemu-devel] experience with SDL2, event loop & main thread
On Mon, 12/12 09:18, Liviu Ionescu wrote: > > > On 12 Dec 2016, at 05:35, Fam Zheng wrote: > > > > Isn't it possible to notify the main thread with an EventNotifier and > > process > > the deferred events in its handler? > > ideally, the SDL main loop might be re-implemented asynchronously, for example > using a pipe to pass the events, and in this case the SDL would be just a > regular client of the main I/O loop. > > any idea how difficult would be to push any changes to SDL? Not sure I understand this question, could you be more specific? Fam
Re: [Qemu-devel] experience with SDL2, event loop & main thread
> On 12 Dec 2016, at 09:39, Fam Zheng wrote: > >> any idea how difficult would be to push any changes to SDL? > > Not sure I understand this question, could you be more specific? I guess making SDL run asynchronously will need some major changes to the SDL source code, not simple patches that can be added to the QEMU build. do you know someone who can not only implement the patches, but also push them to the mainstream SDL repository, to have them available to everyone? regards, Liviu
Re: [Qemu-devel] [PATCH for-2.9 v1 0/7] crypto: add HMAC algorithms support
Hi, Your series failed automatic build test. Please find the testing commands and their output below. If you have docker installed, you can probably reproduce it locally. Subject: [Qemu-devel] [PATCH for-2.9 v1 0/7] crypto: add HMAC algorithms support Type: series Message-id: 1481527639-17520-1-git-send-email-longpe...@huawei.com === TEST SCRIPT BEGIN === #!/bin/bash set -e git submodule update --init dtc # Let docker tests dump environment info export SHOW_ENV=1 export J=16 make docker-test-quick@centos6 make docker-test-mingw@fedora make docker-test-build@min-glib === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu * [new tag] patchew/1481527639-17520-1-git-send-email-longpe...@huawei.com -> patchew/1481527639-17520-1-git-send-email-longpe...@huawei.com Switched to a new branch 'test' b614df7 crypto: add HMAC algorithms testcases 8ad1449 crypto: support HMAC algorithms based on nettle ae965e0 crypto: support HMAC algorithms based on glibc 3c8ead8 crypto: support HMAC algorithms based on libgcrypt 11f716b configure: add CONFIG_GCRYPT_SUPPORT_HMAC item c45ef52 crypto: add HMAC algorithms framework 4d98eee qapi: crypto: add defination about HMAC algorithms === OUTPUT BEGIN === Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc' Cloning into 'dtc'... Submodule path 'dtc': checked out '65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf' BUILD centos6 make[1]: Entering directory `/var/tmp/patchew-tester-tmp-2sk4ey4p/src' ARCHIVE qemu.tgz ARCHIVE dtc.tgz COPYRUNNER RUN test-quick in qemu:centos6 Packages installed: SDL-devel-1.2.14-7.el6_7.1.x86_64 ccache-3.1.6-2.el6.x86_64 epel-release-6-8.noarch gcc-4.4.7-17.el6.x86_64 git-1.7.1-4.el6_7.1.x86_64 glib2-devel-2.28.8-5.el6.x86_64 libfdt-devel-1.4.0-1.el6.x86_64 make-3.81-23.el6.x86_64 package g++ is not installed pixman-devel-0.32.8-1.el6.x86_64 tar-1.23-15.el6_8.x86_64 zlib-devel-1.2.3-29.el6.x86_64 Environment variables: PACKAGES=libfdt-devel ccache tar git make gcc g++ zlib-devel glib2-devel SDL-devel pixman-devel epel-release HOSTNAME=770fcc9f59e0 TERM=xterm MAKEFLAGS= -j16 HISTSIZE=1000 J=16 USER=root CCACHE_DIR=/var/tmp/ccache EXTRA_CONFIGURE_OPTS= V= SHOW_ENV=1 MAIL=/var/spool/mail/root PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/ LANG=en_US.UTF-8 TARGET_LIST= HISTCONTROL=ignoredups SHLVL=1 HOME=/root TEST_DIR=/tmp/qemu-test LOGNAME=root LESSOPEN=||/usr/bin/lesspipe.sh %s FEATURES= dtc DEBUG= G_BROKEN_FILENAMES=1 CCACHE_HASHDIR= _=/usr/bin/env Configure options: --enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install No C++ compiler available; disabling C++ specific optional code Install prefix/var/tmp/qemu-build/install BIOS directory/var/tmp/qemu-build/install/share/qemu binary directory /var/tmp/qemu-build/install/bin library directory /var/tmp/qemu-build/install/lib module directory /var/tmp/qemu-build/install/lib/qemu libexec directory /var/tmp/qemu-build/install/libexec include directory /var/tmp/qemu-build/install/include config directory /var/tmp/qemu-build/install/etc local state directory /var/tmp/qemu-build/install/var Manual directory /var/tmp/qemu-build/install/share/man ELF interp prefix /usr/gnemul/qemu-%M Source path /tmp/qemu-test/src C compilercc Host C compiler cc C++ compiler Objective-C compiler cc ARFLAGS rv CFLAGS-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g QEMU_CFLAGS -I/usr/include/pixman-1-pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all LDFLAGS -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g make make install install pythonpython -B smbd /usr/sbin/smbd module supportno host CPU x86_64 host big endian no target list x86_64-softmmu aarch64-softmmu tcg debug enabled no gprof enabled no sparse enabledno strip binariesyes profiler no static build no pixmansystem SDL support yes (1.2.14) GTK support no GTK GL supportno VTE support no TLS priority NORMAL GNUTLS supportno GNUTLS rndno libgcrypt no libgcrypt kdf no nettleno nettle kdfno libtasn1 no curses supportno virgl support no curl support no mingw32 support no Audio drivers oss Block whitelist (rw) Block whitelist (r